xref: /petsc/src/ts/tutorials/ex11.c (revision c14a7e842cb667c271838f3e6a97a7763d83d882)
1c4762a1bSJed Brown static char help[] = "Second Order TVD Finite Volume Example.\n";
2c4762a1bSJed Brown /*F
3c4762a1bSJed Brown 
4c4762a1bSJed Brown We use a second order TVD finite volume method to evolve a system of PDEs. Our simple upwinded residual evaluation loops
5c4762a1bSJed Brown over all mesh faces and uses a Riemann solver to produce the flux given the face geometry and cell values,
6c4762a1bSJed Brown \begin{equation}
7c4762a1bSJed Brown   f_i = \mathrm{riemann}(\mathrm{phys}, p_\mathrm{centroid}, \hat n, x^L, x^R)
8c4762a1bSJed Brown \end{equation}
9c4762a1bSJed Brown and then update the cell values given the cell volume.
10c4762a1bSJed Brown \begin{eqnarray}
11c4762a1bSJed Brown     f^L_i &-=& \frac{f_i}{vol^L} \\
12c4762a1bSJed Brown     f^R_i &+=& \frac{f_i}{vol^R}
13c4762a1bSJed Brown \end{eqnarray}
14c4762a1bSJed Brown 
15c4762a1bSJed Brown As an example, we can consider the shallow water wave equation,
16c4762a1bSJed Brown \begin{eqnarray}
17c4762a1bSJed Brown      h_t + \nabla\cdot \left( uh                              \right) &=& 0 \\
18c4762a1bSJed Brown   (uh)_t + \nabla\cdot \left( u\otimes uh + \frac{g h^2}{2} I \right) &=& 0
19c4762a1bSJed Brown \end{eqnarray}
20c4762a1bSJed Brown where $h$ is wave height, $u$ is wave velocity, and $g$ is the acceleration due to gravity.
21c4762a1bSJed Brown 
22c4762a1bSJed Brown A representative Riemann solver for the shallow water equations is given in the PhysicsRiemann_SW() function,
23c4762a1bSJed Brown \begin{eqnarray}
24c4762a1bSJed Brown   f^{L,R}_h    &=& uh^{L,R} \cdot \hat n \\
25c4762a1bSJed Brown   f^{L,R}_{uh} &=& \frac{f^{L,R}_h}{h^{L,R}} uh^{L,R} + g (h^{L,R})^2 \hat n \\
26c4762a1bSJed Brown   c^{L,R}      &=& \sqrt{g h^{L,R}} \\
27c4762a1bSJed Brown   s            &=& \max\left( \left|\frac{uh^L \cdot \hat n}{h^L}\right| + c^L, \left|\frac{uh^R \cdot \hat n}{h^R}\right| + c^R \right) \\
28c4762a1bSJed Brown   f_i          &=& \frac{A_\mathrm{face}}{2} \left( f^L_i + f^R_i + s \left( x^L_i - x^R_i \right) \right)
29c4762a1bSJed Brown \end{eqnarray}
30c4762a1bSJed Brown where $c$ is the local gravity wave speed and $f_i$ is a Rusanov flux.
31c4762a1bSJed Brown 
32c4762a1bSJed Brown The more sophisticated residual evaluation in RHSFunctionLocal_LS() uses a least-squares fit to a quadratic polynomial
33c4762a1bSJed Brown over a neighborhood of the given element.
34c4762a1bSJed Brown 
35c4762a1bSJed Brown The mesh is read in from an ExodusII file, usually generated by Cubit.
3652115386SStefano Zampini 
3752115386SStefano Zampini The example also shows how to handle AMR in a time-dependent TS solver.
38c4762a1bSJed Brown F*/
39c4762a1bSJed Brown #include <petscdmplex.h>
40c4762a1bSJed Brown #include <petscdmforest.h>
41c4762a1bSJed Brown #include <petscds.h>
42c4762a1bSJed Brown #include <petscts.h>
43c4762a1bSJed Brown 
44c4762a1bSJed Brown #define DIM 2 /* Geometric dimension */
45c4762a1bSJed Brown 
468d2c18caSMukkund Sunjii static PetscFunctionList PhysicsList, PhysicsRiemannList_SW;
47c4762a1bSJed Brown 
48c4762a1bSJed Brown /* Represents continuum physical equations. */
49c4762a1bSJed Brown typedef struct _n_Physics *Physics;
50c4762a1bSJed Brown 
51c4762a1bSJed Brown /* Physical model includes boundary conditions, initial conditions, and functionals of interest. It is
52c4762a1bSJed Brown  * discretization-independent, but its members depend on the scenario being solved. */
53c4762a1bSJed Brown typedef struct _n_Model *Model;
54c4762a1bSJed Brown 
55c4762a1bSJed Brown /* 'User' implements a discretization of a continuous model. */
56c4762a1bSJed Brown typedef struct _n_User *User;
57c4762a1bSJed Brown typedef PetscErrorCode (*SolutionFunction)(Model, PetscReal, const PetscReal *, PetscScalar *, void *);
5845480ffeSMatthew G. Knepley typedef PetscErrorCode (*SetUpBCFunction)(DM, PetscDS, Physics);
59c4762a1bSJed Brown typedef PetscErrorCode (*FunctionalFunction)(Model, PetscReal, const PetscReal *, const PetscScalar *, PetscReal *, void *);
60c4762a1bSJed Brown typedef PetscErrorCode (*SetupFields)(Physics, PetscSection);
61c4762a1bSJed Brown static PetscErrorCode ModelSolutionSetDefault(Model, SolutionFunction, void *);
62c4762a1bSJed Brown static PetscErrorCode ModelFunctionalRegister(Model, const char *, PetscInt *, FunctionalFunction, void *);
63c4762a1bSJed Brown static PetscErrorCode OutputVTK(DM, const char *, PetscViewer *);
64c4762a1bSJed Brown 
65c4762a1bSJed Brown struct FieldDescription {
66c4762a1bSJed Brown   const char *name;
67c4762a1bSJed Brown   PetscInt    dof;
68c4762a1bSJed Brown };
69c4762a1bSJed Brown 
70c4762a1bSJed Brown typedef struct _n_FunctionalLink *FunctionalLink;
71c4762a1bSJed Brown struct _n_FunctionalLink {
72c4762a1bSJed Brown   char              *name;
73c4762a1bSJed Brown   FunctionalFunction func;
74c4762a1bSJed Brown   void              *ctx;
75c4762a1bSJed Brown   PetscInt           offset;
76c4762a1bSJed Brown   FunctionalLink     next;
77c4762a1bSJed Brown };
78c4762a1bSJed Brown 
79c4762a1bSJed Brown struct _n_Physics {
80c4762a1bSJed Brown   PetscRiemannFunc               riemann;
81c4762a1bSJed Brown   PetscInt                       dof;      /* number of degrees of freedom per cell */
82c4762a1bSJed Brown   PetscReal                      maxspeed; /* kludge to pick initial time step, need to add monitoring and step control */
83c4762a1bSJed Brown   void                          *data;
84c4762a1bSJed Brown   PetscInt                       nfields;
85c4762a1bSJed Brown   const struct FieldDescription *field_desc;
86c4762a1bSJed Brown };
87c4762a1bSJed Brown 
88c4762a1bSJed Brown struct _n_Model {
89da81f932SPierre Jolivet   MPI_Comm         comm; /* Does not do collective communication, but some error conditions can be collective */
90c4762a1bSJed Brown   Physics          physics;
91c4762a1bSJed Brown   FunctionalLink   functionalRegistry;
92c4762a1bSJed Brown   PetscInt         maxComputed;
93c4762a1bSJed Brown   PetscInt         numMonitored;
94c4762a1bSJed Brown   FunctionalLink  *functionalMonitored;
95c4762a1bSJed Brown   PetscInt         numCall;
96c4762a1bSJed Brown   FunctionalLink  *functionalCall;
97c4762a1bSJed Brown   SolutionFunction solution;
98c4762a1bSJed Brown   SetUpBCFunction  setupbc;
99c4762a1bSJed Brown   void            *solutionctx;
100c4762a1bSJed Brown   PetscReal        maxspeed; /* estimate of global maximum speed (for CFL calculation) */
101c4762a1bSJed Brown   PetscReal        bounds[2 * DIM];
102c4762a1bSJed Brown   PetscErrorCode (*errorIndicator)(PetscInt, PetscReal, PetscInt, const PetscScalar[], const PetscScalar[], PetscReal *, void *);
103c4762a1bSJed Brown   void *errorCtx;
104c4762a1bSJed Brown };
105c4762a1bSJed Brown 
106c4762a1bSJed Brown struct _n_User {
107c4762a1bSJed Brown   PetscInt  vtkInterval;                        /* For monitor */
108c4762a1bSJed Brown   char      outputBasename[PETSC_MAX_PATH_LEN]; /* Basename for output files */
109c4762a1bSJed Brown   PetscInt  monitorStepOffset;
110c4762a1bSJed Brown   Model     model;
111c4762a1bSJed Brown   PetscBool vtkmon;
112c4762a1bSJed Brown };
113c4762a1bSJed Brown 
114d71ae5a4SJacob Faibussowitsch static inline PetscReal DotDIMReal(const PetscReal *x, const PetscReal *y)
115d71ae5a4SJacob Faibussowitsch {
116c4762a1bSJed Brown   PetscInt  i;
117c4762a1bSJed Brown   PetscReal prod = 0.0;
118c4762a1bSJed Brown 
119c4762a1bSJed Brown   for (i = 0; i < DIM; i++) prod += x[i] * y[i];
120c4762a1bSJed Brown   return prod;
121c4762a1bSJed Brown }
122d71ae5a4SJacob Faibussowitsch static inline PetscReal NormDIM(const PetscReal *x)
123d71ae5a4SJacob Faibussowitsch {
1249371c9d4SSatish Balay   return PetscSqrtReal(PetscAbsReal(DotDIMReal(x, x)));
1259371c9d4SSatish Balay }
126c4762a1bSJed Brown 
127d71ae5a4SJacob Faibussowitsch static inline PetscReal Dot2Real(const PetscReal *x, const PetscReal *y)
128d71ae5a4SJacob Faibussowitsch {
1299371c9d4SSatish Balay   return x[0] * y[0] + x[1] * y[1];
1309371c9d4SSatish Balay }
131d71ae5a4SJacob Faibussowitsch static inline PetscReal Norm2Real(const PetscReal *x)
132d71ae5a4SJacob Faibussowitsch {
1339371c9d4SSatish Balay   return PetscSqrtReal(PetscAbsReal(Dot2Real(x, x)));
1349371c9d4SSatish Balay }
135d71ae5a4SJacob Faibussowitsch static inline void Normalize2Real(PetscReal *x)
136d71ae5a4SJacob Faibussowitsch {
1379371c9d4SSatish Balay   PetscReal a = 1. / Norm2Real(x);
1389371c9d4SSatish Balay   x[0] *= a;
1399371c9d4SSatish Balay   x[1] *= a;
1409371c9d4SSatish Balay }
141d71ae5a4SJacob Faibussowitsch static inline void Waxpy2Real(PetscReal a, const PetscReal *x, const PetscReal *y, PetscReal *w)
142d71ae5a4SJacob Faibussowitsch {
1439371c9d4SSatish Balay   w[0] = a * x[0] + y[0];
1449371c9d4SSatish Balay   w[1] = a * x[1] + y[1];
1459371c9d4SSatish Balay }
146d71ae5a4SJacob Faibussowitsch static inline void Scale2Real(PetscReal a, const PetscReal *x, PetscReal *y)
147d71ae5a4SJacob Faibussowitsch {
1489371c9d4SSatish Balay   y[0] = a * x[0];
1499371c9d4SSatish Balay   y[1] = a * x[1];
1509371c9d4SSatish Balay }
151c4762a1bSJed Brown 
152c4762a1bSJed Brown /******************* Advect ********************/
1539371c9d4SSatish Balay typedef enum {
1549371c9d4SSatish Balay   ADVECT_SOL_TILTED,
1559371c9d4SSatish Balay   ADVECT_SOL_BUMP,
1569371c9d4SSatish Balay   ADVECT_SOL_BUMP_CAVITY
1579371c9d4SSatish Balay } AdvectSolType;
158c4762a1bSJed Brown static const char *const AdvectSolTypes[] = {"TILTED", "BUMP", "BUMP_CAVITY", "AdvectSolType", "ADVECT_SOL_", 0};
1599371c9d4SSatish Balay typedef enum {
1609371c9d4SSatish Balay   ADVECT_SOL_BUMP_CONE,
1619371c9d4SSatish Balay   ADVECT_SOL_BUMP_COS
1629371c9d4SSatish Balay } AdvectSolBumpType;
163c4762a1bSJed Brown static const char *const AdvectSolBumpTypes[] = {"CONE", "COS", "AdvectSolBumpType", "ADVECT_SOL_BUMP_", 0};
164c4762a1bSJed Brown 
165c4762a1bSJed Brown typedef struct {
166c4762a1bSJed Brown   PetscReal wind[DIM];
167c4762a1bSJed Brown } Physics_Advect_Tilted;
168c4762a1bSJed Brown typedef struct {
169c4762a1bSJed Brown   PetscReal         center[DIM];
170c4762a1bSJed Brown   PetscReal         radius;
171c4762a1bSJed Brown   AdvectSolBumpType type;
172c4762a1bSJed Brown } Physics_Advect_Bump;
173c4762a1bSJed Brown 
174c4762a1bSJed Brown typedef struct {
175c4762a1bSJed Brown   PetscReal     inflowState;
176c4762a1bSJed Brown   AdvectSolType soltype;
1779371c9d4SSatish Balay   union
1789371c9d4SSatish Balay   {
179c4762a1bSJed Brown     Physics_Advect_Tilted tilted;
180c4762a1bSJed Brown     Physics_Advect_Bump   bump;
181c4762a1bSJed Brown   } sol;
182c4762a1bSJed Brown   struct {
183c4762a1bSJed Brown     PetscInt Solution;
184c4762a1bSJed Brown     PetscInt Error;
185c4762a1bSJed Brown   } functional;
186c4762a1bSJed Brown } Physics_Advect;
187c4762a1bSJed Brown 
1889371c9d4SSatish Balay static const struct FieldDescription PhysicsFields_Advect[] = {
1899371c9d4SSatish Balay   {"U",  1},
1909371c9d4SSatish Balay   {NULL, 0}
1919371c9d4SSatish Balay };
192c4762a1bSJed Brown 
193d71ae5a4SJacob Faibussowitsch static PetscErrorCode PhysicsBoundary_Advect_Inflow(PetscReal time, const PetscReal *c, const PetscReal *n, const PetscScalar *xI, PetscScalar *xG, void *ctx)
194d71ae5a4SJacob Faibussowitsch {
195c4762a1bSJed Brown   Physics         phys   = (Physics)ctx;
196c4762a1bSJed Brown   Physics_Advect *advect = (Physics_Advect *)phys->data;
197c4762a1bSJed Brown 
198c4762a1bSJed Brown   PetscFunctionBeginUser;
199c4762a1bSJed Brown   xG[0] = advect->inflowState;
2003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
201c4762a1bSJed Brown }
202c4762a1bSJed Brown 
203d71ae5a4SJacob Faibussowitsch static PetscErrorCode PhysicsBoundary_Advect_Outflow(PetscReal time, const PetscReal *c, const PetscReal *n, const PetscScalar *xI, PetscScalar *xG, void *ctx)
204d71ae5a4SJacob Faibussowitsch {
205c4762a1bSJed Brown   PetscFunctionBeginUser;
206c4762a1bSJed Brown   xG[0] = xI[0];
2073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
208c4762a1bSJed Brown }
209c4762a1bSJed Brown 
210d71ae5a4SJacob Faibussowitsch static void PhysicsRiemann_Advect(PetscInt dim, PetscInt Nf, const PetscReal *qp, const PetscReal *n, const PetscScalar *xL, const PetscScalar *xR, PetscInt numConstants, const PetscScalar constants[], PetscScalar *flux, Physics phys)
211d71ae5a4SJacob Faibussowitsch {
212c4762a1bSJed Brown   Physics_Advect *advect = (Physics_Advect *)phys->data;
213c4762a1bSJed Brown   PetscReal       wind[DIM], wn;
214c4762a1bSJed Brown 
215c4762a1bSJed Brown   switch (advect->soltype) {
216c4762a1bSJed Brown   case ADVECT_SOL_TILTED: {
217c4762a1bSJed Brown     Physics_Advect_Tilted *tilted = &advect->sol.tilted;
218c4762a1bSJed Brown     wind[0]                       = tilted->wind[0];
219c4762a1bSJed Brown     wind[1]                       = tilted->wind[1];
220c4762a1bSJed Brown   } break;
221c4762a1bSJed Brown   case ADVECT_SOL_BUMP:
222c4762a1bSJed Brown     wind[0] = -qp[1];
223c4762a1bSJed Brown     wind[1] = qp[0];
224c4762a1bSJed Brown     break;
2259371c9d4SSatish Balay   case ADVECT_SOL_BUMP_CAVITY: {
226c4762a1bSJed Brown     PetscInt  i;
227c4762a1bSJed Brown     PetscReal comp2[3] = {0., 0., 0.}, rad2;
228c4762a1bSJed Brown 
229c4762a1bSJed Brown     rad2 = 0.;
230c4762a1bSJed Brown     for (i = 0; i < dim; i++) {
231c4762a1bSJed Brown       comp2[i] = qp[i] * qp[i];
232c4762a1bSJed Brown       rad2 += comp2[i];
233c4762a1bSJed Brown     }
234c4762a1bSJed Brown 
235c4762a1bSJed Brown     wind[0] = -qp[1];
236c4762a1bSJed Brown     wind[1] = qp[0];
237c4762a1bSJed Brown     if (rad2 > 1.) {
238c4762a1bSJed Brown       PetscInt  maxI     = 0;
239c4762a1bSJed Brown       PetscReal maxComp2 = comp2[0];
240c4762a1bSJed Brown 
241c4762a1bSJed Brown       for (i = 1; i < dim; i++) {
242c4762a1bSJed Brown         if (comp2[i] > maxComp2) {
243c4762a1bSJed Brown           maxI     = i;
244c4762a1bSJed Brown           maxComp2 = comp2[i];
245c4762a1bSJed Brown         }
246c4762a1bSJed Brown       }
247c4762a1bSJed Brown       wind[maxI] = 0.;
248c4762a1bSJed Brown     }
2499371c9d4SSatish Balay   } break;
2509371c9d4SSatish Balay   default: {
251c4762a1bSJed Brown     PetscInt i;
252c4762a1bSJed Brown     for (i = 0; i < DIM; ++i) wind[i] = 0.0;
253c4762a1bSJed Brown   }
25498921bdaSJacob Faibussowitsch     /* default: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for solution type %s",AdvectSolBumpTypes[advect->soltype]); */
255c4762a1bSJed Brown   }
256c4762a1bSJed Brown   wn      = Dot2Real(wind, n);
257c4762a1bSJed Brown   flux[0] = (wn > 0 ? xL[0] : xR[0]) * wn;
258c4762a1bSJed Brown }
259c4762a1bSJed Brown 
260d71ae5a4SJacob Faibussowitsch static PetscErrorCode PhysicsSolution_Advect(Model mod, PetscReal time, const PetscReal *x, PetscScalar *u, void *ctx)
261d71ae5a4SJacob Faibussowitsch {
262c4762a1bSJed Brown   Physics         phys   = (Physics)ctx;
263c4762a1bSJed Brown   Physics_Advect *advect = (Physics_Advect *)phys->data;
264c4762a1bSJed Brown 
265c4762a1bSJed Brown   PetscFunctionBeginUser;
266c4762a1bSJed Brown   switch (advect->soltype) {
267c4762a1bSJed Brown   case ADVECT_SOL_TILTED: {
268c4762a1bSJed Brown     PetscReal              x0[DIM];
269c4762a1bSJed Brown     Physics_Advect_Tilted *tilted = &advect->sol.tilted;
270c4762a1bSJed Brown     Waxpy2Real(-time, tilted->wind, x, x0);
271c4762a1bSJed Brown     if (x0[1] > 0) u[0] = 1. * x[0] + 3. * x[1];
272c4762a1bSJed Brown     else u[0] = advect->inflowState;
273c4762a1bSJed Brown   } break;
274c4762a1bSJed Brown   case ADVECT_SOL_BUMP_CAVITY:
275c4762a1bSJed Brown   case ADVECT_SOL_BUMP: {
276c4762a1bSJed Brown     Physics_Advect_Bump *bump = &advect->sol.bump;
277c4762a1bSJed Brown     PetscReal            x0[DIM], v[DIM], r, cost, sint;
278c4762a1bSJed Brown     cost  = PetscCosReal(time);
279c4762a1bSJed Brown     sint  = PetscSinReal(time);
280c4762a1bSJed Brown     x0[0] = cost * x[0] + sint * x[1];
281c4762a1bSJed Brown     x0[1] = -sint * x[0] + cost * x[1];
282c4762a1bSJed Brown     Waxpy2Real(-1, bump->center, x0, v);
283c4762a1bSJed Brown     r = Norm2Real(v);
284c4762a1bSJed Brown     switch (bump->type) {
285d71ae5a4SJacob Faibussowitsch     case ADVECT_SOL_BUMP_CONE:
286d71ae5a4SJacob Faibussowitsch       u[0] = PetscMax(1 - r / bump->radius, 0);
287d71ae5a4SJacob Faibussowitsch       break;
288d71ae5a4SJacob Faibussowitsch     case ADVECT_SOL_BUMP_COS:
289d71ae5a4SJacob Faibussowitsch       u[0] = 0.5 + 0.5 * PetscCosReal(PetscMin(r / bump->radius, 1) * PETSC_PI);
290d71ae5a4SJacob Faibussowitsch       break;
291c4762a1bSJed Brown     }
292c4762a1bSJed Brown   } break;
293d71ae5a4SJacob Faibussowitsch   default:
294d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unknown solution type");
295c4762a1bSJed Brown   }
2963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
297c4762a1bSJed Brown }
298c4762a1bSJed Brown 
299d71ae5a4SJacob Faibussowitsch static PetscErrorCode PhysicsFunctional_Advect(Model mod, PetscReal time, const PetscReal *x, const PetscScalar *y, PetscReal *f, void *ctx)
300d71ae5a4SJacob Faibussowitsch {
301c4762a1bSJed Brown   Physics         phys      = (Physics)ctx;
302c4762a1bSJed Brown   Physics_Advect *advect    = (Physics_Advect *)phys->data;
303391faea4SSatish Balay   PetscScalar     yexact[1] = {0.0};
304c4762a1bSJed Brown 
305c4762a1bSJed Brown   PetscFunctionBeginUser;
3069566063dSJacob Faibussowitsch   PetscCall(PhysicsSolution_Advect(mod, time, x, yexact, phys));
307c4762a1bSJed Brown   f[advect->functional.Solution] = PetscRealPart(y[0]);
308c4762a1bSJed Brown   f[advect->functional.Error]    = PetscAbsScalar(y[0] - yexact[0]);
3093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
310c4762a1bSJed Brown }
311c4762a1bSJed Brown 
312d71ae5a4SJacob Faibussowitsch static PetscErrorCode SetUpBC_Advect(DM dm, PetscDS prob, Physics phys)
313d71ae5a4SJacob Faibussowitsch {
314c4762a1bSJed Brown   const PetscInt inflowids[] = {100, 200, 300}, outflowids[] = {101};
31545480ffeSMatthew G. Knepley   DMLabel        label;
316c4762a1bSJed Brown 
317c4762a1bSJed Brown   PetscFunctionBeginUser;
318c4762a1bSJed Brown   /* Register "canned" boundary conditions and defaults for where to apply. */
3199566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
320dd39110bSPierre Jolivet   PetscCall(PetscDSAddBoundary(prob, DM_BC_NATURAL_RIEMANN, "inflow", label, PETSC_STATIC_ARRAY_LENGTH(inflowids), inflowids, 0, 0, NULL, (void (*)(void))PhysicsBoundary_Advect_Inflow, NULL, phys, NULL));
321dd39110bSPierre Jolivet   PetscCall(PetscDSAddBoundary(prob, DM_BC_NATURAL_RIEMANN, "outflow", label, PETSC_STATIC_ARRAY_LENGTH(outflowids), outflowids, 0, 0, NULL, (void (*)(void))PhysicsBoundary_Advect_Outflow, NULL, phys, NULL));
3223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
323c4762a1bSJed Brown }
324c4762a1bSJed Brown 
325d71ae5a4SJacob Faibussowitsch static PetscErrorCode PhysicsCreate_Advect(Model mod, Physics phys, PetscOptionItems *PetscOptionsObject)
326d71ae5a4SJacob Faibussowitsch {
327c4762a1bSJed Brown   Physics_Advect *advect;
328c4762a1bSJed Brown 
329c4762a1bSJed Brown   PetscFunctionBeginUser;
330c4762a1bSJed Brown   phys->field_desc = PhysicsFields_Advect;
331c4762a1bSJed Brown   phys->riemann    = (PetscRiemannFunc)PhysicsRiemann_Advect;
3329566063dSJacob Faibussowitsch   PetscCall(PetscNew(&advect));
333c4762a1bSJed Brown   phys->data   = advect;
334c4762a1bSJed Brown   mod->setupbc = SetUpBC_Advect;
335c4762a1bSJed Brown 
336d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "Advect options");
337c4762a1bSJed Brown   {
338c4762a1bSJed Brown     PetscInt two = 2, dof = 1;
339c4762a1bSJed Brown     advect->soltype = ADVECT_SOL_TILTED;
3409566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEnum("-advect_sol_type", "solution type", "", AdvectSolTypes, (PetscEnum)advect->soltype, (PetscEnum *)&advect->soltype, NULL));
341c4762a1bSJed Brown     switch (advect->soltype) {
342c4762a1bSJed Brown     case ADVECT_SOL_TILTED: {
343c4762a1bSJed Brown       Physics_Advect_Tilted *tilted = &advect->sol.tilted;
344c4762a1bSJed Brown       two                           = 2;
345c4762a1bSJed Brown       tilted->wind[0]               = 0.0;
346c4762a1bSJed Brown       tilted->wind[1]               = 1.0;
3479566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-advect_tilted_wind", "background wind vx,vy", "", tilted->wind, &two, NULL));
348c4762a1bSJed Brown       advect->inflowState = -2.0;
3499566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-advect_tilted_inflow", "Inflow state", "", &advect->inflowState, &dof, NULL));
350c4762a1bSJed Brown       phys->maxspeed = Norm2Real(tilted->wind);
351c4762a1bSJed Brown     } break;
352c4762a1bSJed Brown     case ADVECT_SOL_BUMP_CAVITY:
353c4762a1bSJed Brown     case ADVECT_SOL_BUMP: {
354c4762a1bSJed Brown       Physics_Advect_Bump *bump = &advect->sol.bump;
355c4762a1bSJed Brown       two                       = 2;
356c4762a1bSJed Brown       bump->center[0]           = 2.;
357c4762a1bSJed Brown       bump->center[1]           = 0.;
3589566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-advect_bump_center", "location of center of bump x,y", "", bump->center, &two, NULL));
359c4762a1bSJed Brown       bump->radius = 0.9;
3609566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-advect_bump_radius", "radius of bump", "", bump->radius, &bump->radius, NULL));
361c4762a1bSJed Brown       bump->type = ADVECT_SOL_BUMP_CONE;
3629566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnum("-advect_bump_type", "type of bump", "", AdvectSolBumpTypes, (PetscEnum)bump->type, (PetscEnum *)&bump->type, NULL));
363c4762a1bSJed Brown       phys->maxspeed = 3.; /* radius of mesh, kludge */
364c4762a1bSJed Brown     } break;
365c4762a1bSJed Brown     }
366c4762a1bSJed Brown   }
367d0609cedSBarry Smith   PetscOptionsHeadEnd();
368c4762a1bSJed Brown   /* Initial/transient solution with default boundary conditions */
3699566063dSJacob Faibussowitsch   PetscCall(ModelSolutionSetDefault(mod, PhysicsSolution_Advect, phys));
370c4762a1bSJed Brown   /* Register "canned" functionals */
3719566063dSJacob Faibussowitsch   PetscCall(ModelFunctionalRegister(mod, "Solution", &advect->functional.Solution, PhysicsFunctional_Advect, phys));
3729566063dSJacob Faibussowitsch   PetscCall(ModelFunctionalRegister(mod, "Error", &advect->functional.Error, PhysicsFunctional_Advect, phys));
3733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
374c4762a1bSJed Brown }
375c4762a1bSJed Brown 
376c4762a1bSJed Brown /******************* Shallow Water ********************/
377c4762a1bSJed Brown typedef struct {
378c4762a1bSJed Brown   PetscReal gravity;
379c4762a1bSJed Brown   PetscReal boundaryHeight;
380c4762a1bSJed Brown   struct {
381c4762a1bSJed Brown     PetscInt Height;
382c4762a1bSJed Brown     PetscInt Speed;
383c4762a1bSJed Brown     PetscInt Energy;
384c4762a1bSJed Brown   } functional;
385c4762a1bSJed Brown } Physics_SW;
386c4762a1bSJed Brown typedef struct {
387c4762a1bSJed Brown   PetscReal h;
388c4762a1bSJed Brown   PetscReal uh[DIM];
389c4762a1bSJed Brown } SWNode;
3909371c9d4SSatish Balay typedef union
3919371c9d4SSatish Balay {
392c4762a1bSJed Brown   SWNode    swnode;
393c4762a1bSJed Brown   PetscReal vals[DIM + 1];
394c4762a1bSJed Brown } SWNodeUnion;
395c4762a1bSJed Brown 
3969371c9d4SSatish Balay static const struct FieldDescription PhysicsFields_SW[] = {
3979371c9d4SSatish Balay   {"Height",   1  },
3989371c9d4SSatish Balay   {"Momentum", DIM},
3999371c9d4SSatish Balay   {NULL,       0  }
4009371c9d4SSatish Balay };
401c4762a1bSJed Brown 
402c4762a1bSJed Brown /*
403c4762a1bSJed Brown  * h_t + div(uh) = 0
404c4762a1bSJed Brown  * (uh)_t + div (u\otimes uh + g h^2 / 2 I) = 0
405c4762a1bSJed Brown  *
406c4762a1bSJed Brown  * */
407d71ae5a4SJacob Faibussowitsch static PetscErrorCode SWFlux(Physics phys, const PetscReal *n, const SWNode *x, SWNode *f)
408d71ae5a4SJacob Faibussowitsch {
409c4762a1bSJed Brown   Physics_SW *sw = (Physics_SW *)phys->data;
410c4762a1bSJed Brown   PetscReal   uhn, u[DIM];
411c4762a1bSJed Brown   PetscInt    i;
412c4762a1bSJed Brown 
413c4762a1bSJed Brown   PetscFunctionBeginUser;
414c4762a1bSJed Brown   Scale2Real(1. / x->h, x->uh, u);
415c4762a1bSJed Brown   uhn  = x->uh[0] * n[0] + x->uh[1] * n[1];
416c4762a1bSJed Brown   f->h = uhn;
417c4762a1bSJed Brown   for (i = 0; i < DIM; i++) f->uh[i] = u[i] * uhn + sw->gravity * PetscSqr(x->h) * n[i];
4183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
419c4762a1bSJed Brown }
420c4762a1bSJed Brown 
421d71ae5a4SJacob Faibussowitsch static PetscErrorCode PhysicsBoundary_SW_Wall(PetscReal time, const PetscReal *c, const PetscReal *n, const PetscScalar *xI, PetscScalar *xG, void *ctx)
422d71ae5a4SJacob Faibussowitsch {
423c4762a1bSJed Brown   PetscFunctionBeginUser;
424c4762a1bSJed Brown   xG[0] = xI[0];
425c4762a1bSJed Brown   xG[1] = -xI[1];
426c4762a1bSJed Brown   xG[2] = -xI[2];
4273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
428c4762a1bSJed Brown }
429c4762a1bSJed Brown 
430d71ae5a4SJacob Faibussowitsch static void PhysicsRiemann_SW_HLL(PetscInt dim, PetscInt Nf, const PetscReal *qp, const PetscReal *n, const PetscScalar *xL, const PetscScalar *xR, PetscInt numConstants, const PetscScalar constants[], PetscScalar *flux, Physics phys)
431d71ae5a4SJacob Faibussowitsch {
4328d2c18caSMukkund Sunjii   Physics_SW *sw = (Physics_SW *)phys->data;
4338d2c18caSMukkund Sunjii   PetscReal   aL, aR;
4348d2c18caSMukkund Sunjii   PetscReal   nn[DIM];
4358d2c18caSMukkund Sunjii #if !defined(PETSC_USE_COMPLEX)
4368d2c18caSMukkund Sunjii   const SWNode *uL = (const SWNode *)xL, *uR = (const SWNode *)xR;
4378d2c18caSMukkund Sunjii #else
4388d2c18caSMukkund Sunjii   SWNodeUnion   uLreal, uRreal;
4398d2c18caSMukkund Sunjii   const SWNode *uL = &uLreal.swnode;
4408d2c18caSMukkund Sunjii   const SWNode *uR = &uRreal.swnode;
4418d2c18caSMukkund Sunjii #endif
4428d2c18caSMukkund Sunjii   SWNodeUnion fL, fR;
4438d2c18caSMukkund Sunjii   PetscInt    i;
4448d2c18caSMukkund Sunjii   PetscReal   zero = 0.;
4458d2c18caSMukkund Sunjii 
4468d2c18caSMukkund Sunjii #if defined(PETSC_USE_COMPLEX)
4479371c9d4SSatish Balay   uLreal.swnode.h = 0;
4489371c9d4SSatish Balay   uRreal.swnode.h = 0;
4498d2c18caSMukkund Sunjii   for (i = 0; i < 1 + dim; i++) uLreal.vals[i] = PetscRealPart(xL[i]);
4508d2c18caSMukkund Sunjii   for (i = 0; i < 1 + dim; i++) uRreal.vals[i] = PetscRealPart(xR[i]);
4518d2c18caSMukkund Sunjii #endif
4528d2c18caSMukkund Sunjii   if (uL->h <= 0 || uR->h <= 0) {
4538d2c18caSMukkund Sunjii     for (i = 0; i < 1 + dim; i++) flux[i] = zero;
4548d2c18caSMukkund Sunjii     return;
4558d2c18caSMukkund Sunjii   } /* SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Reconstructed thickness is negative"); */
4568d2c18caSMukkund Sunjii   nn[0] = n[0];
4578d2c18caSMukkund Sunjii   nn[1] = n[1];
4588d2c18caSMukkund Sunjii   Normalize2Real(nn);
4593ba16761SJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, SWFlux(phys, nn, uL, &(fL.swnode)));
4603ba16761SJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, SWFlux(phys, nn, uR, &(fR.swnode)));
4618d2c18caSMukkund Sunjii   /* gravity wave speed */
4628d2c18caSMukkund Sunjii   aL = PetscSqrtReal(sw->gravity * uL->h);
4638d2c18caSMukkund Sunjii   aR = PetscSqrtReal(sw->gravity * uR->h);
4648d2c18caSMukkund Sunjii   // Defining u_tilda and v_tilda as u and v
4658d2c18caSMukkund Sunjii   PetscReal u_L, u_R;
4668d2c18caSMukkund Sunjii   u_L = Dot2Real(uL->uh, nn) / uL->h;
4678d2c18caSMukkund Sunjii   u_R = Dot2Real(uR->uh, nn) / uR->h;
4688d2c18caSMukkund Sunjii   PetscReal sL, sR;
4698d2c18caSMukkund Sunjii   sL = PetscMin(u_L - aL, u_R - aR);
4708d2c18caSMukkund Sunjii   sR = PetscMax(u_L + aL, u_R + aR);
4718d2c18caSMukkund Sunjii   if (sL > zero) {
472ad540459SPierre Jolivet     for (i = 0; i < dim + 1; i++) flux[i] = fL.vals[i] * Norm2Real(n);
4738d2c18caSMukkund Sunjii   } else if (sR < zero) {
474ad540459SPierre Jolivet     for (i = 0; i < dim + 1; i++) flux[i] = fR.vals[i] * Norm2Real(n);
4758d2c18caSMukkund Sunjii   } else {
476ad540459SPierre Jolivet     for (i = 0; i < dim + 1; i++) flux[i] = ((sR * fL.vals[i] - sL * fR.vals[i] + sR * sL * (xR[i] - xL[i])) / (sR - sL)) * Norm2Real(n);
4778d2c18caSMukkund Sunjii   }
4788d2c18caSMukkund Sunjii }
4798d2c18caSMukkund Sunjii 
480d71ae5a4SJacob Faibussowitsch static void PhysicsRiemann_SW_Rusanov(PetscInt dim, PetscInt Nf, const PetscReal *qp, const PetscReal *n, const PetscScalar *xL, const PetscScalar *xR, PetscInt numConstants, const PetscScalar constants[], PetscScalar *flux, Physics phys)
481d71ae5a4SJacob Faibussowitsch {
482c4762a1bSJed Brown   Physics_SW *sw = (Physics_SW *)phys->data;
483c4762a1bSJed Brown   PetscReal   cL, cR, speed;
484c4762a1bSJed Brown   PetscReal   nn[DIM];
485c4762a1bSJed Brown #if !defined(PETSC_USE_COMPLEX)
486c4762a1bSJed Brown   const SWNode *uL = (const SWNode *)xL, *uR = (const SWNode *)xR;
487c4762a1bSJed Brown #else
488c4762a1bSJed Brown   SWNodeUnion   uLreal, uRreal;
489c4762a1bSJed Brown   const SWNode *uL = &uLreal.swnode;
490c4762a1bSJed Brown   const SWNode *uR = &uRreal.swnode;
491c4762a1bSJed Brown #endif
492c4762a1bSJed Brown   SWNodeUnion fL, fR;
493c4762a1bSJed Brown   PetscInt    i;
494c4762a1bSJed Brown   PetscReal   zero = 0.;
495c4762a1bSJed Brown 
496c4762a1bSJed Brown #if defined(PETSC_USE_COMPLEX)
4979371c9d4SSatish Balay   uLreal.swnode.h = 0;
4989371c9d4SSatish Balay   uRreal.swnode.h = 0;
499c4762a1bSJed Brown   for (i = 0; i < 1 + dim; i++) uLreal.vals[i] = PetscRealPart(xL[i]);
500c4762a1bSJed Brown   for (i = 0; i < 1 + dim; i++) uRreal.vals[i] = PetscRealPart(xR[i]);
501c4762a1bSJed Brown #endif
5029371c9d4SSatish Balay   if (uL->h < 0 || uR->h < 0) {
5039371c9d4SSatish Balay     for (i = 0; i < 1 + dim; i++) flux[i] = zero / zero;
5049371c9d4SSatish Balay     return;
5059371c9d4SSatish Balay   } /* reconstructed thickness is negative */
506c4762a1bSJed Brown   nn[0] = n[0];
507c4762a1bSJed Brown   nn[1] = n[1];
508c4762a1bSJed Brown   Normalize2Real(nn);
5093ba16761SJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, SWFlux(phys, nn, uL, &(fL.swnode)));
5103ba16761SJacob Faibussowitsch   PetscCallAbort(PETSC_COMM_SELF, SWFlux(phys, nn, uR, &(fR.swnode)));
511c4762a1bSJed Brown   cL    = PetscSqrtReal(sw->gravity * uL->h);
512c4762a1bSJed Brown   cR    = PetscSqrtReal(sw->gravity * uR->h); /* gravity wave speed */
513c4762a1bSJed Brown   speed = PetscMax(PetscAbsReal(Dot2Real(uL->uh, nn) / uL->h) + cL, PetscAbsReal(Dot2Real(uR->uh, nn) / uR->h) + cR);
514c4762a1bSJed Brown   for (i = 0; i < 1 + dim; i++) flux[i] = (0.5 * (fL.vals[i] + fR.vals[i]) + 0.5 * speed * (xL[i] - xR[i])) * Norm2Real(n);
515c4762a1bSJed Brown }
516c4762a1bSJed Brown 
517d71ae5a4SJacob Faibussowitsch static PetscErrorCode PhysicsSolution_SW(Model mod, PetscReal time, const PetscReal *x, PetscScalar *u, void *ctx)
518d71ae5a4SJacob Faibussowitsch {
519c4762a1bSJed Brown   PetscReal dx[2], r, sigma;
520c4762a1bSJed Brown 
521c4762a1bSJed Brown   PetscFunctionBeginUser;
52254c59aa7SJacob Faibussowitsch   PetscCheck(time == 0.0, mod->comm, PETSC_ERR_SUP, "No solution known for time %g", (double)time);
523c4762a1bSJed Brown   dx[0] = x[0] - 1.5;
524c4762a1bSJed Brown   dx[1] = x[1] - 1.0;
525c4762a1bSJed Brown   r     = Norm2Real(dx);
526c4762a1bSJed Brown   sigma = 0.5;
527c4762a1bSJed Brown   u[0]  = 1 + 2 * PetscExpReal(-PetscSqr(r) / (2 * PetscSqr(sigma)));
528c4762a1bSJed Brown   u[1]  = 0.0;
529c4762a1bSJed Brown   u[2]  = 0.0;
5303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
531c4762a1bSJed Brown }
532c4762a1bSJed Brown 
533d71ae5a4SJacob Faibussowitsch static PetscErrorCode PhysicsFunctional_SW(Model mod, PetscReal time, const PetscReal *coord, const PetscScalar *xx, PetscReal *f, void *ctx)
534d71ae5a4SJacob Faibussowitsch {
535c4762a1bSJed Brown   Physics       phys = (Physics)ctx;
536c4762a1bSJed Brown   Physics_SW   *sw   = (Physics_SW *)phys->data;
537c4762a1bSJed Brown   const SWNode *x    = (const SWNode *)xx;
538c4762a1bSJed Brown   PetscReal     u[2];
539c4762a1bSJed Brown   PetscReal     h;
540c4762a1bSJed Brown 
541c4762a1bSJed Brown   PetscFunctionBeginUser;
542c4762a1bSJed Brown   h = x->h;
543c4762a1bSJed Brown   Scale2Real(1. / x->h, x->uh, u);
544c4762a1bSJed Brown   f[sw->functional.Height] = h;
545c4762a1bSJed Brown   f[sw->functional.Speed]  = Norm2Real(u) + PetscSqrtReal(sw->gravity * h);
546c4762a1bSJed Brown   f[sw->functional.Energy] = 0.5 * (Dot2Real(x->uh, u) + sw->gravity * PetscSqr(h));
5473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
548c4762a1bSJed Brown }
549c4762a1bSJed Brown 
550d71ae5a4SJacob Faibussowitsch static PetscErrorCode SetUpBC_SW(DM dm, PetscDS prob, Physics phys)
551d71ae5a4SJacob Faibussowitsch {
552c4762a1bSJed Brown   const PetscInt wallids[] = {100, 101, 200, 300};
55345480ffeSMatthew G. Knepley   DMLabel        label;
55445480ffeSMatthew G. Knepley 
555c4762a1bSJed Brown   PetscFunctionBeginUser;
5569566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
557dd39110bSPierre Jolivet   PetscCall(PetscDSAddBoundary(prob, DM_BC_NATURAL_RIEMANN, "wall", label, PETSC_STATIC_ARRAY_LENGTH(wallids), wallids, 0, 0, NULL, (void (*)(void))PhysicsBoundary_SW_Wall, NULL, phys, NULL));
5583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
559c4762a1bSJed Brown }
560c4762a1bSJed Brown 
561d71ae5a4SJacob Faibussowitsch static PetscErrorCode PhysicsCreate_SW(Model mod, Physics phys, PetscOptionItems *PetscOptionsObject)
562d71ae5a4SJacob Faibussowitsch {
563c4762a1bSJed Brown   Physics_SW *sw;
5648d2c18caSMukkund Sunjii   char        sw_riemann[64] = "rusanov";
565c4762a1bSJed Brown 
566c4762a1bSJed Brown   PetscFunctionBeginUser;
567c4762a1bSJed Brown   phys->field_desc = PhysicsFields_SW;
5689566063dSJacob Faibussowitsch   PetscCall(PetscNew(&sw));
569c4762a1bSJed Brown   phys->data   = sw;
570c4762a1bSJed Brown   mod->setupbc = SetUpBC_SW;
571c4762a1bSJed Brown 
5723ba16761SJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&PhysicsRiemannList_SW, "rusanov", PhysicsRiemann_SW_Rusanov));
5733ba16761SJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&PhysicsRiemannList_SW, "hll", PhysicsRiemann_SW_HLL));
5748d2c18caSMukkund Sunjii 
575d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "SW options");
576c4762a1bSJed Brown   {
5778d2c18caSMukkund Sunjii     void (*PhysicsRiemann_SW)(PetscInt, PetscInt, const PetscReal *, const PetscReal *, const PetscScalar *, const PetscScalar *, PetscInt, const PetscScalar, PetscScalar *, Physics);
578c4762a1bSJed Brown     sw->gravity = 1.0;
5799566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-sw_gravity", "Gravitational constant", "", sw->gravity, &sw->gravity, NULL));
5809566063dSJacob Faibussowitsch     PetscCall(PetscOptionsFList("-sw_riemann", "Riemann solver", "", PhysicsRiemannList_SW, sw_riemann, sw_riemann, sizeof sw_riemann, NULL));
5819566063dSJacob Faibussowitsch     PetscCall(PetscFunctionListFind(PhysicsRiemannList_SW, sw_riemann, &PhysicsRiemann_SW));
5828d2c18caSMukkund Sunjii     phys->riemann = (PetscRiemannFunc)PhysicsRiemann_SW;
583c4762a1bSJed Brown   }
584d0609cedSBarry Smith   PetscOptionsHeadEnd();
585c4762a1bSJed Brown   phys->maxspeed = PetscSqrtReal(2.0 * sw->gravity); /* Mach 1 for depth of 2 */
586c4762a1bSJed Brown 
5879566063dSJacob Faibussowitsch   PetscCall(ModelSolutionSetDefault(mod, PhysicsSolution_SW, phys));
5889566063dSJacob Faibussowitsch   PetscCall(ModelFunctionalRegister(mod, "Height", &sw->functional.Height, PhysicsFunctional_SW, phys));
5899566063dSJacob Faibussowitsch   PetscCall(ModelFunctionalRegister(mod, "Speed", &sw->functional.Speed, PhysicsFunctional_SW, phys));
5909566063dSJacob Faibussowitsch   PetscCall(ModelFunctionalRegister(mod, "Energy", &sw->functional.Energy, PhysicsFunctional_SW, phys));
591c4762a1bSJed Brown 
5923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
593c4762a1bSJed Brown }
594c4762a1bSJed Brown 
595c4762a1bSJed Brown /******************* Euler Density Shock (EULER_IV_SHOCK,EULER_SS_SHOCK) ********************/
596c4762a1bSJed Brown /* An initial-value and self-similar solutions of the compressible Euler equations */
597c4762a1bSJed Brown /* Ravi Samtaney and D. I. Pullin */
598c4762a1bSJed Brown /* Phys. Fluids 8, 2650 (1996); http://dx.doi.org/10.1063/1.869050 */
5999371c9d4SSatish Balay typedef enum {
6009371c9d4SSatish Balay   EULER_PAR_GAMMA,
6019371c9d4SSatish Balay   EULER_PAR_RHOR,
6029371c9d4SSatish Balay   EULER_PAR_AMACH,
6039371c9d4SSatish Balay   EULER_PAR_ITANA,
6049371c9d4SSatish Balay   EULER_PAR_SIZE
6059371c9d4SSatish Balay } EulerParamIdx;
6069371c9d4SSatish Balay typedef enum {
6079371c9d4SSatish Balay   EULER_IV_SHOCK,
6089371c9d4SSatish Balay   EULER_SS_SHOCK,
6099371c9d4SSatish Balay   EULER_SHOCK_TUBE,
6109371c9d4SSatish Balay   EULER_LINEAR_WAVE
6119371c9d4SSatish Balay } EulerType;
612c4762a1bSJed Brown typedef struct {
613c4762a1bSJed Brown   PetscReal r;
614c4762a1bSJed Brown   PetscReal ru[DIM];
615c4762a1bSJed Brown   PetscReal E;
616c4762a1bSJed Brown } EulerNode;
6179371c9d4SSatish Balay typedef union
6189371c9d4SSatish Balay {
619c4762a1bSJed Brown   EulerNode eulernode;
620c4762a1bSJed Brown   PetscReal vals[DIM + 2];
621c4762a1bSJed Brown } EulerNodeUnion;
622c4762a1bSJed Brown typedef PetscErrorCode (*EquationOfState)(const PetscReal *, const EulerNode *, PetscReal *);
623c4762a1bSJed Brown typedef struct {
624c4762a1bSJed Brown   EulerType       type;
625c4762a1bSJed Brown   PetscReal       pars[EULER_PAR_SIZE];
626c4762a1bSJed Brown   EquationOfState sound;
627c4762a1bSJed Brown   struct {
628c4762a1bSJed Brown     PetscInt Density;
629c4762a1bSJed Brown     PetscInt Momentum;
630c4762a1bSJed Brown     PetscInt Energy;
631c4762a1bSJed Brown     PetscInt Pressure;
632c4762a1bSJed Brown     PetscInt Speed;
633c4762a1bSJed Brown   } monitor;
634c4762a1bSJed Brown } Physics_Euler;
635c4762a1bSJed Brown 
6369371c9d4SSatish Balay static const struct FieldDescription PhysicsFields_Euler[] = {
6379371c9d4SSatish Balay   {"Density",  1  },
6389371c9d4SSatish Balay   {"Momentum", DIM},
6399371c9d4SSatish Balay   {"Energy",   1  },
6409371c9d4SSatish Balay   {NULL,       0  }
6419371c9d4SSatish Balay };
642c4762a1bSJed Brown 
643c4762a1bSJed Brown /* initial condition */
644c4762a1bSJed Brown int                   initLinearWave(EulerNode *ux, const PetscReal gamma, const PetscReal coord[], const PetscReal Lx);
645d71ae5a4SJacob Faibussowitsch static PetscErrorCode PhysicsSolution_Euler(Model mod, PetscReal time, const PetscReal *x, PetscScalar *u, void *ctx)
646d71ae5a4SJacob Faibussowitsch {
647c4762a1bSJed Brown   PetscInt       i;
648c4762a1bSJed Brown   Physics        phys = (Physics)ctx;
649c4762a1bSJed Brown   Physics_Euler *eu   = (Physics_Euler *)phys->data;
650c4762a1bSJed Brown   EulerNode     *uu   = (EulerNode *)u;
651c4762a1bSJed Brown   PetscReal      p0, gamma, c;
652c4762a1bSJed Brown   PetscFunctionBeginUser;
65354c59aa7SJacob Faibussowitsch   PetscCheck(time == 0.0, mod->comm, PETSC_ERR_SUP, "No solution known for time %g", (double)time);
654c4762a1bSJed Brown 
655c4762a1bSJed Brown   for (i = 0; i < DIM; i++) uu->ru[i] = 0.0; /* zero out initial velocity */
656c4762a1bSJed Brown   /* set E and rho */
657c4762a1bSJed Brown   gamma = eu->pars[EULER_PAR_GAMMA];
658c4762a1bSJed Brown 
659c4762a1bSJed Brown   if (eu->type == EULER_IV_SHOCK || eu->type == EULER_SS_SHOCK) {
660c4762a1bSJed Brown     /******************* Euler Density Shock ********************/
661c4762a1bSJed Brown     /* On initial-value and self-similar solutions of the compressible Euler equations */
662c4762a1bSJed Brown     /* Ravi Samtaney and D. I. Pullin */
663c4762a1bSJed Brown     /* Phys. Fluids 8, 2650 (1996); http://dx.doi.org/10.1063/1.869050 */
664c4762a1bSJed Brown     /* initial conditions 1: left of shock, 0: left of discontinuity 2: right of discontinuity,  */
665c4762a1bSJed Brown     p0 = 1.;
666c4762a1bSJed Brown     if (x[0] < 0.0 + x[1] * eu->pars[EULER_PAR_ITANA]) {
667c4762a1bSJed Brown       if (x[0] < mod->bounds[0] * 0.5) { /* left of shock (1) */
668c4762a1bSJed Brown         PetscReal amach, rho, press, gas1, p1;
669c4762a1bSJed Brown         amach     = eu->pars[EULER_PAR_AMACH];
670c4762a1bSJed Brown         rho       = 1.;
671c4762a1bSJed Brown         press     = p0;
672c4762a1bSJed Brown         p1        = press * (1.0 + 2.0 * gamma / (gamma + 1.0) * (amach * amach - 1.0));
673c4762a1bSJed Brown         gas1      = (gamma - 1.0) / (gamma + 1.0);
674c4762a1bSJed Brown         uu->r     = rho * (p1 / press + gas1) / (gas1 * p1 / press + 1.0);
675c4762a1bSJed Brown         uu->ru[0] = ((uu->r - rho) * PetscSqrtReal(gamma * press / rho) * amach);
676c4762a1bSJed Brown         uu->E     = p1 / (gamma - 1.0) + .5 / uu->r * uu->ru[0] * uu->ru[0];
6779371c9d4SSatish Balay       } else {      /* left of discontinuity (0) */
678c4762a1bSJed Brown         uu->r = 1.; /* rho = 1 */
679c4762a1bSJed Brown         uu->E = p0 / (gamma - 1.0);
680c4762a1bSJed Brown       }
6819371c9d4SSatish Balay     } else { /* right of discontinuity (2) */
682c4762a1bSJed Brown       uu->r = eu->pars[EULER_PAR_RHOR];
683c4762a1bSJed Brown       uu->E = p0 / (gamma - 1.0);
684c4762a1bSJed Brown     }
6859371c9d4SSatish Balay   } else if (eu->type == EULER_SHOCK_TUBE) {
686c4762a1bSJed Brown     /* For (x<x0) set (rho,u,p)=(8,0,10) and for (x>x0) set (rho,u,p)=(1,0,1). Choose x0 to the midpoint of the domain in the x-direction. */
687c4762a1bSJed Brown     if (x[0] < 0.0) {
688c4762a1bSJed Brown       uu->r = 8.;
689c4762a1bSJed Brown       uu->E = 10. / (gamma - 1.);
6909371c9d4SSatish Balay     } else {
691c4762a1bSJed Brown       uu->r = 1.;
692c4762a1bSJed Brown       uu->E = 1. / (gamma - 1.);
693c4762a1bSJed Brown     }
6949371c9d4SSatish Balay   } else if (eu->type == EULER_LINEAR_WAVE) {
695c4762a1bSJed Brown     initLinearWave(uu, gamma, x, mod->bounds[1] - mod->bounds[0]);
6969371c9d4SSatish Balay   } else SETERRQ(mod->comm, PETSC_ERR_SUP, "Unknown type %d", eu->type);
697c4762a1bSJed Brown 
698c4762a1bSJed Brown   /* set phys->maxspeed: (mod->maxspeed = phys->maxspeed) in main; */
6993ba16761SJacob Faibussowitsch   PetscCall(eu->sound(&gamma, uu, &c));
700c4762a1bSJed Brown   c = (uu->ru[0] / uu->r) + c;
701c4762a1bSJed Brown   if (c > phys->maxspeed) phys->maxspeed = c;
702c4762a1bSJed Brown 
7033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
704c4762a1bSJed Brown }
705c4762a1bSJed Brown 
706d71ae5a4SJacob Faibussowitsch static PetscErrorCode Pressure_PG(const PetscReal gamma, const EulerNode *x, PetscReal *p)
707d71ae5a4SJacob Faibussowitsch {
708c4762a1bSJed Brown   PetscReal ru2;
709c4762a1bSJed Brown 
710c4762a1bSJed Brown   PetscFunctionBeginUser;
711c4762a1bSJed Brown   ru2  = DotDIMReal(x->ru, x->ru);
712c4762a1bSJed Brown   (*p) = (x->E - 0.5 * ru2 / x->r) * (gamma - 1.0); /* (E - rho V^2/2)(gamma-1) = e rho (gamma-1) */
7133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
714c4762a1bSJed Brown }
715c4762a1bSJed Brown 
716d71ae5a4SJacob Faibussowitsch static PetscErrorCode SpeedOfSound_PG(const PetscReal *gamma, const EulerNode *x, PetscReal *c)
717d71ae5a4SJacob Faibussowitsch {
718c4762a1bSJed Brown   PetscReal p;
719c4762a1bSJed Brown 
720c4762a1bSJed Brown   PetscFunctionBeginUser;
7213ba16761SJacob Faibussowitsch   PetscCall(Pressure_PG(*gamma, x, &p));
72254c59aa7SJacob Faibussowitsch   PetscCheck(p >= 0., PETSC_COMM_WORLD, PETSC_ERR_SUP, "negative pressure time %g -- NEED TO FIX!!!!!!", (double)p);
723c4762a1bSJed Brown   /* pars[EULER_PAR_GAMMA] = heat capacity ratio */
724c4762a1bSJed Brown   (*c) = PetscSqrtReal(*gamma * p / x->r);
7253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
726c4762a1bSJed Brown }
727c4762a1bSJed Brown 
728c4762a1bSJed Brown /*
729c4762a1bSJed Brown  * x = (rho,rho*(u_1),...,rho*e)^T
730c4762a1bSJed Brown  * x_t+div(f_1(x))+...+div(f_DIM(x)) = 0
731c4762a1bSJed Brown  *
732c4762a1bSJed Brown  * f_i(x) = u_i*x+(0,0,...,p,...,p*u_i)^T
733c4762a1bSJed Brown  *
734c4762a1bSJed Brown  */
735d71ae5a4SJacob Faibussowitsch static PetscErrorCode EulerFlux(Physics phys, const PetscReal *n, const EulerNode *x, EulerNode *f)
736d71ae5a4SJacob Faibussowitsch {
737c4762a1bSJed Brown   Physics_Euler *eu = (Physics_Euler *)phys->data;
738c4762a1bSJed Brown   PetscReal      nu, p;
739c4762a1bSJed Brown   PetscInt       i;
740c4762a1bSJed Brown 
741c4762a1bSJed Brown   PetscFunctionBeginUser;
7423ba16761SJacob Faibussowitsch   PetscCall(Pressure_PG(eu->pars[EULER_PAR_GAMMA], x, &p));
743c4762a1bSJed Brown   nu   = DotDIMReal(x->ru, n);
744c4762a1bSJed Brown   f->r = nu;                                                     /* A rho u */
745c4762a1bSJed Brown   nu /= x->r;                                                    /* A u */
746c4762a1bSJed Brown   for (i = 0; i < DIM; i++) f->ru[i] = nu * x->ru[i] + n[i] * p; /* r u^2 + p */
747c4762a1bSJed Brown   f->E = nu * (x->E + p);                                        /* u(e+p) */
7483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
749c4762a1bSJed Brown }
750c4762a1bSJed Brown 
751c4762a1bSJed Brown /* PetscReal* => EulerNode* conversion */
752d71ae5a4SJacob Faibussowitsch static PetscErrorCode PhysicsBoundary_Euler_Wall(PetscReal time, const PetscReal *c, const PetscReal *n, const PetscScalar *a_xI, PetscScalar *a_xG, void *ctx)
753d71ae5a4SJacob Faibussowitsch {
754c4762a1bSJed Brown   PetscInt         i;
755c4762a1bSJed Brown   const EulerNode *xI   = (const EulerNode *)a_xI;
756c4762a1bSJed Brown   EulerNode       *xG   = (EulerNode *)a_xG;
757c4762a1bSJed Brown   Physics          phys = (Physics)ctx;
758c4762a1bSJed Brown   Physics_Euler   *eu   = (Physics_Euler *)phys->data;
759c4762a1bSJed Brown   PetscFunctionBeginUser;
760c4762a1bSJed Brown   xG->r = xI->r;                                     /* ghost cell density - same */
761c4762a1bSJed Brown   xG->E = xI->E;                                     /* ghost cell energy - same */
762c4762a1bSJed Brown   if (n[1] != 0.) {                                  /* top and bottom */
763c4762a1bSJed Brown     xG->ru[0] = xI->ru[0];                           /* copy tang to wall */
764c4762a1bSJed Brown     xG->ru[1] = -xI->ru[1];                          /* reflect perp to t/b wall */
7659371c9d4SSatish Balay   } else {                                           /* sides */
766c4762a1bSJed Brown     for (i = 0; i < DIM; i++) xG->ru[i] = xI->ru[i]; /* copy */
767c4762a1bSJed Brown   }
768c4762a1bSJed Brown   if (eu->type == EULER_LINEAR_WAVE) { /* debug */
769c4762a1bSJed Brown #if 0
77063a3b9bcSJacob Faibussowitsch     PetscPrintf(PETSC_COMM_WORLD,"%s coord=%g,%g\n",PETSC_FUNCTION_NAME,(double)c[0],(double)c[1]);
771c4762a1bSJed Brown #endif
772c4762a1bSJed Brown   }
7733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
774c4762a1bSJed Brown }
775c4762a1bSJed Brown int godunovflux(const PetscScalar *ul, const PetscScalar *ur, PetscScalar *flux, const PetscReal *nn, const int *ndim, const PetscReal *gamma);
776c4762a1bSJed Brown /* PetscReal* => EulerNode* conversion */
777d71ae5a4SJacob Faibussowitsch static void PhysicsRiemann_Euler_Godunov(PetscInt dim, PetscInt Nf, const PetscReal *qp, const PetscReal *n, const PetscScalar *xL, const PetscScalar *xR, PetscInt numConstants, const PetscScalar constants[], PetscScalar *flux, Physics phys)
778d71ae5a4SJacob Faibussowitsch {
779c4762a1bSJed Brown   Physics_Euler *eu = (Physics_Euler *)phys->data;
780c4762a1bSJed Brown   PetscReal      cL, cR, speed, velL, velR, nn[DIM], s2;
781c4762a1bSJed Brown   PetscInt       i;
782c4762a1bSJed Brown   PetscErrorCode ierr;
783c4762a1bSJed Brown 
784d0609cedSBarry Smith   PetscFunctionBeginUser;
785c4762a1bSJed Brown   for (i = 0, s2 = 0.; i < DIM; i++) {
786c4762a1bSJed Brown     nn[i] = n[i];
787c4762a1bSJed Brown     s2 += nn[i] * nn[i];
788c4762a1bSJed Brown   }
789c4762a1bSJed Brown   s2 = PetscSqrtReal(s2); /* |n|_2 = sum(n^2)^1/2 */
790c4762a1bSJed Brown   for (i = 0.; i < DIM; i++) nn[i] /= s2;
791c4762a1bSJed Brown   if (0) { /* Rusanov */
792c4762a1bSJed Brown     const EulerNode *uL = (const EulerNode *)xL, *uR = (const EulerNode *)xR;
793c4762a1bSJed Brown     EulerNodeUnion   fL, fR;
7943ba16761SJacob Faibussowitsch     PetscCallAbort(PETSC_COMM_SELF, EulerFlux(phys, nn, uL, &(fL.eulernode)));
7953ba16761SJacob Faibussowitsch     PetscCallAbort(PETSC_COMM_SELF, EulerFlux(phys, nn, uR, &(fR.eulernode)));
7969371c9d4SSatish Balay     ierr = eu->sound(&eu->pars[EULER_PAR_GAMMA], uL, &cL);
7979371c9d4SSatish Balay     if (ierr) exit(13);
7989371c9d4SSatish Balay     ierr = eu->sound(&eu->pars[EULER_PAR_GAMMA], uR, &cR);
7999371c9d4SSatish Balay     if (ierr) exit(14);
800c4762a1bSJed Brown     velL  = DotDIMReal(uL->ru, nn) / uL->r;
801c4762a1bSJed Brown     velR  = DotDIMReal(uR->ru, nn) / uR->r;
802c4762a1bSJed Brown     speed = PetscMax(velR + cR, velL + cL);
803c4762a1bSJed Brown     for (i = 0; i < 2 + dim; i++) flux[i] = 0.5 * ((fL.vals[i] + fR.vals[i]) + speed * (xL[i] - xR[i])) * s2;
8049371c9d4SSatish Balay   } else {
805c4762a1bSJed Brown     int dim = DIM;
806c4762a1bSJed Brown     /* int iwave =  */
807c4762a1bSJed Brown     godunovflux(xL, xR, flux, nn, &dim, &eu->pars[EULER_PAR_GAMMA]);
808c4762a1bSJed Brown     for (i = 0; i < 2 + dim; i++) flux[i] *= s2;
809c4762a1bSJed Brown   }
810c4762a1bSJed Brown   PetscFunctionReturnVoid();
811c4762a1bSJed Brown }
812c4762a1bSJed Brown 
813d71ae5a4SJacob Faibussowitsch static PetscErrorCode PhysicsFunctional_Euler(Model mod, PetscReal time, const PetscReal *coord, const PetscScalar *xx, PetscReal *f, void *ctx)
814d71ae5a4SJacob Faibussowitsch {
815c4762a1bSJed Brown   Physics          phys = (Physics)ctx;
816c4762a1bSJed Brown   Physics_Euler   *eu   = (Physics_Euler *)phys->data;
817c4762a1bSJed Brown   const EulerNode *x    = (const EulerNode *)xx;
818c4762a1bSJed Brown   PetscReal        p;
819c4762a1bSJed Brown 
820c4762a1bSJed Brown   PetscFunctionBeginUser;
821c4762a1bSJed Brown   f[eu->monitor.Density]  = x->r;
822c4762a1bSJed Brown   f[eu->monitor.Momentum] = NormDIM(x->ru);
823c4762a1bSJed Brown   f[eu->monitor.Energy]   = x->E;
824c4762a1bSJed Brown   f[eu->monitor.Speed]    = NormDIM(x->ru) / x->r;
8253ba16761SJacob Faibussowitsch   PetscCall(Pressure_PG(eu->pars[EULER_PAR_GAMMA], x, &p));
826c4762a1bSJed Brown   f[eu->monitor.Pressure] = p;
8273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
828c4762a1bSJed Brown }
829c4762a1bSJed Brown 
830d71ae5a4SJacob Faibussowitsch static PetscErrorCode SetUpBC_Euler(DM dm, PetscDS prob, Physics phys)
831d71ae5a4SJacob Faibussowitsch {
832c4762a1bSJed Brown   Physics_Euler *eu = (Physics_Euler *)phys->data;
83345480ffeSMatthew G. Knepley   DMLabel        label;
83445480ffeSMatthew G. Knepley 
835362febeeSStefano Zampini   PetscFunctionBeginUser;
8369566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
837c4762a1bSJed Brown   if (eu->type == EULER_LINEAR_WAVE) {
838c4762a1bSJed Brown     const PetscInt wallids[] = {100, 101};
839dd39110bSPierre Jolivet     PetscCall(PetscDSAddBoundary(prob, DM_BC_NATURAL_RIEMANN, "wall", label, PETSC_STATIC_ARRAY_LENGTH(wallids), wallids, 0, 0, NULL, (void (*)(void))PhysicsBoundary_Euler_Wall, NULL, phys, NULL));
8409371c9d4SSatish Balay   } else {
841c4762a1bSJed Brown     const PetscInt wallids[] = {100, 101, 200, 300};
842dd39110bSPierre Jolivet     PetscCall(PetscDSAddBoundary(prob, DM_BC_NATURAL_RIEMANN, "wall", label, PETSC_STATIC_ARRAY_LENGTH(wallids), wallids, 0, 0, NULL, (void (*)(void))PhysicsBoundary_Euler_Wall, NULL, phys, NULL));
843c4762a1bSJed Brown   }
8443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
845c4762a1bSJed Brown }
846c4762a1bSJed Brown 
847d71ae5a4SJacob Faibussowitsch static PetscErrorCode PhysicsCreate_Euler(Model mod, Physics phys, PetscOptionItems *PetscOptionsObject)
848d71ae5a4SJacob Faibussowitsch {
849c4762a1bSJed Brown   Physics_Euler *eu;
850c4762a1bSJed Brown 
851c4762a1bSJed Brown   PetscFunctionBeginUser;
852c4762a1bSJed Brown   phys->field_desc = PhysicsFields_Euler;
853c4762a1bSJed Brown   phys->riemann    = (PetscRiemannFunc)PhysicsRiemann_Euler_Godunov;
8549566063dSJacob Faibussowitsch   PetscCall(PetscNew(&eu));
855c4762a1bSJed Brown   phys->data   = eu;
856c4762a1bSJed Brown   mod->setupbc = SetUpBC_Euler;
857d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "Euler options");
858c4762a1bSJed Brown   {
859c4762a1bSJed Brown     PetscReal alpha;
860c4762a1bSJed Brown     char      type[64] = "linear_wave";
861c4762a1bSJed Brown     PetscBool is;
862c4762a1bSJed Brown     eu->pars[EULER_PAR_GAMMA] = 1.4;
863c4762a1bSJed Brown     eu->pars[EULER_PAR_AMACH] = 2.02;
864c4762a1bSJed Brown     eu->pars[EULER_PAR_RHOR]  = 3.0;
865c4762a1bSJed Brown     eu->pars[EULER_PAR_ITANA] = 0.57735026918963; /* angle of Euler self similar (SS) shock */
8669566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-eu_gamma", "Heat capacity ratio", "", eu->pars[EULER_PAR_GAMMA], &eu->pars[EULER_PAR_GAMMA], NULL));
8679566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-eu_amach", "Shock speed (Mach)", "", eu->pars[EULER_PAR_AMACH], &eu->pars[EULER_PAR_AMACH], NULL));
8689566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-eu_rho2", "Density right of discontinuity", "", eu->pars[EULER_PAR_RHOR], &eu->pars[EULER_PAR_RHOR], NULL));
869c4762a1bSJed Brown     alpha = 60.;
8709566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-eu_alpha", "Angle of discontinuity", "", alpha, &alpha, NULL));
87163a3b9bcSJacob Faibussowitsch     PetscCheck(alpha > 0. && alpha <= 90., PETSC_COMM_WORLD, PETSC_ERR_SUP, "Alpha bust be > 0 and <= 90 (%g)", (double)alpha);
872c4762a1bSJed Brown     eu->pars[EULER_PAR_ITANA] = 1. / PetscTanReal(alpha * PETSC_PI / 180.0);
8739566063dSJacob Faibussowitsch     PetscCall(PetscOptionsString("-eu_type", "Type of Euler test", "", type, type, sizeof(type), NULL));
8749566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(type, "linear_wave", &is));
875c4762a1bSJed Brown     if (is) {
87630602db0SMatthew G. Knepley       /* Remember this should be periodic */
877c4762a1bSJed Brown       eu->type = EULER_LINEAR_WAVE;
8789566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%s set Euler type: %s\n", PETSC_FUNCTION_NAME, "linear_wave"));
8799371c9d4SSatish Balay     } else {
88054c59aa7SJacob Faibussowitsch       PetscCheck(DIM == 2, PETSC_COMM_WORLD, PETSC_ERR_SUP, "DIM must be 2 unless linear wave test %s", type);
8819566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(type, "iv_shock", &is));
882c4762a1bSJed Brown       if (is) {
883c4762a1bSJed Brown         eu->type = EULER_IV_SHOCK;
8849566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%s set Euler type: %s\n", PETSC_FUNCTION_NAME, "iv_shock"));
8859371c9d4SSatish Balay       } else {
8869566063dSJacob Faibussowitsch         PetscCall(PetscStrcmp(type, "ss_shock", &is));
887c4762a1bSJed Brown         if (is) {
888c4762a1bSJed Brown           eu->type = EULER_SS_SHOCK;
8899566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%s set Euler type: %s\n", PETSC_FUNCTION_NAME, "ss_shock"));
8909371c9d4SSatish Balay         } else {
8919566063dSJacob Faibussowitsch           PetscCall(PetscStrcmp(type, "shock_tube", &is));
892c4762a1bSJed Brown           if (is) eu->type = EULER_SHOCK_TUBE;
89398921bdaSJacob Faibussowitsch           else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Unknown Euler type %s", type);
8949566063dSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%s set Euler type: %s\n", PETSC_FUNCTION_NAME, "shock_tube"));
895c4762a1bSJed Brown         }
896c4762a1bSJed Brown       }
897c4762a1bSJed Brown     }
898c4762a1bSJed Brown   }
899d0609cedSBarry Smith   PetscOptionsHeadEnd();
900c4762a1bSJed Brown   eu->sound      = SpeedOfSound_PG;
901c4762a1bSJed Brown   phys->maxspeed = 0.; /* will get set in solution */
9029566063dSJacob Faibussowitsch   PetscCall(ModelSolutionSetDefault(mod, PhysicsSolution_Euler, phys));
9039566063dSJacob Faibussowitsch   PetscCall(ModelFunctionalRegister(mod, "Speed", &eu->monitor.Speed, PhysicsFunctional_Euler, phys));
9049566063dSJacob Faibussowitsch   PetscCall(ModelFunctionalRegister(mod, "Energy", &eu->monitor.Energy, PhysicsFunctional_Euler, phys));
9059566063dSJacob Faibussowitsch   PetscCall(ModelFunctionalRegister(mod, "Density", &eu->monitor.Density, PhysicsFunctional_Euler, phys));
9069566063dSJacob Faibussowitsch   PetscCall(ModelFunctionalRegister(mod, "Momentum", &eu->monitor.Momentum, PhysicsFunctional_Euler, phys));
9079566063dSJacob Faibussowitsch   PetscCall(ModelFunctionalRegister(mod, "Pressure", &eu->monitor.Pressure, PhysicsFunctional_Euler, phys));
908c4762a1bSJed Brown 
9093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
910c4762a1bSJed Brown }
911c4762a1bSJed Brown 
912d71ae5a4SJacob Faibussowitsch static PetscErrorCode ErrorIndicator_Simple(PetscInt dim, PetscReal volume, PetscInt numComps, const PetscScalar u[], const PetscScalar grad[], PetscReal *error, void *ctx)
913d71ae5a4SJacob Faibussowitsch {
914c4762a1bSJed Brown   PetscReal err = 0.;
915c4762a1bSJed Brown   PetscInt  i, j;
916c4762a1bSJed Brown 
917c4762a1bSJed Brown   PetscFunctionBeginUser;
918c4762a1bSJed Brown   for (i = 0; i < numComps; i++) {
919ad540459SPierre Jolivet     for (j = 0; j < dim; j++) err += PetscSqr(PetscRealPart(grad[i * dim + j]));
920c4762a1bSJed Brown   }
921c4762a1bSJed Brown   *error = volume * err;
9223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
923c4762a1bSJed Brown }
924c4762a1bSJed Brown 
925d71ae5a4SJacob Faibussowitsch PetscErrorCode CreatePartitionVec(DM dm, DM *dmCell, Vec *partition)
926d71ae5a4SJacob Faibussowitsch {
927c4762a1bSJed Brown   PetscSF      sfPoint;
928c4762a1bSJed Brown   PetscSection coordSection;
929c4762a1bSJed Brown   Vec          coordinates;
930c4762a1bSJed Brown   PetscSection sectionCell;
931c4762a1bSJed Brown   PetscScalar *part;
932c4762a1bSJed Brown   PetscInt     cStart, cEnd, c;
933c4762a1bSJed Brown   PetscMPIInt  rank;
934c4762a1bSJed Brown 
935c4762a1bSJed Brown   PetscFunctionBeginUser;
9369566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
9379566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
9389566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, dmCell));
9399566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sfPoint));
9409566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(*dmCell, sfPoint));
9419566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateSection(*dmCell, PETSC_DETERMINE, coordSection));
9429566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dmCell, coordinates));
9439566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9449566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &sectionCell));
9459566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(*dmCell, 0, &cStart, &cEnd));
9469566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(sectionCell, cStart, cEnd));
94748a46eb9SPierre Jolivet   for (c = cStart; c < cEnd; ++c) PetscCall(PetscSectionSetDof(sectionCell, c, 1));
9489566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(sectionCell));
9499566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*dmCell, sectionCell));
9509566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&sectionCell));
9519566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(*dmCell, partition));
9529566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*partition, "partition"));
9539566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*partition, &part));
954c4762a1bSJed Brown   for (c = cStart; c < cEnd; ++c) {
955c4762a1bSJed Brown     PetscScalar *p;
956c4762a1bSJed Brown 
9579566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRef(*dmCell, c, part, &p));
958c4762a1bSJed Brown     p[0] = rank;
959c4762a1bSJed Brown   }
9609566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*partition, &part));
9613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
962c4762a1bSJed Brown }
963c4762a1bSJed Brown 
964d71ae5a4SJacob Faibussowitsch PetscErrorCode CreateMassMatrix(DM dm, Vec *massMatrix, User user)
965d71ae5a4SJacob Faibussowitsch {
9663e9753d6SMatthew G. Knepley   DM                 plex, dmMass, dmFace, dmCell, dmCoord;
967c4762a1bSJed Brown   PetscSection       coordSection;
968c4762a1bSJed Brown   Vec                coordinates, facegeom, cellgeom;
969c4762a1bSJed Brown   PetscSection       sectionMass;
970c4762a1bSJed Brown   PetscScalar       *m;
971c4762a1bSJed Brown   const PetscScalar *fgeom, *cgeom, *coords;
972c4762a1bSJed Brown   PetscInt           vStart, vEnd, v;
973c4762a1bSJed Brown 
974c4762a1bSJed Brown   PetscFunctionBeginUser;
9759566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
9769566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
9779566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
9789566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmMass));
9799566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateSection(dmMass, PETSC_DETERMINE, coordSection));
9809566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmMass, coordinates));
9819566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &sectionMass));
9829566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9839566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(sectionMass, vStart, vEnd));
984c4762a1bSJed Brown   for (v = vStart; v < vEnd; ++v) {
985c4762a1bSJed Brown     PetscInt numFaces;
986c4762a1bSJed Brown 
9879566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmMass, v, &numFaces));
9889566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(sectionMass, v, numFaces * numFaces));
989c4762a1bSJed Brown   }
9909566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(sectionMass));
9919566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(dmMass, sectionMass));
9929566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&sectionMass));
9939566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmMass, massMatrix));
9949566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*massMatrix, &m));
9959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetGeometryFVM(plex, &facegeom, &cellgeom, NULL));
9969566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
9979566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &fgeom));
9989566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
9999566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cgeom));
10009566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &dmCoord));
10019566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
1002c4762a1bSJed Brown   for (v = vStart; v < vEnd; ++v) {
1003c4762a1bSJed Brown     const PetscInt  *faces;
1004c4762a1bSJed Brown     PetscFVFaceGeom *fgA, *fgB, *cg;
1005c4762a1bSJed Brown     PetscScalar     *vertex;
1006c4762a1bSJed Brown     PetscInt         numFaces, sides[2], f, g;
1007c4762a1bSJed Brown 
10089566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCoord, v, coords, &vertex));
10099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmMass, v, &numFaces));
10109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmMass, v, &faces));
1011c4762a1bSJed Brown     for (f = 0; f < numFaces; ++f) {
1012c4762a1bSJed Brown       sides[0] = faces[f];
10139566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmFace, faces[f], fgeom, &fgA));
1014c4762a1bSJed Brown       for (g = 0; g < numFaces; ++g) {
1015c4762a1bSJed Brown         const PetscInt *cells = NULL;
1016c4762a1bSJed Brown         PetscReal       area  = 0.0;
1017c4762a1bSJed Brown         PetscInt        numCells;
1018c4762a1bSJed Brown 
1019c4762a1bSJed Brown         sides[1] = faces[g];
10209566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, faces[g], fgeom, &fgB));
10219566063dSJacob Faibussowitsch         PetscCall(DMPlexGetJoin(dmMass, 2, sides, &numCells, &cells));
102254c59aa7SJacob Faibussowitsch         PetscCheck(numCells == 1, PETSC_COMM_SELF, PETSC_ERR_LIB, "Invalid join for faces");
10239566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmCell, cells[0], cgeom, &cg));
1024c4762a1bSJed Brown         area += PetscAbsScalar((vertex[0] - cg->centroid[0]) * (fgA->centroid[1] - cg->centroid[1]) - (vertex[1] - cg->centroid[1]) * (fgA->centroid[0] - cg->centroid[0]));
1025c4762a1bSJed Brown         area += PetscAbsScalar((vertex[0] - cg->centroid[0]) * (fgB->centroid[1] - cg->centroid[1]) - (vertex[1] - cg->centroid[1]) * (fgB->centroid[0] - cg->centroid[0]));
1026c4762a1bSJed Brown         m[f * numFaces + g] = Dot2Real(fgA->normal, fgB->normal) * area * 0.5;
10279566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreJoin(dmMass, 2, sides, &numCells, &cells));
1028c4762a1bSJed Brown       }
1029c4762a1bSJed Brown     }
1030c4762a1bSJed Brown   }
10319566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &fgeom));
10329566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cgeom));
10339566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
10349566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*massMatrix, &m));
10359566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmMass));
10369566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
10373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1038c4762a1bSJed Brown }
1039c4762a1bSJed Brown 
1040c4762a1bSJed Brown /* Behavior will be different for multi-physics or when using non-default boundary conditions */
1041d71ae5a4SJacob Faibussowitsch static PetscErrorCode ModelSolutionSetDefault(Model mod, SolutionFunction func, void *ctx)
1042d71ae5a4SJacob Faibussowitsch {
1043c4762a1bSJed Brown   PetscFunctionBeginUser;
1044c4762a1bSJed Brown   mod->solution    = func;
1045c4762a1bSJed Brown   mod->solutionctx = ctx;
10463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1047c4762a1bSJed Brown }
1048c4762a1bSJed Brown 
1049d71ae5a4SJacob Faibussowitsch static PetscErrorCode ModelFunctionalRegister(Model mod, const char *name, PetscInt *offset, FunctionalFunction func, void *ctx)
1050d71ae5a4SJacob Faibussowitsch {
1051c4762a1bSJed Brown   FunctionalLink link, *ptr;
1052c4762a1bSJed Brown   PetscInt       lastoffset = -1;
1053c4762a1bSJed Brown 
1054c4762a1bSJed Brown   PetscFunctionBeginUser;
1055c4762a1bSJed Brown   for (ptr = &mod->functionalRegistry; *ptr; ptr = &(*ptr)->next) lastoffset = (*ptr)->offset;
10569566063dSJacob Faibussowitsch   PetscCall(PetscNew(&link));
10579566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(name, &link->name));
1058c4762a1bSJed Brown   link->offset = lastoffset + 1;
1059c4762a1bSJed Brown   link->func   = func;
1060c4762a1bSJed Brown   link->ctx    = ctx;
1061c4762a1bSJed Brown   link->next   = NULL;
1062c4762a1bSJed Brown   *ptr         = link;
1063c4762a1bSJed Brown   *offset      = link->offset;
10643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1065c4762a1bSJed Brown }
1066c4762a1bSJed Brown 
1067d71ae5a4SJacob Faibussowitsch static PetscErrorCode ModelFunctionalSetFromOptions(Model mod, PetscOptionItems *PetscOptionsObject)
1068d71ae5a4SJacob Faibussowitsch {
1069c4762a1bSJed Brown   PetscInt       i, j;
1070c4762a1bSJed Brown   FunctionalLink link;
1071c4762a1bSJed Brown   char          *names[256];
1072c4762a1bSJed Brown 
1073c4762a1bSJed Brown   PetscFunctionBeginUser;
1074dd39110bSPierre Jolivet   mod->numMonitored = PETSC_STATIC_ARRAY_LENGTH(names);
10759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsStringArray("-monitor", "list of functionals to monitor", "", names, &mod->numMonitored, NULL));
1076c4762a1bSJed Brown   /* Create list of functionals that will be computed somehow */
10779566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(mod->numMonitored, &mod->functionalMonitored));
1078c4762a1bSJed Brown   /* Create index of calls that we will have to make to compute these functionals (over-allocation in general). */
10799566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(mod->numMonitored, &mod->functionalCall));
1080c4762a1bSJed Brown   mod->numCall = 0;
1081c4762a1bSJed Brown   for (i = 0; i < mod->numMonitored; i++) {
1082c4762a1bSJed Brown     for (link = mod->functionalRegistry; link; link = link->next) {
1083c4762a1bSJed Brown       PetscBool match;
10849566063dSJacob Faibussowitsch       PetscCall(PetscStrcasecmp(names[i], link->name, &match));
1085c4762a1bSJed Brown       if (match) break;
1086c4762a1bSJed Brown     }
108754c59aa7SJacob Faibussowitsch     PetscCheck(link, mod->comm, PETSC_ERR_USER, "No known functional '%s'", names[i]);
1088c4762a1bSJed Brown     mod->functionalMonitored[i] = link;
1089c4762a1bSJed Brown     for (j = 0; j < i; j++) {
1090c4762a1bSJed Brown       if (mod->functionalCall[j]->func == link->func && mod->functionalCall[j]->ctx == link->ctx) goto next_name;
1091c4762a1bSJed Brown     }
1092c4762a1bSJed Brown     mod->functionalCall[mod->numCall++] = link; /* Just points to the first link using the result. There may be more results. */
1093c4762a1bSJed Brown   next_name:
10949566063dSJacob Faibussowitsch     PetscCall(PetscFree(names[i]));
1095c4762a1bSJed Brown   }
1096c4762a1bSJed Brown 
1097c4762a1bSJed Brown   /* Find out the maximum index of any functional computed by a function we will be calling (even if we are not using it) */
1098c4762a1bSJed Brown   mod->maxComputed = -1;
1099c4762a1bSJed Brown   for (link = mod->functionalRegistry; link; link = link->next) {
1100c4762a1bSJed Brown     for (i = 0; i < mod->numCall; i++) {
1101c4762a1bSJed Brown       FunctionalLink call = mod->functionalCall[i];
1102ad540459SPierre Jolivet       if (link->func == call->func && link->ctx == call->ctx) mod->maxComputed = PetscMax(mod->maxComputed, link->offset);
1103c4762a1bSJed Brown     }
1104c4762a1bSJed Brown   }
11053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1106c4762a1bSJed Brown }
1107c4762a1bSJed Brown 
1108d71ae5a4SJacob Faibussowitsch static PetscErrorCode FunctionalLinkDestroy(FunctionalLink *link)
1109d71ae5a4SJacob Faibussowitsch {
1110c4762a1bSJed Brown   FunctionalLink l, next;
1111c4762a1bSJed Brown 
1112c4762a1bSJed Brown   PetscFunctionBeginUser;
11133ba16761SJacob Faibussowitsch   if (!link) PetscFunctionReturn(PETSC_SUCCESS);
1114c4762a1bSJed Brown   l     = *link;
1115c4762a1bSJed Brown   *link = NULL;
1116c4762a1bSJed Brown   for (; l; l = next) {
1117c4762a1bSJed Brown     next = l->next;
11189566063dSJacob Faibussowitsch     PetscCall(PetscFree(l->name));
11199566063dSJacob Faibussowitsch     PetscCall(PetscFree(l));
1120c4762a1bSJed Brown   }
11213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1122c4762a1bSJed Brown }
1123c4762a1bSJed Brown 
1124c4762a1bSJed Brown /* put the solution callback into a functional callback */
1125d71ae5a4SJacob Faibussowitsch static PetscErrorCode SolutionFunctional(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *modctx)
1126d71ae5a4SJacob Faibussowitsch {
1127c4762a1bSJed Brown   Model mod;
11287510d9b0SBarry Smith   PetscFunctionBeginUser;
1129c4762a1bSJed Brown   mod = (Model)modctx;
11309566063dSJacob Faibussowitsch   PetscCall((*mod->solution)(mod, time, x, u, mod->solutionctx));
11313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1132c4762a1bSJed Brown }
1133c4762a1bSJed Brown 
1134d71ae5a4SJacob Faibussowitsch PetscErrorCode SetInitialCondition(DM dm, Vec X, User user)
1135d71ae5a4SJacob Faibussowitsch {
1136c4762a1bSJed Brown   PetscErrorCode (*func[1])(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx);
1137c4762a1bSJed Brown   void *ctx[1];
1138c4762a1bSJed Brown   Model mod = user->model;
1139c4762a1bSJed Brown 
1140c4762a1bSJed Brown   PetscFunctionBeginUser;
1141c4762a1bSJed Brown   func[0] = SolutionFunctional;
1142c4762a1bSJed Brown   ctx[0]  = (void *)mod;
11439566063dSJacob Faibussowitsch   PetscCall(DMProjectFunction(dm, 0.0, func, ctx, INSERT_ALL_VALUES, X));
11443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1145c4762a1bSJed Brown }
1146c4762a1bSJed Brown 
1147d71ae5a4SJacob Faibussowitsch static PetscErrorCode OutputVTK(DM dm, const char *filename, PetscViewer *viewer)
1148d71ae5a4SJacob Faibussowitsch {
1149c4762a1bSJed Brown   PetscFunctionBeginUser;
11509566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(PetscObjectComm((PetscObject)dm), viewer));
11519566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERVTK));
11529566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(*viewer, filename));
11533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1154c4762a1bSJed Brown }
1155c4762a1bSJed Brown 
1156d71ae5a4SJacob Faibussowitsch static PetscErrorCode MonitorVTK(TS ts, PetscInt stepnum, PetscReal time, Vec X, void *ctx)
1157d71ae5a4SJacob Faibussowitsch {
1158c4762a1bSJed Brown   User        user = (User)ctx;
11593e9753d6SMatthew G. Knepley   DM          dm, plex;
1160c4762a1bSJed Brown   PetscViewer viewer;
1161c4762a1bSJed Brown   char        filename[PETSC_MAX_PATH_LEN], *ftable = NULL;
1162c4762a1bSJed Brown   PetscReal   xnorm;
1163c4762a1bSJed Brown 
1164c4762a1bSJed Brown   PetscFunctionBeginUser;
11659566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)X, "u"));
11669566063dSJacob Faibussowitsch   PetscCall(VecGetDM(X, &dm));
11679566063dSJacob Faibussowitsch   PetscCall(VecNorm(X, NORM_INFINITY, &xnorm));
1168c4762a1bSJed Brown 
1169ad540459SPierre Jolivet   if (stepnum >= 0) stepnum += user->monitorStepOffset;
1170c4762a1bSJed Brown   if (stepnum >= 0) { /* No summary for final time */
1171c4762a1bSJed Brown     Model              mod = user->model;
11723e9753d6SMatthew G. Knepley     Vec                cellgeom;
1173c4762a1bSJed Brown     PetscInt           c, cStart, cEnd, fcount, i;
1174c4762a1bSJed Brown     size_t             ftableused, ftablealloc;
1175c4762a1bSJed Brown     const PetscScalar *cgeom, *x;
1176c4762a1bSJed Brown     DM                 dmCell;
1177c4762a1bSJed Brown     DMLabel            vtkLabel;
1178c4762a1bSJed Brown     PetscReal         *fmin, *fmax, *fintegral, *ftmp;
11793e9753d6SMatthew G. Knepley 
11809566063dSJacob Faibussowitsch     PetscCall(DMConvert(dm, DMPLEX, &plex));
11819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetGeometryFVM(plex, NULL, &cellgeom, NULL));
1182c4762a1bSJed Brown     fcount = mod->maxComputed + 1;
11839566063dSJacob Faibussowitsch     PetscCall(PetscMalloc4(fcount, &fmin, fcount, &fmax, fcount, &fintegral, fcount, &ftmp));
1184c4762a1bSJed Brown     for (i = 0; i < fcount; i++) {
1185c4762a1bSJed Brown       fmin[i]      = PETSC_MAX_REAL;
1186c4762a1bSJed Brown       fmax[i]      = PETSC_MIN_REAL;
1187c4762a1bSJed Brown       fintegral[i] = 0;
1188c4762a1bSJed Brown     }
11899566063dSJacob Faibussowitsch     PetscCall(VecGetDM(cellgeom, &dmCell));
11909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSimplexOrBoxCells(dmCell, 0, &cStart, &cEnd));
11919566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(cellgeom, &cgeom));
11929566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(X, &x));
11939566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "vtk", &vtkLabel));
1194c4762a1bSJed Brown     for (c = cStart; c < cEnd; ++c) {
1195c4762a1bSJed Brown       PetscFVCellGeom   *cg;
1196c4762a1bSJed Brown       const PetscScalar *cx     = NULL;
1197c4762a1bSJed Brown       PetscInt           vtkVal = 0;
1198c4762a1bSJed Brown 
1199c4762a1bSJed Brown       /* not that these two routines as currently implemented work for any dm with a
1200c4762a1bSJed Brown        * localSection/globalSection */
12019566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, c, cgeom, &cg));
12029566063dSJacob Faibussowitsch       PetscCall(DMPlexPointGlobalRead(dm, c, x, &cx));
12039566063dSJacob Faibussowitsch       if (vtkLabel) PetscCall(DMLabelGetValue(vtkLabel, c, &vtkVal));
1204c4762a1bSJed Brown       if (!vtkVal || !cx) continue; /* ghost, or not a global cell */
1205c4762a1bSJed Brown       for (i = 0; i < mod->numCall; i++) {
1206c4762a1bSJed Brown         FunctionalLink flink = mod->functionalCall[i];
12079566063dSJacob Faibussowitsch         PetscCall((*flink->func)(mod, time, cg->centroid, cx, ftmp, flink->ctx));
1208c4762a1bSJed Brown       }
1209c4762a1bSJed Brown       for (i = 0; i < fcount; i++) {
1210c4762a1bSJed Brown         fmin[i] = PetscMin(fmin[i], ftmp[i]);
1211c4762a1bSJed Brown         fmax[i] = PetscMax(fmax[i], ftmp[i]);
1212c4762a1bSJed Brown         fintegral[i] += cg->volume * ftmp[i];
1213c4762a1bSJed Brown       }
1214c4762a1bSJed Brown     }
12159566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(cellgeom, &cgeom));
12169566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(X, &x));
12179566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&plex));
1218712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(MPI_IN_PLACE, fmin, fcount, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)ts)));
1219712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(MPI_IN_PLACE, fmax, fcount, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)ts)));
1220712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(MPI_IN_PLACE, fintegral, fcount, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)ts)));
1221c4762a1bSJed Brown 
1222c4762a1bSJed Brown     ftablealloc = fcount * 100;
1223c4762a1bSJed Brown     ftableused  = 0;
12249566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ftablealloc, &ftable));
1225c4762a1bSJed Brown     for (i = 0; i < mod->numMonitored; i++) {
1226c4762a1bSJed Brown       size_t         countused;
1227c4762a1bSJed Brown       char           buffer[256], *p;
1228c4762a1bSJed Brown       FunctionalLink flink = mod->functionalMonitored[i];
1229c4762a1bSJed Brown       PetscInt       id    = flink->offset;
1230c4762a1bSJed Brown       if (i % 3) {
12319566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(buffer, "  ", 2));
1232c4762a1bSJed Brown         p = buffer + 2;
1233c4762a1bSJed Brown       } else if (i) {
1234c4762a1bSJed Brown         char newline[] = "\n";
12359566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(buffer, newline, sizeof(newline) - 1));
1236c4762a1bSJed Brown         p = buffer + sizeof(newline) - 1;
1237c4762a1bSJed Brown       } else {
1238c4762a1bSJed Brown         p = buffer;
1239c4762a1bSJed Brown       }
12409566063dSJacob Faibussowitsch       PetscCall(PetscSNPrintfCount(p, sizeof buffer - (p - buffer), "%12s [%10.7g,%10.7g] int %10.7g", &countused, flink->name, (double)fmin[id], (double)fmax[id], (double)fintegral[id]));
1241c4762a1bSJed Brown       countused--;
1242c4762a1bSJed Brown       countused += p - buffer;
1243c4762a1bSJed Brown       if (countused > ftablealloc - ftableused - 1) { /* reallocate */
1244c4762a1bSJed Brown         char *ftablenew;
1245c4762a1bSJed Brown         ftablealloc = 2 * ftablealloc + countused;
12469566063dSJacob Faibussowitsch         PetscCall(PetscMalloc(ftablealloc, &ftablenew));
12479566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(ftablenew, ftable, ftableused));
12489566063dSJacob Faibussowitsch         PetscCall(PetscFree(ftable));
1249c4762a1bSJed Brown         ftable = ftablenew;
1250c4762a1bSJed Brown       }
12519566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(ftable + ftableused, buffer, countused));
1252c4762a1bSJed Brown       ftableused += countused;
1253c4762a1bSJed Brown       ftable[ftableused] = 0;
1254c4762a1bSJed Brown     }
12559566063dSJacob Faibussowitsch     PetscCall(PetscFree4(fmin, fmax, fintegral, ftmp));
1256c4762a1bSJed Brown 
125763a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)ts), "% 3" PetscInt_FMT "  time %8.4g  |x| %8.4g  %s\n", stepnum, (double)time, (double)xnorm, ftable ? ftable : ""));
12589566063dSJacob Faibussowitsch     PetscCall(PetscFree(ftable));
1259c4762a1bSJed Brown   }
12603ba16761SJacob Faibussowitsch   if (user->vtkInterval < 1) PetscFunctionReturn(PETSC_SUCCESS);
1261c4762a1bSJed Brown   if ((stepnum == -1) ^ (stepnum % user->vtkInterval == 0)) {
1262c4762a1bSJed Brown     if (stepnum == -1) { /* Final time is not multiple of normal time interval, write it anyway */
12639566063dSJacob Faibussowitsch       PetscCall(TSGetStepNumber(ts, &stepnum));
1264c4762a1bSJed Brown     }
126563a3b9bcSJacob Faibussowitsch     PetscCall(PetscSNPrintf(filename, sizeof filename, "%s-%03" PetscInt_FMT ".vtu", user->outputBasename, stepnum));
12669566063dSJacob Faibussowitsch     PetscCall(OutputVTK(dm, filename, &viewer));
12679566063dSJacob Faibussowitsch     PetscCall(VecView(X, viewer));
12689566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
1269c4762a1bSJed Brown   }
12703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1271c4762a1bSJed Brown }
1272c4762a1bSJed Brown 
1273d71ae5a4SJacob Faibussowitsch static PetscErrorCode initializeTS(DM dm, User user, TS *ts)
1274d71ae5a4SJacob Faibussowitsch {
12757510d9b0SBarry Smith   PetscFunctionBeginUser;
12769566063dSJacob Faibussowitsch   PetscCall(TSCreate(PetscObjectComm((PetscObject)dm), ts));
12779566063dSJacob Faibussowitsch   PetscCall(TSSetType(*ts, TSSSP));
12789566063dSJacob Faibussowitsch   PetscCall(TSSetDM(*ts, dm));
12791baa6e33SBarry Smith   if (user->vtkmon) PetscCall(TSMonitorSet(*ts, MonitorVTK, user, NULL));
12809566063dSJacob Faibussowitsch   PetscCall(DMTSSetBoundaryLocal(dm, DMPlexTSComputeBoundary, user));
12819566063dSJacob Faibussowitsch   PetscCall(DMTSSetRHSFunctionLocal(dm, DMPlexTSComputeRHSFunctionFVM, user));
12829566063dSJacob Faibussowitsch   PetscCall(TSSetMaxTime(*ts, 2.0));
12839566063dSJacob Faibussowitsch   PetscCall(TSSetExactFinalTime(*ts, TS_EXACTFINALTIME_STEPOVER));
12843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1285c4762a1bSJed Brown }
1286c4762a1bSJed Brown 
128752115386SStefano Zampini typedef struct {
128852115386SStefano Zampini   PetscFV      fvm;
128952115386SStefano Zampini   VecTagger    refineTag;
129052115386SStefano Zampini   VecTagger    coarsenTag;
129152115386SStefano Zampini   DM           adaptedDM;
129252115386SStefano Zampini   User         user;
129352115386SStefano Zampini   PetscReal    cfl;
129452115386SStefano Zampini   PetscLimiter limiter;
129552115386SStefano Zampini   PetscLimiter noneLimiter;
129652115386SStefano Zampini } TransferCtx;
129752115386SStefano Zampini 
129852115386SStefano Zampini static PetscErrorCode adaptToleranceFVMSetUp(TS ts, PetscInt nstep, PetscReal time, Vec sol, PetscBool *resize, void *ctx)
1299d71ae5a4SJacob Faibussowitsch {
130052115386SStefano Zampini   TransferCtx       *tctx       = (TransferCtx *)ctx;
130152115386SStefano Zampini   PetscFV            fvm        = tctx->fvm;
130252115386SStefano Zampini   VecTagger          refineTag  = tctx->refineTag;
130352115386SStefano Zampini   VecTagger          coarsenTag = tctx->coarsenTag;
130452115386SStefano Zampini   User               user       = tctx->user;
1305c4762a1bSJed Brown   DM                 dm, gradDM, plex, cellDM, adaptedDM = NULL;
1306c4762a1bSJed Brown   Vec                cellGeom, faceGeom;
1307c4762a1bSJed Brown   PetscBool          isForest, computeGradient;
1308c4762a1bSJed Brown   Vec                grad, locGrad, locX, errVec;
1309c4762a1bSJed Brown   PetscInt           cStart, cEnd, c, dim, nRefine, nCoarsen;
131052115386SStefano Zampini   PetscReal          minMaxInd[2] = {PETSC_MAX_REAL, PETSC_MIN_REAL}, minMaxIndGlobal[2];
1311c4762a1bSJed Brown   PetscScalar       *errArray;
1312c4762a1bSJed Brown   const PetscScalar *pointVals;
1313c4762a1bSJed Brown   const PetscScalar *pointGrads;
1314c4762a1bSJed Brown   const PetscScalar *pointGeom;
1315c4762a1bSJed Brown   DMLabel            adaptLabel = NULL;
1316c4762a1bSJed Brown   IS                 refineIS, coarsenIS;
1317c4762a1bSJed Brown 
13187510d9b0SBarry Smith   PetscFunctionBeginUser;
131952115386SStefano Zampini   *resize = PETSC_FALSE;
13209566063dSJacob Faibussowitsch   PetscCall(VecGetDM(sol, &dm));
13219566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
132252115386SStefano Zampini   PetscCall(PetscFVSetLimiter(fvm, tctx->noneLimiter));
13239566063dSJacob Faibussowitsch   PetscCall(PetscFVGetComputeGradients(fvm, &computeGradient));
13249566063dSJacob Faibussowitsch   PetscCall(PetscFVSetComputeGradients(fvm, PETSC_TRUE));
13259566063dSJacob Faibussowitsch   PetscCall(DMIsForest(dm, &isForest));
13269566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
13279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(plex, fvm, &cellGeom, &faceGeom, &gradDM));
13289566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(plex, &locX));
13299566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(plex, PETSC_TRUE, locX, 0.0, faceGeom, cellGeom, NULL));
13309566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(plex, sol, INSERT_VALUES, locX));
13319566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(plex, sol, INSERT_VALUES, locX));
13329566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(gradDM, &grad));
13339566063dSJacob Faibussowitsch   PetscCall(DMPlexReconstructGradientsFVM(plex, locX, grad));
13349566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(gradDM, &locGrad));
13359566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(gradDM, grad, INSERT_VALUES, locGrad));
13369566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(gradDM, grad, INSERT_VALUES, locGrad));
13379566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&grad));
13389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(plex, 0, &cStart, &cEnd));
13399566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(locGrad, &pointGrads));
13409566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellGeom, &pointGeom));
13419566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(locX, &pointVals));
13429566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellGeom, &cellDM));
13439566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PETSC_COMM_SELF, "adapt", &adaptLabel));
134477433607SBarry Smith   PetscCall(VecCreateFromOptions(PetscObjectComm((PetscObject)plex), NULL, 1, cEnd - cStart, PETSC_DETERMINE, &errVec));
13459566063dSJacob Faibussowitsch   PetscCall(VecSetUp(errVec));
13469566063dSJacob Faibussowitsch   PetscCall(VecGetArray(errVec, &errArray));
1347c4762a1bSJed Brown   for (c = cStart; c < cEnd; c++) {
1348c4762a1bSJed Brown     PetscReal        errInd = 0.;
1349c4762a1bSJed Brown     PetscScalar     *pointGrad;
1350c4762a1bSJed Brown     PetscScalar     *pointVal;
1351c4762a1bSJed Brown     PetscFVCellGeom *cg;
1352c4762a1bSJed Brown 
13539566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(gradDM, c, pointGrads, &pointGrad));
13549566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(cellDM, c, pointGeom, &cg));
13559566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(plex, c, pointVals, &pointVal));
1356c4762a1bSJed Brown 
13579566063dSJacob Faibussowitsch     PetscCall((user->model->errorIndicator)(dim, cg->volume, user->model->physics->dof, pointVal, pointGrad, &errInd, user->model->errorCtx));
1358c4762a1bSJed Brown     errArray[c - cStart] = errInd;
1359c4762a1bSJed Brown     minMaxInd[0]         = PetscMin(minMaxInd[0], errInd);
1360c4762a1bSJed Brown     minMaxInd[1]         = PetscMax(minMaxInd[1], errInd);
1361c4762a1bSJed Brown   }
13629566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(errVec, &errArray));
13639566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(locX, &pointVals));
13649566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellGeom, &pointGeom));
13659566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(locGrad, &pointGrads));
13669566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&locGrad));
13679566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&locX));
13689566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
1369c4762a1bSJed Brown 
13709566063dSJacob Faibussowitsch   PetscCall(VecTaggerComputeIS(refineTag, errVec, &refineIS, NULL));
13719566063dSJacob Faibussowitsch   PetscCall(VecTaggerComputeIS(coarsenTag, errVec, &coarsenIS, NULL));
13729566063dSJacob Faibussowitsch   PetscCall(ISGetSize(refineIS, &nRefine));
13739566063dSJacob Faibussowitsch   PetscCall(ISGetSize(coarsenIS, &nCoarsen));
13749566063dSJacob Faibussowitsch   if (nRefine) PetscCall(DMLabelSetStratumIS(adaptLabel, DM_ADAPT_REFINE, refineIS));
13759566063dSJacob Faibussowitsch   if (nCoarsen) PetscCall(DMLabelSetStratumIS(adaptLabel, DM_ADAPT_COARSEN, coarsenIS));
13769566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&coarsenIS));
13779566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&refineIS));
13789566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&errVec));
1379c4762a1bSJed Brown 
13809566063dSJacob Faibussowitsch   PetscCall(PetscFVSetComputeGradients(fvm, computeGradient));
138152115386SStefano Zampini   PetscCall(PetscFVSetLimiter(fvm, tctx->limiter));
1382c4762a1bSJed Brown   minMaxInd[1] = -minMaxInd[1];
1383712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(minMaxInd, minMaxIndGlobal, 2, MPIU_REAL, MPI_MIN, PetscObjectComm((PetscObject)dm)));
138452115386SStefano Zampini   PetscCall(PetscInfo(ts, "error indicator range (%E, %E)\n", (double)minMaxIndGlobal[0], (double)(-minMaxIndGlobal[1])));
1385c4762a1bSJed Brown   if (nRefine || nCoarsen) { /* at least one cell is over the refinement threshold */
13869566063dSJacob Faibussowitsch     PetscCall(DMAdaptLabel(dm, adaptLabel, &adaptedDM));
1387c4762a1bSJed Brown   }
13889566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&adaptLabel));
1389c4762a1bSJed Brown   if (adaptedDM) {
139052115386SStefano Zampini     tctx->adaptedDM = adaptedDM;
139152115386SStefano Zampini     PetscCall(PetscInfo(ts, "Step %" PetscInt_FMT " adapted mesh, marking %" PetscInt_FMT " cells for refinement, and %" PetscInt_FMT " cells for coarsening\n", nstep, nRefine, nCoarsen));
139252115386SStefano Zampini     *resize = PETSC_TRUE;
1393c4762a1bSJed Brown   } else {
139452115386SStefano Zampini     PetscCall(PetscInfo(ts, "Step %" PetscInt_FMT " no adaptation\n", nstep));
1395c4762a1bSJed Brown   }
13963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1397c4762a1bSJed Brown }
1398c4762a1bSJed Brown 
139952115386SStefano Zampini static PetscErrorCode Transfer(TS ts, PetscInt nv, Vec vecsin[], Vec vecsout[], void *ctx)
140052115386SStefano Zampini {
140152115386SStefano Zampini   TransferCtx *tctx = (TransferCtx *)ctx;
140252115386SStefano Zampini   DM           dm;
140352115386SStefano Zampini   PetscReal    time;
140452115386SStefano Zampini 
140552115386SStefano Zampini   PetscFunctionBeginUser;
140652115386SStefano Zampini   PetscCall(TSGetDM(ts, &dm));
140752115386SStefano Zampini   PetscCall(TSGetTime(ts, &time));
140852115386SStefano Zampini   PetscCheck(tctx->adaptedDM, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "Missing adaptedDM");
140952115386SStefano Zampini   for (PetscInt i = 0; i < nv; i++) {
141052115386SStefano Zampini     const char *name;
141152115386SStefano Zampini 
141252115386SStefano Zampini     PetscCall(DMCreateGlobalVector(tctx->adaptedDM, &vecsout[i]));
141352115386SStefano Zampini     PetscCall(DMForestTransferVec(dm, vecsin[i], tctx->adaptedDM, vecsout[i], PETSC_TRUE, time));
141452115386SStefano Zampini     PetscCall(PetscObjectGetName((PetscObject)vecsin[i], &name));
141552115386SStefano Zampini     PetscCall(PetscObjectSetName((PetscObject)vecsout[i], name));
141652115386SStefano Zampini   }
141752115386SStefano Zampini   PetscCall(DMForestSetAdaptivityForest(tctx->adaptedDM, NULL)); /* clear internal references to the previous dm */
141852115386SStefano Zampini 
141952115386SStefano Zampini   Model     mod  = tctx->user->model;
142052115386SStefano Zampini   Physics   phys = mod->physics;
142152115386SStefano Zampini   PetscReal minRadius;
142252115386SStefano Zampini 
142352115386SStefano Zampini   PetscCall(DMPlexGetGeometryFVM(tctx->adaptedDM, NULL, NULL, &minRadius));
142452115386SStefano Zampini   PetscCall(MPIU_Allreduce(&phys->maxspeed, &mod->maxspeed, 1, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)ts)));
142552115386SStefano Zampini   PetscCheck(mod->maxspeed > 0, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "Physics did not set maxspeed");
142652115386SStefano Zampini 
142752115386SStefano Zampini   PetscReal dt = tctx->cfl * minRadius / mod->maxspeed;
142852115386SStefano Zampini   PetscCall(TSSetTimeStep(ts, dt));
142952115386SStefano Zampini 
143052115386SStefano Zampini   PetscCall(TSSetDM(ts, tctx->adaptedDM));
143152115386SStefano Zampini   PetscCall(DMDestroy(&tctx->adaptedDM));
143252115386SStefano Zampini 
143352115386SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
143452115386SStefano Zampini }
143552115386SStefano Zampini 
1436d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
1437d71ae5a4SJacob Faibussowitsch {
1438c4762a1bSJed Brown   MPI_Comm          comm;
1439c4762a1bSJed Brown   PetscDS           prob;
1440c4762a1bSJed Brown   PetscFV           fvm;
1441c4762a1bSJed Brown   PetscLimiter      limiter = NULL, noneLimiter = NULL;
1442c4762a1bSJed Brown   User              user;
1443c4762a1bSJed Brown   Model             mod;
1444c4762a1bSJed Brown   Physics           phys;
14453e9753d6SMatthew G. Knepley   DM                dm, plex;
1446c4762a1bSJed Brown   PetscReal         ftime, cfl, dt, minRadius;
1447c4762a1bSJed Brown   PetscInt          dim, nsteps;
1448c4762a1bSJed Brown   TS                ts;
1449c4762a1bSJed Brown   TSConvergedReason reason;
1450c4762a1bSJed Brown   Vec               X;
1451c4762a1bSJed Brown   PetscViewer       viewer;
1452b5a892a1SMatthew G. Knepley   PetscBool         vtkCellGeom, useAMR;
145330602db0SMatthew G. Knepley   PetscInt          adaptInterval;
1454c4762a1bSJed Brown   char              physname[256] = "advect";
1455c4762a1bSJed Brown   VecTagger         refineTag = NULL, coarsenTag = NULL;
145652115386SStefano Zampini   TransferCtx       tctx;
1457c4762a1bSJed Brown 
1458327415f7SBarry Smith   PetscFunctionBeginUser;
14599566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, (char *)0, help));
1460c4762a1bSJed Brown   comm = PETSC_COMM_WORLD;
1461c4762a1bSJed Brown 
14629566063dSJacob Faibussowitsch   PetscCall(PetscNew(&user));
14639566063dSJacob Faibussowitsch   PetscCall(PetscNew(&user->model));
14649566063dSJacob Faibussowitsch   PetscCall(PetscNew(&user->model->physics));
1465c4762a1bSJed Brown   mod           = user->model;
1466c4762a1bSJed Brown   phys          = mod->physics;
1467c4762a1bSJed Brown   mod->comm     = comm;
1468c4762a1bSJed Brown   useAMR        = PETSC_FALSE;
1469c4762a1bSJed Brown   adaptInterval = 1;
1470c4762a1bSJed Brown 
1471c4762a1bSJed Brown   /* Register physical models to be available on the command line */
14729566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&PhysicsList, "advect", PhysicsCreate_Advect));
14739566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&PhysicsList, "sw", PhysicsCreate_SW));
14749566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&PhysicsList, "euler", PhysicsCreate_Euler));
1475c4762a1bSJed Brown 
1476d0609cedSBarry Smith   PetscOptionsBegin(comm, NULL, "Unstructured Finite Volume Mesh Options", "");
1477c4762a1bSJed Brown   {
1478c4762a1bSJed Brown     cfl = 0.9 * 4; /* default SSPRKS2 with s=5 stages is stable for CFL number s-1 */
14799566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-ufv_cfl", "CFL number per step", "", cfl, &cfl, NULL));
1480c4762a1bSJed Brown     user->vtkInterval = 1;
14819566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-ufv_vtk_interval", "VTK output interval (0 to disable)", "", user->vtkInterval, &user->vtkInterval, NULL));
1482c4762a1bSJed Brown     user->vtkmon = PETSC_TRUE;
14839566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-ufv_vtk_monitor", "Use VTKMonitor routine", "", user->vtkmon, &user->vtkmon, NULL));
1484c4762a1bSJed Brown     vtkCellGeom = PETSC_FALSE;
1485c6a7a370SJeremy L Thompson     PetscCall(PetscStrncpy(user->outputBasename, "ex11", sizeof(user->outputBasename)));
14869566063dSJacob Faibussowitsch     PetscCall(PetscOptionsString("-ufv_vtk_basename", "VTK output basename", "", user->outputBasename, user->outputBasename, sizeof(user->outputBasename), NULL));
14879566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-ufv_vtk_cellgeom", "Write cell geometry (for debugging)", "", vtkCellGeom, &vtkCellGeom, NULL));
14889566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-ufv_use_amr", "use local adaptive mesh refinement", "", useAMR, &useAMR, NULL));
14899566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-ufv_adapt_interval", "time steps between AMR", "", adaptInterval, &adaptInterval, NULL));
1490c4762a1bSJed Brown   }
1491d0609cedSBarry Smith   PetscOptionsEnd();
1492c4762a1bSJed Brown 
1493c4762a1bSJed Brown   if (useAMR) {
1494c4762a1bSJed Brown     VecTaggerBox refineBox, coarsenBox;
1495c4762a1bSJed Brown 
1496c4762a1bSJed Brown     refineBox.min = refineBox.max = PETSC_MAX_REAL;
1497c4762a1bSJed Brown     coarsenBox.min = coarsenBox.max = PETSC_MIN_REAL;
1498c4762a1bSJed Brown 
14999566063dSJacob Faibussowitsch     PetscCall(VecTaggerCreate(comm, &refineTag));
15009566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)refineTag, "refine_"));
15019566063dSJacob Faibussowitsch     PetscCall(VecTaggerSetType(refineTag, VECTAGGERABSOLUTE));
15029566063dSJacob Faibussowitsch     PetscCall(VecTaggerAbsoluteSetBox(refineTag, &refineBox));
15039566063dSJacob Faibussowitsch     PetscCall(VecTaggerSetFromOptions(refineTag));
15049566063dSJacob Faibussowitsch     PetscCall(VecTaggerSetUp(refineTag));
15059566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)refineTag, NULL, "-tag_view"));
1506c4762a1bSJed Brown 
15079566063dSJacob Faibussowitsch     PetscCall(VecTaggerCreate(comm, &coarsenTag));
15089566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)coarsenTag, "coarsen_"));
15099566063dSJacob Faibussowitsch     PetscCall(VecTaggerSetType(coarsenTag, VECTAGGERABSOLUTE));
15109566063dSJacob Faibussowitsch     PetscCall(VecTaggerAbsoluteSetBox(coarsenTag, &coarsenBox));
15119566063dSJacob Faibussowitsch     PetscCall(VecTaggerSetFromOptions(coarsenTag));
15129566063dSJacob Faibussowitsch     PetscCall(VecTaggerSetUp(coarsenTag));
15139566063dSJacob Faibussowitsch     PetscCall(PetscObjectViewFromOptions((PetscObject)coarsenTag, NULL, "-tag_view"));
1514c4762a1bSJed Brown   }
1515c4762a1bSJed Brown 
1516d0609cedSBarry Smith   PetscOptionsBegin(comm, NULL, "Unstructured Finite Volume Physics Options", "");
1517c4762a1bSJed Brown   {
1518c4762a1bSJed Brown     PetscErrorCode (*physcreate)(Model, Physics, PetscOptionItems *);
15199566063dSJacob Faibussowitsch     PetscCall(PetscOptionsFList("-physics", "Physics module to solve", "", PhysicsList, physname, physname, sizeof physname, NULL));
15209566063dSJacob Faibussowitsch     PetscCall(PetscFunctionListFind(PhysicsList, physname, &physcreate));
15219566063dSJacob Faibussowitsch     PetscCall(PetscMemzero(phys, sizeof(struct _n_Physics)));
15229566063dSJacob Faibussowitsch     PetscCall((*physcreate)(mod, phys, PetscOptionsObject));
1523c4762a1bSJed Brown     /* Count number of fields and dofs */
1524c4762a1bSJed Brown     for (phys->nfields = 0, phys->dof = 0; phys->field_desc[phys->nfields].name; phys->nfields++) phys->dof += phys->field_desc[phys->nfields].dof;
152554c59aa7SJacob Faibussowitsch     PetscCheck(phys->dof > 0, comm, PETSC_ERR_ARG_WRONGSTATE, "Physics '%s' did not set dof", physname);
15269566063dSJacob Faibussowitsch     PetscCall(ModelFunctionalSetFromOptions(mod, PetscOptionsObject));
1527c4762a1bSJed Brown   }
1528d0609cedSBarry Smith   PetscOptionsEnd();
1529c4762a1bSJed Brown 
1530c4762a1bSJed Brown   /* Create mesh */
1531c4762a1bSJed Brown   {
153230602db0SMatthew G. Knepley     PetscInt i;
153330602db0SMatthew G. Knepley 
15349566063dSJacob Faibussowitsch     PetscCall(DMCreate(comm, &dm));
15359566063dSJacob Faibussowitsch     PetscCall(DMSetType(dm, DMPLEX));
15369566063dSJacob Faibussowitsch     PetscCall(DMSetFromOptions(dm));
15379371c9d4SSatish Balay     for (i = 0; i < DIM; i++) {
15389371c9d4SSatish Balay       mod->bounds[2 * i]     = 0.;
15399371c9d4SSatish Balay       mod->bounds[2 * i + 1] = 1.;
15409371c9d4SSatish Balay     };
1541c4762a1bSJed Brown     dim = DIM;
154230602db0SMatthew G. Knepley     { /* a null name means just do a hex box */
154330602db0SMatthew G. Knepley       PetscInt  cells[3] = {1, 1, 1}, n = 3;
154430602db0SMatthew G. Knepley       PetscBool flg2, skew              = PETSC_FALSE;
1545c4762a1bSJed Brown       PetscInt  nret2 = 2 * DIM;
1546d0609cedSBarry Smith       PetscOptionsBegin(comm, NULL, "Rectangular mesh options", "");
15479566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-grid_bounds", "bounds of the mesh in each direction (i.e., x_min,x_max,y_min,y_max", "", mod->bounds, &nret2, &flg2));
15489566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-grid_skew_60", "Skew grid for 60 degree shock mesh", "", skew, &skew, NULL));
15499566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", cells, &n, NULL));
1550d0609cedSBarry Smith       PetscOptionsEnd();
155130602db0SMatthew G. Knepley       /* TODO Rewrite this with Mark, and remove grid_bounds at that time */
1552c4762a1bSJed Brown       if (flg2) {
1553c4762a1bSJed Brown         PetscInt     dimEmbed, i;
1554c4762a1bSJed Brown         PetscInt     nCoords;
1555c4762a1bSJed Brown         PetscScalar *coords;
1556c4762a1bSJed Brown         Vec          coordinates;
1557c4762a1bSJed Brown 
15589566063dSJacob Faibussowitsch         PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
15599566063dSJacob Faibussowitsch         PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
15609566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(coordinates, &nCoords));
156154c59aa7SJacob Faibussowitsch         PetscCheck(!(nCoords % dimEmbed), PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Coordinate vector the wrong size");
15629566063dSJacob Faibussowitsch         PetscCall(VecGetArray(coordinates, &coords));
1563c4762a1bSJed Brown         for (i = 0; i < nCoords; i += dimEmbed) {
1564c4762a1bSJed Brown           PetscInt j;
1565c4762a1bSJed Brown 
1566c4762a1bSJed Brown           PetscScalar *coord = &coords[i];
1567c4762a1bSJed Brown           for (j = 0; j < dimEmbed; j++) {
1568c4762a1bSJed Brown             coord[j] = mod->bounds[2 * j] + coord[j] * (mod->bounds[2 * j + 1] - mod->bounds[2 * j]);
1569c4762a1bSJed Brown             if (dim == 2 && cells[1] == 1 && j == 0 && skew) {
1570c4762a1bSJed Brown               if (cells[0] == 2 && i == 8) {
1571c4762a1bSJed Brown                 coord[j] = .57735026918963; /* hack to get 60 deg skewed mesh */
157230602db0SMatthew G. Knepley               } else if (cells[0] == 3) {
1573c4762a1bSJed Brown                 if (i == 2 || i == 10) coord[j] = mod->bounds[1] / 4.;
1574c4762a1bSJed Brown                 else if (i == 4) coord[j] = mod->bounds[1] / 2.;
1575c4762a1bSJed Brown                 else if (i == 12) coord[j] = 1.57735026918963 * mod->bounds[1] / 2.;
1576c4762a1bSJed Brown               }
1577c4762a1bSJed Brown             }
1578c4762a1bSJed Brown           }
1579c4762a1bSJed Brown         }
15809566063dSJacob Faibussowitsch         PetscCall(VecRestoreArray(coordinates, &coords));
15819566063dSJacob Faibussowitsch         PetscCall(DMSetCoordinatesLocal(dm, coordinates));
1582c4762a1bSJed Brown       }
1583c4762a1bSJed Brown     }
1584c4762a1bSJed Brown   }
15859566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-orig_dm_view"));
15869566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
1587c4762a1bSJed Brown 
1588c4762a1bSJed Brown   /* set up BCs, functions, tags */
15899566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
1590c4762a1bSJed Brown   mod->errorIndicator = ErrorIndicator_Simple;
1591c4762a1bSJed Brown 
1592c4762a1bSJed Brown   {
1593c4762a1bSJed Brown     DM gdm;
1594c4762a1bSJed Brown 
15959566063dSJacob Faibussowitsch     PetscCall(DMPlexConstructGhostCells(dm, NULL, NULL, &gdm));
15969566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dm));
1597c4762a1bSJed Brown     dm = gdm;
15989566063dSJacob Faibussowitsch     PetscCall(DMViewFromOptions(dm, NULL, "-dm_view"));
1599c4762a1bSJed Brown   }
1600c4762a1bSJed Brown 
16019566063dSJacob Faibussowitsch   PetscCall(PetscFVCreate(comm, &fvm));
16029566063dSJacob Faibussowitsch   PetscCall(PetscFVSetFromOptions(fvm));
16039566063dSJacob Faibussowitsch   PetscCall(PetscFVSetNumComponents(fvm, phys->dof));
16049566063dSJacob Faibussowitsch   PetscCall(PetscFVSetSpatialDimension(fvm, dim));
16059566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fvm, ""));
1606c4762a1bSJed Brown   {
1607c4762a1bSJed Brown     PetscInt f, dof;
1608c4762a1bSJed Brown     for (f = 0, dof = 0; f < phys->nfields; f++) {
1609c4762a1bSJed Brown       PetscInt newDof = phys->field_desc[f].dof;
1610c4762a1bSJed Brown 
1611c4762a1bSJed Brown       if (newDof == 1) {
16129566063dSJacob Faibussowitsch         PetscCall(PetscFVSetComponentName(fvm, dof, phys->field_desc[f].name));
16139371c9d4SSatish Balay       } else {
1614c4762a1bSJed Brown         PetscInt j;
1615c4762a1bSJed Brown 
1616c4762a1bSJed Brown         for (j = 0; j < newDof; j++) {
1617c4762a1bSJed Brown           char compName[256] = "Unknown";
1618c4762a1bSJed Brown 
161963a3b9bcSJacob Faibussowitsch           PetscCall(PetscSNPrintf(compName, sizeof(compName), "%s_%" PetscInt_FMT, phys->field_desc[f].name, j));
16209566063dSJacob Faibussowitsch           PetscCall(PetscFVSetComponentName(fvm, dof + j, compName));
1621c4762a1bSJed Brown         }
1622c4762a1bSJed Brown       }
1623c4762a1bSJed Brown       dof += newDof;
1624c4762a1bSJed Brown     }
1625c4762a1bSJed Brown   }
1626c4762a1bSJed Brown   /* FV is now structured with one field having all physics as components */
16279566063dSJacob Faibussowitsch   PetscCall(DMAddField(dm, NULL, (PetscObject)fvm));
16289566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(dm));
16299566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
16309566063dSJacob Faibussowitsch   PetscCall(PetscDSSetRiemannSolver(prob, 0, user->model->physics->riemann));
16319566063dSJacob Faibussowitsch   PetscCall(PetscDSSetContext(prob, 0, user->model->physics));
16329566063dSJacob Faibussowitsch   PetscCall((*mod->setupbc)(dm, prob, phys));
16339566063dSJacob Faibussowitsch   PetscCall(PetscDSSetFromOptions(prob));
1634c4762a1bSJed Brown   {
1635c4762a1bSJed Brown     char      convType[256];
1636c4762a1bSJed Brown     PetscBool flg;
1637c4762a1bSJed Brown 
1638d0609cedSBarry Smith     PetscOptionsBegin(comm, "", "Mesh conversion options", "DMPLEX");
16399566063dSJacob Faibussowitsch     PetscCall(PetscOptionsFList("-dm_type", "Convert DMPlex to another format", "ex12", DMList, DMPLEX, convType, 256, &flg));
1640d0609cedSBarry Smith     PetscOptionsEnd();
1641c4762a1bSJed Brown     if (flg) {
1642c4762a1bSJed Brown       DM dmConv;
1643c4762a1bSJed Brown 
16449566063dSJacob Faibussowitsch       PetscCall(DMConvert(dm, convType, &dmConv));
1645c4762a1bSJed Brown       if (dmConv) {
16469566063dSJacob Faibussowitsch         PetscCall(DMViewFromOptions(dmConv, NULL, "-dm_conv_view"));
16479566063dSJacob Faibussowitsch         PetscCall(DMDestroy(&dm));
1648c4762a1bSJed Brown         dm = dmConv;
16499566063dSJacob Faibussowitsch         PetscCall(DMSetFromOptions(dm));
1650c4762a1bSJed Brown       }
1651c4762a1bSJed Brown     }
1652c4762a1bSJed Brown   }
1653c4762a1bSJed Brown 
16549566063dSJacob Faibussowitsch   PetscCall(initializeTS(dm, user, &ts));
1655c4762a1bSJed Brown 
16569566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dm, &X));
16579566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)X, "solution"));
16589566063dSJacob Faibussowitsch   PetscCall(SetInitialCondition(dm, X, user));
1659c4762a1bSJed Brown   if (useAMR) {
1660c4762a1bSJed Brown     PetscInt adaptIter;
1661c4762a1bSJed Brown 
1662c4762a1bSJed Brown     /* use no limiting when reconstructing gradients for adaptivity */
16639566063dSJacob Faibussowitsch     PetscCall(PetscFVGetLimiter(fvm, &limiter));
16649566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)limiter));
16659566063dSJacob Faibussowitsch     PetscCall(PetscLimiterCreate(PetscObjectComm((PetscObject)fvm), &noneLimiter));
16669566063dSJacob Faibussowitsch     PetscCall(PetscLimiterSetType(noneLimiter, PETSCLIMITERNONE));
1667c4762a1bSJed Brown 
166852115386SStefano Zampini     /* Refinement context */
166952115386SStefano Zampini     tctx.fvm         = fvm;
167052115386SStefano Zampini     tctx.refineTag   = refineTag;
167152115386SStefano Zampini     tctx.coarsenTag  = coarsenTag;
167252115386SStefano Zampini     tctx.adaptedDM   = NULL;
167352115386SStefano Zampini     tctx.user        = user;
167452115386SStefano Zampini     tctx.noneLimiter = noneLimiter;
167552115386SStefano Zampini     tctx.limiter     = limiter;
167652115386SStefano Zampini     tctx.cfl         = cfl;
167752115386SStefano Zampini 
167852115386SStefano Zampini     /* Do some initial refinement steps */
1679c4762a1bSJed Brown     for (adaptIter = 0;; ++adaptIter) {
1680c4762a1bSJed Brown       PetscLogDouble bytes;
168152115386SStefano Zampini       PetscBool      resize;
1682c4762a1bSJed Brown 
16839566063dSJacob Faibussowitsch       PetscCall(PetscMemoryGetCurrentUsage(&bytes));
168463a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(ts, "refinement loop %" PetscInt_FMT ": memory used %g\n", adaptIter, (double)bytes));
16859566063dSJacob Faibussowitsch       PetscCall(DMViewFromOptions(dm, NULL, "-initial_dm_view"));
16869566063dSJacob Faibussowitsch       PetscCall(VecViewFromOptions(X, NULL, "-initial_vec_view"));
1687c4762a1bSJed Brown 
168852115386SStefano Zampini       PetscCall(adaptToleranceFVMSetUp(ts, -1, 0.0, X, &resize, &tctx));
168952115386SStefano Zampini       if (!resize) break;
16909566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dm));
16919566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&X));
169252115386SStefano Zampini       dm             = tctx.adaptedDM;
169352115386SStefano Zampini       tctx.adaptedDM = NULL;
169452115386SStefano Zampini       PetscCall(TSSetDM(ts, dm));
16959566063dSJacob Faibussowitsch       PetscCall(DMCreateGlobalVector(dm, &X));
16969566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)X, "solution"));
16979566063dSJacob Faibussowitsch       PetscCall(SetInitialCondition(dm, X, user));
1698c4762a1bSJed Brown     }
1699c4762a1bSJed Brown   }
1700c4762a1bSJed Brown 
17019566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
1702c4762a1bSJed Brown   if (vtkCellGeom) {
1703c4762a1bSJed Brown     DM  dmCell;
1704c4762a1bSJed Brown     Vec cellgeom, partition;
1705c4762a1bSJed Brown 
17069566063dSJacob Faibussowitsch     PetscCall(DMPlexGetGeometryFVM(plex, NULL, &cellgeom, NULL));
17079566063dSJacob Faibussowitsch     PetscCall(OutputVTK(dm, "ex11-cellgeom.vtk", &viewer));
17089566063dSJacob Faibussowitsch     PetscCall(VecView(cellgeom, viewer));
17099566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
17109566063dSJacob Faibussowitsch     PetscCall(CreatePartitionVec(dm, &dmCell, &partition));
17119566063dSJacob Faibussowitsch     PetscCall(OutputVTK(dmCell, "ex11-partition.vtk", &viewer));
17129566063dSJacob Faibussowitsch     PetscCall(VecView(partition, viewer));
17139566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
17149566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&partition));
17159566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmCell));
1716c4762a1bSJed Brown   }
1717c4762a1bSJed Brown   /* collect max maxspeed from all processes -- todo */
17189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetGeometryFVM(plex, NULL, NULL, &minRadius));
17199566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
1720712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(&phys->maxspeed, &mod->maxspeed, 1, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)ts)));
172154c59aa7SJacob Faibussowitsch   PetscCheck(mod->maxspeed > 0, comm, PETSC_ERR_ARG_WRONGSTATE, "Physics '%s' did not set maxspeed", physname);
1722c4762a1bSJed Brown   dt = cfl * minRadius / mod->maxspeed;
17239566063dSJacob Faibussowitsch   PetscCall(TSSetTimeStep(ts, dt));
17249566063dSJacob Faibussowitsch   PetscCall(TSSetFromOptions(ts));
1725c4762a1bSJed Brown 
172652115386SStefano Zampini   /* When using adaptive mesh refinement
172752115386SStefano Zampini      specify callbacks to refine the solution
172852115386SStefano Zampini      and interpolate data from old to new mesh */
172952115386SStefano Zampini   if (useAMR) { PetscCall(TSSetResize(ts, adaptToleranceFVMSetUp, Transfer, &tctx)); }
173052115386SStefano Zampini   PetscCall(TSSetSolution(ts, X));
17319566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&X));
173252115386SStefano Zampini   PetscCall(TSSolve(ts, NULL));
17339566063dSJacob Faibussowitsch   PetscCall(TSGetSolveTime(ts, &ftime));
17349566063dSJacob Faibussowitsch   PetscCall(TSGetStepNumber(ts, &nsteps));
17359566063dSJacob Faibussowitsch   PetscCall(TSGetConvergedReason(ts, &reason));
173663a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%s at time %g after %" PetscInt_FMT " steps\n", TSConvergedReasons[reason], (double)ftime, nsteps));
17379566063dSJacob Faibussowitsch   PetscCall(TSDestroy(&ts));
1738c4762a1bSJed Brown 
17399566063dSJacob Faibussowitsch   PetscCall(VecTaggerDestroy(&refineTag));
17409566063dSJacob Faibussowitsch   PetscCall(VecTaggerDestroy(&coarsenTag));
17419566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDestroy(&PhysicsList));
17429566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListDestroy(&PhysicsRiemannList_SW));
17439566063dSJacob Faibussowitsch   PetscCall(FunctionalLinkDestroy(&user->model->functionalRegistry));
17449566063dSJacob Faibussowitsch   PetscCall(PetscFree(user->model->functionalMonitored));
17459566063dSJacob Faibussowitsch   PetscCall(PetscFree(user->model->functionalCall));
17469566063dSJacob Faibussowitsch   PetscCall(PetscFree(user->model->physics->data));
17479566063dSJacob Faibussowitsch   PetscCall(PetscFree(user->model->physics));
17489566063dSJacob Faibussowitsch   PetscCall(PetscFree(user->model));
17499566063dSJacob Faibussowitsch   PetscCall(PetscFree(user));
17509566063dSJacob Faibussowitsch   PetscCall(PetscLimiterDestroy(&limiter));
17519566063dSJacob Faibussowitsch   PetscCall(PetscLimiterDestroy(&noneLimiter));
17529566063dSJacob Faibussowitsch   PetscCall(PetscFVDestroy(&fvm));
17539566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dm));
17549566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
1755b122ec5aSJacob Faibussowitsch   return 0;
1756c4762a1bSJed Brown }
1757c4762a1bSJed Brown 
1758c4762a1bSJed Brown /* Godunov fluxs */
1759d71ae5a4SJacob Faibussowitsch PetscScalar cvmgp_(PetscScalar *a, PetscScalar *b, PetscScalar *test)
1760d71ae5a4SJacob Faibussowitsch {
1761c4762a1bSJed Brown   /* System generated locals */
1762c4762a1bSJed Brown   PetscScalar ret_val;
1763c4762a1bSJed Brown 
1764ad540459SPierre Jolivet   if (PetscRealPart(*test) > 0.) goto L10;
1765c4762a1bSJed Brown   ret_val = *b;
1766c4762a1bSJed Brown   return ret_val;
1767c4762a1bSJed Brown L10:
1768c4762a1bSJed Brown   ret_val = *a;
1769c4762a1bSJed Brown   return ret_val;
1770c4762a1bSJed Brown } /* cvmgp_ */
1771c4762a1bSJed Brown 
1772d71ae5a4SJacob Faibussowitsch PetscScalar cvmgm_(PetscScalar *a, PetscScalar *b, PetscScalar *test)
1773d71ae5a4SJacob Faibussowitsch {
1774c4762a1bSJed Brown   /* System generated locals */
1775c4762a1bSJed Brown   PetscScalar ret_val;
1776c4762a1bSJed Brown 
1777ad540459SPierre Jolivet   if (PetscRealPart(*test) < 0.) goto L10;
1778c4762a1bSJed Brown   ret_val = *b;
1779c4762a1bSJed Brown   return ret_val;
1780c4762a1bSJed Brown L10:
1781c4762a1bSJed Brown   ret_val = *a;
1782c4762a1bSJed Brown   return ret_val;
1783c4762a1bSJed Brown } /* cvmgm_ */
1784c4762a1bSJed Brown 
1785d71ae5a4SJacob Faibussowitsch int riem1mdt(PetscScalar *gaml, PetscScalar *gamr, PetscScalar *rl, PetscScalar *pl, PetscScalar *uxl, PetscScalar *rr, PetscScalar *pr, PetscScalar *uxr, PetscScalar *rstarl, PetscScalar *rstarr, PetscScalar *pstar, PetscScalar *ustar)
1786d71ae5a4SJacob Faibussowitsch {
1787c4762a1bSJed Brown   /* Initialized data */
1788c4762a1bSJed Brown 
1789c4762a1bSJed Brown   static PetscScalar smallp = 1e-8;
1790c4762a1bSJed Brown 
1791c4762a1bSJed Brown   /* System generated locals */
1792c4762a1bSJed Brown   int         i__1;
1793c4762a1bSJed Brown   PetscScalar d__1, d__2;
1794c4762a1bSJed Brown 
1795c4762a1bSJed Brown   /* Local variables */
1796c4762a1bSJed Brown   static int         i0;
1797c4762a1bSJed Brown   static PetscScalar cl, cr, wl, zl, wr, zr, pst, durl, skpr1, skpr2;
1798c4762a1bSJed Brown   static int         iwave;
1799c4762a1bSJed Brown   static PetscScalar gascl4, gascr4, cstarl, dpstar, cstarr;
1800c4762a1bSJed Brown   /* static PetscScalar csqrl, csqrr, gascl1, gascl2, gascl3, gascr1, gascr2, gascr3; */
1801c4762a1bSJed Brown   static int         iterno;
1802c4762a1bSJed Brown   static PetscScalar ustarl, ustarr, rarepr1, rarepr2;
1803c4762a1bSJed Brown 
1804c4762a1bSJed Brown   /* gascl1 = *gaml - 1.; */
1805c4762a1bSJed Brown   /* gascl2 = (*gaml + 1.) * .5; */
1806c4762a1bSJed Brown   /* gascl3 = gascl2 / *gaml; */
1807c4762a1bSJed Brown   gascl4 = 1. / (*gaml - 1.);
1808c4762a1bSJed Brown 
1809c4762a1bSJed Brown   /* gascr1 = *gamr - 1.; */
1810c4762a1bSJed Brown   /* gascr2 = (*gamr + 1.) * .5; */
1811c4762a1bSJed Brown   /* gascr3 = gascr2 / *gamr; */
1812c4762a1bSJed Brown   gascr4 = 1. / (*gamr - 1.);
1813c4762a1bSJed Brown   iterno = 10;
1814c4762a1bSJed Brown   /*        find pstar: */
1815c4762a1bSJed Brown   cl = PetscSqrtScalar(*gaml * *pl / *rl);
1816c4762a1bSJed Brown   cr = PetscSqrtScalar(*gamr * *pr / *rr);
1817c4762a1bSJed Brown   wl = *rl * cl;
1818c4762a1bSJed Brown   wr = *rr * cr;
1819c4762a1bSJed Brown   /* csqrl = wl * wl; */
1820c4762a1bSJed Brown   /* csqrr = wr * wr; */
1821c4762a1bSJed Brown   *pstar  = (wl * *pr + wr * *pl) / (wl + wr);
1822c4762a1bSJed Brown   *pstar  = PetscMax(PetscRealPart(*pstar), PetscRealPart(smallp));
1823c4762a1bSJed Brown   pst     = *pl / *pr;
1824c4762a1bSJed Brown   skpr1   = cr * (pst - 1.) * PetscSqrtScalar(2. / (*gamr * (*gamr - 1. + (*gamr + 1.) * pst)));
1825c4762a1bSJed Brown   d__1    = (*gamr - 1.) / (*gamr * 2.);
1826c4762a1bSJed Brown   rarepr2 = gascr4 * 2. * cr * (1. - PetscPowScalar(pst, d__1));
1827c4762a1bSJed Brown   pst     = *pr / *pl;
1828c4762a1bSJed Brown   skpr2   = cl * (pst - 1.) * PetscSqrtScalar(2. / (*gaml * (*gaml - 1. + (*gaml + 1.) * pst)));
1829c4762a1bSJed Brown   d__1    = (*gaml - 1.) / (*gaml * 2.);
1830c4762a1bSJed Brown   rarepr1 = gascl4 * 2. * cl * (1. - PetscPowScalar(pst, d__1));
1831c4762a1bSJed Brown   durl    = *uxr - *uxl;
1832c4762a1bSJed Brown   if (PetscRealPart(*pr) < PetscRealPart(*pl)) {
1833c4762a1bSJed Brown     if (PetscRealPart(durl) >= PetscRealPart(rarepr1)) {
1834c4762a1bSJed Brown       iwave = 100;
1835c4762a1bSJed Brown     } else if (PetscRealPart(durl) <= PetscRealPart(-skpr1)) {
1836c4762a1bSJed Brown       iwave = 300;
1837c4762a1bSJed Brown     } else {
1838c4762a1bSJed Brown       iwave = 400;
1839c4762a1bSJed Brown     }
1840c4762a1bSJed Brown   } else {
1841c4762a1bSJed Brown     if (PetscRealPart(durl) >= PetscRealPart(rarepr2)) {
1842c4762a1bSJed Brown       iwave = 100;
1843c4762a1bSJed Brown     } else if (PetscRealPart(durl) <= PetscRealPart(-skpr2)) {
1844c4762a1bSJed Brown       iwave = 300;
1845c4762a1bSJed Brown     } else {
1846c4762a1bSJed Brown       iwave = 200;
1847c4762a1bSJed Brown     }
1848c4762a1bSJed Brown   }
1849c4762a1bSJed Brown   if (iwave == 100) {
1850c4762a1bSJed Brown     /*     1-wave: rarefaction wave, 3-wave: rarefaction wave */
1851c4762a1bSJed Brown     /*     case (100) */
1852c4762a1bSJed Brown     i__1 = iterno;
1853c4762a1bSJed Brown     for (i0 = 1; i0 <= i__1; ++i0) {
1854c4762a1bSJed Brown       d__1    = *pstar / *pl;
1855c4762a1bSJed Brown       d__2    = 1. / *gaml;
1856c4762a1bSJed Brown       *rstarl = *rl * PetscPowScalar(d__1, d__2);
1857c4762a1bSJed Brown       cstarl  = PetscSqrtScalar(*gaml * *pstar / *rstarl);
1858c4762a1bSJed Brown       ustarl  = *uxl - gascl4 * 2. * (cstarl - cl);
1859c4762a1bSJed Brown       zl      = *rstarl * cstarl;
1860c4762a1bSJed Brown       d__1    = *pstar / *pr;
1861c4762a1bSJed Brown       d__2    = 1. / *gamr;
1862c4762a1bSJed Brown       *rstarr = *rr * PetscPowScalar(d__1, d__2);
1863c4762a1bSJed Brown       cstarr  = PetscSqrtScalar(*gamr * *pstar / *rstarr);
1864c4762a1bSJed Brown       ustarr  = *uxr + gascr4 * 2. * (cstarr - cr);
1865c4762a1bSJed Brown       zr      = *rstarr * cstarr;
1866c4762a1bSJed Brown       dpstar  = zl * zr * (ustarr - ustarl) / (zl + zr);
1867c4762a1bSJed Brown       *pstar -= dpstar;
1868c4762a1bSJed Brown       *pstar = PetscMax(PetscRealPart(*pstar), PetscRealPart(smallp));
1869c4762a1bSJed Brown       if (PetscAbsScalar(dpstar) / PetscRealPart(*pstar) <= 1e-8) {
1870c4762a1bSJed Brown #if 0
1871c4762a1bSJed Brown         break;
1872c4762a1bSJed Brown #endif
1873c4762a1bSJed Brown       }
1874c4762a1bSJed Brown     }
1875c4762a1bSJed Brown     /*     1-wave: shock wave, 3-wave: rarefaction wave */
1876c4762a1bSJed Brown   } else if (iwave == 200) {
1877c4762a1bSJed Brown     /*     case (200) */
1878c4762a1bSJed Brown     i__1 = iterno;
1879c4762a1bSJed Brown     for (i0 = 1; i0 <= i__1; ++i0) {
1880c4762a1bSJed Brown       pst     = *pstar / *pl;
1881c4762a1bSJed Brown       ustarl  = *uxl - (pst - 1.) * cl * PetscSqrtScalar(2. / (*gaml * (*gaml - 1. + (*gaml + 1.) * pst)));
1882c4762a1bSJed Brown       zl      = *pl / cl * PetscSqrtScalar(*gaml * 2. * (*gaml - 1. + (*gaml + 1.) * pst)) * (*gaml - 1. + (*gaml + 1.) * pst) / (*gaml * 3. - 1. + (*gaml + 1.) * pst);
1883c4762a1bSJed Brown       d__1    = *pstar / *pr;
1884c4762a1bSJed Brown       d__2    = 1. / *gamr;
1885c4762a1bSJed Brown       *rstarr = *rr * PetscPowScalar(d__1, d__2);
1886c4762a1bSJed Brown       cstarr  = PetscSqrtScalar(*gamr * *pstar / *rstarr);
1887c4762a1bSJed Brown       zr      = *rstarr * cstarr;
1888c4762a1bSJed Brown       ustarr  = *uxr + gascr4 * 2. * (cstarr - cr);
1889c4762a1bSJed Brown       dpstar  = zl * zr * (ustarr - ustarl) / (zl + zr);
1890c4762a1bSJed Brown       *pstar -= dpstar;
1891c4762a1bSJed Brown       *pstar = PetscMax(PetscRealPart(*pstar), PetscRealPart(smallp));
1892c4762a1bSJed Brown       if (PetscAbsScalar(dpstar) / PetscRealPart(*pstar) <= 1e-8) {
1893c4762a1bSJed Brown #if 0
1894c4762a1bSJed Brown         break;
1895c4762a1bSJed Brown #endif
1896c4762a1bSJed Brown       }
1897c4762a1bSJed Brown     }
1898c4762a1bSJed Brown     /*     1-wave: shock wave, 3-wave: shock */
1899c4762a1bSJed Brown   } else if (iwave == 300) {
1900c4762a1bSJed Brown     /*     case (300) */
1901c4762a1bSJed Brown     i__1 = iterno;
1902c4762a1bSJed Brown     for (i0 = 1; i0 <= i__1; ++i0) {
1903c4762a1bSJed Brown       pst    = *pstar / *pl;
1904c4762a1bSJed Brown       ustarl = *uxl - (pst - 1.) * cl * PetscSqrtScalar(2. / (*gaml * (*gaml - 1. + (*gaml + 1.) * pst)));
1905c4762a1bSJed Brown       zl     = *pl / cl * PetscSqrtScalar(*gaml * 2. * (*gaml - 1. + (*gaml + 1.) * pst)) * (*gaml - 1. + (*gaml + 1.) * pst) / (*gaml * 3. - 1. + (*gaml + 1.) * pst);
1906c4762a1bSJed Brown       pst    = *pstar / *pr;
1907c4762a1bSJed Brown       ustarr = *uxr + (pst - 1.) * cr * PetscSqrtScalar(2. / (*gamr * (*gamr - 1. + (*gamr + 1.) * pst)));
1908c4762a1bSJed Brown       zr     = *pr / cr * PetscSqrtScalar(*gamr * 2. * (*gamr - 1. + (*gamr + 1.) * pst)) * (*gamr - 1. + (*gamr + 1.) * pst) / (*gamr * 3. - 1. + (*gamr + 1.) * pst);
1909c4762a1bSJed Brown       dpstar = zl * zr * (ustarr - ustarl) / (zl + zr);
1910c4762a1bSJed Brown       *pstar -= dpstar;
1911c4762a1bSJed Brown       *pstar = PetscMax(PetscRealPart(*pstar), PetscRealPart(smallp));
1912c4762a1bSJed Brown       if (PetscAbsScalar(dpstar) / PetscRealPart(*pstar) <= 1e-8) {
1913c4762a1bSJed Brown #if 0
1914c4762a1bSJed Brown         break;
1915c4762a1bSJed Brown #endif
1916c4762a1bSJed Brown       }
1917c4762a1bSJed Brown     }
1918c4762a1bSJed Brown     /*     1-wave: rarefaction wave, 3-wave: shock */
1919c4762a1bSJed Brown   } else if (iwave == 400) {
1920c4762a1bSJed Brown     /*     case (400) */
1921c4762a1bSJed Brown     i__1 = iterno;
1922c4762a1bSJed Brown     for (i0 = 1; i0 <= i__1; ++i0) {
1923c4762a1bSJed Brown       d__1    = *pstar / *pl;
1924c4762a1bSJed Brown       d__2    = 1. / *gaml;
1925c4762a1bSJed Brown       *rstarl = *rl * PetscPowScalar(d__1, d__2);
1926c4762a1bSJed Brown       cstarl  = PetscSqrtScalar(*gaml * *pstar / *rstarl);
1927c4762a1bSJed Brown       ustarl  = *uxl - gascl4 * 2. * (cstarl - cl);
1928c4762a1bSJed Brown       zl      = *rstarl * cstarl;
1929c4762a1bSJed Brown       pst     = *pstar / *pr;
1930c4762a1bSJed Brown       ustarr  = *uxr + (pst - 1.) * cr * PetscSqrtScalar(2. / (*gamr * (*gamr - 1. + (*gamr + 1.) * pst)));
1931c4762a1bSJed Brown       zr      = *pr / cr * PetscSqrtScalar(*gamr * 2. * (*gamr - 1. + (*gamr + 1.) * pst)) * (*gamr - 1. + (*gamr + 1.) * pst) / (*gamr * 3. - 1. + (*gamr + 1.) * pst);
1932c4762a1bSJed Brown       dpstar  = zl * zr * (ustarr - ustarl) / (zl + zr);
1933c4762a1bSJed Brown       *pstar -= dpstar;
1934c4762a1bSJed Brown       *pstar = PetscMax(PetscRealPart(*pstar), PetscRealPart(smallp));
1935c4762a1bSJed Brown       if (PetscAbsScalar(dpstar) / PetscRealPart(*pstar) <= 1e-8) {
1936c4762a1bSJed Brown #if 0
1937c4762a1bSJed Brown               break;
1938c4762a1bSJed Brown #endif
1939c4762a1bSJed Brown       }
1940c4762a1bSJed Brown     }
1941c4762a1bSJed Brown   }
1942c4762a1bSJed Brown 
1943c4762a1bSJed Brown   *ustar = (zl * ustarr + zr * ustarl) / (zl + zr);
1944c4762a1bSJed Brown   if (PetscRealPart(*pstar) > PetscRealPart(*pl)) {
1945c4762a1bSJed Brown     pst     = *pstar / *pl;
19469371c9d4SSatish Balay     *rstarl = ((*gaml + 1.) * pst + *gaml - 1.) / ((*gaml - 1.) * pst + *gaml + 1.) * *rl;
1947c4762a1bSJed Brown   }
1948c4762a1bSJed Brown   if (PetscRealPart(*pstar) > PetscRealPart(*pr)) {
1949c4762a1bSJed Brown     pst     = *pstar / *pr;
19509371c9d4SSatish Balay     *rstarr = ((*gamr + 1.) * pst + *gamr - 1.) / ((*gamr - 1.) * pst + *gamr + 1.) * *rr;
1951c4762a1bSJed Brown   }
1952c4762a1bSJed Brown   return iwave;
1953c4762a1bSJed Brown }
1954c4762a1bSJed Brown 
1955d71ae5a4SJacob Faibussowitsch PetscScalar sign(PetscScalar x)
1956d71ae5a4SJacob Faibussowitsch {
1957c4762a1bSJed Brown   if (PetscRealPart(x) > 0) return 1.0;
1958c4762a1bSJed Brown   if (PetscRealPart(x) < 0) return -1.0;
1959c4762a1bSJed Brown   return 0.0;
1960c4762a1bSJed Brown }
1961c4762a1bSJed Brown /*        Riemann Solver */
1962c4762a1bSJed Brown /* -------------------------------------------------------------------- */
1963d71ae5a4SJacob Faibussowitsch int riemannsolver(PetscScalar *xcen, PetscScalar *xp, PetscScalar *dtt, PetscScalar *rl, PetscScalar *uxl, PetscScalar *pl, PetscScalar *utl, PetscScalar *ubl, PetscScalar *gaml, PetscScalar *rho1l, PetscScalar *rr, PetscScalar *uxr, PetscScalar *pr, PetscScalar *utr, PetscScalar *ubr, PetscScalar *gamr, PetscScalar *rho1r, PetscScalar *rx, PetscScalar *uxm, PetscScalar *px, PetscScalar *utx, PetscScalar *ubx, PetscScalar *gam, PetscScalar *rho1)
1964d71ae5a4SJacob Faibussowitsch {
1965c4762a1bSJed Brown   /* System generated locals */
1966c4762a1bSJed Brown   PetscScalar d__1, d__2;
1967c4762a1bSJed Brown 
1968c4762a1bSJed Brown   /* Local variables */
1969c4762a1bSJed Brown   static PetscScalar s, c0, p0, r0, u0, w0, x0, x2, ri, cx, sgn0, wsp0, gasc1, gasc2, gasc3, gasc4;
1970c4762a1bSJed Brown   static PetscScalar cstar, pstar, rstar, ustar, xstar, wspst, ushock, streng, rstarl, rstarr, rstars;
1971c4762a1bSJed Brown   int                iwave;
1972c4762a1bSJed Brown 
1973c4762a1bSJed Brown   if (*rl == *rr && *pr == *pl && *uxl == *uxr && *gaml == *gamr) {
1974c4762a1bSJed Brown     *rx  = *rl;
1975c4762a1bSJed Brown     *px  = *pl;
1976c4762a1bSJed Brown     *uxm = *uxl;
1977c4762a1bSJed Brown     *gam = *gaml;
1978c4762a1bSJed Brown     x2   = *xcen + *uxm * *dtt;
1979c4762a1bSJed Brown 
1980c4762a1bSJed Brown     if (PetscRealPart(*xp) >= PetscRealPart(x2)) {
1981c4762a1bSJed Brown       *utx  = *utr;
1982c4762a1bSJed Brown       *ubx  = *ubr;
1983c4762a1bSJed Brown       *rho1 = *rho1r;
1984c4762a1bSJed Brown     } else {
1985c4762a1bSJed Brown       *utx  = *utl;
1986c4762a1bSJed Brown       *ubx  = *ubl;
1987c4762a1bSJed Brown       *rho1 = *rho1l;
1988c4762a1bSJed Brown     }
1989c4762a1bSJed Brown     return 0;
1990c4762a1bSJed Brown   }
1991c4762a1bSJed Brown   iwave = riem1mdt(gaml, gamr, rl, pl, uxl, rr, pr, uxr, &rstarl, &rstarr, &pstar, &ustar);
1992c4762a1bSJed Brown 
1993c4762a1bSJed Brown   x2   = *xcen + ustar * *dtt;
1994c4762a1bSJed Brown   d__1 = *xp - x2;
1995c4762a1bSJed Brown   sgn0 = sign(d__1);
1996c4762a1bSJed Brown   /*            x is in 3-wave if sgn0 = 1 */
1997c4762a1bSJed Brown   /*            x is in 1-wave if sgn0 = -1 */
1998c4762a1bSJed Brown   r0     = cvmgm_(rl, rr, &sgn0);
1999c4762a1bSJed Brown   p0     = cvmgm_(pl, pr, &sgn0);
2000c4762a1bSJed Brown   u0     = cvmgm_(uxl, uxr, &sgn0);
2001c4762a1bSJed Brown   *gam   = cvmgm_(gaml, gamr, &sgn0);
2002c4762a1bSJed Brown   gasc1  = *gam - 1.;
2003c4762a1bSJed Brown   gasc2  = (*gam + 1.) * .5;
2004c4762a1bSJed Brown   gasc3  = gasc2 / *gam;
2005c4762a1bSJed Brown   gasc4  = 1. / (*gam - 1.);
2006c4762a1bSJed Brown   c0     = PetscSqrtScalar(*gam * p0 / r0);
2007c4762a1bSJed Brown   streng = pstar - p0;
2008c4762a1bSJed Brown   w0     = *gam * r0 * p0 * (gasc3 * streng / p0 + 1.);
2009c4762a1bSJed Brown   rstars = r0 / (1. - r0 * streng / w0);
2010c4762a1bSJed Brown   d__1   = p0 / pstar;
2011c4762a1bSJed Brown   d__2   = -1. / *gam;
2012c4762a1bSJed Brown   rstarr = r0 * PetscPowScalar(d__1, d__2);
2013c4762a1bSJed Brown   rstar  = cvmgm_(&rstarr, &rstars, &streng);
2014c4762a1bSJed Brown   w0     = PetscSqrtScalar(w0);
2015c4762a1bSJed Brown   cstar  = PetscSqrtScalar(*gam * pstar / rstar);
2016c4762a1bSJed Brown   wsp0   = u0 + sgn0 * c0;
2017c4762a1bSJed Brown   wspst  = ustar + sgn0 * cstar;
2018c4762a1bSJed Brown   ushock = ustar + sgn0 * w0 / rstar;
2019c4762a1bSJed Brown   wspst  = cvmgp_(&ushock, &wspst, &streng);
2020c4762a1bSJed Brown   wsp0   = cvmgp_(&ushock, &wsp0, &streng);
2021c4762a1bSJed Brown   x0     = *xcen + wsp0 * *dtt;
2022c4762a1bSJed Brown   xstar  = *xcen + wspst * *dtt;
2023c4762a1bSJed Brown   /*           using gas formula to evaluate rarefaction wave */
2024c4762a1bSJed Brown   /*            ri : reiman invariant */
2025c4762a1bSJed Brown   ri   = u0 - sgn0 * 2. * gasc4 * c0;
2026c4762a1bSJed Brown   cx   = sgn0 * .5 * gasc1 / gasc2 * ((*xp - *xcen) / *dtt - ri);
2027c4762a1bSJed Brown   *uxm = ri + sgn0 * 2. * gasc4 * cx;
2028c4762a1bSJed Brown   s    = p0 / PetscPowScalar(r0, *gam);
2029c4762a1bSJed Brown   d__1 = cx * cx / (*gam * s);
2030c4762a1bSJed Brown   *rx  = PetscPowScalar(d__1, gasc4);
2031c4762a1bSJed Brown   *px  = cx * cx * *rx / *gam;
2032c4762a1bSJed Brown   d__1 = sgn0 * (x0 - *xp);
2033c4762a1bSJed Brown   *rx  = cvmgp_(rx, &r0, &d__1);
2034c4762a1bSJed Brown   d__1 = sgn0 * (x0 - *xp);
2035c4762a1bSJed Brown   *px  = cvmgp_(px, &p0, &d__1);
2036c4762a1bSJed Brown   d__1 = sgn0 * (x0 - *xp);
2037c4762a1bSJed Brown   *uxm = cvmgp_(uxm, &u0, &d__1);
2038c4762a1bSJed Brown   d__1 = sgn0 * (xstar - *xp);
2039c4762a1bSJed Brown   *rx  = cvmgm_(rx, &rstar, &d__1);
2040c4762a1bSJed Brown   d__1 = sgn0 * (xstar - *xp);
2041c4762a1bSJed Brown   *px  = cvmgm_(px, &pstar, &d__1);
2042c4762a1bSJed Brown   d__1 = sgn0 * (xstar - *xp);
2043c4762a1bSJed Brown   *uxm = cvmgm_(uxm, &ustar, &d__1);
2044c4762a1bSJed Brown   if (PetscRealPart(*xp) >= PetscRealPart(x2)) {
2045c4762a1bSJed Brown     *utx  = *utr;
2046c4762a1bSJed Brown     *ubx  = *ubr;
2047c4762a1bSJed Brown     *rho1 = *rho1r;
2048c4762a1bSJed Brown   } else {
2049c4762a1bSJed Brown     *utx  = *utl;
2050c4762a1bSJed Brown     *ubx  = *ubl;
2051c4762a1bSJed Brown     *rho1 = *rho1l;
2052c4762a1bSJed Brown   }
2053c4762a1bSJed Brown   return iwave;
2054c4762a1bSJed Brown }
2055d71ae5a4SJacob Faibussowitsch int godunovflux(const PetscScalar *ul, const PetscScalar *ur, PetscScalar *flux, const PetscReal *nn, const int *ndim, const PetscReal *gamma)
2056d71ae5a4SJacob Faibussowitsch {
2057c4762a1bSJed Brown   /* System generated locals */
2058c4762a1bSJed Brown   int         i__1, iwave;
2059c4762a1bSJed Brown   PetscScalar d__1, d__2, d__3;
2060c4762a1bSJed Brown 
2061c4762a1bSJed Brown   /* Local variables */
2062c4762a1bSJed Brown   static int         k;
20639371c9d4SSatish Balay   static PetscScalar bn[3], fn, ft, tg[3], pl, rl, pm, pr, rr, xp, ubl, ubm, ubr, dtt, unm, tmp, utl, utm, uxl, utr, uxr, gaml, gamm, gamr, xcen, rhom, rho1l, rho1m, rho1r;
2064c4762a1bSJed Brown 
2065c4762a1bSJed Brown   /* Function Body */
2066c4762a1bSJed Brown   xcen = 0.;
2067c4762a1bSJed Brown   xp   = 0.;
2068c4762a1bSJed Brown   i__1 = *ndim;
2069c4762a1bSJed Brown   for (k = 1; k <= i__1; ++k) {
2070c4762a1bSJed Brown     tg[k - 1] = 0.;
2071c4762a1bSJed Brown     bn[k - 1] = 0.;
2072c4762a1bSJed Brown   }
2073c4762a1bSJed Brown   dtt = 1.;
2074c4762a1bSJed Brown   if (*ndim == 3) {
2075a795f3e7SBarry Smith     if (nn[0] == 0. && nn[1] == 0.) {
2076c4762a1bSJed Brown       tg[0] = 1.;
2077c4762a1bSJed Brown     } else {
2078a795f3e7SBarry Smith       tg[0] = -nn[1];
2079a795f3e7SBarry Smith       tg[1] = nn[0];
2080c4762a1bSJed Brown     }
2081c4762a1bSJed Brown     /*           tmp=dsqrt(tg(1)**2+tg(2)**2) */
2082c4762a1bSJed Brown     /*           tg=tg/tmp */
2083a795f3e7SBarry Smith     bn[0] = -nn[2] * tg[1];
2084a795f3e7SBarry Smith     bn[1] = nn[2] * tg[0];
2085a795f3e7SBarry Smith     bn[2] = nn[0] * tg[1] - nn[1] * tg[0];
2086c4762a1bSJed Brown     /* Computing 2nd power */
2087c4762a1bSJed Brown     d__1 = bn[0];
2088c4762a1bSJed Brown     /* Computing 2nd power */
2089c4762a1bSJed Brown     d__2 = bn[1];
2090c4762a1bSJed Brown     /* Computing 2nd power */
2091c4762a1bSJed Brown     d__3 = bn[2];
2092c4762a1bSJed Brown     tmp  = PetscSqrtScalar(d__1 * d__1 + d__2 * d__2 + d__3 * d__3);
2093c4762a1bSJed Brown     i__1 = *ndim;
2094ad540459SPierre Jolivet     for (k = 1; k <= i__1; ++k) bn[k - 1] /= tmp;
2095c4762a1bSJed Brown   } else if (*ndim == 2) {
2096a795f3e7SBarry Smith     tg[0] = -nn[1];
2097a795f3e7SBarry Smith     tg[1] = nn[0];
2098c4762a1bSJed Brown     /*           tmp=dsqrt(tg(1)**2+tg(2)**2) */
2099c4762a1bSJed Brown     /*           tg=tg/tmp */
2100c4762a1bSJed Brown     bn[0] = 0.;
2101c4762a1bSJed Brown     bn[1] = 0.;
2102c4762a1bSJed Brown     bn[2] = 1.;
2103c4762a1bSJed Brown   }
2104a795f3e7SBarry Smith   rl   = ul[0];
2105a795f3e7SBarry Smith   rr   = ur[0];
2106c4762a1bSJed Brown   uxl  = 0.;
2107c4762a1bSJed Brown   uxr  = 0.;
2108c4762a1bSJed Brown   utl  = 0.;
2109c4762a1bSJed Brown   utr  = 0.;
2110c4762a1bSJed Brown   ubl  = 0.;
2111c4762a1bSJed Brown   ubr  = 0.;
2112c4762a1bSJed Brown   i__1 = *ndim;
2113c4762a1bSJed Brown   for (k = 1; k <= i__1; ++k) {
2114a795f3e7SBarry Smith     uxl += ul[k] * nn[k - 1];
2115a795f3e7SBarry Smith     uxr += ur[k] * nn[k - 1];
2116a795f3e7SBarry Smith     utl += ul[k] * tg[k - 1];
2117a795f3e7SBarry Smith     utr += ur[k] * tg[k - 1];
2118a795f3e7SBarry Smith     ubl += ul[k] * bn[k - 1];
2119a795f3e7SBarry Smith     ubr += ur[k] * bn[k - 1];
2120c4762a1bSJed Brown   }
2121c4762a1bSJed Brown   uxl /= rl;
2122c4762a1bSJed Brown   uxr /= rr;
2123c4762a1bSJed Brown   utl /= rl;
2124c4762a1bSJed Brown   utr /= rr;
2125c4762a1bSJed Brown   ubl /= rl;
2126c4762a1bSJed Brown   ubr /= rr;
2127c4762a1bSJed Brown 
2128c4762a1bSJed Brown   gaml = *gamma;
2129c4762a1bSJed Brown   gamr = *gamma;
2130c4762a1bSJed Brown   /* Computing 2nd power */
2131c4762a1bSJed Brown   d__1 = uxl;
2132c4762a1bSJed Brown   /* Computing 2nd power */
2133c4762a1bSJed Brown   d__2 = utl;
2134c4762a1bSJed Brown   /* Computing 2nd power */
2135c4762a1bSJed Brown   d__3 = ubl;
2136a795f3e7SBarry Smith   pl   = (*gamma - 1.) * (ul[*ndim + 1] - rl * .5 * (d__1 * d__1 + d__2 * d__2 + d__3 * d__3));
2137c4762a1bSJed Brown   /* Computing 2nd power */
2138c4762a1bSJed Brown   d__1 = uxr;
2139c4762a1bSJed Brown   /* Computing 2nd power */
2140c4762a1bSJed Brown   d__2 = utr;
2141c4762a1bSJed Brown   /* Computing 2nd power */
2142c4762a1bSJed Brown   d__3  = ubr;
2143a795f3e7SBarry Smith   pr    = (*gamma - 1.) * (ur[*ndim + 1] - rr * .5 * (d__1 * d__1 + d__2 * d__2 + d__3 * d__3));
2144c4762a1bSJed Brown   rho1l = rl;
2145c4762a1bSJed Brown   rho1r = rr;
2146c4762a1bSJed Brown 
21479371c9d4SSatish Balay   iwave = riemannsolver(&xcen, &xp, &dtt, &rl, &uxl, &pl, &utl, &ubl, &gaml, &rho1l, &rr, &uxr, &pr, &utr, &ubr, &gamr, &rho1r, &rhom, &unm, &pm, &utm, &ubm, &gamm, &rho1m);
2148c4762a1bSJed Brown 
2149a795f3e7SBarry Smith   flux[0] = rhom * unm;
2150c4762a1bSJed Brown   fn      = rhom * unm * unm + pm;
2151c4762a1bSJed Brown   ft      = rhom * unm * utm;
2152c4762a1bSJed Brown   /*           flux(2)=fn*nn(1)+ft*nn(2) */
2153c4762a1bSJed Brown   /*           flux(3)=fn*tg(1)+ft*tg(2) */
2154a795f3e7SBarry Smith   flux[1] = fn * nn[0] + ft * tg[0];
2155a795f3e7SBarry Smith   flux[2] = fn * nn[1] + ft * tg[1];
2156c4762a1bSJed Brown   /*           flux(2)=rhom*unm*(unm)+pm */
2157c4762a1bSJed Brown   /*           flux(3)=rhom*(unm)*utm */
2158ad540459SPierre Jolivet   if (*ndim == 3) flux[3] = rhom * unm * ubm;
2159a795f3e7SBarry Smith   flux[*ndim + 1] = (rhom * .5 * (unm * unm + utm * utm + ubm * ubm) + gamm / (gamm - 1.) * pm) * unm;
2160c4762a1bSJed Brown   return iwave;
2161c4762a1bSJed Brown } /* godunovflux_ */
2162c4762a1bSJed Brown 
2163c4762a1bSJed Brown /* Subroutine to set up the initial conditions for the */
2164c4762a1bSJed Brown /* Shock Interface interaction or linear wave (Ravi Samtaney,Mark Adams). */
2165c4762a1bSJed Brown /* ----------------------------------------------------------------------- */
2166d71ae5a4SJacob Faibussowitsch int projecteqstate(PetscReal wc[], const PetscReal ueq[], PetscReal lv[][3])
2167d71ae5a4SJacob Faibussowitsch {
2168c4762a1bSJed Brown   int j, k;
2169c4762a1bSJed Brown   /*      Wc=matmul(lv,Ueq) 3 vars */
2170c4762a1bSJed Brown   for (k = 0; k < 3; ++k) {
2171c4762a1bSJed Brown     wc[k] = 0.;
2172ad540459SPierre Jolivet     for (j = 0; j < 3; ++j) wc[k] += lv[k][j] * ueq[j];
2173c4762a1bSJed Brown   }
2174c4762a1bSJed Brown   return 0;
2175c4762a1bSJed Brown }
2176c4762a1bSJed Brown /* ----------------------------------------------------------------------- */
2177d71ae5a4SJacob Faibussowitsch int projecttoprim(PetscReal v[], const PetscReal wc[], PetscReal rv[][3])
2178d71ae5a4SJacob Faibussowitsch {
2179c4762a1bSJed Brown   int k, j;
2180c4762a1bSJed Brown   /*      V=matmul(rv,WC) 3 vars */
2181c4762a1bSJed Brown   for (k = 0; k < 3; ++k) {
2182c4762a1bSJed Brown     v[k] = 0.;
2183ad540459SPierre Jolivet     for (j = 0; j < 3; ++j) v[k] += rv[k][j] * wc[j];
2184c4762a1bSJed Brown   }
2185c4762a1bSJed Brown   return 0;
2186c4762a1bSJed Brown }
2187c4762a1bSJed Brown /* ---------------------------------------------------------------------- */
2188d71ae5a4SJacob Faibussowitsch int eigenvectors(PetscReal rv[][3], PetscReal lv[][3], const PetscReal ueq[], PetscReal gamma)
2189d71ae5a4SJacob Faibussowitsch {
2190c4762a1bSJed Brown   int       j, k;
2191c4762a1bSJed Brown   PetscReal rho, csnd, p0;
2192c4762a1bSJed Brown   /* PetscScalar u; */
2193c4762a1bSJed Brown 
21949371c9d4SSatish Balay   for (k = 0; k < 3; ++k)
21959371c9d4SSatish Balay     for (j = 0; j < 3; ++j) {
21969371c9d4SSatish Balay       lv[k][j] = 0.;
21979371c9d4SSatish Balay       rv[k][j] = 0.;
21989371c9d4SSatish Balay     }
2199c4762a1bSJed Brown   rho = ueq[0];
2200c4762a1bSJed Brown   /* u = ueq[1]; */
2201c4762a1bSJed Brown   p0       = ueq[2];
2202c4762a1bSJed Brown   csnd     = PetscSqrtReal(gamma * p0 / rho);
2203c4762a1bSJed Brown   lv[0][1] = rho * .5;
2204c4762a1bSJed Brown   lv[0][2] = -.5 / csnd;
2205c4762a1bSJed Brown   lv[1][0] = csnd;
2206c4762a1bSJed Brown   lv[1][2] = -1. / csnd;
2207c4762a1bSJed Brown   lv[2][1] = rho * .5;
2208c4762a1bSJed Brown   lv[2][2] = .5 / csnd;
2209c4762a1bSJed Brown   rv[0][0] = -1. / csnd;
2210c4762a1bSJed Brown   rv[1][0] = 1. / rho;
2211c4762a1bSJed Brown   rv[2][0] = -csnd;
2212c4762a1bSJed Brown   rv[0][1] = 1. / csnd;
2213c4762a1bSJed Brown   rv[0][2] = 1. / csnd;
2214c4762a1bSJed Brown   rv[1][2] = 1. / rho;
2215c4762a1bSJed Brown   rv[2][2] = csnd;
2216c4762a1bSJed Brown   return 0;
2217c4762a1bSJed Brown }
2218c4762a1bSJed Brown 
2219d71ae5a4SJacob Faibussowitsch int initLinearWave(EulerNode *ux, const PetscReal gamma, const PetscReal coord[], const PetscReal Lx)
2220d71ae5a4SJacob Faibussowitsch {
2221c4762a1bSJed Brown   PetscReal p0, u0, wcp[3], wc[3];
2222c4762a1bSJed Brown   PetscReal lv[3][3];
2223c4762a1bSJed Brown   PetscReal vp[3];
2224c4762a1bSJed Brown   PetscReal rv[3][3];
2225c4762a1bSJed Brown   PetscReal eps, ueq[3], rho0, twopi;
2226c4762a1bSJed Brown 
2227c4762a1bSJed Brown   /* Function Body */
2228c4762a1bSJed Brown   twopi  = 2. * PETSC_PI;
2229c4762a1bSJed Brown   eps    = 1e-4;    /* perturbation */
2230c4762a1bSJed Brown   rho0   = 1e3;     /* density of water */
2231c4762a1bSJed Brown   p0     = 101325.; /* init pressure of 1 atm (?) */
2232c4762a1bSJed Brown   u0     = 0.;
2233c4762a1bSJed Brown   ueq[0] = rho0;
2234c4762a1bSJed Brown   ueq[1] = u0;
2235c4762a1bSJed Brown   ueq[2] = p0;
2236c4762a1bSJed Brown   /* Project initial state to characteristic variables */
2237c4762a1bSJed Brown   eigenvectors(rv, lv, ueq, gamma);
2238c4762a1bSJed Brown   projecteqstate(wc, ueq, lv);
2239c4762a1bSJed Brown   wcp[0] = wc[0];
2240c4762a1bSJed Brown   wcp[1] = wc[1];
2241c4762a1bSJed Brown   wcp[2] = wc[2] + eps * PetscCosReal(coord[0] * 2. * twopi / Lx);
2242c4762a1bSJed Brown   projecttoprim(vp, wcp, rv);
2243c4762a1bSJed Brown   ux->r     = vp[0];         /* density */
2244c4762a1bSJed Brown   ux->ru[0] = vp[0] * vp[1]; /* x momentum */
2245c4762a1bSJed Brown   ux->ru[1] = 0.;
2246c4762a1bSJed Brown #if defined DIM > 2
2247c4762a1bSJed Brown   if (dim > 2) ux->ru[2] = 0.;
2248c4762a1bSJed Brown #endif
2249c4762a1bSJed Brown   /* E = rho * e + rho * v^2/2 = p/(gam-1) + rho*v^2/2 */
2250c4762a1bSJed Brown   ux->E = vp[2] / (gamma - 1.) + 0.5 * vp[0] * vp[1] * vp[1];
2251c4762a1bSJed Brown   return 0;
2252c4762a1bSJed Brown }
2253c4762a1bSJed Brown 
2254c4762a1bSJed Brown /*TEST
2255c4762a1bSJed Brown 
225630602db0SMatthew G. Knepley   testset:
225730602db0SMatthew G. Knepley     args: -dm_plex_adj_cone -dm_plex_adj_closure 0
225830602db0SMatthew G. Knepley 
225930602db0SMatthew G. Knepley     test:
226030602db0SMatthew G. Knepley       suffix: adv_2d_tri_0
226130602db0SMatthew G. Knepley       requires: triangle
226230602db0SMatthew G. Knepley       TODO: how did this ever get in main when there is no support for this
226330602db0SMatthew G. Knepley       args: -ufv_vtk_interval 0 -simplex -dm_refine 3 -dm_plex_faces 1,1 -dm_plex_separate_marker -bc_inflow 1,2,4 -bc_outflow 3
226430602db0SMatthew G. Knepley 
226530602db0SMatthew G. Knepley     test:
226630602db0SMatthew G. Knepley       suffix: adv_2d_tri_1
226730602db0SMatthew G. Knepley       requires: triangle
226830602db0SMatthew G. Knepley       TODO: how did this ever get in main when there is no support for this
226930602db0SMatthew G. Knepley       args: -ufv_vtk_interval 0 -simplex -dm_refine 5 -dm_plex_faces 1,1 -dm_plex_separate_marker -grid_bounds -0.5,0.5,-0.5,0.5 -bc_inflow 1,2,4 -bc_outflow 3 -advect_sol_type bump -advect_bump_center 0.25,0 -advect_bump_radius 0.1
227030602db0SMatthew G. Knepley 
227130602db0SMatthew G. Knepley     test:
227230602db0SMatthew G. Knepley       suffix: tut_1
227330602db0SMatthew G. Knepley       requires: exodusii
227430602db0SMatthew G. Knepley       nsize: 1
2275*c14a7e84SMatthew G. Knepley       args: -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/sevenside.exo -exodusii_check_reserved 0
227630602db0SMatthew G. Knepley 
227730602db0SMatthew G. Knepley     test:
227830602db0SMatthew G. Knepley       suffix: tut_2
227930602db0SMatthew G. Knepley       requires: exodusii
228030602db0SMatthew G. Knepley       nsize: 1
2281*c14a7e84SMatthew G. Knepley       args: -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/sevenside.exo -exodusii_check_reserved 0 -ts_type rosw
228230602db0SMatthew G. Knepley 
228330602db0SMatthew G. Knepley     test:
228430602db0SMatthew G. Knepley       suffix: tut_3
228530602db0SMatthew G. Knepley       requires: exodusii
228630602db0SMatthew G. Knepley       nsize: 4
2287e600fa54SMatthew G. Knepley       args: -dm_distribute_overlap 1 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/annulus-20.exo -monitor Error -advect_sol_type bump -petscfv_type leastsquares -petsclimiter_type sin
228830602db0SMatthew G. Knepley 
228930602db0SMatthew G. Knepley     test:
229030602db0SMatthew G. Knepley       suffix: tut_4
229130602db0SMatthew G. Knepley       requires: exodusii
229230602db0SMatthew G. Knepley       nsize: 4
2293e600fa54SMatthew G. Knepley       args: -dm_distribute_overlap 1 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/annulus-20.exo -physics sw -monitor Height,Energy -petscfv_type leastsquares -petsclimiter_type minmod
229430602db0SMatthew G. Knepley 
229530602db0SMatthew G. Knepley   testset:
229630602db0SMatthew G. Knepley     args: -dm_plex_adj_cone -dm_plex_adj_closure 0 -dm_plex_simplex 0 -dm_plex_box_faces 1,1,1
229730602db0SMatthew G. Knepley 
2298c4762a1bSJed Brown     # 2D Advection 0-10
2299c4762a1bSJed Brown     test:
2300c4762a1bSJed Brown       suffix: 0
2301c4762a1bSJed Brown       requires: exodusii
2302*c14a7e84SMatthew G. Knepley       args: -ufv_vtk_interval 0 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/sevenside.exo -exodusii_check_reserved 0
2303c4762a1bSJed Brown 
2304c4762a1bSJed Brown     test:
2305c4762a1bSJed Brown       suffix: 1
2306c4762a1bSJed Brown       requires: exodusii
230730602db0SMatthew G. Knepley       args: -ufv_vtk_interval 0 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/sevenside-quad-15.exo
2308c4762a1bSJed Brown 
2309c4762a1bSJed Brown     test:
2310c4762a1bSJed Brown       suffix: 2
2311c4762a1bSJed Brown       requires: exodusii
2312c4762a1bSJed Brown       nsize: 2
2313*c14a7e84SMatthew G. Knepley       args: -dm_distribute_overlap 1 -ufv_vtk_interval 0 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/sevenside.exo -exodusii_check_reserved 0
2314c4762a1bSJed Brown 
2315c4762a1bSJed Brown     test:
2316c4762a1bSJed Brown       suffix: 3
2317c4762a1bSJed Brown       requires: exodusii
2318c4762a1bSJed Brown       nsize: 2
2319e600fa54SMatthew G. Knepley       args: -dm_distribute_overlap 1 -ufv_vtk_interval 0 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/sevenside-quad-15.exo
2320c4762a1bSJed Brown 
2321c4762a1bSJed Brown     test:
2322c4762a1bSJed Brown       suffix: 4
2323c4762a1bSJed Brown       requires: exodusii
23246c2b77d5SStefano Zampini       nsize: 4
23256c2b77d5SStefano Zampini       args: -dm_distribute_overlap 1 -ufv_vtk_interval 0 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/sevenside-quad.exo -petscpartitioner_type simple
2326c4762a1bSJed Brown 
2327c4762a1bSJed Brown     test:
2328c4762a1bSJed Brown       suffix: 5
2329c4762a1bSJed Brown       requires: exodusii
2330*c14a7e84SMatthew G. Knepley       args: -ufv_vtk_interval 0 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/sevenside.exo -exodusii_check_reserved 0 -ts_type rosw -ts_adapt_reject_safety 1
2331c4762a1bSJed Brown 
2332c4762a1bSJed Brown     test:
2333c4762a1bSJed Brown       suffix: 7
2334c4762a1bSJed Brown       requires: exodusii
233530602db0SMatthew G. Knepley       args: -ufv_vtk_interval 0 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/sevenside-quad-15.exo -dm_refine 1
2336c4762a1bSJed Brown 
2337c4762a1bSJed Brown     test:
2338c4762a1bSJed Brown       suffix: 8
2339c4762a1bSJed Brown       requires: exodusii
2340c4762a1bSJed Brown       nsize: 2
2341e600fa54SMatthew G. Knepley       args: -dm_distribute_overlap 1 -ufv_vtk_interval 0 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/sevenside-quad-15.exo -dm_refine 1
2342c4762a1bSJed Brown 
2343c4762a1bSJed Brown     test:
2344c4762a1bSJed Brown       suffix: 9
2345c4762a1bSJed Brown       requires: exodusii
2346c4762a1bSJed Brown       nsize: 8
2347e600fa54SMatthew G. Knepley       args: -dm_distribute_overlap 1 -ufv_vtk_interval 0 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/sevenside-quad-15.exo -dm_refine 1
2348c4762a1bSJed Brown 
2349c4762a1bSJed Brown     test:
2350c4762a1bSJed Brown       suffix: 10
2351c4762a1bSJed Brown       requires: exodusii
235230602db0SMatthew G. Knepley       args: -ufv_vtk_interval 0 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/sevenside-quad.exo
2353c4762a1bSJed Brown 
2354c4762a1bSJed Brown   # 2D Shallow water
2355993a5519SMatthew G. Knepley   testset:
2356993a5519SMatthew G. Knepley     args: -physics sw -ufv_vtk_interval 0 -dm_plex_adj_cone -dm_plex_adj_closure 0
2357993a5519SMatthew G. Knepley 
2358c4762a1bSJed Brown     test:
2359c4762a1bSJed Brown       suffix: sw_0
2360c4762a1bSJed Brown       requires: exodusii
2361993a5519SMatthew G. Knepley       args: -bc_wall 100,101 -ufv_cfl 5 -petscfv_type leastsquares -petsclimiter_type sin \
2362993a5519SMatthew G. Knepley             -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/annulus-20.exo \
2363993a5519SMatthew G. Knepley             -ts_max_time 1 -ts_ssp_type rks2 -ts_ssp_nstages 10 \
2364993a5519SMatthew G. Knepley             -monitor height,energy
2365993a5519SMatthew G. Knepley 
2366993a5519SMatthew G. Knepley     test:
2367993a5519SMatthew G. Knepley       suffix: sw_1
2368993a5519SMatthew G. Knepley       nsize: 2
2369993a5519SMatthew G. Knepley       args: -bc_wall 1,3 -ufv_cfl 5 -petsclimiter_type sin \
2370993a5519SMatthew G. Knepley             -dm_plex_shape annulus -dm_plex_simplex 0 -dm_plex_box_faces 24,12 -dm_plex_box_lower 0,1 -dm_plex_box_upper 1,3 -dm_distribute_overlap 1 \
2371993a5519SMatthew G. Knepley             -ts_max_time 1 -ts_ssp_type rks2 -ts_ssp_nstages 10 \
2372993a5519SMatthew G. Knepley             -monitor height,energy
2373c4762a1bSJed Brown 
23748d2c18caSMukkund Sunjii     test:
23758d2c18caSMukkund Sunjii       suffix: sw_hll
2376993a5519SMatthew G. Knepley       args: -sw_riemann hll -bc_wall 1,2,3,4 -ufv_cfl 3 -petscfv_type leastsquares -petsclimiter_type sin \
2377993a5519SMatthew G. Knepley             -grid_bounds 0,5,0,5 -dm_plex_simplex 0 -dm_plex_box_faces 25,25 \
2378993a5519SMatthew G. Knepley             -ts_max_steps 5 -ts_ssp_type rks2 -ts_ssp_nstages 10 \
2379993a5519SMatthew G. Knepley             -monitor height,energy
2380993a5519SMatthew G. Knepley 
2381993a5519SMatthew G. Knepley   testset:
2382993a5519SMatthew G. Knepley     args: -dm_plex_adj_cone -dm_plex_adj_closure 0 -dm_plex_simplex 0 -dm_plex_box_faces 1,1,1
23838d2c18caSMukkund Sunjii 
2384c4762a1bSJed Brown     # 2D Advection: p4est
2385c4762a1bSJed Brown     test:
2386c4762a1bSJed Brown       suffix: p4est_advec_2d
2387c4762a1bSJed Brown       requires: p4est
238830602db0SMatthew G. Knepley       args: -ufv_vtk_interval 0 -dm_type p4est -dm_forest_minimum_refinement 1 -dm_forest_initial_refinement 2 -dm_p4est_refine_pattern hash   -dm_forest_maximum_refinement 5
2389c4762a1bSJed Brown 
2390c4762a1bSJed Brown     # Advection in a box
2391c4762a1bSJed Brown     test:
2392c4762a1bSJed Brown       suffix: adv_2d_quad_0
2393c4762a1bSJed Brown       args: -ufv_vtk_interval 0 -dm_refine 3 -dm_plex_separate_marker -bc_inflow 1,2,4 -bc_outflow 3
2394c4762a1bSJed Brown 
2395c4762a1bSJed Brown     test:
2396c4762a1bSJed Brown       suffix: adv_2d_quad_1
2397c4762a1bSJed Brown       args: -ufv_vtk_interval 0 -dm_refine 3 -dm_plex_separate_marker -grid_bounds -0.5,0.5,-0.5,0.5 -bc_inflow 1,2,4 -bc_outflow 3 -advect_sol_type bump -advect_bump_center 0.25,0 -advect_bump_radius 0.1
2398c4762a1bSJed Brown       timeoutfactor: 3
2399c4762a1bSJed Brown 
2400c4762a1bSJed Brown     test:
2401c4762a1bSJed Brown       suffix: adv_2d_quad_p4est_0
2402c4762a1bSJed Brown       requires: p4est
2403c4762a1bSJed Brown       args: -ufv_vtk_interval 0 -dm_refine 5 -dm_type p4est -dm_plex_separate_marker -bc_inflow 1,2,4 -bc_outflow 3
2404c4762a1bSJed Brown 
2405c4762a1bSJed Brown     test:
2406c4762a1bSJed Brown       suffix: adv_2d_quad_p4est_1
2407c4762a1bSJed Brown       requires: p4est
2408c4762a1bSJed Brown       args: -ufv_vtk_interval 0 -dm_refine 5 -dm_type p4est -dm_plex_separate_marker -grid_bounds -0.5,0.5,-0.5,0.5 -bc_inflow 1,2,4 -bc_outflow   3 -advect_sol_type bump -advect_bump_center 0.25,0 -advect_bump_radius 0.1
2409c4762a1bSJed Brown       timeoutfactor: 3
2410c4762a1bSJed Brown 
2411c4762a1bSJed Brown     test:
2412c4762a1bSJed Brown       suffix: adv_2d_quad_p4est_adapt_0
2413c4762a1bSJed Brown       requires: p4est !__float128 #broken for quad precision
2414c4762a1bSJed Brown       args: -ufv_vtk_interval 0 -dm_refine 3 -dm_type p4est -dm_plex_separate_marker -grid_bounds -0.5,0.5,-0.5,0.5 -bc_inflow 1,2,4 -bc_outflow   3 -advect_sol_type bump -advect_bump_center 0.25,0 -advect_bump_radius 0.1 -ufv_use_amr -refine_vec_tagger_box 0.005,inf -coarsen_vec_tagger_box   0,1.e-5 -petscfv_type leastsquares -ts_max_time 0.01
2415c4762a1bSJed Brown       timeoutfactor: 3
2416c4762a1bSJed Brown 
2417c4762a1bSJed Brown     test:
2418c4762a1bSJed Brown       suffix: adv_0
2419c4762a1bSJed Brown       requires: exodusii
2420*c14a7e84SMatthew G. Knepley       args: -ufv_vtk_interval 0 -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.exo -exodusii_check_reserved 0 -bc_inflow 100,101,200 -bc_outflow 201
2421c4762a1bSJed Brown 
2422c4762a1bSJed Brown     test:
2423c4762a1bSJed Brown       suffix: shock_0
2424c4762a1bSJed Brown       requires: p4est !single !complex
242530602db0SMatthew G. Knepley       args: -dm_plex_box_faces 2,1 -grid_bounds -1,1.,0.,1 -grid_skew_60 \
242630602db0SMatthew G. Knepley       -dm_type p4est -dm_forest_partition_overlap 1 -dm_forest_maximum_refinement 6 -dm_forest_minimum_refinement 2 -dm_forest_initial_refinement 2 \
242730602db0SMatthew G. Knepley       -ufv_use_amr -refine_vec_tagger_box 0.5,inf -coarsen_vec_tagger_box 0,1.e-2 -refine_tag_view -coarsen_tag_view \
242830602db0SMatthew G. Knepley       -bc_wall 1,2,3,4 -physics euler -eu_type iv_shock -ufv_cfl 10 -eu_alpha 60. -eu_gamma 1.4 -eu_amach 2.02 -eu_rho2 3. \
242930602db0SMatthew G. Knepley       -petscfv_type leastsquares -petsclimiter_type minmod -petscfv_compute_gradients 0 \
243030602db0SMatthew G. Knepley       -ts_max_time 0.5 -ts_ssp_type rks2 -ts_ssp_nstages 10 \
243130602db0SMatthew G. Knepley       -ufv_vtk_basename ${wPETSC_DIR}/ex11 -ufv_vtk_interval 0 -monitor density,energy
2432c4762a1bSJed Brown       timeoutfactor: 3
2433c4762a1bSJed Brown 
2434c4762a1bSJed Brown     # Test GLVis visualization of PetscFV fields
2435c4762a1bSJed Brown     test:
2436c4762a1bSJed Brown       suffix: glvis_adv_2d_tet
243730602db0SMatthew G. Knepley       args: -ufv_vtk_interval 0 -ufv_vtk_monitor 0 \
243830602db0SMatthew G. Knepley             -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/square_periodic.msh -dm_plex_gmsh_periodic 0 \
243930602db0SMatthew G. Knepley             -ts_monitor_solution glvis: -ts_max_steps 0
2440c4762a1bSJed Brown 
2441c4762a1bSJed Brown     test:
2442c4762a1bSJed Brown       suffix: glvis_adv_2d_quad
244330602db0SMatthew G. Knepley       args: -ufv_vtk_interval 0 -ufv_vtk_monitor 0 -bc_inflow 1,2,4 -bc_outflow 3 \
244430602db0SMatthew G. Knepley             -dm_refine 5 -dm_plex_separate_marker \
244530602db0SMatthew G. Knepley             -ts_monitor_solution glvis: -ts_max_steps 0
2446c4762a1bSJed Brown 
2447c4762a1bSJed Brown TEST*/
2448