-
Notifications
You must be signed in to change notification settings - Fork 7
/
flux.mergedc2ea2cmethod.c
9394 lines (8796 loc) · 328 KB
/
flux.mergedc2ea2cmethod.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include "decs.h"
/* So good news is that if I just replace FullSimplify by Simplify, then even for 7 products of 2nd order polynomials it can get the result after about 30 minutes that is actually simplified. The optimization format package for C output then helps reduce the redundancy. */
/* FYI, the total number of multiplications is roughly, for each number of products is *twice* the below numbers (one for left and one for right): */
/* 1) 2 */
/* 2) 12 - 15 */
/* 3) 46 - 50 */
/* 4) 92 - 120 */
/* 5) 229 - 250 */
/* 6) 381 - 400 */
/* 7) 628 - 700 */
/* So things scale roughly as a power of 2 at large product number, which make sense. */
/* I have to do this for both matter and electromagnetic terms, that involve *each* of the 3 dimensions doing: */
/* Matter terms seem quite simple. In the most general case one has for *each* left and right fluxes */
/* RHO: 3-product (\detg \rho_0 u^i) */
/* UU,U1,U2,U3 each: 4-product (\detg [ (\rho_0 + u + p)u^\mu u_\nu] ) */
/* U^{dir} 2-product (\detg [ p \delta^\mu_\nu ] ) */
/* For the EM terms it's much more involved: */
/* UU-U3 each: This one is crazy! One has most generally for each of the 4 EOMs: */
/* 3X 7-product (\detg/(u^t)^2) (B^2 u^\mu u_\nu) */
/* 3X 5-product (\detg/(u^t)^2) ( (1/2)B^2 \delta^\mu_\nu) */
/* 6X 7-product (\detg/(u^t)^2) ( (1/2)(u_i B^i)^2 \delta^\mu_\nu) */
/* 1X 5-product (\detg/(u^t)^2) (B^\mu B_\nu) */
/* 3X 7-product (\detg/(u^t)^2) (B^\mu u_\nu (u_i B^i)) */
/* 3X 7-product (\detg/(u^t)^2) (u^\mu B_\nu (u_i B^i)) */
/* The explosion in the number of terms is because of the vector nature of the field. */
/* B1,B2,B3 each: 3-product but has to be done in 2D not 1D (i.e. simultaneous deconvolution in both directions in plane). This I've not done yet. I expect it to be similar to a 6-product in complexity: \detg (B^i v^j - B^j v^i) */
/* Now, an important point is that for the EMF I interpolation the 3-velocity since it would require many more interpolations to interpolate the 4-velocity to the corner. So I suppose it wouldn't be crazy to also interpolate the 3-velocity in the stress-energy tensor. For the 7-products, this reduces it to a 5-product. It doesn't help the 5-products that have no 4-velocity to absorb into them. This would be overall more similar to using the 4-field but where I've analytically canceled that bad \gamma^2 term (or after division by \gamma^2 is a bad order unity term where other terms are divided by \gamma of some power). */
/* My question is how bad do you think this is to treat the 3-velocity instead of the 4-velocity? As you know the 3-velocity is not used in HARM for the *primitive* interpolation because at the interface the metric has changed and the 3-velocity there can easily imply no solution (i.e. \gamma is complex). That's certainly bad. */
/* However, the flux correction is local, so the metric is unchanged. That is, even though we use a distribution in all quantities, we only actually use their dependence at the location we get the correction. The 0th order flux will be no different since the face values are as from interpolating the primitives as however we choose them and normally involve good 4-velocities. */
/* I think it would be bad to group, e.g., u.B or B^2 together for the same reason that directly interpolating u.B or B^2 is a bad idea as we know. At least for B^2, when the sign changes in B but B^2 is constant, then the interpolation wouldn't be aware of this. */
/* However, at the same time, if B^2 is directly manifested in the EOM, then any result of it won't be affected by that sign issue. The only concern then is perhaps that B^2 is treated to a lower accuracy as a parabola. It may be that this B^2 is exactly the thing that creates the error when B^2/\rho_0\gg 1, so I'm quite weary of grouping B's together. */
/* Any thoughts? Perhaps we can chat for less than an hour some time if you have any thoughts since typing is not a good idea. */
// local declarations
static int deconvolve_flux(int dir, int odir1, int odir2, FTYPE *EOSextra, struct of_state *stateleft, struct of_state *statecent, struct of_state *stateright, FTYPE *Fleft, FTYPE *Fright);
static int deconvolve_flux_ma(int dir, int odir1, int odir2, FTYPE *EOSextra, struct of_state *stateleft, struct of_state *statecent, struct of_state *stateright, FTYPE *Fleft, FTYPE *Fright);
static int deconvolve_flux_em(int dir, int odir1, int odir2, FTYPE *EOSextra, struct of_state *stateleft, struct of_state *statecent, struct of_state *stateright, FTYPE *Fleft, FTYPE *Fright);
static int onetermdeconvolution(
FTYPE rhol, FTYPE rhoc, FTYPE rhor
,FTYPE *Fleft, FTYPE *Fright
);
static int twotermdeconvolution(
FTYPE rhol, FTYPE rhoc, FTYPE rhor
,FTYPE udirl, FTYPE udirc, FTYPE udirr
,FTYPE *Fleft, FTYPE *Fright
);
static int threetermdeconvolution(
FTYPE gdetl, FTYPE gdetc, FTYPE gdetr
,FTYPE rhol, FTYPE rhoc, FTYPE rhor
,FTYPE udirl, FTYPE udirc, FTYPE udirr
,FTYPE *Fleft, FTYPE *Fright
);
static int fourtermdeconvolution(
FTYPE gdetl, FTYPE gdetc, FTYPE gdetr
,FTYPE rhol, FTYPE rhoc, FTYPE rhor
,FTYPE udirl, FTYPE udirc, FTYPE udirr
,FTYPE udnul, FTYPE udnuc, FTYPE udnur
,FTYPE *Fleft, FTYPE *Fright
);
static int fivetermdeconvolution(
FTYPE gdetl, FTYPE gdetc, FTYPE gdetr
,FTYPE Bconl, FTYPE Bconc, FTYPE Bconr
,FTYPE Bcovl, FTYPE Bcovc, FTYPE Bcovr
,FTYPE uu0l, FTYPE uu0c, FTYPE uu0r
,FTYPE ud0l, FTYPE ud0c, FTYPE ud0r
,FTYPE *Fleft, FTYPE *Fright
);
static int sixtermdeconvolution(
FTYPE gdetl, FTYPE gdetc, FTYPE gdetr
,FTYPE Bconl, FTYPE Bconc, FTYPE Bconr
,FTYPE Bcovl, FTYPE Bcovc, FTYPE Bcovr
,FTYPE uu0l, FTYPE uu0c, FTYPE uu0r
,FTYPE ud0l, FTYPE ud0c, FTYPE ud0r
,FTYPE udnul, FTYPE udnuc, FTYPE udnur
,FTYPE *Fleft, FTYPE *Fright
);
static int seventermdeconvolution(
FTYPE gdetl, FTYPE gdetc, FTYPE gdetr
,FTYPE Bconl, FTYPE Bconc, FTYPE Bconr
,FTYPE Bcovl, FTYPE Bcovc, FTYPE Bcovr
,FTYPE uu0l, FTYPE uu0c, FTYPE uu0r
,FTYPE ud0l, FTYPE ud0c, FTYPE ud0r
,FTYPE udnul, FTYPE udnuc, FTYPE udnur
,FTYPE uunul, FTYPE uunuc, FTYPE uunur
,FTYPE *Fleft, FTYPE *Fright
);
static int twoterm2Ddeconvolution(
FTYPE Bconc,FTYPE Bconld, FTYPE Bconrd, FTYPE Bconlu, FTYPE Bconru, FTYPE Bconl, FTYPE Bconr, FTYPE Bcond, FTYPE Bconu
,FTYPE vconc,FTYPE vconld, FTYPE vconrd, FTYPE vconlu, FTYPE vconru, FTYPE vconl, FTYPE vconr, FTYPE vcond, FTYPE vconu
,FTYPE *Fld, FTYPE *Frd, FTYPE *Flu, FTYPE *Fru
);
static int threeterm2Ddeconvolution(
FTYPE gdetc,FTYPE gdetld, FTYPE gdetrd, FTYPE gdetlu, FTYPE gdetru, FTYPE gdetl, FTYPE gdetr, FTYPE gdetd, FTYPE gdetu
,FTYPE Bconc,FTYPE Bconld, FTYPE Bconrd, FTYPE Bconlu, FTYPE Bconru, FTYPE Bconl, FTYPE Bconr, FTYPE Bcond, FTYPE Bconu
,FTYPE vconc,FTYPE vconld, FTYPE vconrd, FTYPE vconlu, FTYPE vconru, FTYPE vconl, FTYPE vconr, FTYPE vcond, FTYPE vconu
,FTYPE *Fld, FTYPE *Frd, FTYPE *Flu, FTYPE *Fru
);
static int a2cflux_from_prim(int dir, FTYPE (*prim_coef_list)[MAXSPACEORDER]);
static int deconvolve_emf_1d(int corner, int odir1, int odir2, int *Nvec, int *NNOT1vec, int i, int j, int k, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR]);
static int deconvolve_emf_2d(int corner, int odir1, int odir2, int *Nvec, int *NNOT1vec, int i, int j, int k, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR]);
//TODO:
//1) Setup fully 3D SPC setup:
//a) Just average (somehow) flux, using \delta term that is larger, not just average?
//b) Test in 1D with (e.g.) shock.
// NOTE: When called with merged method, the flux loop over which compute_and_store_fluxstate() is called should have been over slightly larger range to store the full cell's left-right values (e.g. for i=-1 we compute interpolation and normally only need pright -> p_l[0] -> F[0], but for merged method we also need pleft->p_r[-1] to do a2c -> F[0] as well)
// TODO:
// 1) Worry about boundary edges and that don't store entire cell interpolation at very edges where only previously needed flux at face. Might need to store more p_l, p_r, pl_ct, pr_ct, and state info
// a) For stag method also need to *compute* additional interpolation to other corners at outer-most grid points not where EMF is computed but part of same cell
// b) For non-stag method, already compute interpolation to outermost face not where computing flux, but don't store or compute state for it yet
// 2) Work out rest of EM stress-energy tensor
// 3) Work out EMF sorting issue
// 4)
// get corner \detg for EMF calculation when doing merged method
// Only needed when CORNGDETVERSION==1, since otherwise \detg already put into field that goes into EMF
void store_geomcorn(int corner, int odir1, int odir2,FTYPE (*geomcorn)[NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3])
{
int is,ie,js,je,ks,ke,di,dj,dk;
int i,j,k;
struct of_gdetgeom geomcorndontuse;
struct of_gdetgeom *ptrgeomcorn=&geomcorndontuse;
#if(MERGEDC2EA2CMETHODEM&&FIELDSTAGMEM)
// then supposed to be here
#else
dualfprintf(fail_file,"Why doing store_geomcorn()?\n");
myexit(3468346);
#endif
// define loop range
set_interppoint_loop_ranges_geomcorn_formerged(ENOINTERPTYPE, corner, odir1, odir2, &is, &ie, &js, &je, &ks, &ke, &di, &dj, &dk);
// loop over all i,j,k
COMPZSLOOP(is,ie,js,je,ks,ke){
// assume ptrgeom->g all that's needed, not ptrgeom->EOMFUNCMAC(pl) since for field ptrgeom->EOMFUNCMAC's must be consistent!
get_geometry_gdetonly(i, j, k, CORN1-1+corner, ptrgeomcorn); // at CORN[dir]
// then need to store geometry for merged method
MACP1A0(geomcorn,corner,i,j,k)=ptrgeomcorn->gdet; // SUPERGODMARK: Should be avoided since already stored metric if doing new method
}// end loop over i,j,k
}
// used for flux.mergedc2aa2cmethod.c to obtain values necessary for 2D deconvolution
// return \detg B^i always, instead of ever B^i alone
// Note velocity needs to be 3-velocity corresponding to 3-field
// This means v^i = u^i/u^t in lab-frame and B^i = *F^{it}
// vcon1/2 and Bcon1/2 correspond to vcon[odir1/odir2] and Bcon[odir1/odir2] referenced from dir=corner
// below left/right are as for emf with NUMCS data size. Here added CENT4EMF for centered position
//
// NEWMARK: Need to work out signature issues
//
int setup_9value_vB(int corner, int odir1, int odir2, int *Nvec, int *NNOT1vec, int i, int j, int k,
// FTYPE (*pbcorn)[COMPDIM][NUMCS][NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3],
FTYPE (*pvbcorn)[NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3][COMPDIM][NUMCS+1][NUMCS],
struct of_state (*fluxstatecent)[NSTORE2][NSTORE3],
struct of_state (*fluxstate)[NSTORE1][NSTORE2][NSTORE3][NUMLEFTRIGHT],
FTYPE (*geomcorn)[NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3],
FTYPE (*vcon)[NUMCS+1][NUMCS+1],
FTYPE (*gdetBcon)[NUMCS+1][NUMCS+1]
)
{
int ileft, jleft, kleft;
int irightodir1, jrightodir1, krightodir1;
int irightodir2, jrightodir2, krightodir2;
int ijkdimen,ijkcorn[NDIM][NUMCS+1][NUMCS+1];
FTYPE localgeomcorn;
int m,l;
int ii,jj,kk;
#if(MERGEDC2EA2CMETHOD)
// face and cent values
// MACP1A1(fluxstate,dimen,i,j,k,ISLEFT)
// MAC(fluxstatecent,i,j,k)
// MACP1A1(fluxstate,dimen,i,j,k,ISRIGHT)
// OPTMARK: Should compute these things outside ijk loop and pass to this function
// left-flux position (centered or left in odir1 and/or odir2)
ileft=i;
jleft=j;
kleft=k;
// right-flux position for odir1 direction and centered in odir2 dir
irightodir1=i+(1==odir1)*N1NOT1;
jrightodir1=j+(2==odir1)*N2NOT1;
krightodir1=k+(3==odir1)*N3NOT1;
// right-flux position for odir2 direction and centered in odir1 dir
irightodir2=i+(1==odir2)*N1NOT1;
jrightodir2=j+(2==odir2)*N2NOT1;
krightodir2=k+(3==odir2)*N3NOT1;
// +-odir1 and +-odir2 w.r.t. cell center
// set default i,j,k position
// DIMENLOOP(ijkdimen){
for(m=0;m<NUMCS;m++){
for(l=0;l<NUMCS;l++){
ijkcorn[1][m][l]=i;
ijkcorn[2][m][l]=j;
ijkcorn[3][m][l]=k;
}
}
//}
// shift i,j,k up only as required
// shift each
ijkcorn[odir1][RIGHT4EMF][LEFT4EMF]+=NNOT1vec[odir1];
ijkcorn[odir2][LEFT4EMF][RIGHT4EMF]+=NNOT1vec[odir2];
// shift both
ijkcorn[odir1][RIGHT4EMF][RIGHT4EMF]+=NNOT1vec[odir1];
ijkcorn[odir2][RIGHT4EMF][RIGHT4EMF]+=NNOT1vec[odir2];
/////////////////////
//
// lab-frame 3-velocity: v^i
// lab-frame 3-field: B^i
//
/////////////////////
// cent-cent
vcon[odir1][CENT4EMF][CENT4EMF]=MAC(fluxstatecent,i,j,k).vcon[odir1]; // v^{odir1} = u^{odir1}/u^t
vcon[odir2][CENT4EMF][CENT4EMF]=MAC(fluxstatecent,i,j,k).vcon[odir2]; // v^{odir2} = u^{odir2}/u^t
gdetBcon[odir1][CENT4EMF][CENT4EMF]=MAC(fluxstatecent,i,j,k).gdetBcon[odir1]; // \detg B^{odir1}
gdetBcon[odir2][CENT4EMF][CENT4EMF]=MAC(fluxstatecent,i,j,k).gdetBcon[odir2]; // \detg B^{odir2}
// left-center (note: As in flux.mergedc2ea2cmethod.c, position of left value is stored in local cell's ISRIGHT)
vcon[odir1][LEFT4EMF][CENT4EMF]=MACP1A1(fluxstate,odir1,ileft,jleft,kleft,ISRIGHT).vcon[odir1]; // v^{odir1} = u^{odir1}/u^t
vcon[odir2][LEFT4EMF][CENT4EMF]=MACP1A1(fluxstate,odir1,ileft,jleft,kleft,ISRIGHT).vcon[odir2]; // v^{odir2} = u^{odir2}/u^t
gdetBcon[odir1][LEFT4EMF][CENT4EMF]=MACP1A1(fluxstate,odir1,ileft,jleft,kleft,ISRIGHT).gdetBcon[odir1]; // // \detg B^{odir1}
gdetBcon[odir2][LEFT4EMF][CENT4EMF]=MACP1A1(fluxstate,odir1,ileft,jleft,kleft,ISRIGHT).gdetBcon[odir2]; // // \detg B^{odir2}
// right-center
vcon[odir1][RIGHT4EMF][CENT4EMF]=MACP1A1(fluxstate,odir1,irightodir1,jrightodir1,krightodir1,ISLEFT).vcon[odir1]; // v^{odir1} = u^{odir1}/u^t
vcon[odir2][RIGHT4EMF][CENT4EMF]=MACP1A1(fluxstate,odir1,irightodir1,jrightodir1,krightodir1,ISLEFT).vcon[odir2]; // v^{odir2} = u^{odir2}/u^t
gdetBcon[odir1][RIGHT4EMF][CENT4EMF]=MACP1A1(fluxstate,odir1,irightodir1,jrightodir1,krightodir1,ISLEFT).gdetBcon[odir1];
gdetBcon[odir2][RIGHT4EMF][CENT4EMF]=MACP1A1(fluxstate,odir1,irightodir1,jrightodir1,krightodir1,ISLEFT).gdetBcon[odir2];
// center-left
vcon[odir1][CENT4EMF][LEFT4EMF]=MACP1A1(fluxstate,odir2,ileft,jleft,kleft,ISRIGHT).vcon[odir1];
vcon[odir2][CENT4EMF][LEFT4EMF]=MACP1A1(fluxstate,odir2,ileft,jleft,kleft,ISRIGHT).vcon[odir2];
gdetBcon[odir1][CENT4EMF][LEFT4EMF]=MACP1A1(fluxstate,odir2,ileft,jleft,kleft,ISRIGHT).gdetBcon[odir1];
gdetBcon[odir2][CENT4EMF][LEFT4EMF]=MACP1A1(fluxstate,odir2,ileft,jleft,kleft,ISRIGHT).gdetBcon[odir2];
// right-center
vcon[odir1][CENT4EMF][RIGHT4EMF]=MACP1A1(fluxstate,odir2,irightodir2,jrightodir2,krightodir2,ISLEFT).vcon[odir1];
vcon[odir2][CENT4EMF][RIGHT4EMF]=MACP1A1(fluxstate,odir2,irightodir2,jrightodir2,krightodir2,ISLEFT).vcon[odir2];
gdetBcon[odir1][CENT4EMF][RIGHT4EMF]=MACP1A1(fluxstate,odir2,irightodir2,jrightodir2,krightodir2,ISLEFT).gdetBcon[odir1];
gdetBcon[odir2][CENT4EMF][RIGHT4EMF]=MACP1A1(fluxstate,odir2,irightodir2,jrightodir2,krightodir2,ISLEFT).gdetBcon[odir2];
//////////////////
//
// CORNER lab-frame 3-velocity: v^i and B^i
//
//////////////////
// pvcorn[which corner][which component in pl form][+-odir1][+-odir2]
// pbcorn[which corner][which component in pl form][+-remaining direction that is not corn nor pl-dir]
// for example, emf3[+-x][+-y] = By[+-x]*vx[+-x][+-y] - Bx[+-y]*vy[+-x][+-y]
// -odir1 -odir2 w.r.t. cell center i,j,k
ii=ijkcorn[1][LEFT4EMF][LEFT4EMF];
jj=ijkcorn[2][LEFT4EMF][LEFT4EMF];
kk=ijkcorn[3][LEFT4EMF][LEFT4EMF];
vcon[odir1][LEFT4EMF][LEFT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir1,RIGHT4EMF,RIGHT4EMF);
vcon[odir2][LEFT4EMF][LEFT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir2,RIGHT4EMF,RIGHT4EMF);
// +odir1 -odir2
ii=ijkcorn[1][RIGHT4EMF][LEFT4EMF];
jj=ijkcorn[2][RIGHT4EMF][LEFT4EMF];
kk=ijkcorn[3][RIGHT4EMF][LEFT4EMF];
vcon[odir1][RIGHT4EMF][LEFT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir1,LEFT4EMF,RIGHT4EMF);
vcon[odir2][RIGHT4EMF][LEFT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir2,LEFT4EMF,RIGHT4EMF);
// -odir1 +odir2
ii=ijkcorn[1][LEFT4EMF][RIGHT4EMF];
jj=ijkcorn[2][LEFT4EMF][RIGHT4EMF];
kk=ijkcorn[3][LEFT4EMF][RIGHT4EMF];
vcon[odir1][LEFT4EMF][RIGHT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir1,RIGHT4EMF,LEFT4EMF);
vcon[odir2][LEFT4EMF][RIGHT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir2,RIGHT4EMF,LEFT4EMF);
// +odir1 +odir2
ii=ijkcorn[1][RIGHT4EMF][RIGHT4EMF];
jj=ijkcorn[2][RIGHT4EMF][RIGHT4EMF];
kk=ijkcorn[3][RIGHT4EMF][RIGHT4EMF];
vcon[odir1][RIGHT4EMF][RIGHT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir1,LEFT4EMF,LEFT4EMF);
vcon[odir2][RIGHT4EMF][RIGHT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir2,LEFT4EMF,LEFT4EMF);
//////////////////
//
// CORNER lab-frame 3-field: B^i
//
// Note pbcorn[corner][B1-1+odir1][LEFT4EMF][iodir1] = pbcorn[corner][B1-1+odir1][RIGHT4EMF][iodir1], so within an i,j,k cell, field along itself on upper edge is obtained from LEFT @ iodir+1, not right that doesn't exist
// That is, pbcorn[LEFT4EMF/RIGHT4EMF] always refers to transverse direction to field pl-direction
//
//////////////////
////////////////////////
//
// first deal with geometry to be consistent with how stored pbcorn[] when doing face2corn()
//
////////////////////////
// -odir1 -odir2 w.r.t. cell center i,j,k
ii=ijkcorn[1][LEFT4EMF][LEFT4EMF];
jj=ijkcorn[2][LEFT4EMF][LEFT4EMF];
kk=ijkcorn[3][LEFT4EMF][LEFT4EMF];
#if(CORNGDETVERSION==1)
// means pbcorn has no \detg, so must put it back
localgeomcorn=MACP1A0(geomcorn,corner,ii,jj,kk); // SUPERGODMARK: Should use stored metric at whatever location required
#else
// means pbcorn has \detg already
localgeomcorn=1.0;
#endif
gdetBcon[odir1][LEFT4EMF][LEFT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir1,NUMCS,RIGHT4EMF)*localgeomcorn;
gdetBcon[odir2][LEFT4EMF][LEFT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir2,NUMCS,RIGHT4EMF)*localgeomcorn;
// +odir1 -odir2 w.r.t. cell center i,j,k
ii=ijkcorn[1][RIGHT4EMF][LEFT4EMF];
jj=ijkcorn[2][RIGHT4EMF][LEFT4EMF];
kk=ijkcorn[3][RIGHT4EMF][LEFT4EMF];
#if(CORNGDETVERSION==1)
// means pbcorn has no \detg, so must put it back
localgeomcorn=MACP1A0(geomcorn,corner,ii,jj,kk);
#else
// means pbcorn has \detg already
localgeomcorn=1.0;
#endif
gdetBcon[odir1][RIGHT4EMF][LEFT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir1,NUMCS,RIGHT4EMF)*localgeomcorn;
gdetBcon[odir2][RIGHT4EMF][LEFT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir2,NUMCS,LEFT4EMF)*localgeomcorn;
// -odir1 +odir2 w.r.t. cell center i,j,k
ii=ijkcorn[1][LEFT4EMF][RIGHT4EMF];
jj=ijkcorn[2][LEFT4EMF][RIGHT4EMF];
kk=ijkcorn[3][LEFT4EMF][RIGHT4EMF];
#if(CORNGDETVERSION==1)
// means pbcorn has no \detg, so must put it back
localgeomcorn=MACP1A0(geomcorn,corner,ii,jj,kk);
#else
// means pbcorn has \detg already
localgeomcorn=1.0;
#endif
gdetBcon[odir1][LEFT4EMF][RIGHT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir1,NUMCS,LEFT4EMF)*localgeomcorn;
gdetBcon[odir2][LEFT4EMF][RIGHT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir2,NUMCS,RIGHT4EMF)*localgeomcorn;
// +odir1 +odir2 w.r.t. cell center i,j,k
ii=ijkcorn[1][RIGHT4EMF][RIGHT4EMF];
jj=ijkcorn[2][RIGHT4EMF][RIGHT4EMF];
kk=ijkcorn[3][RIGHT4EMF][RIGHT4EMF];
#if(CORNGDETVERSION==1)
// means pbcorn has no \detg, so must put it back
localgeomcorn=MACP1A0(geomcorn,corner,ii,jj,kk);
#else
// means pbcorn has \detg already
localgeomcorn=1.0;
#endif
gdetBcon[odir1][RIGHT4EMF][RIGHT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir1,NUMCS,LEFT4EMF)*localgeomcorn;
gdetBcon[odir2][RIGHT4EMF][RIGHT4EMF]=MACP1A3(pvbcorn,corner,ii,jj,kk,odir2,NUMCS,LEFT4EMF)*localgeomcorn;
#endif// end if merged method
return(0);
}
// used to obtain 1-D line in case where EMF only varies in one transverse direction rather than 2 transverse directions
// OPTMARK: for now don't optimize, just get full 9 value and return along needed line
int setup_3value_vB(int corner, int odir1, int odir2, int *Nvec, int *NNOT1vec, int i, int j, int k,
// FTYPE (*pbcorn)[COMPDIM][NUMCS][NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3],
FTYPE (*pvbcorn)[NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3][COMPDIM][NUMCS+1][NUMCS],
struct of_state (*fluxstatecent)[NSTORE2][NSTORE3],
struct of_state (*fluxstate)[NSTORE1][NSTORE2][NSTORE3][NUMLEFTRIGHT],
FTYPE (*geomcorn)[NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3],
FTYPE (*vcon)[NUMCS+1],
FTYPE (*gdetBcon)[NUMCS+1]
)
{
int setup_9value_vB(int corner, int odir1, int odir2, int *Nvec, int *NNOT1vec, int i, int j, int k,
// FTYPE (*pbcorn)[COMPDIM][NUMCS][NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3],
FTYPE (*pvbcorn)[NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3][COMPDIM][NUMCS+1][NUMCS],
struct of_state (*fluxstatecent)[NSTORE2][NSTORE3],
struct of_state (*fluxstate)[NSTORE1][NSTORE2][NSTORE3][NUMLEFTRIGHT],
FTYPE (*geomcorn)[NSTORE1+SHIFTSTORE1][NSTORE2+SHIFTSTORE2][NSTORE3+SHIFTSTORE3],
FTYPE (*vcon)[NUMCS+1][NUMCS+1],
FTYPE (*gdetBcon)[NUMCS+1][NUMCS+1]
);
FTYPE vcon9[NDIM][NUMCS+1][NUMCS+1];
FTYPE gdetBcon9[NDIM][NUMCS+1][NUMCS+1];
int jj;
int positer;
int refodir1,refodir2;
int odir1pos,odir2pos;
setup_9value_vB(corner, odir1, odir2 , Nvec, NNOT1vec, i,j,k, pvbcorn,fluxstatecent,fluxstate,geomcorn, vcon9 ,gdetBcon9 );
// choose starting position for positer loop
// This chooses relevant odir direction for positer loop below
// use of CENT4EMF as opposed to other positions is not relevant if using setup_9value_vB()
refodir1=NNOT1vec[odir1]*START4EMF + (1-NNOT1vec[odir1])*CENT4EMF;
refodir2=NNOT1vec[odir2]*START4EMF + (1-NNOT1vec[odir2])*CENT4EMF;
SLOOPA(jj){ // OPTMARK: not all jj are needed, just the odir1 and odir2 components, so could somehow skip jj==corner if it avoided conditional and that might be better
for(positer=0;positer<NUMPOS4EMF;positer++){
odir1pos=refodir1+positer*NNOT1vec[odir1];
odir2pos=refodir2+positer*NNOT1vec[odir2];
vcon[jj][positer]=vcon9[jj][odir1pos][odir2pos];
gdetBcon[jj][positer]=gdetBcon9[jj][odir1pos][odir2pos];
}
}
return(0);
}
// called from flux.c from fluxcalc() after all dimensions fluxes are computed and need to correct
void mergedc2ea2cmethod_compute(int *Nvec, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR])
{
int dimen;
int corner;
FTYPE Fleft[NPR],Fright[NPR];
int is,ie,js,je,ks,ke,di,dj,dk;
int i,j,k;
int ileft,jleft,kleft;
int iright,jright,kright;
int pl,pliter;
int odir1,odir2;
int odimen1,odimen2;
int NNOT1vec[NDIM];
// setup which directions are not 1 in size
NNOT1vec[0]=0;
NNOT1vec[1]=N1NOT1;
NNOT1vec[2]=N2NOT1;
NNOT1vec[3]=N3NOT1;
// avoid changing EMFs if doing FLUXB==FLUXCTTOTH since this merged call is after the FLUXCTTOTH correction in flux.c
// No correction if Nvec[dimen]==1
// We loop over i,j,k corresponding to center of cell that has primitive distribution within it that will be used to update the conserved quantity at CENT
// fluxes are corrected on edges of this box
// NOTE: Uses global variables fluxstate and fluxstatecent
DIMENLOOP(dimen){
if(Nvec[dimen]>1){
get_odirs(dimen,&odimen1,&odimen2);
// define loop range
// loop range should be same as where computed fluxes, or where formed primitive interpolation, as in interppoint.c:
// set range of positions interpolated to (di,dj,dk useless)
set_interppoint_loop_ranges(ENOINTERPTYPE, dimen, &is, &ie, &js, &je, &ks, &ke, &di, &dj, &dk);
// loop over all i,j,k
COMPZSLOOP(is,ie,js,je,ks,ke){
// initialize Fleft and Fright updates
PLOOP(pliter,pl){
Fleft[pl]=Fright[pl]=0.0;
}
// left-flux position
ileft=i;
jleft=j;
kleft=k;
// right-flux position
iright=i+(1==dimen)*N1NOT1;
jright=j+(2==dimen)*N2NOT1;
kright=k+(3==dimen)*N3NOT1;
// deconvolve flux
// Note meaning of Fleft and Fright is not same as F_l and F_r:
//
// | F_l|F_r |
// | fs[ISLEFT][i]|fs[ISRIGHT][i] fs[ISLEFT][i+1]|
// | | i |
// | | |
// | |Fleft Fright|
// | |fluxvec |
// | | EOSextra |
//
// Assume EOSextra can be DONOR accurate
// And note that F_l=fluxstate[ISLEFT] and F_r=fluxstate[ISRIGHT]
// so single cell needs Fleft=state[ISRIGHT][i] and Fright=state[ISLEFT][i+1]
// And note that fluxvec is single-valued at face and so naturally identified by [i] for cell [i]
// So Fleft modifies fluxvec[i] and Fright modifies fluxvec[i+1]
//
deconvolve_flux(dimen, odimen1, odimen2, GLOBALMAC(EOSextraglobal,i,j,k), &GLOBALMACP1A1(fluxstate,dimen,ileft,jleft,kleft,ISRIGHT), &GLOBALMAC(fluxstatecent,i,j,k), &GLOBALMACP1A1(fluxstate,dimen,iright,jright,kright,ISLEFT), Fleft, Fright);
// Now realize that at faces each correction is applied ultimately as average of 2 fluxes for non-EMF terms
// ultimately if smooth, then is actually full correction since both sides of face will contribute same correction
// Note that using interpolation loop means apply correction beyond where needed, but this is ok as long as 2 boundary condition cells (for upper edge) and 1 for lower edge
// correct flux on left part of cell
PLOOP(pliter,pl) MACP1A1(fluxvec,dimen,ileft,jleft,kleft,pl) += 0.5*Fleft[pl];
// correct flux on right part of cell
PLOOP(pliter,pl) MACP1A1(fluxvec,dimen,iright,jright,kright,pl) += 0.5*Fright[pl];
}// end over i,j,k
}// end if dimension exists
}// end over dimensions
// TODO: GODMARK: Not done --
if(MERGEDC2EA2CMETHODEM&&(FLUXB==FLUXCTSTAG)){ // STAG has information at corners, while FLUXCTTOTH and FLUXCTHLL methods don't
// Don't apply EMF correct if doing Toth method since inconsistent with Toth averaging
// NOTE: Uses global variables fluxstate and fluxstatecent
DIMENLOOP(corner){
get_odirs(corner,&odir1,&odir2);
if(!(Nvec[odir1]==1 && Nvec[odir2]==1)){
// only here if doing correction with non-zero (non-cancelling) EMF
if(CORNGDETVERSION==1){
// need to get corner geometry over all domain before processing EMF
// OPTMARK: if metric is changing, then need to do this every time, else could avoid
store_geomcorn(corner,odir1,odir2,GLOBALPOINT(geomcornglobal));
}
// set range of positions interpolated to (di,dj,dk useless)
// loop range should be over all cell centers that have a final flux on one face (upper or lower) that needs to be corrected
set_interppoint_loop_ranges_2D_EMF_formerged(ENOINTERPTYPE, corner, odir1, odir2, &is, &ie, &js, &je, &ks, &ke, &di, &dj, &dk);
// deconvolve flux
if(Nvec[odir1]==1 || Nvec[odir2]==1){
// then only need to do 1D deconvolution in odir2 direction
// e.g. if corner=CORN2, then odir1=3 and odir2=1 and in 2D(N1>1 and N2>1 and N3==1), then correction of E2 in odir2=1 needs to be done.
// e.g. cont. In this limit, deconvolution is 1D and takes place using values at FACE1(i), CENT(i), FACE1(i+1) since no offset in odir1=3 direction as would be true if N3>1
//
// loop over all i,j,k
COMPZSLOOP(is,ie,js,je,ks,ke){
deconvolve_emf_1d(corner, odir1, odir2, Nvec, NNOT1vec, i,j,k, fluxvec);
}
}
else{
// full 2D deconvolution
// correction done inside
// loop over all i,j,k
COMPZSLOOP(is,ie,js,je,ks,ke){
deconvolve_emf_2d(corner, odir1, odir2, Nvec, NNOT1vec, i,j,k, fluxvec);
}
}
}// end if emf has transverse direction to correct
}// end over corners
}
}
// should operate on a single dimension
// can turn on/off MA or EM terms separately
static int deconvolve_flux(int dir, int odir1, int odir2, FTYPE *EOSextra, struct of_state *stateleft, struct of_state *statecent, struct of_state *stateright, FTYPE *Fleft, FTYPE *Fright)
{
#if(MERGEDC2EA2CMETHODMA)
// do matter parts first
deconvolve_flux_ma(dir, odir1, odir2, EOSextra, stateleft, statecent, stateright, Fleft, Fright);
#endif
#if(MERGEDC2EA2CMETHODEM)
// then do EM parts
deconvolve_flux_em(dir, odir1, odir2, EOSextra, stateleft, statecent, stateright, Fleft, Fright);
#endif
return(0);
}
// should operate on a single dimension
static int deconvolve_flux_ma(int dir, int odir1, int odir2, FTYPE *EOSextra, struct of_state *stateleft, struct of_state *statecent, struct of_state *stateright, FTYPE *Fleft, FTYPE *Fright)
{
FTYPE gdetl,gdetc,gdetr;
FTYPE rhol,rhoc,rhor;
FTYPE iel,iec,ier;
FTYPE pressl,pressc,pressr;
FTYPE udirl,udirc,udirr;
FTYPE udnul,udnuc,udnur;
FTYPE Flefttemp,Frighttemp;
FTYPE Fpressleft,Fpressright;
int jj;
FTYPE genucovl[NDIM];
FTYPE genucovc[NDIM];
FTYPE genucovr[NDIM];
// use fluxstate, fluxstatecent per cell per dimension to get corrections to flux for each dimension and each MA-type of flux
// use e[pl] for \gdet for each equation of motion
// F^i_\rho = \rho u^i
// F_E^i = (\rho+u+p)u^i u_t
// F_{\rho v^j}^i = (\rho+u+p)u^i u_j + p\delta^i_j (note F_{\rho v^i}^i = F_E^i u_i/u_t + p
// generally, F_{\rho v^j}^i = F_E^i u_i/u_t + p \delta^i_j
////////////////////////
//
// Setup things common to all EOMs
//
////////////////////////
#if(MERGEDC2EA2CMETHOD)
// \detg for \rho_0
// overridden by below if WHICHEOM!=WITHGDET
gdetl=stateleft->gdet;
gdetc=statecent->gdet;
gdetr=stateright->gdet;
// \rho_0
rhol=stateleft->prim[RHO];
rhoc=statecent->prim[RHO];
rhor=stateright->prim[RHO];
// ie (internal energy density)
iel=stateleft->prim[UU];
iec=statecent->prim[UU];
ier=stateright->prim[UU];
#endif
// pressure
pressl=stateleft->pressure;
pressc=statecent->pressure;
pressr=stateright->pressure;
// 4-velocity in coordinate frame
udirl=stateleft->ucon[dir];
udirc=statecent->ucon[dir];
udirr=stateright->ucon[dir];
///////////////////
//
// REST-MASS FLUX: \detg \rho_0 u^{dir}
//
///////////////////
#if(WHICHEOM!=WITHGDET&&MERGEDC2EA2CMETHOD)
// need gdet for each variable
gdetl=stateleft->EOMFUNCMAC(RHO);
gdetc=statecent->EOMFUNCMAC(RHO);
gdetr=stateright->EOMFUNCMAC(RHO);
#endif
#if(MERGEDC2EA2CMETHOD)
#if(MCOORD==CARTMINKMETRIC)
twotermdeconvolution(rhol, rhoc, rhor ,udirl, udirc, udirr ,&Flefttemp, &Frighttemp);
Fleft[RHO] = gdetc*Flefttemp;
Fright[RHO] = gdetc*Frighttemp;
#else
threetermdeconvolution(gdetl, gdetc, gdetr, rhol, rhoc, rhor ,udirl, udirc, udirr ,&Fleft[RHO], &Fright[RHO]);
#endif
#endif
///////////////////
//
// Energy-Momentum FLUX: \detg [ (\rho_0 + u + P)u^i u_\nu + \delta^i_\nu P ]
//
// Note: \rho_0+u+P term is linear so no deconvolution correction, so can just sum those up *before* deconvolution and result will be same
//
//
// when REMOVERESTMASSFROMUU==1,2 then really have for TT term:
//
// \detg [ (\rho_0 [1+u_t] + (u+p)u_t)u^i + \delta^i_\nu P ]
// so in this case have to break \rho away from u+p term
//
//
//
///////////////////
/////////////
//
// setup 1+u_t or u_t depending upon REMOVERESTMASSFROMUU==0 or 1,2
// by the time we reach here, UtoU() has operated on flux and if REMOVERESTMASSFROMUU>0 then final flux in UEVOLVE form has no rest-mass term
//
//////////////
SLOOPA(jj){
genucovl[jj]=stateleft->ucov[jj];
genucovc[jj]=statecent->ucov[jj];
genucovr[jj]=stateright->ucov[jj];
}
jj=TT;
genucovl[jj]=stateleft->ifremoverestplus1ud0elseud0;
genucovc[jj]=statecent->ifremoverestplus1ud0elseud0;
genucovr[jj]=stateright->ifremoverestplus1ud0elseud0;
///////////////
//
// Loop over T^{dir}_\mu type term
//
///////////////
DLOOPA(jj){
#if(WHICHEOM!=WITHGDET&&MERGEDC2EA2CMETHOD)
// need gdet for each variable
gdetl=stateleft->EOMFUNCMAC(UU+jj);
gdetc=statecent->EOMFUNCMAC(UU+jj);
gdetr=stateright->EOMFUNCMAC(UU+jj);
#endif
// lower 4-velocity in coordinate frame
udnul=stateleft->ucov[jj];
udnuc=statecent->ucov[jj];
udnur=stateright->ucov[jj];
// initialize as we loop over terms that are simply part of sum that has no extra coupling for deconvolution
Fleft[UU+jj] = 0.0;
Fright[UU+jj] = 0.0;
#if(MCOORD==CARTMINKMETRIC)
#if(REMOVERESTMASSFROMUU==1 || REMOVERESTMASSFROMUU==2)
threetermdeconvolution(rhol, rhoc, rhor ,udirl, udirc, udirr, genucovl[jj], genucovc[jj], genucovr[jj] ,&Flefttemp, &Frighttemp);
Fleft[UU+jj] += Flefttemp;
Fright[UU+jj] += Frighttemp;
threetermdeconvolution(iel+pressl, iec+pressc, ier+pressr ,udirl, udirc, udirr, udnul, udnuc, udnur ,&Flefttemp, &Frighttemp);
Fleft[UU+jj] += Flefttemp;
Fright[UU+jj] += Frighttemp;
#else
// the sum on rho+ie+P is allowed because single term with otherwise same multiplications, each term is itself rather than some function, so deconvolution integral is same for those terms together or apart
threetermdeconvolution(rhol+iel+pressl, rhoc+iec+pressc, rhor+ier+pressr ,udirl, udirc, udirr, udnul, udnuc, udnur ,&Flefttemp, &Frighttemp);
Fleft[UU+jj] += Flefttemp;
Fright[UU+jj] += Frighttemp;
#endif
if(jj==dir){
onetermdeconvolution(pressl, pressc, pressr ,&Flefttemp, &Frighttemp);
Fleft[UU+jj] += Flefttemp;
Fright[UU+jj] += Frighttemp;
}
// finally apply constant \detg factor
Fleft[UU+jj]*=gdetc;
Fright[UU+jj]*=gdetc;
#else
#if(REMOVERESTMASSFROMUU==1 || REMOVERESTMASSFROMUU==2)
fourtermdeconvolution(gdetl, gdetc, gdetr, rhol, rhoc, rhor ,udirl, udirc, udirr, genucovl[jj], genucovc[jj], genucovr[jj] ,&Flefttemp, &Frighttemp);
Fleft[UU+jj] += Flefttemp;
Fright[UU+jj] += Frighttemp;
fourtermdeconvolution(gdetl, gdetc, gdetr, iel+pressl, iec+pressc, ier+pressr ,udirl, udirc, udirr, udnul, udnuc, udnur ,&Flefttemp, &Frighttemp);
Fleft[UU+jj] += Flefttemp;
Fright[UU+jj] += Frighttemp;
#else
// the sum on rho+ie+P is allowed because single term with otherwise same multiplications, each term is itself rather than some function, so deconvolution integral is same for those terms together or apart
fourtermdeconvolution(gdetl, gdetc, gdetr, rhol+iel+pressl, rhoc+iec+pressc, rhor+ier+pressr ,udirl, udirc, udirr, udnul, udnuc, udnur ,&Flefttemp, &Frighttemp);
Fleft[UU+jj] += Flefttemp;
Fright[UU+jj] += Frighttemp;
#endif
if(jj==dir){
twotermdeconvolution(gdetl, gdetc, gdetr, pressl, pressc, pressr ,&Flefttemp, &Frighttemp);
Fleft[UU+jj] += Flefttemp;
Fright[UU+jj] += Frighttemp;
}
#endif
}// end loop over jj = \nu={0,1,2,3}
//////////
//
// setup Y_L and Y_\nu terms
//
//////////
#if(MERGEDC2EA2CMETHOD)
#if(DOYNU!=DONOYNU)
FTYPE YNUl,YNUc,YNUr;
// Y_\nu:
YNUl=stateleft->prim[YNU];
YNUc=statecent->prim[YNU];
YNUr=stateright->prim[YNU];
#endif
#endif
#if(MERGEDC2EA2CMETHOD)
#if(DOYL!=DONOYL)
FTYPE YLl,YLc,YLr;
// Y_l:
YLl=stateleft->prim[YL];
YLc=statecent->prim[YL];
YLr=stateright->prim[YL];
#endif
#endif
///////////////////
//
// Flux of Y_l : \detg \rho_0 Y_l u^i
//
///////////////////
#if(MERGEDC2EA2CMETHOD)
#if(DOYL!=DONOYL)
FTYPE yl2advectl,yl2advectc,yl2advectr;
#if(WHICHEOS==KAZFULL)
yl2advect_kazfull(EOSextra,YLl,YNUl,&yl2advectl);
yl2advect_kazfull(EOSextra,YLc,YNUc,&yl2advectc);
yl2advect_kazfull(EOSextra,YLr,YNUr,&yl2advectr);
#else
yl2advectl=YLl;
yl2advectc=YLc;
yl2advectr=YLr;
#endif
#if(MCOORD==CARTMINKMETRIC)
threetermdeconvolution(rhol, rhoc, rhor ,udirl, udirc, udirr, yl2advectl, yl2advectc, yl2advectr ,&Fleft[YL], &Fright[YL]);
// Apply constant \detg factor
Fleft[YL]*=gdetc;
Fright[YL]*=gdetc;
#else
fourtermdeconvolution(gdetl, gdetc, gdetr, rhol, rhoc, rhor ,udirl, udirc, udirr, yl2advectl, yl2advectc, yl2advectr ,&Fleft[YL], &Fright[YL]);
#endif
#endif // end if doing YL
#endif
///////////////////
//
// Flux of Y_\nu : \detg \rho_0 Y_\nu u^i
//
///////////////////
#if(MERGEDC2EA2CMETHOD)
#if(DOYNU!=DONOYNU)
FTYPE ynu2advectl,ynu2advectc,ynu2advectr;
#if(WHICHEOS==KAZFULL)
ynu2advect_kazfull(EOSextra,YLl,YNUl,&ynu2advectl);
ynu2advect_kazfull(EOSextra,YLc,YNUc,&ynu2advectc);
ynu2advect_kazfull(EOSextra,YLr,YNUr,&ynu2advectr);
#else
ynu2advectl=YNUl;
ynu2advectc=YNUc;
ynu2advectr=YNUr;
#endif
#if(MCOORD==CARTMINKMETRIC)
threetermdeconvolution(rhol, rhoc, rhor ,udirl, udirc, udirr, ynu2advectl, ynu2advectc, ynu2advectr ,&Fleft[YNU], &Fright[YNU]);
// Apply constant \detg factor
Fleft[YNU]*=gdetc;
Fright[YNU]*=gdetc;