Statistiques
| Révision :

root / TrouNoir / TrouNoir.py @ 199

Historique | Voir | Annoter | Télécharger (11,73 ko)

1 199 equemene
#!/usr/bin/env python
2 199 equemene
#
3 199 equemene
# TrouNoir model using PyOpenCL
4 199 equemene
#
5 199 equemene
# CC BY-NC-SA 2011 : <emmanuel.quemener@ens-lyon.fr>
6 199 equemene
#
7 199 equemene
# Thanks to Andreas Klockner for PyOpenCL:
8 199 equemene
# http://mathema.tician.de/software/pyopencl
9 199 equemene
#
10 199 equemene
# Interesting links:
11 199 equemene
# http://viennacl.sourceforge.net/viennacl-documentation.html
12 199 equemene
# http://enja.org/2011/02/22/adventures-in-pyopencl-part-1-getting-started-with-python/
13 199 equemene
14 199 equemene
import pyopencl as cl
15 199 equemene
import numpy
16 199 equemene
from PIL import Image
17 199 equemene
import time,string
18 199 equemene
from numpy.random import randint as nprnd
19 199 equemene
import sys
20 199 equemene
import getopt
21 199 equemene
import matplotlib.pyplot as plt
22 199 equemene
23 199 equemene
KERNEL_CODE=string.Template("""
24 199 equemene

25 199 equemene
#define PI (float)3.14159265359
26 199 equemene
#define nbr 200
27 199 equemene

28 199 equemene
float atanp(float x,float y)
29 199 equemene
{
30 199 equemene
  float angle;
31 199 equemene

32 199 equemene
  angle=atan2(y,x);
33 199 equemene

34 199 equemene
  if (angle<0)
35 199 equemene
    {
36 199 equemene
      angle+=(float)2.e0f*PI;
37 199 equemene
    }
38 199 equemene

39 199 equemene
  return angle;
40 199 equemene
}
41 199 equemene

42 199 equemene
float f(float v)
43 199 equemene
{
44 199 equemene
  return v;
45 199 equemene
}
46 199 equemene

47 199 equemene
float g(float u,float m,float b)
48 199 equemene
{
49 199 equemene
  return (3.*m/b*pow(u,2)-u);
50 199 equemene
}
51 199 equemene

52 199 equemene

53 199 equemene
void calcul(float *us,float *vs,float up,float vp,
54 199 equemene
            float h,float m,float b)
55 199 equemene
{
56 199 equemene
  float c0,c1,c2,c3,d0,d1,d2,d3;
57 199 equemene

58 199 equemene
  c0=h*f(vp);
59 199 equemene
  c1=h*f(vp+c0/2.);
60 199 equemene
  c2=h*f(vp+c1/2.);
61 199 equemene
  c3=h*f(vp+c2);
62 199 equemene
  d0=h*g(up,m,b);
63 199 equemene
  d1=h*g(up+d0/2.,m,b);
64 199 equemene
  d2=h*g(up+d1/2.,m,b);
65 199 equemene
  d3=h*g(up+d2,m,b);
66 199 equemene

67 199 equemene
  *us=up+(c0+2.*c1+2.*c2+c3)/6.;
68 199 equemene
  *vs=vp+(d0+2.*d1+2.*d2+d3)/6.;
69 199 equemene
}
70 199 equemene

71 199 equemene
void rungekutta(float *ps,float *us,float *vs,
72 199 equemene
                float pp,float up,float vp,
73 199 equemene
                float h,float m,float b)
74 199 equemene
{
75 199 equemene
  calcul(us,vs,up,vp,h,m,b);
76 199 equemene
  *ps=pp+h;
77 199 equemene
}
78 199 equemene

79 199 equemene
float decalage_spectral(float r,float b,float phi,
80 199 equemene
                         float tho,float m)
81 199 equemene
{
82 199 equemene
  return (sqrt(1-3*m/r)/(1+sqrt(m/pow(r,3))*b*sin(tho)*sin(phi)));
83 199 equemene
}
84 199 equemene

85 199 equemene
float spectre(float rf,int q,float b,float db,
86 199 equemene
             float h,float r,float m,float bss)
87 199 equemene
{
88 199 equemene
  float flx;
89 199 equemene
  int fi;
90 199 equemene

91 199 equemene
  fi=(int)(rf*nbr/bss);
92 199 equemene
  flx=pow(r/m,q)*pow(rf,4)*b*db*h;
93 199 equemene
  return(flx);
94 199 equemene
}
95 199 equemene

96 199 equemene
float spectre_cn(float rf,float b,float db,
97 199 equemene
                float h,float r,float m,float bss)
98 199 equemene
{
99 199 equemene
  float flx;
100 199 equemene
  float nu_rec,nu_em,qu,v,temp,temp_em,flux_int,m_point,planck,c,k;
101 199 equemene
  int fi,posfreq;
102 199 equemene

103 199 equemene
  planck=6.62e-34;
104 199 equemene
  k=1.38e-23;
105 199 equemene
  temp=3.e7;
106 199 equemene
  m_point=1.e14;
107 199 equemene
  v=1.-3./r;
108 199 equemene

109 199 equemene
  qu=1/sqrt(1-3./r)/sqrt(r)*(sqrt(r)-sqrt(6.)+sqrt(3.)/2.*log((sqrt(r)+sqrt(3.))/(sqrt(r)-sqrt(3.))*(sqrt(6.)-sqrt(3.))/(sqrt(6.)+sqrt(3.))));
110 199 equemene

111 199 equemene
  temp_em=temp*sqrt(m)*exp(0.25*log(m_point))*exp(-0.75*log(r))*
112 199 equemene
    exp(-0.125*log(v))*exp(0.25*log(qu));
113 199 equemene

114 199 equemene
  flux_int=0;
115 199 equemene
  flx=0;
116 199 equemene

117 199 equemene
  for (fi=1;fi<nbr;fi++)
118 199 equemene
    {
119 199 equemene
      nu_em=bss*fi/nbr;
120 199 equemene
      nu_rec=nu_em*rf;
121 199 equemene
      posfreq=1./bss*nu_rec*nbr;
122 199 equemene
      if ((posfreq>0)&&(posfreq<nbr))
123 199 equemene
        {
124 199 equemene
          flux_int=2*planck/9.e16f*pow(nu_em,3)/(exp(planck*nu_em/k/temp_em)-1.)*pow(rf,3)*b*db*h;
125 199 equemene
          flx+=flux_int;
126 199 equemene
        }
127 199 equemene
    }
128 199 equemene
  return(flx);
129 199 equemene
}
130 199 equemene

131 199 equemene
void impact(float phi,float r,float b,float tho,float m,
132 199 equemene
            float *zp,float *fp,
133 199 equemene
            int q,float db,
134 199 equemene
            float h,float bss,int raie)
135 199 equemene
{
136 199 equemene
  float flx,rf;
137 199 equemene

138 199 equemene
  rf=decalage_spectral(r,b,phi,tho,m);
139 199 equemene

140 199 equemene
  if (raie==0)
141 199 equemene
    {
142 199 equemene
      flx=spectre(rf,q,b,db,h,r,m,bss);
143 199 equemene
    }
144 199 equemene
  else
145 199 equemene
    {
146 199 equemene
      flx=spectre_cn(rf,b,db,h,r,m,bss);
147 199 equemene
    }
148 199 equemene

149 199 equemene
  *zp=1./rf;
150 199 equemene
  *fp=flx;
151 199 equemene

152 199 equemene
}
153 199 equemene

154 199 equemene
__kernel void EachPixel(__global float *MyImage)
155 199 equemene
{
156 199 equemene
   uint xi=(uint)get_global_id(0);
157 199 equemene
   uint yi=(uint)get_global_id(1);
158 199 equemene
   uint sizex=(uint)get_global_size(0);
159 199 equemene
   uint sizey=(uint)get_global_size(1);
160 199 equemene

161 199 equemene
   // Perform trajectory for each pixel
162 199 equemene

163 199 equemene
  float m,rs,ri,re,tho,ro;
164 199 equemene
  int q;
165 199 equemene

166 199 equemene
  float bss,stp;
167 199 equemene
  int nmx,dim;
168 199 equemene
  float d,bmx,db,b,h;
169 199 equemene
  float up,vp,pp;
170 199 equemene
  float us,vs,ps;
171 199 equemene
  float rp[2000];
172 199 equemene
  float zmx,fmx,zen,fen;
173 199 equemene
  float flux_tot,impc_tot;
174 199 equemene
  float phi,thi,thx,phd,php,nr,r;
175 199 equemene
  int ni,ii,i,imx,j,n,tst,dist,raie,pc,fcl,zcl;
176 199 equemene
  int nh;
177 199 equemene
  int ExitOnImpact;
178 199 equemene
  float zp,fp;
179 199 equemene

180 199 equemene
  m=1.;
181 199 equemene
  rs=2.*m;
182 199 equemene
  ri=3.*rs;
183 199 equemene
  re=12.;
184 199 equemene
  ro=100.;
185 199 equemene
  //tho=PI/180.*80;
186 199 equemene
  tho=PI/180.*0.;
187 199 equemene
  q=-2;
188 199 equemene
  dist=1;
189 199 equemene
  raie=0;
190 199 equemene

191 199 equemene
  nmx=(float)sizex/2.;
192 199 equemene
  stp=0.5;
193 199 equemene
  // Autosize for image
194 199 equemene
  bmx=1.25*re;
195 199 equemene
  b=0.;
196 199 equemene
  thx=asin(bmx/ro);
197 199 equemene
  pc=0;
198 199 equemene

199 199 equemene
  h=PI/5.e2f;
200 199 equemene

201 199 equemene
  // set origin as center of image
202 199 equemene
  float x=(float)xi-(float)(sizex/2)+(float)5e-1f;
203 199 equemene
  float y=(float)(sizey/2)-(float)yi-(float)5e-1f;
204 199 equemene
  // angle extracted from cylindric symmetry
205 199 equemene
  phi=atanp(x,y);
206 199 equemene
  phd=atanp(cos(phi)*sin(tho),cos(tho));
207 199 equemene

208 199 equemene
  if (dist==1)
209 199 equemene
  {
210 199 equemene
     db=bmx/nmx;
211 199 equemene
     // impact parameter
212 199 equemene
     b=sqrt(x*x+y*y)*(float)2.e0f/(float)sizex*bmx;
213 199 equemene
     up=0.;
214 199 equemene
     vp=1.;
215 199 equemene
  }
216 199 equemene
  else
217 199 equemene
  {
218 199 equemene
     b=sqrt(x*x+y*y)*(float)2.e0f/(float)sizex*bmx;
219 199 equemene
     thi=asin(b/ro);
220 199 equemene
     db=bmx/nmx;
221 199 equemene
     up=sin(thi);
222 199 equemene
     vp=cos(thi);
223 199 equemene
  }
224 199 equemene

225 199 equemene
  pp=0.;
226 199 equemene
  nh=0;
227 199 equemene

228 199 equemene
  rungekutta(&ps,&us,&vs,pp,up,vp,h,m,b);
229 199 equemene

230 199 equemene
  rp[nh]=fabs(b/us);
231 199 equemene

232 199 equemene
  ExitOnImpact=0;
233 199 equemene

234 199 equemene
  do
235 199 equemene
  {
236 199 equemene
     nh++;
237 199 equemene
     pp=ps;
238 199 equemene
     up=us;
239 199 equemene
     vp=vs;
240 199 equemene
     rungekutta(&ps,&us,&vs,pp,up,vp,h,m,b);
241 199 equemene
     rp[nh]=fabs(b/us);
242 199 equemene
     ExitOnImpact = (((fmod(pp,PI)<fmod(phd,PI))&&(fmod(ps,PI)>fmod(phd,PI)))||((fmod(ps,PI)<fmod(phd,PI))&&(fmod(pp,PI)>fmod(phd,PI))))&&(rp[nh]>ri)&&(rp[nh]<re)?1:0;
243 199 equemene

244 199 equemene
  } while ((rp[nh]>=rs)&&(rp[nh]<=rp[0])&&(ExitOnImpact==0));
245 199 equemene

246 199 equemene
  if (ExitOnImpact==1) {
247 199 equemene
     impact(phi,rp[nh-1],b,tho,m,&zp,&fp,q,db,h,bss,raie);
248 199 equemene
  }
249 199 equemene
  else
250 199 equemene
  {
251 199 equemene
     zp=0.;
252 199 equemene
  }
253 199 equemene

254 199 equemene
//
255 199 equemene
  MyImage[yi+sizex*xi]=(float)zp;
256 199 equemene

257 199 equemene
  barrier(CLK_LOCAL_MEM_FENCE);
258 199 equemene

259 199 equemene
}
260 199 equemene
""")
261 199 equemene
262 199 equemene
def ImageOutput(sigma,prefix):
263 199 equemene
    Max=sigma.max()
264 199 equemene
    Min=sigma.min()
265 199 equemene
266 199 equemene
    # Normalize value as 8bits Integer
267 199 equemene
    SigmaInt=(255*(sigma-Min)/(Max-Min)).astype('uint8')
268 199 equemene
    image = Image.fromarray(SigmaInt)
269 199 equemene
    image.save("%s.jpg" % prefix)
270 199 equemene
271 199 equemene
def BlackHole(MyImage,Device):
272 199 equemene
273 199 equemene
    kernel_params = {}
274 199 equemene
275 199 equemene
    # Je detecte un peripherique GPU dans la liste des peripheriques
276 199 equemene
    Id=0
277 199 equemene
    HasXPU=False
278 199 equemene
    for platform in cl.get_platforms():
279 199 equemene
        for device in platform.get_devices():
280 199 equemene
            if Id==Device:
281 199 equemene
                XPU=device
282 199 equemene
                print "CPU/GPU selected: ",device.name.lstrip()
283 199 equemene
                HasXPU=True
284 199 equemene
            Id+=1
285 199 equemene
286 199 equemene
    if HasXPU==False:
287 199 equemene
        print "No XPU #%i found in all of %i devices, sorry..." % (Device,Id-1)
288 199 equemene
        sys.exit()
289 199 equemene
290 199 equemene
    ctx = cl.Context([XPU])
291 199 equemene
    queue = cl.CommandQueue(ctx,
292 199 equemene
                            properties=cl.command_queue_properties.PROFILING_ENABLE)
293 199 equemene
294 199 equemene
    BlackHoleCL = cl.Program(ctx,KERNEL_CODE.substitute(kernel_params)).build()
295 199 equemene
296 199 equemene
    # Je recupere les flag possibles pour les buffers
297 199 equemene
    mf = cl.mem_flags
298 199 equemene
299 199 equemene
    print(MyImage)
300 199 equemene
301 199 equemene
    # Program based on Kernel2
302 199 equemene
    MyImageCL = cl.Buffer(ctx, mf.WRITE_ONLY | mf.COPY_HOST_PTR, hostbuf=MyImage)
303 199 equemene
304 199 equemene
    start_time=time.time()
305 199 equemene
306 199 equemene
    CLLaunch=BlackHoleCL.EachPixel(queue,(MyImage.shape[0],MyImage.shape[1]),None,MyImageCL)
307 199 equemene
308 199 equemene
    CLLaunch.wait()
309 199 equemene
    elapsed = time.time()-start_time
310 199 equemene
    print("Elapsed %f: " % elapsed)
311 199 equemene
312 199 equemene
    cl.enqueue_copy(queue,MyImage,MyImageCL).wait()
313 199 equemene
314 199 equemene
    print(MyImage)
315 199 equemene
    MyImageCL.release()
316 199 equemene
317 199 equemene
    ImageOutput(MyImage,"TrouNoir")
318 199 equemene
    return(elapsed)
319 199 equemene
320 199 equemene
if __name__=='__main__':
321 199 equemene
322 199 equemene
    GpuStyle = 'OpenCL'
323 199 equemene
    Mass = 1.
324 199 equemene
    # Internal Radius 3 times de Schwarzschild Radius
325 199 equemene
    InternalRadius=6.*Mass
326 199 equemene
    #
327 199 equemene
    ExternalRadius=12.
328 199 equemene
    #
329 199 equemene
    ObserverDistance=100.
330 199 equemene
    # Angle with normal to disc 10 degrees
331 199 equemene
    Angle = numpy.pi/180.*(90.-10.)
332 199 equemene
    # Radiation of disc : BlackBody or Monochromatic
333 199 equemene
    BlackBody = True
334 199 equemene
    # Camera : Angular Camera or plate with the size of camera
335 199 equemene
    AngularCamera = True
336 199 equemene
    # Size of image
337 199 equemene
    Size=256
338 199 equemene
    # Variable Type
339 199 equemene
    VariableType='FP32'
340 199 equemene
    # ?
341 199 equemene
    q=-2
342 199 equemene
343 199 equemene
    HowToUse='%s -h [Help] -b [BlackBodyEmission] -c [AngularCamera] -s <SizeInPixels> -m <Mass> -i <DiscInternalRadius> -x <DiscExternalRadius> -o <ObservatorDistance> -a <AngleAboveDisc> -d <DeviceId> -g <CUDA/OpenCL> -t <FP32/FP64>'
344 199 equemene
345 199 equemene
    try:
346 199 equemene
        opts, args = getopt.getopt(sys.argv[1:],"hbcs:m:i:x:o:a:d:g:t:",["blackbody","camera","size=","mass=","internal=","external=","observer=","angle=","device=","gpustyle=","variabletype="])
347 199 equemene
    except getopt.GetoptError:
348 199 equemene
        print(HowToUse % sys.argv[0])
349 199 equemene
        sys.exit(2)
350 199 equemene
351 199 equemene
    # List of Devices
352 199 equemene
    Devices=[]
353 199 equemene
    Alu={}
354 199 equemene
355 199 equemene
    for opt, arg in opts:
356 199 equemene
        if opt == '-h':
357 199 equemene
            print(HowToUse % sys.argv[0])
358 199 equemene
359 199 equemene
            print("\nInformations about devices detected under OpenCL API:")
360 199 equemene
            # For PyOpenCL import
361 199 equemene
            try:
362 199 equemene
                import pyopencl as cl
363 199 equemene
                Id=0
364 199 equemene
                for platform in cl.get_platforms():
365 199 equemene
                    for device in platform.get_devices():
366 199 equemene
                        #deviceType=cl.device_type.to_string(device.type)
367 199 equemene
                        deviceType="xPU"
368 199 equemene
                        print("Device #%i from %s of type %s : %s" % (Id,platform.vendor.lstrip(),deviceType,device.name.lstrip()))
369 199 equemene
                        Id=Id+1
370 199 equemene
371 199 equemene
            except:
372 199 equemene
                print("Your platform does not seem to support OpenCL")
373 199 equemene
374 199 equemene
            print("\nInformations about devices detected under CUDA API:")
375 199 equemene
                # For PyCUDA import
376 199 equemene
            try:
377 199 equemene
                import pycuda.driver as cuda
378 199 equemene
                cuda.init()
379 199 equemene
                for Id in range(cuda.Device.count()):
380 199 equemene
                    device=cuda.Device(Id)
381 199 equemene
                    print("Device #%i of type GPU : %s" % (Id,device.name()))
382 199 equemene
                print
383 199 equemene
            except:
384 199 equemene
                print("Your platform does not seem to support CUDA")
385 199 equemene
386 199 equemene
            sys.exit()
387 199 equemene
388 199 equemene
        elif opt in ("-d", "--device"):
389 199 equemene
#            Devices.append(int(arg))
390 199 equemene
            Device=int(arg)
391 199 equemene
        elif opt in ("-g", "--gpustyle"):
392 199 equemene
            GpuStyle = arg
393 199 equemene
        elif opt in ("-t", "--variabletype"):
394 199 equemene
            VariableType = arg
395 199 equemene
        elif opt in ("-s", "--size"):
396 199 equemene
            Size = int(arg)
397 199 equemene
        elif opt in ("-m", "--mass"):
398 199 equemene
            Mass = float(arg)
399 199 equemene
        elif opt in ("-i", "--internal"):
400 199 equemene
            InternalRadius = float(arg)
401 199 equemene
        elif opt in ("-e", "--external"):
402 199 equemene
            ExternalRadius = float(arg)
403 199 equemene
        elif opt in ("-o", "--observer"):
404 199 equemene
            ObserverDistance = float(arg)
405 199 equemene
        elif opt in ("-a", "--angle"):
406 199 equemene
            Angle = numpy.pi/180.*(90.-float(arg))
407 199 equemene
        elif opt in ("-b", "--blackbody"):
408 199 equemene
            BlackBody = True
409 199 equemene
        elif opt in ("-c", "--camera"):
410 199 equemene
            AngularCamera = True
411 199 equemene
412 199 equemene
    print("Device Identification selected : %s" % Device)
413 199 equemene
    print("GpuStyle used : %s" % GpuStyle)
414 199 equemene
    print("VariableType : %s" % VariableType)
415 199 equemene
    print("Size : %i" % Size)
416 199 equemene
    print("Mass : %f" % Mass)
417 199 equemene
    print("Internal Radius : %f" % InternalRadius)
418 199 equemene
    print("External Radius : %f" % ExternalRadius)
419 199 equemene
    print("Observer Distance : %f" % ObserverDistance)
420 199 equemene
    print("Angle with normal of (in radians) : %f" % Angle)
421 199 equemene
    print("Black Body Disc Emission (monochromatic instead) : %s" % BlackBody)
422 199 equemene
    print("Angular Camera (dimension of object instead) : %s" % AngularCamera)
423 199 equemene
424 199 equemene
    if GpuStyle=='CUDA':
425 199 equemene
        print("\nSelection of CUDA device")
426 199 equemene
        try:
427 199 equemene
            # For PyCUDA import
428 199 equemene
            import pycuda.driver as cuda
429 199 equemene
430 199 equemene
            cuda.init()
431 199 equemene
            for Id in range(cuda.Device.count()):
432 199 equemene
                device=cuda.Device(Id)
433 199 equemene
                print("Device #%i of type GPU : %s" % (Id,device.name()))
434 199 equemene
                if Id in Devices:
435 199 equemene
                    Alu[Id]='GPU'
436 199 equemene
437 199 equemene
        except ImportError:
438 199 equemene
            print("Platform does not seem to support CUDA")
439 199 equemene
440 199 equemene
    if GpuStyle=='OpenCL':
441 199 equemene
        print("\nSelection of OpenCL device")
442 199 equemene
        try:
443 199 equemene
            # For PyOpenCL import
444 199 equemene
            import pyopencl as cl
445 199 equemene
            Id=0
446 199 equemene
            for platform in cl.get_platforms():
447 199 equemene
                for device in platform.get_devices():
448 199 equemene
                    #deviceType=cl.device_type.to_string(device.type)
449 199 equemene
                    deviceType="xPU"
450 199 equemene
                    print("Device #%i from %s of type %s : %s" % (Id,platform.vendor.lstrip().rstrip(),deviceType,device.name.lstrip().rstrip()))
451 199 equemene
452 199 equemene
                    if Id in Devices:
453 199 equemene
                    # Set the Alu as detected Device Type
454 199 equemene
                        Alu[Id]=deviceType
455 199 equemene
                    Id=Id+1
456 199 equemene
        except ImportError:
457 199 equemene
            print("Platform does not seem to support OpenCL")
458 199 equemene
459 199 equemene
#    print(Devices,Alu)
460 199 equemene
461 199 equemene
#    MyImage=numpy.where(numpy.random.zeros(Size,Size)>0,1,-1).astype(numpy.float32)
462 199 equemene
    MyImage=numpy.zeros((Size,Size),dtype=numpy.float32)
463 199 equemene
464 199 equemene
    print(MyImage)
465 199 equemene
466 199 equemene
    duration=BlackHole(MyImage,Device)
467 199 equemene