HARM
harm and utilities
 All Data Structures Files Functions Variables Typedefs Macros Pages
init.tools.c
Go to the documentation of this file.
1 
2 
8 #include "decs.h"
9 
10 
11 extern FTYPE normglobal;
12 extern int inittypeglobal; // for bounds to communicate detail of what doing
13 
14 extern int init_dsandvels(int inittype, int pos, int *whichvel, int *whichcoord, SFTYPE time, int i, int j, int k, FTYPE *p, FTYPE *pstag);
15 
16 
18 {
19  FTYPE Rhor,rminus;
20 
21  Rhor=rhor_calc(0);
22  *rin=setRin(setihor());
23 
24  // (*rin) = 0.98 * Rhor;
25 
26 
27  trifprintf("R0=%21.15g Rhor=%21.15g Rin=%21.15g Rout=%21.15g ihor=%d MBH=%g\n",R0,Rhor,(*rin),Rout,setihor(),MBH);
28 
29  if((*rin)<R0){
30  dualfprintf(fail_file,"Wrong Rin calculation\n");
31  myexit(34968346);
32  }
33  if((*rin)<0.0){
34  dualfprintf(fail_file,"Very Poor Rin<0 calculation\n");
35  myexit(34968347);
36  }
37  rminus=rhor_calc(1);
38  if((*rin)<rminus){
39  dualfprintf(fail_file,"Rin<r_- : Poor Rin calculation: %g %g\n",*rin,rminus);
40  myexit(34968348);
41  }
42  if((*rin)>Rhor){
43  dualfprintf(fail_file,"Rin>r_+ : Poor Rin calculation: %g %g\n",*rin,Rhor);
44  myexit(34968349);
45  }
46 
47 
48  return(0);
49 }
50 
51 // some very common, but not completely general, user-type functions for init.c
52 
54 {
55 
56  // choice// GODMARK: not convenient location, but needed for init_mpi()
57  periodicx1=0;
58  periodicx2=0;
59 #if(N3!=1)
60  periodicx3=1;// GODMARK: periodic in \phi for 3D spherical polar
61 #else
62  periodicx3=0;
63 #endif
64 
65 
66 
67  if(PRODUCTION){
68  // assume if production always want binary data with text header
69  binaryoutput=MIXEDOUTPUT; // choice: mixed or binary
70  }
71 
72 
73  return(0);
74 
75 }
76 
77 
78 
79 int user1_init_conservatives(int *fieldfrompotential, FTYPE (*prim)[NSTORE2][NSTORE3][NPR],FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*Utemp)[NSTORE2][NSTORE3][NPR], FTYPE (*U)[NSTORE2][NSTORE3][NPR])
80 {
81  int pl,pliter;
82 
83  PLOOPBONLY(pl) trifprintf("fieldfrompotential[%d]=%d\n",pl-B1+1,fieldfrompotential[pl-B1+1]);
84 
85 
86  trifprintf("begin init_conservatives\n");
87  pi2Uavg(fieldfrompotential, prim, pstag, Utemp, U);
88  trifprintf("end init_conservatives\n");
89 
90  return(0);
91 
92 }
93 
94 
96 {
97  // globally used parameters set by specific initial condition routines, reran for restart as well *after* all other calculations
98 
100 
101  // UTOPRIMVERSION = UTOPRIM5D1;
102  // UTOPRIMVERSION = UTOPRIM2DFINAL;
103 
104  return(0);
105 }
106 
107 
109 {
110  int pl,pliter;
111 
112  DODIAGEVERYSUBSTEP = 0;
113 
114 
115  SAFE=1.3;
116  // cour = 0.9;
117  // cour=0.8;
118  cour = 0.4999;
119 
120  // NOTEMARK on cour
121  // Changed to cour=0.5 because noticed that with STOREWAVESPEEDS==1 that extremely unstable with 0.8 near pole due to larger or smaller wave speeds from max-averaging from CENT to FACE1/2/3. While may be inconsistency in Riemann solution, LAXF is simply a diffusive solution so shouldn't be so dependent upon exact wave speed. Noticed that with one setup where instability appeared (large radii 512x32 type run) that forcing timestep to be like STOREWAVESPEEDS==0 led to much more stable solution, but still kinda unstable to a saturation point. That was with cour=0.83*0.8=664. For safety, use cour=0.4999. In any case, this is motivated by fact that only with cour<0.5 will Riemann waves from interface not intersect by a single timestep, and only with non-intersecting waves does Riemann solution make sense. So cour>0.5 is really too aggressive. Still keep multi-dimen effective courant reducer since that's there for different reasons of multi-dimen stability issues.
122 
123  // NOTEMARK on cour
124  // For standard non-tilted torus model at a=0.9375 in fully 3D with 64x64x8 resolution.
125  // As of 07/26/2012, I have found cour=0.4999 leads to ~40k "entropy and bad" or "Failed to find" SOFT errors and no hard failures (i.e. "cold and bad"). But, cour=0.8 leads to only 21K non-hard failures but gets 1 or 2 hard failures.
126  // So overall cour=0.4999 more trustable to evolve velocity, but more frequently fails to evolve densities.
127 
128  // Also while a single Riemann fan won't go reach into another cell with cour>0.5 && cour<1.0, the Riemann fans from each cells collide for anything using cour>=0.5. And so in that case the average state isn't at all like what the Riemann solver predicts.
129 
131  //
132  // ENO-RELATED STUFF
133  //
135 
139 
140  LIMIT_AC_FRAC_CHANGE=0; // CHANGINGMARK: avoiding complication for now
141  // have to make consistent with weno-minimization for fluxes
142  MAX_AC_FRAC_CHANGE=0.2;
143 
144  // need MAXBND==17 if not evolving point field and doing full WENO5BND
145  // test1103 N1=8 is smallest tried and new simple_ limiting works at 10% very well
146  //dofluxreconevolvepointfield=0;
147  // only need MAXBND==11 like normal higher-order method (like FV method)
149 
150 
151 
152  if(DOEVOLVERHO){
153 
154 
155  //avgscheme[1]=avgscheme[2]=avgscheme[3]=WENO5BND;
156  // lim[1] = lim[2] = lim[3] = WENO5BND;
157  lim[1] = lim[2] = lim[3] = PARALINE;
158 
159  avgscheme[1]=avgscheme[2]=avgscheme[3]=DONOR; // CHANGINGMARK
160  //lim[1] = lim[2] = lim[3] = MC; // CHANGINGMARK
161 
162 
164  //DOENOFLUX = ENOFLUXRECON; // CHANGINGMARK
165  //DOENOFLUX = ENOFINITEVOLUME;
166 
167  if(DOENOFLUX == ENOFLUXRECON){
168  // below applies to all fluxes
171  // below used for re-averaging of field in advance.c for dBhat/dt method
174  }
175 
176  if(DOENOFLUX == ENOFINITEVOLUME){
179  PALLLOOP(pl) do_source_integration[pl] = 0;
180  PLOOPBONLY(pl) do_source_integration[pl] = 0;
183  // do_conserved_integration[B1-1+DIRZ] = 1;
184  }
185 
186 
187 
188  FLUXB = FLUXCTSTAG; // CHANGINGMARK
189  // FLUXB = FLUXCTHLL;
190  //FLUXB = FLUXCTTOTH;
191  // TIMEORDER=2;
192  TIMEORDER=4;
193  // TIMEORDER=3;
195  // PALLLOOP(pl) fluxmethod[pl]= HLLFLUX;
196  PALLLOOP(pl) fluxmethod[pl]= LAXFFLUX; // generally more robust than HLLFLUX for various reasons
197 
198 
199  // UTOPRIMVERSION=UTOPRIM5D1;
201  // UTOPRIMVERSION = UTOPRIM1DFINAL;
202  }
203 
204 
206  // PARA and TO=4 and HLL not trustable in FFDE so far
207  lim[1] =lim[2]=lim[3]= MC;
208  TIMEORDER=2;
210 
211 
212  // below applies to all fluxes
215  // below used for re-averaging of field in advance.c for dBhat/dt method
218 
219 
220 
221  PALLLOOP(pl) fluxmethod[pl]=LAXFFLUX; // generally more robust than HLLFLUX
222  // FLUXB = FLUXCTTOTH;
223  FLUXB = FLUXCTSTAG;
224  // UTOPRIMVERSION=UTOPRIM2DFINAL;
226  // whether/which ENO used to interpolate fluxes
227  // DOENOFLUX = ENOFINITEVOLUME;
229  //DOENOFLUX=ENOFLUXRECON;
230  }
231 
232 
233 
234  ranc(1,0); // no MPI method yet, so just pure randomization
235  /* some physics parameters */
236  gam = 4. / 3.;
238 
239 
245 
247  // rescaletype=1;
248  rescaletype=4;
249  BSQORHOLIMIT=1E2; // was 1E2 but latest BC test had 1E3 // CHANGINGMARK
250  BSQOULIMIT=1E3; // was 1E3 but latest BC test had 1E4
251  UORHOLIMIT=1E3;
252  RHOMIN = 1E-4;
253  UUMIN = 1E-6;
254 
255  GAMMAMAXRAD=10000.0;
257 
258 
259  // below floor model is only used if rescaletype!=4
260  if(BCtype[X1UP]==FIXEDOUTFLOW){ // then doing bondi inflow
261  // avoids constant floor activation -- trying to be more physical
262  prfloorcoef[RHO]=RHOMIN/100.0;
263  prfloorcoef[UU]=UUMIN/100.0;
264  }
265  else{
268  }
269 
271  // rescaletype=1;
272  rescaletype=4;
273  BSQORHOLIMIT=1E2; // was 1E2 but latest BC test had 1E3 // CHANGINGMARK
274  BSQOULIMIT=1E3; // was 1E3 but latest BC test had 1E4
275  UORHOLIMIT=1E3;
276  RHOMIN = 1E-4;
277  UUMIN = 1E-6;
278 
279 
280  /* dumping frequency, in units of M */
281  int idt;
282  for(idt=0;idt<NUMDUMPTYPES;idt++) DTdumpgen[idt]=50.0;
283  // ener period
284  DTdumpgen[ENERDUMPTYPE] = 2.0;
285  /* image file frequ., in units of M */
286  DTdumpgen[IMAGEDUMPTYPE] = 2.0;
287  // fieldline locked to images so can overlay
289 
290  /* debug file */
291  DTdumpgen[DEBUGDUMPTYPE] = 50.0;
292  // DTr = .1 ; /* restart file frequ., in units of M */
293  /* restart file period in steps */
294  DTr = 3000;
295  DTfake=MAX(1,DTr/10);
296 
297 
298  tf=2E3; // very problem dependent, should override
299 
300  return(0);
301 }
302 
303 
304 // assumes normalized density
305 int user1_init_atmosphere(int *whichvel, int*whichcoord,int i, int j, int k, FTYPE *pr)
306 {
307  int pl,pliter;
308  struct of_geom realgeomdontuse;
309  struct of_geom *ptrrealgeom=&realgeomdontuse;
310  FTYPE pratm[NPR];
311 
312 
313 
314 
315  get_geometry(i, j, k, CENT, ptrrealgeom); // true coordinate system
316  set_atmosphere(-1,WHICHVEL,ptrrealgeom,pratm); // set velocity in chosen WHICHVEL frame in any coordinate system
317 
318  if(pr[RHO]<pratm[RHO]){
319  PLOOP(pliter,pl) pr[pl]=pratm[pl];
320  }
321 
322 
323  *whichvel=WHICHVEL;
324  *whichcoord=PRIMECOORDS;
325  return(0);
326 
327 
328 }
329 
330 
331 
332 int user1_init_primitives(int inittype, FTYPE (*prim)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*ucons)[NSTORE2][NSTORE3][NPR], FTYPE (*vpot)[NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3], FTYPE (*Bhat)[NSTORE2][NSTORE3][NPR], FTYPE (*panalytic)[NSTORE2][NSTORE3][NPR], FTYPE (*pstaganalytic)[NSTORE2][NSTORE3][NPR], FTYPE (*vpotanalytic)[NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3], FTYPE (*Bhatanalytic)[NSTORE2][NSTORE3][NPR],
333  FTYPE (*F1)[NSTORE2][NSTORE3][NPR+NSPECIAL],FTYPE (*F2)[NSTORE2][NSTORE3][NPR+NSPECIAL],FTYPE (*F3)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*Atemp)[NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3])
334 {
335  int whichvel, whichcoord;
336  int initreturn;
337  int i = 0, j = 0, k = 0, l;
338  FTYPE r,th,X[NDIM],V[NDIM];
339  int normalize_densities(FTYPE (*prim)[NSTORE2][NSTORE3][NPR]);
340  int normalize_field(FTYPE (*prim)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*ucons)[NSTORE2][NSTORE3][NPR], FTYPE (*vpot)[NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3], FTYPE (*Bhat)[NSTORE2][NSTORE3][NPR]);
341  int init_atmosphere(int *whichvel, int *whichcoord, int i, int j, int k, FTYPE *pr);
342  int pl,pliter;
343 
345  //
346  // Assign primitive variables
347  //
349  trifprintf("Assign primitives\n");
350 
351 
352 
353  // assume we start in bl coords and convert to KSprim
354  // so field defined when get to floor model (fixup)
355  init_3dnpr_fullloop(0.0,prim);
356 
357 
358 
359 
361  //
362  // assume we start in bl coords and convert to KSprim
363  //
365 #pragma omp parallel private(i,j,k,initreturn,whichvel,whichcoord) OPENMPGLOBALPRIVATEFULL
366  {
370 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
372  OPENMP3DLOOPBLOCK2IJK(i,j,k);
373 
374  initreturn=init_dsandvels(inittype, CENT, &whichvel, &whichcoord,t,i,j,k,MAC(prim,i,j,k),MAC(pstag,i,j,k)); // request densities for all computational centers // t is ok here for initialization
375  if(initreturn>0){
376  FAILSTATEMENT("init.c:init_primitives()", "init_dsandvels()", 1);
377  }
378  else MYFUN(transform_primitive_vB(whichvel, whichcoord, i,j,k, prim, pstag),"init.c:init_primitives","transform_primitive_vB()",0);
379 
380 
381  // force dummy entropy variable to be same as ug so restart file consistent -- even if not used by the code.
382  if(ENTROPY>=0){
383  MACP0A1(prim,i,j,k,ENTROPY)=MACP0A1(prim,i,j,k,UU);
384  }
385 
386 
387  }
388  }// end parallel region
389 
390 
391 
393  //
394  // assign rough pstag value in case not using vector potential
395  //
397  if(FLUXB==FLUXCTSTAG){
398 #pragma omp parallel private(i,j,k,initreturn,whichvel,whichcoord) OPENMPGLOBALPRIVATEFULL
399  {
403 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
405  OPENMP3DLOOPBLOCK2IJK(i,j,k);
406 
407  MYFUN(assignrough_primitive_pstag(i,j,k, prim, pstag, ucons),"init.c:init_primitives","transform_primitive_vB()",0);
408 
409  }
410  }// end parallel region
411  }
412 
413 
415  //
416  // normalize density if wanted
417  //
419  // at this point densities are still standard, so just send "prim"
420  trifprintf("Normalize densities\n");
421  normalize_densities(prim);
422 
424  //
425  // Define an atmosphere if wanted
426  //
428 
429  if(DOEVOLVERHO||DOEVOLVEUU){
430  // normalized atmosphere
431  trifprintf("Add atmosphere\n");
432 
433 #pragma omp parallel private(i,j,k,initreturn,whichvel,whichcoord) OPENMPGLOBALPRIVATEFULL
434  {
438 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
440  OPENMP3DLOOPBLOCK2IJK(i,j,k);
441 
442  initreturn=init_atmosphere(&whichvel, &whichcoord,i,j,k,MAC(prim,i,j,k));
443  if(initreturn>0){
444  FAILSTATEMENT("init.c:init_primitives()", "init_atmosphere()", 1);
445  }
446  else if(initreturn==-1){
447  // then do nothing -- no atmosphere
448  }
449  else{ // initreturn==0
450  // transform from whichcoord to MCOORD
451  if (bl2met2metp2v(whichvel, whichcoord,MAC(prim,i,j,k), i,j,k) >= 1){
452  FAILSTATEMENT("init.c:init()", "bl2ks2ksp2v()", 1);
453  }
454 
455  }
456  }// end 3D LOOP
457  }// end parallel region
458  }
459 
460 
462  //
463  // Set analytics
464  //
466 
467 
468 #if(ANALYTICMEMORY)
469  // copy over initial solution as analytic solution
470  // NEEDED FOR BOUND in case uses panalytic
471  // NOTEMARK: Sasha: I also noticed that when using analytic solution, the default code behavior upon restart is to save the prims at the time of restart into panalytic array. It might be better instead to save the actual initial conditions into panalytic, which is what I do in my version of the code. I left the original default behavior unchanged.
472  copy_prim2panalytic(prim,panalytic,pstag,pstaganalytic,vpot,vpotanalytic,Bhat,Bhatanalytic);
473 #endif
474 
475 
477  //
478  // Fixup and Bound variables since some primitive quantities may have changed
479  // These may be used to define vector potential below
480  // Also setup pre_fixup() type quantities
481  //
483 
484  if(0){
485  //dump pre-fixup'ed version
486  GLOBALPOINT(pdump)=GLOBALPOINT(pglobal);
487  if (dump(9999) >= 1){
488  dualfprintf(fail_file,"unable to print dump file\n");
489  return (1);
490  }
491  }
492 
493 
494  trifprintf("Fixup #1\n");
495 #if(FIXUPAFTERINIT)
496  if(fixup(STAGEM1,prim,ucons,0)>=1) FAILSTATEMENT("init.c:init()", "fixup()", 1);
497 #endif
498 
499  if(0){
500  //dump post-fixup'ed version
501  GLOBALPOINT(pdump)=GLOBALPOINT(pglobal);
502  if (dump(99988) >= 1){
503  dualfprintf(fail_file,"unable to print dump file\n");
504  return (1);
505  }
506  }
507 
508 
509  {
510  trifprintf("Bound #1\n");
511  int finalstep=1; // modifies initial ucum-like-primitives
512  if (bound_prim(STAGEM1,finalstep,t,prim, pstag, Bhat, USEMPI) >= 1) FAILSTATEMENT("init.c:init()", "bound_prim()", 1); // t is ok here
513  }
514 
515  if(0){
516  //dump post-bound version
517  GLOBALPOINT(pdump)=GLOBALPOINT(pglobal);
518  if (dump(9998) >= 1){
519  dualfprintf(fail_file,"unable to print dump file\n");
520  return (1);
521  }
522  }
523 
524 
525  trifprintf("pre_interpolate_and_advance #1\n");
526  // now fully bounded, initialize interpolations in case interpolate using prim/pstag data
527  pre_interpolate_and_advance(prim);
528 
529 
530  // SUPERGODMARK TODO
531  trifprintf("pre_fixup #1\n");
532  if(pre_fixup(STAGEM1,prim)>=1) FAILSTATEMENT("init.c:init()", "pre_fixup()", 1);
533 
534 
535 
536 
538  //
539  // Initialize field from vector potential
540  //
542 
543 #if(1)
544  trifprintf("init_vpot #1\n");
545  init_vpot(prim,pstag,ucons,vpot,Bhat,F1,F2,F3,Atemp);
546  trifprintf("normalize_field #1\n");
547  normalize_field(prim,pstag,ucons,vpot,Bhat); // normalizes p and pstag and unew and vpot if tracked
548 #else
549  // no field
550  trifprintf("init_zero_field #1\n");
551  init_zero_field(prim,pstag,ucons,vpot,Bhat);
552 
553 #endif
554 
555 
556 
557  if(1){
558 #pragma omp parallel private(i,j,k) OPENMPGLOBALPRIVATEFULL
559  {
563 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
565  OPENMP3DLOOPBLOCK2IJK(i,j,k);
566 
567  init_postvpot(i, j, k, MAC(prim,i,j,k), MAC(pstag,i,j,k), MAC(ucons,i,j,k));
568  }
569  }// end parallel region
570  }
571 
572 
573 
574 
575 
576 #if(ANALYTICMEMORY)
577  // copy over initial solution as analytic solution
578  // NEEDED FOR BOUND in case uses panalytic
579  trifprintf("copy_prim2panalytic #1\n");
580  copy_prim2panalytic(prim,panalytic,pstag,pstaganalytic,vpot,vpotanalytic,Bhat,Bhatanalytic);
581 #endif
582 
584  //
585  // Fixup and Bound variables since some primitive quantities may have changed
586  // These may be used to define vector potential below
587  // Also setup pre_fixup() type quantities
588  //
589  //
590  // BOUND AGAIN IN CASE USING PANALYTIC TO BOUND!
591  //
593 
594  if(0){
595  //dump pre-fixup version2
596  GLOBALPOINT(pdump)=GLOBALPOINT(pglobal);
597  if (dump(9997) >= 1){
598  dualfprintf(fail_file,"unable to print dump file\n");
599  return (1);
600  }
601  }
602 
603  trifprintf("Fixup #2\n");
604 #if(FIXUPAFTERINIT)
605  if(fixup(STAGEM1,prim,ucons,0)>=1) FAILSTATEMENT("init.c:init()", "fixup()", 1);
606 #endif
607 
608  {
609  trifprintf("Bound #2\n");
610  int finalstep=1; // modifies initial ucum-like-primitives
611  if (bound_allprim(STAGEM1,finalstep,0.0,prim,pstag,ucons, USEMPI) >= 1) FAILSTATEMENT("init.c:init()", "bound_allprim()", 1);
612  }
613 
614 
615  if(0){
616  //dump post-fixup'ed version2
617  GLOBALPOINT(pdump)=GLOBALPOINT(pglobal);
618  if (dump(9996) >= 1){
619  dualfprintf(fail_file,"unable to print dump file\n");
620  return (1);
621  }
622  }
623 
624 
626  //
627  // Set EOSextras related to keeping table result consistent
628  //
630 
631  if(WHICHEOS==KAZFULL){
632  trifprintf("EOSextra\n");
633  FULLLOOP{
634  // then store pressure
635  // assume standard inversion at loc=CENT
636  GLOBALMACP0A1(EOSextraglobal,i,j,k,PGASGLOBAL)=pressure_rho0_u(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k),MACP0A1(prim,i,j,k,RHO),MACP0A1(prim,i,j,k,UU));
637  }
638  }
639 
640 
641 
642  // now fully bounded, initialize interpolations in case interpolate using prim/pstag data
643  trifprintf("pre_interpolate_and_advance #2\n");
644  pre_interpolate_and_advance(prim);
645 
646 
647  trifprintf("pre_fixup #2\n");
648  if(pre_fixup(STAGEM1,prim)>=1) FAILSTATEMENT("init.c:init()", "pre_fixup()", 1);
649 
650  return(0);
651 
652 
653 }
654 
655 
656 
657 
658 
659 
660 
661 int user1_init_vpot2field_user(SFTYPE time, int *fieldfrompotential, FTYPE (*A)[NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3],FTYPE (*prim)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*ucons)[NSTORE2][NSTORE3][NPR], FTYPE (*Bhat)[NSTORE2][NSTORE3][NPR])
662 {
663  int i,j,k,pl,pliter;
664  int toreturn;
665  extern int set_fieldfrompotential(int *fieldfrompotential);
666 
667 
668  // uses ptemparray as temporary variable
669  // use PLOOP (not PLOOPBONLY) since rho,u,etc. used for interpolation in some cases
670  copy_3dnpr_fullloop(prim,GLOBALPOINT(ptemparray));
671 
672  set_fieldfrompotential(fieldfrompotential);
673 
674  // obtain primitive magnetic field from vector potential
675  // uses ptemparray as temporary variable. Uses emf as temporary variable.
676  toreturn=vpot2field(time, A,GLOBALPOINT(ptemparray),pstag,ucons,Bhat,GLOBALPOINT(F1),GLOBALPOINT(F2),GLOBALPOINT(F3),GLOBALPOINT(emf),GLOBALPOINT(ulastglobal));
677 
678 
679  // Can override vector potential choice for some field components, like B3 in axisymmetry
680  // see init.sasha.c
681 
682  // Can override vector potential choice for some field components, like B3 in axisymmetry
683  // see init.sasha.c
684  if(fieldfrompotential[1]==1 && fieldfrompotential[2]==1 && fieldfrompotential[3]==1){
686  //
687  // copy back
688  // don't override
689  //
691  copy_3d_fieldonly_fullloop(GLOBALPOINT(ptemparray),prim);
692  }
693  else{
694  struct of_geom geomdontuse;
695  struct of_geom *ptrgeom=&geomdontuse;
696  int loc;
697  FULLLOOP{
698  PLOOPBONLY(pl){
699  if(fieldfrompotential[pl-B1+1]==1){
700  MACP0A1(prim,i,j,k,pl) = GLOBALMACP0A1(ptemparray,i,j,k,pl);
701  }
702  else{
703  if(FLUXB==FLUXCTSTAG) loc=FACE1+(B1-1);
704  else loc=CENT;
705  get_geometry(i,j,k,loc,ptrgeom);
706  if(pstag!=NULL){
707  MACP0A1(pstag,i,j,k,pl) = MACP0A1(prim,i,j,k,pl); // don't use pstag since vpot2field() overwrites pstag. Ok, since assume user only avoids vpot if constant in 1D.
708  }
709  if(ucons!=NULL){
710  MACP0A1(ucons,i,j,k,pl) = ptrgeom->EOMFUNCMAC(pl) * MACP0A1(prim,i,j,k,pl); // don't use pstag since vpot2field() overwrites pstag. Ok, since assume user only avoids vpot if constant in 1D.
711  // dualfprintf(fail_file,"i=%d pl=%d pstag=%g ucons=%g\n",i,pl,MACP0A1(pstag,i,j,k,pl),MACP0A1(ucons,i,j,k,pl));
712  }
713  if(Bhat!=NULL){
714  MACP0A1(Bhat,i,j,k,pl) = ptrgeom->EOMFUNCMAC(pl) * MACP0A1(pstag,i,j,k,pl);
715  }
716  }
717  }
718  }
719  }
720 
721  return(toreturn);
722 
723 }
724 
725 
726 
727 
728 // assumes we are fed the true densities
729 // OPENMPOPTMARK: Too user specific to worry about optimizing
730 int user1_normalize_densities(int eqline, FTYPE *parms, FTYPE (*prim)[NSTORE2][NSTORE3][NPR], FTYPE *rhomax, FTYPE *umax)
731 {
732  int i,j,k;
733  FTYPE X[NDIM],V[NDIM],r,th;
734  FTYPE rin,rhodisk;
735 
736 
737  *rhomax=SMALL;
738  *umax=SMALL;
739  rin=parms[0];
740  rhodisk=parms[1];
741 
742 
743  COMPZLOOP {
744  bl_coord_ijk_2(i, j, k, CENT, X, V);
745  r=V[1];
746  th=V[2];
747 
748  if (MACP0A1(prim,i,j,k,RHO) > *rhomax) *rhomax = MACP0A1(prim,i,j,k,RHO);
749  if(eqline){
750  if (MACP0A1(prim,i,j,k,UU) > *umax && (r > rin)) *umax = MACP0A1(prim,i,j,k,UU);
751  }
752  else{
753  if (MACP0A1(prim,i,j,k,UU) > *umax ) *umax = MACP0A1(prim,i,j,k,UU);
754  }
755  }
756 
757 
759  //
760  // Find max over all MPI procs
761  //
763  mpimax(rhomax);
764  mpimax(umax);
765  trifprintf("rhomax: %21.15g umax: %21.15g\n", *rhomax, *umax);
766 
767 
769  //
770  // Normalize densities
771  //
773 
774  COMPZLOOP{
775  MACP0A1(prim,i,j,k,RHO) *= rhodisk/(*rhomax);
776  MACP0A1(prim,i,j,k,UU) *= rhodisk/(*rhomax);
777  }
778 
779 
781  //
782  // Reset maximum u and rho as consistent with renormalization
783  //
785 
786  *umax *= rhodisk/(*rhomax);
787  *rhomax = rhodisk;
788 
789  return(0);
790 }
791 
792 
793 
794 // assumes we are fed the true densities
795 // OPENMPOPTMARK: No benefit from OpenMP due to critical region required
797 {
798  int i,j,k;
799  FTYPE X[NDIM],V[NDIM],r,th;
800 
801 
802  *rhomax=SMALL;
803  *umax=SMALL;
804 
805 
806  ZLOOP{
807  bl_coord_ijk_2(i, j, k, CENT, X, V);
808  r=V[1];
809  th=V[2];
810 
811  // dualfprintf(fail_file,"rho=%g u=%g\n",MACP0A1(prim,i,j,k,RHO),MACP0A1(prim,i,j,k,UU));
812 
813  if (MACP0A1(prim,i,j,k,RHO) > *rhomax) *rhomax = MACP0A1(prim,i,j,k,RHO);
814  if (MACP0A1(prim,i,j,k,UU) > *umax ) *umax = MACP0A1(prim,i,j,k,UU);
815  }
816 
817 
819  //
820  // Find max over all MPI procs
821  //
823  mpimax(rhomax);
824  mpimax(umax);
825 
826 
827  trifprintf("rhomax: %21.15g umax: %21.15g\n", *rhomax, *umax);
828 
829  return(0);
830 }
831 
832 
833 
834 // assumes we are fed the true densities
835 // OPENMPOPTMARK: No benefit from OpenMP due to critical region required
837 {
838  int i,j,k;
839  FTYPE X[NDIM],V[NDIM],r,th;
840 
841 
842  *rhomax=SMALL;
843  *umax=SMALL;
844  *uradmax=SMALL;
845  *utotmax=SMALL;
846  *pmax=SMALL;
847  *pradmax=SMALL;
848  *ptotmax=SMALL;
849 
850  FTYPE utot,p,prad,ptot;
851 
852  ZLOOP{
853  bl_coord_ijk_2(i, j, k, CENT, X, V);
854  r=V[1];
855  th=V[2];
856 
857  FTYPE *pr = &MACP0A1(prim,i,j,k,0);
858 
859  if (pr[RHO] > *rhomax) *rhomax = pr[RHO];
860  if (pr[UU] > *umax ) *umax = pr[UU];
861  if (pr[URAD0] > *uradmax ) *uradmax = pr[URAD0];
862  utot = pr[UU]+pr[URAD0];
863  if (utot > *utotmax ) *utotmax = utot;
864 
865  p=pressure_rho0_u_simple(i,j,k,CENT,pr[RHO],pr[UU]);
866  prad=pr[URAD0]*(4.0/3.0-1.0);
867  ptot=p+prad; // meaningful as a pressure as diagonal term in stress.
868 
869  if (p > *pmax ) *pmax = p;
870  if (prad > *pmax ) *pradmax = prad;
871  if (ptot > *ptotmax ) *ptotmax = ptot;
872  }
873 
874 
876  //
877  // Find max over all MPI procs
878  //
880  mpimax(rhomax);
881  mpimax(umax);
882  mpimax(uradmax);
883  mpimax(utotmax);
884  mpimax(pmax);
885  mpimax(pradmax);
886  mpimax(ptotmax);
887 
888 
889  trifprintf("rhomax: %21.15g umax: %21.15g uradmax: %21.15g utotmax: %21.15g pmax: %21.15g pradmax: %21.15g ptotmax: %21.15g\n", *rhomax, *umax, *uradmax, *utotmax, *pmax, *pradmax, *ptotmax);
890 
891  return(0);
892 }
893 
894 
895 
896 // get maximum b^2 and p_g and minimum of beta
897 // OPENMPOPTMARK: No benefit from OpenMP due to critical region required and too user specific
898 int user1_get_maxes(int eqslice, FTYPE *parms, FTYPE (*prim)[NSTORE2][NSTORE3][NPR], FTYPE *bsq_max, FTYPE *ptot_max, FTYPE *beta_min)
899 {
900  int i,j,k;
901  FTYPE bsq_ij,ptot_ij,beta_ij;
902  struct of_geom geomdontuse;
903  struct of_geom *ptrgeom=&geomdontuse;
904  FTYPE X[NDIM],V[NDIM];
905  FTYPE dxdxp[NDIM][NDIM];
906  FTYPE r,th;
907  int gotnormal;
908  FTYPE rin,rout,THETAEQ;
909  int loc;
910 
911 
912 
913 
914  rin=parms[0];
915  rout=parms[1];
916  THETAEQ=parms[2];
917  if(rout<=rin) rout=2.0*rin; // default (a bit model dependent -- user should really have set rout)
918  dualfprintf(fail_file,"rin=%g rout=%g THETAEQ=%g\n",rin,rout,THETAEQ);
919 
920  bsq_max[0] = SMALL;
921  ptot_max[0]= 0.;
922  beta_min[0]=VERYBIG;
923  gotnormal=0; // to check if ever was in location where wanted to normalize
924  loc=CENT;
925 
926  ZLOOP {
927  get_geometry(i, j, k, loc, ptrgeom);
928  FTYPE *pr = &MACP0A1(prim,i,j,k,0);
929 
930  bl_coord_ijk_2(i, j, k, loc, X, V);
931  r=V[1];
932  th=V[2];
933 
934  // if(0&&eqslice){
935  if(eqslice){
936 
937 
938  // FTYPE THETAEQ=0.3;
939 
940  if((r>rin&&r<rout)&&(fabs(th-M_PI*0.5)<THETAEQ)){
941  gotnormal=1;
942  if (bsq_calc(MAC(prim,i,j,k), ptrgeom, &bsq_ij) >= 1) FAILSTATEMENT("init.c:init()", "bsq_calc()", 1);
943  if (bsq_ij > bsq_max[0]) bsq_max[0] = bsq_ij;
944 
945  ptot_ij=pressure_rho0_u_simple(i,j,k,loc,MACP0A1(prim,i,j,k,RHO),MACP0A1(prim,i,j,k,UU));
946  if(EOMRADTYPE!=EOMRADNONE) ptot_ij += pr[URAD0]*(4.0/3.0-1.0);
947 
948 
949  if (ptot_ij > ptot_max[0]) ptot_max[0] = ptot_ij;
950 
951  beta_ij=ptot_ij/(bsq_ij*0.5);
952 
953  if (beta_ij < beta_min[0]) beta_min[0] = beta_ij;
954 
955  }
956  }
957  else{
958 
959  if(r>rin && r<rout){
960 
961  gotnormal=1;
962  if (bsq_calc(MAC(prim,i,j,k), ptrgeom, &bsq_ij) >= 1) FAILSTATEMENT("init.c:init()", "bsq_calc()", 1);
963  if (bsq_ij > bsq_max[0]) bsq_max[0] = bsq_ij;
964 
965  ptot_ij=pressure_rho0_u_simple(i,j,k,loc,MACP0A1(prim,i,j,k,RHO),MACP0A1(prim,i,j,k,UU));
966  if(EOMRADTYPE!=EOMRADNONE) ptot_ij += pr[URAD0]*(4.0/3.0-1.0);
967 
968  if (ptot_ij > ptot_max[0]) ptot_max[0] = ptot_ij;
969 
970  beta_ij=ptot_ij/(bsq_ij*0.5);
971 
972  if (beta_ij < beta_min[0]) beta_min[0] = beta_ij;
973  }
974  }
975  }
976 
977 
978  mpiisum(&gotnormal);
979 
980  if(gotnormal==0){
981  dualfprintf(fail_file,"Never found place to normalize field\n");
982  if(N2==1 && N3==1){
983  ZLOOP {
984  bl_coord_ijk_2(i, j, k, loc, X, V);
985  dxdxprim_ijk(i, j, k, loc, dxdxp);
986  r=V[1];
987  th=V[2];
988 
989  dualfprintf(fail_file,"i=%d j=%d k=%d V[1]=%21.15g dxdxp[1][1]*dx[1]=%21.15g dx[1]=%21.15g\n",i,j,k,V[1],dxdxp[1][1]*dx[1],dx[1]);
990  }
991  }
992  myexit(111);
993  }
994 
995  mpimax(bsq_max);
996  mpimax(ptot_max);
997  mpimin(beta_min);
998 
999 
1000  return(0);
1001 
1002 }
1003 
1004 
1005 // 0: maxes method
1006 // 1: betamin
1007 #define FIELDBETANORMMETHOD 1
1008 
1009 // assumes normal field definition
1011 {
1012  FTYPE bsq_max, norm, beta_act;
1013  FTYPE myptotmax;
1014  FTYPE betamin;
1015  int get_maxes(FTYPE (*prim)[NSTORE2][NSTORE3][NPR], FTYPE *bsq_max, FTYPE *myptotmax, FTYPE *beta_min);
1016 
1017 
1018  if(EOMTYPE==EOMFFDE||EOMTYPE==EOMFFDE2) return(0); // do nothing
1019 
1020 
1021  // get initial maximum
1022  get_maxes(prim, &bsq_max, &myptotmax, &betamin);
1023  trifprintf("initial bsq_max: %21.15g ptotmax: %21.15g betamin=%21.15g\n", bsq_max,myptotmax,betamin);
1024 
1025 #if(FIELDBETANORMMETHOD==0)
1026  // get normalization parameter
1027  beta_act = myptotmax / (0.5 * bsq_max);
1028  norm = sqrt(beta_act / beta);
1029 #elif(FIELDBETANORMMETHOD==1)
1030  beta_act = betamin;
1031  norm = sqrt(beta_act / beta);
1032 #endif
1033  trifprintf("initial beta: %21.15g (should be %21.15g) norm=%21.15g\n", beta_act,beta,norm);
1034 
1035 
1036  // not quite right since only correct static field energy, not moving field energy
1037  normalize_field_withnorm(norm, prim, pstag, ucons, vpot, Bhat);
1038 
1039  // get new maxes to check if beta is correct
1040  get_maxes(prim, &bsq_max, &myptotmax, &betamin);
1041  trifprintf("new initial bsq_max: %21.15g ptotmax: %21.15g betamin=%21.15g\n", bsq_max,myptotmax,betamin);
1042 
1043 #if(FIELDBETANORMMETHOD==0)
1044  beta_act = myptotmax / (0.5 * bsq_max);
1045 #elif(FIELDBETANORMMETHOD==1)
1046  beta_act = betamin;
1047 #endif
1048  trifprintf("final beta: %21.15g (should be %21.15g)\n", beta_act,beta);
1049 
1050 
1051  return(0);
1052 }
1053 
1054 
1055 #if(EOMTYPE==EOMGRMHD||EOMTYPE==EOMCOLDGRMHD||EOMTYPE==EOMENTROPYGRMHD)
1056 #define NORMALIZEFIELDMETHOD 0 // choice
1057 // 0 : by sigma
1058 // 1 : by b^2\sim B^2
1059 #else
1060 #define NORMALIZEFIELDMETHOD 1 // no choice
1061 #endif
1062 
1063 
1064 // assumes normal field definition for NSBH problem
1065 int user1_normalize_field_sigma(FTYPE sigma0, FTYPE bpole, FTYPE (*prim)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*ucons)[NSTORE2][NSTORE3][NPR], FTYPE (*vpot)[NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3], FTYPE (*Bhat)[NSTORE2][NSTORE3][NPR])
1066 {
1067  FTYPE sigma_pole, bsq_pole, norm;
1068  int user1_get_sigmabsq_atpole(FTYPE (*prim)[NSTORE2][NSTORE3][NPR], FTYPE *sigma_pole, FTYPE *bsq_pole);
1069 
1070  // get initial maximum
1071  user1_get_sigmabsq_atpole(prim, &sigma_pole,&bsq_pole);
1072  trifprintf("initial sigma_pole: %21.15g bsq_pole: %21.15g\n", sigma_pole,bsq_pole);
1073 
1074  if(NORMALIZEFIELDMETHOD==0){
1075  // get normalization parameter (uses final sigma to set field strength)
1076  norm = sqrt(sigma0/sigma_pole);
1077  trifprintf("initial sigma_pole: %21.15g (should be %21.15g) norm=%21.15g\n", sigma_pole,sigma0,norm);
1078  }
1079  else if(NORMALIZEFIELDMETHOD==1){
1080  // get normalization parameter (uses final sigma to set field strength)
1081  norm = sqrt(bpole*bpole/bsq_pole);
1082  trifprintf("initial bsq_pole: %21.15g (should be %21.15g) norm=%21.15g\n", bsq_pole,bpole*bpole,norm);
1083  }
1084 
1085 
1086  // not quite right since only correct static field energy, not moving field energy
1087  normalize_field_withnorm(norm, prim, pstag, ucons, vpot, Bhat);
1088 
1089 
1090  // get new maxes to check if normalization is correct
1091  user1_get_sigmabsq_atpole(prim, &sigma_pole,&bsq_pole);
1092  trifprintf("new initial sigma_pole: %21.15g bsq_pole: %21.15g\n", sigma_pole,bsq_pole);
1093 
1094 
1095  if(NORMALIZEFIELDMETHOD==0){
1096  trifprintf("initial sigma_pole: %21.15g (should be %21.15g) norm=%21.15g\n", sigma_pole,sigma0,norm);
1097  }
1098  else if(NORMALIZEFIELDMETHOD==1){
1099  trifprintf("initial bsq_pole: %21.15g (should be %21.15g) norm=%21.15g\n", bsq_pole,bpole*bpole,norm);
1100  }
1101 
1102 
1103 
1104  // for use when calling init_vpot_user later
1105  // if called this twice, need both renormalizations as multiplied by each other
1106  normglobal*=norm;
1107 
1108 
1109  return(0);
1110 }
1111 
1112 
1113 // normalize densities after field has been normalized
1115 {
1116  int i,j,k;
1117  struct of_geom geomdontuse;
1118  struct of_geom *ptrgeom=&geomdontuse;
1119  FTYPE X[NDIM],V[NDIM];
1120  FTYPE dxdxp[NDIM][NDIM];
1121  FTYPE r,th;
1122  int loc;
1123 
1124 
1125 
1126 
1127  loc=CENT;
1128  FTYPE R;
1129 
1130  FTYPE bsq_ij,sigma_ij;
1131  FTYPE sigmahot_ij;
1132  FTYPE uorho;
1133 
1134 
1135  // LOOP
1136  FULLLOOP{
1137  get_geometry(i, j, k, loc, ptrgeom);
1138 
1139  bl_coord_ijk_2(i, j, k, loc, X, V);
1140  r=V[1];
1141  th=V[2];
1142  R=r*sin(th);
1143 
1144  if(1){
1145 
1146  if (bsq_calc(MAC(prim,i,j,k), ptrgeom, &bsq_ij) >= 1) FAILSTATEMENT("init.c:init()", "bsq_calc()", 1);
1147 
1148  // \sigma \sim \mu \sim b^2/(2\rho_0)
1149  sigma_ij=bsq_ij/(2.0*fabs(MACP0A1(prim,i,j,k,RHO)+SMALL));
1150 
1151  if(sigma_ij>BSQORHOLIMIT*0.5){
1152  dualfprintf(fail_file,"RENORMDEN1: %d %d %d %21.15g %21.15g\n",i,j,k,sigma_ij,MACP0A1(prim,i,j,k,RHO));
1153  MACP0A1(prim,i,j,k,RHO)*=sigma_ij/(BSQORHOLIMIT*0.5);
1154  }
1155 
1156  // \sigma \sim \mu \sim b^2/(2u)
1157  sigmahot_ij=bsq_ij/(2.0*fabs(MACP0A1(prim,i,j,k,UU))+SMALL);
1158 
1159  if(sigmahot_ij>BSQOULIMIT*0.5){
1160  dualfprintf(fail_file,"RENORMDEN2: %d %d %d %21.15g %21.15g\n",i,j,k,sigmahot_ij,MACP0A1(prim,i,j,k,UU));
1161  MACP0A1(prim,i,j,k,UU)*=sigmahot_ij/(BSQOULIMIT*0.5);
1162  }
1163 
1164  // u/\rho_0
1165  uorho=MACP0A1(prim,i,j,k,UU)/(fabs(MACP0A1(prim,i,j,k,RHO))+SMALL);
1166 
1167  if(uorho>UORHOLIMIT){
1168  dualfprintf(fail_file,"RENORMDEN3: %d %d %d %21.15g %21.15g %21.15g\n",i,j,k,uorho,MACP0A1(prim,i,j,k,RHO),MACP0A1(prim,i,j,k,UU));
1169  MACP0A1(prim,i,j,k,RHO)*=uorho/UORHOLIMIT;
1170  }
1171 
1172  // old, stupid, maybe:
1173  // MACP0A1(prim,i,j,k,RHO)*=normglobal*normglobal;
1174  // MACP0A1(prim,i,j,k,UU)*=normglobal*normglobal;
1175 
1176  }
1177  }
1178 
1179  return(0);
1180 
1181 
1182 }
1183 
1184 
1185 
1186 
1187 
1188 
1189 // get \sigma at pole of NS
1190 int user1_get_sigmabsq_atpole(FTYPE (*prim)[NSTORE2][NSTORE3][NPR], FTYPE *sigma_pole, FTYPE *bsq_pole)
1191 {
1192  int i,j,k;
1193  FTYPE bsq_ij,sigma_ij;
1194  struct of_geom geomdontuse;
1195  struct of_geom *ptrgeom=&geomdontuse;
1196  FTYPE X[NDIM],V[NDIM];
1197  FTYPE dxdxp[NDIM][NDIM];
1198  FTYPE r,th;
1199  int gotnormal;
1200  FTYPE rin;
1201  int loc;
1202 
1203 
1204 
1205 
1206  sigma_pole[0] = SMALL;
1207  bsq_pole[0] = SMALL;
1208  gotnormal=0; // to check if ever was in location where wanted to normalize
1209  loc=CENT;
1210 
1211 
1212  FTYPE R;
1213 
1214 
1215  // LOOP
1216  ZLOOP {
1217  get_geometry(i, j, k, loc, ptrgeom);
1218 
1219  bl_coord_ijk_2(i, j, k, loc, X, V);
1220  r=V[1];
1221  th=V[2];
1222  R=r*sin(th);
1223 
1224 
1225  if(1){
1226 
1227  gotnormal=1;
1228  if (bsq_calc(MAC(prim,i,j,k), ptrgeom, &bsq_ij) >= 1) FAILSTATEMENT("init.c:init()", "bsq_calc()", 1);
1229 
1230  // \sigma \sim \mu \sim b^2/(2\rho_0)
1231  sigma_ij=bsq_ij/(2.0*fabs(MACP0A1(prim,i,j,k,RHO))+SMALL);
1232 
1233  // dualfprintf(fail_file,"SIGMA: %d %d %d : sigma_ij=%21.15g\n",i,j,k,sigma_ij);
1234 
1235  // if multiple positions found, keep getting maximum
1236  if (sigma_ij > sigma_pole[0]) sigma_pole[0] = sigma_ij;
1237  if (bsq_ij > bsq_pole[0]) bsq_pole[0] = bsq_ij;
1238  }
1239  }
1240 
1241 
1242  mpiisum(&gotnormal);
1243 
1244  if(gotnormal==0){
1245  dualfprintf(fail_file,"Never found place to normalize field for NS\n");
1246  if(N2==1 && N3==1){
1247  ZLOOP {
1248  bl_coord_ijk_2(i, j, k, loc, X, V);
1249  dxdxprim_ijk(i, j, k, loc, dxdxp);
1250  r=V[1];
1251  th=V[2];
1252 
1253  dualfprintf(fail_file,"i=%d j=%d k=%d V[1]=%21.15g dxdxp[1][1]*dx[1]=%21.15g dx[1]=%21.15g\n",i,j,k,V[1],dxdxp[1][1]*dx[1],dx[1]);
1254  }
1255  }
1256  myexit(111);
1257  }
1258 
1259  mpimax(sigma_pole);
1260  mpimax(bsq_pole);
1261 
1262  return(0);
1263 
1264 }
1265 
1266 
1267 
1268 
1269 
1270 // UUMIN/RHOMIN used for atmosphere
1271 
1272 // for each WHICHVEL possibility, set atmosphere state for any coordinate system
1273 // which=0 : initial condition
1274 // which=1 : evolution condition (might also include a specific angular momentum or whatever)
1275 // which==1 assumes pr set to something locally reasonable, and we adjust to that slowly
1276 
1277 #define TAUADJUSTATM (10.0) // timescale for boundary to adjust to using preset inflow
1278 int user1_set_atmosphere(int atmospheretype, int whichcond, int whichvel, struct of_geom *ptrgeom, FTYPE *pr)
1279 {
1280  FTYPE rho,u,ur,uh,up;
1281  FTYPE X[NDIM],V[NDIM];
1282  FTYPE r,th;
1283  FTYPE prlocal[NPR];
1284  int pl,pliter;
1285 
1286  // Bondi like initial atmosphere
1287  // rho = RHOMIN * 1.E-14;
1288  // u = UUMIN * 1.E-14;
1289  bl_coord_ijk_2(ptrgeom->i, ptrgeom->j, ptrgeom->k, ptrgeom->p, X, V);
1290  r=V[1];
1291  th=V[2];
1292 
1293  // default
1294  PLOOP(pliter,pl) prlocal[pl]=pr[pl];
1295 
1296  if(DOEVOLVERHO){
1297  // Bondi-like atmosphere
1298  if(rescaletype==4){
1299  if(atmospheretype==1){
1300  // couple rescaletype to atmosphere type
1301  prlocal[RHO] = RHOMIN*pow(r,-2.0);
1302  }
1303  else if(atmospheretype==2){
1304  // couple rescaletype to atmosphere type
1305  if(r>40.0) prlocal[RHO] = RHOMIN*pow(r,-2.0);
1306  else prlocal[RHO] = RHOMIN*pow(40.0,-2.0);
1307  }
1308  }
1309  else{
1310  prlocal[RHO] = RHOMIN*pow(r,-1.5);
1311  }
1312  }
1313  else{
1314  prlocal[RHO] = 0;
1315  }
1316 
1317 
1318  if(DOEVOLVEUU){
1319  // Bondi-like atmosphere
1320  prlocal[UU] = UUMIN*pow(r,-2.5);
1321  }
1322  else{
1323  prlocal[UU] = 0;
1324  }
1325 
1326 
1327  // bl-normal observer (4-vel components)
1328  set_zamo_velocity(whichvel,ptrgeom,prlocal);
1329 
1330  if(whichcond==1){
1331  if(100.0*dt>TAUADJUSTATM){
1332  dualfprintf(fail_file,"dt=%21.15g and TAUADJUSTATM=%21.15g\n",dt,TAUADJUSTATM);
1333  myexit(1);
1334  }
1335  // TAUADJUSTATM must be >> dt always in order for this to make sense (i.e. critical damping to fixed solution)
1336  PLOOP(pliter,pl) pr[pl] = pr[pl]+(prlocal[pl]-pr[pl])*dt/TAUADJUSTATM;
1337  }
1338  else if(whichcond==0){
1339  PLOOP(pliter,pl) pr[pl] = prlocal[pl];
1340  // very specific
1341  // always outflow field
1342  // pr[B1] = pr[B2] = pr[B3] = 0;
1343  }
1344  else if(whichcond==-1){
1345  // t=0, just sets as "floor"
1346  PLOOP(pliter,pl) pr[pl] = prlocal[pl];
1347  pr[B1] = pr[B2] = pr[B3] = 0;
1348  }
1349 
1350 
1351  return(0);
1352 
1353 }
1354 
1355 
1356