HARM
harm and utilities
 All Data Structures Files Functions Variables Typedefs Macros Pages
coord.c
Go to the documentation of this file.
1 
2 #include "decs.h"
3 
27 static void blcoord_singfixes(FTYPE *X, FTYPE *V);
28 
29 
31 //
32 // These static variables can only be set in set_coord_parms() type functions, not bl_coord() or dxdxp(). if need to set inside bl_coord() or dxdxp(), then move variable there!
33 //
35 // for defcoord==COMPLEX1TH
36 static FTYPE der0=9;
37 //static FTYPE Ri=8.0; // too unresolved for 256x128
38 static FTYPE Ri=20.0;
39 
40 // for defcoord==COMPLEX2TH
41 static FTYPE x2trans;
43 
44 // for defcoord==JET1COORDS
46 static FTYPE npow;
47 
48 // for defcoord=JET2COORDS
50 
51 // for defcoord=JET3COORDS
53 
54 // for SJETCOORDS
55 static FTYPE fracphi;
56 static FTYPE npow2;
57 static FTYPE cpow2;
58 static FTYPE rbr;
59 static FTYPE x1br;
60 static FTYPE fracdisk;
61 static FTYPE fracjet;
62 static FTYPE rsjet;
63 static FTYPE r0grid;
64 static FTYPE r0jet;
65 static FTYPE rjetend;
66 static FTYPE r0disk;
67 static FTYPE rdiskend;
68 static FTYPE jetnu;
69 static FTYPE x10;
70 static FTYPE x20;
71 #define USESJETLOGHOVERR 1
72 #if(USESJETLOGHOVERR)
73 static FTYPE torusrmax; // was extern and original located in init.sashatorus.c, but should be inverted as now is so extern is in init.sashatorus.c.
74 #endif
76 
77 
78 
79 // for defcoord=JET6COORDS
81 static FTYPE cpow3;
82 
83 // for defcoord=BPTHIN1
85 
86 // for defcoord=PULSARCOORDS
88 
89 // for defcoord=JET4COORDS
90 static FTYPE rs,r0;
91 
92 // UNI2LOG similar to LOGSINTH with new features and simpler startx/dx and grid growth factor
93 static int Nstar;
95 
96 // for defcoord=JET5COORDS
98 static FTYPE ii0;
99 
100 // for defcoord=SJETCOORDS
101 static void vofx_sjetcoords( FTYPE *X, FTYPE *V ); //original coordinates
102 static void vofx_cylindrified( FTYPE *Xin, void (*vofx)(FTYPE*, FTYPE*), FTYPE *Vout ); //coordinate "cylindrifier"
103 
104 // for defcoord=JET6COORDSTHIN
106 
107 
108 
110 void set_coord_parms(int defcoordlocal)
111 {
112 
113  set_coord_parms_nodeps(defcoordlocal);
114  set_coord_parms_deps(defcoordlocal);
115 
116 
117 }
118 
119 
120 
124 void set_coord_parms_nodeps(int defcoordlocal)
125 {
126 
127 
128 #if(USEOPENMP)
129  if(omp_in_parallel()){
130  dualfprintf(fail_file,"set_coord_parms_nodeps() called in parallel region\n");
131  myexit(784653446);
132  }
133 #endif
134 
135 
136 
137  // assumes R0, Rin, Rout, and hslope are so general that are set in init.c
138  if (defcoordlocal == USERCOORD) {
139  extern void set_coord_parms_nodeps_user(int defcoordlocal);
140  set_coord_parms_nodeps_user(defcoordlocal);
141  }
142  else if (defcoordlocal == LOGRSINTH) {
143  }
144  else if (defcoordlocal == REBECCAGRID) {
145  }
146  else if (defcoordlocal == COMPLEX0TH) {
147  }
148  else if(defcoordlocal == UNIRSINTH || defcoordlocal == UNIRSINTH2){
149  }
150  else if (defcoordlocal == EQMIRROR) {
151  }
152  else if(defcoordlocal == COMPLEX1TH) {
153  }
154  else if(defcoordlocal == COMPLEX2TH) {
155  x2trans=0.1; // user settable, must be same as below in dxdxp
156  }
157  else if (defcoordlocal == LOGRUNITH) { // uniform theta and log in radius
158  }
159  else if (defcoordlocal == JET1COORDS) {
160  // optimal is npow=10 R0=-3
161  npow=1.0;
162  //R0=0.0;
163 
164  // must be same as in dxdxp()
165  hf=2.0-0.22;
166  rh0=40.0;
167 
168  }
169  else if (defcoordlocal == JET2COORDS) {
170  npow=1.0;
171 
172  // must be same as in dxdxp()
173  if(1){
174  r1jet=16.0;
175  njet=0.3;
176  rpjet=0.9;
177  }
178  else{
179  r1jet=9.0;
180  njet=0.3;
181  rpjet=.9;
182  }
183  }
184  else if (defcoordlocal == JET3COORDS) {
185  npow=1.0;
186 
187  // must be same as in dxdxp()
188  if(0){ // first attempt
189  r1jet=2.8;
190  njet=0.3;
191  r0jet=7.0;
192  rsjet=21.0;
193  Qjet=1.7;
194  }
195  else if(0){ // chosen to resolve disk then resolve jet
196  r1jet=2.8;
197  njet=0.3;
198  r0jet=20.0;
199  rsjet=80.0;
200  Qjet=1.8;
201  }
202  else if(1){
203  r1jet=2.8;
204  njet=0.3;
205  r0jet=20.0;
206  rsjet=80.0;
207  Qjet=1.3; // chosen to help keep jet resolved even within disk region
208  }
209  }
210  else if (defcoordlocal == SJETCOORDS) {
211  }
212  else if (defcoordlocal == JET6COORDS) {
213 
214  // see jet3coords_checknew.nb
215  npow=1.0;
216 
218  // RADIAL GRID SETUP
220  npow=1.0; //don't change it, essentially equivalent to changing cpow2
221 
222  //radial hyperexponential grid
223 
224  //power exponent
225  npow2=6.0; // WALD: 6.0->4.0
226 
227  cpow2=1.0; //exponent prefactor (the larger it is, the more hyperexponentiation is)
228  // cpow3=0.01;
229  cpow3=1.0;
230  //radius at which hyperexponentiation kicks in
231  // rbr = 1E3;
232  // rbr = 5E2; // WALD 5E2->5E7 // SUPER-EDD: 2E3
233  rbr = 2E3; // SUPERMADNEW
234 
235 
236  // must be same as in dxdxp()
237  // GODMARK: Note njet here is overwritten by njet later, but could have been different values if setup variable names differently.
238  if(0){ // first attempt
239  r1jet=2.8;
240  njet=0.3;
241  r0jet=7.0;
242  rsjet=21.0;
243  Qjet=1.7;
244  }
245  else if(0){ // chosen to resolve disk then resolve jet
246  r1jet=2.8;
247  njet=0.3;
248  r0jet=20.0;
249  rsjet=80.0;
250  Qjet=1.8;
251  }
252  else if(0){
253  r1jet=2.8;
254  njet=0.3;
255  r0jet=15.0;
256  rsjet=40.0;
257  Qjet=1.3; // chosen to help keep jet resolved even within disk region
258  // Qjet=1.7; // chosen to help keep jet resolved even within disk region
259  }
260  else if(1){ // SUPERMADNEW
261  r1jet=30.0;
262  njet=0.7;
263  r0jet=30.0;
264  rsjet=40.0;
265  Qjet=1.6;
266  }
267 
268  // for switches from normal theta to ramesh theta
269  if(0){
270  rs=40.0; // shift
271  r0=20.0; // divisor
272  r0jet3=20.0; // divisor
273  rsjet3=0.0; // subtractor
274  }
275  else{// SUPERMADNEW
276  rs=40.0; // shift
277  r0=40.0; // divisor
278  r0jet3=40.0; // divisor
279  rsjet3=0.0; // subtractor
280  }
281 
282  // for theta1
283  // hslope=0.3 ; // resolve inner-radial region near equator
284 
285  // for theta2
286  //h0=0.3; // inner-radial "hslope" for theta2
287  h0=0.2; // inner-radial "hslope" for theta2
288  //h0=0.1; // inner-radial "hslope" for theta2 // for thinner disks, change this.
289  // GODMARK: Note that this overwrites above njet!
290  // power \theta_j \propto r^{-njet}
291  if(0){
292  njet=1.0; // WALD: 1.0->0.0
293  }
294  else{//SUPERMADNEW
295  // no change
296  }
297 
298 
299  // see fix_3dpoledtissue.nb
300  if(0){
301 #if(0)
302  ntheta=21.0;
303  htheta=0.15;
304  rsjet2=5.0;
305  r0jet2=2.0;
306 #else
307  ntheta=5.0;
308  htheta=0.15;
309  rsjet2=5.0;
310  r0jet2=2.0;
311 #endif
312  }
313  else{ // SUPERMADNEW
314  ntheta=5.0;
315  if(a<0.4){
316  htheta=0.15;
317  rsjet2=5.0;
318  r0jet2=2.0;
319  }
320  else{
321  htheta=0.15;
322  rsjet2=8.0;
323  r0jet2=3.0;
324  }
325  }
326  }
327  else if (defcoordlocal == JET6COORDSTHIN) {
328 
329  // see jet3coords_checknew.nb
330  th_npow=1.0;
331 
333  // RADIAL GRID SETUP
335  th_npow=1.0; //don't change it, essentially equivalent to changing cpow2
336 
337  //radial hyperexponential grid
338  // npow2=4.0; //power exponent
339  th_npow2=4.0; //power exponent
340  th_cpow2=1.0; //exponent prefactor (the larger it is, the more hyperexponentiation is)
341  // rbr = 1E3; //radius at which hyperexponentiation kicks in
342  th_rbr = 1E2; //radius at which hyperexponentiation kicks in
343 
344 
345 
346  // must be same as in dxdxp()
347  // GODMARK: Note njet here is overwritten by njet later, but could have been different values if setup variable names differently.
348  if(0){ // first attempt
349  th_r1jet=2.8;
350  th_njet=0.3;
351  th_r0jet=7.0;
352  th_rsjet=21.0;
353  th_Qjet=1.7;
354  }
355  else if(0){ // chosen to resolve disk then resolve jet
356  th_r1jet=2.8;
357  th_njet=0.3;
358  th_r0jet=20.0;
359  th_rsjet=80.0;
360  th_Qjet=1.8;
361  }
362  else if(1){
363  th_r1jet=2.8;
364  th_njet=0.3;
365  th_r0jet=15.0;
366  th_rsjet=40.0;
367  th_Qjet=2.0-0.05; // chosen to help keep jet resolved even within disk region
368  }
369 
370  // for switches from normal theta to ramesh theta
371  th_rs=60.0; // shift
372  th_r0=20.0; // divisor
373 
374  // for theta1
375  // hslope=0.3 ; // resolve inner-radial region near equator
376  th_r0jet3=20.0; // divisor
377  th_rsjet3=0.0; // subtractor
378 
379  // for theta2
380  th_h0=0.05; // inner-radial "hslope" for theta2
381  //h0=0.1; // inner-radial "hslope" for theta2 // for thinner disks, change this.
382  // GODMARK: Note that this overwrites above njet!
383  th_njet=0.0; // power \theta_j \propto r^{-njet}
384 
385 
386  // see fix_3dpoledtissue.nb
387 #if(0)
388  th_ntheta=21.0;
389  th_htheta=0.15;
390  th_rsjet2=5.0;
391  th_r0jet2=2.0;
392 #else
393  th_ntheta=5.0;
394  th_htheta=0.02;
395  th_rsjet2=5.0;
396  th_r0jet2=2.0;
397 #endif
398 
399  }
400  else if (defcoordlocal == BPTHIN1) {
401 
402  // see jet3coords_checknew.nb
403  bp_npow=1.0;
404 
406  // RADIAL GRID SETUP
408  bp_npow=1.0; //don't change it, essentially equivalent to changing cpow2
409 
410  //radial hyperexponential grid
411  // npow2=4.0; //power exponent
412  bp_npow2=5.0; //MAVARANOTE must be odd now unless I add a sign explicitly to power component this contributes to sum in exponent //10.0; //5.0; // 10.0; // MARKNOTE set to 10.0 before using BP values //power exponent
413  bp_cpow2=1.0; //exponent prefactor (the larger it is, the more hyperexponentiation is)
414  // rbr = 1E3; //radius at which hyperexponentiation kicks in
415  bp_rbr = 200.0; //radius at which hyperexponentiation kicks in
416 
417 
418 
419  // must be same as in dxdxp()
420  // GODMARK: Note njet here is overwritten by njet later, but could have been different values if setup variable names differently.
421  if(0){ // first attempt
422  bp_r1jet=2.8;
423  bp_njet1=0.3;
424  bp_r0jet=7.0;
425  bp_rsjet=21.0;
426  bp_Qjet=1.7;
427  }
428  else if(0){ // chosen to resolve disk then resolve jet
429  bp_r1jet=2.8;
430  bp_njet1=0.3;
431  bp_r0jet=20.0;
432  bp_rsjet=80.0;
433  bp_Qjet=1.8;
434  }
435  else if(1){
436  bp_r1jet=2.8;
437  bp_njet1=0.1; // MARKNOTE set to 0.3 before using BP values
438  bp_r0jet=35.0;
439  bp_rsjet=30.0;
440  bp_Qjet=1.9;//-hslope; // chosen to help keep jet resolved even within disk region
441  }
442 
443  // for switches from normal theta to ramesh theta
444  bp_rs=200.0; // shift
445  bp_r0=60.0; // divisor
446 
447  // for switches from innermost region of disk (inside horizon) to regular disk to increase timestep set by smallest vertical cell size
448  bp_rsinner=2.0;//5.6;//4.0*Rin; //MAVARACHANGE changed from 4. and added the Rin so that the ratio bp_rsinner/r doesn't grow too large or too fast. maybe make that ratio **.5 to be even safer?
449  bp_r0inner=1.33; //maybe 1.0 is too quick? not really same problem as outer radii I suppose since it just flattens off;
450 
451  // for theta1
452  // hslope=0.3 ; // resolve inner-radial region near equator
453  bp_r0jet3=200.0; // divisor
454  bp_rsjet3=0.0; //MAVARANOTE0.0; // subtractor
455 
456  // for theta2
457  bp_h0=0.1; // inner-radial "hslope" for theta2
458  // GODMARK: Note that this overwrites above njet!
459  bp_njet=0.5; // MARKNOTE set to 1.0 before using BP values // power \theta_j \propto r^{-njet}
460 
461 
462  // see fix_3dpoledtissue.nb
463 #if(0)//HIGHRES // MAVARACHANGE I choose this because bp_ntheta 5 is less than the 0 used for the thin regime for the bp study. so, 5 note extreme enough.
464  bp_ntheta=21.0; //13.0; // MAVARANOTE only use 21 for high res, use 15 for mid-res, non for low-res
465  bp_htheta=0.45; // changed from .15 to be in line with my own additions for theta-flaring
466  bp_rsjet2=5.0;
467  bp_r0jet2=2.0;
468 #endif
469 #if(1) //MIDRES note that lowres doesn't use polefix code
470  bp_ntheta=15.0;
471  bp_htheta=0.15;
472  bp_rsjet2=5.0;
473  bp_r0jet2=2.0;
474 #endif
475 
476 
477  }
478  else if (defcoordlocal == JET5COORDS) {
479  // exp grid merged with exp-exp grid
480  // parameters solved using hyperexp_gridnew.nb
481  // Depends upon Rin, Rout, Rj, totalsize[1], and for below we used Rin=1.2, Rout=10^(10), Rj=200, TS1=256, and ii0,CC,Rj for radial arctan
482  // Rj probably doesn't have to be the same thing, but for now it is since this is where grid changes alot and after which much lower resolution
483 
484 #define JET5TOTALSIZE (256)
485 #define JET5RIN (1.2)
486 #define JET5ROUT (1.0E10)
487 
488  // checks
489  if(totalsize[1]!=JET5TOTALSIZE){
490  dualfprintf(fail_file,"Current version of JET5COORDS requires totalsize[1]=256\n");
491  myexit(348766346);
492  }
493 
494  // probably don't need to set Rout, but should in case user expects it
495  Rin=JET5RIN;
496  Rout=JET5ROUT;
497 
498  AAAA=1999999.0/10000000.0; // 0.1999999
499  R0=AAAA; // effectively R0 is AAAA
500 
501  AAA=0.0413459589685779052930351140071389811117796472908765122327766247871075306910922595355681060060416677474341974954736231119642058094;
502  // \
503  // 4691814961939384683077670140242359180355488020296128748293771170061841869426340268505040612342717691948841149166838622798123171255523798596 \
504  // 5818680547438536476798449141070248313113472199351567812172169767872353912078416440520778774394376979127646837398673038048093220394452697865 \
505  // 6270959185899435937659309684785579314134506823471357528404980034204759236451791458247221099942310718563615360919275492961171913096250029921 \
506  // 4602829374292931981963109018352727784709700476977587800651816760158953266217495724111120779750291873137970716049214552447910902507302350084 \
507  // 8366635098055440220680071046750709751515603946356328254368704921793804765397498748680467740257796496333857261456594221499641719912265168350 \
508  // 4446757128527854665947791196023009608509876847107243924551220166086198337782848685465542023953471925358173682394567187686793903610577481426 \
509  // 443229809938992518536215813767712488;
510 
511  BBB=-11.730265173318042629015657514515818843547237290015385234914265620733433049284290050282184485;
512  // \
513  // 2224409622873658975481691490225985175297668826368377571878745806585146061321107420949292473465725043868512923396688827607703073903863397993 \
514  // 2646469619777851403629789176127509226495862609935541778298333029485043643870849780090683673135501928153917249217151527805740858293313649525 \
515  // 1577278440925240711864457756461606512526439401436022717818816632223921127138564528631741386676062985954517161211597241100034689634177608896 \
516  // 2609005653930210512763437351860547338180817425783109360814416873897105930531521949202423966791692201348394578245024979983828552773565452313 \
517  // 9427391374740569005171185204456464084827678985364372511780199067938494425840793867427758167352923180341529476553568176436448946131066359190 \
518  // 5940692681151957860911707070494249851557079085990630079038126862565401104450140890585318688339870170091825436768403083368348398427545899255 \
519  // 91796942327692774760083202686018064712337746785361430187509415618384926325;
520 
521  DDD=0.055717934049496306640561701541245682756775321774122925900528950779091605796182691888079948813285317249415181430716632182425357598150;
522  // \
523  // 9878315509631578902141939586183299923885176395546296181175926730413185041822815279504848229461737912619728960820136753407636343528158363579 \
524  // 3015197668283754748946354820375719585870499599501931419253237151291548191762172574322092394412311930543039905230389647665970462514296542459 \
525  // 6284119291308204987329361603064178657563059514526318343174490238136571828705510375083642956288576409110703492926390263521348433706396587719 \
526  // 4076567127699214794076208495287633220730415894184618889390695112123895752908866508866230483057346798669374527001159485781544411226064994838 \
527  // 9334249843823760573294461519240571810219944708047592001849464422681300782954876398308748055099942704435601529920984600254710048152168797114 \
528  // 1500470907761667436213106445853175905130588447192393215135706743963572902579082652204804896110286228839660989062139576983695311500579346405 \
529  // 67924814417848136324354859648264319;
530 
531  // control radial arctan
532  ii0=(FTYPE)(totalsize[1])*0.5;
533  CCCC=5.0;
534  Rj=200.0;
535 
536 
537 
538  // control \theta's arctan
539  r1jet=2.8;
540  njet=0.3;
541  r0jet=20.0;
542  rsjet=80.0;
543  Qjet=1.3; // chosen to help keep jet resolved even within disk region
544 
545  }
546  else if (defcoordlocal == PULSARCOORDS) {
547 
548  if(0){// pulsar in force free
549  // pulsar_grid.nb for theta part and for the radial part:
550  // see pulsar_gridnew.nb
551  // for Rout=10^6 and R0=0.786*Rin Rin=4.84, npow=10 gives same dr/r as npow=1 R0=0.9*Rin at r=Rin
552  npow=1.0;
553 
554  // must be same as in dxdxp()
555  r0jet=5.0; // spread in radius over which hslope changes
556  rsjet=18.0; // location of current sheet beginning for NS pulsar
557  }
558  else if(1){ // NS-pulsar in GRMHD
559  npow=10.0;
560  r0jet=5.0; // spread in radius over which hslope changes
561  rsjet=15.0; // location of current sheet beginning for NS pulsar
562  }
563 
564  }
565  else if (defcoordlocal == UNIFORMCOORDS) {
566  //uniform grid for Cartesian coordinates
567  }
568  else if (defcoordlocal == BILOGCYLCOORDS) {
569  npow=10.0; // exponential rate
570  }
571  else if (defcoordlocal == RAMESHCOORDS || defcoordlocal == RAMESHCOORDS_HALFDISK) {
572  // myhslope=pow( (*r-rsjet)/r0jet , njet);
573  npow=10.0;
574  //npow=3.0;
575 
576  r0jet=2.0; // divisor
577  njet=0.34; // power \theta_j \propto r^{-njet}
578  //njet=1.0;
579  rsjet=0.5; // subtractor
580  }
581  else if (defcoordlocal == JET4COORDS ) {
582  // see net_jet_grid.nb
583  // for small Rout, should use R0~0 (i.e. instead use R0~-3) or hslope>1
584 
585 
586  // this coordinate system uses: R0 and npow for radius , hslope for theta1 , rsjet and r0 for switch and switchi , h0, rs, r0, njet for theta2 (as in JET3COORDS)
587 
588  // npow, R0, rs, r0, hslope, h0, r0jet, rsjet, njet
589 
590  // for radial grid
591  npow=1.0;
592  // npow=10.0;
593  //npow=3.0;
594  R0 = -3.0;
595 
596  // for switches
597  rs=15.0;
598  r0=25.0;
599 
600  // for theta1
601  hslope=0.3 ; // resolve inner-radial region near equator
602  // below 2 not used right now
603  r0jet=15.0; // divisor
604  rsjet=0.0; // subtractor
605 
606  // for theta2
607  njet=0.34; // power \theta_j \propto r^{-njet}
608  }
609  else if (defcoordlocal == UNI2LOG) {
610 
611  if(1){
612  Nstar = 20; // # of cells between Rin and Rstar (probably Rin=0)
613  Afactor = 1000.0; // roughly Rout/Rstar
614  }
615  else{
616  // GODMARK
617  Nstar = 0;
618  Afactor = 1.01;
619  }
620 
621  }
622  else{
623  dualfprintf(fail_file,"Shouldn't reach end of set_coord_parms: You set defcoordlocal=%d\n",defcoordlocal);
624  myexit(1);
625  }
626 
627 }
628 
629 
631 void set_coord_parms_deps(int defcoordlocal)
632 {
633 
634 #if(USEOPENMP)
635  if(omp_in_parallel()){
636  dualfprintf(fail_file,"set_coord_parms_deps() called in parallel region\n");
637  myexit(784653446);
638  }
639 #endif
640 
641  // assumes R0, Rin, Rout, and hslope are so general that are set in init.c
642  if (defcoordlocal == USERCOORD) {
643  extern void set_coord_parms_deps_user(int defcoordlocal);
644  set_coord_parms_deps_user(defcoordlocal);
645  }
646  else if (defcoordlocal == LOGRSINTH) {
647  }
648  else if (defcoordlocal == REBECCAGRID) {
649  }
650  else if (defcoordlocal == COMPLEX0TH) {
651  }
652  else if(defcoordlocal == UNIRSINTH || defcoordlocal == UNIRSINTH2){
653  }
654  else if (defcoordlocal == EQMIRROR) {
655  }
656  else if(defcoordlocal == COMPLEX1TH) {
657  }
658  else if(defcoordlocal == COMPLEX2TH) {
659  thetatores=2.5*h_over_r;
660 
661  // fixed coefficients
662  m2=(3.*(-2.*thetatores + M_PI))/(2.*x2trans) + (4.*thetatores)/(-1. + 2.*x2trans);
663  d2=(2.*thetatores - M_PI + 2.*M_PI*x2trans)/(-2.*pow(x2trans,3.) + 4.*pow(x2trans,4.));
664  c2=(6.*thetatores - 3.*M_PI + 6.*M_PI*x2trans)/(2.*pow(x2trans,2.) - 4.*pow(x2trans, 3.));
665  m3=(2.*thetatores)/(1. - 2.*x2trans);
666  b3=M_PI/2. + thetatores/(-1. + 2.*x2trans);
667  }
668  else if (defcoordlocal == LOGRUNITH) { // uniform theta and log in radius
669  }
670  else if (defcoordlocal == JET1COORDS) {
671  h0=hslope;
672  myrout=Rout;
673  dmyhslope1dr = (hf-h0)/(myrout-rh0);
675  x1in=log(Rin-R0);
676  x1out=log(Rout-R0);
677  }
678  else if (defcoordlocal == JET2COORDS) {
679  }
680  else if (defcoordlocal == JET3COORDS) {
681  }
682  else if (defcoordlocal == SJETCOORDS) { // AKMARK
684  // RADIAL GRID SETUP
686  npow=global_npow; //don't change it, essentially equivalent to changing cpow2
687 
688  //radial hyperexponential grid
689  npow2=global_npow2; //power exponent
690  cpow2=global_cpow2; //exponent prefactor (the larger it is, the more hyperexponentiation is)
691  rbr = global_rbr; //radius at which hyperexponentiation kicks in
692  x1br = log( rbr - R0 ) / npow; //the corresponding X[1] value
693 
695  //ANGULAR GRID SETUP
697 
698  x10 = global_x10;
699  x20 = global_x20;
700 
701  //transverse resolution fraction devoted to different components
702  //(sum should be <1)
705 
706  jetnu = global_jetnu; //the nu-parameter that determines jet shape
707 
708  //subtractor, controls the size of the last few cells close to axis:
709  //if rsjet = 0, then no modification <- *** default for use with grid cylindrification
710  //if rsjet ~ 0.5, the grid is nearly vertical rather than monopolar,
711  // which makes the timestep larger
712  rsjet = global_rsjet;
713 
714  //distance at which theta-resolution is *exactly* uniform in the jet grid -- want to have this at BH horizon;
715  //otherwise, near-uniform near jet axis but less resolution (much) further from it
716  //the larger r0grid, the larger the thickness of the jet
717  //to resolve
719 
720  //distance at which jet part of the grid becomes monopolar
721  //should be the same as r0disk to avoid cell crowding at the interface of jet and disk grids
723 
724  //distance after which the jet grid collimates according to the usual jet formula
725  //the larger this distance, the wider is the jet region of the grid
727 
728  //distance at which disk part of the grid becomes monopolar
729  //the larger r0disk, the larger the thickness of the disk
730  //to resolve
732 
733  //distance after which the disk grid collimates to merge with the jet grid
734  //should be roughly outer edge of the disk
736 #if(USESJETLOGHOVERR)
738 #else
739  torusrmax_loc = 0.; //if not used, fill with dummy value
740 #endif
741 
742 
744  //PHI GRID SETUP
746  if( dofull2pi ) {
747  fracphi = 1;
748  }
749  else {
750  fracphi = global_fracphi; //phi-extent measured in units of 2*PI, i.e. 0.25 means PI/2
751  }
752  }
753  else if (defcoordlocal == JET6COORDS) {
754  x1br = log( rbr - R0 ) / npow; //the corresponding X[1] value
755  }
756  else if (defcoordlocal == BPTHIN1) {
757 
759  //PHI GRID SETUP
761  if( dofull2pi ) {
762  fracphi = 1;
763  }
764  else {
765  fracphi = global_fracphi; //phi-extent measured in units of 2*PI, i.e. 0.25 means PI/2
766  }
767  bp_x1br = log( bp_rbr - R0 ) / bp_npow; //the corresponding X[1] value
768  }
769  else if (defcoordlocal == JET6COORDSTHIN) {
770  th_x1br = log( th_rbr - R0 ) / th_npow; //the corresponding X[1] value
771  }
772  else if (defcoordlocal == JET5COORDS) {
773  }
774  else if (defcoordlocal == PULSARCOORDS) {
775 
776  if(0){// pulsar in force free
777  hinner=hslope; // hslope specifies inner hslope
778  houter=hslope*0.05; // reduce by some arbitrary factor (currently 1/20)
779  }
780  else if(1){ // NS-pulsar in GRMHD
781  hinner=1.9*hslope; // hslope specifies inner hslope
782  //houter=hslope*0.001; // reduce by some arbitrary factor (currently 1/20)
783  houter=hslope*1.5; // increase houter up to 2.0
784  }
785 
786  }
787  else if (defcoordlocal == UNIFORMCOORDS) {
788  }
789  else if (defcoordlocal == BILOGCYLCOORDS) {
790  }
791  else if (defcoordlocal == RAMESHCOORDS || defcoordlocal == RAMESHCOORDS_HALFDISK) {
792  }
793  else if (defcoordlocal == JET4COORDS ) {
794  // for theta2
795  h0=hslope; // inner-radial "hslope" for theta2
796  }
797  else if (defcoordlocal == UNI2LOG) {
798 
799  if(1){
800  Rstar = 10.0*1E5/Lunit; // 10km
801  }
802  else{
803  // GODMARK
804  Rstar = Rin;
805  }
806 
807  if(Nstar==0){
808  if(fabs(Rstar-Rin)>SMALL){
809  dualfprintf(fail_file,"If Nstar=0 then Rstar=Rin must be set\n");
810  myexit(9279);
811  }
812  }
813 
814  trifprintf("Rstar = %26.20g Nstar=%d Afactor=%26.20g\n",Rstar,Nstar,Afactor);
815  }
816  else{
817  dualfprintf(fail_file,"Shouldn't reach end of set_coord_parms: You set defcoordlocal=%d\n",defcoordlocal);
818  myexit(1);
819  }
820 
821 }
822 
823 
824 
826 void write_coord_parms(int defcoordlocal)
827 {
828  FILE *out;
829  int dimen;
830 
831 #if(USEOPENMP)
832  if(omp_in_parallel()){
833  dualfprintf(fail_file,"write_coord_parms_parms() called in parallel region\n");
834  myexit(784653446);
835  }
836 #endif
837 
838 
839  if(myid==0){
840  if((out=fopen("coordparms.dat","wt"))==NULL){
841  dualfprintf(fail_file,"Couldn't write coordparms.dat file\n");
842  myexit(1);
843  }
844  else{
845 
846  // same for all coords (notice no carraige return)
847  fprintf(out,"%26.20g %26.20g %26.20g %26.20g %d ",R0,Rin,Rout,hslope,dofull2pi);
848 
849  if (defcoordlocal == USERCOORD) {
850  extern void write_coord_parms_user(int defcoordlocal, FILE *out);
851  write_coord_parms_user(defcoordlocal,out);
852  }
853  else if (defcoordlocal == LOGRSINTH) {
854  }
855  else if (defcoordlocal == REBECCAGRID) {
856  }
857  else if (defcoordlocal == COMPLEX0TH) {
858  }
859  else if(defcoordlocal == UNIRSINTH || defcoordlocal == UNIRSINTH2){
860  }
861  else if (defcoordlocal == EQMIRROR) {
862  }
863  else if(defcoordlocal == COMPLEX1TH) {
864  }
865  else if(defcoordlocal == COMPLEX2TH) {
866  fprintf(out,"%26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g\n",x2trans,thetatores,m2,d2,c2,m3,b3,h_over_r);
867  }
868  else if (defcoordlocal == LOGRUNITH) { // uniform theta and log in radius
869  DIMENLOOP(dimen) fprintf(out,"%26.20g ",Rin_array[dimen]);
870  DIMENLOOP(dimen) fprintf(out,"%26.20g ",Rout_array[dimen]);
871  fprintf(out,"\n");
872  }
873  else if (defcoordlocal == JET1COORDS) {
874  fprintf(out,"%26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g\n",npow,h0,hf,rh0,myrout,dmyhslope1dr,dmyhslope2dx1,x1in,x1out);
875  }
876  else if (defcoordlocal == JET2COORDS) {
877  fprintf(out,"%26.20g %26.20g %26.20g %26.20g\n",npow,r1jet,njet,rpjet);
878  }
879  else if (defcoordlocal == JET3COORDS) {
880  fprintf(out,"%26.20g %26.20g %26.20g %26.20g %26.20g %26.20g\n",npow,r1jet,njet,r0jet,rsjet,Qjet);
881  }
882  else if (defcoordlocal == SJETCOORDS) {
883  fprintf(out,"%26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g\n",npow,r1jet,njet,r0grid,r0jet,rjetend,rsjet,Qjet,fracphi,npow2,cpow2,rbr,x1br,fracdisk,fracjet,r0disk,rdiskend,torusrmax_loc,jetnu,x10,x20);
884  }
885  else if (defcoordlocal == JET6COORDS) {
886  fprintf(out,"%26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g\n",npow,r1jet,njet,r0jet,rsjet,Qjet,ntheta,htheta,rsjet2,r0jet2,rsjet3,r0jet3,rs,r0,npow2,cpow2,rbr,x1br,cpow3);
887  }
888  else if (defcoordlocal == JET6COORDSTHIN) {
889  fprintf(out,"%26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g\n",th_npow,th_r1jet,th_njet,th_r0jet,th_rsjet,th_Qjet,th_ntheta,th_htheta,th_rsjet2,th_r0jet2,th_rsjet3,th_r0jet3,th_rs,th_r0,th_npow2,th_cpow2,th_rbr,th_x1br,th_rbr,th_h0,th_njet1);
890  }
891  else if (defcoordlocal == BPTHIN1) {
892  fprintf(out,"%21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g\n",bp_npow,bp_r1jet,bp_njet,bp_r0jet,bp_rsjet,bp_Qjet,bp_ntheta,bp_htheta,bp_rsjet2,bp_r0jet2,bp_rsjet3,bp_r0jet3,bp_rs,bp_r0,bp_rsinner,bp_r0inner,bp_npow2,bp_cpow2,bp_rbr,bp_x1br,fracphi); // MARKTODO add bp_h0? and add bp_njet1
893  }
894  else if (defcoordlocal == JET5COORDS) {
895  fprintf(out,"%26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g\n",AAAA,AAA,BBB,DDD,ii0,CCCC,Rj);
896  fprintf(out,"%26.20g %26.20g %26.20g %26.20g %26.20g\n",r1jet,njet,r0jet,rsjet,Qjet);
897  }
898  else if (defcoordlocal == PULSARCOORDS) {
899  fprintf(out,"%26.20g %26.20g %26.20g %26.20g %26.20g\n",npow,hinner,houter,r0jet,rsjet);
900  }
901  else if (defcoordlocal == UNIFORMCOORDS) {
902  //uniform grid for Cartesian coordinates
903  DIMENLOOP(dimen) fprintf(out,"%26.20g ",Rin_array[dimen]);
904  DIMENLOOP(dimen) fprintf(out,"%26.20g ",Rout_array[dimen]);
905  fprintf(out,"\n");
906  }
907  else if (defcoordlocal == BILOGCYLCOORDS) {
908  fprintf(out,"%26.20g\n",npow);
909  }
910  else if (defcoordlocal == RAMESHCOORDS || defcoordlocal == RAMESHCOORDS_HALFDISK) {
911  fprintf(out,"%26.20g %26.20g %26.20g %26.20g\n",npow,r0jet,njet,rsjet);
912  }
913  else if (defcoordlocal == JET4COORDS) {
914  // npow, rs, r0, h0, r0jet, njet, rsjet
915  fprintf(out,"%26.20g %26.20g %26.20g %26.20g %26.20g %26.20g %26.20g\n",npow,rs,r0,h0,r0jet,njet,rsjet);
916  }
917  else if (defcoordlocal == UNI2LOG) {
918  fprintf(out,"%d %26.20g %26.20g\n",Nstar,Rstar,Afactor);
919  }
920  else{
921  dualfprintf(fail_file,"Shouldn't reach end of write_coord_parms: You set defcoordlocal=%d\n",defcoordlocal);
922  myexit(1);
923  }
924 
925  fclose(out);
926  }
927  }
928 }
929 
930 
932 void read_coord_parms(int defcoordlocal)
933 {
934  FILE *in;
935  FTYPE ftemp;
936  int dimen;
937 
938 
939 #if(USEOPENMP)
940  if(omp_in_parallel()){
941  dualfprintf(fail_file,"read_coord_parms_parms() called in parallel region\n");
942  myexit(784653446);
943  }
944 #endif
945 
946  if(myid==0){
947  in=fopen("coordparms.dat","rt");
948  if(in==NULL){
949  dualfprintf(fail_file,"Couldn't read coordparms.dat file. I'll assume coded coordinates and let restart header overwrite any global restart parameters\n");
951  }
952  else{
953  // don't want to overwrite since restart file sets this
954  // fscanf(in,HEADER5IN,&ftemp,&ftemp,&ftemp,&ftemp,&ftemp);
955  // NO: jon_interp.c requires read these in, so assume restart file has equal values to coordparms.dat file
956  fscanf(in,HEADER4IN,&R0,&Rin,&Rout,&hslope);
957  fscanf(in,"%d",&dofull2pi);
958 
959 
960 
961  if (defcoordlocal == USERCOORD) {
962  extern void read_coord_parms_user(int defcoordlocal, FILE *in);
963  read_coord_parms_user(defcoordlocal, in);
964  }
965  else if (defcoordlocal == LOGRSINTH) {
966  }
967  else if (defcoordlocal == REBECCAGRID) {
968  }
969  else if (defcoordlocal == COMPLEX0TH) {
970  }
971  else if(defcoordlocal == UNIRSINTH || defcoordlocal == UNIRSINTH2){
972  }
973  else if (defcoordlocal == EQMIRROR) {
974  }
975  else if(defcoordlocal == COMPLEX1TH) {
976  }
977  else if(defcoordlocal == COMPLEX2TH) {
978  fscanf(in,HEADER8IN,&x2trans,&thetatores,&m2,&d2,&c2,&m3,&b3,&h_over_r);
979  }
980  else if (defcoordlocal == LOGRUNITH) { // uniform theta and log in radius
981  DIMENLOOP(dimen) fscanf(in,HEADERONEIN,&Rin_array[dimen]);
982  DIMENLOOP(dimen) fscanf(in,HEADERONEIN,&Rout_array[dimen]);
983  }
984  else if (defcoordlocal == JET1COORDS) {
986  }
987  else if (defcoordlocal == JET2COORDS) {
988  fscanf(in,HEADER4IN,&npow,&r1jet,&njet,&rpjet);
989  }
990  else if (defcoordlocal == JET3COORDS) {
991  fscanf(in,HEADER6IN,&npow,&r1jet,&njet,&r0jet,&rsjet,&Qjet);
992  }
993  else if (defcoordlocal == SJETCOORDS) {
996  fscanf(in,HEADER3IN,&jetnu,&x10,&x20);
997  }
998  else if (defcoordlocal == JET6COORDS) {
1000  }
1001  else if (defcoordlocal == JET6COORDSTHIN) {
1002  fscanf(in,HEADER21IN,&th_npow,&th_r1jet,&th_njet,&th_r0jet,&th_rsjet,&th_Qjet,&th_ntheta,&th_htheta,&th_rsjet2,&th_r0jet2,&th_rsjet3,&th_r0jet3,&th_rs,&th_r0,&th_npow2,&th_cpow2,&th_rbr,&th_x1br,&th_rbr,&th_h0,&th_njet1);
1003  }
1004  else if (defcoordlocal == BPTHIN1) {
1006  }
1007  else if (defcoordlocal == JET5COORDS) {
1008  fscanf(in,HEADER7IN,&AAAA,&AAA,&BBB,&DDD,&ii0,&CCCC,&Rj);
1009  fscanf(in,HEADER5IN,&r1jet,&njet,&r0jet,&rsjet,&Qjet);
1010  }
1011  else if (defcoordlocal == PULSARCOORDS) {
1012  fscanf(in,HEADER5IN,&npow,&hinner,&houter,&r0jet,&rsjet);
1013  }
1014  else if (defcoordlocal == UNIFORMCOORDS) {
1015  //uniform grid for Cartesian coordinates
1016  DIMENLOOP(dimen) fscanf(in,HEADERONEIN,&Rin_array[dimen]);
1017  DIMENLOOP(dimen) fscanf(in,HEADERONEIN,&Rout_array[dimen]);
1018  }
1019  else if (defcoordlocal == BILOGCYLCOORDS) {
1020  fscanf(in,HEADERONEIN,&npow);
1021  }
1022  else if (defcoordlocal == RAMESHCOORDS|| defcoordlocal == RAMESHCOORDS_HALFDISK) {
1023  fscanf(in,HEADER4IN,&npow,&r0jet,&njet,&rsjet);
1024  }
1025  else if (defcoordlocal == JET4COORDS) {
1026  fscanf(in,HEADER7IN,&npow,&rs,&r0,&h0,&r0jet,&njet,&rsjet);
1027  // npow, rs, r0, h0, r0jet, njet, rsjet
1028  }
1029  else if (defcoordlocal == UNI2LOG) {
1030  fscanf(in,"%d",&Nstar);
1031  fscanf(in,HEADERONEIN,&Rstar);
1032  fscanf(in,HEADERONEIN,&Afactor);
1033  }
1034  else{
1035  dualfprintf(fail_file,"Shouldn't reach end of read_coord_parms: You set defcoordlocal=%d\n",defcoordlocal);
1036  myexit(1);
1037  }
1038 
1039  fclose(in);
1040  }
1041  }
1042 
1043 #if(USEMPI)
1044  // broadcast
1045  MPI_Bcast(&R0, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1046  MPI_Bcast(&Rin, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1047  MPI_Bcast(&Rout, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1048  MPI_Bcast(&hslope, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1049  MPI_Bcast(&dofull2pi, 1, MPI_INT, MPIid[0], MPI_COMM_GRMHD);
1050 
1051 
1052  if (defcoordlocal == USERCOORD) {
1053  extern void read_coord_parms_mpi_user(int defcoordlocal);
1054  read_coord_parms_mpi_user(defcoordlocal);
1055  }
1056  else if (defcoordlocal == LOGRSINTH) {
1057  }
1058  else if (defcoordlocal == REBECCAGRID) {
1059  }
1060  else if (defcoordlocal == COMPLEX0TH) {
1061  }
1062  else if(defcoordlocal == UNIRSINTH || defcoordlocal == UNIRSINTH2){
1063  }
1064  else if (defcoordlocal == EQMIRROR) {
1065  }
1066  else if(defcoordlocal == COMPLEX1TH) {
1067  }
1068  else if(defcoordlocal == COMPLEX2TH) {
1069  MPI_Bcast(&x2trans, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1070  MPI_Bcast(&thetatores, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1071  MPI_Bcast(&m2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1072  MPI_Bcast(&d2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1073  MPI_Bcast(&c2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1074  MPI_Bcast(&m3, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1075  MPI_Bcast(&b3, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1076  // MPI_Bcast(&h_over_r, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD); // set by pre_init_specific_init() in init.c
1077  }
1078  else if (defcoordlocal == LOGRUNITH) { // uniform theta and log in radius
1079  DIMENLOOP(dimen) MPI_Bcast(&Rin_array[dimen], 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1080  DIMENLOOP(dimen) MPI_Bcast(&Rout_array[dimen], 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1081  }
1082  else if (defcoordlocal == JET1COORDS) {
1083  MPI_Bcast(&npow, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1084  MPI_Bcast(&h0, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1085  MPI_Bcast(&hf, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1086  MPI_Bcast(&rh0, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1087  MPI_Bcast(&myrout, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1088  MPI_Bcast(&dmyhslope1dr, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1089  MPI_Bcast(&dmyhslope2dx1, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1090  MPI_Bcast(&x1in, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1091  MPI_Bcast(&x1out, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1092  }
1093  else if (defcoordlocal == JET2COORDS) {
1094  MPI_Bcast(&npow, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1095  MPI_Bcast(&r1jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1096  MPI_Bcast(&njet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1097  MPI_Bcast(&rpjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1098  }
1099  else if (defcoordlocal == JET3COORDS) {
1100  MPI_Bcast(&npow, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1101  MPI_Bcast(&r1jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1102  MPI_Bcast(&njet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1103  MPI_Bcast(&r0jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1104  MPI_Bcast(&rsjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1105  MPI_Bcast(&Qjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1106  }
1107  else if (defcoordlocal == SJETCOORDS) {
1108  MPI_Bcast(&npow, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1109  MPI_Bcast(&r1jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1110  MPI_Bcast(&njet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1111  MPI_Bcast(&r0grid, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1112  MPI_Bcast(&r0jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1113  MPI_Bcast(&rjetend, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1114  MPI_Bcast(&rsjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1115  MPI_Bcast(&Qjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1116  //new params
1117  MPI_Bcast(&fracphi, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1118  MPI_Bcast(&npow2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1119  MPI_Bcast(&cpow2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1120  MPI_Bcast(&rbr, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1121  MPI_Bcast(&x1br, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1122  MPI_Bcast(&fracdisk, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1123  MPI_Bcast(&fracjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1124  MPI_Bcast(&r0disk, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1125  MPI_Bcast(&rdiskend, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1126  MPI_Bcast(&torusrmax_loc, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1127  MPI_Bcast(&jetnu, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1128  MPI_Bcast(&x10, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1129  MPI_Bcast(&x20, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1130  }
1131  else if (defcoordlocal == JET6COORDS) {
1132  MPI_Bcast(&npow, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1133  MPI_Bcast(&r1jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1134  MPI_Bcast(&njet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1135  MPI_Bcast(&r0jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1136  MPI_Bcast(&rsjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1137  MPI_Bcast(&Qjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1138  MPI_Bcast(&ntheta, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1139  MPI_Bcast(&htheta, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1140  MPI_Bcast(&rsjet2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1141  MPI_Bcast(&r0jet2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1142  MPI_Bcast(&rsjet3, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1143  MPI_Bcast(&r0jet3, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1144  MPI_Bcast(&rs, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1145  MPI_Bcast(&r0, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1146  MPI_Bcast(&npow2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1147  MPI_Bcast(&cpow2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1148  MPI_Bcast(&rbr, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1149  MPI_Bcast(&x1br, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1150  MPI_Bcast(&cpow3, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1151  }
1152  else if (defcoordlocal == JET6COORDSTHIN) {
1153  MPI_Bcast(&th_npow, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1154  MPI_Bcast(&th_r1jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1155  MPI_Bcast(&th_njet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1156  MPI_Bcast(&th_r0jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1157  MPI_Bcast(&th_rsjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1158  MPI_Bcast(&th_Qjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1159  MPI_Bcast(&th_ntheta, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1160  MPI_Bcast(&th_htheta, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1161  MPI_Bcast(&th_rsjet2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1162  MPI_Bcast(&th_r0jet2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1163  MPI_Bcast(&th_rsjet3, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1164  MPI_Bcast(&th_r0jet3, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1165  MPI_Bcast(&th_rs, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1166  MPI_Bcast(&th_r0, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1167  MPI_Bcast(&th_npow2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1168  MPI_Bcast(&th_cpow2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1169  MPI_Bcast(&th_rbr, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1170  MPI_Bcast(&th_x1br, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1171  MPI_Bcast(&th_rbr, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1172  MPI_Bcast(&th_h0, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1173  MPI_Bcast(&th_njet1, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1174  }
1175  else if (defcoordlocal == BPTHIN1) {
1176  MPI_Bcast(&bp_npow, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1177  MPI_Bcast(&bp_r1jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1178  MPI_Bcast(&bp_njet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1179  MPI_Bcast(&bp_r0jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1180  MPI_Bcast(&bp_rsjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1181  MPI_Bcast(&bp_Qjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1182  MPI_Bcast(&bp_ntheta, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1183  MPI_Bcast(&bp_htheta, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1184  MPI_Bcast(&bp_rsjet2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1185  MPI_Bcast(&bp_r0jet2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1186  MPI_Bcast(&bp_rsjet3, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1187  MPI_Bcast(&bp_r0jet3, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1188  MPI_Bcast(&bp_rs, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1189  MPI_Bcast(&bp_r0, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1190  MPI_Bcast(&bp_rsinner, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1191  MPI_Bcast(&bp_r0inner, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1192  MPI_Bcast(&bp_npow2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1193  MPI_Bcast(&bp_cpow2, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1194  MPI_Bcast(&bp_rbr, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1195  MPI_Bcast(&bp_x1br, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1196  MPI_Bcast(&fracphi, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1197  }
1198  else if (defcoordlocal == JET5COORDS) {
1199  MPI_Bcast(&AAAA, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1200  MPI_Bcast(&AAA, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1201  MPI_Bcast(&BBB, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1202  MPI_Bcast(&DDD, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1203  MPI_Bcast(&ii0, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1204  MPI_Bcast(&CCCC, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1205  MPI_Bcast(&Rj, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1206 
1207  MPI_Bcast(&r1jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1208  MPI_Bcast(&njet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1209  MPI_Bcast(&r0jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1210  MPI_Bcast(&rsjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1211  MPI_Bcast(&Qjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1212  }
1213  else if (defcoordlocal == PULSARCOORDS) {
1214  MPI_Bcast(&npow, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1215  MPI_Bcast(&hinner, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1216  MPI_Bcast(&houter, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1217  MPI_Bcast(&r0jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1218  MPI_Bcast(&rsjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1219  }
1220  else if (defcoordlocal == UNIFORMCOORDS) {
1221  //uniform grid for Cartesian coordinates
1222  DIMENLOOP(dimen) MPI_Bcast(&Rin_array[dimen], 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1223  DIMENLOOP(dimen) MPI_Bcast(&Rout_array[dimen], 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1224  }
1225  else if (defcoordlocal == BILOGCYLCOORDS) {
1226  MPI_Bcast(&npow, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1227  }
1228  else if (defcoordlocal == RAMESHCOORDS|| defcoordlocal == RAMESHCOORDS_HALFDISK) {
1229  MPI_Bcast(&npow, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1230  MPI_Bcast(&r0jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1231  MPI_Bcast(&njet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1232  MPI_Bcast(&rsjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1233  }
1234  else if (defcoordlocal == JET4COORDS) {
1235  MPI_Bcast(&npow, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1236  MPI_Bcast(&rs, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1237  MPI_Bcast(&r0, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1238  MPI_Bcast(&h0, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1239  MPI_Bcast(&r0jet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1240  MPI_Bcast(&njet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1241  MPI_Bcast(&rsjet, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1242  }
1243  else if (defcoordlocal == UNI2LOG) {
1244  MPI_Bcast(&Nstar, 1, MPI_INT, MPIid[0], MPI_COMM_GRMHD);
1245  MPI_Bcast(&Rstar, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1246  MPI_Bcast(&Afactor, 1, MPI_FTYPE, MPIid[0], MPI_COMM_GRMHD);
1247  }
1248  else{
1249  dualfprintf(fail_file,"Shouldn't reach end of read_coord_parms MPI stuff: You set defcoordlocal=%d\n",defcoordlocal);
1250  myexit(1);
1251  }
1252 
1253 #endif
1254 
1255 }
1256 
1257 
1258 
1261 {
1262  extern FTYPE mysin(FTYPE th);
1263  FTYPE myx2;
1264  FTYPE mysign,ts1,fnstar,myNrat;
1265  FTYPE BB,CC;
1266  FTYPE myhslope1,myhslope2,myhslope;
1267  FTYPE flip1,flip2;
1268  FTYPE th0,th0toprint,th2,switch0,switch2,switchinner0,switchinner2,switchrad0,switchrad2,thetasign,x2temp;
1269  FTYPE r,dtheta2dx1,dtheta2dx2,dtheta0dx2,dtheta0dx1,dswitch0dr,dswitch2dr;
1270  // FTYPE th0,th2,switch0,switch2;
1271  // FTYPE r,dtheta2dx1,dtheta2dx2,dtheta0dx2,dtheta0dx1,dswitch0dr,dswitch2dr;
1272  FTYPE X0;
1273  // for defcoord=JET5COORDS
1274  FTYPE ii,logform,radialarctan,thetaarctan; // temp vars
1275  //for SJETCOORDS
1276  FTYPE theexp,theexp1,theexp2;
1277 
1278 
1279  // AKMARK: coordinates defined, in particular, phi wedge (e.g., V[3]=2.0*M_PI*X[3])
1280  // below will give correct dxdxp[1][1], etc.
1281  V[0]=X[0]; // assume time = X[0] means time now and negative means time in past and positive means future
1282 
1283  // in spherical polar coords: t=V[0] r=V[1] th=V[2] phi=V[3]
1284 
1285 
1286  if(defcoord == USERCOORD) {
1287  extern void blcoord_user(FTYPE *X, FTYPE *V);
1288  blcoord_user(X,V);
1289  }
1290  else if (defcoord == LOGRSINTH) {
1291 #if(1)
1292  if(BCtype[X1DN]==R0SING){
1293  if(R0>=0.0){
1294  dualfprintf(fail_file,"With log grid and R0SING must have R0<0 instead of %26.20g\n",R0);
1295  myexit(8274);
1296  }
1297  X0 = log(-R0);
1298  if(X[1]>X0) V[1] = R0+exp(X[1]) ;
1299  else V[1] = -(R0+R0*R0*exp(-X[1])) ;
1300  // dualfprintf(fail_file,"X0=%26.20g V[1]=%26.20g\n",X0,V[1]);
1301  }
1302  else{
1303  V[1] = R0+exp(X[1]) ;
1304  // if V[1]=r<0 here, the presume only where interpolation boundaries are, not evolved quantities, and not extending so far negative radius that reach beyond, e.g. light cylinder so that velocities will be undefined with simple extrapolation
1305  }
1306 #else
1307 
1308  V[1] = R0+exp(X[1]) ;
1309 #endif
1310 
1311 
1312  // V[1] = Rin*exp(X[1]) ;
1313  //V[1] = Rin * exp(X[1]);
1314  if(X[2]<0.5){
1315  V[2] = M_PI * X[2] + ((1. - hslope) / 2.) * mysin(2. * M_PI * X[2]);
1316  }
1317  else{
1318  // V[2] = 0.5*M_PI + M_PI * fabs(X[2]-0.5) + ((1. - hslope) / 2.) * (-mysin(2. * M_PI * (1.0-X[2])));
1319  V[2] = M_PI - (M_PI * (1.0-X[2])) + ((1. - hslope) / 2.) * (-mysin(2. * M_PI * (1.0-X[2])));
1320  }
1321 
1322  // default is uniform \phi grid
1323  V[3]=2.0*M_PI*X[3];
1324 
1325  }
1326  else if (defcoord == REBECCAGRID) {
1327  // V[1] = Rin*exp(X[1]) ;
1328  V[1] = R0+exp(X[1]) ;
1329  //V[1] = Rin * exp(X[1]);
1330  // if(X[2]<0.5){
1331  // V[2] = M_PI * X[2] + ((1. - hslope) / 2.) * mysin(2. * M_PI * X[2]);
1332  // }
1333  // else{
1334  // V[2] = 0.5*M_PI + M_PI * fabs(X[2]-0.5) + ((1. - hslope) / 2.) * (-mysin(2. * M_PI * (1.0-X[2])));
1335  // V[2] = M_PI - (M_PI * (1.0-X[2])) + ((1. - hslope) / 2.) * (-mysin(2. * M_PI * (1.0-X[2])));
1336  // }
1337  V[2]=(hslope*((X[2]-0.5)/0.5) + (1-hslope)*pow((X[2]-0.5)/0.5, 7.0)+1.)*M_PI/2.;
1338  // default is uniform \phi grid
1339  V[3]=0.5*M_PI*X[3];
1340 
1341  }
1342  else if (defcoord == COMPLEX0TH) {
1343  V[1] = R0+Rin * exp(X[1] * log(Rout / Rin));
1344  V[2] =
1345  ((-49. * hslope + 60. * M_PI) * X[2]) / 12. +
1346  ((247. * hslope - 240. * M_PI) * pow(X[2],2)) / 12. +
1347  ((-83. * hslope + 80. * M_PI) * pow(X[2],3)) / 2. -
1348  (5. * (-25. * hslope + 24. * M_PI) * pow(X[2], 4)) / 3. +
1349  (2. * (-25. * hslope + 24. * M_PI) * pow(X[2], 5)) / 3.;
1350  // default is uniform \phi grid
1351  V[3]=2.0*M_PI*X[3];
1352  }
1353  else if(defcoord==UNIRSINTH){
1354  V[1]=X[1];
1355  V[2] = M_PI* X[2] + ((1. - hslope) / 2.) * sin(2. * M_PI * X[2]);
1356  // default is uniform \phi grid
1357  V[3]=2.0*M_PI*X[3];
1358  }
1359  else if(defcoord==UNIRSINTH2){
1360  V[1]=Rin + (Rout-Rin)*X[1];
1361  V[2] = M_PI* X[2] + ((1. - hslope) / 2.) * sin(2. * M_PI * X[2]);
1362  // default is uniform \phi grid
1363  V[3]=2.0*M_PI*X[3];
1364  }
1365  else if (defcoord == EQMIRROR) {
1366  // MIRROR at equator, equator is outer theta edge
1367  V[1] = R0+exp(X[1]) ;
1368  V[2] = M_PI * X[2] + ((1. - hslope) / 2.) * sin(2. * M_PI * X[2]);
1369  // default is uniform \phi grid
1370  V[3]=2.0*M_PI*X[3];
1371  }
1372  else if(defcoord == COMPLEX1TH) {
1373  V[1] = R0+exp(X[1]) ;
1374 
1375  V[2] = (der0*X[2]*(-32.*pow(-1. + X[2],3.)*pow(X[2],2.)*(-1. + 2.*X[2]) -
1376  Ri*(-1. + X[2])*pow(-1. + 2.*X[2],3.)*
1377  (-1. + 7.*(-1. + X[2])*X[2])) +
1378  M_PI*Ri*pow(X[2],3.)*(70. +
1379  3.*X[2]*(-105. + 2.*X[2]*(91. + 10.*X[2]*(-7. + 2.*X[2])))))/Ri;
1380 
1381  // default is uniform \phi grid
1382  V[3]=2.0*M_PI*X[3];
1383  }
1384  else if(defcoord == COMPLEX2TH) {
1385 
1386  V[1] = R0+exp(X[1]) ;
1387 
1388  // now assign values
1389  if(X[2]<0.5){ myx2=X[2]; flip1=0.0; flip2=1.0;}
1390  else{ myx2=1.0-X[2]; flip1=M_PI; flip2=-1.0;}
1391 
1392  if(myx2<=x2trans){
1393  V[2] = flip1+flip2*(d2*pow(myx2,3.0)+c2*pow(myx2,2.0)+m2*myx2);
1394  }
1395  else{
1396  V[2] = flip1+flip2*(m3*myx2+b3);
1397  }
1398  // default is uniform \phi grid
1399  V[3]=2.0*M_PI*X[3];
1400 
1401  }
1402  else if (defcoord == LOGRUNITH) { // uniform theta and log in radius
1403  V[1] = R0+exp(X[1]) ;
1404  V[2] = Rin_array[2] + X[2] * ( Rout_array[2] - Rin_array[2] );
1405  V[3] = Rin_array[3] + X[3] * ( Rout_array[3] - Rin_array[3] );
1406  }
1407  else if (defcoord == JET1COORDS) {
1408  V[1] = R0+exp(pow(X[1],npow)) ;
1409 
1410  myhslope1 = h0+dmyhslope1dr*((V[1])-rh0);
1411  myhslope2 = h0+(hf-h0)*(X[1]-x1in)/(x1out-x1in);
1412 
1413  myhslope=(myhslope1+myhslope2)*0.5;
1414  V[2] = M_PI * X[2] + ((1. - myhslope) / 2.) * sin(2. * M_PI * X[2]);
1415  // default is uniform \phi grid
1416  V[3]=2.0*M_PI*X[3];
1417  }
1418  else if (defcoord == JET2COORDS) {
1419  V[1] = R0+exp(pow(X[1],npow)) ;
1420 
1421  myhslope=2.0-pow(V[1]/r1jet,njet*(-1.0+exp(1.0)/exp(V[1]+rpjet)));
1422 
1423  V[2] = M_PI * X[2] + ((1. - myhslope) / 2.) * sin(2. * M_PI * X[2]);
1424  // default is uniform \phi grid
1425  V[3]=2.0*M_PI*X[3];
1426  }
1427  else if (defcoord == JET3COORDS) {
1428  V[1] = R0+exp(pow(X[1],npow)) ;
1429 
1430  myhslope=2.0-Qjet*pow(V[1]/r1jet,-njet*(0.5+1.0/M_PI*atan(V[1]/r0jet-rsjet/r0jet)));
1431 
1432  if(X[2]<0.5){
1433  V[2] = M_PI * X[2] + ((1. - myhslope) / 2.) * mysin(2. * M_PI * X[2]);
1434  }
1435  else{
1436  V[2] = M_PI - (M_PI * (1.0-X[2])) + ((1. - myhslope) / 2.) * (-mysin(2. * M_PI * (1.0-X[2])));
1437  }
1438  // default is uniform \phi grid
1439  V[3]=2.0*M_PI*X[3];
1440  }
1441  else if (defcoord == SJETCOORDS) {
1442 #if(0)
1443  //use original coordinates
1444  vofx_sjetcoords( X, V );
1445 #else
1446  //apply cylindrification to original coordinates
1447  //[this internally calls vofx_sjetcoords()]
1448  vofx_cylindrified( X, vofx_sjetcoords, V );
1449 #endif
1450 
1451  }
1452  else if (defcoord == JET6COORDS) {
1453 
1454 #if(0) // no change in exponentiation
1455  // JET3COORDS-like radial grid
1456  V[1] = R0+exp(pow(X[1],npow)) ;
1457 #elif(1)
1458 
1459  theexp = npow*X[1];
1460  if( X[1] > x1br ) {
1461  theexp += cpow2 * pow(X[1]-x1br,npow2);
1462  }
1463  V[1] = R0+exp(theexp);
1464 
1465 
1466  // FTYPE npowtrue,npowlarger=10.0;
1467  // FTYPE npowrs=1E3;
1468  // FTYPE npowr0=2E2;
1469  // npowtrue = npow + (npowlarger-npow)*(0.5+1.0/M_PI*atan((V[1]-npowrs)/npowr0));
1470  // V[1] = R0+exp(pow(X[1],npowtrue)) ;
1471 #elif(0)
1472  // avoid jump in grid at rbr
1473  // determine switches
1474  FTYPE r0rbr=rbr/2.0;
1475  switch0 = 0.5+1.0/M_PI*atan((V[1]-rbr)/r0rbr); // 1 for outer r
1476 
1477  FTYPE V1 = R0+exp(npow*X[1]);
1478  FTYPE V2 = R0+exp(npow*X[1] + cpow2 * pow(cpow3*(X[1]-x1br*1.0),npow2));
1479 
1480  V[1] = V1*(1.0-switch0) + V2*switch0;
1481 
1482 #endif
1483 
1484 
1485 
1486  FTYPE theta1,theta2,arctan2;
1487 
1488 
1489 #if(0)
1490  // JET3COORDS-based:
1491  myhslope=2.0-Qjet*pow(V[1]/r1jet,-njet*(0.5+1.0/M_PI*atan(V[1]/r0jet-rsjet/r0jet)));
1492  theta1 = M_PI * X[2] + ((1. - myhslope) * 0.5) * mysin(2. * M_PI * X[2]);
1493 #else
1494  // RAMESH BASED
1495  // myhslope here is h2 in MCAF paper
1496  // // h0 here is h3 in MCAF paper
1497  //FTYPE njetvsr;
1498  //if(V[1]<rbr) njetvsr=njet;
1499  // else njetvsr=njet/(V[1])*rbr;
1500  //else njetvsr=
1501  //njetvsr=njet;
1502 
1503  FTYPE localrbr=rbr; //500.0; // rbr;
1504 // FTYPE localrbrr0=MAX(100.0,localrbr/2.0);
1505  FTYPE localrbrr0=100.0;
1506 
1507  switch0 = 0.5+1.0/M_PI*atan((V[1]-localrbr)/localrbrr0); // large r
1508  switch2 = 1.0-switch0; // small r
1509 
1510 
1511  FTYPE myhslope1=h0 + pow( (V[1]-rsjet3)/r0jet3 , njet);
1512  FTYPE myhslope2=h0 + pow( (localrbr-rsjet3)/r0jet3 , njet);
1513  myhslope = myhslope1*switch2 + myhslope2*switch0;
1514 
1515  // determine theta2
1516  if(X[2]>1.0) myx2=2.0-X[2];
1517  else if(X[2]<0.0) myx2=-X[2];
1518  else myx2=X[2];
1519 
1520  th2 = 0.5*M_PI*(1.0 + atan(myhslope*(myx2-0.5))/atan(myhslope*0.5));
1521 
1522  if(X[2]>1.0) th2=2.0*M_PI-th2;
1523  else if(X[2]<0.0) th2=-th2;
1524 
1525  // determine theta0
1526  // JET3COORDS-based:
1527  myhslope1=2.0-Qjet*pow(V[1]/r1jet,-njet*(0.5+1.0/M_PI*atan(V[1]/r0jet-rsjet/r0jet)));
1528  myhslope2=2.0-Qjet*pow(localrbr/r1jet,-njet*(0.5+1.0/M_PI*atan(localrbr/r0jet-rsjet/r0jet)));
1529  myhslope = myhslope1*switch2 + myhslope2*switch0;
1530 
1531  if(0){
1532  // myhslope here is h0 in MCAF paper
1533  th0 = M_PI * X[2] + ((1. - myhslope) * 0.5) * mysin(2. * M_PI * X[2]);
1534  }
1535  else{ // SUPERMADNEW
1536  // poly grid
1537  FTYPE xi=((1. - myhslope) * 0.5);
1538  th0 = M_PI * .5 * (myhslope*(2.0*X[2]-1.0) + (1.0-myhslope)*pow(2.0*X[2]-1.0,3.0)+1.);
1539  // dualfprintf(fail_file,"myhslope=%g th0=%g\n",myhslope,th0);
1540  }
1541 
1542  // determine switches (only function of radius and not x2 or theta)
1543  switch0 = 0.5+1.0/M_PI*atan((V[1]-rs)/r0); // switch in .nb file // switch0->1 as r->infinity
1544  switch2 = 1.0-switch0; // for inner radial region
1545 
1546  // this works because all functions are monotonic, so final result is monotonic. Also, th(x2=1)=Pi and th(x2=0)=0 as required
1547  theta1 = th0*switch2 + th2*switch0; // th0 is activated for small V[1] and th2 is activated at large radii. Notice that sum of switch2+switch0=1 so normalization correct.
1548 
1549 #endif
1550 
1551  // fix_3dpoledtissue.nb based:
1552  theta2 = M_PI*0.5*(htheta*(2.0*X[2]-1.0)+(1.0-htheta)*pow(2.0*X[2]-1.0,ntheta)+1.0);
1553 
1554  // generate interpolation factor
1555  arctan2 = 0.5 + 1.0/M_PI*(atan( (V[1]-rsjet2)/r0jet2) );
1556 
1557  // now interpolate between them
1558  V[2] = theta2 + arctan2*(theta1-theta2);
1559 
1560 
1561 
1562  // default is uniform \phi grid
1563  V[3]=2.0*M_PI*X[3];
1564  }
1565  else if (defcoord == BPTHIN1) {
1566 
1567 #if(0) // no change in exponentiation
1568  // JET3COORDS-like radial grid
1569  V[1] = R0+exp(pow(X[1],bp_npow)) ;
1570 #else
1571 
1572 #if(0)
1573  theexp = bp_npow*X[1];
1574  if( X[1] > bp_x1br ) {
1575  theexp += bp_cpow2 * pow(X[1]-bp_x1br,bp_npow2);
1576  }
1577  V[1] = R0+exp(theexp);
1578 #else
1579  /*if(X[1]<bp_x1br){
1580  switchrad0=0.0;
1581  switchrad2=1.0;
1582  }
1583  else
1584  {
1585  switchrad0=1.0;
1586  switchrad2=0.0;
1587  }*/
1588  switchrad0 = 0.5+1.0/M_PI*atan((X[1]-bp_x1br)*5.*10./dx[1]/totalsize[1]); //dx[1]/N1);//totalsize[1]); // switch in .nb file
1589  switchrad2 = 0.5-1.0/M_PI*atan((X[1]-bp_x1br)*5.*10./dx[1]/totalsize[1]); //dx[1]~.03151/N1);//totalsize[1]); // switchi in .nb file
1590 
1591  theexp1 = bp_npow*X[1];
1592  theexp2 = theexp1+bp_cpow2 * pow(X[1]-bp_x1br,bp_npow2);
1593  V[1] = (R0+exp(theexp1))*switchrad2 + (R0+exp(theexp2))*switchrad0;
1594 #endif
1595 
1596  // FTYPE npowtrue,npowlarger=10.0;
1597  // FTYPE npowrs=1E3;
1598  // FTYPE npowr0=2E2;
1599  // npowtrue = npow + (npowlarger-npow)*(0.5+1.0/M_PI*atan((V[1]-npowrs)/npowr0));
1600  // V[1] = R0+exp(pow(X[1],npowtrue)) ;
1601 #endif
1602 
1603 
1604 
1605  FTYPE theta1,theta2,arctan2;
1606 
1607 
1608 #if(0)
1609  // JET3COORDS-based:
1610  myhslope=2.0-bp_Qjet*pow(V[1]/bp_r1jet,-bp_njet*(0.5+1.0/M_PI*atan(V[1]/bp_r0jet-bp_rsjet/bp_r0jet)));
1611  theta1 = M_PI * X[2] + ((1. - myhslope) * 0.5) * mysin(2. * M_PI * X[2]);
1612 #else
1613  // RAMESH BASED
1614  // myhslope here is h2 in MCAF paper
1615  // h0 here is h3 in MCAF paper
1616  //if(V[1] > bp_rsjet3){
1617  myhslope=bp_h0 + pow( (V[1]-bp_rsjet3)/bp_r0jet3 , bp_njet);
1618  //}
1619  /*else {
1620  myhslope=bp_h0;
1621  }*/
1622  // determine theta2
1623  if(X[2]>1.0) myx2=2.0-X[2];
1624  else if(X[2]<0.0) myx2=-X[2];
1625  else myx2=X[2];
1626 
1627  th2 = M_PI*.5*(.2*(2.0*myx2-1.0) + (1.0-.2)*pow(2.0*myx2-1,3.0)+1.0);
1628 
1629  if(X[2]>1.0) th2=2.0*M_PI-th2;
1630  else if(X[2]<0.0) th2=-th2;
1631 
1632  // determine theta0
1633  // JET3COORDS-based:
1634  // myhslope=2.0-bp_Qjet*pow(V[1]/bp_r1jet,-bp_njet1*(0.5+1.0/M_PI*atan(V[1]/bp_r0jet-bp_rsjet/bp_r0jet)));
1635  myhslope=hslope;
1636  // myhslope here is h0 in MCAF paper
1637 
1638 
1639  // th0 = M_PI * .5 * (1. + (1.-((1. - myhslope) * 0.5))*(2.*X[2]-1.) + ((1. - myhslope) * 0.5)*pow(2.*X[2]-1.,9) ) ; // MARKTODODONE switched to poly type from Noble+ 2010 on June 10, 2013
1640  FTYPE xi=((1. - myhslope) * 0.5);
1641  // th0 = M_PI * .5 * (1. + (1.-xi)*(2.*X[2]-1.) + xi*pow(2.*X[2]-1.,9) ) ; // MARKTODODONE switched to poly type from Noble+ 2010 on June 10, 2013
1642  //switchinner0 = 0.5+1.0/M_PI*atan((V[1]-bp_rsinner)/bp_r0inner); // switch in .nb file
1643  //switchinner2 = 0.5-1.0/M_PI*atan((V[1]-bp_rsinner)/bp_r0inner); // switchi in .nb file
1644 
1645  //th0 = M_PI * .5 * (.2*(2.0*X[2]-1.0) + (1.0-.2)*pow(2.0*X[2]-1.0,9.0)+1.) ;
1646  /*
1647  if(X[2]>=.5){
1648  thetasign=+1.0;
1649  x2temp=X[2];
1650  }
1651  else {
1652  thetasign=-1.0;
1653  x2temp=1.0-X[2];
1654  }
1655  */
1656  th0 = M_PI * .5 * (.11875*(1.+(bp_rsinner/V[1]))*(2.0*X[2]-1.0) +(1.0-.11875*(1.+(bp_rsinner/V[1])))*pow(2.0*X[2]-1.0,9.0)+1.) ; // .1096=.1425/(1+6/20) -- .11875 is .1425/(1+4/20) --- .17 is .2/(1.+4/15.)
1657  // if(X[2]>=0.5 && (mycpupos[2]==ncpux2/2 && ncpux2>1 || ncpux2==1)) printf("at radius %21.15g and X[2] = %21.15g the diff is %21.15e\n",V[1],X[2],th0toprint);
1658 
1659  // th0 = M_PI * .5 * (.2*(2.0*X[2]-1.0) + (1.0-.2)*pow(2.0*X[2]-1.0,9.0)+1.) ;
1660 
1661  // determine switches (only function of radius and not x2 or theta)
1662  switch0 = 0.5+1.0/M_PI*atan((V[1]-bp_rs)/bp_r0); // switch in .nb file
1663  switch2 = 0.5-1.0/M_PI*atan((V[1]-bp_rs)/bp_r0); // switchi in .nb file
1664 
1665  // this works because all functions are monotonic, so final result is monotonic. Also, th(x2=1)=Pi and th(x2=0)=0 as required
1666  theta1 = th0*switch2 + th2*switch0; // th0 is activated for small V[1] and th2 is activated at large radii. Notice that sum of switch2+switch0=1 so normalization correct.
1667 
1668 #endif
1669 
1670 #if(1)
1671  // fix_3dpoledtissue.nb based:
1672  theta2 = M_PI*0.5*(.11875*(1.+(bp_rsinner/V[1]))*(2.0*X[2]-1.0)+(1.0-.11875*(1.+(bp_rsinner/V[1])))*pow(2.0*X[2]-1.0,bp_ntheta)+1.0);
1673 
1674  // generate interpolation factor
1675  arctan2 = 0.5 + 1.0/M_PI*(atan( (V[1]-bp_rsjet2)/bp_r0jet2) ); // MAVARA: outside a certain radius this switches the v2 dependence from theta2 to theta1....known as interpolation. this interpolation fixes pole issue. previous involving switch0/2 involves more fundamental difference in vertical distribution.
1676 
1677  // now interpolate between them
1678  V[2] = theta2 + arctan2*(theta1-theta2);
1679 #else
1680  V[2] = theta1;
1681 #endif
1682 
1683 
1684  // default is uniform \phi grid
1685  V[3]=2.0*M_PI*X[3];
1686  }
1687  else if (defcoord == JET5COORDS) {
1688 
1689  // radial grid
1690  ii=X[1]*((FTYPE)totalsize[1]); // assume X[1]=0..1 for active grid going from Rin to Rout
1691 
1692  // radial arctan
1693  radialarctan=(1.0/2.0) + (1.0/M_PI)*atan((ii-ii0)/CCCC);
1694 
1695  // merge of exp grid and exp-exp grid
1696 
1697  // first term is normal exp, second term is exp-exp
1698  logform = AAA*ii + exp(BBB+DDD*ii)*radialarctan;
1699 
1700  // final radius
1701  V[1] = AAAA+exp(logform);
1702 
1703 
1704 
1705 
1707  // \theta grid
1708 
1709  // theta arctan
1710  thetaarctan=(1.0/2.0) + (1.0/M_PI)*atan((V[1]-rsjet)/r0jet);
1711 
1712  // h(r)
1713  myhslope=2.0-Qjet*pow(V[1]/r1jet,-njet*thetaarctan);
1714 
1715  // final theta
1716  if(X[2]<0.5){
1717  V[2] = M_PI * X[2] + ((1. - myhslope) / 2.) * mysin(2. * M_PI * X[2]);
1718  }
1719  else{
1720  V[2] = M_PI - (M_PI * (1.0-X[2])) + ((1. - myhslope) / 2.) * (-mysin(2. * M_PI * (1.0-X[2])));
1721  }
1722 
1724  // \phi grid
1725  // default is uniform \phi grid
1726  V[3]=2.0*M_PI*X[3];
1727 
1728  }
1729  else if (defcoord == JET6COORDSTHIN) {
1730 
1731 #if(0) // no change in exponentiation
1732  // JET3COORDS-like radial grid
1733  V[1] = R0+exp(pow(X[1],th_npow)) ;
1734 #else
1735 
1736  theexp = th_npow*X[1];
1737  if( X[1] > th_x1br ) {
1738  theexp += th_cpow2 * pow(X[1]-th_x1br,th_npow2);
1739  }
1740  V[1] = R0+exp(theexp);
1741 
1742 
1743  // FTYPE npowtrue,npowlarger=10.0;
1744  // FTYPE th_npowrs=1E3;
1745  // FTYPE th_npowr0=2E2;
1746  // npowtrue = th_npow + (npowlarger-th_npow)*(0.5+1.0/M_PI*atan((V[1]-th_npowrs)/th_npowr0));
1747  // V[1] = R0+exp(pow(X[1],npowtrue)) ;
1748 #endif
1749 
1750 
1751 
1752  FTYPE theta1,theta2,arctan2;
1753 
1754 
1755 #if(0)
1756  // JET3COORDS-based:
1757  myhslope=2.0-th_Qjet*pow(V[1]/th_r1jet,-th_njet*(0.5+1.0/M_PI*atan(V[1]/th_r0jet-th_rsjet/th_r0jet)));
1758  theta1 = M_PI * X[2] + ((1. - myhslope) * 0.5) * mysin(2. * M_PI * X[2]);
1759 #else
1760  // RAMESH BASED
1761  // myhslope here is h2 in MCAF paper
1762  // // h0 here is h3 in MCAF paper
1763  //FTYPE njetvsr;
1764  //if(V[1]<th_rbr) njetvsr=th_njet;
1765  // else njetvsr=th_njet/(V[1])*th_rbr;
1766  //else njetvsr=
1767  //njetvsr=th_njet;
1768 
1769  if(V[1]<th_rbr){
1770  myhslope=th_h0 + pow( (V[1]-th_rsjet3)/th_r0jet3 , th_njet);
1771  }
1772  else myhslope=th_h0 + pow( (th_rbr-th_rsjet3)/th_r0jet3 , th_njet);
1773 
1774  // determine theta2
1775  if(X[2]>1.0) myx2=2.0-X[2];
1776  else if(X[2]<0.0) myx2=-X[2];
1777  else myx2=X[2];
1778 
1779  th2 = 0.5*M_PI*(1.0 + atan(myhslope*(myx2-0.5))/atan(myhslope*0.5));
1780 
1781  if(X[2]>1.0) th2=2.0*M_PI-th2;
1782  else if(X[2]<0.0) th2=-th2;
1783 
1784  // determine theta0
1785  // JET3COORDS-based:
1786  if(V[1]<th_rbr){
1787  myhslope=2.0-th_Qjet*pow(V[1]/th_r1jet,-th_njet*(0.5+1.0/M_PI*atan(V[1]/th_r0jet-th_rsjet/th_r0jet)));
1788  }
1789  else myhslope=2.0-th_Qjet*pow(th_rbr/th_r1jet,-th_njet*(0.5+1.0/M_PI*atan(th_rbr/th_r0jet-th_rsjet/th_r0jet)));
1790 
1791 
1792  if(0){
1793  // myhslope here is h0 in MCAF paper
1794  th0 = M_PI * X[2] + ((1. - myhslope) * 0.5) * mysin(2. * M_PI * X[2]);
1795  }
1796  if(1){
1797  // poly grid
1798  FTYPE xi=((1. - myhslope) * 0.5);
1799  th0 = M_PI * .5 * (myhslope*(2.0*X[2]-1.0) + (1.0-myhslope)*pow(2.0*X[2]-1.0,9.0)+1.);
1800  }
1801 
1802  // determine switches (only function of radius and not x2 or theta)
1803  switch0 = 0.5+1.0/M_PI*atan((V[1]-th_rs)/th_r0); // switch in .nb file
1804  switch2 = 0.5-1.0/M_PI*atan((V[1]-th_rs)/th_r0); // switchi in .nb file
1805 
1806  // this works because all functions are monotonic, so final result is monotonic. Also, th(x2=1)=Pi and th(x2=0)=0 as required
1807  theta1 = th0*switch2 + th2*switch0; // th0 is activated for small V[1] and th2 is activated at large radii. Notice that sum of switch2+switch0=1 so normalization correct.
1808 
1809 #endif
1810 
1811  // fix_3dpoledtissue.nb based:
1812  theta2 = M_PI*0.5*(th_htheta*(2.0*X[2]-1.0)+(1.0-th_htheta)*pow(2.0*X[2]-1.0,th_ntheta)+1.0);
1813 
1814  // generate interpolation factor
1815  arctan2 = 0.5 + 1.0/M_PI*(atan( (V[1]-th_rsjet2)/th_r0jet2) );
1816 
1817  // now interpolate between them
1818  V[2] = theta2 + arctan2*(theta1-theta2);
1819 
1820 
1821 
1822  // default is uniform \phi grid
1823  V[3]=2.0*M_PI*X[3];
1824  }
1825  else if (defcoord == JET5COORDS) {
1826 
1827  // radial grid
1828  ii=X[1]*((FTYPE)totalsize[1]); // assume X[1]=0..1 for active grid going from Rin to Rout
1829 
1830  // radial arctan
1831  radialarctan=(1.0/2.0) + (1.0/M_PI)*atan((ii-ii0)/CCCC);
1832 
1833  // merge of exp grid and exp-exp grid
1834 
1835  // first term is normal exp, second term is exp-exp
1836  logform = AAA*ii + exp(BBB+DDD*ii)*radialarctan;
1837 
1838  // final radius
1839  V[1] = AAAA+exp(logform);
1840 
1841 
1842 
1843 
1845  // \theta grid
1846 
1847  // theta arctan
1848  thetaarctan=(1.0/2.0) + (1.0/M_PI)*atan((V[1]-rsjet)/r0jet);
1849 
1850  // h(r)
1851  myhslope=2.0-Qjet*pow(V[1]/r1jet,-njet*thetaarctan);
1852 
1853  // final theta
1854  if(X[2]<0.5){
1855  V[2] = M_PI * X[2] + ((1. - myhslope) / 2.) * mysin(2. * M_PI * X[2]);
1856  }
1857  else{
1858  V[2] = M_PI - (M_PI * (1.0-X[2])) + ((1. - myhslope) / 2.) * (-mysin(2. * M_PI * (1.0-X[2])));
1859  }
1860 
1862  // \phi grid
1863  // default is uniform \phi grid
1864  V[3]=2.0*M_PI*X[3];
1865 
1866  }
1867  else if (defcoord == PULSARCOORDS) {
1868  V[1] = R0+exp(pow(X[1],npow)) ;
1869 
1870  myhslope=(0.5+1.0/M_PI*atan((V[1]-rsjet)/r0jet))*(houter-hinner)+hinner;
1871 
1872  if(X[2]<0.5){
1873  V[2] = M_PI * X[2] + ((1. - myhslope) / 2.) * mysin(2. * M_PI * X[2]);
1874  }
1875  else{
1876  V[2] = M_PI - (M_PI * (1.0-X[2])) + ((1. - myhslope) / 2.) * (-mysin(2. * M_PI * (1.0-X[2])));
1877  }
1878  // default is uniform \phi grid
1879  V[3]=2.0*M_PI*X[3];
1880  }
1881  else if (defcoord == UNIFORMCOORDS) {
1882  //uniform grid for Cartesian coordinates
1883  V[1] = Rin_array[1] + X[1] * ( Rout_array[1] - Rin_array[1] );
1884  V[2] = Rin_array[2] + X[2] * ( Rout_array[2] - Rin_array[2] );
1885  V[3] = Rin_array[3] + X[3] * ( Rout_array[3] - Rin_array[3] );
1886  }
1887  else if (defcoord == BILOGCYLCOORDS) {
1888  // R : cylindrical radius, assumes X[1]=0..1
1889  // exponential grid
1890  V[1] = ((Rout-Rin)*exp(npow*X[1])+Rin*exp(npow)-Rout)/(exp(npow)-1.0);
1891 
1892  // z : cylindrical height, assumes X[2]=-1..1
1893  // bi-exponential grid
1894  // here the grid goes from Zin to Zout in a bi-log way, and X[2]=0 is Z=0
1895  if(X[2]>0.0) V[2] = ((Zout-0)*exp(npow*fabs(X[2])) + 0*exp(npow)-Zout)/(exp(npow)-1.0);
1896  else V[2] = ((Zin-0)*exp(npow*fabs(X[2])) + 0*exp(npow)-Zin)/(exp(npow)-1.0);
1897 
1898  }
1900  V[1] = R0+exp(pow(X[1],npow)) ;
1901 
1902  myhslope=pow( (V[1]-rsjet)/r0jet , njet);
1903 
1904  if(X[2]>1.0) myx2=2.0-X[2];
1905  else if(X[2]<0.0) myx2=-X[2];
1906  else myx2=X[2];
1907 
1908  V[2] = 0.5*M_PI*(1.0 + atan(myhslope*(myx2-0.5))/atan(myhslope*0.5));
1909 
1910  if(X[2]>1.0) V[2]=2.0*M_PI-V[2];
1911  else if(X[2]<0.0) V[2]=-V[2];
1912 
1913  // default is uniform \phi grid
1914  V[3]=2.0*M_PI*X[3];
1915 
1916 
1917  }
1918  else if (defcoord == JET4COORDS) {
1919 
1920 
1921 #if(0)
1922  // combines RAMESHCOORDS with original simple SINTH grid
1923 
1924  if(BCtype[X1DN]==R0SING){
1925  if(R0>=0.0){
1926  dualfprintf(fail_file,"With log grid and R0SING must have R0<0 instead of %26.20g\n",R0);
1927  myexit(8274);
1928  }
1929  X0 = log(-R0);
1930  if(X[1]>X0) V[1] = R0+exp(X[1]) ;
1931  else V[1] = -(R0+R0*R0*exp(-X[1])) ;
1932  // dualfprintf(fail_file,"X0=%26.20g V[1]=%26.20g\n",X0,V[1]);
1933  }
1934  else{
1935  V[1] = R0+exp(X[1]) ;
1936  // if V[1]=r<0 here, the presume only where interpolation boundaries are, not evolved quantities, and not extending so far negative radius that reach beyond, e.g. light cylinder so that velocities will be undefined with simple extrapolation
1937  }
1938 #else
1939  // JET3COORDS-like radial grid
1940  V[1] = R0+exp(pow(X[1],npow)) ;
1941 #endif
1942 
1943 
1944 
1945  myhslope=h0 + pow( (V[1]-rsjet)/r0jet , njet);
1946 
1947  // determine theta2
1948  if(X[2]>1.0) myx2=2.0-X[2];
1949  else if(X[2]<0.0) myx2=-X[2];
1950  else myx2=X[2];
1951 
1952  th2 = 0.5*M_PI*(1.0 + atan(myhslope*(myx2-0.5))/atan(myhslope*0.5));
1953 
1954  if(X[2]>1.0) th2=2.0*M_PI-th2;
1955  else if(X[2]<0.0) th2=-th2;
1956 
1957  // determine theta0
1958  myhslope=hslope;
1959 
1960  if(X[2]<0.5){
1961  th0 = M_PI * X[2] + ((1. - myhslope) / 2.) * mysin(2. * M_PI * X[2]);
1962  }
1963  else{
1964  th0 = M_PI - (M_PI * (1.0-X[2])) + ((1. - myhslope) / 2.) * (-mysin(2. * M_PI * (1.0-X[2])));
1965  }
1966 
1967  // determine switches (only function of radius and not x2 or theta)
1968  switch0 = 0.5+1.0/M_PI*atan((V[1]-rs)/r0); // switch in .nb file
1969  switch2 = 0.5-1.0/M_PI*atan((V[1]-rs)/r0); // switchi in .nb file
1970 
1971  FTYPE theta1,theta2,arctan2;
1972 
1973  // this works because all functions are monotonic, so final result is monotonic. Also, th(x2=1)=Pi and th(x2=0)=0 as required
1974  theta1 = th0*switch2 + th2*switch0; // th0 is activated for small V[1] and th2 is activated at large radii. Notice that sum of switch2+switch0=1 so normalization correct.
1975 
1976  // fix_3dpoledtissue.nb based:
1977  theta2 = M_PI*0.5*(htheta*(2.0*X[2]-1.0)+(1.0-htheta)*pow(2.0*X[2]-1.0,ntheta)+1.0);
1978 
1979  // generate interpolation factor
1980  arctan2 = 0.5 + 1.0/M_PI*(atan( (V[1]-rsjet2)/r0jet2) );
1981 
1982  // now interpolate between them
1983  V[2] = theta2 + arctan2*(theta1-theta2);
1984 
1985 
1986 
1987 
1988  // default is uniform \phi grid
1989  V[3]=2.0*M_PI*X[3];
1990 
1991 
1992  }
1993  else if (defcoord == UNI2LOG) {
1994 
1995 
1996  if(BCtype[X1DN]==R0SING && X[1]<0.0){
1997  mysign=-1.0;
1998  }
1999  else{
2000  mysign=1.0;
2001  }
2002  ts1 = (FTYPE)totalsize[1];
2003  fnstar = ((FTYPE)Nstar);
2004  myNrat = ts1/(fnstar+SMALL);
2005 
2006 
2007  if( Nstar==0 || fabs(X[1])>=1.0/myNrat ){ // same as if(fabs(i)>=Nstar)
2008  // log grid (similar to UNIRSINTH, but now such that startx=0 and dx=1/totalsize[1] and starts at Rstar and arbitrary growth factor Afactor)
2009  V[1] = mysign*(Rstar + (Rout-Rstar)*(pow(Afactor, (fabs(X[1])*ts1-fnstar)/(ts1-fnstar))-1.0)/(Afactor-1.0));
2010  }
2011  else{
2012  // see UNI2LOGgrid.nb in mathematica
2013  //
2014  // uniform grid (sign is correct already with uniform grid)
2015  // V[1] = Rin + (Rstar-Rin)*myNrat*X[1]; // purely uniform grid leads to big connection coefficient at i=Nstar-1
2016  // so use smoother transition
2017  // i/Nstar = x1*totalsize[1]/Nstar = x1*myNrat
2018  // sign is not correct for this grid, so fix it
2019  BB = ( (Rout-Rstar)*log(Afactor)/( (Afactor-1.0)*(myNrat-1.0) ) );
2020  CC = BB + (Rin-Rstar);
2021  V[1] = mysign*( Rstar + BB*(fabs(X[1])*myNrat-1.0) + CC*(fabs(X[1])*myNrat-1.0)*(fabs(X[1])*myNrat-1.0) );
2022  }
2023 
2024  // fully express r=0 coordinate singularity
2025  // V[1]\sim 1E-14 if don't do this, and then gdet!=0 at r=0 and then flux through r=0 causes MBH and $a$ to be computed wrong.
2026  if(BCtype[X1DN]==R0SING && fabs(V[1]-10.0*NUMEPSILON)<10.0*NUMEPSILON ){
2027  V[1] = 0.0; // so coordinate singularity is fully represented in metric, etc.
2028  }
2029 
2030 
2031 
2032 
2033  // x2-direction
2034 
2035 
2036 
2037  if(X[2]<0.5){
2038  V[2] = M_PI * X[2] + ((1. - hslope) / 2.) * mysin(2. * M_PI * X[2]);
2039  }
2040  else{
2041  // V[2] = 0.5*M_PI + M_PI * fabs(X[2]-0.5) + ((1. - hslope) / 2.) * (-mysin(2. * M_PI * (1.0-X[2])));
2042  V[2] = M_PI - (M_PI * (1.0-X[2])) + ((1. - hslope) / 2.) * (-mysin(2. * M_PI * (1.0-X[2])));
2043  }
2044 
2045  // x3-direction
2046 
2047 
2048  // default is uniform \phi grid
2049  V[3]=2.0*M_PI*X[3];
2050 
2051  }
2052  else{
2053  dualfprintf(fail_file,"Shouldn't reach end of bl_coord: defcoord=%d\n",defcoord);
2054  myexit(1);
2055  }
2056 
2057 
2058 
2059 
2060 
2061 
2062 
2063 
2064  blcoord_singfixes(X,V);
2065 
2066 
2067 }
2068 
2070 {
2071 
2073  //
2074  // don't allow to be smaller to avoid singularity
2075  // noted this caused problems with jon_interp in calculating jacobian
2076  //
2078  if(POSDEFMETRIC){
2079  if(V[2]<0) V[2] = -V[2];
2080  if(V[2]>M_PI) V[2]=2.0*M_PI-V[2];
2081 
2082  if(V[3]<0) V[3] = -V[3];
2083  if(V[3]>2.0*M_PI) V[3]=4.0*M_PI-V[3];
2084 
2085  }
2086 
2087 
2088 #if( COORDSINGFIXCYL ) //SUPERSASMARK fix the singularity for the cylinrical coordinates
2089  // NOTEMARK: just shifting (e.g.) i=0 cell up a bit, nothing else to do. Assume only 1 grid cell (in "i") is there within such tolerance of SINGSMALL
2090  if(fabs(V[1]-0.0)<SINGSMALL) V[1]=SINGSMALL;
2091 #endif
2092 
2093 
2095  // avoid polar axis if SPC. Also used for CTSTAG approach so can evolve B2
2096 #if(1)
2097  // So use X[2] only -- closer to using j itself that we don't have available.
2098  if(BCtype[X2DN]==POLARAXIS && fabs(startx[TH]-X[TH])<SINGSMALL) V[TH]=SINGSMALL;
2099  FTYPE endx2=startx[TH]+totalsize[TH]*dx[TH];
2100  if(BCtype[X2UP]==POLARAXIS && fabs(endx2-X[TH])<SINGSMALL) V[TH]=M_PI-SINGSMALL;
2101 #endif
2102 #if(0)
2103  // OK, but worry about large radii where \theta is small towards axis
2104  if (BCtype[X2DN]==POLARAXIS && fabs(V[TH]) < SINGSMALL) V[TH]+=SINGSMALL;
2105  else if (BCtype[X2UP]==POLARAXIS && fabs(M_PI-V[TH]) < SINGSMALL) V[TH]-=SINGSMALL;
2106 #endif
2107 #if(0)
2108  // WRONG!
2109  if (BCtype[X2DN]==POLARAXIS && fabs(V[TH]) < SINGSMALL){
2110  if(V[TH]>=0) V[TH]=SINGSMALL;
2111  if(V[TH]<0) V[TH]=-SINGSMALL;
2112  }
2113  if (BCtype[X2UP]==POLARAXIS && fabs(M_PI-V[TH]) < SINGSMALL){
2114  if(V[TH]>=M_PI) V[TH]=M_PI+SINGSMALL;
2115  if(V[TH]<M_PI) V[TH]=M_PI-SINGSMALL;
2116  }
2117 #endif
2118 
2119  }
2120 
2121 }
2122 
2123 
2125 void vofx_sjetcoords( FTYPE *X, FTYPE *V )
2126 {
2127  //for SJETCOORDS
2128  FTYPE theexp;
2129  FTYPE Ftrgen( FTYPE x, FTYPE xa, FTYPE xb, FTYPE ya, FTYPE yb );
2130  FTYPE limlin( FTYPE x, FTYPE x0, FTYPE dx, FTYPE y0 );
2131  FTYPE minlin( FTYPE x, FTYPE x0, FTYPE dx, FTYPE y0 );
2132  FTYPE mins( FTYPE f1, FTYPE f2, FTYPE df );
2133  FTYPE maxs( FTYPE f1, FTYPE f2, FTYPE df );
2134  FTYPE thetaofx2(FTYPE x2, FTYPE ror0nu);
2135  FTYPE fac, faker, ror0nu;
2136  FTYPE fakerdisk, fakerjet;
2137  FTYPE rbeforedisk, rinsidedisk, rinsidediskmax, rafterdisk;
2138 
2139 #define DOIMPROVEJETCOORDS 1
2140 #if(DOIMPROVEJETCOORDS)
2141  FTYPE ror0nudisk, ror0nujet, thetadisk, thetajet;
2142 #endif
2143 
2144  V[0] = X[0];
2145 
2146  theexp = npow*X[1];
2147 
2148  if( X[1] > x1br ) {
2149  theexp += cpow2 * pow(X[1]-x1br,npow2);
2150  }
2151  V[1] = R0+exp(theexp);
2152 
2153 #if(0) //JON's method
2154  myhslope=2.0-Qjet*pow(V[1]/r1jet,-njet*(0.5+1.0/M_PI*atan(V[1]/r0grid-rsjet/r0grid)));
2155 
2156  if(X[2]<0.5){
2157  V[2] = M_PI * X[2] + ((1. - myhslope) / 2.) * mysin(2. * M_PI * X[2]);
2158  }
2159  else{
2160  V[2] = M_PI - (M_PI * (1.0-X[2])) + ((1. - myhslope) / 2.) * (-mysin(2. * M_PI * (1.0-X[2])));
2161  }
2162 #elif(1) //SASHA's
2163  fac = Ftrgen( fabs(X[2]), fracdisk, 1-fracjet, 0, 1 );
2164 
2165  //faker = fac*V[1] + (1 - fac)*limlin(V[1],r0disk,0.5*r0disk,r0disk)*minlin(V[1],rdiskend,0.5*rdiskend,r0disk)/r0disk - rsjet*Rin;
2166 
2167  rbeforedisk = mins( V[1], r0disk, 0.5*r0disk );
2168 #if(USESJETLOGHOVERR)
2169  //rinsidedisk = 1 for r < torusrmax_loc and increases logarithmically while r <= rdiskend, after which it
2170  //levels off to the value = rinsidediskmax
2171  rinsidedisk = pow( 1. + 0.5*log10(mins(maxs(1,V[1]/torusrmax_loc,0.5),rdiskend/torusrmax_loc,0.5*rdiskend/torusrmax_loc)), 2./jetnu );
2172  rinsidediskmax = pow( 1. + 0.5*log10(rdiskend/torusrmax_loc), 2./jetnu);
2173 #else
2174  rinsidedisk = 1.;
2175  rinsidediskmax = 1.;
2176 #endif
2177  rafterdisk = maxs( 1, 1 + (V[1]-rdiskend)*r0jet/(rjetend*r0disk*rinsidediskmax), 0.5*rdiskend*r0jet/(rjetend*r0disk*rinsidediskmax) );
2178 
2179  fakerdisk = rbeforedisk * rinsidedisk * rafterdisk;
2180 
2181  fakerjet = mins( V[1], r0jet, 0.5*r0jet ) * maxs( 1, V[1]/rjetend, 0.5 );
2182 
2183 #if( DOIMPROVEJETCOORDS )
2184  ror0nudisk = pow( (fakerdisk - rsjet*Rin)/r0grid, jetnu/2 );
2185  ror0nujet = pow( (fakerjet - rsjet*Rin)/r0grid, jetnu/2 );
2186  thetadisk = thetaofx2( X[2], ror0nudisk );
2187  thetajet = thetaofx2( X[2], ror0nujet );
2188  V[2] = fac*thetajet + (1 - fac)*thetadisk;
2189 #else
2190  faker = fac*fakerjet + (1 - fac)*fakerdisk - rsjet*Rin;
2191  ror0nu = pow( faker/r0grid, jetnu/2 );
2192  V[2] = thetaofx2( X[2], ror0nu );
2193 #endif
2194 
2195 
2196 
2197 
2198 #else
2199  //if((1+X[2])/2.<0.5){
2200  // V[2] = M_PI * (1+X[2])/2. + ((1. - hslope) / 2.) * mysin(2. * M_PI * (1+X[2])/2.);
2201  //}
2202  //else{
2203  // // V[2] = 0.5*M_PI + M_PI * fabs(X[2]-0.5) + ((1. - hslope) / 2.) * (-mysin(2. * M_PI * (1.0-X[2])));
2204  // V[2] = M_PI - (M_PI * (1.0-(1+X[2])/2.)) + ((1. - hslope) / 2.) * (-mysin(2. * M_PI * (1.0-(1+X[2])/2.)));
2205  //}
2206  V[2] = M_PI_2l * (1.0+ X[2]);
2207 #endif
2208 
2209  // default is uniform \phi grid
2210  V[3]=2.0*M_PI*X[3];
2211 }
2212 
2213 
2216 {
2217  FTYPE theta;
2218  if( x2 < -0.5 ) {
2219  theta = 0 + atan( tan((x2+1)*M_PI_2l)/ror0nu );
2220  }
2221  else if( x2 > 0.5 ) {
2222  theta = M_PI + atan( tan((x2-1)*M_PI_2l)/ror0nu );
2223  }
2224  else {
2225  theta = M_PI_2l + atan( tan(x2*M_PI_2l)*ror0nu );
2226  }
2227  return(theta);
2228 }
2229 
2230 
2239 void dxdxprim(FTYPE *X, FTYPE *V, FTYPE (*dxdxp)[NDIM])
2240 {
2241  void dxdxp_numerical(FTYPE *X, FTYPE (*dxdxp)[NDIM]);
2242  void dxdxp_analytic(FTYPE *X, FTYPE *V, FTYPE (*dxdxp)[NDIM]);
2243 
2244  if(defcoord<ANALYTICSWITCH){ // then have analytic dxdxp
2245  dxdxp_analytic(X,V,dxdxp);
2246  }
2247  else{
2249  }
2250 
2251  if(ISSPCMCOORD(MCOORD)){
2252  // below is because \int_0^\theta sin\theta d\theta d\phi is approximated as locally instead of finite volume
2253  if(totalsize[2]==1 && FIXGDETSPC_WHEN_1DRADIAL){
2254  dxdxp[2][2] = 2.0/dx[2]; // so that d\theta = 2
2255  }
2256 
2257 #if(1)
2258  // dxdxp[2][1] changes sign across axis if consistently decollimate/collimate grid. Yet, this will cause gv311 [primecoords] to be asymmetric for any given theta,phi when theta goes negative or beyond \pi.
2259  // To have correct symmetries in true SPC (not just extended \theta meanginless domain) must change sign and use FLIPU3AXIS 0 , FLIPB3AXIS 0 , FLIPU2AXIS 0 , and FLIPB2AXIS 0 .
2260  // This is the only way (e.g.) uu1 will be properly symmetric at respective theta,\phi positions when including ghost zones. EMF needs v1=uu1/u0, so symmetry requires this to be correct.
2261  // This forces symmetry on primitives across pole, but may be bad for interpolation unless flip sign when doing interpolation itself.
2262  FTYPE endx2=startx[TH]+totalsize[TH]*dx[TH];
2263  if(X[2]<startx[2] || X[2]>endx2){
2264  dxdxp[2][0]*=-1.0;
2265  dxdxp[2][1]*=-1.0;
2266  dxdxp[2][3]*=-1.0;
2267  }
2268 #endif
2269 
2270  }
2271 
2272 }
2273 
2274 
2275 
2276 
2277 
2279 void dxdxp_analytic(FTYPE *X, FTYPE *V, FTYPE (*dxdxp)[NDIM])
2280 {
2281  int j,k;
2282  extern FTYPE mycos(FTYPE th);
2283  extern FTYPE mysin(FTYPE th);
2284  FTYPE myhslope1,myhslope2,myhslope;
2285  FTYPE dmyhslopedr,dmyhslopedx1;
2286  FTYPE myx2;
2287  FTYPE flip1,flip2;
2288  FTYPE th0,th2,switch0,switch2;
2289  FTYPE r,dtheta2dx1,dtheta2dx2,dtheta0dx2,dtheta0dx1,dswitch0dr,dswitch2dr;
2290  FTYPE X0;
2291  // for defcoord=JET5COORDS
2292  FTYPE ii,logform,radialarctan,thetaarctan; // temp vars
2293 
2294 
2295 
2296  // default identity transformation
2297  DLOOP(j,k) dxdxp[j][k]=0.0;
2298  DLOOPA(j) dxdxp[j][j]=1.0;
2299 
2300  if (defcoord == USERCOORD) {
2301  extern void dxdxp_analytic_user(FTYPE *X, FTYPE *V, FTYPE (*dxdxp)[NDIM]);
2303  }
2304  else if (defcoord == LOGRSINTH) {
2305  dxdxp[1][1] = V[1]-R0;
2306  if(X[2]<0.5){
2307  dxdxp[2][2] = M_PI + (1. - hslope) * M_PI * mycos(2. * M_PI * X[2]);
2308  }
2309  else{
2310  dxdxp[2][2] = M_PI + (1. - hslope) * M_PI * mycos(2. * M_PI * (1.0-X[2]) );
2311  }
2312  dxdxp[3][3] = 2.0*M_PI;
2313  }
2314  else if (defcoord == REBECCAGRID) {
2315  dxdxp[1][1] = V[1]-R0;
2316  dxdxp[2][2]=M_PI/2.*( (hslope * X[2])/0.5 + (7. * (1-hslope))/(pow(0.5, 7.)) *pow(X[2]-0.5, 6.)) ;
2317 
2318  // if(X[2]<0.5){
2319  // dxdxp[2][2] = M_PI + (1. - hslope) * M_PI * mycos(2. * M_PI * X[2]);
2320  // }
2321  // else{
2322  // dxdxp[2][2] = M_PI + (1. - hslope) * M_PI * mycos(2. * M_PI * (1.0-X[2]) );
2323  // }
2324  dxdxp[3][3] = 0.5*M_PI;
2325  }
2326  else if (defcoord == COMPLEX0TH) {
2327  dxdxp[1][1] = (V[1]-R0) * log(Rout / Rin);
2328 
2329  dxdxp[2][2] = (-49. * hslope + 60. * M_PI) / 12. +
2330  ((247. * hslope - 240. * M_PI) * X[2]) / 6. +
2331  (3. * (-83. * hslope + 80. * M_PI) * pow(X[2], 2)) / 2. -
2332  (20. * (-25. * hslope + 24. * M_PI) * pow(X[2], 3)) / 3. +
2333  (10. * (-25. * hslope + 24. * M_PI) * pow(X[2], 4)) / 3.;
2334 
2335  dxdxp[3][3] = 2.0*M_PI;
2336 
2337  } else if(defcoord == UNIRSINTH || defcoord == UNIRSINTH2){
2338  dxdxp[2][2] = (totalsize[2]==1) ? (2.0) : (M_PI + (1. - hslope) * M_PI * cos(2. * M_PI * X[2]));
2339  dxdxp[3][3] = 2.0*M_PI;
2340  }
2341  else if (defcoord == EQMIRROR) {
2342  dxdxp[1][1] = V[1]-R0;
2343  dxdxp[2][2] = M_PI + (1. - hslope) * M_PI * cos(2. * M_PI * X[2]);
2344  dxdxp[3][3] = 2.0*M_PI;
2345  }
2346  else if (defcoord == COMPLEX1TH) {
2347  dxdxp[1][1] = V[1]-R0;
2348  dxdxp[2][2] = (210.*M_PI*Ri*pow(1. - 2.*X[2],2.)*pow(-1. + X[2],2.)*
2349  pow(X[2],2.) + der0*
2350  (-32.*pow(-1. + X[2],2.)*pow(X[2],2.)*
2351  (3. + 14.*(-1. + X[2])*X[2]) -
2352  Ri*pow(1. - 2.*X[2],2.)*
2353  (-1. + 2.*(-1. + X[2])*X[2]*(2. + 49.*(-1. + X[2])*X[2]))))/Ri;
2354  dxdxp[3][3] = 2.0*M_PI;
2355  }
2356  else if(defcoord == COMPLEX2TH) {
2357  dxdxp[1][1] = V[1]-R0;
2358 
2359  // now assign values
2360  if(X[2]<0.5){ myx2=X[2]; flip1=0.0; flip2=1.0;}
2361  else{ myx2=1.0-X[2]; flip1=M_PI; flip2=-1.0;}
2362 
2363  if(myx2<=x2trans){
2364  dxdxp[2][2] = (3.0*d2*pow(myx2,2.0)+2.0*c2*pow(myx2,1.0)+m2);
2365  }
2366  else{
2367  dxdxp[2][2] = (m3);
2368  }
2369 
2370 
2371  dxdxp[3][3] = 2.0*M_PI;
2372 
2373 
2374  }
2375  else if (defcoord == LOGRUNITH) {
2376  dxdxp[1][1] = V[1]-R0;
2377  dxdxp[2][2] = Rout_array[2] - Rin_array[2];
2378  dxdxp[3][3] = Rout_array[3] - Rin_array[3];
2379  }
2380  else if (defcoord == JET1COORDS) {
2381 
2382  //dxdxp[1][1] = npow*(V[1]-R0)*pow(log(V[1]-R0),(npow-1.0)/npow);
2383  dxdxp[1][1] = npow*(V[1]-R0)*pow(X[1],npow-1.0);
2384 
2385  myhslope1 = h0+dmyhslope1dr*(V[1]-rh0);
2386  myhslope2 = h0+dmyhslope2dx1*(X[1]-x1in);
2387 
2388  dmyhslopedx1=0.5*(dmyhslope1dr*dxdxp[1][1]+dmyhslope2dx1);
2389  myhslope=0.5*(myhslope1+myhslope2);
2390 
2391  dxdxp[2][2] = M_PI + (1. - myhslope) * M_PI * cos(2. * M_PI * X[2]);
2392  // d\theta/dx1 not 0
2393  // d\theta/dx1 = (d\theta/dr)*(dr/dx1) (is this generally true or just when V[1](x1)?
2394  dxdxp[2][1] = -0.5*dmyhslopedx1* sin(2. * M_PI * X[2]);
2395 
2396  dxdxp[3][3] = 2.0*M_PI;
2397  }
2398  else if (defcoord == JET2COORDS) {
2399  // drdx1
2400  dxdxp[1][1] = npow*(V[1]-R0)*pow(X[1],npow-1.0);
2401 
2402 
2403  myhslope=2.0-pow(V[1]/r1jet,njet*(-1.0+exp(1.0)/exp(V[1]+rpjet)));
2404 
2405  dmyhslopedr=-((pow(exp(1.0),-V[1] - rpjet)*myhslope*njet*(-exp(1.0) + pow(exp(1.0),V[1] + rpjet) + exp(1.0)*V[1]*log(V[1]/r1jet)))/V[1]);
2406  dmyhslopedx1=dmyhslopedr*dxdxp[1][1];
2407 
2408  dxdxp[2][2] = M_PI + (1. - myhslope) * M_PI * cos(2. * M_PI * X[2]);
2409  dxdxp[2][1] = -0.5*dmyhslopedx1* sin(2. * M_PI * X[2]);
2410  dxdxp[3][3] = 2.0*M_PI;
2411  }
2412  else if(defcoord == JET3COORDS){
2413  // drdx1
2414  dxdxp[1][1] = npow*(V[1]-R0)*pow(X[1],npow-1.0);
2415 
2416 
2417  myhslope=2.0-Qjet*pow(V[1]/r1jet,-njet*(0.5+1.0/M_PI*atan(V[1]/r0jet-rsjet/r0jet)));
2418 
2419  dmyhslopedr=-((Qjet*(-((njet*(0.5 + atan(V[1]/r0jet - rsjet/r0jet)/M_PI))/V[1]) - (njet*r0jet*log(V[1]/r1jet))/(M_PI*(pow(r0jet,2) + pow(V[1] - rsjet,2)))))/pow(V[1]/r1jet,njet*(0.5 + atan(V[1]/r0jet - rsjet/r0jet)/M_PI)));
2420 
2421  dmyhslopedx1=dmyhslopedr*dxdxp[1][1];
2422 
2423  if(X[2]<0.5){
2424  dxdxp[2][2] = M_PI + (1. - myhslope) * M_PI * mycos(2. * M_PI * X[2]);
2425  dxdxp[2][1] = -0.5*dmyhslopedx1* mysin(2. * M_PI * X[2]);
2426  }
2427  else{
2428  dxdxp[2][2] = M_PI + (1. - myhslope) * M_PI * mycos(2. * M_PI * (1.0-X[2]));
2429  dxdxp[2][1] = -0.5*dmyhslopedx1* (-mysin(2. * M_PI * (1.0-X[2])));
2430  }
2431 
2432 
2433  dxdxp[3][3] = 2.0*M_PI;
2434 
2435 
2436 
2437  }
2438  else if(defcoord == JET6COORDS){
2439  dualfprintf(fail_file,"Should not be computing JET6COORDS analytically\n");
2440  myexit(34698346);
2441  dxdxp[3][3] = 2.0*M_PI;
2442  }
2443  else if(defcoord == JET6COORDSTHIN){
2444  dualfprintf(fail_file,"Should not be computing JET6COORDSTHIN analytically\n");
2445  myexit(34698346);
2446  dxdxp[3][3] = 2.0*M_PI;
2447  }
2448  else if(defcoord == BPTHIN1){
2449  dualfprintf(fail_file,"Should not be computing BPTHIN1 analytically\n");
2450  myexit(34698346);
2451  dxdxp[3][3] = 2.0*M_PI;
2452  }
2453  else if(defcoord == JET5COORDS){
2454  dualfprintf(fail_file,"Should not be computing JET5COORDS analytically\n");
2455  myexit(34698346);
2456  dxdxp[3][3] = 2.0*M_PI;
2457  }
2458  else if(defcoord == PULSARCOORDS){
2459  // drdx1
2460  dxdxp[1][1] = npow*(V[1]-R0)*pow(X[1],npow-1.0);
2461 
2462  myhslope=(0.5+1.0/M_PI*atan((V[1]-rsjet)/r0jet))*(houter-hinner)+hinner;
2463  dmyhslopedr=(houter-hinner)*r0jet/(M_PI*(r0jet*r0jet+(V[1]-rsjet)*(V[1]-rsjet)));
2464  dmyhslopedx1=dmyhslopedr*dxdxp[1][1];
2465 
2466  dxdxp[2][2] = M_PI + (1. - myhslope) * M_PI * cos(2. * M_PI * X[2]);
2467  dxdxp[2][1] = -0.5*dmyhslopedx1* sin(2. * M_PI * X[2]);
2468 
2469 
2470 
2471  dxdxp[3][3] = 2.0*M_PI;
2472 
2473 
2474 
2475 
2476 
2477  }
2478  else if (defcoord == UNIFORMCOORDS) {
2479  //uniform grid for Cartesian coordinates
2480  dxdxp[1][1] = Rout_array[1] - Rin_array[1];
2481  dxdxp[2][2] = Rout_array[2] - Rin_array[2];
2482  dxdxp[3][3] = Rout_array[3] - Rin_array[3];
2483  // dualfprintf(fail_file,"COORD.c: dxdxp[1][1]=%26.20g\n",dxdxp[1][1]);
2484  }
2485  else if (defcoord == BILOGCYLCOORDS) {
2486  myexit(6666);
2487  }
2489 
2490 
2491  // V[1] = R0+exp(pow(X[1],npow)) ;
2492  // myhslope=pow( (*r-rsjet)/r0jet , njet);
2493  // V[2] = 0.5*M_PI*(1.0 + atan(myhslope*(X[2]-0.5))/atan(myhslope*0.5));
2494 
2495 
2496  // drdx1
2497  dxdxp[1][1] = npow*(V[1]-R0)*pow(X[1],npow-1.0);
2498  // drdx2 = 0
2499 
2500 
2501  myhslope=pow( (V[1]-rsjet)/r0jet , njet);
2502  dmyhslopedr=(njet/r0jet)*pow( (V[1]-rsjet)/r0jet , njet-1.0);
2503 
2504  if(!finite(dmyhslopedr)){
2505  dualfprintf(fail_file,"Problem with dmyhslopedr=%g\n",dmyhslopedr);
2506  dualfprintf(fail_file,"njet=%g r=%g rsjet=%g r0jet=%g\n",njet,V[1],rsjet,r0jet);
2507  myexit(1);
2508  }
2509 
2510  // dhslope/dx1
2511  dmyhslopedx1=dmyhslopedr*dxdxp[1][1];
2512 
2513 
2514  if(X[2]>1.0) myx2=2.0-X[2];
2515  else if(X[2]<0.0) myx2=-X[2];
2516  else myx2=X[2];
2517 
2518 
2519  // d\theta/dx2
2520  // (2*Pi*h(r))/(ArcTan(h(r)/2.)*(4 + Power(1 - 2*x2,2)*Power(h(r),2)))
2521 
2522  dxdxp[2][2] = (2.0*M_PI*myhslope)/(atan(myhslope*0.5)*(4.0 + pow(1.0 - 2.0*myx2,2.0)*pow(myhslope,2.0)));
2523 
2524 
2525  // d\theta/dr
2526  //(Pi*((-4*ArcTan((-0.5 + x2)*h(r)))/(4 + Power(h(r),2)) +
2527  // (4*(-1 + 2*x2)*ArcTan(h(r)/2.))/
2528  // (4 + Power(1 - 2*x2,2)*Power(h(r),2)))*
2529  // Derivative(1)(h)(r))/(4.*Power(ArcTan(h(r)/2.),2))
2530 
2531 
2532  // d\theta/dx1 = d\theta/dr dr/dx1
2533  dxdxp[2][1] = (M_PI*dmyhslopedx1*(
2534  (-4.0*atan((-0.5 + myx2)*myhslope))/(4. + pow(myhslope,2.)) +
2535  (4.*(-1. + 2.*myx2)*atan(myhslope/2.))/(4. + pow(1. - 2.*myx2,2.)*pow(myhslope,2.))
2536  )
2537  )/(4.*pow(atan(myhslope/2.),2.));
2538 
2539 
2540  if(X[2]>1.0) dxdxp[2][1]*=-1.0;
2541  if(X[2]<0.0) dxdxp[2][1]*=-1.0;
2542 
2543 
2544  dxdxp[3][3] = 2.0*M_PI;
2545 
2546 
2547 
2548  }
2549  else if(defcoord == JET4COORDS){
2550 
2551 
2552  r=V[1];
2553 
2555  //
2556  // determine theta2
2557  myhslope=h0 + pow( (V[1]-rsjet)/r0jet , njet);
2558 
2559  if(X[2]>1.0) myx2=2.0-X[2];
2560  else if(X[2]<0.0) myx2=-X[2];
2561  else myx2=X[2];
2562 
2563  th2 = 0.5*M_PI*(1.0 + atan(myhslope*(myx2-0.5))/atan(myhslope*0.5));
2564 
2565  if(X[2]>1.0) th2=2.0*M_PI-th2;
2566  else if(X[2]<0.0) th2=-th2;
2567 
2569  //
2570  // determine theta0
2571  myhslope=hslope;
2572 
2573  if(X[2]<0.5){
2574  th0 = M_PI * X[2] + ((1. - myhslope) / 2.) * mysin(2. * M_PI * X[2]);
2575  }
2576  else{
2577  th0 = M_PI - (M_PI * (1.0-X[2])) + ((1. - myhslope) / 2.) * (-mysin(2. * M_PI * (1.0-X[2])));
2578  }
2579 
2580  // determine switches (only function of radius and not x2 or theta)
2581  switch0 = 0.5+1.0/M_PI*atan((V[1]-rs)/r0); // switch in .nb file
2582  switch2 = 0.5-1.0/M_PI*atan((V[1]-rs)/r0); // switchi in .nb file
2583 
2584 
2585  // now get derivatives
2586 
2587  // drdx1
2588  dxdxp[1][1] = npow*(V[1]-R0)*pow(X[1],npow-1.0);
2589  // drdx2 = 0
2590 
2591 
2593  //
2594  // for theta0
2595  //
2597  if(X[2]<0.5){
2598  dtheta0dx2 = M_PI + (1. - hslope) * M_PI * mycos(2. * M_PI * X[2]);
2599  }
2600  else{
2601  dtheta0dx2 = M_PI + (1. - hslope) * M_PI * mycos(2. * M_PI * (1.0-X[2]) );
2602  }
2603 
2604  dtheta0dx1 = 0.0; // for this simple grid with fixed hslope
2605 
2606 
2608  //
2609  // for theta2
2610  //
2612  myhslope=pow( (V[1]-rsjet)/r0jet , njet);
2613  dmyhslopedr=(njet/r0jet)*pow( (V[1]-rsjet)/r0jet , njet-1.0);
2614 
2615  if(!finite(dmyhslopedr)){
2616  dualfprintf(fail_file,"Problem with dmyhslopedr=%g\n",dmyhslopedr);
2617  dualfprintf(fail_file,"njet=%g r=%g rsjet=%g r0jet=%g\n",njet,V[1],rsjet,r0jet);
2618  myexit(1);
2619  }
2620 
2621  // dhslope/dx1
2622  dmyhslopedx1=dmyhslopedr*dxdxp[1][1];
2623 
2624 
2625  if(X[2]>1.0) myx2=2.0-X[2];
2626  else if(X[2]<0.0) myx2=-X[2];
2627  else myx2=X[2];
2628 
2629 
2630 
2631  dtheta2dx2 = (2.0*M_PI*myhslope)/(atan(myhslope*0.5)*(4.0 + pow(1.0 - 2.0*myx2,2.0)*pow(myhslope,2.0)));
2632 
2633  // d\theta/dx1 = d\theta/dr dr/dx1
2634  dtheta2dx1 = (M_PI*dmyhslopedx1*(
2635  (-4.0*atan((-0.5 + myx2)*myhslope))/(4. + pow(myhslope,2.)) +
2636  (4.*(-1. + 2.*myx2)*atan(myhslope/2.))/(4. + pow(1. - 2.*myx2,2.)*pow(myhslope,2.))
2637  )
2638  )/(4.*pow(atan(myhslope/2.),2.));
2639 
2640  if(X[2]>1.0) dtheta2dx1*=-1.0;
2641  if(X[2]<0.0) dtheta2dx1*=-1.0;
2642 
2643 
2644  // switches
2645  dswitch0dr=1.0/(M_PI*r0*(1.0 + (r - rs)*(r - rs)/(r0*r0)));
2646  dswitch2dr=-dswitch0dr;
2647 
2648  // actual final derivatives
2649  dxdxp[2][2] = dtheta0dx2*switch2 + dtheta2dx2*switch0;
2650 
2651  // assumes r doesn't depend on x2
2652  dxdxp[2][1] = dtheta0dx1*switch2 + th0*dswitch2dr*dxdxp[1][1] + dtheta2dx1*switch0+th2*dswitch0dr*dxdxp[1][1] ;
2653 
2654 
2655 
2656 
2657 
2658 
2659  dxdxp[3][3] = 2.0*M_PI;
2660 
2661 
2662 
2663  }
2664 
2665  else{
2666  dualfprintf(fail_file,"Shouldn't reach end of dxdxp: defcoord=%d\n",defcoord);
2667  myexit(1);
2668  }
2669 
2670 
2671 
2672 
2673 }
2674 
2675 
2676 
2677 #define GAMMIEDERIVATIVE 0
2678 #define NUMREC 1 // at present this is too slow since dxdxp is called many times. Could setup permenant memory space, but kinda stupid
2679 
2680 // Note that can't use NUMREC for connection if using numerical dxdxp. Any other form of connection and then any dxdxp can be used.
2681 
2682 // For example, if both connection and dxdxp are computed using GAMMIEDERIVATIVE, seems to work fine as a decent numerical approximation
2683 
2684 // Also, one can use NUMREC for dxdxp if using analytic connection or GAMMIEDERIVATIVE connection.
2685 
2686 //#define DXDERTYPE DIFFNUMREC
2687 #define DXDERTYPE DIFFGAMMIE
2688 
2689 // see conn_func() for notes
2690 #if((REALTYPE==DOUBLETYPE)||(REALTYPE==FLOATTYPE))
2691 #define DXDELTA (MY1EM5)
2692 //#define DXDELTA (dx[1])
2693 #elif(REALTYPE==LONGDOUBLETYPE)
2694 #define DXDELTA (MY1EM6)
2695 #endif
2696 
2697 // finite volume form (nice if one could express so exact cancellation occurs in equations, but some errors vanish so that cannot identify how close to continuous solution one is since here one solves particular discrete equations)
2698 //#define GENDXDELTA(k) (k==TT ? DXDELTA*Diffx[k] : 0.5*dx[k])
2699 
2700 // finite difference form (nice to have "analytical" solution for dxdxp (and connection) so errors result that can be used to indicate how close to continuous solution one is)
2701 // Diffx[k] enters because DXDELTA is relative to total scale involved, which is Diffx[k], not always 1.0
2702 #define GENDXDELTA(k) (DXDELTA*Diffx[k])
2703 
2705 void dxdxp_numerical(FTYPE *X, FTYPE (*dxdxp)[NDIM])
2706 {
2707  int j,k,l;
2708  FTYPE Xh[NDIM], Xl[NDIM];
2709  FTYPE Vh[NDIM],Vl[NDIM];
2710  FTYPE blcoordsimple(struct of_geom *ptrgeom, FTYPE*X, int i, int j);
2711  extern int dfridr(FTYPE (*func)(struct of_geom *,FTYPE*,int,int), struct of_geom *ptrgeom, FTYPE *X,int ii, int jj, int kk, FTYPE *ans);
2712  void donothing(FTYPE *temp);
2713  FTYPE temp;
2714  FTYPE dxmachine[NDIM];
2715  struct of_geom geom;
2716  struct of_geom *ptrgeom;
2717  int failreturn;
2718 
2719 
2720  // setup dummy grid location since dxdxp doesn't need to know if on grid since don't store dxdxp (needed for dfridr())
2721  ptrgeom=&geom;
2722  ptrgeom->i=0;
2723  ptrgeom->j=0;
2724  ptrgeom->k=0;
2725  ptrgeom->p=NOWHERE;
2726 
2727 
2728  // for(k=0;k<NDIM;k++) for(j=0;j<NDIM;j++){
2729  DLOOP(j,k){
2730  failreturn=0;
2731  if(DXDERTYPE==DIFFNUMREC){
2732  failreturn=dfridr(blcoordsimple,ptrgeom,X,0,j,k,&(dxdxp[j][k]));
2733  }
2734  if(DXDERTYPE==DIFFGAMMIE || failreturn==1){
2735 
2736 
2737  // I setup X and V relationship for time and phi to be correct now
2738  // Was usind dxdxp[3][3]=1 when V[3]=2.0*M_PI*X[3], so that was incorrect -- a bug
2739  /*
2740  if((j==TT)||(k==TT)){
2741  // assume no transformation of time coordinate and no mixing of t-coordinate with other coordinates (except what already in metric)
2742  if(j!=k) dxdxp[j][k]=0.0;
2743  else dxdxp[j][k]=1.0;
2744  }
2745  else if((j==PH)||(k==PH)){
2746  // assume no transformation of phi coordinate and no mixing of phi coordinate with other coordinates (at least no additional to existing metric)
2747  if(j!=k) dxdxp[j][k]=0.0;
2748  else dxdxp[j][k]=1.0;
2749  }
2750  else{
2751  */
2752  for(l=0;l<NDIM;l++){
2753  Xl[l]=Xh[l]=X[l]; // location of derivative
2754  temp = X[l]-GENDXDELTA(l);
2755  donothing(&temp);
2756  X[l] = temp+GENDXDELTA(l);
2757  temp = X[l]+GENDXDELTA(l);
2758  donothing(&temp);
2759  dxmachine[l] = temp-X[l];
2760  }
2761 
2762  // Xh[k]+=dxmachine[k]; // shift up
2763  // Xl[k]-=dxmachine[k]; // shift down
2764 
2765  Xh[k]+=GENDXDELTA(k); // shift up
2766  Xl[k]-=GENDXDELTA(k); // shift down
2767 
2768  // dualfprintf(fail_file,"k=%d del=%g\n",k,GENDXDELTA(k));
2769 
2770  // below 2 lines redundant because gets both coordinates, but ok
2771  bl_coord(Xh, Vh);
2772  bl_coord(Xl, Vl);
2773  dxdxp[j][k] = (Vh[j] - Vl[j]) / (Xh[k] - Xl[k]);
2774 
2775  // GODMARK: unless N is a power of 2, X causes V to not be machine representable
2776  // GODMARK: Also, not only Xh-Xl, but each Xl and Xh must be machine representable
2777 
2778  // So even for a uniform grid dxdxp can vary near machine level
2779  // dualfprintf(fail_file,"Vh=%26.20g Vl=%26.20g Xh=%2.15g Xl=%26.20g DX=%26.20g\n",Vh[j],Vl[j],Xh[k],Xl[k],GENDXDELTA(k));
2780  // dualfprintf(fail_file,"(Vh[%d] - Vl[%d])=%26.20g (Xh[%d] - Xl[%d])=%26.20g\n",j,j,(Vh[j] - Vl[j]),k,k,(Xh[k] - Xl[k]));
2781  // }
2782 
2783  if(j==k && fabs(dxdxp[j][k])<NUMEPSILON){
2784  dualfprintf(fail_file,"dxdxp[%d][%d]=%g is too small. Ensure SINGSMALL=%g < %g\n",j,k,dxdxp[j][k],SINGSMALL,(Xh[k] - Xl[k]));
2785  }
2786 
2787  }
2788  }
2789 }
2790 
2791 
2793 void donothing(FTYPE *temp)
2794 {
2795  *temp=*temp;
2796 
2797 }
2798 
2799 
2801 FTYPE blcoordsimple(struct of_geom *ptrgeom, FTYPE*X, int i, int j) // i not used
2802 {
2803  FTYPE V[NDIM];
2804 
2805  // "dummy linear relationship" is right way and now setup when calling bl_coord()
2806  // if((j==TT)||(j==PH)) return(X[j]); // dummy linear relationship
2807  // else{
2808  bl_coord(X, V);
2809  return(V[j]);
2810  // }
2811 
2812 }
2813 
2814 
2815 
2817 //
2818 // Below set X uniform grid -- usually doesn't change.
2819 // Can usually force startx[1]=startx[2]=0. and dx[1]=1./N1 dx[2]=1./N2
2820 //
2822 
2823 
2827 void set_points()
2828 {
2829  int jj;
2830 
2831  //for SJETCOORDS
2832  FTYPE x1max0, x1max,dxmax;
2833  int iter;
2834  const FTYPE RELACC = NUMEPSILON*100.0;
2835  const int ITERMAX = 100;
2836 
2837  // below 2 things not used since we set X[0] directly using t
2838  startx[0]=0;
2839  dx[0]=dt;
2840 
2841  if (defcoord == USERCOORD) {
2842  extern void set_points_user(void);
2843  set_points_user();
2844  }
2845  else if (defcoord == LOGRSINTH) {
2846  startx[1] = log(Rin-R0);
2847  startx[2] = 0.;
2848  startx[3] = 0.;
2849  dx[1] = log((Rout-R0)/(Rin-R0)) / totalsize[1];
2850  dx[2] = 1. / totalsize[2];
2851  dx[3] = 1.0/totalsize[3];
2852  }
2853  else if (defcoord == REBECCAGRID) {
2854  startx[1] = log(Rin-R0);
2855  startx[2] = 0.;
2856  startx[3] = 0.;
2857  dx[1] = log((Rout-R0)/(Rin-R0)) / totalsize[1];
2858  dx[2] = 1. / totalsize[2];
2859  dx[3] = 1.0/totalsize[3];
2860  }
2861  else if (defcoord == COMPLEX0TH) {
2862  startx[1] = 0.;
2863  startx[2] = 0.;
2864  startx[3] = 0.;
2865  dx[1] = 1. / totalsize[1];
2866  dx[2] = 1. / totalsize[2];
2867  dx[3] = 1.0/totalsize[3];
2868  } else if (defcoord == UNIRSINTH) {
2869  startx[1] = Rin;
2870  // startx[2] = 0.324;
2871  startx[2] = 0.0;
2872  startx[3] = 0.;
2873  dx[1] = (Rout-Rin) / totalsize[1];
2874  // dx[2] = (1.0-2*.324) / totalsize[2];
2875  dx[2] = 1.0 / totalsize[2];
2876  dx[3] = 1.0/totalsize[3];
2877  } else if (defcoord == UNIRSINTH2) {
2878  startx[1] = 0.0;
2879  startx[2] = 0.0;
2880  startx[3] = 0.0;
2881  dx[1] = 1.0 / totalsize[1];
2882  dx[2] = 1.0 / totalsize[2];
2883  dx[3] = 1.0 / totalsize[3];
2884  }
2885  else if (defcoord == EQMIRROR) {
2886  startx[1] = log(Rin-R0);
2887  startx[2] = 0.;
2888  startx[3] = 0.;
2889  dx[1] = log((Rout-R0)/(Rin-R0)) / totalsize[1];
2890  dx[2] = 0.5 / totalsize[2];
2891  dx[3] = 1.0/totalsize[3];
2892  }
2893  else if (defcoord == COMPLEX1TH) {
2894  startx[1] = log(Rin-R0);
2895  startx[2] = 0.;
2896  startx[3] = 0.;
2897  dx[1] = log((Rout-R0)/(Rin-R0)) / totalsize[1];
2898  dx[2] = 1. / totalsize[2];
2899  dx[3] = 1.0/totalsize[3];
2900  }
2901  else if (defcoord == COMPLEX2TH) {
2902  startx[1] = log(Rin-R0);
2903  startx[2] = 0.;
2904  startx[3] = 0.;
2905  dx[1] = log((Rout-R0)/(Rin-R0)) / totalsize[1];
2906  dx[2] = 1. / totalsize[2];
2907  dx[3] = 1.0/totalsize[3];
2908  }
2909  else if (defcoord == LOGRUNITH) {
2910  startx[1] = log(Rin-R0);
2911  startx[2] = 0.;
2912  startx[3] = 0.;
2913  dx[1] = log((Rout-R0)/(Rin-R0)) / totalsize[1];
2914  dx[2] = 1. / totalsize[2];
2915  dx[3] = 1.0/totalsize[3];
2916  }
2917  else if (defcoord == JET1COORDS) {
2918  startx[1] = pow(log(Rin-R0),1.0/npow);
2919  startx[2] = 0.;
2920  startx[3] = 0.;
2921  dx[1] = (pow(log(Rout-R0),1.0/npow)-pow(log(Rin-R0),1.0/npow)) / totalsize[1];
2922  dx[2] = 1. / totalsize[2];
2923  dx[3] = 1.0/totalsize[3];
2924  }
2925  else if (defcoord == JET2COORDS) {
2926  startx[1] = pow(log(Rin-R0),1.0/npow);
2927  startx[2] = 0.;
2928  startx[3] = 0.;
2929  dx[1] = (pow(log(Rout-R0),1.0/npow)-pow(log(Rin-R0),1.0/npow)) / totalsize[1];
2930  dx[2] = 1. / totalsize[2];
2931  dx[3] = 1.0/totalsize[3];
2932  }
2933  else if (defcoord == JET3COORDS) {
2934  startx[1] = pow(log(Rin-R0),1.0/npow);
2935  startx[2] = 0.;
2936  startx[3] = 0.;
2937  dx[1] = (pow(log(Rout-R0),1.0/npow)-pow(log(Rin-R0),1.0/npow)) / totalsize[1];
2938  dx[2] = 1. / totalsize[2];
2939  dx[3] = 1.0/totalsize[3];
2940  }
2941  else if (defcoord == SJETCOORDS) {
2942  startx[1] = log(Rin-R0)/npow;
2943 
2944  if( Rout < rbr ) {
2945  x1max = log(Rout-R0)/npow;
2946  }
2947  else {
2948  x1max0 = 1;
2949  x1max = 2;
2950 
2951  //find the root via iterations
2952  for( iter = 0; iter < ITERMAX; iter++ ) {
2953  if( fabs((x1max - x1max0)/x1max) < RELACC ) {
2954  break;
2955  }
2956  x1max0 = x1max;
2957  dxmax= (pow( (log(Rout-R0) - npow*x1max0)/cpow2, 1./npow2 ) + x1br) - x1max0;
2958 
2959  // need a slight damping factor
2960  FTYPE dampingfactor=0.5;
2961  x1max = x1max0 + dampingfactor*dxmax;
2962  }
2963 
2964  if( iter == ITERMAX ) {
2965  trifprintf( "Error: iteration procedure for finding x1max has not converged: x1max = %g, dx1max/x1max = %g, iter = %d\n",
2966  x1max, (x1max-x1max0)/x1max, iter );
2967  exit(1);
2968  }
2969  else {
2970  trifprintf( "x1max = %g (dx1max/x1max = %g, itno = %d)\n", x1max, (x1max-x1max0)/x1max, iter );
2971  }
2972  }
2973 
2974  startx[2] = -1.;
2975  startx[3] = 0.;
2976  dx[1] = ( x1max - startx[1] ) /totalsize[1];
2977  dx[2] = 2. / totalsize[2];
2978  dx[3] = fracphi/totalsize[3];
2979  }
2980  else if (defcoord == JET6COORDS) { // same as JET3COORDS since radial grid same
2981  startx[1] = pow(log(Rin-R0),1.0/npow);
2982  startx[2] = 0.;
2983  startx[3] = 0.;
2984  dx[1] = (pow(log(Rout-R0),1.0/npow)-pow(log(Rin-R0),1.0/npow)) / totalsize[1];
2985  dx[2] = 1. / totalsize[2];
2986  dx[3] = 1.0/totalsize[3];
2987 
2988 #if(1)
2989  startx[1] = log(Rin-R0)/npow;
2990 
2991  trifprintf( "ITERATIVE dx1: Rout=%26.20g R0=%26.20g npow=%26.20g cpow2=%26.20g cpow3=%26.20g npow2=%26.20g x1br=%26.20g rbr=%26.20g\n",Rout,R0,npow,cpow2,cpow3,npow2,x1br,rbr);
2992 
2993  if( Rout < rbr ) {
2994  x1max = log(Rout-R0)/npow;
2995  }
2996  else {
2997  x1max0 = 1.1*x1br;
2998  x1max = 1.2*x1br;
2999 
3000  //find the root via iterations
3001  for( iter = 0; iter < ITERMAX; iter++ ) {
3002 
3003  // trifprintf( "iter=%d x1max=%26.20g x2max0=%26.20g\n",iter,x1max0,x1max);
3004 
3005  if( fabs((x1max - x1max0)/x1max) < RELACC ) {
3006  break;
3007  }
3008  x1max0 = x1max;
3009 
3010  if(1){
3011  dxmax= (pow( (log(Rout-R0) - npow*x1max0)/cpow2, 1./npow2 ) + x1br*1.0) - x1max0;
3012  }
3013  else{
3014  // f-f0 = (x-x0)*dfdx -> if f=Rout -> x = (Rout-f0)/dfdx+x0
3015 
3016  FTYPE dVdx1=(npow + cpow2*npow2*cpow3*pow(cpow3*(x1max0-x1br*1.0),npow2-1.0)) * exp(npow*x1max0 + cpow2 * pow(cpow3*(x1max0-x1br*1.0),npow2));
3017  FTYPE V0 = R0 + exp(npow*x1max0 + cpow2 * pow(cpow3*(x1max0-x1br*1.0),npow2));
3018 
3019  dxmax=(Rout-V0)/dVdx1; // x-x0
3020 
3021  dualfprintf(fail_file,"dVdx1=%g V0=%g dxmax=%g x1max=%g x1max0=%g\n",dVdx1,V0,dxmax,x1max,x1max0);
3022  }
3023 
3024  // need a slight damping factor
3025  FTYPE dampingfactor=0.5;
3026  x1max = x1max0 + dampingfactor*dxmax;
3027 
3028 
3029  }
3030 
3031  if( iter == ITERMAX ) {
3032  trifprintf( "Error: iteration procedure for finding x1max has not converged: x1max = %g, dx1max/x1max = %g, iter = %d\n",
3033  x1max, (x1max-x1max0)/x1max, iter );
3034  exit(1);
3035  }
3036  else {
3037  trifprintf( "x1max = %g (dx1max/x1max = %g, itno = %d)\n", x1max, (x1max-x1max0)/x1max, iter );
3038  }
3039  }
3040 
3041  dx[1] = ( x1max - startx[1] ) /totalsize[1];
3042 #endif
3043 
3044 
3045  }
3046  else if (defcoord == JET6COORDSTHIN) {
3047  startx[1] = pow(log(Rin-R0),1.0/th_npow);
3048  startx[2] = 0.;
3049  startx[3] = 0.;
3050  dx[1] = (pow(log(Rout-R0),1.0/th_npow)-pow(log(Rin-R0),1.0/th_npow)) / totalsize[1];
3051  dx[2] = 1. / totalsize[2];
3052  dx[3] = 1.0/totalsize[3];
3053 
3054 #if(1)
3055  startx[1] = log(Rin-R0)/th_npow;
3056 
3057  trifprintf( "ITERATIVE dx1: Rout=%26.20g R0=%26.20g npow=%26.20g cpow2=%26.20g npow2=%26.20g x1br=%26.20g rbr=%26.20g\n",Rout,R0,th_npow,th_cpow2,th_npow2,th_x1br,th_rbr);
3058 
3059  if( Rout < th_rbr ) {
3060  x1max = log(Rout-R0)/th_npow;
3061  }
3062  else {
3063  x1max0 = 1;
3064  x1max = 2;
3065 
3066  //find the root via iterations
3067  for( iter = 0; iter < ITERMAX; iter++ ) {
3068 
3069  // trifprintf( "iter=%d x1max=%26.20g x2max0=%26.20g\n",iter,x1max0,x1max);
3070 
3071  if( fabs((x1max - x1max0)/x1max) < RELACC ) {
3072  break;
3073  }
3074  x1max0 = x1max;
3075  dxmax= (pow( (log(Rout-R0) - th_npow*x1max0)/th_cpow2, 1./th_npow2 ) + th_x1br) - x1max0;
3076 
3077  // need a slight damping factor
3078  FTYPE dampingfactor=0.5;
3079  x1max = x1max0 + dampingfactor*dxmax;
3080 
3081  }
3082 
3083  if( iter == ITERMAX ) {
3084  trifprintf( "Error: iteration procedure for finding x1max has not converged: x1max = %g, dx1max/x1max = %g, iter = %d\n",
3085  x1max, (x1max-x1max0)/x1max, iter );
3086  exit(1);
3087  }
3088  else {
3089  trifprintf( "x1max = %g (dx1max/x1max = %g, itno = %d)\n", x1max, (x1max-x1max0)/x1max, iter );
3090  }
3091  }
3092 
3093  dx[1] = ( x1max - startx[1] ) /totalsize[1];
3094 #endif
3095 
3096 
3097  }
3098  else if (defcoord == BPTHIN1) { // same as JET3COORDS since radial grid same
3099  startx[1] = pow(log(Rin-R0),1.0/bp_npow);
3100  startx[2] = 0.;
3101  startx[3] = 0.;
3102  dx[1] = (pow(log(Rout-R0),1.0/bp_npow)-pow(log(Rin-R0),1.0/bp_npow)) / totalsize[1];
3103  dx[2] = 1. / totalsize[2];
3104  dx[3] = fracphi/totalsize[3];
3105 
3106 #if(1)
3107  startx[1] = log(Rin-R0)/bp_npow;
3108 
3109  trifprintf( "ITERATIVE dx1: Rout=%21.15g R0=%21.15g bp_npow=%21.15g bp_cpow2=%21.15g bp_npow2=%21.15g bp_x1br=%21.15g bp_rbr=%21.15g\n",Rout,R0,bp_npow,bp_cpow2,bp_npow2,bp_x1br,bp_rbr);
3110 
3111  if( Rout < bp_rbr ) {
3112  x1max = log(Rout-R0)/bp_npow;
3113  }
3114  else {
3115  x1max0 = 1;
3116  x1max = 2;
3117 
3118  //find the root via iterations
3119  for( iter = 0; iter < ITERMAX; iter++ ) {
3120 
3121  // trifprintf( "iter=%d x1max=%21.15g x2max0=%21.15g\n",iter,x1max0,x1max);
3122 
3123  if( fabs((x1max - x1max0)/x1max) < RELACC ) {
3124  break;
3125  }
3126  x1max0 = x1max;
3127  dxmax= (pow( (log(Rout-R0) - bp_npow*x1max0)/bp_cpow2, 1./bp_npow2 ) + bp_x1br) - x1max0;
3128 
3129  // need a slight damping factor
3130  FTYPE dampingfactor=0.5;
3131  x1max = x1max0 + dampingfactor*dxmax;
3132 
3133  }
3134 
3135  if( iter == ITERMAX ) {
3136  trifprintf( "Error: iteration procedure for finding x1max has not converged: x1max = %g, dx1max/x1max = %g, iter = %d\n",
3137  x1max, (x1max-x1max0)/x1max, iter );
3138  exit(1);
3139  }
3140  else {
3141  trifprintf( "x1max = %g (dx1max/x1max = %g, itno = %d)\n", x1max, (x1max-x1max0)/x1max, iter );
3142  }
3143  }
3144 
3145  dx[1] = ( x1max - startx[1] ) /totalsize[1];
3146 #endif
3147 
3148 
3149  }
3150  else if (defcoord == JET5COORDS) {
3151  startx[1] = 0.0;
3152  startx[2] = 0.0;
3153  startx[3] = 0.0;
3154  dx[1] = 1.0 / totalsize[1];
3155  dx[2] = 1.0 / totalsize[2];
3156  dx[3] = 1.0 / totalsize[3];
3157  }
3158  else if (defcoord == PULSARCOORDS) {
3159  startx[1] = pow(log(Rin-R0),1.0/npow);
3160  startx[2] = 0.;
3161  startx[3] = 0.;
3162  dx[1] = (pow(log(Rout-R0),1.0/npow)-pow(log(Rin-R0),1.0/npow)) / totalsize[1];
3163  dx[2] = 1. / totalsize[2];
3164 
3165  dx[3] = 1.0 / totalsize[3];
3166  // dx[3] = 2.0*M_PI;
3167  }
3168  else if (defcoord == BILOGCYLCOORDS) {
3169  startx[1] = 0.;
3170  startx[2] = -1.0;
3171  startx[3] = 0.0;
3172  dx[1] = 1.0 / totalsize[1];
3173  dx[2] = 2.0 / totalsize[2];
3174  dx[3] = 1.0 / totalsize[3];
3175  }
3176  else if (defcoord == UNIFORMCOORDS) {
3177  //uniform grid for Cartesian coordinates
3178  startx[1] = 0.;
3179  startx[2] = 0.;
3180  startx[3] = 0.;
3181  dx[1] = 1. / totalsize[1];
3182  dx[2] = 1. / totalsize[2];
3183  dx[3] = 1. / totalsize[3];
3184  }
3185  else if (defcoord == RAMESHCOORDS) {
3186  startx[1] = pow(log(Rin-R0),1.0/npow);
3187  startx[2] = 0.;
3188  startx[3] = 0.;
3189  dx[1] = (pow(log(Rout-R0),1.0/npow)-pow(log(Rin-R0),1.0/npow)) / totalsize[1];
3190  dx[2] = 1. / totalsize[2];
3191  dx[3] = 1. / totalsize[3];
3192  }
3193  else if (defcoord == RAMESHCOORDS_HALFDISK) {
3194  startx[1] = pow(log(Rin-R0),1.0/npow);
3195 
3196  if(BCtype[X2DN]==DISKSURFACE){
3197  startx[2] = 0.5;
3198  }
3199  else if(BCtype[X2UP]==DISKSURFACE){
3200  startx[2] = 0.0;
3201  }
3202 
3203  startx[3] = 0.;
3204  dx[1] = (pow(log(Rout-R0),1.0/npow)-pow(log(Rin-R0),1.0/npow)) / totalsize[1];
3205  dx[2] = 0.5 / totalsize[2];
3206 
3207  dx[3] = 1. / totalsize[3];
3208  }
3209  else if (defcoord == JET4COORDS) {
3210  startx[1] = pow(log(Rin-R0),1.0/npow);
3211  startx[2] = 0.;
3212  startx[3] = 0.;
3213  dx[1] = (pow(log(Rout-R0),1.0/npow)-pow(log(Rin-R0),1.0/npow)) / totalsize[1];
3214  dx[2] = 1. / totalsize[2];
3215  dx[3] = 1. / totalsize[3];
3216  }
3217  else if (defcoord == UNI2LOG) {
3218  startx[1] = 0.0;
3219  startx[2] = 0.0;
3220  startx[3] = 0.0;
3221  dx[1] = 1.0 / totalsize[1];
3222  dx[2] = 1.0 / totalsize[2];
3223  dx[3] = 1.0 / totalsize[3];
3224  }
3225  else{
3226  dualfprintf(fail_file,"Shouldn't reach end of set_points: defcoord=%d\n",defcoord);
3227  myexit(1);
3228  }
3229 
3230 
3231  dV = dx[1] * dx[2] * dx[3]; // computational volume
3232  dVF = dV ; // full 3d volume
3233 
3234  // determine endx[]
3235  DLOOPA(jj) endx[jj] = startx[jj] + totalsize[jj]*dx[jj];
3236  // overwrite TT term so Diffx[TT] = DXDELTA, which is used
3237  jj=TT; endx[TT] = startx[TT] + DXDELTA;
3238 
3239  // total endx-startx
3240  // fabs() used since only ever used as absolute value
3241  DLOOPA(jj) Diffx[jj] = fabs(endx[jj] - startx[jj]);
3242 
3243  // DLOOPA(jj) fprintf(stderr,"jj=%d Diffx=%26.20g endx=%26.20g startx=%26.20g\n",jj,Diffx[jj],endx[jj],startx[jj]);
3244 
3245 
3246 }
3247 
3248 
3249 
3250 #undef DXDERTYPE
3251 #undef DXDELTA
3252 
3253 
3254 
3255 #define MAXIHOR MAXBND
3256 #define FRACN1 (0.1)
3257 #define ADJUSTFRACT (0.25)
3258 
3259 
3261 int setihor(void)
3262 {
3263  // set to smaller of either totalsize[1]*0.1 or MAXIHOR
3264  if(totalsize[1]*FRACN1>MAXIHOR) return((int)MAXIHOR);
3265  else return((int)((FTYPE)totalsize[1]*(FTYPE)FRACN1));
3266 }
3267 
3268 
3272 FTYPE setRin(int ihor)
3273 {
3274 
3275  FTYPE ftemp;
3276  FTYPE ihoradjust;
3277 
3278 
3279  ihoradjust=((FTYPE)ihor)+ADJUSTFRACT; // can't have grid edge exactly on horizon due to ucon_calc()
3280 
3281  // fprintf(stderr,"ihoradjust = %26.20g\n",ihoradjust);
3282 
3283  if(defcoord == USERCOORD){
3284  extern FTYPE setRin_user(int ihor, FTYPE ihoradjust);
3285  return(setRin_user(ihor,ihoradjust));
3286  }
3287  else if(defcoord == LOGRSINTH){
3288  ftemp=ihoradjust/(FTYPE)totalsize[1];
3289  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3290  }
3291  else if(defcoord == REBECCAGRID){
3292  ftemp=ihoradjust/(FTYPE)totalsize[1];
3293  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3294  }
3295  else if(defcoord == COMPLEX0TH){ // even though form appears different in X1, same Rin results
3296  ftemp=ihoradjust/(FTYPE)totalsize[1];
3297  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3298  }
3299  else if(defcoord == UNIRSINTH || defcoord == UNIRSINTH2){ // uniform
3300  ftemp=ihoradjust/(FTYPE)totalsize[1];
3301  return((Rhor-ftemp*Rout)/(1.0-ftemp));
3302  }
3303  else if(defcoord == EQMIRROR){ // as defcoord=0
3304  ftemp=ihoradjust/(FTYPE)totalsize[1];
3305  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3306  }
3307  else if(defcoord == COMPLEX1TH){ // as above
3308  ftemp=ihoradjust/(FTYPE)totalsize[1];
3309  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3310  }
3311  else if(defcoord == COMPLEX2TH){ // as above
3312  ftemp=ihoradjust/(FTYPE)totalsize[1];
3313  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3314  }
3315  else if(defcoord == LOGRUNITH){ // as above
3316  ftemp=ihoradjust/(FTYPE)totalsize[1];
3317  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3318  }
3319  else if(defcoord == JET1COORDS){
3320  if(npow==1.0){
3321  ftemp=ihoradjust/(FTYPE)totalsize[1];
3322  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3323  }
3324  else{
3325  // SUPERGODMARK : need to change for npow>1.0
3326  return(1.1);
3327  }
3328  }
3329  else if(defcoord == JET2COORDS){
3330  if(npow==1.0){
3331  ftemp=ihoradjust/(FTYPE)totalsize[1];
3332  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3333  }
3334  else{
3335  // SUPERGODMARK : need to change for npow>1.0
3336  return(1.1);
3337  }
3338  }
3339  else if(defcoord == JET3COORDS){
3340  // see jet3coords_checknew.nb to have chosen Rin and ihor and compute required R0
3341  if(npow==1.0){
3342  ftemp=ihoradjust/(FTYPE)totalsize[1];
3343  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3344  }
3345  else{
3346  dualfprintf(fail_file,"ihoradjust=%26.20g totalsize[1]=%d Rhor=%26.20g R0=%26.20g npow=%26.20g Rout=%26.20g\n",ihoradjust,totalsize[1],Rhor,R0,npow,Rout);
3347  return(R0+exp( pow((totalsize[1]*pow(log(Rhor-R0),1.0/npow) - ihoradjust*pow(log(Rout-R0),1.0/npow))/(totalsize[1]-ihoradjust),npow)));
3348  }
3349  }
3350  else if(defcoord == SJETCOORDS){
3351  dualfprintf( fail_file, "setRin(): not implemented for SJETCOORDS\n" );
3352  myexit(1);
3353  }
3354  else if(defcoord == JET6COORDS){
3355  // see jet3coords_checknew.nb (and fix_3dpolestissue.nb) to have chosen Rin and ihor and compute required R0
3356  if(npow==1.0){
3357  ftemp=ihoradjust/(FTYPE)totalsize[1];
3358  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3359  }
3360  else if(npow2>0){
3361  return(1.2);
3362  }
3363  else{
3364  dualfprintf(fail_file,"ihoradjust=%26.20g totalsize[1]=%d Rhor=%26.20g R0=%26.20g npow=%26.20g Rout=%26.20g\n",ihoradjust,totalsize[1],Rhor,R0,npow,Rout);
3365  return(R0+exp( pow((totalsize[1]*pow(log(Rhor-R0),1.0/npow) - ihoradjust*pow(log(Rout-R0),1.0/npow))/(totalsize[1]-ihoradjust),npow)));
3366  }
3367  }
3368  else if(defcoord == JET6COORDSTHIN){
3369  // see jet3coords_checknew.nb (and fix_3dpolestissue.nb) to have chosen Rin and ihor and compute required R0
3370  if(th_npow==1.0){
3371  ftemp=ihoradjust/(FTYPE)totalsize[1];
3372  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3373  }
3374  else if(th_npow2>0){
3375  return(1.2);
3376  }
3377  else{
3378  dualfprintf(fail_file,"ihoradjust=%26.20g totalsize[1]=%d Rhor=%26.20g R0=%26.20g npow=%26.20g Rout=%26.20g\n",ihoradjust,totalsize[1],Rhor,R0,th_npow,Rout);
3379  return(R0+exp( pow((totalsize[1]*pow(log(Rhor-R0),1.0/th_npow) - ihoradjust*pow(log(Rout-R0),1.0/th_npow))/(totalsize[1]-ihoradjust),th_npow)));
3380  }
3381  }
3382  else if(defcoord == BPTHIN1){
3383  // see jet3coords_checknew.nb (and fix_3dpolestissue.nb) to have chosen Rin and ihor and compute required R0
3384  if(bp_npow==1.0){
3385  ftemp=ihoradjust/(FTYPE)totalsize[1];
3386  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3387  }
3388  else if(bp_npow2>0){
3389  return(1.2);
3390  }
3391  else{
3392  dualfprintf(fail_file,"ihoradjust=%21.15g totalsize[1]=%d Rhor=%21.15g R0=%21.15g bp_npow=%21.15g Rout=%21.15g\n",ihoradjust,totalsize[1],Rhor,R0,bp_npow,Rout);
3393  return(R0+exp( pow((totalsize[1]*pow(log(Rhor-R0),1.0/bp_npow) - ihoradjust*pow(log(Rout-R0),1.0/bp_npow))/(totalsize[1]-ihoradjust),bp_npow)));
3394  }
3395  }
3396  else if(defcoord == JET5COORDS){
3397  return(JET5RIN); // not free! Must be consistent with how determine coordinates
3398  }
3399  else if(defcoord == PULSARCOORDS){
3400  if(npow==1.0){
3401  ftemp=ihoradjust/(FTYPE)totalsize[1];
3402  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3403  }
3404  else{
3405  // SUPERGODMARK : need to change for npow>1.0
3406  return(1.1);
3407  }
3408  }
3409  else if (defcoord == UNIFORMCOORDS) {
3410  //uniform grid for Cartesian coordinates
3411  //no horizon in Cartesian coords -> do not set anything
3412  return( 1.0 );
3413  }
3415  if(npow==1.0){
3416  ftemp=ihoradjust/(FTYPE)totalsize[1];
3417  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3418  }
3419  else{
3420  // SUPERGODMARK : need to change for npow>1.0
3421  return(1.1);
3422  }
3423  }
3424  else if(defcoord == JET4COORDS){
3425  if(npow==1.0){
3426  ftemp=ihoradjust/(FTYPE)totalsize[1];
3427  return(R0+pow((Rhor-R0)/pow(Rout-R0,ftemp),1.0/(1.0-ftemp)));
3428  }
3429  else{
3430  // SUPERGODMARK : need to change for npow>1.0
3431  return(1.1);
3432  }
3433  }
3434  else if(defcoord == UNI2LOG){
3435  dualfprintf(fail_file,"This grid's setRin is not setup defcoord=%d\n",defcoord);
3436  myexit(1);
3437  return(-1);
3438  }
3439 
3440  dualfprintf(fail_file,"Shouldn't reach end of setRin: defcoord=%d\n",defcoord);
3441  myexit(1);
3442  return(-1);
3443 
3444 }
3445 
3446 
3447 
3450 void coord(int i, int j, int k, int loc, FTYPE *X)
3451 {
3452  // as in get_geometry(), these ?global's are used by other routines as a global indicator of where in position space we are so don't have to pass to all subfunctions
3453  //iglobal=i;
3454  //jglobal=j;
3455  //kglobal=k;
3456  //pglobal=loc;
3457 
3458 
3459  if (loc == CENT) {
3460  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3461  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3462  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3463  }
3464  else if (loc == FACE1) {
3465 #if(N1>1)
3466  X[1] = startx[1] + (i + startpos[1] ) * dx[1];
3467 #else
3468  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3469 #endif
3470 
3471  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3472  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3473  }
3474  else if (loc == FACE2) {
3475  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3476 
3477 #if(N2>1)
3478  X[2] = startx[2] + (j + startpos[2] ) * dx[2];
3479 #else
3480  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3481 #endif
3482 
3483  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3484  }
3485  else if (loc == FACE3) {
3486  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3487  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3488 
3489 #if(N3>1)
3490  X[3] = startx[3] + (k + startpos[3] ) * dx[3];
3491 #else
3492  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3493 #endif
3494  }
3495  else if (loc == CORN1) {
3496  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3497 
3498 #if(N2>1)
3499  X[2] = startx[2] + (j + startpos[2] ) * dx[2];
3500 #else
3501  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3502 #endif
3503 #if(N3>1)
3504  X[3] = startx[3] + (k + startpos[3] ) * dx[3];
3505 #else
3506  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3507 #endif
3508  }
3509  else if (loc == CORN2) {
3510 #if(N1>1)
3511  X[1] = startx[1] + (i + startpos[1] ) * dx[1];
3512 #else
3513  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3514 #endif
3515 
3516  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3517 
3518 #if(N3>1)
3519  X[3] = startx[3] + (k + startpos[3] ) * dx[3];
3520 #else
3521  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3522 #endif
3523  }
3524  else if (loc == CORN3) {
3525 #if(N1>1)
3526  X[1] = startx[1] + (i + startpos[1] ) * dx[1];
3527 #else
3528  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3529 #endif
3530 #if(N2>1)
3531  X[2] = startx[2] + (j + startpos[2] ) * dx[2];
3532 #else
3533  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3534 #endif
3535 
3536  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3537  }
3538  else if (loc == CORNT) {
3539 #if(N1>1)
3540  X[1] = startx[1] + (i + startpos[1] ) * dx[1];
3541 #else
3542  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3543 #endif
3544 #if(N2>1)
3545  X[2] = startx[2] + (j + startpos[2] ) * dx[2];
3546 #else
3547  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3548 #endif
3549 #if(N3>1)
3550  X[3] = startx[3] + (k + startpos[3] ) * dx[3];
3551 #else
3552  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3553 #endif
3554  }
3555 
3556  // present time is always denoted by X[0]=0 so that past times are negative X[0]
3557  // X[0]=0.0;
3558  // below only applies for longsteps method
3559  // X[0]=t; // use X[0] to indicate time in standard temporal coordinates
3560 
3561  // present time of metric quantities
3562  // assume Xmetricnew setup in set_grid before this function (coord) is called
3563  X[TT] = Xmetricnew[TT];
3564 
3565  return;
3566 }
3567 
3568 
3573 void coord_free(int i, int j, int k, int loc, FTYPE *X)
3574 {
3575 
3576  //iglobal=i;
3577  //jglobal=j;
3578  //kglobal=k;
3579  //pglobal=loc;
3580 
3581  if (loc == CENT) {
3582  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3583  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3584  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3585  }
3586  else if (loc == FACE1) {
3587  X[1] = startx[1] + (i + startpos[1] ) * dx[1];
3588  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3589  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3590  }
3591  else if (loc == FACE2) {
3592  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3593  X[2] = startx[2] + (j + startpos[2] ) * dx[2];
3594  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3595  }
3596  else if (loc == FACE3) {
3597  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3598  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3599  X[3] = startx[3] + (k + startpos[3] ) * dx[3];
3600  }
3601  else if (loc == CORN1) {
3602  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3603  X[2] = startx[2] + (j + startpos[2] ) * dx[2];
3604  X[3] = startx[3] + (k + startpos[3] ) * dx[3];
3605  }
3606  else if (loc == CORN2) {
3607  X[1] = startx[1] + (i + startpos[1] ) * dx[1];
3608  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3609  X[3] = startx[3] + (k + startpos[3] ) * dx[3];
3610  }
3611  else if (loc == CORN3) {
3612  X[1] = startx[1] + (i + startpos[1] ) * dx[1];
3613  X[2] = startx[2] + (j + startpos[2] ) * dx[2];
3614  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3615  }
3616  else if (loc == CORNT) {
3617  X[1] = startx[1] + (i + startpos[1] ) * dx[1];
3618  X[2] = startx[2] + (j + startpos[2] ) * dx[2];
3619  X[3] = startx[3] + (k + startpos[3] ) * dx[3];
3620  }
3621 
3622  // present time is always denoted by X[0]=0 so that past times are negative X[0]
3623  // X[0]=0.0;
3624  // below only applies for longsteps method
3625  // X[0]=t; // use X[0] to indicate time in standard temporal coordinates
3626 
3627  // present time of metric quantities
3628  // assume Xmetricnew setup in set_grid before this function (coord) is called
3629  X[TT] = Xmetricnew[TT];
3630 
3631  return;
3632 }
3633 
3634 
3635 
3637 void coordf(FTYPE i, FTYPE j, FTYPE k, int loc, FTYPE *X)
3638 {
3639  //iglobal=ROUND2INT(i);
3640  //jglobal=ROUND2INT(j);
3641  //kglobal=ROUND2INT(k);
3642  //pglobal=loc;
3643 
3644  if (loc == CENT) {
3645  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3646  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3647  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3648  }
3649  else if (loc == FACE1) {
3650 #if(N1>1)
3651  X[1] = startx[1] + (i + startpos[1] ) * dx[1];
3652 #else
3653  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3654 #endif
3655 
3656  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3657  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3658  }
3659  else if (loc == FACE2) {
3660  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3661 
3662 #if(N2>1)
3663  X[2] = startx[2] + (j + startpos[2] ) * dx[2];
3664 #else
3665  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3666 #endif
3667 
3668  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3669  }
3670  else if (loc == FACE3) {
3671  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3672  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3673 
3674 #if(N3>1)
3675  X[3] = startx[3] + (k + startpos[3] ) * dx[3];
3676 #else
3677  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3678 #endif
3679  }
3680  else if (loc == CORN1) {
3681  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3682 
3683 #if(N2>1)
3684  X[2] = startx[2] + (j + startpos[2] ) * dx[2];
3685 #else
3686  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3687 #endif
3688 #if(N3>1)
3689  X[3] = startx[3] + (k + startpos[3] ) * dx[3];
3690 #else
3691  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3692 #endif
3693  }
3694  else if (loc == CORN2) {
3695 #if(N1>1)
3696  X[1] = startx[1] + (i + startpos[1] ) * dx[1];
3697 #else
3698  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3699 #endif
3700 
3701  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3702 
3703 #if(N3>1)
3704  X[3] = startx[3] + (k + startpos[3] ) * dx[3];
3705 #else
3706  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3707 #endif
3708  }
3709  else if (loc == CORN3) {
3710 #if(N1>1)
3711  X[1] = startx[1] + (i + startpos[1] ) * dx[1];
3712 #else
3713  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3714 #endif
3715 #if(N2>1)
3716  X[2] = startx[2] + (j + startpos[2] ) * dx[2];
3717 #else
3718  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3719 #endif
3720 
3721  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3722  }
3723  else if (loc == CORNT) {
3724 #if(N1>1)
3725  X[1] = startx[1] + (i + startpos[1] ) * dx[1];
3726 #else
3727  X[1] = startx[1] + (i + startpos[1] + 0.5) * dx[1];
3728 #endif
3729 #if(N2>1)
3730  X[2] = startx[2] + (j + startpos[2] ) * dx[2];
3731 #else
3732  X[2] = startx[2] + (j + startpos[2] + 0.5) * dx[2];
3733 #endif
3734 #if(N3>1)
3735  X[3] = startx[3] + (k + startpos[3] ) * dx[3];
3736 #else
3737  X[3] = startx[3] + (k + startpos[3] + 0.5) * dx[3];
3738 #endif
3739  }
3740 
3741  // present time is always denoted by X[0]=0 so that past times are negative X[0]
3742  // X[0]=0.0;
3743  // below only applies for longsteps method
3744  // X[0]=t; // use X[0] to indicate time in standard temporal coordinates
3745 
3746  // present time of metric quantities
3747  // assume Xmetricnew setup in set_grid before this function (coord) is called
3748  X[TT] = Xmetricnew[TT];
3749 
3750  return;
3751 }
3752 
3753 
3755 void icoord(FTYPE *X,int loc, int *i, int *j, int *k)
3756 {
3757  if(loc == CENT){
3758  *i = (int)((X[1]-startx[1])/dx[1] - 0.5) ;
3759  *j = (int)((X[2]-startx[2])/dx[2] - 0.5) ;
3760  *k = (int)((X[3]-startx[3])/dx[3] - 0.5) ;
3761  }
3762 
3763  if(startpos[1]+ *i>=totalsize[1]+N1BND) *i=totalsize[1]-1+N1BND;
3764  if(startpos[2]+ *j>=totalsize[2]+N2BND) *j=totalsize[2]-1+N2BND;
3765  if(startpos[3]+ *k>=totalsize[3]+N3BND) *k=totalsize[3]-1+N3BND;
3766 
3767  if(startpos[1]+ *i<-N1BND) *i=-N1BND;
3768  if(startpos[2]+ *j<-N2BND) *j=-N2BND;
3769  if(startpos[3]+ *k<-N3BND) *k=-N3BND;
3770 
3771 }
3772 
3773 #define INCLUDEROUND 0 // default
3774 
3775 #ifdef WIN32
3776 #undef INCLUDEROUND
3777 #define INCLUDEROUND 1
3778 #endif
3779 
3780 // roundl is not part of long double library
3781 #if(REALTYPE==LONGDOUBLETYPE)
3782 #undef INCLUDEROUND
3783 #define INCLUDEROUND 1
3784 #endif
3785 
3786 #if(INCLUDEROUND)
3787 
3789 {
3790  FTYPE xfloor,xceil;
3791 
3792  xfloor=floor(x);
3793  xceil=ceil(x);
3794  if(fabs(x-xfloor)>fabs(x-xceil)) return(xceil);
3795  else return(xfloor);
3796 }
3797 
3799 long int lrint(FTYPE x)
3800 {
3801  return((long int)round(x));
3802 }
3803 #endif
3804 
3805 
3806 
3808 FTYPE myround(FTYPE x)
3809 {
3810 
3811 #if(REALTYPE==FLOATTYPE)
3812  return(roundf(x));
3813 #elif(REALTYPE==DOUBLETYPE || REALTYPE==LONGDOUBLETYPE)
3814  // ceill will be used automatically by conversion to long doubles
3815  return(round(x));
3816 #endif
3817 
3818 }
3819 
3820 
3821 #if(0)
3822 
3823 long int myround2int(FTYPE x)
3824 {
3825 
3826 #if(REALTYPE==FLOATTYPE)
3827  return(lrintf(x));
3828 #elif(REALTYPE==DOUBLETYPE)
3829  return(lrint(x));
3830 #elif(REALTYPE==LONGDOUBLETYPE)
3831  return(lrintl(x));
3832 #endif
3833 }
3834 #else
3835 #define myround2int(x) (ROUND2INT(x))
3836 #endif
3837 
3839 void icoord_round(FTYPE *X,int loc, int *i, int *j, int *k)
3840 {
3841  FTYPE myround(FTYPE x);
3842  // long int myround2int(FTYPE x);
3843 
3844  if(loc == CENT){
3845  *i = myround2int((X[1]-startx[1])/dx[1] - 0.5) ;
3846  *j = myround2int((X[2]-startx[2])/dx[2] - 0.5) ;
3847  *k = myround2int((X[3]-startx[3])/dx[3] - 0.5) ;
3848  }
3849 
3850  if(startpos[1]+ *i>=totalsize[1]+N1BND) *i=totalsize[1]-1+N1BND;
3851  if(startpos[2]+ *j>=totalsize[2]+N2BND) *j=totalsize[2]-1+N2BND;
3852  if(startpos[3]+ *k>=totalsize[3]+N3BND) *k=totalsize[3]-1+N3BND;
3853 
3854  if(startpos[1]+ *i<-N1BND) *i=-N1BND;
3855  if(startpos[2]+ *j<-N2BND) *j=-N2BND;
3856  if(startpos[3]+ *k<-N3BND) *k=-N3BND;
3857 
3858 }
3859 
3860 
3863 int is_inside_surface(int dir, int ii, int jj, int kk, int pp)
3864 {
3865  int is_on_surface(int dir, int ii, int jj, int kk, int pp);
3866  int ijk[NDIM];
3867  int dimen;
3868  int dirsign;
3869  int isonsurf;
3870 
3871  ijk[1]=ii;
3872  ijk[2]=jj;
3873  ijk[3]=kk;
3874 
3875 
3876  dimen=DIMEN(dir);
3877  dirsign=DIRSIGN(dir);
3878 
3879  isonsurf=is_on_surface(dir,ii,jj,kk,pp);
3880 
3881  if(isonsurf){
3882  return(1);
3883  }
3884  else if(
3885  (startpos[dimen]+ijk[dimen]<0 && dirsign==-1)
3886  ||
3887  (startpos[dimen]+ijk[dimen]>totalsize[dimen]-1 && dirsign==1)
3888  ){
3889  return(1);
3890  }
3891  else return(0);
3892 
3893 }
3894 
3896 int is_on_surface(int dir, int ii, int jj, int kk, int pp)
3897 {
3898  int ijk[NDIM];
3899  int dimen;
3900  int dirsign;
3901 
3902  ijk[1]=ii;
3903  ijk[2]=jj;
3904  ijk[3]=kk;
3905 
3906 
3907  dimen=DIMEN(dir);
3908  dirsign=DIRSIGN(dir);
3909 
3910  if(
3911  ((dimen==1)&&(dirsign==-1)&&(startpos[dimen]+ii==0) && (pp==FACE1 || pp==CORN2 || pp==CORN3 || pp==CORNT))||
3912  ((dimen==1)&&(dirsign==1) &&(startpos[dimen]+ii==totalsize[dimen]) && (pp==FACE1 || pp==CORN2 || pp==CORN3 || pp==CORNT))||
3913  ((dimen==2)&&(dirsign==-1)&&(startpos[dimen]+jj==0) && (pp==FACE2 || pp==CORN1 || pp==CORN3 || pp==CORNT))||
3914  ((dimen==2)&&(dirsign==1) &&(startpos[dimen]+jj==totalsize[dimen]) && (pp==FACE2 || pp==CORN1 || pp==CORN3 || pp==CORNT))||
3915  ((dimen==3)&&(dirsign==-1)&&(startpos[dimen]+kk==0) && (pp==FACE3 || pp==CORN2 || pp==CORN1 || pp==CORNT))||
3916  ((dimen==3)&&(dirsign==1) &&(startpos[dimen]+kk==totalsize[dimen]) && (pp==FACE3 || pp==CORN2 || pp==CORN1 || pp==CORNT))
3917  ){
3918  return(1);
3919  }
3920  else return(0);
3921 
3922 }
3923 
3924 
3925 
3927 // GODMARK: Should improve this. Right now if I call coord_ijk and then immediately bl_coord_ijk and first time called, then expensive since coord() called twice
3928 // NEVER CALL *_ijk_*() type functions if input i,j,k is meant to be related to total grid that would access beyond stored arrays
3929 
3930 
3932 void dxdxprim_ijk(int i, int j, int k, int loc, FTYPE (*dxdxp)[NDIM])
3933 {
3934  int jj,kk;
3935  FTYPE X[NDIM],V[NDIM];
3936 
3937  //iglobal=i;
3938  //jglobal=j;
3939  //kglobal=k;
3940  //pglobal=loc;
3941 
3942 
3943  if(didstorepositiondata && loc!=NOWHERE){
3944  DLOOP(jj,kk) dxdxp[jj][kk] = GLOBALMETMACP1A2(dxdxpstore,loc,i,j,k,jj,kk);
3945 #if(PRODUCTION==0)
3946  if(i<-N1BND || i>N1-1+SHIFT1+N1BND || j<-N2BND || j>N2-1+SHIFT2+N2BND || k<-N3BND || k>N3-1+SHIFT3+N3BND){
3947  dualfprintf(fail_file,"Beyond stored location: %d %d %d\n",i,j,k);
3948  myexit(10365262);
3949  }
3950 #endif
3951  }
3952  else if(loc!=NOWHERE){
3953  bl_coord_ijk_2(i, j, k, loc, X, V);
3954  dxdxprim(X,V,dxdxp);
3955  }
3956  else{
3957  dualfprintf(fail_file,"dxdxprim_ijk(): No X to compute V or dxdxp ijk=%d %d %d loc=%d\n",i,j,k,loc);
3958  myexit(8813);
3959  }
3960 
3961 }
3962 
3963 
3965 void dxdxprim_ijk_2(struct of_geom *ptrgeom, FTYPE *X, FTYPE *V, FTYPE (*dxdxp)[NDIM])
3966 {
3967  int i,j,k,loc;
3968  int jj,kk;
3969 
3970 
3971 
3972  i=ptrgeom->i;
3973  j=ptrgeom->j;
3974  k=ptrgeom->k;
3975  loc=ptrgeom->p;
3976 
3977  //iglobal=i;
3978  //jglobal=j;
3979  //kglobal=k;
3980  //pglobal=loc;
3981 
3982 
3983  if(didstorepositiondata && loc!=NOWHERE){
3984  DLOOP(jj,kk) dxdxp[jj][kk] = GLOBALMETMACP1A2(dxdxpstore,loc,i,j,k,jj,kk);
3985 #if(PRODUCTION==0)
3986  if(i<-N1BND || i>N1-1+SHIFT1+N1BND || j<-N2BND || j>N2-1+SHIFT2+N2BND || k<-N3BND || k>N3-1+SHIFT3+N3BND){
3987  dualfprintf(fail_file,"Beyond stored location: %d %d %d\n",i,j,k);
3988  myexit(10365263);
3989  }
3990 #endif
3991  }
3992  else if(loc!=NOWHERE){
3993  bl_coord_ijk_2(i, j, k, loc, X, V);
3994  dxdxprim(X,V,dxdxp);
3995  }
3996  else{
3997  dxdxprim(X,V,dxdxp);
3998  }
3999 
4000 }
4001 
4003 void idxdxprim(FTYPE (*dxdxp)[NDIM], FTYPE (*idxdxp)[NDIM])
4004 {
4005 
4006  matrix_inverse(PRIMECOORDS, dxdxp,idxdxp);
4007 
4008 }
4009 
4010 
4011 
4012 
4014 void idxdxprim_ijk(int i, int j, int k, int loc, FTYPE (*idxdxp)[NDIM])
4015 {
4016  int jj,kk;
4017  FTYPE X[NDIM],V[NDIM];
4018  FTYPE dxdxp[NDIM][NDIM];
4019 
4020  //iglobal=i;
4021  //jglobal=j;
4022  //kglobal=k;
4023  //pglobal=loc;
4024 
4025 
4026  if(didstorepositiondata && loc!=NOWHERE){
4027  DLOOP(jj,kk) idxdxp[jj][kk] = GLOBALMETMACP1A2(idxdxpstore,loc,i,j,k,jj,kk);
4028 #if(PRODUCTION==0)
4029  if(i<-N1BND || i>N1-1+SHIFT1+N1BND || j<-N2BND || j>N2-1+SHIFT2+N2BND || k<-N3BND || k>N3-1+SHIFT3+N3BND){
4030  dualfprintf(fail_file,"Beyond stored location: %d %d %d\n",i,j,k);
4031  myexit(10365264);
4032  }
4033 #endif
4034  }
4035  else if(loc!=NOWHERE){
4036  bl_coord_ijk_2(i, j, k, loc, X, V);
4037  dxdxprim(X,V,dxdxp);
4038  idxdxprim(dxdxp,idxdxp);
4039  }
4040  else{
4041  dualfprintf(fail_file,"idxdxprim_ijk(): No X, V, or dxdxp to compute idxdxp\n");
4042  myexit(8814);
4043  }
4044 
4045 }
4046 
4047 
4051 void idxdxprim_ijk_2(struct of_geom *ptrgeom, FTYPE *X, FTYPE *V, FTYPE (*idxdxp)[NDIM])
4052 {
4053  int i,j,k,loc;
4054  int jj,kk;
4055  FTYPE dxdxp[NDIM][NDIM];
4056 
4057 
4058  i=ptrgeom->i;
4059  j=ptrgeom->j;
4060  k=ptrgeom->k;
4061  loc=ptrgeom->p;
4062 
4063  //iglobal=i;
4064  //jglobal=j;
4065  //kglobal=k;
4066  //pglobal=loc;
4067 
4068 
4069  if(didstorepositiondata && loc!=NOWHERE){
4070  // if here, don't assume X and V already set, so set them both:
4071  bl_coord_ijk_2(ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p,X,V);
4072  DLOOP(jj,kk) idxdxp[jj][kk] = GLOBALMETMACP1A2(idxdxpstore,loc,i,j,k,jj,kk);
4073 #if(PRODUCTION==0)
4074  if(i<-N1BND || i>N1-1+SHIFT1+N1BND || j<-N2BND || j>N2-1+SHIFT2+N2BND || k<-N3BND || k>N3-1+SHIFT3+N3BND){
4075  dualfprintf(fail_file,"Beyond stored location: %d %d %d\n",i,j,k);
4076  myexit(10365265);
4077  }
4078 #endif
4079  }
4080  else if(loc!=NOWHERE){
4081  // then assume ptrgeom->{i,j,k} is good for ptrgeom->p
4082  bl_coord_ijk_2(ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p,X,V);
4083  dxdxprim(X,V,dxdxp);
4084  idxdxprim(dxdxp,idxdxp);
4085  }
4086  else{
4087  // if idxdxprim_ijk_2 is called, assume fed in X and V already
4088  dxdxprim(X,V,dxdxp);
4089  idxdxprim(dxdxp,idxdxp);
4090  }
4091 
4092 }
4093 
4094 
4095 
4098 void bl_coord_ijk(int i, int j, int k, int loc, FTYPE *V)
4099 {
4100  int jj;
4101  FTYPE X[NDIM];
4102 
4103  //iglobal=i;
4104  //jglobal=j;
4105  //kglobal=k;
4106  //pglobal=loc;
4107 
4108 
4109 
4110  if(didstorepositiondata && loc!=NOWHERE){
4111  DLOOPA(jj) V[jj] = GLOBALMACP1A1(Vstore,loc,i,j,k,jj);
4112 #if(PRODUCTION==0)
4113  if(i<-N1BND-SHIFT1 || i>N1-1+SHIFT1*2+N1BND || j<-N2BND-SHIFT2 || j>N2-1+SHIFT2*2+N2BND || k<-N3BND-SHIFT3 || k>N3-1+SHIFT3*2+N3BND){
4114  dualfprintf(fail_file,"Beyond stored location: %d %d %d\n",i,j,k);
4115  myexit(10365266);
4116  }
4117 #endif
4118  V[TT]=Xmetricnew[TT];
4119  }
4120  else if(loc!=NOWHERE){
4121  coord(i, j, k, loc, X);
4122  bl_coord(X,V);
4123  }
4124  else{
4125  dualfprintf(fail_file,"bl_coord_ijk(): No X to compute V : ijk=%d %d %d loc=%d\n",i,j,k,loc);
4126  myexit(8815);
4127  }
4128 
4129 
4130 }
4131 
4135 void bl_coord_ijk_2(int i, int j, int k, int loc, FTYPE *X, FTYPE *V)
4136 {
4137  int jj;
4138 
4139  //iglobal=i;
4140  //jglobal=j;
4141  //kglobal=k;
4142  //pglobal=loc;
4143 
4144 
4145  // dualfprintf(fail_file,"i=%d didstorepositiondata=%d loc=%d\n",i,didstorepositiondata,loc);
4146 
4147  if(didstorepositiondata && loc!=NOWHERE){
4148 
4149  coord_ijk(i,j,k,loc,X); // get X
4150 
4151  DLOOPA(jj) V[jj] = GLOBALMACP1A1(Vstore,loc,i,j,k,jj);
4152 #if(PRODUCTION==0)
4153  if(i<-N1BND-SHIFT1 || i>N1-1+SHIFT1*2+N1BND || j<-N2BND-SHIFT2 || j>N2-1+SHIFT2*2+N2BND || k<-N3BND-SHIFT3 || k>N3-1+SHIFT3*2+N3BND){
4154  dualfprintf(fail_file,"Beyond stored location: %d %d %d\n",i,j,k);
4155  myexit(10365267);
4156  }
4157 #endif
4158  V[TT]=Xmetricnew[TT]; // not really true, but dont use V[TT] yet
4159  }
4160  else if(loc!=NOWHERE){
4161  // Assume X is output, not input, if using bl_coord_ijk_?. If didn't know i,j,k, then would have been forced to use bl_coord(X,V) anyways.
4162  coord(i,j,k,loc,X);
4163  bl_coord(X,V);
4164  }
4165  else{
4166  // then must use X directly
4167  bl_coord(X,V);
4168  // if really NOWHERE, then not associated with i,j,k at all, so can't use coord() to get X, so shouldn't be using bl_coord_ijk_2() in first place. But assume X is already set
4169  }
4170 
4171 
4172 }
4173 
4176 void bl_coord_coord(int i, int j, int k, int loc, FTYPE *X, FTYPE *V)
4177 {
4178 
4179  coord(i,j,k,loc,X);
4180  bl_coord(X,V);
4181 
4182 }
4183 
4184 
4187 void coord_ijk(int i, int j, int k, int loc, FTYPE *X)
4188 {
4189  int jj;
4190 
4191  //iglobal=i;
4192  //jglobal=j;
4193  //kglobal=k;
4194  //pglobal=loc;
4195 
4196 
4197  if(didstorepositiondata && loc!=NOWHERE){
4198  DLOOPA(jj) X[jj] = GLOBALMACP1A1(Xstore,loc,i,j,k,jj);
4199 #if(PRODUCTION==0)
4200  if(i<-N1BND-SHIFT1 || i>N1-1+SHIFT1*2+N1BND || j<-N2BND-SHIFT2 || j>N2-1+SHIFT2*2+N2BND || k<-N3BND-SHIFT3 || k>N3-1+SHIFT3*2+N3BND){
4201  dualfprintf(fail_file,"Beyond stored location: %d %d %d\n",i,j,k);
4202  myexit(10365268);
4203  }
4204 #endif
4205  // time is not constant
4206  X[TT] = Xmetricnew[TT];
4207  }
4208  else if(loc!=NOWHERE){
4209  // coord must use i,j,k, so always safe for any loc?
4210  coord(i, j, k, loc, X);
4211  }
4212  else{
4213  dualfprintf(fail_file,"coord_ijk() NOWHERE: Can't use loc=%d to compute X\n",loc);
4214  myexit(8816);
4215  }
4216 
4217 
4218 }
4219 
4220 
4221 
4225 {
4226  FTYPE res;
4227 
4228  if( x <= 0 ) {
4229  res = 0;
4230  }
4231  else if( x >= 1 ) {
4232  res = 1;
4233  }
4234  else {
4235  res = (64 + cos(5*M_PI*x) + 70*sin((M_PI*(-1 + 2*x))/2.) + 5*sin((3*M_PI*(-1 + 2*x))/2.))/128.;
4236  }
4237 
4238  return( res );
4239 }
4240 
4242 {
4243  FTYPE Ftr( FTYPE x );
4244  FTYPE res;
4245 
4246  res = (x*ya)/xa + (-((x*ya)/xa) + ((x - xb)*(1 - yb))/(1 - xb) + yb)*Ftr((x - xa)/(-xa + xb));
4247 
4248  return( res );
4249 }
4250 
4251 FTYPE Ftrgen( FTYPE x, FTYPE xa, FTYPE xb, FTYPE ya, FTYPE yb )
4252 {
4253  FTYPE Ftr( FTYPE x );
4254  FTYPE res;
4255 
4256  res = ya + (yb-ya)*Ftr( (x-xa)/(xb-xa) );
4257 
4258  return( res );
4259 }
4260 
4262 {
4263  FTYPE res;
4264 
4265  if( x <= -1 ) {
4266  res = 0;
4267  }
4268  else if( x >= 1 ) {
4269  res = x;
4270  }
4271  else {
4272  res = (1 + x + (-140*sin((M_PI*(1 + x))/2.) + (10*sin((3*M_PI*(1 + x))/2.))/3. + (2*sin((5*M_PI*(1 + x))/2.))/5.)/(64.*M_PI))/2.;
4273  }
4274 
4275  return( res );
4276 
4277 }
4278 
4279 FTYPE limlin( FTYPE x, FTYPE x0, FTYPE dxx, FTYPE y0 )
4280 {
4281  FTYPE Fangle( FTYPE x );
4282  return( y0 - dxx * Fangle(-(x-x0)/dxx) );
4283 }
4284 
4285 FTYPE minlin( FTYPE x, FTYPE x0, FTYPE dxx, FTYPE y0 )
4286 {
4287  FTYPE Fangle( FTYPE x );
4288  return( y0 + dxx * Fangle((x-x0)/dxx) );
4289 }
4290 
4291 FTYPE mins( FTYPE f1, FTYPE f2, FTYPE df )
4292 {
4293  FTYPE limlin( FTYPE x, FTYPE x0, FTYPE dxx, FTYPE y0 );
4294  return( limlin(f1, f2, df, f2) );
4295 }
4296 
4297 FTYPE maxs( FTYPE f1, FTYPE f2, FTYPE df )
4298 {
4299  FTYPE mins( FTYPE f1, FTYPE f2, FTYPE df );
4300  return( -mins(-f1, -f2, df) );
4301 }
4302 
4303 
4306 FTYPE minmaxs( FTYPE f1, FTYPE f2, FTYPE df, FTYPE dir )
4307 {
4308  FTYPE mins( FTYPE f1, FTYPE f2, FTYPE df );
4309  FTYPE maxs( FTYPE f1, FTYPE f2, FTYPE df );
4310  if( dir>=0 ) {
4311  return( maxs(f1, f2, df) );
4312  }
4313 
4314  return( mins(f1, f2, df) );
4315 }
4316 
4317 static FTYPE sinth0( FTYPE *X0, FTYPE *X, void (*vofx)(FTYPE*, FTYPE*) );
4318 static FTYPE sinth1in( FTYPE *X0, FTYPE *X, void (*vofx)(FTYPE*, FTYPE*) );
4319 static FTYPE th2in( FTYPE *X0, FTYPE *X, void (*vofx)(FTYPE*, FTYPE*) );
4320 static void to1stquadrant( FTYPE *Xin, FTYPE *Xout, int *ismirrored );
4321 static FTYPE func1( FTYPE *X0, FTYPE *X, void (*vofx)(FTYPE*, FTYPE*) );
4322 static FTYPE func2( FTYPE *X0, FTYPE *X, void (*vofx)(FTYPE*, FTYPE*) );
4323 
4328 void to1stquadrant( FTYPE *Xin, FTYPE *Xout, int *ismirrored )
4329 {
4330  FTYPE ntimes;
4331  int dim;
4332 
4333  DLOOPA(dim) Xout[dim] = Xin[dim];
4334 
4335  //bring the angle variables to -2..2 (for X) and -2pi..2pi (for V)
4336  ntimes = floor( (Xin[2]+2.0)/4.0 );
4337  //this forces -2 < Xout[2] < 2
4338  Xout[2] -= 4 * ntimes;
4339 
4340  *ismirrored = 0;
4341 
4342  if( Xout[2] > 0. ) {
4343  Xout[2] = -Xout[2];
4344  *ismirrored = 1-*ismirrored;
4345  }
4346 
4347  //now force -1 < Xout[2] < 0
4348  if( Xout[2] < -1. ) {
4349  Xout[2] = -2. - Xout[2];
4350  *ismirrored = 1-*ismirrored;
4351  }
4352 }
4353 
4355 FTYPE sinth0( FTYPE *X0, FTYPE *X, void (*vofx)(FTYPE*, FTYPE*) )
4356 {
4357  FTYPE V0[NDIM];
4358  FTYPE Vc0[NDIM];
4359  FTYPE Xc0[NDIM];
4360  int dim;
4361 
4362  //X1 = {0, X[1], X0[1], 0}
4363  DLOOPA(dim) Xc0[dim] = X[dim];
4364  Xc0[2] = X0[2];
4365 
4366  vofx( Xc0, Vc0 );
4367  vofx( X0, V0 );
4368 
4369 
4370  return( V0[1] * sin(V0[2]) / Vc0[1] );
4371 }
4372 
4374 FTYPE sinth1in( FTYPE *X0, FTYPE *X, void (*vofx)(FTYPE*, FTYPE*) )
4375 {
4376  FTYPE V[NDIM];
4377  FTYPE V0[NDIM];
4378  FTYPE V0c[NDIM];
4379  FTYPE X0c[NDIM];
4380  int dim;
4381 
4382  //X1 = {0, X[1], X0[1], 0}
4383  DLOOPA(dim) X0c[dim] = X0[dim];
4384  X0c[2] = X[2];
4385 
4386  vofx( X, V );
4387  vofx( X0c, V0c );
4388  vofx( X0, V0 );
4389 
4390  return( V0[1] * sin(V0c[2]) / V[1] );
4391 }
4392 
4393 
4395 FTYPE th2in( FTYPE *X0, FTYPE *X, void (*vofx)(FTYPE*, FTYPE*) )
4396 {
4397  FTYPE V[NDIM];
4398  FTYPE V0[NDIM];
4399  FTYPE Vc0[NDIM];
4400  FTYPE Xc0[NDIM];
4401  FTYPE Xcmid[NDIM];
4402  FTYPE Vcmid[NDIM];
4403  int dim;
4404  FTYPE res;
4405  FTYPE th0;
4406 
4407  DLOOPA(dim) Xc0[dim] = X[dim];
4408  Xc0[2] = X0[2];
4409  vofx( Xc0, Vc0 );
4410 
4411  DLOOPA(dim) Xcmid[dim] = X[dim];
4412  Xcmid[2] = 0;
4413  vofx( Xcmid, Vcmid );
4414 
4415  vofx( X0, V0 );
4416  vofx( X, V );
4417 
4418  th0 = asin( sinth0(X0, X, vofx) );
4419 
4420  res = (V[2] - Vc0[2])/(Vcmid[2] - Vc0[2]) * (Vcmid[2]-th0) + th0;
4421 
4422  return( res );
4423 }
4424 
4431 void vofx_cylindrified( FTYPE *Xin, void (*vofx)(FTYPE*, FTYPE*), FTYPE *Vout )
4432 {
4433  FTYPE npiovertwos;
4434  FTYPE X[NDIM], V[NDIM];
4435  FTYPE Vin[NDIM];
4436  FTYPE X0[NDIM], V0[NDIM];
4437  FTYPE Xtr[NDIM], Vtr[NDIM];
4438  FTYPE f1, f2, dftr;
4439  FTYPE sinth, th;
4440  int dim, ismirrored;
4441 
4442  vofx( Xin, Vin );
4443 
4444  // BRING INPUT TO 1ST QUADRANT: X[2] \in [-1 and 0]
4445  to1stquadrant( Xin, X, &ismirrored );
4446  vofx( X, V );
4447 
4448  //initialize X0: cylindrify region
4449  //X[1] < X0[1] && X[2] < X0[2] (value of X0[3] not used)
4450  X0[0] = Xin[0];
4451  X0[1] = x10;
4452  X0[2] = x20;
4453  X0[3] = 0;
4454  vofx( X0, V0 );
4455 
4456  //{0, roughly midpoint between grid origin and x10, -1, 0}
4457  DLOOPA(dim) Xtr[dim] = X[dim];
4458  Xtr[1] = log( 0.5*( exp(X0[1])+exp(startx[1]) ) ); //always bound to be between startx[1] and X0[1]
4459  vofx( Xtr, Vtr );
4460 
4461  f1 = func1( X0, X, vofx );
4462  f2 = func2( X0, X, vofx );
4463  dftr = func2( X0, Xtr, vofx ) - func1( X0, Xtr, vofx );
4464 
4465  // Compute new theta
4466  sinth = maxs( V[1]*f1, V[1]*f2, Vtr[1]*fabs(dftr)+SMALL ) / V[1];
4467 
4468  th = asin( sinth );
4469 
4470  //initialize Vout with the original values
4471  DLOOPA(dim) Vout[dim] = Vin[dim];
4472 
4473  //apply change in theta in the original quadrant
4474  if( 0 == ismirrored ) {
4475  Vout[2] = Vin[2] + (th - V[2]);
4476  }
4477  else {
4478  //if mirrrored, flip the sign
4479  Vout[2] = Vin[2] - (th - V[2]);
4480  }
4481 }
4482 
4484 FTYPE func1( FTYPE *X0, FTYPE *X, void (*vofx)(FTYPE*, FTYPE*) )
4485 {
4486  FTYPE V[NDIM];
4487 
4488  vofx( X, V );
4489 
4490  return( sin(V[2]) );
4491 }
4492 
4494 FTYPE func2( FTYPE *X0, FTYPE *X, void (*vofx)(FTYPE*, FTYPE*) )
4495 {
4496  FTYPE V[NDIM];
4497  FTYPE Xca[NDIM];
4498  FTYPE func2;
4499  int dim;
4500  FTYPE sth1in, sth2in, sth1inaxis, sth2inaxis;
4501 
4502  //{0, X[1], -1, 0}
4503  DLOOPA(dim) Xca[dim] = X[dim];
4504  Xca[2] = -1;
4505 
4506  vofx( X, V );
4507 
4508  sth1in = sinth1in( X0, X, vofx );
4509  sth2in = sin( th2in(X0, X, vofx) );
4510 
4511  sth1inaxis = sinth1in( X0, Xca, vofx );
4512  sth2inaxis = sin( th2in(X0, Xca, vofx) );
4513 
4514  func2 = minmaxs( sth1in, sth2in, fabs(sth2inaxis-sth1inaxis)+SMALL, X[1] - X0[1] );
4515 
4516  return( func2 );
4517 }
4518 
4519 
4520 
4521 
4522 
4523 
4524 
4525 
4526 
4527 
4528 
4529 
4530 
4531 
4532 
4533 
4534 
4535 
4536 
4537 
4538 
4539 
4540 
4541 
4542 
4543 
4544 
4545 
4546 
4547 
4548 
4549 
4550 
4551 
4552 
4553 
4554 
4555 
4556 
4557 
4558 
4559 
4560 
4561 
4562 
4563 
4564 
4565 
4566 
4567 
4568 
4569