Statistiques
| Révision :

root / TrouNoir / trou_noir_20190607.c @ 310

Historique | Voir | Annoter | Télécharger (10,48 ko)

1
/*
2
        Programme original realise en Fortran 77 en mars 1994
3
        pour les Travaux Pratiques de Modelisation Numerique
4
        DEA d'astrophysique et techniques spatiales de Meudon
5

6
                par Herve Aussel et Emmanuel Quemener
7

8
        Conversion en C par Emmanuel Quemener en aout 1997
9

10
        Remerciements a :
11

12
        - Herve Aussel pour sa procedure sur le spectre de corps noir
13
        - Didier Pelat pour l'aide lors de ce travail
14
        - Jean-Pierre Luminet pour son article de 1979
15
        - Le Numerical Recipies pour ses recettes de calcul
16
        - Luc Blanchet pour sa disponibilite lors de mes interrogations en RG
17

18
        Mes Coordonnees :        Emmanuel Quemener
19
                                Departement Optique
20
                                ENST de Bretagne
21
                                BP 832
22
                                29285 BREST Cedex
23

24
                                Emmanuel.Quemener@enst-bretagne.fr
25

26
        Compilation sous gcc ( Compilateur GNU sous Linux ) :
27

28
                gcc -O6 -m486 -o trou_noir trou_noir.c -lm
29
*/ 
30

    
31
#include <stdio.h>
32
#include <math.h>
33
#include <stdlib.h>
34
#include <string.h>
35

    
36
#define nbr 200 /* Nombre de colonnes du spectre */
37

    
38
#define PI 3.14159265359
39

    
40
float atanp(float x,float y)
41
{
42
  float angle;
43

    
44
  angle=atan2(y,x);
45

    
46
  if (angle<0)
47
    {
48
      angle+=2*PI;
49
    }
50

    
51
  return angle;
52
}
53

    
54

    
55
float f(float v)
56
{
57
  return v;
58
}
59

    
60
float g(float u,float m,float b)
61
{
62
  return (3.*m/b*pow(u,2)-u);
63
}
64

    
65

    
66
void calcul(float *us,float *vs,float up,float vp,
67
            float h,float m,float b)
68
{
69
  float c[4],d[4];
70

    
71
  c[0]=h*f(vp);
72
  c[1]=h*f(vp+c[0]/2.);
73
  c[2]=h*f(vp+c[1]/2.);
74
  c[3]=h*f(vp+c[2]);
75
  d[0]=h*g(up,m,b);
76
  d[1]=h*g(up+d[0]/2.,m,b);
77
  d[2]=h*g(up+d[1]/2.,m,b);
78
  d[3]=h*g(up+d[2],m,b);
79

    
80
  *us=up+(c[0]+2.*c[1]+2.*c[2]+c[3])/6.;
81
  *vs=vp+(d[0]+2.*d[1]+2.*d[2]+d[3])/6.;
82
}
83

    
84
void rungekutta(float *ps,float *us,float *vs,
85
                float pp,float up,float vp,
86
                float h,float m,float b)
87
{
88
  calcul(us,vs,up,vp,h,m,b);
89
  *ps=pp+h;
90
}
91

    
92

    
93
float decalage_spectral(float r,float b,float phi,
94
                         float tho,float m)
95
{
96
  return (sqrt(1-3*m/r)/(1+sqrt(m/pow(r,3))*b*sin(tho)*sin(phi)));
97
}
98

    
99
/* void spectre(float rf,int q,float b,float db, */
100
/*              float h,float r,float m,float bss,float *flx) */
101
float spectre(float rf,int q,float b,float db,
102
             float h,float r,float m,float bss)
103
{
104
  float flx;
105
  int fi;
106

    
107
  fi=(int)(rf*nbr/bss);
108
  flx=pow(r/m,q)*pow(rf,4)*b*db*h;
109
  return(flx);
110
}
111

    
112
/* void spectre_cn(float rf,float b,float db, */
113
/*                 float h,float r,float m,float bss,float *flx) */
114
float spectre_cn(float rf,float b,float db,
115
                float h,float r,float m,float bss)
116
{
117
  float flx;
118
  float nu_rec,nu_em,qu,v,temp,temp_em,flux_int,m_point,planck,c,k;
119
  int fi,posfreq;
120

    
121
  planck=6.62e-34;
122
  k=1.38e-23;
123
  temp=3.e7;
124
  m_point=1.e14;
125
  v=1.-3./r;
126

    
127
  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))));
128

    
129
  temp_em=temp*sqrt(m)*exp(0.25*log(m_point))*exp(-0.75*log(r))*
130
    exp(-0.125*log(v))*exp(0.25*log(qu));
131

    
132
  flux_int=0;
133
  flx=0;
134

    
135
  for (fi=1;fi<nbr;fi++)
136
    {
137
      nu_em=bss*fi/nbr;
138
      nu_rec=nu_em*rf; 
139
      posfreq=1./bss*nu_rec*nbr;
140
      if ((posfreq>0)&&(posfreq<nbr))
141
        {
142
          flux_int=2*planck/9e16*pow(nu_em,3)/(exp(planck*nu_em/k/temp_em)-1.)*pow(rf,3)*b*db*h;
143
          flx+=flux_int;
144
        }
145
    }
146
  return(flx);
147
}
148

    
149
void impact(float d,float phi,int dim,float r,float b,float tho,float m,
150
            float **zp,float **fp,
151
            int q,float db,
152
            float h,float bss,int raie)
153
{
154
  float xe,ye;
155
  int xi,yi;
156
  float flx,rf;
157
  xe=d*sin(phi);
158
  ye=-d*cos(phi);
159

    
160
  xi=(int)xe+dim/2;
161
  yi=(int)ye+dim/2;
162

    
163
  rf=decalage_spectral(r,b,phi,tho,m);
164

    
165
  if (raie==0)
166
    {
167
      flx=spectre(rf,q,b,db,h,r,m,bss);
168
    }
169
  else
170
    {
171
      flx=spectre_cn(rf,b,db,h,r,m,bss);
172
    }
173
  
174
  if (zp[xi][yi]==0.)
175
    {
176
      zp[xi][yi]=1./rf;
177
    }
178
  
179
  if (fp[xi][yi]==0.)
180
    {
181
      fp[xi][yi]=flx;
182
    }
183
}
184

    
185
void sauvegarde_pgm(char nom[24],unsigned int **image,int dim)
186
{
187
  FILE            *sortie;
188
  unsigned long   i,j;
189
  
190
  sortie=fopen(nom,"w");
191
  
192
  fprintf(sortie,"P5\n");
193
  fprintf(sortie,"%i %i\n",dim,dim);
194
  fprintf(sortie,"255\n");
195

    
196
  for (j=0;j<dim;j++) for (i=0;i<dim;i++)
197
    {
198
      fputc(image[i][j],sortie);
199
    }
200

    
201
  fclose(sortie);
202
}
203

    
204
int main(int argc,char *argv[])
205
{
206

    
207
  float m,rs,ri,re,tho,ro;
208
  int q;
209

    
210
  float bss,stp;
211
  int nmx,dim;
212
  float d,bmx,db,b,h;
213
  float up,vp,pp;
214
  float us,vs,ps;
215
  float rp[2000];
216
  float **zp,**fp;
217
  unsigned int **izp,**ifp;
218
  float zmx,fmx,zen,fen;
219
  float flux_tot,impc_tot;
220
  float phi,thi,thx,phd,php,nr,r;
221
  int ni,ii,i,imx,j,n,tst,dist,raie,pc,fcl,zcl;
222
  float nh;
223

    
224
  if (argc==2)
225
    {
226
      if (strcmp(argv[1],"-aide")==0)
227
        {
228
          printf("\nSimulation d'un disque d'accretion autour d'un trou noir\n");
229
          printf("\nParametres a definir :\n\n");
230
          printf("   1) Dimension de l'Image\n");
231
          printf("   2) Masse relative du trou noir\n");
232
          printf("   3) Dimension du disque exterieur\n");
233
          printf("   4) Distance de l'observateur\n");
234
          printf("   5) Inclinaison par rapport au disque (en degres)\n");
235
          printf("   6) Observation a distance FINIE ou INFINIE\n");
236
          printf("   7) Rayonnement de disque MONOCHROMATIQUE ou CORPS_NOIR\n");
237
          printf("   8) Normalisation des flux INTERNE ou EXTERNE\n");
238
          printf("   9) Normalisation de z INTERNE ou EXTERNE\n"); 
239
          printf("  10) Impression des images NEGATIVE ou POSITIVE\n"); 
240
          printf("  11) Nom de l'image des Flux\n");
241
          printf("  12) Nom de l'image des decalages spectraux\n");
242
          printf("  13) Valeur de normalisation des flux\n");
243
          printf("  14) Valeur de normalisation des decalages spectraux\n");
244
          printf("\nSi aucun parametre defini, parametres par defaut :\n\n");
245
          printf("   1) Dimension de l'image : 256 pixels de cote\n");
246
          printf("   2) Masse relative du trou noir : 1\n");
247
          printf("   3) Dimension du disque exterieur : 12 \n");
248
          printf("   4) Distance de l'observateur : 100 \n");
249
          printf("   5) Inclinaison par rapport au disque (en degres) : 10\n");
250
          printf("   6) Observation a distance FINIE\n");
251
          printf("   7) Rayonnement de disque MONOCHROMATIQUE\n");
252
          printf("   8) Normalisation des flux INTERNE\n");
253
          printf("   9) Normalisation des z INTERNE\n");
254
          printf("  10) Impression des images NEGATIVE ou POSITIVE\n"); 
255
                 printf("  11) Nom de l'image des flux : flux.pgm\n");
256
          printf("  12) Nom de l'image des z : z.pgm\n");
257
          printf("  13) <non definie>\n");
258
          printf("  14) <non definie>\n");
259
        }
260
    }
261
  
262
  if ((argc==13)||(argc==15))
263
    {
264
      printf("# Utilisation les valeurs definies par l'utilisateur\n");
265
      
266
      dim=atoi(argv[1]);
267
      m=atof(argv[2]);
268
      re=atof(argv[3]);
269
      ro=atof(argv[4]);
270
      tho=PI/180.*(90-atof(argv[5]));
271
      
272
      rs=2.*m;
273
      ri=3.*rs;
274
      q=-2;
275

    
276
      if (strcmp(argv[6],"FINIE")==0)
277
        {
278
          dist=0;
279
        }
280
      else
281
        {
282
          dist=1;
283
        }
284

    
285
      if (strcmp(argv[7],"MONOCHROMATIQUE")==0)
286
        {
287
          raie=0;
288
        }
289
      else
290
        {
291
          raie=1;
292
        }
293

    
294
      if (strcmp(argv[8],"EXTERNE")==0)
295
        {
296
          fen=atof(argv[14]);
297
        }
298
      
299
      if (strcmp(argv[9],"EXTERNE")==0)
300
        {
301
          zen=atof(argv[15]);
302
        }
303
      
304
    }
305
  else
306
    {
307
      printf("# Utilisation les valeurs par defaut\n");
308
      
309
      dim=256;
310
      m=1.;
311
      rs=2.*m;
312
      ri=3.*rs;
313
      re=12.;
314
      ro=100.;
315
      tho=PI/180.*80;
316
      q=-2;
317
      dist=0;
318
      raie=0;
319
    }
320
      
321
  printf("# Dimension de l'image : %i\n",dim);
322
  printf("# Masse : %f\n",m);
323
  printf("# Rayon singularite : %f\n",rs);
324
  printf("# Rayon interne : %f\n",ri);
325
  printf("# Rayon externe : %f\n",re);
326
  printf("# Distance de l'observateur : %f\n",ro);
327
  printf("# Inclinaison a la normale en radian : %f\n",tho);
328
  
329
  zp=(float**)calloc(dim,sizeof(float*));
330
  zp[0]=(float*)calloc(dim*dim,sizeof(float));
331
  
332
  fp=(float**)calloc(dim,sizeof(float*));
333
  fp[0]=(float*)calloc(dim*dim,sizeof(float));
334

    
335
  izp=(unsigned int**)calloc(dim,sizeof(unsigned int*));
336
  izp[0]=(unsigned int*)calloc(dim*dim,sizeof(unsigned int));
337
  
338
  ifp=(unsigned int**)calloc(dim,sizeof(unsigned int*));
339
  ifp[0]=(unsigned int*)calloc(dim*dim,sizeof(unsigned int));
340

    
341
  for (i=1;i<dim;i++)
342
    {
343
      zp[i]=zp[i-1]+dim;
344
      fp[i]=fp[i-1]+dim;
345
      izp[i]=izp[i-1]+dim;
346
      ifp[i]=ifp[i-1]+dim;
347
    }
348

    
349
  nmx=dim;
350
  stp=dim/(2.*nmx);
351
  bmx=1.25*re;
352
  b=0.;
353
  thx=asin(bmx/ro);
354
  pc=0;
355

    
356
  if (raie==0)
357
    {
358
      bss=2;
359
    }
360
  else
361
    {
362
      bss=3e21;
363
    }
364
  
365
  for (n=1;n<=nmx;n++)
366
    {     
367
      h=PI/500.;
368
      d=stp*n;
369

    
370
      if (dist==1)
371
        {
372
          db=bmx/(float)nmx;
373
          b=db*(float)n;
374
          up=0.;
375
          vp=1.;
376
        }
377
      else
378
        {
379
          thi=thx/(float)nmx*(float)n;
380
          db=ro*sin(thi)-b;
381
          b=ro*sin(thi);
382
          up=sin(thi);
383
          vp=cos(thi);
384
        }
385
      
386
      pp=0.;
387
      nh=1;
388

    
389
      rungekutta(&ps,&us,&vs,pp,up,vp,h,m,b);
390
    
391
      rp[(int)nh]=fabs(b/us);
392
      
393
      do
394
        {
395
          nh++;
396
          pp=ps;
397
          up=us;
398
          vp=vs;
399
          rungekutta(&ps,&us,&vs,pp,up,vp,h,m,b);
400
          
401
          rp[(int)nh]=b/us;
402
          
403
        } while ((rp[(int)nh]>=rs)&&(rp[(int)nh]<=rp[1]));
404
      
405
      for (i=nh+1;i<2000;i++)
406
        {
407
          rp[i]=0.; 
408
        }
409
      
410
      imx=(int)(8*d);
411
      
412
      for (i=0;i<=imx;i++)
413
        {
414
          phi=2.*PI/(float)imx*(float)i;
415
          phd=atanp(cos(phi)*sin(tho),cos(tho));
416
          phd=fmod(phd,PI);
417
          ii=0;
418
          tst=0;
419
          
420
          do
421
            {
422
              php=phd+(float)ii*PI;
423
              nr=php/h;
424
              ni=(int)nr;
425

    
426
              if ((float)ni<nh)
427
                {
428
                  r=(rp[ni+1]-rp[ni])*(nr-ni*1.)+rp[ni];
429
                }
430
              else
431
                {
432
                  r=rp[ni];
433
                }
434
           
435
              if ((r<=re)&&(r>=ri))
436
                {
437
                  tst=1;
438
                  impact(d,phi,dim,r,b,tho,m,zp,fp,q,db,h,bss,raie);
439
                }
440
              
441
              ii++;
442
            } while ((ii<=2)&&(tst==0));
443
        }
444
    }
445

    
446
  fmx=fp[0][0];
447
  zmx=zp[0][0];
448
  
449
  for (i=0;i<dim;i++) for (j=0;j<dim;j++)
450
    {
451
      if (fmx<fp[i][j])
452
        {
453
          fmx=fp[i][j];
454
        }
455
      
456
      if (zmx<zp[i][j])
457
        {
458
          zmx=zp[i][j];
459
        }
460
    }
461

    
462
  printf("\nLe flux maximal detecte est de %f",fmx);
463
  printf("\nLe decalage spectral maximal detecte est de %f\n\n",zmx);
464

    
465
  if (strcmp(argv[8],"EXTERNE")==0)
466
    {
467
      fmx=fen;
468
    }
469

    
470
  if (strcmp(argv[9],"EXTERNE")==0)
471
    {  
472
      zmx=zen;
473
    }
474

    
475
  for (i=0;i<dim;i++) for (j=0;j<dim;j++)
476
    {
477
      zcl=(int)(255/zmx*zp[i][dim-1-j]);
478
      fcl=(int)(255/fmx*fp[i][dim-1-j]);
479

    
480
      if (strcmp(argv[8],"NEGATIVE")==0)
481
        {
482
          if (zcl>255)
483
            {
484
              izp[i][j]=0;
485
            }
486
          else
487
            {
488
              izp[i][j]=255-zcl;
489
            }
490
          
491
          if (fcl>255)
492
            {
493
              ifp[i][j]=0;
494
            }
495
          else
496
            {
497
              ifp[i][j]=255-fcl;
498
            } 
499
          
500
        }
501
      else
502
        {
503
          if (zcl>255)
504
            {
505
              izp[i][j]=255;
506
            }
507
          else
508
            {
509
              izp[i][j]=zcl;
510
            }
511
          
512
          if (fcl>255)
513
            {
514
              ifp[i][j]=255;
515
            }
516
          else
517
            {
518
              ifp[i][j]=fcl;
519
            } 
520
          
521
        }
522
        
523
    }
524

    
525
  if ((argc==14)||(argc==16))
526
   {
527
     sauvegarde_pgm(argv[11],ifp,dim);
528
     sauvegarde_pgm(argv[12],izp,dim);
529
   }
530
  else
531
    {
532
      sauvegarde_pgm("z.pgm",izp,dim);
533
      sauvegarde_pgm("flux.pgm",ifp,dim);
534
    }
535

    
536
  free(zp[0]);
537
  free(zp);
538
  free(fp[0]);
539
  free(fp);
540

    
541
  free(izp[0]);
542
  free(izp);
543
  free(ifp[0]);
544
  free(ifp);
545

    
546
}
547

    
548