xref: /petsc/src/ts/tutorials/multirate/finitevolume1d.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
1c4762a1bSJed Brown #include "finitevolume1d.h"
2c4762a1bSJed Brown #include <petscdmda.h>
3c4762a1bSJed Brown #include <petscdraw.h>
4c4762a1bSJed Brown #include <petsc/private/tsimpl.h>
5c4762a1bSJed Brown 
6c4762a1bSJed Brown #include <petsc/private/kernels/blockinvert.h> /* For the Kernel_*_gets_* stuff for BAIJ */
784ff8c8bSHong Zhang const char *FVBCTypes[] = {"PERIODIC", "OUTFLOW", "INFLOW", "FVBCType", "FVBC_", 0};
8c4762a1bSJed Brown 
9*9371c9d4SSatish Balay static inline PetscReal Sgn(PetscReal a) {
10*9371c9d4SSatish Balay   return (a < 0) ? -1 : 1;
11*9371c9d4SSatish Balay }
12*9371c9d4SSatish Balay static inline PetscReal Abs(PetscReal a) {
13*9371c9d4SSatish Balay   return (a < 0) ? 0 : a;
14*9371c9d4SSatish Balay }
15*9371c9d4SSatish Balay static inline PetscReal Sqr(PetscReal a) {
16*9371c9d4SSatish Balay   return a * a;
17*9371c9d4SSatish Balay }
1884ff8c8bSHong Zhang 
19*9371c9d4SSatish Balay PETSC_UNUSED static inline PetscReal MinAbs(PetscReal a, PetscReal b) {
20*9371c9d4SSatish Balay   return (PetscAbs(a) < PetscAbs(b)) ? a : b;
21*9371c9d4SSatish Balay }
22*9371c9d4SSatish Balay static inline PetscReal MinMod2(PetscReal a, PetscReal b) {
23*9371c9d4SSatish Balay   return (a * b < 0) ? 0 : Sgn(a) * PetscMin(PetscAbs(a), PetscAbs(b));
24*9371c9d4SSatish Balay }
25*9371c9d4SSatish Balay static inline PetscReal MaxMod2(PetscReal a, PetscReal b) {
26*9371c9d4SSatish Balay   return (a * b < 0) ? 0 : Sgn(a) * PetscMax(PetscAbs(a), PetscAbs(b));
27*9371c9d4SSatish Balay }
28*9371c9d4SSatish Balay static inline PetscReal MinMod3(PetscReal a, PetscReal b, PetscReal c) {
29*9371c9d4SSatish Balay   return (a * b < 0 || a * c < 0) ? 0 : Sgn(a) * PetscMin(PetscAbs(a), PetscMin(PetscAbs(b), PetscAbs(c)));
30*9371c9d4SSatish Balay }
31c4762a1bSJed Brown 
32c4762a1bSJed Brown /* ----------------------- Lots of limiters, these could go in a separate library ------------------------- */
33*9371c9d4SSatish Balay void Limit_Upwind(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) {
34c4762a1bSJed Brown   PetscInt i;
35c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = 0;
36c4762a1bSJed Brown }
37*9371c9d4SSatish Balay void Limit_LaxWendroff(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) {
38c4762a1bSJed Brown   PetscInt i;
39c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = jR[i];
40c4762a1bSJed Brown }
41*9371c9d4SSatish Balay void Limit_BeamWarming(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) {
42c4762a1bSJed Brown   PetscInt i;
43c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = jL[i];
44c4762a1bSJed Brown }
45*9371c9d4SSatish Balay void Limit_Fromm(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) {
46c4762a1bSJed Brown   PetscInt i;
47c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] + jR[i]);
48c4762a1bSJed Brown }
49*9371c9d4SSatish Balay void Limit_Minmod(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) {
50c4762a1bSJed Brown   PetscInt i;
51c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i], jR[i]);
52c4762a1bSJed Brown }
53*9371c9d4SSatish Balay void Limit_Superbee(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) {
54c4762a1bSJed Brown   PetscInt i;
55c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i], 2 * jR[i]), MinMod2(2 * jL[i], jR[i]));
56c4762a1bSJed Brown }
57*9371c9d4SSatish Balay void Limit_MC(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) {
58c4762a1bSJed Brown   PetscInt i;
59c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i], 0.5 * (jL[i] + jR[i]), 2 * jR[i]);
60c4762a1bSJed Brown }
61*9371c9d4SSatish Balay void Limit_VanLeer(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) { /* phi = (t + abs(t)) / (1 + abs(t)) */
62c4762a1bSJed Brown   PetscInt i;
63c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = (jL[i] * Abs(jR[i]) + Abs(jL[i]) * jR[i]) / (Abs(jL[i]) + Abs(jR[i]) + 1e-15);
64c4762a1bSJed Brown }
65c4762a1bSJed Brown void Limit_VanAlbada(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) /* differentiable */
66c4762a1bSJed Brown {                                                                                                    /* phi = (t + t^2) / (1 + t^2) */
67c4762a1bSJed Brown   PetscInt i;
68c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = (jL[i] * Sqr(jR[i]) + Sqr(jL[i]) * jR[i]) / (Sqr(jL[i]) + Sqr(jR[i]) + 1e-15);
69c4762a1bSJed Brown }
70*9371c9d4SSatish Balay void Limit_VanAlbadaTVD(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) { /* phi = (t + t^2) / (1 + t^2) */
71c4762a1bSJed Brown   PetscInt i;
72c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = (jL[i] * jR[i] < 0) ? 0 : (jL[i] * Sqr(jR[i]) + Sqr(jL[i]) * jR[i]) / (Sqr(jL[i]) + Sqr(jR[i]) + 1e-15);
73c4762a1bSJed Brown }
74c4762a1bSJed Brown void Limit_Koren(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) /* differentiable */
75c4762a1bSJed Brown {                                                                                                /* phi = (t + 2*t^2) / (2 - t + 2*t^2) */
76c4762a1bSJed Brown   PetscInt i;
77c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = ((jL[i] * Sqr(jR[i]) + 2 * Sqr(jL[i]) * jR[i]) / (2 * Sqr(jL[i]) - jL[i] * jR[i] + 2 * Sqr(jR[i]) + 1e-15));
78c4762a1bSJed Brown }
79c4762a1bSJed Brown void Limit_KorenSym(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) /* differentiable */
80c4762a1bSJed Brown {                                                                                                   /* Symmetric version of above */
81c4762a1bSJed Brown   PetscInt i;
82c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = (1.5 * (jL[i] * Sqr(jR[i]) + Sqr(jL[i]) * jR[i]) / (2 * Sqr(jL[i]) - jL[i] * jR[i] + 2 * Sqr(jR[i]) + 1e-15));
83c4762a1bSJed Brown }
84*9371c9d4SSatish Balay void Limit_Koren3(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) { /* Eq 11 of Cada-Torrilhon 2009 */
85c4762a1bSJed Brown   PetscInt i;
86c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i], (jL[i] + 2 * jR[i]) / 3, 2 * jR[i]);
87c4762a1bSJed Brown }
88*9371c9d4SSatish Balay static PetscReal CadaTorrilhonPhiHatR_Eq13(PetscReal L, PetscReal R) {
89c4762a1bSJed Brown   return PetscMax(0, PetscMin((L + 2 * R) / 3, PetscMax(-0.5 * L, PetscMin(2 * L, PetscMin((L + 2 * R) / 3, 1.6 * R)))));
90c4762a1bSJed Brown }
91*9371c9d4SSatish Balay void Limit_CadaTorrilhon2(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) { /* Cada-Torrilhon 2009, Eq 13 */
92c4762a1bSJed Brown   PetscInt i;
93c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = CadaTorrilhonPhiHatR_Eq13(jL[i], jR[i]);
94c4762a1bSJed Brown }
95*9371c9d4SSatish Balay void Limit_CadaTorrilhon3R(PetscReal r, LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) { /* Cada-Torrilhon 2009, Eq 22 */
96c4762a1bSJed Brown   /* They recommend 0.001 < r < 1, but larger values are more accurate in smooth regions */
97c4762a1bSJed Brown   const PetscReal eps = 1e-7, hx = info->hx;
98c4762a1bSJed Brown   PetscInt        i;
99c4762a1bSJed Brown   for (i = 0; i < info->m; i++) {
100c4762a1bSJed Brown     const PetscReal eta = (Sqr(jL[i]) + Sqr(jR[i])) / Sqr(r * hx);
101c4762a1bSJed Brown     lmt[i] = ((eta < 1 - eps) ? (jL[i] + 2 * jR[i]) / 3 : ((eta > 1 + eps) ? CadaTorrilhonPhiHatR_Eq13(jL[i], jR[i]) : 0.5 * ((1 - (eta - 1) / eps) * (jL[i] + 2 * jR[i]) / 3 + (1 + (eta + 1) / eps) * CadaTorrilhonPhiHatR_Eq13(jL[i], jR[i]))));
102c4762a1bSJed Brown   }
103c4762a1bSJed Brown }
104*9371c9d4SSatish Balay void Limit_CadaTorrilhon3R0p1(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) {
105c4762a1bSJed Brown   Limit_CadaTorrilhon3R(0.1, info, jL, jR, lmt);
106c4762a1bSJed Brown }
107*9371c9d4SSatish Balay void Limit_CadaTorrilhon3R1(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) {
108c4762a1bSJed Brown   Limit_CadaTorrilhon3R(1, info, jL, jR, lmt);
109c4762a1bSJed Brown }
110*9371c9d4SSatish Balay void Limit_CadaTorrilhon3R10(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) {
111c4762a1bSJed Brown   Limit_CadaTorrilhon3R(10, info, jL, jR, lmt);
112c4762a1bSJed Brown }
113*9371c9d4SSatish Balay void Limit_CadaTorrilhon3R100(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, PetscScalar *lmt) {
114c4762a1bSJed Brown   Limit_CadaTorrilhon3R(100, info, jL, jR, lmt);
115c4762a1bSJed Brown }
116c4762a1bSJed Brown 
117c4762a1bSJed Brown /* ----------------------- Limiters for split systems ------------------------- */
118c4762a1bSJed Brown 
119*9371c9d4SSatish Balay void Limit2_Upwind(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sf, const PetscInt fs, PetscInt n, PetscScalar *lmt) {
120c4762a1bSJed Brown   PetscInt i;
121c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = 0;
122c4762a1bSJed Brown }
123*9371c9d4SSatish Balay void Limit2_LaxWendroff(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sf, const PetscInt fs, PetscInt n, PetscScalar *lmt) {
124c4762a1bSJed Brown   PetscInt i;
125c4762a1bSJed Brown   if (n < sf - 1) { /* slow components */
126c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jR[i] / info->hxs;
127c4762a1bSJed Brown   } else if (n == sf - 1) { /* slow component which is next to fast components */
128c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jR[i] / (info->hxs / 2.0 + info->hxf / 2.0);
129c4762a1bSJed Brown   } else if (n == sf) { /* fast component which is next to slow components */
130c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jR[i] / info->hxf;
131c4762a1bSJed Brown   } else if (n > sf && n < fs - 1) { /* fast components */
132c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jR[i] / info->hxf;
133c4762a1bSJed Brown   } else if (n == fs - 1) { /* fast component next to slow components */
134c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jR[i] / (info->hxf / 2.0 + info->hxs / 2.0);
135c4762a1bSJed Brown   } else if (n == fs) { /* slow component next to fast components */
136c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jR[i] / info->hxs;
137c4762a1bSJed Brown   } else { /* slow components */
138c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jR[i] / info->hxs;
139c4762a1bSJed Brown   }
140c4762a1bSJed Brown }
141*9371c9d4SSatish Balay void Limit2_BeamWarming(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sf, const PetscInt fs, PetscInt n, PetscScalar *lmt) {
142c4762a1bSJed Brown   PetscInt i;
143c4762a1bSJed Brown   if (n < sf - 1) {
144c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jL[i] / info->hxs;
145c4762a1bSJed Brown   } else if (n == sf - 1) {
146c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jL[i] / info->hxs;
147c4762a1bSJed Brown   } else if (n == sf) {
148c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jL[i] / (info->hxs / 2.0 + info->hxf / 2.0);
149c4762a1bSJed Brown   } else if (n > sf && n < fs - 1) {
150c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jL[i] / info->hxf;
151c4762a1bSJed Brown   } else if (n == fs - 1) {
152c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jL[i] / info->hxf;
153c4762a1bSJed Brown   } else if (n == fs) {
154c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jL[i] / (info->hxf / 2.0 + info->hxs / 2.0);
155c4762a1bSJed Brown   } else {
156c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jL[i] / info->hxs;
157c4762a1bSJed Brown   }
158c4762a1bSJed Brown }
159*9371c9d4SSatish Balay void Limit2_Fromm(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sf, const PetscInt fs, PetscInt n, PetscScalar *lmt) {
160c4762a1bSJed Brown   PetscInt i;
161c4762a1bSJed Brown   if (n < sf - 1) {
162c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] + jR[i]) / info->hxs;
163c4762a1bSJed Brown   } else if (n == sf - 1) {
164c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] / info->hxs + jR[i] / (info->hxs / 2.0 + info->hxf / 2.0));
165c4762a1bSJed Brown   } else if (n == sf) {
166c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] / (info->hxs / 2.0 + info->hxf / 2.0) + jR[i] / info->hxf);
167c4762a1bSJed Brown   } else if (n > sf && n < fs - 1) {
168c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] + jR[i]) / info->hxf;
169c4762a1bSJed Brown   } else if (n == fs - 1) {
170c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] / info->hxf + jR[i] / (info->hxf / 2.0 + info->hxs / 2.0));
171c4762a1bSJed Brown   } else if (n == fs) {
172c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] / (info->hxf / 2.0 + info->hxs / 2.0) + jR[i] / info->hxs);
173c4762a1bSJed Brown   } else {
174c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] + jR[i]) / info->hxs;
175c4762a1bSJed Brown   }
176c4762a1bSJed Brown }
177*9371c9d4SSatish Balay void Limit2_Minmod(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sf, const PetscInt fs, PetscInt n, PetscScalar *lmt) {
178c4762a1bSJed Brown   PetscInt i;
179c4762a1bSJed Brown   if (n < sf - 1) {
180c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i], jR[i]) / info->hxs;
181c4762a1bSJed Brown   } else if (n == sf - 1) {
182c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i] / info->hxs, jR[i] / (info->hxs / 2.0 + info->hxf / 2.0));
183c4762a1bSJed Brown   } else if (n == sf) {
184c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i] / (info->hxs / 2.0 + info->hxf / 2.0), jR[i] / info->hxf);
185c4762a1bSJed Brown   } else if (n > sf && n < fs - 1) {
186c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i], jR[i]) / info->hxf;
187c4762a1bSJed Brown   } else if (n == fs - 1) {
188c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i] / info->hxf, jR[i] / (info->hxf / 2.0 + info->hxs / 2.0));
189c4762a1bSJed Brown   } else if (n == fs) {
190c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i] / (info->hxf / 2.0 + info->hxs / 2.0), jR[i] / info->hxs);
191c4762a1bSJed Brown   } else {
192c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i], jR[i]) / info->hxs;
193c4762a1bSJed Brown   }
194c4762a1bSJed Brown }
195*9371c9d4SSatish Balay void Limit2_Superbee(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sf, const PetscInt fs, PetscInt n, PetscScalar *lmt) {
196c4762a1bSJed Brown   PetscInt i;
197c4762a1bSJed Brown   if (n < sf - 1) {
198c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i], 2 * jR[i]), MinMod2(2 * jL[i], jR[i])) / info->hxs;
199c4762a1bSJed Brown   } else if (n == sf - 1) {
200c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i] / info->hxs, 2 * jR[i] / (info->hxs / 2.0 + info->hxf / 2.0)), MinMod2(2 * jL[i] / info->hxs, jR[i] / (info->hxs / 2.0 + info->hxf / 2.0)));
201c4762a1bSJed Brown   } else if (n == sf) {
202c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i] / (info->hxs / 2.0 + info->hxf / 2.0), 2 * jR[i] / info->hxf), MinMod2(2 * jL[i] / (info->hxs / 2.0 + info->hxf / 2.0), jR[i] / info->hxf));
203c4762a1bSJed Brown   } else if (n > sf && n < fs - 1) {
204c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i], 2 * jR[i]), MinMod2(2 * jL[i], jR[i])) / info->hxf;
205c4762a1bSJed Brown   } else if (n == fs - 1) {
206c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i] / info->hxf, 2 * jR[i] / (info->hxf / 2.0 + info->hxs / 2.0)), MinMod2(2 * jL[i] / info->hxf, jR[i] / (info->hxf / 2.0 + info->hxs / 2.0)));
207c4762a1bSJed Brown   } else if (n == fs) {
208c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i] / (info->hxf / 2.0 + info->hxs / 2.0), 2 * jR[i] / info->hxs), MinMod2(2 * jL[i] / (info->hxf / 2.0 + info->hxs / 2.0), jR[i] / info->hxs));
209c4762a1bSJed Brown   } else {
210c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i], 2 * jR[i]), MinMod2(2 * jL[i], jR[i])) / info->hxs;
211c4762a1bSJed Brown   }
212c4762a1bSJed Brown }
213*9371c9d4SSatish Balay void Limit2_MC(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sf, const PetscInt fs, PetscInt n, PetscScalar *lmt) {
214c4762a1bSJed Brown   PetscInt i;
215c4762a1bSJed Brown   if (n < sf - 1) {
216c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i], 0.5 * (jL[i] + jR[i]), 2 * jR[i]) / info->hxs;
217c4762a1bSJed Brown   } else if (n == sf - 1) {
218c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / info->hxs, 0.5 * (jL[i] / info->hxs + jR[i] / (info->hxf / 2.0 + info->hxs / 2.0)), 2 * jR[i] / (info->hxf / 2.0 + info->hxs / 2.0));
219c4762a1bSJed Brown   } else if (n == sf) {
220c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / (info->hxs / 2.0 + info->hxf / 2.0), 0.5 * (jL[i] / (info->hxs / 2.0 + info->hxf / 2.0) + jR[i] / info->hxf), 2 * jR[i] / info->hxf);
221c4762a1bSJed Brown   } else if (n > sf && n < fs - 1) {
222c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i], 0.5 * (jL[i] + jR[i]), 2 * jR[i]) / info->hxf;
223c4762a1bSJed Brown   } else if (n == fs - 1) {
224c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / info->hxf, 0.5 * (jL[i] / info->hxf + jR[i] / (info->hxf / 2.0 + info->hxs / 2.0)), 2 * jR[i] / (info->hxf / 2.0 + info->hxs / 2.0));
225c4762a1bSJed Brown   } else if (n == fs) {
226c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / (info->hxf / 2.0 + info->hxs / 2.0), 0.5 * (jL[i] / (info->hxf / 2.0 + info->hxs / 2.0) + jR[i] / info->hxs), 2 * jR[i] / info->hxs);
227c4762a1bSJed Brown   } else {
228c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i], 0.5 * (jL[i] + jR[i]), 2 * jR[i]) / info->hxs;
229c4762a1bSJed Brown   }
230c4762a1bSJed Brown }
231*9371c9d4SSatish Balay void Limit2_Koren3(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sf, const PetscInt fs, PetscInt n, PetscScalar *lmt) { /* Eq 11 of Cada-Torrilhon 2009 */
232c4762a1bSJed Brown   PetscInt i;
233c4762a1bSJed Brown   if (n < sf - 1) {
234c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i], (jL[i] + 2 * jR[i]) / 3, 2 * jR[i]) / info->hxs;
235c4762a1bSJed Brown   } else if (n == sf - 1) {
236c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / info->hxs, (jL[i] / info->hxs + 2 * jR[i] / (info->hxf / 2.0 + info->hxs / 2.0)) / 3, 2 * jR[i] / (info->hxf / 2.0 + info->hxs / 2.0));
237c4762a1bSJed Brown   } else if (n == sf) {
238c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / (info->hxs / 2.0 + info->hxf / 2.0), (jL[i] / (info->hxs / 2.0 + info->hxf / 2.0) + 2 * jR[i] / info->hxf) / 3, 2 * jR[i] / info->hxf);
239c4762a1bSJed Brown   } else if (n > sf && n < fs - 1) {
240c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i], (jL[i] + 2 * jR[i]) / 3, 2 * jR[i]) / info->hxf;
241c4762a1bSJed Brown   } else if (n == fs - 1) {
242c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / info->hxf, (jL[i] / info->hxf + 2 * jR[i] / (info->hxf / 2.0 + info->hxs / 2.0)) / 3, 2 * jR[i] / (info->hxf / 2.0 + info->hxs / 2.0));
243c4762a1bSJed Brown   } else if (n == fs) {
244c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / (info->hxf / 2.0 + info->hxs / 2.0), (jL[i] / (info->hxf / 2.0 + info->hxs / 2.0) + 2 * jR[i] / info->hxs) / 3, 2 * jR[i] / info->hxs);
245c4762a1bSJed Brown   } else {
246c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i], (jL[i] + 2 * jR[i]) / 3, 2 * jR[i]) / info->hxs;
247c4762a1bSJed Brown   }
248c4762a1bSJed Brown }
249c4762a1bSJed Brown 
250c4762a1bSJed Brown /* ---- Three-way splitting ---- */
251*9371c9d4SSatish Balay void Limit3_Upwind(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sm, const PetscInt mf, const PetscInt fm, const PetscInt ms, PetscInt n, PetscScalar *lmt) {
252c4762a1bSJed Brown   PetscInt i;
253c4762a1bSJed Brown   for (i = 0; i < info->m; i++) lmt[i] = 0;
254c4762a1bSJed Brown }
255*9371c9d4SSatish Balay void Limit3_LaxWendroff(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sm, const PetscInt mf, const PetscInt fm, const PetscInt ms, PetscInt n, PetscScalar *lmt) {
256c4762a1bSJed Brown   PetscInt i;
257c4762a1bSJed Brown   if (n < sm - 1 || n > ms) { /* slow components */
258c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jR[i] / info->hxs;
259c4762a1bSJed Brown   } else if (n == sm - 1 || n == ms - 1) { /* slow component which is next to medium components */
260c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jR[i] / (info->hxs / 2.0 + info->hxm / 2.0);
261c4762a1bSJed Brown   } else if (n < mf - 1 || n > fm) { /* medium components */
262c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jR[i] / info->hxm;
263c4762a1bSJed Brown   } else if (n == mf - 1 || n == fm) { /* medium component next to fast components */
264c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jR[i] / (info->hxm / 2.0 + info->hxf / 2.0);
265c4762a1bSJed Brown   } else { /* fast components */
266c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jR[i] / info->hxf;
267c4762a1bSJed Brown   }
268c4762a1bSJed Brown }
269*9371c9d4SSatish Balay void Limit3_BeamWarming(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sm, const PetscInt mf, const PetscInt fm, const PetscInt ms, PetscInt n, PetscScalar *lmt) {
270c4762a1bSJed Brown   PetscInt i;
271c4762a1bSJed Brown   if (n < sm || n > ms) {
272c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jL[i] / info->hxs;
273c4762a1bSJed Brown   } else if (n == sm || n == ms) {
274c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jL[i] / (info->hxs / 2.0 + info->hxf / 2.0);
275c4762a1bSJed Brown   } else if (n < mf || n > fm) {
276c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jL[i] / info->hxm;
277c4762a1bSJed Brown   } else if (n == mf || n == fm) {
278c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jL[i] / (info->hxm / 2.0 + info->hxf / 2.0);
279c4762a1bSJed Brown   } else {
280c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = jL[i] / info->hxf;
281c4762a1bSJed Brown   }
282c4762a1bSJed Brown }
283*9371c9d4SSatish Balay void Limit3_Fromm(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sm, const PetscInt mf, const PetscInt fm, const PetscInt ms, PetscInt n, PetscScalar *lmt) {
284c4762a1bSJed Brown   PetscInt i;
285c4762a1bSJed Brown   if (n < sm - 1 || n > ms) {
286c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] + jR[i]) / info->hxs;
287c4762a1bSJed Brown   } else if (n == sm - 1) {
288c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] / info->hxs + jR[i] / (info->hxs / 2.0 + info->hxf / 2.0));
289c4762a1bSJed Brown   } else if (n == sm) {
290c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] / (info->hxs / 2.0 + info->hxm / 2.0) + jR[i] / info->hxm);
291c4762a1bSJed Brown   } else if (n == ms - 1) {
292c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] / info->hxm + jR[i] / (info->hxs / 2.0 + info->hxf / 2.0));
293c4762a1bSJed Brown   } else if (n == ms) {
294c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] / (info->hxm / 2.0 + info->hxs / 2.0) + jR[i] / info->hxs);
295c4762a1bSJed Brown   } else if (n < mf - 1 || n > fm) {
296c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] + jR[i]) / info->hxm;
297c4762a1bSJed Brown   } else if (n == mf - 1) {
298c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] / info->hxm + jR[i] / (info->hxm / 2.0 + info->hxf / 2.0));
299c4762a1bSJed Brown   } else if (n == mf) {
300c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] / (info->hxm / 2.0 + info->hxf / 2.0) + jR[i] / info->hxf);
301c4762a1bSJed Brown   } else if (n == fm - 1) {
302c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] / info->hxf + jR[i] / (info->hxf / 2.0 + info->hxm / 2.0));
303c4762a1bSJed Brown   } else if (n == fm) {
304c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] / (info->hxf / 2.0 + info->hxm / 2.0) + jR[i] / info->hxm);
305c4762a1bSJed Brown   } else {
306c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] + jR[i]) / info->hxf;
307c4762a1bSJed Brown   }
308c4762a1bSJed Brown }
309*9371c9d4SSatish Balay void Limit3_Minmod(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sm, const PetscInt mf, const PetscInt fm, const PetscInt ms, PetscInt n, PetscScalar *lmt) {
310c4762a1bSJed Brown   PetscInt i;
311c4762a1bSJed Brown   if (n < sm - 1 || n > ms) {
312c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i], jR[i]) / info->hxs;
313c4762a1bSJed Brown   } else if (n == sm - 1) {
314c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i] / info->hxs, jR[i] / (info->hxs / 2.0 + info->hxf / 2.0));
315c4762a1bSJed Brown   } else if (n == sm) {
316c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i] / (info->hxs / 2.0 + info->hxf / 2.0), jR[i] / info->hxf);
317c4762a1bSJed Brown   } else if (n == ms - 1) {
318c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i] / info->hxm, jR[i] / (info->hxm / 2.0 + info->hxs / 2.0));
319c4762a1bSJed Brown   } else if (n == ms) {
320c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i] / (info->hxm / 2.0 + info->hxs / 2.0), jR[i] / info->hxs);
321c4762a1bSJed Brown   } else if (n < mf - 1 || n > fm) {
322c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i], jR[i]) / info->hxm;
323c4762a1bSJed Brown   } else if (n == mf - 1) {
324c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i] / info->hxm, jR[i] / (info->hxm / 2.0 + info->hxf / 2.0));
325c4762a1bSJed Brown   } else if (n == mf) {
326c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i] / (info->hxm / 2.0 + info->hxf / 2.0), jR[i] / info->hxf);
327c4762a1bSJed Brown   } else if (n == fm - 1) {
328c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i] / info->hxf, jR[i] / (info->hxf / 2.0 + info->hxm / 2.0));
329c4762a1bSJed Brown   } else if (n == fm) {
330c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(jL[i] / (info->hxf / 2.0 + info->hxm / 2.0), jR[i] / info->hxm);
331c4762a1bSJed Brown   } else {
332c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = 0.5 * (jL[i] + jR[i]) / info->hxf;
333c4762a1bSJed Brown   }
334c4762a1bSJed Brown }
335*9371c9d4SSatish Balay void Limit3_Superbee(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sm, const PetscInt mf, const PetscInt fm, const PetscInt ms, PetscInt n, PetscScalar *lmt) {
336c4762a1bSJed Brown   PetscInt i;
337c4762a1bSJed Brown   if (n < sm - 1 || n > ms) {
338c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i], 2 * jR[i]), MinMod2(2 * jL[i], jR[i])) / info->hxs;
339c4762a1bSJed Brown   } else if (n == sm - 1) {
340c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i] / info->hxs, 2 * jR[i] / (info->hxs / 2.0 + info->hxm / 2.0)), MinMod2(2 * jL[i] / info->hxs, jR[i] / (info->hxs / 2.0 + info->hxm / 2.0)));
341c4762a1bSJed Brown   } else if (n == sm) {
342c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i] / (info->hxs / 2.0 + info->hxm / 2.0), 2 * jR[i] / info->hxm), MinMod2(2 * jL[i] / (info->hxs / 2.0 + info->hxm / 2.0), jR[i] / info->hxm));
343c4762a1bSJed Brown   } else if (n == ms - 1) {
344c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i] / info->hxm, 2 * jR[i] / (info->hxm / 2.0 + info->hxs / 2.0)), MinMod2(2 * jL[i] / info->hxm, jR[i] / (info->hxm / 2.0 + info->hxs / 2.0)));
345c4762a1bSJed Brown   } else if (n == ms) {
346c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i] / (info->hxm / 2.0 + info->hxs / 2.0), 2 * jR[i] / info->hxs), MinMod2(2 * jL[i] / (info->hxm / 2.0 + info->hxs / 2.0), jR[i] / info->hxs));
347c4762a1bSJed Brown   } else if (n < mf - 1 || n > fm) {
348c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i], 2 * jR[i]), MinMod2(2 * jL[i], jR[i])) / info->hxm;
349c4762a1bSJed Brown   } else if (n == mf - 1) {
350c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i] / info->hxm, 2 * jR[i] / (info->hxm / 2.0 + info->hxf / 2.0)), MinMod2(2 * jL[i] / info->hxm, jR[i] / (info->hxm / 2.0 + info->hxf / 2.0)));
351c4762a1bSJed Brown   } else if (n == mf) {
352c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i] / (info->hxm / 2.0 + info->hxf / 2.0), 2 * jR[i] / info->hxf), MinMod2(2 * jL[i] / (info->hxm / 2.0 + info->hxf / 2.0), jR[i] / info->hxf));
353c4762a1bSJed Brown   } else if (n == fm - 1) {
354c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i] / info->hxf, 2 * jR[i] / (info->hxf / 2.0 + info->hxm / 2.0)), MinMod2(2 * jL[i] / info->hxf, jR[i] / (info->hxf / 2.0 + info->hxm / 2.0)));
355c4762a1bSJed Brown   } else if (n == fm) {
356c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod2(MinMod2(jL[i] / (info->hxf / 2.0 + info->hxm / 2.0), 2 * jR[i] / info->hxm), MinMod2(2 * jL[i] / (info->hxf / 2.0 + info->hxm / 2.0), jR[i] / info->hxm));
357c4762a1bSJed Brown   } else {
358c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MaxMod2(MinMod2(jL[i], 2 * jR[i]), MinMod2(2 * jL[i], jR[i])) / info->hxf;
359c4762a1bSJed Brown   }
360c4762a1bSJed Brown }
361*9371c9d4SSatish Balay void Limit3_MC(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sm, const PetscInt mf, const PetscInt fm, const PetscInt ms, PetscInt n, PetscScalar *lmt) {
362c4762a1bSJed Brown   PetscInt i;
363c4762a1bSJed Brown   if (n < sm - 1 || n > ms) {
364c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i], 0.5 * (jL[i] + jR[i]), 2 * jR[i]) / info->hxs;
365c4762a1bSJed Brown   } else if (n == sm - 1) {
366c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / info->hxs, 0.5 * (jL[i] / info->hxs + jR[i] / (info->hxs / 2.0 + info->hxm / 2.0)), 2 * jR[i] / (info->hxs / 2.0 + info->hxm / 2.0));
367c4762a1bSJed Brown   } else if (n == sm) {
368c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / (info->hxs / 2.0 + info->hxm / 2.0), 0.5 * (jL[i] / (info->hxs / 2.0 + info->hxm / 2.0) + jR[i] / info->hxm), 2 * jR[i] / info->hxm);
369c4762a1bSJed Brown   } else if (n == ms - 1) {
370c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / info->hxm, 0.5 * (jL[i] / info->hxm + jR[i] / (info->hxm / 2.0 + info->hxs / 2.0)), 2 * jR[i] / (info->hxm / 2.0 + info->hxs / 2.0));
371c4762a1bSJed Brown   } else if (n == ms) {
372c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / (info->hxm / 2.0 + info->hxs / 2.0), 0.5 * (jL[i] / (info->hxm / 2.0 + info->hxs / 2.0) + jR[i] / info->hxs), 2 * jR[i] / info->hxs);
373c4762a1bSJed Brown   } else if (n < mf - 1 || n > fm) {
374c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i], 0.5 * (jL[i] + jR[i]), 2 * jR[i]) / info->hxm;
375c4762a1bSJed Brown   } else if (n == mf - 1) {
376c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / info->hxm, 0.5 * (jL[i] / info->hxm + jR[i] / (info->hxm / 2.0 + info->hxf / 2.0)), 2 * jR[i] / (info->hxm / 2.0 + info->hxf / 2.0));
377c4762a1bSJed Brown   } else if (n == mf) {
378c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / (info->hxm / 2.0 + info->hxf / 2.0), 0.5 * (jL[i] / (info->hxm / 2.0 + info->hxf / 2.0) + jR[i] / info->hxf), 2 * jR[i] / info->hxf);
379c4762a1bSJed Brown   } else if (n == fm - 1) {
380c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / info->hxf, 0.5 * (jL[i] / info->hxf + jR[i] / (info->hxf / 2.0 + info->hxm / 2.0)), 2 * jR[i] / (info->hxf / 2.0 + info->hxm / 2.0));
381c4762a1bSJed Brown   } else if (n == fm) {
382c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / (info->hxf / 2.0 + info->hxm / 2.0), 0.5 * (jL[i] / (info->hxf / 2.0 + info->hxm / 2.0) + jR[i] / info->hxm), 2 * jR[i] / info->hxm);
383c4762a1bSJed Brown   } else {
384c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i], 0.5 * (jL[i] + jR[i]), 2 * jR[i]) / info->hxf;
385c4762a1bSJed Brown   }
386c4762a1bSJed Brown }
387*9371c9d4SSatish Balay void Limit3_Koren3(LimitInfo info, const PetscScalar *jL, const PetscScalar *jR, const PetscInt sm, const PetscInt mf, const PetscInt fm, const PetscInt ms, PetscInt n, PetscScalar *lmt) { /* Eq 11 of Cada-Torrilhon 2009 */
388c4762a1bSJed Brown   PetscInt i;
389c4762a1bSJed Brown   if (n < sm - 1 || n > ms) {
390c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i], (jL[i] + 2 * jR[i]) / 3, 2 * jR[i]) / info->hxs;
391c4762a1bSJed Brown   } else if (n == sm - 1) {
392c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / info->hxs, (jL[i] / info->hxs + 2 * jR[i] / (info->hxm / 2.0 + info->hxs / 2.0)) / 3, 2 * jR[i] / (info->hxm / 2.0 + info->hxs / 2.0));
393c4762a1bSJed Brown   } else if (n == sm) {
394c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / (info->hxs / 2.0 + info->hxm / 2.0), (jL[i] / (info->hxs / 2.0 + info->hxm / 2.0) + 2 * jR[i] / info->hxm) / 3, 2 * jR[i] / info->hxm);
395c4762a1bSJed Brown   } else if (n == ms - 1) {
396c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / info->hxm, (jL[i] / info->hxm + 2 * jR[i] / (info->hxm / 2.0 + info->hxs / 2.0)) / 3, 2 * jR[i] / (info->hxm / 2.0 + info->hxs / 2.0));
397c4762a1bSJed Brown   } else if (n == ms) {
398c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / (info->hxm / 2.0 + info->hxs / 2.0), (jL[i] / (info->hxm / 2.0 + info->hxs / 2.0) + 2 * jR[i] / info->hxs) / 3, 2 * jR[i] / info->hxs);
399c4762a1bSJed Brown   } else if (n < mf - 1 || n > fm) {
400c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i], (jL[i] + 2 * jR[i]) / 3, 2 * jR[i]) / info->hxm;
401c4762a1bSJed Brown   } else if (n == mf - 1) {
402c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / info->hxm, (jL[i] / info->hxm + 2 * jR[i] / (info->hxm / 2.0 + info->hxf / 2.0)) / 3, 2 * jR[i] / (info->hxm / 2.0 + info->hxf / 2.0));
403c4762a1bSJed Brown   } else if (n == mf) {
404c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / (info->hxm / 2.0 + info->hxf / 2.0), (jL[i] / (info->hxm / 2.0 + info->hxf / 2.0) + 2 * jR[i] / info->hxf) / 3, 2 * jR[i] / info->hxf);
405c4762a1bSJed Brown   } else if (n == fm - 1) {
406c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / info->hxf, (jL[i] / info->hxf + 2 * jR[i] / (info->hxf / 2.0 + info->hxm / 2.0)) / 3, 2 * jR[i] / (info->hxf / 2.0 + info->hxm / 2.0));
407c4762a1bSJed Brown   } else if (n == fm) {
408c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i] / (info->hxf / 2.0 + info->hxm / 2.0), (jL[i] / (info->hxf / 2.0 + info->hxm / 2.0) + 2 * jR[i] / info->hxm) / 3, 2 * jR[i] / info->hxm);
409c4762a1bSJed Brown   } else {
410c4762a1bSJed Brown     for (i = 0; i < info->m; i++) lmt[i] = MinMod3(2 * jL[i], (jL[i] + 2 * jR[i]) / 3, 2 * jR[i]) / info->hxs;
411c4762a1bSJed Brown   }
412c4762a1bSJed Brown }
41384ff8c8bSHong Zhang 
414*9371c9d4SSatish Balay PetscErrorCode RiemannListAdd(PetscFunctionList *flist, const char *name, RiemannFunction rsolve) {
415c4762a1bSJed Brown   PetscFunctionBeginUser;
4169566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(flist, name, rsolve));
417c4762a1bSJed Brown   PetscFunctionReturn(0);
418c4762a1bSJed Brown }
419c4762a1bSJed Brown 
420*9371c9d4SSatish Balay PetscErrorCode RiemannListFind(PetscFunctionList flist, const char *name, RiemannFunction *rsolve) {
421c4762a1bSJed Brown   PetscFunctionBeginUser;
4229566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(flist, name, rsolve));
4233c633725SBarry Smith   PetscCheck(*rsolve, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Riemann solver \"%s\" could not be found", name);
424c4762a1bSJed Brown   PetscFunctionReturn(0);
425c4762a1bSJed Brown }
426c4762a1bSJed Brown 
427*9371c9d4SSatish Balay PetscErrorCode ReconstructListAdd(PetscFunctionList *flist, const char *name, ReconstructFunction r) {
428c4762a1bSJed Brown   PetscFunctionBeginUser;
4299566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(flist, name, r));
430c4762a1bSJed Brown   PetscFunctionReturn(0);
431c4762a1bSJed Brown }
432c4762a1bSJed Brown 
433*9371c9d4SSatish Balay PetscErrorCode ReconstructListFind(PetscFunctionList flist, const char *name, ReconstructFunction *r) {
434c4762a1bSJed Brown   PetscFunctionBeginUser;
4359566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(flist, name, r));
4363c633725SBarry Smith   PetscCheck(*r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Reconstruction \"%s\" could not be found", name);
437c4762a1bSJed Brown   PetscFunctionReturn(0);
438c4762a1bSJed Brown }
439c4762a1bSJed Brown 
440*9371c9d4SSatish Balay PetscErrorCode RiemannListAdd_2WaySplit(PetscFunctionList *flist, const char *name, RiemannFunction_2WaySplit rsolve) {
44184ff8c8bSHong Zhang   PetscFunctionBeginUser;
4429566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(flist, name, rsolve));
44384ff8c8bSHong Zhang   PetscFunctionReturn(0);
44484ff8c8bSHong Zhang }
44584ff8c8bSHong Zhang 
446*9371c9d4SSatish Balay PetscErrorCode RiemannListFind_2WaySplit(PetscFunctionList flist, const char *name, RiemannFunction_2WaySplit *rsolve) {
44784ff8c8bSHong Zhang   PetscFunctionBeginUser;
4489566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(flist, name, rsolve));
4493c633725SBarry Smith   PetscCheck(*rsolve, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Riemann solver \"%s\" could not be found", name);
45084ff8c8bSHong Zhang   PetscFunctionReturn(0);
45184ff8c8bSHong Zhang }
45284ff8c8bSHong Zhang 
453*9371c9d4SSatish Balay PetscErrorCode ReconstructListAdd_2WaySplit(PetscFunctionList *flist, const char *name, ReconstructFunction_2WaySplit r) {
45484ff8c8bSHong Zhang   PetscFunctionBeginUser;
4559566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(flist, name, r));
45684ff8c8bSHong Zhang   PetscFunctionReturn(0);
45784ff8c8bSHong Zhang }
45884ff8c8bSHong Zhang 
459*9371c9d4SSatish Balay PetscErrorCode ReconstructListFind_2WaySplit(PetscFunctionList flist, const char *name, ReconstructFunction_2WaySplit *r) {
46084ff8c8bSHong Zhang   PetscFunctionBeginUser;
4619566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(flist, name, r));
4623c633725SBarry Smith   PetscCheck(*r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Reconstruction \"%s\" could not be found", name);
46384ff8c8bSHong Zhang   PetscFunctionReturn(0);
46484ff8c8bSHong Zhang }
46584ff8c8bSHong Zhang 
46684ff8c8bSHong Zhang /* --------------------------------- Physics ------- */
467*9371c9d4SSatish Balay PetscErrorCode PhysicsDestroy_SimpleFree(void *vctx) {
468c4762a1bSJed Brown   PetscFunctionBeginUser;
4699566063dSJacob Faibussowitsch   PetscCall(PetscFree(vctx));
470c4762a1bSJed Brown   PetscFunctionReturn(0);
471c4762a1bSJed Brown }
472c4762a1bSJed Brown 
47384ff8c8bSHong Zhang /* --------------------------------- Finite Volume Solver --------------- */
474*9371c9d4SSatish Balay PetscErrorCode FVRHSFunction(TS ts, PetscReal time, Vec X, Vec F, void *vctx) {
475c4762a1bSJed Brown   FVCtx       *ctx = (FVCtx *)vctx;
476c4762a1bSJed Brown   PetscInt     i, j, k, Mx, dof, xs, xm;
477c4762a1bSJed Brown   PetscReal    hx, cfl_idt = 0;
478c4762a1bSJed Brown   PetscScalar *x, *f, *slope;
479c4762a1bSJed Brown   Vec          Xloc;
480c4762a1bSJed Brown   DM           da;
481c4762a1bSJed Brown 
482c4762a1bSJed Brown   PetscFunctionBeginUser;
4839566063dSJacob Faibussowitsch   PetscCall(TSGetDM(ts, &da));
4849566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(da, &Xloc));                                 /* Xloc contains ghost points */
4859566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, 0, &Mx, 0, 0, 0, 0, 0, &dof, 0, 0, 0, 0, 0)); /* Mx is the number of center points */
486c4762a1bSJed Brown   hx = (ctx->xmax - ctx->xmin) / Mx;
4879566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(da, X, INSERT_VALUES, Xloc)); /* X is solution vector which does not contain ghost points */
4889566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(da, X, INSERT_VALUES, Xloc));
4899566063dSJacob Faibussowitsch   PetscCall(VecZeroEntries(F)); /* F is the right hand side function corresponds to center points */
4909566063dSJacob Faibussowitsch   PetscCall(DMDAVecGetArray(da, Xloc, &x));
4919566063dSJacob Faibussowitsch   PetscCall(DMDAVecGetArray(da, F, &f));
4929566063dSJacob Faibussowitsch   PetscCall(DMDAGetArray(da, PETSC_TRUE, &slope)); /* contains ghost points */
4939566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, 0, 0, &xm, 0, 0));
494c4762a1bSJed Brown 
495c4762a1bSJed Brown   if (ctx->bctype == FVBC_OUTFLOW) {
496c4762a1bSJed Brown     for (i = xs - 2; i < 0; i++) {
497c4762a1bSJed Brown       for (j = 0; j < dof; j++) x[i * dof + j] = x[j];
498c4762a1bSJed Brown     }
499c4762a1bSJed Brown     for (i = Mx; i < xs + xm + 2; i++) {
500c4762a1bSJed Brown       for (j = 0; j < dof; j++) x[i * dof + j] = x[(xs + xm - 1) * dof + j];
501c4762a1bSJed Brown     }
502c4762a1bSJed Brown   }
50384ff8c8bSHong Zhang 
504c4762a1bSJed Brown   for (i = xs - 1; i < xs + xm + 1; i++) {
505c4762a1bSJed Brown     struct _LimitInfo info;
506c4762a1bSJed Brown     PetscScalar      *cjmpL, *cjmpR;
507c4762a1bSJed Brown     /* Determine the right eigenvectors R, where A = R \Lambda R^{-1} */
5089566063dSJacob Faibussowitsch     PetscCall((*ctx->physics.characteristic)(ctx->physics.user, dof, &x[i * dof], ctx->R, ctx->Rinv, ctx->speeds, ctx->xmin + hx * i));
509c4762a1bSJed Brown     /* Evaluate jumps across interfaces (i-1, i) and (i, i+1), put in characteristic basis */
5109566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(ctx->cjmpLR, 2 * dof));
511c4762a1bSJed Brown     cjmpL = &ctx->cjmpLR[0];
512c4762a1bSJed Brown     cjmpR = &ctx->cjmpLR[dof];
513c4762a1bSJed Brown     for (j = 0; j < dof; j++) {
514c4762a1bSJed Brown       PetscScalar jmpL, jmpR;
515c4762a1bSJed Brown       jmpL = x[(i + 0) * dof + j] - x[(i - 1) * dof + j];
516c4762a1bSJed Brown       jmpR = x[(i + 1) * dof + j] - x[(i + 0) * dof + j];
517c4762a1bSJed Brown       for (k = 0; k < dof; k++) {
518c4762a1bSJed Brown         cjmpL[k] += ctx->Rinv[k + j * dof] * jmpL;
519c4762a1bSJed Brown         cjmpR[k] += ctx->Rinv[k + j * dof] * jmpR;
520c4762a1bSJed Brown       }
521c4762a1bSJed Brown     }
522c4762a1bSJed Brown     /* Apply limiter to the left and right characteristic jumps */
523c4762a1bSJed Brown     info.m  = dof;
524c4762a1bSJed Brown     info.hx = hx;
525c4762a1bSJed Brown     (*ctx->limit)(&info, cjmpL, cjmpR, ctx->cslope);
526c4762a1bSJed Brown     for (j = 0; j < dof; j++) ctx->cslope[j] /= hx; /* rescale to a slope */
527c4762a1bSJed Brown     for (j = 0; j < dof; j++) {
528c4762a1bSJed Brown       PetscScalar tmp = 0;
529c4762a1bSJed Brown       for (k = 0; k < dof; k++) tmp += ctx->R[j + k * dof] * ctx->cslope[k];
530c4762a1bSJed Brown       slope[i * dof + j] = tmp;
531c4762a1bSJed Brown     }
532c4762a1bSJed Brown   }
533c4762a1bSJed Brown 
534c4762a1bSJed Brown   for (i = xs; i < xs + xm + 1; i++) {
535c4762a1bSJed Brown     PetscReal    maxspeed;
536c4762a1bSJed Brown     PetscScalar *uL, *uR;
537c4762a1bSJed Brown     uL = &ctx->uLR[0];
538c4762a1bSJed Brown     uR = &ctx->uLR[dof];
539c4762a1bSJed Brown     for (j = 0; j < dof; j++) {
540c4762a1bSJed Brown       uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hx / 2;
541c4762a1bSJed Brown       uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hx / 2;
542c4762a1bSJed Brown     }
5439566063dSJacob Faibussowitsch     PetscCall((*ctx->physics.riemann)(ctx->physics.user, dof, uL, uR, ctx->flux, &maxspeed, ctx->xmin + hx * i, ctx->xmin, ctx->xmax));
544c4762a1bSJed Brown     cfl_idt = PetscMax(cfl_idt, PetscAbsScalar(maxspeed / hx)); /* Max allowable value of 1/Delta t */
545c4762a1bSJed Brown     if (i > xs) {
546c4762a1bSJed Brown       for (j = 0; j < dof; j++) f[(i - 1) * dof + j] -= ctx->flux[j] / hx;
547c4762a1bSJed Brown     }
548c4762a1bSJed Brown     if (i < xs + xm) {
549c4762a1bSJed Brown       for (j = 0; j < dof; j++) f[i * dof + j] += ctx->flux[j] / hx;
550c4762a1bSJed Brown     }
551c4762a1bSJed Brown   }
5529566063dSJacob Faibussowitsch   PetscCall(DMDAVecRestoreArray(da, Xloc, &x));
5539566063dSJacob Faibussowitsch   PetscCall(DMDAVecRestoreArray(da, F, &f));
5549566063dSJacob Faibussowitsch   PetscCall(DMDARestoreArray(da, PETSC_TRUE, &slope));
5559566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(da, &Xloc));
5569566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&cfl_idt, &ctx->cfl_idt, 1, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)da)));
557c4762a1bSJed Brown   if (0) {
558c4762a1bSJed Brown     /* We need to a way to inform the TS of a CFL constraint, this is a debugging fragment */
559c4762a1bSJed Brown     PetscReal dt, tnow;
5609566063dSJacob Faibussowitsch     PetscCall(TSGetTimeStep(ts, &dt));
5619566063dSJacob Faibussowitsch     PetscCall(TSGetTime(ts, &tnow));
562c4762a1bSJed Brown     if (dt > 0.5 / ctx->cfl_idt) {
56384ff8c8bSHong Zhang       if (1) {
5649566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(ctx->comm, "Stability constraint exceeded at t=%g, dt %g > %g\n", (double)tnow, (double)dt, (double)(0.5 / ctx->cfl_idt)));
56598921bdaSJacob Faibussowitsch       } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Stability constraint exceeded, %g > %g", (double)dt, (double)(ctx->cfl / ctx->cfl_idt));
566c4762a1bSJed Brown     }
567c4762a1bSJed Brown   }
568c4762a1bSJed Brown   PetscFunctionReturn(0);
569c4762a1bSJed Brown }
570c4762a1bSJed Brown 
571*9371c9d4SSatish Balay PetscErrorCode FVSample(FVCtx *ctx, DM da, PetscReal time, Vec U) {
572c4762a1bSJed Brown   PetscScalar *u, *uj;
573c4762a1bSJed Brown   PetscInt     i, j, k, dof, xs, xm, Mx;
574c4762a1bSJed Brown 
575c4762a1bSJed Brown   PetscFunctionBeginUser;
5763c633725SBarry Smith   PetscCheck(ctx->physics.sample, PETSC_COMM_SELF, PETSC_ERR_SUP, "Physics has not provided a sampling function");
5779566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, 0, &Mx, 0, 0, 0, 0, 0, &dof, 0, 0, 0, 0, 0));
5789566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, &xs, 0, 0, &xm, 0, 0));
5799566063dSJacob Faibussowitsch   PetscCall(DMDAVecGetArray(da, U, &u));
5809566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(dof, &uj));
581c4762a1bSJed Brown   for (i = xs; i < xs + xm; i++) {
582c4762a1bSJed Brown     const PetscReal h = (ctx->xmax - ctx->xmin) / Mx, xi = ctx->xmin + h / 2 + i * h;
583c4762a1bSJed Brown     const PetscInt  N = 200;
584c4762a1bSJed Brown     /* Integrate over cell i using trapezoid rule with N points. */
585c4762a1bSJed Brown     for (k = 0; k < dof; k++) u[i * dof + k] = 0;
586c4762a1bSJed Brown     for (j = 0; j < N + 1; j++) {
587c4762a1bSJed Brown       PetscScalar xj = xi + h * (j - N / 2) / (PetscReal)N;
5889566063dSJacob Faibussowitsch       PetscCall((*ctx->physics.sample)(ctx->physics.user, ctx->initial, ctx->bctype, ctx->xmin, ctx->xmax, time, xj, uj));
589c4762a1bSJed Brown       for (k = 0; k < dof; k++) u[i * dof + k] += ((j == 0 || j == N) ? 0.5 : 1.0) * uj[k] / N;
590c4762a1bSJed Brown     }
591c4762a1bSJed Brown   }
5929566063dSJacob Faibussowitsch   PetscCall(DMDAVecRestoreArray(da, U, &u));
5939566063dSJacob Faibussowitsch   PetscCall(PetscFree(uj));
594c4762a1bSJed Brown   PetscFunctionReturn(0);
595c4762a1bSJed Brown }
596c4762a1bSJed Brown 
597*9371c9d4SSatish Balay PetscErrorCode SolutionStatsView(DM da, Vec X, PetscViewer viewer) {
598c4762a1bSJed Brown   PetscReal          xmin, xmax;
599c4762a1bSJed Brown   PetscScalar        sum, tvsum, tvgsum;
600c4762a1bSJed Brown   const PetscScalar *x;
601c4762a1bSJed Brown   PetscInt           imin, imax, Mx, i, j, xs, xm, dof;
602c4762a1bSJed Brown   Vec                Xloc;
603c4762a1bSJed Brown   PetscBool          iascii;
604c4762a1bSJed Brown 
605c4762a1bSJed Brown   PetscFunctionBeginUser;
6069566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
607c4762a1bSJed Brown   if (iascii) {
608c4762a1bSJed Brown     /* PETSc lacks a function to compute total variation norm (difficult in multiple dimensions), we do it here */
6099566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(da, &Xloc));
6109566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(da, X, INSERT_VALUES, Xloc));
6119566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(da, X, INSERT_VALUES, Xloc));
6129566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArrayRead(da, Xloc, (void *)&x));
6139566063dSJacob Faibussowitsch     PetscCall(DMDAGetCorners(da, &xs, 0, 0, &xm, 0, 0));
6149566063dSJacob Faibussowitsch     PetscCall(DMDAGetInfo(da, 0, &Mx, 0, 0, 0, 0, 0, &dof, 0, 0, 0, 0, 0));
615c4762a1bSJed Brown     tvsum = 0;
616c4762a1bSJed Brown     for (i = xs; i < xs + xm; i++) {
617c4762a1bSJed Brown       for (j = 0; j < dof; j++) tvsum += PetscAbsScalar(x[i * dof + j] - x[(i - 1) * dof + j]);
618c4762a1bSJed Brown     }
6199566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(&tvsum, &tvgsum, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)da)));
6209566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArrayRead(da, Xloc, (void *)&x));
6219566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(da, &Xloc));
6229566063dSJacob Faibussowitsch     PetscCall(VecMin(X, &imin, &xmin));
6239566063dSJacob Faibussowitsch     PetscCall(VecMax(X, &imax, &xmax));
6249566063dSJacob Faibussowitsch     PetscCall(VecSum(X, &sum));
62563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Solution range [%8.5f,%8.5f] with minimum at %" PetscInt_FMT ", mean %8.5f, ||x||_TV %8.5f\n", (double)xmin, (double)xmax, imin, (double)(sum / Mx), (double)(tvgsum / Mx)));
626c4762a1bSJed Brown   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Viewer type not supported");
627c4762a1bSJed Brown   PetscFunctionReturn(0);
628c4762a1bSJed Brown }
629