Statistiques
| Révision :

root / NBody / NBody.py @ 149

Historique | Voir | Annoter | Télécharger (18,63 ko)

1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
"""
4
Demonstrateur OpenCL d'interaction NCorps
5

6
Emmanuel QUEMENER <emmanuel.quemener@ens-lyon.fr> CeCILLv2
7
"""
8
import getopt
9
import sys
10
import time
11
import numpy as np
12
import pyopencl as cl
13
import pyopencl.array as cl_array
14
from numpy.random import randint as nprnd
15

    
16
def DictionariesAPI():
17
    Marsaglia={'CONG':0,'SHR3':1,'MWC':2,'KISS':3}
18
    Computing={'FP32':0,'FP64':1}
19
    return(Marsaglia,Computing)
20

    
21

    
22

    
23

    
24

    
25

    
26

    
27

    
28

    
29

    
30

    
31
BlobOpenCL= """
32
#define znew  ((z=36969*(z&65535)+(z>>16))<<16)
33
#define wnew  ((w=18000*(w&65535)+(w>>16))&65535)
34
#define MWC   (znew+wnew)
35
#define SHR3  (jsr=(jsr=(jsr=jsr^(jsr<<17))^(jsr>>13))^(jsr<<5))
36
#define CONG  (jcong=69069*jcong+1234567)
37
#define KISS  ((MWC^CONG)+SHR3)
38

39
#define MWCfp MWC * 2.328306435454494e-10f
40
#define KISSfp KISS * 2.328306435454494e-10f
41
#define SHR3fp SHR3 * 2.328306435454494e-10f
42
#define CONGfp CONG * 2.328306435454494e-10f
43

44
#define TFP32 0
45
#define TFP64 1
46

47
#define LENGTH 1e0f
48

49
#define PI 3.14159265359e0f
50

51
#define SMALL_NUM 1e-9f
52

53
#if TYPE == TFP32
54
#define MYFLOAT4 float4
55
#define MYFLOAT8 float8
56
#define MYFLOAT float
57
#else
58
#pragma OPENCL EXTENSION cl_khr_fp64: enable
59
#define MYFLOAT4 double4
60
#define MYFLOAT8 double8
61
#define MYFLOAT double
62
#endif
63

64
MYFLOAT4 Interaction(MYFLOAT4 m,MYFLOAT4 n)
65
{
66
    return((n-m)/pow(distance(n,m),3));
67
}
68

69
MYFLOAT4 InteractionCore(MYFLOAT4 m,MYFLOAT4 n)
70
{
71
    MYFLOAT core=1e5f;
72
    MYFLOAT r=distance(n,m);
73

74
    return(core*(n-m)/(MYFLOAT)(pow(r*r+core*core,2)));
75
}
76

77
MYFLOAT PairPotential(MYFLOAT4 m,MYFLOAT4 n)
78
{
79
    return((MYFLOAT)(-1e0f)/(distance(n,m)));
80
}
81

82
MYFLOAT AtomicPotential(__global MYFLOAT8* clData,int gid)
83
{
84
    MYFLOAT potential=0e0f;
85
    MYFLOAT4 x=clData[gid].lo; 
86
    
87
    for (int i=0;i<get_global_size(0);i++)
88
    {
89
        if (gid != i)
90
        potential+=PairPotential(x,clData[i].lo);
91
    }
92

93
    barrier(CLK_GLOBAL_MEM_FENCE);
94
    //return(5e-1f*potential);
95
    return(potential);
96
}
97

98
MYFLOAT AtomicPotentialCoM(__global MYFLOAT8* clData,__global MYFLOAT4* clCoM,int gid)
99
{
100
    return(PairPotential(clData[gid].lo,clCoM[0]));
101
}
102

103
MYFLOAT8 AtomicRungeKutta(__global MYFLOAT8* clDataIn,int gid,MYFLOAT dt)
104
{
105
    MYFLOAT4 a0=(MYFLOAT4)(0e0f,0e0f,0e0f,0e0f);
106
    MYFLOAT4 v0=(MYFLOAT4)clDataIn[gid].hi;
107
    MYFLOAT4 x0=(MYFLOAT4)clDataIn[gid].lo;
108
    int N = get_global_size(0);    
109
    
110
    for (int i=0;i<N;i++)
111
    {
112
        if (gid != i)
113
        a0+=Interaction(x0,clDataIn[i].lo);
114
    }
115
        
116
    MYFLOAT4 a1=(MYFLOAT4)(0e0f,0e0f,0e0f,0e0f);
117
    MYFLOAT4 v1=v0+a0*dt;
118
    MYFLOAT4 x1=x0+v0*dt;
119
    for (int i=0;i<N;i++)
120
    {
121
        if (gid != i)
122
        a1+=Interaction(x1,clDataIn[i].lo);
123
    }
124

125
    MYFLOAT4 a2=(MYFLOAT4)(0e0f,0e0f,0e0f,0e0f);
126
    MYFLOAT4 v2=v0+a1*dt*(MYFLOAT)5e-1f;
127
    MYFLOAT4 x2=x0+v1*dt*(MYFLOAT)5e-1f;
128
    for (int i=0;i<N;i++)
129
    {
130
        if (gid != i)
131
        a2+=Interaction(x2,clDataIn[i].lo);
132
    }
133
    
134
    MYFLOAT4 a3=(MYFLOAT4)(0e0f,0e0f,0e0f,0e0f);
135
    MYFLOAT4 v3=v0+a2*dt*(MYFLOAT)5e-1f;
136
    MYFLOAT4 x3=x0+v2*dt*(MYFLOAT)5e-1f;
137
    for (int i=0;i<N;i++)
138
    {
139
        if (gid != i)
140
        a3+=Interaction(x3,clDataIn[i].lo);
141
    }
142
    
143
    MYFLOAT4 a4=(MYFLOAT4)(0e0f,0e0f,0e0f,0e0f);
144
    MYFLOAT4 v4=v0+a3*dt;
145
    MYFLOAT4 x4=x0+v3*dt;
146
    for (int i=0;i<N;i++)
147
    {
148
        if (gid != i)
149
        a4+=Interaction(x4,clDataIn[i].lo);
150
    }
151
    
152
    MYFLOAT4 xf=x0+dt*(v1+(MYFLOAT)2e0f*(v2+v3)+v4)/(MYFLOAT)6e0f;
153
    MYFLOAT4 vf=v0+dt*(a1+(MYFLOAT)2e0f*(a2+a3)+a4)/(MYFLOAT)6e0f;
154
     
155
    return((MYFLOAT8)(xf.s0,xf.s1,xf.s2,0e0f,vf.s0,vf.s1,vf.s2,0e0f));
156
}
157

158
// Elements from : http://doswa.com/2009/01/02/fourth-order-runge-kutta-numerical-integration.html
159

160
MYFLOAT8 AtomicHeun(__global MYFLOAT8* clDataIn,int gid,MYFLOAT dt)
161
{
162
    MYFLOAT4 x,v,a,xi,vi,ai,xf,vf;
163

164
    x=(MYFLOAT4)clDataIn[gid].lo;
165
    v=(MYFLOAT4)clDataIn[gid].hi;
166
    a=(MYFLOAT4)(0e0f,0e0f,0e0f,0e0f);
167

168
    for (int i=0;i<get_global_size(0);i++)
169
    {
170
        if (gid != i)
171
        a+=Interaction(x,clDataIn[i].lo);
172
    }
173

174
    vi=v+dt*a;
175
    xi=x+dt*vi;
176
    ai=(MYFLOAT4)(0e0f,0e0f,0e0f,0e0f);
177

178
    for (int i=0;i<get_global_size(0);i++)
179
    {
180
        if (gid != i)
181
        ai+=Interaction(xi,clDataIn[i].lo);
182
    }
183
       
184
    vf=v+dt*(a+ai)*5e-1f;
185
    xf=x+dt*(v+vi)*5e-1f;
186

187
    return((MYFLOAT8)(xf.s0,xf.s1,xf.s2,0e0f,vf.s0,vf.s1,vf.s2,0e0f));
188
}
189

190
MYFLOAT8 AtomicImplicitEuler(__global MYFLOAT8* clDataIn,int gid,MYFLOAT dt)
191
{
192
    MYFLOAT4 x,v,a,xf,vf;
193

194
    x=(MYFLOAT4)clDataIn[gid].lo;
195
    v=(MYFLOAT4)clDataIn[gid].hi;
196
    a=(MYFLOAT4)(0e0f,0e0f,0e0f,0e0f);
197
    for (int i=0;i<get_global_size(0);i++)
198
    {
199
        if (gid != i)
200
        a+=Interaction(x,clDataIn[i].lo);
201
        //a+=InteractionCore(x,clDataIn[i].lo);
202
    }
203
       
204
    vf=v+dt*a;
205
    xf=x+dt*vf;
206
 
207
    return((MYFLOAT8)(xf.s0,xf.s1,xf.s2,0e0f,vf.s0,vf.s1,vf.s2,0e0f));
208
}
209

210
MYFLOAT8 AtomicExplicitEuler(__global MYFLOAT8* clDataIn,int gid,MYFLOAT dt)
211
{
212
    MYFLOAT4 x,v,a,xf,vf;
213

214
    x=(MYFLOAT4)clDataIn[gid].lo;
215
    v=(MYFLOAT4)clDataIn[gid].hi;
216
    a=(MYFLOAT4)(0e0f,0e0f,0e0f,0e0f);
217
    for (int i=0;i<get_global_size(0);i++)
218
    {
219
        if (gid != i)
220
        a+=Interaction(x,clDataIn[i].lo);
221
    }
222
       
223
    vf=v+dt*a;
224
    xf=x+dt*v;
225
 
226
    return((MYFLOAT8)(xf.s0,xf.s1,xf.s2,0e0f,vf.s0,vf.s1,vf.s2,0e0f));
227
}
228

229
__kernel void SplutterPoints(__global MYFLOAT8* clData, MYFLOAT box, 
230
                             uint seed_z,uint seed_w)
231
{
232
    int gid = get_global_id(0);
233
    uint z=seed_z+(uint)gid;
234
    uint w=seed_w-(uint)gid;
235
    
236
    MYFLOAT x0=box*(MYFLOAT)(MWCfp-5e-1f);
237
    MYFLOAT y0=box*(MYFLOAT)(MWCfp-5e-1f);
238
    MYFLOAT z0=box*(MYFLOAT)(MWCfp-5e-1f);
239

240
    clData[gid].s01234567 = (MYFLOAT8) (x0,y0,z0,0e0f,0e0f,0e0f,0e0f,0e0f);
241
}
242

243
__kernel void SplutterStress(__global MYFLOAT8* clData,__global MYFLOAT4* clCoM, MYFLOAT velocity,uint seed_z,uint seed_w)
244
{
245
    int gid = get_global_id(0);
246
    MYFLOAT N = (MYFLOAT)get_global_size(0);
247
    uint z=seed_z+(uint)gid;
248
    uint w=seed_w-(uint)gid;
249

250
    if (velocity<SMALL_NUM) {
251
       MYFLOAT4 SpeedVector=(MYFLOAT4)normalize(cross(clData[gid].lo,clCoM[0]))*sqrt(-AtomicPotential(clData,gid)*5e-1f);
252
       clData[gid].hi=SpeedVector;
253
    }
254
    else
255
    {    
256
       MYFLOAT theta=MWCfp*PI;
257
       MYFLOAT phi=MWCfp*PI*(MYFLOAT)2e0f;
258
       MYFLOAT sinTheta=sin(theta);
259

260
       clData[gid].s4=velocity*sinTheta*cos(phi);
261
       clData[gid].s5=velocity*sinTheta*sin(phi);
262
       clData[gid].s6=velocity*cos(theta);
263
    }
264
}
265

266
__kernel void RungeKutta(__global MYFLOAT8* clData,MYFLOAT h)
267
{
268
    int gid = get_global_id(0);
269
    
270
    MYFLOAT8 clDataGid=AtomicRungeKutta(clData,gid,h);
271
    barrier(CLK_GLOBAL_MEM_FENCE);
272
    clData[gid]=clDataGid;
273
}
274

275
__kernel void ImplicitEuler(__global MYFLOAT8* clData,MYFLOAT h)
276
{
277
    int gid = get_global_id(0);
278
    
279
    MYFLOAT8 clDataGid=AtomicImplicitEuler(clData,gid,h);
280
    barrier(CLK_GLOBAL_MEM_FENCE);
281
    clData[gid]=clDataGid;
282
}
283

284
__kernel void Heun(__global MYFLOAT8* clData,MYFLOAT h)
285
{
286
    int gid = get_global_id(0);
287
    
288
    MYFLOAT8 clDataGid=AtomicHeun(clData,gid,h);
289
    barrier(CLK_GLOBAL_MEM_FENCE);
290
    clData[gid]=clDataGid;
291
}
292

293
__kernel void ExplicitEuler(__global MYFLOAT8* clData,MYFLOAT h)
294
{
295
    int gid = get_global_id(0);
296
    
297
    MYFLOAT8 clDataGid=AtomicExplicitEuler(clData,gid,h);
298
    barrier(CLK_GLOBAL_MEM_FENCE);
299
    clData[gid]=clDataGid;
300
}
301

302
__kernel void CoMPotential(__global MYFLOAT8* clData,__global MYFLOAT4* clCoM,__global MYFLOAT* clPotential)
303
{
304
    int gid = get_global_id(0);
305

306
    clPotential[gid]=PairPotential(clData[gid].lo,clCoM[0]);
307
}
308

309
__kernel void Potential(__global MYFLOAT8* clData,__global MYFLOAT* clPotential)
310
{
311
    int gid = get_global_id(0);
312

313
    MYFLOAT potential=0e0f;
314
    MYFLOAT4 x=clData[gid].lo; 
315
    
316
    for (int i=0;i<get_global_size(0);i++)
317
    {
318
        if (gid != i)
319
        potential+=PairPotential(x,clData[i].lo);
320
    }
321
                 
322
    barrier(CLK_GLOBAL_MEM_FENCE);
323
    clPotential[gid]=(MYFLOAT)5e-1f*potential;
324
}
325

326
__kernel void CenterOfMass(__global MYFLOAT8* clData,__global MYFLOAT4* clCoM,int Size)
327
{
328
    MYFLOAT4 CoM=clData[0].lo; 
329

330
    for (int i=1;i<Size;i++)
331
    {
332
        CoM+=clData[i].lo;
333
    }
334

335
    barrier(CLK_GLOBAL_MEM_FENCE);
336
    clCoM[0]=(MYFLOAT4)(CoM.s0,CoM.s1,CoM.s2,0e0f)/(MYFLOAT)Size;
337
}
338

339
__kernel void Kinetic(__global MYFLOAT8* clData,__global MYFLOAT* clKinetic)
340
{
341
    int gid = get_global_id(0);
342
    
343
    barrier(CLK_GLOBAL_MEM_FENCE);
344
    clKinetic[gid]=(MYFLOAT)5e-1f*(MYFLOAT)pow(length(clData[gid].hi),2);
345
}
346
"""
347

    
348
def Energy(MyData):
349
    return(sum(pow(MyData,2)))
350

    
351
if __name__=='__main__':
352
    
353
    # ValueType
354
    ValueType='FP32'
355
    class MyFloat(np.float32):pass
356
    clType8=cl_array.vec.float8
357
    clType4=cl_array.vec.float4
358
    # Set defaults values
359
    np.set_printoptions(precision=2)  
360
    # Id of Device : 1 is for first find !
361
    Device=1
362
    # Iterations is integer
363
    Number=4
364
    # Size of box
365
    SizeOfBox=MyFloat(1.)
366
    # Initial velocity of particules
367
    Velocity=MyFloat(1.)
368
    # Redo the last process
369
    Iterations=100
370
    # Step
371
    Step=MyFloat(0.01)
372
    # Method of integration
373
    Method='RungeKutta'
374
    # InitialRandom
375
    InitialRandom=False
376
    # RNG Marsaglia Method
377
    RNG='MWC'
378
    # CheckEnergies
379
    CheckEnergies=False
380
    # Display samples in 3D
381
    GraphSamples=False
382
    # Viriel Distribution of stress
383
    VirielStress=True
384
    
385
    HowToUse='%s -h [Help] -r [InitialRandom] -e [VirielStress] -g [GraphSamples] -c [CheckEnergies] -d <DeviceId> -n <NumberOfParticules> -z <SizeOfBox> -v <Velocity> -s <Step> -i <Iterations> -m <RungeKutta|ImplicitEuler|ExplicitEuler|Heun> -t <FP32|FP64>'
386

    
387
    try:
388
        opts, args = getopt.getopt(sys.argv[1:],"rehgcd:n:z:v:i:s:m:t:",["random","viriel","graph","check","device=","number=","size=","velocity=","iterations=","step=","method=","valuetype="])
389
    except getopt.GetoptError:
390
        print(HowToUse % sys.argv[0])
391
        sys.exit(2)
392

    
393
    for opt, arg in opts:
394
        if opt == '-h':
395
            print(HowToUse % sys.argv[0])
396

    
397
            print("\nInformations about devices detected under OpenCL:")
398
            try:
399
                Id=0
400
                for platform in cl.get_platforms():
401
                    for device in platform.get_devices():
402
                        #deviceType=cl.device_type.to_string(device.type)
403
                        deviceType="xPU"
404
                        print("Device #%i from %s of type %s : %s" % (Id,platform.vendor.lstrip(),deviceType,device.name.lstrip()))
405
                        Id=Id+1
406
                sys.exit()
407
            except ImportError:
408
                print("Your platform does not seem to support OpenCL")
409
                sys.exit()
410

    
411
        elif opt in ("-t", "--valuetype"):
412
            if arg=='FP64':
413
                class MyFloat(np.float64): pass
414
                clType8=cl_array.vec.double8
415
                clType4=cl_array.vec.double4
416
            else:
417
                class MyFloat(np.float32):pass
418
                clType8=cl_array.vec.float8
419
                clType4=cl_array.vec.float4
420
            ValueType = arg
421
        elif opt in ("-d", "--device"):
422
            Device=int(arg)
423
        elif opt in ("-m", "--method"):
424
            Method=arg
425
        elif opt in ("-n", "--number"):
426
            Number=int(arg)
427
        elif opt in ("-z", "--size"):
428
            SizeOfBox=MyFloat(arg)
429
        elif opt in ("-v", "--velocity"):
430
            Velocity=MyFloat(arg)
431
            VirielStress=False
432
        elif opt in ("-s", "--step"):
433
            Step=MyFloat(arg)
434
        elif opt in ("-i", "--iterations"):
435
            Iterations=int(arg)
436
        elif opt in ("-r", "--random"):
437
            InitialRandom=True
438
        elif opt in ("-c", "--check"):
439
            CheckEnergies=True
440
        elif opt in ("-g", "--graph"):
441
            GraphSamples=True
442
        elif opt in ("-e", "--viriel"):
443
            VirielStress=True
444
                        
445
    SizeOfBox=MyFloat(np.power(Number,1./3.)*SizeOfBox)
446
    Velocity=MyFloat(Velocity)
447
    Step=MyFloat(Step)
448
                
449
    print("Device choosed : %s" % Device)
450
    print("Number of particules : %s" % Number)
451
    print("Size of Box : %s" % SizeOfBox)
452
    print("Initial velocity %s" % Velocity)
453
    print("Number of iterations %s" % Iterations)
454
    print("Step of iteration %s" % Step)
455
    print("Method of resolution %s" % Method)
456
    print("Initial Random for RNG Seed %s" % InitialRandom)
457
    print("Check for Energies %s" % CheckEnergies)
458
    print("Graph for Samples %s" % GraphSamples)
459
    print("ValueType is %s" % ValueType)
460
    print("Viriel distribution of stress %s" % VirielStress)
461

    
462
    # Create Numpy array of CL vector with 8 FP32    
463
    MyCoM = np.zeros(1,dtype=clType4)
464
    MyData = np.zeros(Number, dtype=clType8)
465
    MyPotential = np.zeros(Number, dtype=MyFloat)
466
    MyKinetic = np.zeros(Number, dtype=MyFloat)
467

    
468
    Marsaglia,Computing=DictionariesAPI()
469

    
470
    # Scan the OpenCL arrays
471
    Id=0
472
    HasXPU=False
473
    for platform in cl.get_platforms():
474
        for device in platform.get_devices():
475
            if Id==Device:
476
                PlatForm=platform
477
                XPU=device
478
                print("CPU/GPU selected: ",device.name.lstrip())
479
                HasXPU=True
480
            Id+=1
481

    
482
    if HasXPU==False:
483
        print("No XPU #%i found in all of %i devices, sorry..." % (Device,Id-1))
484
        sys.exit()      
485

    
486
    # Create Context
487
    try:
488
        ctx = cl.Context([XPU])
489
        queue = cl.CommandQueue(ctx,properties=cl.command_queue_properties.PROFILING_ENABLE)
490
    except:
491
        print("Crash during context creation")
492

    
493
    print(Marsaglia[RNG],Computing[ValueType])
494
    # Build all routines used for the computing
495
#    MyRoutines = cl.Program(ctx, BlobOpenCL).build(options = "-cl-mad-enable -cl-fast-relaxed-math -DTRNG=%i -DTYPE=%i" % (Marsaglia[RNG],Computing[ValueType]))
496
    MyRoutines = cl.Program(ctx, BlobOpenCL).build(options = "-DTRNG=%i -DTYPE=%i" % (Marsaglia[RNG],Computing[ValueType]))
497

    
498
    mf = cl.mem_flags
499
    clData = cl.Buffer(ctx, mf.READ_WRITE, MyData.nbytes)
500
    clPotential = cl.Buffer(ctx, mf.READ_WRITE, MyPotential.nbytes)
501
    clKinetic = cl.Buffer(ctx, mf.READ_WRITE, MyKinetic.nbytes)
502
    clCoM = cl.Buffer(ctx, mf.READ_WRITE, MyCoM.nbytes)
503
    #clData = cl.Buffer(ctx, mf.WRITE_ONLY|mf.COPY_HOST_PTR,hostbuf=MyData)
504

    
505
    print('All particles superimposed.')
506

    
507
    print(SizeOfBox.dtype)
508
    
509
    # Set particles to RNG points
510
    if InitialRandom:
511
        MyRoutines.SplutterPoints(queue,(Number,1),None,clData,SizeOfBox,np.uint32(nprnd(2**32)),np.uint32(nprnd(2**32)))
512
    else:
513
        MyRoutines.SplutterPoints(queue,(Number,1),None,clData,SizeOfBox,np.uint32(110271),np.uint32(250173))
514

    
515
    print('All particules distributed')
516

    
517
    MyRoutines.CenterOfMass(queue,(1,1),None,clData,clCoM,np.int32(Number))
518
    cl.enqueue_copy(queue,MyCoM,clCoM)
519
    print('Center Of Mass: (%s,%s,%s)' % (MyCoM[0][0],MyCoM[0][1],MyCoM[0][2]))
520
    
521
    if VirielStress:
522
        MyRoutines.SplutterStress(queue,(Number,1),None,clData,clCoM,np.float32(0.),np.uint32(110271),np.uint32(250173))
523
    else:
524
        MyRoutines.SplutterStress(queue,(Number,1),None,clData,clCoM,Velocity,np.uint32(110271),np.uint32(250173))
525
        
526
    if GraphSamples:
527
        cl.enqueue_copy(queue, MyData, clData)
528
        t0=np.array([[MyData[0][0],MyData[0][1],MyData[0][2]]])
529
        t1=np.array([[MyData[1][0],MyData[1][1],MyData[1][2]]])
530
        tL=np.array([[MyData[-1][0],MyData[-1][1],MyData[-1][2]]])
531
        s0=np.array([[MyData[0][4],MyData[0][5],MyData[0][6],MyData[0][7]]])
532
        s1=np.array([[MyData[1][4],MyData[1][5],MyData[1][6],MyData[1][7]]])
533
        sL=np.array([[MyData[-1][4],MyData[-1][5],MyData[-1][6],MyData[-1][7]]])
534

    
535
        #print(t0,t1,tL)
536
        #print(s0,s1,sL)
537
        
538
    CLLaunch=MyRoutines.Potential(queue,(Number,1),None,clData,clPotential)
539
    CLLaunch=MyRoutines.Kinetic(queue,(Number,1),None,clData,clKinetic)
540
    CLLaunch.wait()
541
    cl.enqueue_copy(queue,MyPotential,clPotential)
542
    cl.enqueue_copy(queue,MyKinetic,clKinetic)
543
    print('Viriel=%s Potential=%s Kinetic=%s'% (np.sum(MyPotential)+2*np.sum(MyKinetic),np.sum(MyPotential),np.sum(MyKinetic)))
544
 
545
    if GraphSamples:
546
        cl.enqueue_copy(queue, MyData, clData)
547
        t0=np.array([[MyData[0][0],MyData[0][1],MyData[0][2]]])
548
        t1=np.array([[MyData[1][0],MyData[1][1],MyData[1][2]]])
549
        tL=np.array([[MyData[-1][0],MyData[-1][1],MyData[-1][2]]])
550

    
551
    time_start=time.time()
552
    for i in range(Iterations):
553
        if Method=="ImplicitEuler":            
554
            CLLaunch=MyRoutines.ImplicitEuler(queue,(Number,1),None,clData,Step)
555
        elif Method=="ExplicitEuler":
556
            CLLaunch=MyRoutines.ExplicitEuler(queue,(Number,1),None,clData,Step)
557
        elif Method=="Heun":
558
            CLLaunch=MyRoutines.Heun(queue,(Number,1),None,clData,Step)
559
        else:
560
            CLLaunch=MyRoutines.RungeKutta(queue,(Number,1),None,clData,Step)
561
        CLLaunch.wait()
562
        if CheckEnergies:
563
            CLLaunch=MyRoutines.Potential(queue,(Number,1),None,clData,clPotential)
564
            CLLaunch=MyRoutines.Kinetic(queue,(Number,1),None,clData,clKinetic)
565
            CLLaunch.wait()
566
            cl.enqueue_copy(queue,MyPotential,clPotential)
567
            cl.enqueue_copy(queue,MyKinetic,clKinetic)
568
            print(np.sum(MyPotential)+2*np.sum(MyKinetic),np.sum(MyPotential),np.sum(MyKinetic))
569

    
570
            print(MyPotential,MyKinetic)
571
            
572
        if GraphSamples:
573
            cl.enqueue_copy(queue, MyData, clData)
574
            t0=np.append(t0,[MyData[0][0],MyData[0][1],MyData[0][2]])
575
            t1=np.append(t1,[MyData[1][0],MyData[1][1],MyData[1][2]])
576
            tL=np.append(tL,[MyData[-1][0],MyData[-1][1],MyData[-1][2]])
577
    print("\nDuration on %s for each %s" % (Device,(time.time()-time_start)/Iterations))
578

    
579
    CLLaunch=MyRoutines.Potential(queue,(Number,1),None,clData,clPotential)
580
    CLLaunch=MyRoutines.Kinetic(queue,(Number,1),None,clData,clKinetic)
581
    CLLaunch.wait()
582
    cl.enqueue_copy(queue,MyPotential,clPotential)
583
    cl.enqueue_copy(queue,MyKinetic,clKinetic)
584
    print('Viriel=%s Potential=%s Kinetic=%s'% (np.sum(MyPotential)+2*np.sum(MyKinetic),np.sum(MyPotential),np.sum(MyKinetic)))
585
    MyRoutines.CenterOfMass(queue,(1,1),None,clData,clCoM,np.int32(Number))
586
    cl.enqueue_copy(queue,MyCoM,clCoM)
587
    print('Center Of Mass: (%s,%s,%s)' % (MyCoM[0][0],MyCoM[0][1],MyCoM[0][2]))
588
    
589
    if GraphSamples:    
590
        t0=np.transpose(np.reshape(t0,(Iterations+1,3)))
591
        t1=np.transpose(np.reshape(t1,(Iterations+1,3)))
592
        tL=np.transpose(np.reshape(tL,(Iterations+1,3)))
593
    
594
        import matplotlib.pyplot as plt
595
        from mpl_toolkits.mplot3d import Axes3D
596
    
597
        fig = plt.figure()
598
        ax = fig.gca(projection='3d')
599
        ax.scatter(t0[0],t0[1],t0[2], marker='^',color='blue')
600
        ax.scatter(t1[0],t1[1],t1[2], marker='o',color='red')
601
        ax.scatter(tL[0],tL[1],tL[2], marker='D',color='green')
602
   
603
        ax.set_xlabel('X Label')
604
        ax.set_ylabel('Y Label')
605
        ax.set_zlabel('Z Label')
606

    
607
        plt.show()
608
    
609
    clData.release()
610
    clKinetic.release()
611
    clPotential.release()