xref: /petsc/src/ts/tutorials/ex76.c (revision 367970cfb6cf9c36f6dfab70c2904a544f7ea55d)
1649ef022SMatthew Knepley static char help[] = "Time-dependent Low Mach Flow in 2d and 3d channels with finite elements.\n\
2444129b9SMatthew G. Knepley We solve the Low Mach flow problem for both conducting and non-conducting fluids,\n\
3444129b9SMatthew G. Knepley using a parallel unstructured mesh (DMPLEX) to discretize it.\n\n\n";
4649ef022SMatthew Knepley 
5649ef022SMatthew Knepley /*F
6444129b9SMatthew G. Knepley The non-conducting Low Mach flow is time-dependent isoviscous Navier-Stokes flow. We discretize using the
7649ef022SMatthew Knepley finite element method on an unstructured mesh. The weak form equations are
8649ef022SMatthew Knepley 
9649ef022SMatthew Knepley \begin{align*}
10649ef022SMatthew Knepley     < q, \nabla\cdot u > = 0
11649ef022SMatthew Knepley     <v, du/dt> + <v, u \cdot \nabla u> + < \nabla v, \nu (\nabla u + {\nabla u}^T) > - < \nabla\cdot v, p >  - < v, f  >  = 0
12649ef022SMatthew Knepley     < w, u \cdot \nabla T > + < \nabla w, \alpha \nabla T > - < w, Q > = 0
13649ef022SMatthew Knepley \end{align*}
14649ef022SMatthew Knepley 
15649ef022SMatthew Knepley where $\nu$ is the kinematic viscosity and $\alpha$ is thermal diffusivity.
16649ef022SMatthew Knepley 
17444129b9SMatthew G. Knepley The conducting form is given in the ABLATE documentation [1,2] and derived in Principe and Codina [2].
18444129b9SMatthew G. Knepley 
19649ef022SMatthew Knepley For visualization, use
20649ef022SMatthew Knepley 
21649ef022SMatthew Knepley   -dm_view hdf5:$PWD/sol.h5 -sol_vec_view hdf5:$PWD/sol.h5::append -exact_vec_view hdf5:$PWD/sol.h5::append
22444129b9SMatthew G. Knepley 
23444129b9SMatthew G. Knepley [1] https://ubchrest.github.io/ablate/content/formulations/lowMachFlow/
24444129b9SMatthew G. Knepley [2] https://github.com/UBCHREST/ablate/blob/main/ablateCore/flow/lowMachFlow.c
25444129b9SMatthew G. Knepley [3] J. Principe and R. Codina, "Mathematical models for thermally coupled low speed flows", Adv. in Theo. and App. Mech., 2(1), pp.93--112, 2009.
26649ef022SMatthew Knepley F*/
27649ef022SMatthew Knepley 
28649ef022SMatthew Knepley #include <petscdmplex.h>
29649ef022SMatthew Knepley #include <petscsnes.h>
30649ef022SMatthew Knepley #include <petscts.h>
31649ef022SMatthew Knepley #include <petscds.h>
32649ef022SMatthew Knepley #include <petscbag.h>
33649ef022SMatthew Knepley 
34444129b9SMatthew G. Knepley typedef enum {MOD_INCOMPRESSIBLE, MOD_CONDUCTING, NUM_MOD_TYPES} ModType;
35444129b9SMatthew G. Knepley const char *modTypes[NUM_MOD_TYPES+1] = {"incompressible", "conducting", "unknown"};
36444129b9SMatthew G. Knepley 
37*367970cfSMatthew G. Knepley typedef enum {SOL_QUADRATIC, SOL_CUBIC, SOL_CUBIC_TRIG, SOL_TAYLOR_GREEN, SOL_PIPE, SOL_PIPE_WIGGLY, NUM_SOL_TYPES} SolType;
38*367970cfSMatthew G. Knepley const char *solTypes[NUM_SOL_TYPES+1] = {"quadratic", "cubic", "cubic_trig", "taylor_green", "pipe", "pipe_wiggly", "unknown"};
39444129b9SMatthew G. Knepley 
40444129b9SMatthew G. Knepley /* Fields */
41444129b9SMatthew G. Knepley const PetscInt VEL      = 0;
42444129b9SMatthew G. Knepley const PetscInt PRES     = 1;
43444129b9SMatthew G. Knepley const PetscInt TEMP     = 2;
44444129b9SMatthew G. Knepley /* Sources */
45444129b9SMatthew G. Knepley const PetscInt MOMENTUM = 0;
46444129b9SMatthew G. Knepley const PetscInt MASS     = 1;
47444129b9SMatthew G. Knepley const PetscInt ENERGY   = 2;
48444129b9SMatthew G. Knepley /* Constants */
49444129b9SMatthew G. Knepley const PetscInt STROUHAL = 0;
50444129b9SMatthew G. Knepley const PetscInt FROUDE   = 1;
51444129b9SMatthew G. Knepley const PetscInt REYNOLDS = 2;
52444129b9SMatthew G. Knepley const PetscInt PECLET   = 3;
53444129b9SMatthew G. Knepley const PetscInt P_TH     = 4;
54444129b9SMatthew G. Knepley const PetscInt MU       = 5;
55444129b9SMatthew G. Knepley const PetscInt NU       = 6;
56444129b9SMatthew G. Knepley const PetscInt C_P      = 7;
57444129b9SMatthew G. Knepley const PetscInt K        = 8;
58444129b9SMatthew G. Knepley const PetscInt ALPHA    = 9;
59444129b9SMatthew G. Knepley const PetscInt T_IN     = 10;
60444129b9SMatthew G. Knepley const PetscInt G_DIR    = 11;
61*367970cfSMatthew G. Knepley const PetscInt EPSILON  = 12;
62649ef022SMatthew Knepley 
63649ef022SMatthew Knepley typedef struct {
64444129b9SMatthew G. Knepley   PetscReal Strouhal; /* Strouhal number */
65444129b9SMatthew G. Knepley   PetscReal Froude;   /* Froude number */
66444129b9SMatthew G. Knepley   PetscReal Reynolds; /* Reynolds number */
67444129b9SMatthew G. Knepley   PetscReal Peclet;   /* Peclet number */
68444129b9SMatthew G. Knepley   PetscReal p_th;     /* Thermodynamic pressure */
69444129b9SMatthew G. Knepley   PetscReal mu;       /* Dynamic viscosity */
70649ef022SMatthew Knepley   PetscReal nu;       /* Kinematic viscosity */
71444129b9SMatthew G. Knepley   PetscReal c_p;      /* Specific heat at constant pressure */
72444129b9SMatthew G. Knepley   PetscReal k;        /* Thermal conductivity */
73649ef022SMatthew Knepley   PetscReal alpha;    /* Thermal diffusivity */
74649ef022SMatthew Knepley   PetscReal T_in;     /* Inlet temperature */
75444129b9SMatthew G. Knepley   PetscReal g_dir;    /* Gravity direction */
76*367970cfSMatthew G. Knepley   PetscReal epsilon;  /* Strength of perturbation */
77649ef022SMatthew Knepley } Parameter;
78649ef022SMatthew Knepley 
79649ef022SMatthew Knepley typedef struct {
80649ef022SMatthew Knepley   /* Problem definition */
81649ef022SMatthew Knepley   PetscBag  bag;          /* Holds problem parameters */
82444129b9SMatthew G. Knepley   ModType   modType;      /* Model type */
83649ef022SMatthew Knepley   SolType   solType;      /* MMS solution type */
84444129b9SMatthew G. Knepley   PetscBool hasNullSpace; /* Problem has the constant null space for pressure */
85a712f3bbSMatthew G. Knepley   /* Flow diagnostics */
86a712f3bbSMatthew G. Knepley   DM        dmCell;       /* A DM with piecewise constant discretization */
87649ef022SMatthew Knepley } AppCtx;
88649ef022SMatthew Knepley 
89649ef022SMatthew Knepley static PetscErrorCode zero(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
90649ef022SMatthew Knepley {
91649ef022SMatthew Knepley   PetscInt d;
92649ef022SMatthew Knepley   for (d = 0; d < Nc; ++d) u[d] = 0.0;
93649ef022SMatthew Knepley   return 0;
94649ef022SMatthew Knepley }
95649ef022SMatthew Knepley 
96649ef022SMatthew Knepley static PetscErrorCode constant(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx)
97649ef022SMatthew Knepley {
98649ef022SMatthew Knepley   PetscInt d;
99649ef022SMatthew Knepley   for (d = 0; d < Nc; ++d) u[d] = 1.0;
100649ef022SMatthew Knepley   return 0;
101649ef022SMatthew Knepley }
102649ef022SMatthew Knepley 
103649ef022SMatthew Knepley /*
104649ef022SMatthew Knepley   CASE: quadratic
105649ef022SMatthew Knepley   In 2D we use exact solution:
106649ef022SMatthew Knepley 
107649ef022SMatthew Knepley     u = t + x^2 + y^2
108649ef022SMatthew Knepley     v = t + 2x^2 - 2xy
109649ef022SMatthew Knepley     p = x + y - 1
110444129b9SMatthew G. Knepley     T = t + x + y + 1
111649ef022SMatthew Knepley     f = <t (2x + 2y) + 2x^3 + 4x^2y - 2xy^2 -4\nu + 2, t (2x - 2y) + 4xy^2 + 2x^2y - 2y^3 -4\nu + 2>
112649ef022SMatthew Knepley     Q = 1 + 2t + 3x^2 - 2xy + y^2
113649ef022SMatthew Knepley 
114649ef022SMatthew Knepley   so that
115649ef022SMatthew Knepley 
116649ef022SMatthew Knepley     \nabla \cdot u = 2x - 2x = 0
117649ef022SMatthew Knepley 
118649ef022SMatthew Knepley   f = du/dt + u \cdot \nabla u - \nu \Delta u + \nabla p
119649ef022SMatthew Knepley     = <1, 1> + <t + x^2 + y^2, t + 2x^2 - 2xy> . <<2x, 4x - 2y>, <2y, -2x>> - \nu <4, 4> + <1, 1>
120649ef022SMatthew Knepley     = <t (2x + 2y) + 2x^3 + 4x^2y - 2xy^2, t (2x - 2y) + 2x^2y + 4xy^2 - 2y^3> + <-4 \nu + 2, -4\nu + 2>
121649ef022SMatthew Knepley     = <t (2x + 2y) + 2x^3 + 4x^2y - 2xy^2 - 4\nu + 2, t (2x - 2y) + 4xy^2 + 2x^2y - 2y^3 - 4\nu + 2>
122649ef022SMatthew Knepley 
123649ef022SMatthew Knepley   Q = dT/dt + u \cdot \nabla T - \alpha \Delta T
124649ef022SMatthew Knepley     = 1 + <t + x^2 + y^2, t + 2x^2 - 2xy> . <1, 1> - \alpha 0
125649ef022SMatthew Knepley     = 1 + 2t + 3x^2 - 2xy + y^2
126649ef022SMatthew Knepley */
127649ef022SMatthew Knepley 
128649ef022SMatthew Knepley static PetscErrorCode quadratic_u(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
129649ef022SMatthew Knepley {
130649ef022SMatthew Knepley   u[0] = time + X[0]*X[0] + X[1]*X[1];
131649ef022SMatthew Knepley   u[1] = time + 2.0*X[0]*X[0] - 2.0*X[0]*X[1];
132649ef022SMatthew Knepley   return 0;
133649ef022SMatthew Knepley }
134649ef022SMatthew Knepley static PetscErrorCode quadratic_u_t(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
135649ef022SMatthew Knepley {
136649ef022SMatthew Knepley   u[0] = 1.0;
137649ef022SMatthew Knepley   u[1] = 1.0;
138649ef022SMatthew Knepley   return 0;
139649ef022SMatthew Knepley }
140649ef022SMatthew Knepley 
141649ef022SMatthew Knepley static PetscErrorCode quadratic_p(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *p, void *ctx)
142649ef022SMatthew Knepley {
143649ef022SMatthew Knepley   p[0] = X[0] + X[1] - 1.0;
144649ef022SMatthew Knepley   return 0;
145649ef022SMatthew Knepley }
146649ef022SMatthew Knepley 
147649ef022SMatthew Knepley static PetscErrorCode quadratic_T(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *T, void *ctx)
148649ef022SMatthew Knepley {
149444129b9SMatthew G. Knepley   T[0] = time + X[0] + X[1] + 1.0;
150649ef022SMatthew Knepley   return 0;
151649ef022SMatthew Knepley }
152649ef022SMatthew Knepley static PetscErrorCode quadratic_T_t(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *T, void *ctx)
153649ef022SMatthew Knepley {
154649ef022SMatthew Knepley   T[0] = 1.0;
155649ef022SMatthew Knepley   return 0;
156649ef022SMatthew Knepley }
157649ef022SMatthew Knepley 
158649ef022SMatthew Knepley static void f0_quadratic_v(PetscInt dim, PetscInt Nf, PetscInt NfAux,
159649ef022SMatthew Knepley                            const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
160649ef022SMatthew Knepley                            const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
161649ef022SMatthew Knepley                            PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
162649ef022SMatthew Knepley {
163444129b9SMatthew G. Knepley   const PetscReal nu = PetscRealPart(constants[NU]);
164649ef022SMatthew Knepley 
165444129b9SMatthew G. Knepley   f0[0] -= t*(2*X[0] + 2*X[1]) + 2*X[0]*X[0]*X[0] + 4*X[0]*X[0]*X[1] - 2*X[0]*X[1]*X[1] - 4.0*nu + 2;
166444129b9SMatthew G. Knepley   f0[1] -= t*(2*X[0] - 2*X[1]) + 4*X[0]*X[1]*X[1] + 2*X[0]*X[0]*X[1] - 2*X[1]*X[1]*X[1] - 4.0*nu + 2;
167649ef022SMatthew Knepley }
168649ef022SMatthew Knepley 
169649ef022SMatthew Knepley static void f0_quadratic_w(PetscInt dim, PetscInt Nf, PetscInt NfAux,
170649ef022SMatthew Knepley                            const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
171649ef022SMatthew Knepley                            const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
172649ef022SMatthew Knepley                            PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
173649ef022SMatthew Knepley {
174444129b9SMatthew G. Knepley   f0[0] -= 2*t + 1 + 3*X[0]*X[0] - 2*X[0]*X[1] + X[1]*X[1];
175444129b9SMatthew G. Knepley }
176444129b9SMatthew G. Knepley 
177444129b9SMatthew G. Knepley /*
178444129b9SMatthew G. Knepley   CASE: quadratic
179444129b9SMatthew G. Knepley   In 2D we use exact solution:
180444129b9SMatthew G. Knepley 
181444129b9SMatthew G. Knepley     u = t + x^2 + y^2
182444129b9SMatthew G. Knepley     v = t + 2x^2 - 2xy
183444129b9SMatthew G. Knepley     p = x + y - 1
184444129b9SMatthew G. Knepley     T = t + x + y + 1
185444129b9SMatthew G. Knepley   rho = p^{th} / T
186444129b9SMatthew G. Knepley 
187444129b9SMatthew G. Knepley   so that
188444129b9SMatthew G. Knepley 
189444129b9SMatthew G. Knepley     \nabla \cdot u = 2x - 2x = 0
190444129b9SMatthew G. Knepley     grad u = <<2 x, 4x - 2y>, <2 y, -2x>>
191444129b9SMatthew G. Knepley     epsilon(u) = 1/2 (grad u + grad u^T) = <<2x, 2x>, <2x, -2x>>
192444129b9SMatthew G. Knepley     epsilon'(u) = epsilon(u) - 1/3 (div u) I = epsilon(u)
193444129b9SMatthew G. Knepley     div epsilon'(u) = <2, 2>
194444129b9SMatthew G. Knepley 
195444129b9SMatthew G. Knepley   f = rho S du/dt + rho u \cdot \nabla u - 2\mu/Re div \epsilon'(u) + \nabla p + rho / F^2 \hat y
196444129b9SMatthew G. Knepley     = rho S <1, 1> + rho <t + x^2 + y^2, t + 2x^2 - 2xy> . <<2x, 4x - 2y>, <2y, -2x>> - 2\mu/Re <2, 2> + <1, 1> + rho/F^2 <0, 1>
197444129b9SMatthew G. Knepley     = rho S <1, 1> + rho <t (2x + 2y) + 2x^3 + 4x^2y - 2xy^2, t (2x - 2y) + 2x^2y + 4xy^2 - 2y^3> - mu/Re <4, 4> + <1, 1> + rho/F^2 <0, 1>
198444129b9SMatthew G. Knepley 
199444129b9SMatthew G. Knepley   g = S rho_t + div (rho u)
200444129b9SMatthew G. Knepley     = -S pth T_t/T^2 + rho div (u) + u . grad rho
201444129b9SMatthew G. Knepley     = -S pth 1/T^2 - pth u . grad T / T^2
202444129b9SMatthew G. Knepley     = -pth / T^2 (S + 2t + 3 x^2 - 2xy + y^2)
203444129b9SMatthew G. Knepley 
204444129b9SMatthew G. Knepley   Q = rho c_p S dT/dt + rho c_p u . grad T - 1/Pe div k grad T
205444129b9SMatthew G. Knepley     = c_p S pth / T + c_p pth (2t + 3 x^2 - 2xy + y^2) / T - k/Pe 0
206444129b9SMatthew G. Knepley     = c_p pth / T (S + 2t + 3 x^2 - 2xy + y^2)
207444129b9SMatthew G. Knepley */
208444129b9SMatthew G. Knepley static void f0_conduct_quadratic_v(PetscInt dim, PetscInt Nf, PetscInt NfAux,
209444129b9SMatthew G. Knepley                                    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
210444129b9SMatthew G. Knepley                                    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
211444129b9SMatthew G. Knepley                                    PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
212444129b9SMatthew G. Knepley {
213444129b9SMatthew G. Knepley   const PetscReal S    = PetscRealPart(constants[STROUHAL]);
214444129b9SMatthew G. Knepley   const PetscReal F    = PetscRealPart(constants[FROUDE]);
215444129b9SMatthew G. Knepley   const PetscReal Re   = PetscRealPart(constants[REYNOLDS]);
216444129b9SMatthew G. Knepley   const PetscReal mu   = PetscRealPart(constants[MU]);
217444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
218444129b9SMatthew G. Knepley   const PetscReal rho  = p_th / (t + X[0] + X[1] + 1.);
219444129b9SMatthew G. Knepley   const PetscInt  gd   = (PetscInt) PetscRealPart(constants[G_DIR]);
220444129b9SMatthew G. Knepley 
221444129b9SMatthew G. Knepley   f0[0]  -= rho * S + rho * (2.*t*(X[0] + X[1]) + 2.*X[0]*X[0]*X[0] + 4.*X[0]*X[0]*X[1] - 2.*X[0]*X[1]*X[1]) - 4.*mu/Re + 1.;
222444129b9SMatthew G. Knepley   f0[1]  -= rho * S + rho * (2.*t*(X[0] - X[1]) + 2.*X[0]*X[0]*X[1] + 4.*X[0]*X[1]*X[1] - 2.*X[1]*X[1]*X[1]) - 4.*mu/Re + 1.;
223444129b9SMatthew G. Knepley   f0[gd] -= rho/PetscSqr(F);
224444129b9SMatthew G. Knepley }
225444129b9SMatthew G. Knepley 
226444129b9SMatthew G. Knepley static void f0_conduct_quadratic_q(PetscInt dim, PetscInt Nf, PetscInt NfAux,
227444129b9SMatthew G. Knepley                                    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
228444129b9SMatthew G. Knepley                                    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
229444129b9SMatthew G. Knepley                                    PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
230444129b9SMatthew G. Knepley {
231444129b9SMatthew G. Knepley   const PetscReal S    = PetscRealPart(constants[STROUHAL]);
232444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
233444129b9SMatthew G. Knepley 
234444129b9SMatthew G. Knepley   f0[0] += p_th * (S + 2.*t + 3.*X[0]*X[0] - 2.*X[0]*X[1] + X[1]*X[1]) / PetscSqr(t + X[0] + X[1] + 1.);
235444129b9SMatthew G. Knepley }
236444129b9SMatthew G. Knepley 
237444129b9SMatthew G. Knepley static void f0_conduct_quadratic_w(PetscInt dim, PetscInt Nf, PetscInt NfAux,
238444129b9SMatthew G. Knepley                                    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
239444129b9SMatthew G. Knepley                                    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
240444129b9SMatthew G. Knepley                                    PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
241444129b9SMatthew G. Knepley {
242444129b9SMatthew G. Knepley   const PetscReal S    = PetscRealPart(constants[STROUHAL]);
243444129b9SMatthew G. Knepley   const PetscReal c_p  = PetscRealPart(constants[C_P]);
244444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
245444129b9SMatthew G. Knepley 
246444129b9SMatthew G. Knepley   f0[0] -= c_p*p_th * (S + 2.*t + 3.*X[0]*X[0] - 2.*X[0]*X[1] + X[1]*X[1]) / (t + X[0] + X[1] + 1.);
247649ef022SMatthew Knepley }
248649ef022SMatthew Knepley 
249649ef022SMatthew Knepley /*
250649ef022SMatthew Knepley   CASE: cubic
251649ef022SMatthew Knepley   In 2D we use exact solution:
252649ef022SMatthew Knepley 
253649ef022SMatthew Knepley     u = t + x^3 + y^3
254649ef022SMatthew Knepley     v = t + 2x^3 - 3x^2y
255649ef022SMatthew Knepley     p = 3/2 x^2 + 3/2 y^2 - 1
256649ef022SMatthew Knepley     T = t + 1/2 x^2 + 1/2 y^2
257649ef022SMatthew Knepley     f = < t(3x^2 + 3y^2) + 3x^5 + 6x^3y^2 - 6x^2y^3 - \nu(6x + 6y) + 3x + 1,
258649ef022SMatthew Knepley           t(3x^2 - 6xy) + 6x^2y^3 + 3x^4y - 6xy^4 - \nu(12x - 6y) + 3y + 1>
259649ef022SMatthew Knepley     Q = x^4 + xy^3 + 2x^3y - 3x^2y^2 + xt + yt - 2\alpha + 1
260649ef022SMatthew Knepley 
261649ef022SMatthew Knepley   so that
262649ef022SMatthew Knepley 
263649ef022SMatthew Knepley     \nabla \cdot u = 3x^2 - 3x^2 = 0
264649ef022SMatthew Knepley 
265649ef022SMatthew Knepley   du/dt + u \cdot \nabla u - \nu \Delta u + \nabla p - f
266649ef022SMatthew Knepley   = <1,1> + <t(3x^2 + 3y^2) + 3x^5 + 6x^3y^2 - 6x^2y^3, t(3x^2 - 6xy) + 6x^2y^3 + 3x^4y - 6xy^4> - \nu<6x + 6y, 12x - 6y> + <3x, 3y> - <t(3x^2 + 3y^2) + 3x^5 + 6x^3y^2 - 6x^2y^3 - \nu(6x + 6y) + 3x + 1, t(3x^2 - 6xy) + 6x^2y^3 + 3x^4y - 6xy^4 - \nu(12x - 6y) + 3y + 1>  = 0
267649ef022SMatthew Knepley 
268649ef022SMatthew Knepley   dT/dt + u \cdot \nabla T - \alpha \Delta T - Q = 1 + (x^3 + y^3) x + (2x^3 - 3x^2y) y - 2*\alpha - (x^4 + xy^3 + 2x^3y - 3x^2y^2 - 2*\alpha +1)   = 0
269649ef022SMatthew Knepley */
270649ef022SMatthew Knepley static PetscErrorCode cubic_u(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
271649ef022SMatthew Knepley {
272649ef022SMatthew Knepley   u[0] = time + X[0]*X[0]*X[0] + X[1]*X[1]*X[1];
273649ef022SMatthew Knepley   u[1] = time + 2.0*X[0]*X[0]*X[0] - 3.0*X[0]*X[0]*X[1];
274649ef022SMatthew Knepley   return 0;
275649ef022SMatthew Knepley }
276649ef022SMatthew Knepley static PetscErrorCode cubic_u_t(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
277649ef022SMatthew Knepley {
278649ef022SMatthew Knepley   u[0] = 1.0;
279649ef022SMatthew Knepley   u[1] = 1.0;
280649ef022SMatthew Knepley   return 0;
281649ef022SMatthew Knepley }
282649ef022SMatthew Knepley 
283649ef022SMatthew Knepley static PetscErrorCode cubic_p(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *p, void *ctx)
284649ef022SMatthew Knepley {
285649ef022SMatthew Knepley   p[0] = 3.0*X[0]*X[0]/2.0 + 3.0*X[1]*X[1]/2.0 - 1.0;
286649ef022SMatthew Knepley   return 0;
287649ef022SMatthew Knepley }
288649ef022SMatthew Knepley 
289649ef022SMatthew Knepley static PetscErrorCode cubic_T(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *T, void *ctx)
290649ef022SMatthew Knepley {
291649ef022SMatthew Knepley   T[0] = time + X[0]*X[0]/2.0 + X[1]*X[1]/2.0;
292649ef022SMatthew Knepley   return 0;
293649ef022SMatthew Knepley }
294649ef022SMatthew Knepley static PetscErrorCode cubic_T_t(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *T, void *ctx)
295649ef022SMatthew Knepley {
296649ef022SMatthew Knepley   T[0] = 1.0;
297649ef022SMatthew Knepley   return 0;
298649ef022SMatthew Knepley }
299649ef022SMatthew Knepley 
300649ef022SMatthew Knepley static void f0_cubic_v(PetscInt dim, PetscInt Nf, PetscInt NfAux,
301649ef022SMatthew Knepley                        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
302649ef022SMatthew Knepley                        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
303649ef022SMatthew Knepley                        PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
304649ef022SMatthew Knepley {
305444129b9SMatthew G. Knepley   const PetscReal nu = PetscRealPart(constants[NU]);
306649ef022SMatthew Knepley 
307649ef022SMatthew Knepley   f0[0] -= (t*(3*X[0]*X[0] + 3*X[1]*X[1]) + 3*X[0]*X[0]*X[0]*X[0]*X[0] + 6*X[0]*X[0]*X[0]*X[1]*X[1] - 6*X[0]*X[0]*X[1]*X[1]*X[1] - ( 6*X[0] + 6*X[1])*nu + 3*X[0] + 1);
308649ef022SMatthew Knepley   f0[1] -= (t*(3*X[0]*X[0] - 6*X[0]*X[1]) + 3*X[0]*X[0]*X[0]*X[0]*X[1] + 6*X[0]*X[0]*X[1]*X[1]*X[1] - 6*X[0]*X[1]*X[1]*X[1]*X[1] - (12*X[0] - 6*X[1])*nu + 3*X[1] + 1);
309649ef022SMatthew Knepley }
310649ef022SMatthew Knepley 
311649ef022SMatthew Knepley static void f0_cubic_w(PetscInt dim, PetscInt Nf, PetscInt NfAux,
312649ef022SMatthew Knepley                        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
313649ef022SMatthew Knepley                        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
314649ef022SMatthew Knepley                        PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
315649ef022SMatthew Knepley {
316444129b9SMatthew G. Knepley   const PetscReal alpha = PetscRealPart(constants[ALPHA]);
317649ef022SMatthew Knepley 
318444129b9SMatthew G. Knepley   f0[0] -= X[0]*X[0]*X[0]*X[0] + 2.0*X[0]*X[0]*X[0]*X[1] - 3.0*X[0]*X[0]*X[1]*X[1] + X[0]*X[1]*X[1]*X[1] + X[0]*t + X[1]*t - 2.0*alpha + 1;
319649ef022SMatthew Knepley }
320649ef022SMatthew Knepley 
321649ef022SMatthew Knepley /*
322649ef022SMatthew Knepley   CASE: cubic-trigonometric
323649ef022SMatthew Knepley   In 2D we use exact solution:
324649ef022SMatthew Knepley 
325649ef022SMatthew Knepley     u = beta cos t + x^3 + y^3
326649ef022SMatthew Knepley     v = beta sin t + 2x^3 - 3x^2y
327649ef022SMatthew Knepley     p = 3/2 x^2 + 3/2 y^2 - 1
328649ef022SMatthew Knepley     T = 20 cos t + 1/2 x^2 + 1/2 y^2
329649ef022SMatthew Knepley     f = < beta cos t 3x^2         + beta sin t (3y^2 - 1) + 3x^5 + 6x^3y^2 - 6x^2y^3 - \nu(6x + 6y)  + 3x,
330649ef022SMatthew Knepley           beta cos t (6x^2 - 6xy) - beta sin t (3x^2)     + 3x^4y + 6x^2y^3 - 6xy^4  - \nu(12x - 6y) + 3y>
331649ef022SMatthew Knepley     Q = beta cos t x + beta sin t (y - 1) + x^4 + 2x^3y - 3x^2y^2 + xy^3 - 2\alpha
332649ef022SMatthew Knepley 
333649ef022SMatthew Knepley   so that
334649ef022SMatthew Knepley 
335649ef022SMatthew Knepley     \nabla \cdot u = 3x^2 - 3x^2 = 0
336649ef022SMatthew Knepley 
337649ef022SMatthew Knepley   f = du/dt + u \cdot \nabla u - \nu \Delta u + \nabla p
338649ef022SMatthew Knepley     = <-sin t, cos t> + <cos t + x^3 + y^3, sin t + 2x^3 - 3x^2y> <<3x^2, 6x^2 - 6xy>, <3y^2, -3x^2>> - \nu <6x + 6y, 12x - 6y> + <3x, 3y>
339649ef022SMatthew Knepley     = <-sin t, cos t> + <cos t 3x^2 + 3x^5 + 3x^2y^3 + sin t 3y^2 + 6x^3y^2 - 9x^2y^3, cos t (6x^2 - 6xy) + 6x^5 - 6x^4y + 6x^2y^3 - 6xy^4 + sin t (-3x^2) - 6x^5 + 9x^4y> - \nu <6x + 6y, 12x - 6y> + <3x, 3y>
340649ef022SMatthew Knepley     = <cos t (3x^2)       + sin t (3y^2 - 1) + 3x^5 + 6x^3y^2 - 6x^2y^3 - \nu (6x + 6y)  + 3x,
341649ef022SMatthew Knepley        cos t (6x^2 - 6xy) - sin t (3x^2)     + 3x^4y + 6x^2y^3 - 6xy^4  - \nu (12x - 6y) + 3y>
342649ef022SMatthew Knepley 
343649ef022SMatthew Knepley   Q = dT/dt + u \cdot \nabla T - \alpha \Delta T
344649ef022SMatthew Knepley     = -sin t + <cos t + x^3 + y^3, sin t + 2x^3 - 3x^2y> . <x, y> - 2 \alpha
345649ef022SMatthew Knepley     = -sin t + cos t (x) + x^4 + xy^3 + sin t (y) + 2x^3y - 3x^2y^2 - 2 \alpha
346649ef022SMatthew Knepley     = cos t x + sin t (y - 1) + (x^4 + 2x^3y - 3x^2y^2 + xy^3 - 2 \alpha)
347649ef022SMatthew Knepley */
348649ef022SMatthew Knepley static PetscErrorCode cubic_trig_u(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
349649ef022SMatthew Knepley {
350649ef022SMatthew Knepley   u[0] = 100.*PetscCosReal(time) + X[0]*X[0]*X[0] + X[1]*X[1]*X[1];
351649ef022SMatthew Knepley   u[1] = 100.*PetscSinReal(time) + 2.0*X[0]*X[0]*X[0] - 3.0*X[0]*X[0]*X[1];
352649ef022SMatthew Knepley   return 0;
353649ef022SMatthew Knepley }
354649ef022SMatthew Knepley static PetscErrorCode cubic_trig_u_t(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
355649ef022SMatthew Knepley {
356649ef022SMatthew Knepley   u[0] = -100.*PetscSinReal(time);
357649ef022SMatthew Knepley   u[1] =  100.*PetscCosReal(time);
358649ef022SMatthew Knepley   return 0;
359649ef022SMatthew Knepley }
360649ef022SMatthew Knepley 
361649ef022SMatthew Knepley static PetscErrorCode cubic_trig_p(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *p, void *ctx)
362649ef022SMatthew Knepley {
363649ef022SMatthew Knepley   p[0] = 3.0*X[0]*X[0]/2.0 + 3.0*X[1]*X[1]/2.0 - 1.0;
364649ef022SMatthew Knepley   return 0;
365649ef022SMatthew Knepley }
366649ef022SMatthew Knepley 
367649ef022SMatthew Knepley static PetscErrorCode cubic_trig_T(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *T, void *ctx)
368649ef022SMatthew Knepley {
369649ef022SMatthew Knepley   T[0] = 100.*PetscCosReal(time) + X[0]*X[0]/2.0 + X[1]*X[1]/2.0;
370649ef022SMatthew Knepley   return 0;
371649ef022SMatthew Knepley }
372649ef022SMatthew Knepley static PetscErrorCode cubic_trig_T_t(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *T, void *ctx)
373649ef022SMatthew Knepley {
374649ef022SMatthew Knepley   T[0] = -100.*PetscSinReal(time);
375649ef022SMatthew Knepley   return 0;
376649ef022SMatthew Knepley }
377649ef022SMatthew Knepley 
378649ef022SMatthew Knepley static void f0_cubic_trig_v(PetscInt dim, PetscInt Nf, PetscInt NfAux,
379649ef022SMatthew Knepley                             const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
380649ef022SMatthew Knepley                             const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
381649ef022SMatthew Knepley                             PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
382649ef022SMatthew Knepley {
383444129b9SMatthew G. Knepley   const PetscReal nu = PetscRealPart(constants[NU]);
384649ef022SMatthew Knepley 
385649ef022SMatthew Knepley   f0[0] -= 100.*PetscCosReal(t)*(3*X[0]*X[0])               + 100.*PetscSinReal(t)*(3*X[1]*X[1] - 1.) + 3*X[0]*X[0]*X[0]*X[0]*X[0] + 6*X[0]*X[0]*X[0]*X[1]*X[1] - 6*X[0]*X[0]*X[1]*X[1]*X[1] - ( 6*X[0] + 6*X[1])*nu + 3*X[0];
386649ef022SMatthew Knepley   f0[1] -= 100.*PetscCosReal(t)*(6*X[0]*X[0] - 6*X[0]*X[1]) - 100.*PetscSinReal(t)*(3*X[0]*X[0])      + 3*X[0]*X[0]*X[0]*X[0]*X[1] + 6*X[0]*X[0]*X[1]*X[1]*X[1] - 6*X[0]*X[1]*X[1]*X[1]*X[1] - (12*X[0] - 6*X[1])*nu + 3*X[1];
387649ef022SMatthew Knepley }
388649ef022SMatthew Knepley 
389649ef022SMatthew Knepley static void f0_cubic_trig_w(PetscInt dim, PetscInt Nf, PetscInt NfAux,
390649ef022SMatthew Knepley                             const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
391649ef022SMatthew Knepley                             const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
392649ef022SMatthew Knepley                             PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
393649ef022SMatthew Knepley {
394444129b9SMatthew G. Knepley   const PetscReal alpha = PetscRealPart(constants[ALPHA]);
395649ef022SMatthew Knepley 
396444129b9SMatthew G. Knepley   f0[0] -= 100.*PetscCosReal(t)*X[0] + 100.*PetscSinReal(t)*(X[1] - 1.) + X[0]*X[0]*X[0]*X[0] + 2.0*X[0]*X[0]*X[0]*X[1] - 3.0*X[0]*X[0]*X[1]*X[1] + X[0]*X[1]*X[1]*X[1] - 2.0*alpha;
397649ef022SMatthew Knepley }
398649ef022SMatthew Knepley 
399606d57d4SMatthew G. Knepley /*
400444129b9SMatthew G. Knepley   CASE: Taylor-Green vortex
401606d57d4SMatthew G. Knepley   In 2D we use exact solution:
402606d57d4SMatthew G. Knepley 
403606d57d4SMatthew G. Knepley     u = 1 - cos(\pi(x - t)) sin(\pi(y - t)) exp(-2 \pi^2 \nu t)
404606d57d4SMatthew G. Knepley     v = 1 + sin(\pi(x - t)) cos(\pi(y - t)) exp(-2 \pi^2 \nu t)
405606d57d4SMatthew G. Knepley     p = -1/4 [cos(2 \pi(x - t)) + cos(2 \pi(y - t))] exp(-4 \pi^2 \nu t)
406606d57d4SMatthew G. Knepley     T = t + x + y
407606d57d4SMatthew G. Knepley     f = <\nu \pi^2 exp(-2\nu \pi^2 t) cos(\pi(x-t)) sin(\pi(y-t)), -\nu \pi^2 exp(-2\nu \pi^2 t) sin(\pi(x-t)) cos(\pi(y-t))  >
408606d57d4SMatthew G. Knepley     Q = 3 + sin(\pi(x-y)) exp(-2\nu \pi^2 t)
409606d57d4SMatthew G. Knepley 
410606d57d4SMatthew G. Knepley   so that
411606d57d4SMatthew G. Knepley 
412606d57d4SMatthew G. Knepley   \nabla \cdot u = \pi sin(\pi(x - t)) sin(\pi(y - t)) exp(-2 \pi^2 \nu t) - \pi sin(\pi(x - t)) sin(\pi(y - t)) exp(-2 \pi^2 \nu t) = 0
413606d57d4SMatthew G. Knepley 
414606d57d4SMatthew G. Knepley   f = du/dt + u \cdot \nabla u - \nu \Delta u + \nabla p
415606d57d4SMatthew G. Knepley     = <-\pi (sin(\pi(x - t)) sin(\pi(y - t)) - cos(\pi(x - t)) cos(\pi(y - t)) - 2\pi cos(\pi(x - t)) sin(\pi(y - t))) exp(-2 \pi^2 \nu t),
416606d57d4SMatthew G. Knepley         \pi (sin(\pi(x - t)) sin(\pi(y - t)) - cos(\pi(x - t)) cos(\pi(y - t)) - 2\pi sin(\pi(x - t)) cos(\pi(y - t))) exp(-2 \pi^2 \nu t)>
417606d57d4SMatthew G. Knepley     + < \pi (1 - cos(\pi(x - t)) sin(\pi(y - t)) exp(-2 \pi^2 \nu t)) sin(\pi(x - t)) sin(\pi(y - t)) exp(-2 \pi^2 \nu t),
418606d57d4SMatthew G. Knepley         \pi (1 - cos(\pi(x - t)) sin(\pi(y - t)) exp(-2 \pi^2 \nu t)) cos(\pi(x - t)) cos(\pi(y - t)) exp(-2 \pi^2 \nu t)>
419606d57d4SMatthew G. Knepley     + <-\pi (1 + sin(\pi(x - t)) cos(\pi(y - t)) exp(-2 \pi^2 \nu t)) cos(\pi(x - t)) cos(\pi(y - t)) exp(-2 \pi^2 \nu t),
420606d57d4SMatthew G. Knepley        -\pi (1 + sin(\pi(x - t)) cos(\pi(y - t)) exp(-2 \pi^2 \nu t)) sin(\pi(x - t)) sin(\pi(y - t)) exp(-2 \pi^2 \nu t)>
421606d57d4SMatthew G. Knepley     + <-2\pi^2 cos(\pi(x - t)) sin(\pi(y - t)) exp(-2 \pi^2 \nu t),
422606d57d4SMatthew G. Knepley         2\pi^2 sin(\pi(x - t)) cos(\pi(y - t)) exp(-2 \pi^2 \nu t)>
423606d57d4SMatthew G. Knepley     + < \pi/2 sin(2\pi(x - t)) exp(-4 \pi^2 \nu t),
424606d57d4SMatthew G. Knepley         \pi/2 sin(2\pi(y - t)) exp(-4 \pi^2 \nu t)>
425606d57d4SMatthew G. Knepley     = <-\pi (sin(\pi(x - t)) sin(\pi(y - t)) - cos(\pi(x - t)) cos(\pi(y - t)) - 2\pi cos(\pi(x - t)) sin(\pi(y - t))) exp(-2 \pi^2 \nu t),
426606d57d4SMatthew G. Knepley         \pi (sin(\pi(x - t)) sin(\pi(y - t)) - cos(\pi(x - t)) cos(\pi(y - t)) - 2\pi sin(\pi(x - t)) cos(\pi(y - t))) exp(-2 \pi^2 \nu t)>
427606d57d4SMatthew G. Knepley     + < \pi sin(\pi(x - t)) sin(\pi(y - t)) exp(-2 \pi^2 \nu t),
428606d57d4SMatthew G. Knepley         \pi cos(\pi(x - t)) cos(\pi(y - t)) exp(-2 \pi^2 \nu t)>
429606d57d4SMatthew G. Knepley     + <-\pi cos(\pi(x - t)) cos(\pi(y - t)) exp(-2 \pi^2 \nu t),
430606d57d4SMatthew G. Knepley        -\pi sin(\pi(x - t)) sin(\pi(y - t)) exp(-2 \pi^2 \nu t)>
431606d57d4SMatthew G. Knepley     + <-\pi/2 sin(2\pi(x - t)) exp(-4 \pi^2 \nu t),
432606d57d4SMatthew G. Knepley        -\pi/2 sin(2\pi(y - t)) exp(-4 \pi^2 \nu t)>
433606d57d4SMatthew G. Knepley     + <-2\pi^2 cos(\pi(x - t)) sin(\pi(y - t)) exp(-2 \pi^2 \nu t),
434606d57d4SMatthew G. Knepley         2\pi^2 sin(\pi(x - t)) cos(\pi(y - t)) exp(-2 \pi^2 \nu t)>
435606d57d4SMatthew G. Knepley     + < \pi/2 sin(2\pi(x - t)) exp(-4 \pi^2 \nu t),
436606d57d4SMatthew G. Knepley         \pi/2 sin(2\pi(y - t)) exp(-4 \pi^2 \nu t)>
437606d57d4SMatthew G. Knepley     = <-\pi (sin(\pi(x - t)) sin(\pi(y - t)) - cos(\pi(x - t)) cos(\pi(y - t))) exp(-2 \pi^2 \nu t),
438606d57d4SMatthew G. Knepley         \pi (sin(\pi(x - t)) sin(\pi(y - t)) - cos(\pi(x - t)) cos(\pi(y - t))) exp(-2 \pi^2 \nu t)>
439606d57d4SMatthew G. Knepley     + < \pi sin(\pi(x - t)) sin(\pi(y - t)) exp(-2 \pi^2 \nu t),
440606d57d4SMatthew G. Knepley         \pi cos(\pi(x - t)) cos(\pi(y - t)) exp(-2 \pi^2 \nu t)>
441606d57d4SMatthew G. Knepley     + <-\pi cos(\pi(x - t)) cos(\pi(y - t)) exp(-2 \pi^2 \nu t),
442606d57d4SMatthew G. Knepley        -\pi sin(\pi(x - t)) sin(\pi(y - t)) exp(-2 \pi^2 \nu t)>
443606d57d4SMatthew G. Knepley     = < \pi cos(\pi(x - t)) cos(\pi(y - t)),
444606d57d4SMatthew G. Knepley         \pi sin(\pi(x - t)) sin(\pi(y - t))>
445606d57d4SMatthew G. Knepley     + <-\pi cos(\pi(x - t)) cos(\pi(y - t)),
446606d57d4SMatthew G. Knepley        -\pi sin(\pi(x - t)) sin(\pi(y - t))> = 0
447606d57d4SMatthew G. Knepley   Q = dT/dt + u \cdot \nabla T - \alpha \Delta T
448606d57d4SMatthew G. Knepley     = 1 + u \cdot <1, 1> - 0
449606d57d4SMatthew G. Knepley     = 1 + u + v
450606d57d4SMatthew G. Knepley */
451606d57d4SMatthew G. Knepley 
452606d57d4SMatthew G. Knepley static PetscErrorCode taylor_green_u(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
453606d57d4SMatthew G. Knepley {
454606d57d4SMatthew G. Knepley   u[0] = 1 - PetscCosReal(PETSC_PI*(X[0]-time))*PetscSinReal(PETSC_PI*(X[1]-time))*PetscExpReal(-2*PETSC_PI*PETSC_PI*time);
455606d57d4SMatthew G. Knepley   u[1] = 1 + PetscSinReal(PETSC_PI*(X[0]-time))*PetscCosReal(PETSC_PI*(X[1]-time))*PetscExpReal(-2*PETSC_PI*PETSC_PI*time);
456606d57d4SMatthew G. Knepley   return 0;
457606d57d4SMatthew G. Knepley }
458606d57d4SMatthew G. Knepley static PetscErrorCode taylor_green_u_t(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
459606d57d4SMatthew G. Knepley {
460606d57d4SMatthew G. Knepley   u[0] = -PETSC_PI*(PetscSinReal(PETSC_PI*(X[0]-time))*PetscSinReal(PETSC_PI*(X[1]-time))
461606d57d4SMatthew G. Knepley                   - PetscCosReal(PETSC_PI*(X[0]-time))*PetscCosReal(PETSC_PI*(X[1]-time))
462606d57d4SMatthew G. Knepley                   - 2*PETSC_PI*PetscCosReal(PETSC_PI*(X[0]-time))*PetscSinReal(PETSC_PI*(X[1]-time)))*PetscExpReal(-2*PETSC_PI*PETSC_PI*time);
463606d57d4SMatthew G. Knepley   u[1] =  PETSC_PI*(PetscSinReal(PETSC_PI*(X[0]-time))*PetscSinReal(PETSC_PI*(X[1]-time))
464606d57d4SMatthew G. Knepley                   - PetscCosReal(PETSC_PI*(X[0]-time))*PetscCosReal(PETSC_PI*(X[1]-time))
465606d57d4SMatthew G. Knepley                   - 2*PETSC_PI*PetscSinReal(PETSC_PI*(X[0]-time))*PetscCosReal(PETSC_PI*(X[1]-time)))*PetscExpReal(-2*PETSC_PI*PETSC_PI*time);
466606d57d4SMatthew G. Knepley   return 0;
467606d57d4SMatthew G. Knepley }
468606d57d4SMatthew G. Knepley 
469606d57d4SMatthew G. Knepley static PetscErrorCode taylor_green_p(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *p, void *ctx)
470606d57d4SMatthew G. Knepley {
471606d57d4SMatthew G. Knepley   p[0] = -0.25*(PetscCosReal(2*PETSC_PI*(X[0]-time)) + PetscCosReal(2*PETSC_PI*(X[1]-time)))*PetscExpReal(-4*PETSC_PI*PETSC_PI*time);
472606d57d4SMatthew G. Knepley   return 0;
473606d57d4SMatthew G. Knepley }
474606d57d4SMatthew G. Knepley 
475606d57d4SMatthew G. Knepley static PetscErrorCode taylor_green_p_t(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *p, void *ctx)
476606d57d4SMatthew G. Knepley {
477606d57d4SMatthew G. Knepley   p[0] = PETSC_PI*(0.5*(PetscSinReal(2*PETSC_PI*(X[0]-time)) + PetscSinReal(2*PETSC_PI*(X[1]-time)))
478606d57d4SMatthew G. Knepley                  + PETSC_PI*(PetscCosReal(2*PETSC_PI*(X[0]-time)) + PetscCosReal(2*PETSC_PI*(X[1]-time))))*PetscExpReal(-4*PETSC_PI*PETSC_PI*time);
479606d57d4SMatthew G. Knepley   return 0;
480606d57d4SMatthew G. Knepley }
481606d57d4SMatthew G. Knepley 
482606d57d4SMatthew G. Knepley static PetscErrorCode taylor_green_T(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *T, void *ctx)
483606d57d4SMatthew G. Knepley {
484606d57d4SMatthew G. Knepley   T[0] = time + X[0] + X[1];
485606d57d4SMatthew G. Knepley   return 0;
486606d57d4SMatthew G. Knepley }
487606d57d4SMatthew G. Knepley static PetscErrorCode taylor_green_T_t(PetscInt Dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *T, void *ctx)
488606d57d4SMatthew G. Knepley {
489606d57d4SMatthew G. Knepley   T[0] = 1.0;
490606d57d4SMatthew G. Knepley   return 0;
491606d57d4SMatthew G. Knepley }
492606d57d4SMatthew G. Knepley 
493606d57d4SMatthew G. Knepley static void f0_taylor_green_w(PetscInt dim, PetscInt Nf, PetscInt NfAux,
494606d57d4SMatthew G. Knepley                             const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
495606d57d4SMatthew G. Knepley                             const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
496606d57d4SMatthew G. Knepley                             PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
497606d57d4SMatthew G. Knepley {
498606d57d4SMatthew G. Knepley   PetscScalar vel[2];
499606d57d4SMatthew G. Knepley 
500606d57d4SMatthew G. Knepley   taylor_green_u(dim, t, X, Nf, vel, NULL);
501444129b9SMatthew G. Knepley   f0[0] -= 1.0 + vel[0] + vel[1];
502606d57d4SMatthew G. Knepley }
503606d57d4SMatthew G. Knepley 
504444129b9SMatthew G. Knepley /*
505444129b9SMatthew G. Knepley   CASE: Pipe flow
506444129b9SMatthew G. Knepley   Poiseuille flow, with the incoming fluid having a parabolic temperature profile and the side walls being held at T_in
507444129b9SMatthew G. Knepley 
508444129b9SMatthew G. Knepley     u = \Delta Re/(2 mu) y (1 - y)
509444129b9SMatthew G. Knepley     v = 0
510444129b9SMatthew G. Knepley     p = -\Delta x
511444129b9SMatthew G. Knepley     T = y (1 - y) + T_in
512444129b9SMatthew G. Knepley   rho = p^{th} / T
513444129b9SMatthew G. Knepley 
514444129b9SMatthew G. Knepley   so that
515444129b9SMatthew G. Knepley 
516444129b9SMatthew G. Knepley     \nabla \cdot u = 0 - 0 = 0
517444129b9SMatthew G. Knepley     grad u = \Delta Re/(2 mu) <<0, 0>, <1 - 2y, 0>>
518444129b9SMatthew G. Knepley     epsilon(u) = 1/2 (grad u + grad u^T) = \Delta Re/(4 mu) <<0, 1 - 2y>, <<1 - 2y, 0>>
519444129b9SMatthew G. Knepley     epsilon'(u) = epsilon(u) - 1/3 (div u) I = epsilon(u)
520444129b9SMatthew G. Knepley     div epsilon'(u) = -\Delta Re/(2 mu) <1, 0>
521444129b9SMatthew G. Knepley 
522444129b9SMatthew G. Knepley   f = rho S du/dt + rho u \cdot \nabla u - 2\mu/Re div \epsilon'(u) + \nabla p + rho / F^2 \hat y
523444129b9SMatthew G. Knepley     = 0 + 0 - div (2\mu/Re \epsilon'(u) - pI) + rho / F^2 \hat y
524444129b9SMatthew G. Knepley     = -\Delta div <<x, (1 - 2y)/2>, <<(1 - 2y)/2, x>> + rho / F^2 \hat y
525444129b9SMatthew G. Knepley     = \Delta <1, 0> - \Delta <1, 0> + rho/F^2 <0, 1>
526444129b9SMatthew G. Knepley     = rho/F^2 <0, 1>
527444129b9SMatthew G. Knepley 
528444129b9SMatthew G. Knepley   g = S rho_t + div (rho u)
529444129b9SMatthew G. Knepley     = 0 + rho div (u) + u . grad rho
530444129b9SMatthew G. Knepley     = 0 + 0 - pth u . grad T / T^2
531444129b9SMatthew G. Knepley     = 0
532444129b9SMatthew G. Knepley 
533444129b9SMatthew G. Knepley   Q = rho c_p S dT/dt + rho c_p u . grad T - 1/Pe div k grad T
534444129b9SMatthew G. Knepley     = 0 + c_p pth / T 0 + 2 k/Pe
535444129b9SMatthew G. Knepley     = 2 k/Pe
536444129b9SMatthew G. Knepley 
537444129b9SMatthew G. Knepley   The boundary conditions on the top and bottom are zero velocity and T_in temperature. The boundary term is
538444129b9SMatthew G. Knepley 
539444129b9SMatthew G. Knepley     (2\mu/Re \epsilon'(u) - p I) . n = \Delta <<x, (1 - 2y)/2>, <<(1 - 2y)/2, x>> . n
540444129b9SMatthew G. Knepley 
541444129b9SMatthew G. Knepley   so that
542444129b9SMatthew G. Knepley 
543444129b9SMatthew G. Knepley     x = 0: \Delta <<0, (1 - 2y)/2>, <<(1 - 2y)/2, 0>> . <-1, 0> = <0, (2y - 1)/2>
544444129b9SMatthew G. Knepley     x = 1: \Delta <<1, (1 - 2y)/2>, <<(1 - 2y)/2, 1>> . <1, 0> = <1, (1 - 2y)/2>
545444129b9SMatthew G. Knepley */
546444129b9SMatthew G. Knepley static PetscErrorCode pipe_u(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
547444129b9SMatthew G. Knepley {
548444129b9SMatthew G. Knepley   Parameter *param = (Parameter *) ctx;
549444129b9SMatthew G. Knepley 
550444129b9SMatthew G. Knepley   u[0] = (0.5*param->Reynolds / param->mu) * X[1]*(1.0 - X[1]);
551444129b9SMatthew G. Knepley   u[1] = 0.0;
552444129b9SMatthew G. Knepley   return 0;
553444129b9SMatthew G. Knepley }
554444129b9SMatthew G. Knepley static PetscErrorCode pipe_u_t(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
555444129b9SMatthew G. Knepley {
556444129b9SMatthew G. Knepley   u[0] = 0.0;
557444129b9SMatthew G. Knepley   u[1] = 0.0;
558444129b9SMatthew G. Knepley   return 0;
559444129b9SMatthew G. Knepley }
560444129b9SMatthew G. Knepley 
561444129b9SMatthew G. Knepley static PetscErrorCode pipe_p(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *p, void *ctx)
562444129b9SMatthew G. Knepley {
563444129b9SMatthew G. Knepley   p[0] = -X[0];
564444129b9SMatthew G. Knepley   return 0;
565444129b9SMatthew G. Knepley }
566444129b9SMatthew G. Knepley static PetscErrorCode pipe_p_t(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *p, void *ctx)
567444129b9SMatthew G. Knepley {
568444129b9SMatthew G. Knepley   p[0] = 0.0;
569444129b9SMatthew G. Knepley   return 0;
570444129b9SMatthew G. Knepley }
571444129b9SMatthew G. Knepley 
572444129b9SMatthew G. Knepley static PetscErrorCode pipe_T(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *T, void *ctx)
573444129b9SMatthew G. Knepley {
574444129b9SMatthew G. Knepley   Parameter *param = (Parameter *) ctx;
575444129b9SMatthew G. Knepley 
576444129b9SMatthew G. Knepley   T[0] = X[1]*(1.0 - X[1]) + param->T_in;
577444129b9SMatthew G. Knepley   return 0;
578444129b9SMatthew G. Knepley }
579444129b9SMatthew G. Knepley static PetscErrorCode pipe_T_t(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *T, void *ctx)
580444129b9SMatthew G. Knepley {
581444129b9SMatthew G. Knepley   T[0] = 0.0;
582444129b9SMatthew G. Knepley   return 0;
583444129b9SMatthew G. Knepley }
584444129b9SMatthew G. Knepley 
585444129b9SMatthew G. Knepley static void f0_conduct_pipe_v(PetscInt dim, PetscInt Nf, PetscInt NfAux,
586444129b9SMatthew G. Knepley                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
587444129b9SMatthew G. Knepley                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
588444129b9SMatthew G. Knepley                               PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
589444129b9SMatthew G. Knepley {
590444129b9SMatthew G. Knepley   const PetscReal F    = PetscRealPart(constants[FROUDE]);
591444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
592444129b9SMatthew G. Knepley   const PetscReal T_in = PetscRealPart(constants[T_IN]);
593444129b9SMatthew G. Knepley   const PetscReal rho  = p_th / (X[1]*(1. - X[1]) + T_in);
594444129b9SMatthew G. Knepley   const PetscInt  gd   = (PetscInt) PetscRealPart(constants[G_DIR]);
595444129b9SMatthew G. Knepley 
596444129b9SMatthew G. Knepley   f0[gd] -= rho/PetscSqr(F);
597444129b9SMatthew G. Knepley }
598444129b9SMatthew G. Knepley 
599444129b9SMatthew G. Knepley static void f0_conduct_bd_pipe_v(PetscInt dim, PetscInt Nf, PetscInt NfAux,
600444129b9SMatthew G. Knepley                                  const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
601444129b9SMatthew G. Knepley                                  const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
602444129b9SMatthew G. Knepley                                  PetscReal t, const PetscReal X[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
603444129b9SMatthew G. Knepley {
604444129b9SMatthew G. Knepley   PetscReal sigma[4] = {X[0], 0.5*(1. - 2.*X[1]), 0.5*(1. - 2.*X[1]), X[0]};
605444129b9SMatthew G. Knepley   PetscInt  d, e;
606444129b9SMatthew G. Knepley 
607444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
608444129b9SMatthew G. Knepley     for (e = 0; e < dim; ++e) {
609444129b9SMatthew G. Knepley       f0[d] -= sigma[d*dim + e] * n[e];
610444129b9SMatthew G. Knepley     }
611444129b9SMatthew G. Knepley   }
612444129b9SMatthew G. Knepley }
613444129b9SMatthew G. Knepley 
614444129b9SMatthew G. Knepley static void f0_conduct_pipe_q(PetscInt dim, PetscInt Nf, PetscInt NfAux,
615444129b9SMatthew G. Knepley                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
616444129b9SMatthew G. Knepley                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
617444129b9SMatthew G. Knepley                               PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
618444129b9SMatthew G. Knepley {
619444129b9SMatthew G. Knepley   f0[0] += 0.0;
620444129b9SMatthew G. Knepley }
621444129b9SMatthew G. Knepley 
622444129b9SMatthew G. Knepley static void f0_conduct_pipe_w(PetscInt dim, PetscInt Nf, PetscInt NfAux,
623444129b9SMatthew G. Knepley                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
624444129b9SMatthew G. Knepley                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
625444129b9SMatthew G. Knepley                               PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
626444129b9SMatthew G. Knepley {
627444129b9SMatthew G. Knepley   const PetscReal k  = PetscRealPart(constants[K]);
628444129b9SMatthew G. Knepley   const PetscReal Pe = PetscRealPart(constants[PECLET]);
629444129b9SMatthew G. Knepley 
630444129b9SMatthew G. Knepley   f0[0] -= 2*k/Pe;
631444129b9SMatthew G. Knepley }
632444129b9SMatthew G. Knepley 
633*367970cfSMatthew G. Knepley /*
634*367970cfSMatthew G. Knepley   CASE: Wiggly pipe flow
635*367970cfSMatthew G. Knepley   Perturbed Poiseuille flow, with the incoming fluid having a perturbed parabolic temperature profile and the side walls being held at T_in
636*367970cfSMatthew G. Knepley 
637*367970cfSMatthew G. Knepley     u = \Delta Re/(2 mu) [y (1 - y) + a sin(pi y)]
638*367970cfSMatthew G. Knepley     v = 0
639*367970cfSMatthew G. Knepley     p = -\Delta x
640*367970cfSMatthew G. Knepley     T = y (1 - y) + a sin(pi y) + T_in
641*367970cfSMatthew G. Knepley   rho = p^{th} / T
642*367970cfSMatthew G. Knepley 
643*367970cfSMatthew G. Knepley   so that
644*367970cfSMatthew G. Knepley 
645*367970cfSMatthew G. Knepley     \nabla \cdot u = 0 - 0 = 0
646*367970cfSMatthew G. Knepley     grad u = \Delta Re/(2 mu) <<0, 0>, <1 - 2y + a pi cos(pi y), 0>>
647*367970cfSMatthew G. Knepley     epsilon(u) = 1/2 (grad u + grad u^T) = \Delta Re/(4 mu) <<0, 1 - 2y + a pi cos(pi y)>, <<1 - 2y + a pi cos(pi y), 0>>
648*367970cfSMatthew G. Knepley     epsilon'(u) = epsilon(u) - 1/3 (div u) I = epsilon(u)
649*367970cfSMatthew G. Knepley     div epsilon'(u) = -\Delta Re/(2 mu) <1 + a pi^2/2 sin(pi y), 0>
650*367970cfSMatthew G. Knepley 
651*367970cfSMatthew G. Knepley   f = rho S du/dt + rho u \cdot \nabla u - 2\mu/Re div \epsilon'(u) + \nabla p + rho / F^2 \hat y
652*367970cfSMatthew G. Knepley     = 0 + 0 - div (2\mu/Re \epsilon'(u) - pI) + rho / F^2 \hat y
653*367970cfSMatthew G. Knepley     = -\Delta div <<x, (1 - 2y)/2 + a pi/2 cos(pi y)>, <<(1 - 2y)/2 + a pi/2 cos(pi y), x>> + rho / F^2 \hat y
654*367970cfSMatthew G. Knepley     = -\Delta <1 - 1 - a pi^2/2 sin(pi y), 0> + rho/F^2 <0, 1>
655*367970cfSMatthew G. Knepley     = a \Delta pi^2/2 sin(pi y) <1, 0> + rho/F^2 <0, 1>
656*367970cfSMatthew G. Knepley 
657*367970cfSMatthew G. Knepley   g = S rho_t + div (rho u)
658*367970cfSMatthew G. Knepley     = 0 + rho div (u) + u . grad rho
659*367970cfSMatthew G. Knepley     = 0 + 0 - pth u . grad T / T^2
660*367970cfSMatthew G. Knepley     = 0
661*367970cfSMatthew G. Knepley 
662*367970cfSMatthew G. Knepley   Q = rho c_p S dT/dt + rho c_p u . grad T - 1/Pe div k grad T
663*367970cfSMatthew G. Knepley     = 0 + c_p pth / T 0 - k/Pe div <0, 1 - 2y + a pi cos(pi y)>
664*367970cfSMatthew G. Knepley     = - k/Pe (-2 - a pi^2 sin(pi y))
665*367970cfSMatthew G. Knepley     = 2 k/Pe (1 + a pi^2/2 sin(pi y))
666*367970cfSMatthew G. Knepley 
667*367970cfSMatthew G. Knepley   The boundary conditions on the top and bottom are zero velocity and T_in temperature. The boundary term is
668*367970cfSMatthew G. Knepley 
669*367970cfSMatthew G. Knepley     (2\mu/Re \epsilon'(u) - p I) . n = \Delta <<x, (1 - 2y)/2 + a pi/2 cos(pi y)>, <<(1 - 2y)/2 + a pi/2 cos(pi y), x>> . n
670*367970cfSMatthew G. Knepley 
671*367970cfSMatthew G. Knepley   so that
672*367970cfSMatthew G. Knepley 
673*367970cfSMatthew G. Knepley     x = 0: \Delta <<0, (1 - 2y)/2>, <<(1 - 2y)/2, 0>> . <-1, 0> = <0, (2y - 1)/2 - a pi/2 cos(pi y)>
674*367970cfSMatthew G. Knepley     x = 1: \Delta <<1, (1 - 2y)/2>, <<(1 - 2y)/2, 1>> . < 1, 0> = <1, (1 - 2y)/2 + a pi/2 cos(pi y)>
675*367970cfSMatthew G. Knepley */
676*367970cfSMatthew G. Knepley static PetscErrorCode pipe_wiggly_u(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
677*367970cfSMatthew G. Knepley {
678*367970cfSMatthew G. Knepley   Parameter *param = (Parameter *) ctx;
679*367970cfSMatthew G. Knepley 
680*367970cfSMatthew G. Knepley   u[0] = (0.5*param->Reynolds / param->mu) * (X[1]*(1.0 - X[1]) + param->epsilon*PetscSinReal(PETSC_PI*X[1]));
681*367970cfSMatthew G. Knepley   u[1] = 0.0;
682*367970cfSMatthew G. Knepley   return 0;
683*367970cfSMatthew G. Knepley }
684*367970cfSMatthew G. Knepley static PetscErrorCode pipe_wiggly_u_t(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
685*367970cfSMatthew G. Knepley {
686*367970cfSMatthew G. Knepley   u[0] = 0.0;
687*367970cfSMatthew G. Knepley   u[1] = 0.0;
688*367970cfSMatthew G. Knepley   return 0;
689*367970cfSMatthew G. Knepley }
690*367970cfSMatthew G. Knepley 
691*367970cfSMatthew G. Knepley static PetscErrorCode pipe_wiggly_p(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *p, void *ctx)
692*367970cfSMatthew G. Knepley {
693*367970cfSMatthew G. Knepley   p[0] = -X[0];
694*367970cfSMatthew G. Knepley   return 0;
695*367970cfSMatthew G. Knepley }
696*367970cfSMatthew G. Knepley static PetscErrorCode pipe_wiggly_p_t(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *p, void *ctx)
697*367970cfSMatthew G. Knepley {
698*367970cfSMatthew G. Knepley   p[0] = 0.0;
699*367970cfSMatthew G. Knepley   return 0;
700*367970cfSMatthew G. Knepley }
701*367970cfSMatthew G. Knepley 
702*367970cfSMatthew G. Knepley static PetscErrorCode pipe_wiggly_T(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *T, void *ctx)
703*367970cfSMatthew G. Knepley {
704*367970cfSMatthew G. Knepley   Parameter *param = (Parameter *) ctx;
705*367970cfSMatthew G. Knepley 
706*367970cfSMatthew G. Knepley   T[0] = X[1]*(1.0 - X[1]) + param->epsilon*PetscSinReal(PETSC_PI*X[1]) + param->T_in;
707*367970cfSMatthew G. Knepley   return 0;
708*367970cfSMatthew G. Knepley }
709*367970cfSMatthew G. Knepley static PetscErrorCode pipe_wiggly_T_t(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *T, void *ctx)
710*367970cfSMatthew G. Knepley {
711*367970cfSMatthew G. Knepley   T[0] = 0.0;
712*367970cfSMatthew G. Knepley   return 0;
713*367970cfSMatthew G. Knepley }
714*367970cfSMatthew G. Knepley 
715*367970cfSMatthew G. Knepley static void f0_conduct_pipe_wiggly_v(PetscInt dim, PetscInt Nf, PetscInt NfAux,
716*367970cfSMatthew G. Knepley                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
717*367970cfSMatthew G. Knepley                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
718*367970cfSMatthew G. Knepley                                      PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
719*367970cfSMatthew G. Knepley {
720*367970cfSMatthew G. Knepley   const PetscReal F    = PetscRealPart(constants[FROUDE]);
721*367970cfSMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
722*367970cfSMatthew G. Knepley   const PetscReal T_in = PetscRealPart(constants[T_IN]);
723*367970cfSMatthew G. Knepley   const PetscReal eps  = PetscRealPart(constants[EPSILON]);
724*367970cfSMatthew G. Knepley   const PetscReal rho  = p_th / (X[1]*(1. - X[1]) + T_in);
725*367970cfSMatthew G. Knepley   const PetscInt  gd   = (PetscInt) PetscRealPart(constants[G_DIR]);
726*367970cfSMatthew G. Knepley 
727*367970cfSMatthew G. Knepley   f0[0]  -= eps*0.5*PetscSqr(PETSC_PI)*PetscSinReal(PETSC_PI*X[1]);
728*367970cfSMatthew G. Knepley   f0[gd] -= rho/PetscSqr(F);
729*367970cfSMatthew G. Knepley }
730*367970cfSMatthew G. Knepley 
731*367970cfSMatthew G. Knepley static void f0_conduct_bd_pipe_wiggly_v(PetscInt dim, PetscInt Nf, PetscInt NfAux,
732*367970cfSMatthew G. Knepley                                         const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
733*367970cfSMatthew G. Knepley                                         const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
734*367970cfSMatthew G. Knepley                                         PetscReal t, const PetscReal X[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
735*367970cfSMatthew G. Knepley {
736*367970cfSMatthew G. Knepley   const PetscReal eps = PetscRealPart(constants[EPSILON]);
737*367970cfSMatthew G. Knepley   PetscReal sigma[4] = {X[0], 0.5*(1. - 2.*X[1]) + eps*0.5*PETSC_PI*PetscCosReal(PETSC_PI*X[1]), 0.5*(1. - 2.*X[1]) + eps*0.5*PETSC_PI*PetscCosReal(PETSC_PI*X[1]), X[0]};
738*367970cfSMatthew G. Knepley   PetscInt  d, e;
739*367970cfSMatthew G. Knepley 
740*367970cfSMatthew G. Knepley   for (d = 0; d < dim; ++d) {
741*367970cfSMatthew G. Knepley     for (e = 0; e < dim; ++e) {
742*367970cfSMatthew G. Knepley       f0[d] -= sigma[d*dim + e] * n[e];
743*367970cfSMatthew G. Knepley     }
744*367970cfSMatthew G. Knepley   }
745*367970cfSMatthew G. Knepley }
746*367970cfSMatthew G. Knepley 
747*367970cfSMatthew G. Knepley static void f0_conduct_pipe_wiggly_q(PetscInt dim, PetscInt Nf, PetscInt NfAux,
748*367970cfSMatthew G. Knepley                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
749*367970cfSMatthew G. Knepley                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
750*367970cfSMatthew G. Knepley                                      PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
751*367970cfSMatthew G. Knepley {
752*367970cfSMatthew G. Knepley   f0[0] += 0.0;
753*367970cfSMatthew G. Knepley }
754*367970cfSMatthew G. Knepley 
755*367970cfSMatthew G. Knepley static void f0_conduct_pipe_wiggly_w(PetscInt dim, PetscInt Nf, PetscInt NfAux,
756*367970cfSMatthew G. Knepley                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
757*367970cfSMatthew G. Knepley                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
758*367970cfSMatthew G. Knepley                                      PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
759*367970cfSMatthew G. Knepley {
760*367970cfSMatthew G. Knepley   const PetscReal k  = PetscRealPart(constants[K]);
761*367970cfSMatthew G. Knepley   const PetscReal Pe = PetscRealPart(constants[PECLET]);
762*367970cfSMatthew G. Knepley   const PetscReal eps = PetscRealPart(constants[EPSILON]);
763*367970cfSMatthew G. Knepley 
764*367970cfSMatthew G. Knepley   f0[0] -= 2*k/Pe*(1.0 + eps*0.5*PetscSqr(PETSC_PI)*PetscSinReal(PETSC_PI*X[1]));
765*367970cfSMatthew G. Knepley }
766*367970cfSMatthew G. Knepley 
767444129b9SMatthew G. Knepley /*      Physics Kernels      */
768444129b9SMatthew G. Knepley 
769649ef022SMatthew Knepley static void f0_q(PetscInt dim, PetscInt Nf, PetscInt NfAux,
770649ef022SMatthew Knepley                  const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
771649ef022SMatthew Knepley                  const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
772649ef022SMatthew Knepley                  PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
773649ef022SMatthew Knepley {
774649ef022SMatthew Knepley   PetscInt d;
775649ef022SMatthew Knepley   for (d = 0, f0[0] = 0.0; d < dim; ++d) f0[0] += u_x[d*dim+d];
776649ef022SMatthew Knepley }
777649ef022SMatthew Knepley 
778444129b9SMatthew G. Knepley /* -\frac{Sp^{th}}{T^2} \frac{\partial T}{\partial t} + \frac{p^{th}}{T} \nabla \cdot \vb{u} - \frac{p^{th}}{T^2} \vb{u} \cdot \nabla T */
779444129b9SMatthew G. Knepley static void f0_conduct_q(PetscInt dim, PetscInt Nf, PetscInt NfAux,
780444129b9SMatthew G. Knepley                          const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
781444129b9SMatthew G. Knepley                          const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
782444129b9SMatthew G. Knepley                          PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
783444129b9SMatthew G. Knepley {
784444129b9SMatthew G. Knepley   const PetscReal S    = PetscRealPart(constants[STROUHAL]);
785444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
786444129b9SMatthew G. Knepley   PetscInt        d;
787444129b9SMatthew G. Knepley 
788444129b9SMatthew G. Knepley   // -\frac{S p^{th}}{T^2} \frac{\partial T}{\partial t}
789444129b9SMatthew G. Knepley   f0[0] += -u_t[uOff[TEMP]] * S * p_th / PetscSqr(u[uOff[TEMP]]);
790444129b9SMatthew G. Knepley 
791444129b9SMatthew G. Knepley   // \frac{p^{th}}{T} \nabla \cdot \vb{u}
792444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
793444129b9SMatthew G. Knepley     f0[0] += p_th / u[uOff[TEMP]] * u_x[uOff_x[VEL] + d*dim + d];
794444129b9SMatthew G. Knepley   }
795444129b9SMatthew G. Knepley 
796444129b9SMatthew G. Knepley   // - \frac{p^{th}}{T^2} \vb{u} \cdot \nabla T
797444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
798444129b9SMatthew G. Knepley     f0[0] -= p_th / (u[uOff[TEMP]] * u[uOff[TEMP]]) * u[uOff[VEL] + d] * u_x[uOff_x[TEMP] + d];
799444129b9SMatthew G. Knepley   }
800444129b9SMatthew G. Knepley 
801444129b9SMatthew G. Knepley   // Add in any fixed source term
802444129b9SMatthew G. Knepley   if (NfAux > 0) {
803444129b9SMatthew G. Knepley     f0[0] += a[aOff[MASS]];
804444129b9SMatthew G. Knepley   }
805444129b9SMatthew G. Knepley }
806444129b9SMatthew G. Knepley 
807444129b9SMatthew G. Knepley /* \vb{u}_t + \vb{u} \cdot \nabla\vb{u} */
808444129b9SMatthew G. Knepley static void f0_v(PetscInt dim, PetscInt Nf, PetscInt NfAux,
809444129b9SMatthew G. Knepley                  const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
810444129b9SMatthew G. Knepley                  const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
811444129b9SMatthew G. Knepley                  PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
812444129b9SMatthew G. Knepley {
813444129b9SMatthew G. Knepley   const PetscInt Nc = dim;
814444129b9SMatthew G. Knepley   PetscInt       c, d;
815444129b9SMatthew G. Knepley 
816444129b9SMatthew G. Knepley   for (c = 0; c < Nc; ++c) {
817444129b9SMatthew G. Knepley     /* \vb{u}_t */
818444129b9SMatthew G. Knepley     f0[c] += u_t[uOff[VEL] + c];
819444129b9SMatthew G. Knepley     /* \vb{u} \cdot \nabla\vb{u} */
820444129b9SMatthew G. Knepley     for (d = 0; d < dim; ++d) f0[c] += u[uOff[VEL] + d]*u_x[uOff_x[VEL] + c*dim + d];
821444129b9SMatthew G. Knepley   }
822444129b9SMatthew G. Knepley }
823444129b9SMatthew G. Knepley 
824444129b9SMatthew G. Knepley /* \rho S \frac{\partial \vb{u}}{\partial t} + \rho \vb{u} \cdot \nabla \vb{u} + \rho \frac{\hat{\vb{z}}}{F^2} */
825444129b9SMatthew G. Knepley static void f0_conduct_v(PetscInt dim, PetscInt Nf, PetscInt NfAux,
826444129b9SMatthew G. Knepley                          const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
827444129b9SMatthew G. Knepley                          const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
828444129b9SMatthew G. Knepley                          PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
829444129b9SMatthew G. Knepley {
830444129b9SMatthew G. Knepley   const PetscReal S    = PetscRealPart(constants[STROUHAL]);
831444129b9SMatthew G. Knepley   const PetscReal F    = PetscRealPart(constants[FROUDE]);
832444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
833444129b9SMatthew G. Knepley   const PetscReal rho  = p_th / PetscRealPart(u[uOff[TEMP]]);
834444129b9SMatthew G. Knepley   const PetscInt  gdir = (PetscInt) PetscRealPart(constants[G_DIR]);
835444129b9SMatthew G. Knepley   PetscInt        Nc   = dim;
836444129b9SMatthew G. Knepley   PetscInt        c, d;
837444129b9SMatthew G. Knepley 
838444129b9SMatthew G. Knepley   // \rho S \frac{\partial \vb{u}}{\partial t}
839444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
840444129b9SMatthew G. Knepley     f0[d] = rho * S * u_t[uOff[VEL] + d];
841444129b9SMatthew G. Knepley   }
842444129b9SMatthew G. Knepley 
843444129b9SMatthew G. Knepley   // \rho \vb{u} \cdot \nabla \vb{u}
844444129b9SMatthew G. Knepley   for (c = 0; c < Nc; ++c) {
845444129b9SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
846444129b9SMatthew G. Knepley       f0[c] += rho * u[uOff[VEL] + d] * u_x[uOff_x[VEL] + c*dim + d];
847444129b9SMatthew G. Knepley     }
848444129b9SMatthew G. Knepley   }
849444129b9SMatthew G. Knepley 
850444129b9SMatthew G. Knepley   // rho \hat{z}/F^2
851444129b9SMatthew G. Knepley   f0[gdir] += rho / (F*F);
852444129b9SMatthew G. Knepley 
853444129b9SMatthew G. Knepley   // Add in any fixed source term
854444129b9SMatthew G. Knepley   if (NfAux > 0) {
855444129b9SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
856444129b9SMatthew G. Knepley       f0[d] += a[aOff[MOMENTUM] + d];
857444129b9SMatthew G. Knepley     }
858444129b9SMatthew G. Knepley   }
859444129b9SMatthew G. Knepley }
860444129b9SMatthew G. Knepley 
861649ef022SMatthew Knepley /*f1_v = \nu[grad(u) + grad(u)^T] - pI */
862649ef022SMatthew Knepley static void f1_v(PetscInt dim, PetscInt Nf, PetscInt NfAux,
863649ef022SMatthew Knepley                  const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
864649ef022SMatthew Knepley                  const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
865649ef022SMatthew Knepley                  PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])
866649ef022SMatthew Knepley {
867444129b9SMatthew G. Knepley   const PetscReal nu = PetscRealPart(constants[NU]);
868649ef022SMatthew Knepley   const PetscInt  Nc = dim;
869649ef022SMatthew Knepley   PetscInt        c, d;
870649ef022SMatthew Knepley 
871649ef022SMatthew Knepley   for (c = 0; c < Nc; ++c) {
872649ef022SMatthew Knepley     for (d = 0; d < dim; ++d) {
873649ef022SMatthew Knepley       f1[c*dim+d] = nu*(u_x[c*dim+d] + u_x[d*dim+c]);
874649ef022SMatthew Knepley     }
875649ef022SMatthew Knepley     f1[c*dim+c] -= u[uOff[1]];
876649ef022SMatthew Knepley   }
877649ef022SMatthew Knepley }
878649ef022SMatthew Knepley 
879444129b9SMatthew G. Knepley /* 2 \mu/Re (1/2 (\nabla \vb{u} + \nabla \vb{u}^T) - 1/3 (\nabla \cdot \vb{u}) I) - p I */
880444129b9SMatthew G. Knepley static void f1_conduct_v(PetscInt dim, PetscInt Nf, PetscInt NfAux,
881444129b9SMatthew G. Knepley                          const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
882444129b9SMatthew G. Knepley                          const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
883444129b9SMatthew G. Knepley                          PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])
884444129b9SMatthew G. Knepley {
885444129b9SMatthew G. Knepley   const PetscReal Re    = PetscRealPart(constants[REYNOLDS]);
886444129b9SMatthew G. Knepley   const PetscReal mu    = PetscRealPart(constants[MU]);
887444129b9SMatthew G. Knepley   const PetscReal coef  = mu / Re;
888444129b9SMatthew G. Knepley   PetscReal       u_div = 0.0;
889444129b9SMatthew G. Knepley   const PetscInt  Nc    = dim;
890444129b9SMatthew G. Knepley   PetscInt        c, d;
891444129b9SMatthew G. Knepley 
892444129b9SMatthew G. Knepley   for (c = 0; c < Nc; ++c) {
893444129b9SMatthew G. Knepley     u_div += PetscRealPart(u_x[uOff_x[VEL] + c*dim + c]);
894444129b9SMatthew G. Knepley   }
895444129b9SMatthew G. Knepley 
896444129b9SMatthew G. Knepley   for (c = 0; c < Nc; ++c) {
897444129b9SMatthew G. Knepley     // 2 \mu/Re 1/2 (\nabla \vb{u} + \nabla \vb{u}^T
898444129b9SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
899444129b9SMatthew G. Knepley       f1[c*dim + d] += coef * (u_x[uOff_x[VEL] + c*dim + d] + u_x[uOff_x[VEL] + d*dim + c]);
900444129b9SMatthew G. Knepley     }
901444129b9SMatthew G. Knepley     // -2/3 \mu/Re (\nabla \cdot \vb{u}) I
902444129b9SMatthew G. Knepley     f1[c * dim + c] -= 2.0 * coef / 3.0 * u_div;
903444129b9SMatthew G. Knepley   }
904444129b9SMatthew G. Knepley 
905444129b9SMatthew G. Knepley   // -p I
906444129b9SMatthew G. Knepley   for (c = 0; c < Nc; ++c) {
907444129b9SMatthew G. Knepley     f1[c*dim + c] -= u[uOff[PRES]];
908444129b9SMatthew G. Knepley   }
909444129b9SMatthew G. Knepley }
910444129b9SMatthew G. Knepley 
911444129b9SMatthew G. Knepley /* T_t + \vb{u} \cdot \nabla T */
912444129b9SMatthew G. Knepley static void f0_w(PetscInt dim, PetscInt Nf, PetscInt NfAux,
913444129b9SMatthew G. Knepley                  const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
914444129b9SMatthew G. Knepley                  const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
915444129b9SMatthew G. Knepley                  PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
916444129b9SMatthew G. Knepley {
917444129b9SMatthew G. Knepley   PetscInt d;
918444129b9SMatthew G. Knepley 
919444129b9SMatthew G. Knepley   /* T_t */
920444129b9SMatthew G. Knepley   f0[0] += u_t[uOff[TEMP]];
921444129b9SMatthew G. Knepley   /* \vb{u} \cdot \nabla T */
922444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) f0[0] += u[uOff[VEL] + d] * u_x[uOff_x[TEMP] + d];
923444129b9SMatthew G. Knepley }
924444129b9SMatthew G. Knepley 
925444129b9SMatthew G. Knepley /* \frac{C_p S p^{th}}{T} \frac{\partial T}{\partial t} + \frac{C_p p^{th}}{T} \vb{u} \cdot \nabla T */
926444129b9SMatthew G. Knepley static void f0_conduct_w(PetscInt dim, PetscInt Nf, PetscInt NfAux,
927444129b9SMatthew G. Knepley                          const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
928444129b9SMatthew G. Knepley                          const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
929444129b9SMatthew G. Knepley                          PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
930444129b9SMatthew G. Knepley {
931444129b9SMatthew G. Knepley   const PetscReal S    = PetscRealPart(constants[STROUHAL]);
932444129b9SMatthew G. Knepley   const PetscReal c_p  = PetscRealPart(constants[C_P]);
933444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
934444129b9SMatthew G. Knepley   PetscInt        d;
935444129b9SMatthew G. Knepley 
936444129b9SMatthew G. Knepley   // \frac{C_p S p^{th}}{T} \frac{\partial T}{\partial t}
937444129b9SMatthew G. Knepley   f0[0] = c_p * S * p_th / u[uOff[TEMP]] * u_t[uOff[TEMP]];
938444129b9SMatthew G. Knepley 
939444129b9SMatthew G. Knepley   // \frac{C_p p^{th}}{T} \vb{u} \cdot \nabla T
940444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
941444129b9SMatthew G. Knepley     f0[0] += c_p * p_th / u[uOff[TEMP]] * u[uOff[VEL] + d] * u_x[uOff_x[TEMP] + d];
942444129b9SMatthew G. Knepley   }
943444129b9SMatthew G. Knepley 
944444129b9SMatthew G. Knepley   // Add in any fixed source term
945444129b9SMatthew G. Knepley   if (NfAux > 0) {
946444129b9SMatthew G. Knepley     f0[0] += a[aOff[ENERGY]];
947444129b9SMatthew G. Knepley   }
948444129b9SMatthew G. Knepley }
949444129b9SMatthew G. Knepley 
950649ef022SMatthew Knepley static void f1_w(PetscInt dim, PetscInt Nf, PetscInt NfAux,
951649ef022SMatthew Knepley                  const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
952649ef022SMatthew Knepley                  const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
953649ef022SMatthew Knepley                  PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])
954649ef022SMatthew Knepley {
955444129b9SMatthew G. Knepley   const PetscReal alpha = PetscRealPart(constants[ALPHA]);
956649ef022SMatthew Knepley   PetscInt        d;
957444129b9SMatthew G. Knepley 
958649ef022SMatthew Knepley   for (d = 0; d < dim; ++d) f1[d] = alpha*u_x[uOff_x[2]+d];
959649ef022SMatthew Knepley }
960649ef022SMatthew Knepley 
961444129b9SMatthew G. Knepley /* \frac{k}{Pe} \nabla T */
962444129b9SMatthew G. Knepley static void f1_conduct_w(PetscInt dim, PetscInt Nf, PetscInt NfAux,
963444129b9SMatthew G. Knepley                          const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
964444129b9SMatthew G. Knepley                          const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
965444129b9SMatthew G. Knepley                          PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])
966444129b9SMatthew G. Knepley {
967444129b9SMatthew G. Knepley   const PetscReal Pe = PetscRealPart(constants[PECLET]);
968444129b9SMatthew G. Knepley   const PetscReal k  = PetscRealPart(constants[K]);
969444129b9SMatthew G. Knepley   PetscInt        d;
970444129b9SMatthew G. Knepley 
971444129b9SMatthew G. Knepley   // \frac{k}{Pe} \nabla T
972444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
973444129b9SMatthew G. Knepley     f1[d] = k / Pe * u_x[uOff_x[TEMP] + d];
974444129b9SMatthew G. Knepley   }
975444129b9SMatthew G. Knepley }
976444129b9SMatthew G. Knepley 
977649ef022SMatthew Knepley static void g1_qu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
978649ef022SMatthew Knepley                  const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
979649ef022SMatthew Knepley                  const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
980649ef022SMatthew Knepley                  PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[])
981649ef022SMatthew Knepley {
982649ef022SMatthew Knepley   PetscInt d;
983649ef022SMatthew Knepley   for (d = 0; d < dim; ++d) g1[d*dim+d] = 1.0;
984649ef022SMatthew Knepley }
985649ef022SMatthew Knepley 
986649ef022SMatthew Knepley static void g0_vu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
987649ef022SMatthew Knepley                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
988649ef022SMatthew Knepley                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
989649ef022SMatthew Knepley                   PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
990649ef022SMatthew Knepley {
991649ef022SMatthew Knepley   PetscInt c, d;
992649ef022SMatthew Knepley   const PetscInt  Nc = dim;
993649ef022SMatthew Knepley 
994649ef022SMatthew Knepley   for (d = 0; d < dim; ++d) g0[d*dim+d] = u_tShift;
995649ef022SMatthew Knepley 
996649ef022SMatthew Knepley   for (c = 0; c < Nc; ++c) {
997649ef022SMatthew Knepley     for (d = 0; d < dim; ++d) {
998649ef022SMatthew Knepley       g0[c*Nc+d] += u_x[ c*Nc+d];
999649ef022SMatthew Knepley     }
1000649ef022SMatthew Knepley   }
1001649ef022SMatthew Knepley }
1002649ef022SMatthew Knepley 
1003649ef022SMatthew Knepley static void g1_vu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1004649ef022SMatthew Knepley                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1005649ef022SMatthew Knepley                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1006649ef022SMatthew Knepley                   PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[])
1007649ef022SMatthew Knepley {
1008649ef022SMatthew Knepley   PetscInt NcI = dim;
1009649ef022SMatthew Knepley   PetscInt NcJ = dim;
1010649ef022SMatthew Knepley   PetscInt c, d, e;
1011649ef022SMatthew Knepley 
1012649ef022SMatthew Knepley   for (c = 0; c < NcI; ++c) {
1013649ef022SMatthew Knepley     for (d = 0; d < NcJ; ++d) {
1014649ef022SMatthew Knepley       for (e = 0; e < dim; ++e) {
1015649ef022SMatthew Knepley         if (c == d) {
1016649ef022SMatthew Knepley           g1[(c*NcJ+d)*dim+e] += u[e];
1017649ef022SMatthew Knepley         }
1018649ef022SMatthew Knepley       }
1019649ef022SMatthew Knepley     }
1020649ef022SMatthew Knepley   }
1021649ef022SMatthew Knepley }
1022649ef022SMatthew Knepley 
1023444129b9SMatthew G. Knepley static void g0_conduct_qu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1024444129b9SMatthew G. Knepley                           const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1025444129b9SMatthew G. Knepley                           const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1026444129b9SMatthew G. Knepley                           PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
1027444129b9SMatthew G. Knepley {
1028444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
1029444129b9SMatthew G. Knepley   PetscInt        d;
1030444129b9SMatthew G. Knepley 
1031444129b9SMatthew G. Knepley   // - \phi_i \frac{p^{th}}{T^2} \frac{\partial T}{\partial x_c} \psi_{j, u_c}
1032444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
1033444129b9SMatthew G. Knepley     g0[d] = -p_th / PetscSqr(u[uOff[TEMP]]) * u_x[uOff_x[TEMP] + d];
1034444129b9SMatthew G. Knepley   }
1035444129b9SMatthew G. Knepley }
1036444129b9SMatthew G. Knepley 
1037444129b9SMatthew G. Knepley static void g1_conduct_qu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1038444129b9SMatthew G. Knepley                           const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1039444129b9SMatthew G. Knepley                           const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1040444129b9SMatthew G. Knepley                           PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[])
1041444129b9SMatthew G. Knepley {
1042444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
1043444129b9SMatthew G. Knepley   PetscInt        d;
1044444129b9SMatthew G. Knepley 
1045444129b9SMatthew G. Knepley   // \phi_i \frac{p^{th}}{T} \frac{\partial \psi_{u_c,j}}{\partial x_c}
1046444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
1047444129b9SMatthew G. Knepley     g1[d * dim + d] = p_th / u[uOff[TEMP]];
1048444129b9SMatthew G. Knepley   }
1049444129b9SMatthew G. Knepley }
1050444129b9SMatthew G. Knepley 
1051444129b9SMatthew G. Knepley static void g0_conduct_qT(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1052444129b9SMatthew G. Knepley                           const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1053444129b9SMatthew G. Knepley                           const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1054444129b9SMatthew G. Knepley                           PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
1055444129b9SMatthew G. Knepley {
1056444129b9SMatthew G. Knepley   const PetscReal S    = PetscRealPart(constants[STROUHAL]);
1057444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
1058444129b9SMatthew G. Knepley   PetscInt        d;
1059444129b9SMatthew G. Knepley 
1060444129b9SMatthew G. Knepley   // - \phi_i \frac{S p^{th}}{T^2} \psi_j
1061444129b9SMatthew G. Knepley   g0[0] -= S * p_th / PetscSqr(u[uOff[TEMP]]) * u_tShift;
1062444129b9SMatthew G. Knepley   // \phi_i 2 \frac{S p^{th}}{T^3} T_t \psi_j
1063444129b9SMatthew G. Knepley   g0[0] += 2.0 * S * p_th / PetscPowScalarInt(u[uOff[TEMP]], 3) * u_t[uOff[TEMP]];
1064444129b9SMatthew G. Knepley   // \phi_i \frac{p^{th}}{T^2} \left( - \nabla \cdot \vb{u} \psi_j + \frac{2}{T} \vb{u} \cdot \nabla T \psi_j \right)
1065444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
1066444129b9SMatthew G. Knepley     g0[0] += p_th / PetscSqr(u[uOff[TEMP]]) * (-u_x[uOff_x[VEL] + d * dim + d] + 2.0 / u[uOff[TEMP]] * u[uOff[VEL] + d] * u_x[uOff_x[TEMP] + d]);
1067444129b9SMatthew G. Knepley   }
1068444129b9SMatthew G. Knepley }
1069444129b9SMatthew G. Knepley 
1070444129b9SMatthew G. Knepley static void g1_conduct_qT(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1071444129b9SMatthew G. Knepley                           const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1072444129b9SMatthew G. Knepley                           const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1073444129b9SMatthew G. Knepley                           PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[])
1074444129b9SMatthew G. Knepley {
1075444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
1076444129b9SMatthew G. Knepley   PetscInt        d;
1077444129b9SMatthew G. Knepley 
1078444129b9SMatthew G. Knepley   // - \phi_i \frac{p^{th}}{T^2} \vb{u} \cdot \nabla \psi_j
1079444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
1080444129b9SMatthew G. Knepley     g1[d] = -p_th / PetscSqr(u[uOff[TEMP]]) * u[uOff[VEL] + d];
1081444129b9SMatthew G. Knepley   }
1082444129b9SMatthew G. Knepley }
1083444129b9SMatthew G. Knepley 
1084649ef022SMatthew Knepley static void g2_vp(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1085649ef022SMatthew Knepley                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1086649ef022SMatthew Knepley                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1087649ef022SMatthew Knepley                   PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[])
1088649ef022SMatthew Knepley {
1089649ef022SMatthew Knepley   PetscInt d;
1090649ef022SMatthew Knepley   for (d = 0; d < dim; ++d) g2[d*dim+d] = -1.0;
1091649ef022SMatthew Knepley }
1092649ef022SMatthew Knepley 
1093649ef022SMatthew Knepley static void g3_vu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1094649ef022SMatthew Knepley                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1095649ef022SMatthew Knepley                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1096649ef022SMatthew Knepley                   PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])
1097649ef022SMatthew Knepley {
1098444129b9SMatthew G. Knepley    const PetscReal nu = PetscRealPart(constants[NU]);
1099649ef022SMatthew Knepley    const PetscInt  Nc = dim;
1100649ef022SMatthew Knepley    PetscInt        c, d;
1101649ef022SMatthew Knepley 
1102649ef022SMatthew Knepley   for (c = 0; c < Nc; ++c) {
1103649ef022SMatthew Knepley     for (d = 0; d < dim; ++d) {
1104606d57d4SMatthew G. Knepley       g3[((c*Nc+c)*dim+d)*dim+d] += nu;
1105606d57d4SMatthew G. Knepley       g3[((c*Nc+d)*dim+d)*dim+c] += nu;
1106649ef022SMatthew Knepley     }
1107649ef022SMatthew Knepley   }
1108649ef022SMatthew Knepley }
1109649ef022SMatthew Knepley 
1110444129b9SMatthew G. Knepley static void g0_conduct_vT(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1111444129b9SMatthew G. Knepley                           const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1112444129b9SMatthew G. Knepley                           const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1113444129b9SMatthew G. Knepley                           PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
1114444129b9SMatthew G. Knepley {
1115444129b9SMatthew G. Knepley   const PetscReal S    = PetscRealPart(constants[STROUHAL]);
1116444129b9SMatthew G. Knepley   const PetscReal F    = PetscRealPart(constants[FROUDE]);
1117444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
1118444129b9SMatthew G. Knepley   const PetscInt  gdir = (PetscInt) PetscRealPart(constants[G_DIR]);
1119444129b9SMatthew G. Knepley   const PetscInt  Nc = dim;
1120444129b9SMatthew G. Knepley   PetscInt        c, d;
1121444129b9SMatthew G. Knepley 
1122444129b9SMatthew G. Knepley   // - \vb{\phi}_i \cdot \vb{u}_t \frac{p^{th} S}{T^2} \psi_j
1123444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
1124444129b9SMatthew G. Knepley     g0[d] -= p_th * S / PetscSqr(u[uOff[TEMP]]) * u_t[uOff[VEL] + d];
1125444129b9SMatthew G. Knepley   }
1126444129b9SMatthew G. Knepley 
1127444129b9SMatthew G. Knepley   // - \vb{\phi}_i \cdot \vb{u} \cdot \nabla \vb{u} \frac{p^{th}}{T^2} \psi_j
1128444129b9SMatthew G. Knepley   for (c = 0; c < Nc; ++c) {
1129444129b9SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
1130444129b9SMatthew G. Knepley       g0[c] -= p_th / PetscSqr(u[uOff[TEMP]]) * u[uOff[VEL] + d] * u_x[uOff_x[VEL] + c * dim + d];
1131444129b9SMatthew G. Knepley     }
1132444129b9SMatthew G. Knepley   }
1133444129b9SMatthew G. Knepley 
1134444129b9SMatthew G. Knepley   // - \vb{\phi}_i \cdot \vu{z} \frac{p^{th}}{T^2 F^2} \psi_j
1135444129b9SMatthew G. Knepley   g0[gdir] -= p_th / PetscSqr(u[uOff[TEMP]] * F);
1136444129b9SMatthew G. Knepley }
1137444129b9SMatthew G. Knepley 
1138444129b9SMatthew G. Knepley static void g0_conduct_vu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1139444129b9SMatthew G. Knepley                           const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1140444129b9SMatthew G. Knepley                           const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1141444129b9SMatthew G. Knepley                           PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
1142444129b9SMatthew G. Knepley {
1143444129b9SMatthew G. Knepley   const PetscReal S    = PetscRealPart(constants[STROUHAL]);
1144444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
1145444129b9SMatthew G. Knepley   const PetscInt  Nc   = dim;
1146444129b9SMatthew G. Knepley   PetscInt        c, d;
1147444129b9SMatthew G. Knepley 
1148444129b9SMatthew G. Knepley   // \vb{\phi}_i \cdot S \rho \psi_j
1149444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
1150444129b9SMatthew G. Knepley     g0[d * dim + d] = S * p_th / u[uOff[TEMP]] * u_tShift;
1151444129b9SMatthew G. Knepley   }
1152444129b9SMatthew G. Knepley 
1153444129b9SMatthew G. Knepley   // \phi^c_i \cdot \rho \frac{\partial u^c}{\partial x^d} \psi^d_j
1154444129b9SMatthew G. Knepley   for (c = 0; c < Nc; ++c) {
1155444129b9SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
1156444129b9SMatthew G. Knepley       g0[c * Nc + d] += p_th / u[uOff[TEMP]] * u_x[uOff_x[VEL] + c * Nc + d];
1157444129b9SMatthew G. Knepley     }
1158444129b9SMatthew G. Knepley   }
1159444129b9SMatthew G. Knepley }
1160444129b9SMatthew G. Knepley 
1161444129b9SMatthew G. Knepley static void g1_conduct_vu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1162444129b9SMatthew G. Knepley                           const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1163444129b9SMatthew G. Knepley                           const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1164444129b9SMatthew G. Knepley                           PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[])
1165444129b9SMatthew G. Knepley {
1166444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
1167444129b9SMatthew G. Knepley   const PetscInt  NcI = dim;
1168444129b9SMatthew G. Knepley   const PetscInt  NcJ = dim;
1169444129b9SMatthew G. Knepley   PetscInt        c, d, e;
1170444129b9SMatthew G. Knepley 
1171444129b9SMatthew G. Knepley   // \phi^c_i \rho u^e \frac{\partial \psi^d_j}{\partial x^e}
1172444129b9SMatthew G. Knepley   for (c = 0; c < NcI; ++c) {
1173444129b9SMatthew G. Knepley     for (d = 0; d < NcJ; ++d) {
1174444129b9SMatthew G. Knepley       for (e = 0; e < dim; ++e) {
1175444129b9SMatthew G. Knepley         if (c == d) {
1176444129b9SMatthew G. Knepley           g1[(c * NcJ + d) * dim + e] += p_th / u[uOff[TEMP]] * u[uOff[VEL] + e];
1177444129b9SMatthew G. Knepley         }
1178444129b9SMatthew G. Knepley       }
1179444129b9SMatthew G. Knepley     }
1180444129b9SMatthew G. Knepley   }
1181444129b9SMatthew G. Knepley }
1182444129b9SMatthew G. Knepley 
1183444129b9SMatthew G. Knepley static void g3_conduct_vu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1184444129b9SMatthew G. Knepley                           const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1185444129b9SMatthew G. Knepley                           const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1186444129b9SMatthew G. Knepley                           PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])
1187444129b9SMatthew G. Knepley {
1188444129b9SMatthew G. Knepley   const PetscReal Re = PetscRealPart(constants[REYNOLDS]);
1189444129b9SMatthew G. Knepley   const PetscReal mu = PetscRealPart(constants[MU]);
1190444129b9SMatthew G. Knepley   const PetscInt  Nc = dim;
1191444129b9SMatthew G. Knepley   PetscInt        c, d;
1192444129b9SMatthew G. Knepley 
1193444129b9SMatthew G. Knepley   for (c = 0; c < Nc; ++c) {
1194444129b9SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
1195444129b9SMatthew G. Knepley       // \frac{\partial \phi^c_i}{\partial x^d} \mu/Re \frac{\partial \psi^c_i}{\partial x^d}
1196444129b9SMatthew G. Knepley       g3[((c * Nc + c) * dim + d) * dim + d] += mu / Re;  // gradU
1197444129b9SMatthew G. Knepley       // \frac{\partial \phi^c_i}{\partial x^d} \mu/Re \frac{\partial \psi^d_i}{\partial x^c}
1198444129b9SMatthew G. Knepley       g3[((c * Nc + d) * dim + d) * dim + c] += mu / Re;  // gradU transpose
1199444129b9SMatthew G. Knepley       // \frac{\partial \phi^c_i}{\partial x^d} -2/3 \mu/Re \frac{\partial \psi^d_i}{\partial x^c}
1200444129b9SMatthew G. Knepley       g3[((c * Nc + d) * dim + c) * dim + d] -= 2.0 / 3.0 * mu / Re;
1201444129b9SMatthew G. Knepley     }
1202444129b9SMatthew G. Knepley   }
1203444129b9SMatthew G. Knepley }
1204444129b9SMatthew G. Knepley 
1205444129b9SMatthew G. Knepley static void g2_conduct_vp(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1206444129b9SMatthew G. Knepley                           const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1207444129b9SMatthew G. Knepley                           const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1208444129b9SMatthew G. Knepley                           PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[])
1209444129b9SMatthew G. Knepley {
1210444129b9SMatthew G. Knepley   PetscInt d;
1211444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
1212444129b9SMatthew G. Knepley     g2[d * dim + d] = -1.0;
1213444129b9SMatthew G. Knepley   }
1214444129b9SMatthew G. Knepley }
1215444129b9SMatthew G. Knepley 
1216649ef022SMatthew Knepley static void g0_wT(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1217649ef022SMatthew Knepley                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1218649ef022SMatthew Knepley                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1219649ef022SMatthew Knepley                   PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
1220649ef022SMatthew Knepley {
1221a712f3bbSMatthew G. Knepley   g0[0] = u_tShift;
1222649ef022SMatthew Knepley }
1223649ef022SMatthew Knepley 
1224649ef022SMatthew Knepley static void g0_wu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1225649ef022SMatthew Knepley                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1226649ef022SMatthew Knepley                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1227649ef022SMatthew Knepley                   PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
1228649ef022SMatthew Knepley {
1229649ef022SMatthew Knepley   PetscInt d;
1230649ef022SMatthew Knepley   for (d = 0; d < dim; ++d) g0[d] = u_x[uOff_x[2]+d];
1231649ef022SMatthew Knepley }
1232649ef022SMatthew Knepley 
1233649ef022SMatthew Knepley static void g1_wT(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1234649ef022SMatthew Knepley                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1235649ef022SMatthew Knepley                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1236649ef022SMatthew Knepley                   PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[])
1237649ef022SMatthew Knepley {
1238649ef022SMatthew Knepley   PetscInt d;
1239649ef022SMatthew Knepley   for (d = 0; d < dim; ++d) g1[d] = u[uOff[0]+d];
1240649ef022SMatthew Knepley }
1241649ef022SMatthew Knepley 
1242649ef022SMatthew Knepley static void g3_wT(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1243649ef022SMatthew Knepley                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1244649ef022SMatthew Knepley                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1245649ef022SMatthew Knepley                   PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])
1246649ef022SMatthew Knepley {
1247444129b9SMatthew G. Knepley   const PetscReal alpha = PetscRealPart(constants[ALPHA]);
1248649ef022SMatthew Knepley   PetscInt        d;
1249649ef022SMatthew Knepley 
1250649ef022SMatthew Knepley   for (d = 0; d < dim; ++d) g3[d*dim+d] = alpha;
1251649ef022SMatthew Knepley }
1252649ef022SMatthew Knepley 
1253444129b9SMatthew G. Knepley static void g0_conduct_wu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1254444129b9SMatthew G. Knepley                           const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1255444129b9SMatthew G. Knepley                           const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1256444129b9SMatthew G. Knepley                           PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
1257444129b9SMatthew G. Knepley {
1258444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
1259444129b9SMatthew G. Knepley   const PetscReal c_p  = PetscRealPart(constants[C_P]);
1260444129b9SMatthew G. Knepley   PetscInt        d;
1261444129b9SMatthew G. Knepley 
1262444129b9SMatthew G. Knepley   // \phi_i \frac{C_p p^{th}}{T} \nabla T \cdot \psi_j
1263444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
1264444129b9SMatthew G. Knepley     g0[d] = c_p * p_th / u[uOff[TEMP]] * u_x[uOff_x[TEMP] + d];
1265444129b9SMatthew G. Knepley   }
1266444129b9SMatthew G. Knepley }
1267444129b9SMatthew G. Knepley 
1268444129b9SMatthew G. Knepley static void g0_conduct_wT(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1269444129b9SMatthew G. Knepley                           const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1270444129b9SMatthew G. Knepley                           const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1271444129b9SMatthew G. Knepley                           PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
1272444129b9SMatthew G. Knepley {
1273444129b9SMatthew G. Knepley   const PetscReal S    = PetscRealPart(constants[STROUHAL]);
1274444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
1275444129b9SMatthew G. Knepley   const PetscReal c_p  = PetscRealPart(constants[C_P]);
1276444129b9SMatthew G. Knepley   PetscInt        d;
1277444129b9SMatthew G. Knepley 
1278444129b9SMatthew G. Knepley   // \psi_i C_p S p^{th}\T \psi_{j}
1279444129b9SMatthew G. Knepley   g0[0] += c_p * S * p_th / u[uOff[TEMP]] * u_tShift;
1280444129b9SMatthew G. Knepley   // - \phi_i C_p S p^{th}/T^2 T_t \psi_j
1281444129b9SMatthew G. Knepley   g0[0] -= c_p * S * p_th / PetscSqr(u[uOff[TEMP]]) * u_t[uOff[TEMP]];
1282444129b9SMatthew G. Knepley   // - \phi_i C_p p^{th}/T^2 \vb{u} \cdot \nabla T \psi_j
1283444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
1284444129b9SMatthew G. Knepley     g0[0] -= c_p * p_th / PetscSqr(u[uOff[TEMP]]) * u[uOff[VEL] + d] * u_x[uOff_x[TEMP] + d];
1285444129b9SMatthew G. Knepley   }
1286444129b9SMatthew G. Knepley }
1287444129b9SMatthew G. Knepley 
1288444129b9SMatthew G. Knepley static void g1_conduct_wT(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1289444129b9SMatthew G. Knepley                           const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1290444129b9SMatthew G. Knepley                           const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1291444129b9SMatthew G. Knepley                           PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[])
1292444129b9SMatthew G. Knepley {
1293444129b9SMatthew G. Knepley   const PetscReal p_th = PetscRealPart(constants[P_TH]);
1294444129b9SMatthew G. Knepley   const PetscReal c_p  = PetscRealPart(constants[C_P]);
1295444129b9SMatthew G. Knepley   PetscInt        d;
1296444129b9SMatthew G. Knepley 
1297444129b9SMatthew G. Knepley   // \phi_i C_p p^{th}/T \vb{u} \cdot \nabla \psi_j
1298444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
1299444129b9SMatthew G. Knepley     g1[d] += c_p * p_th / u[uOff[TEMP]] * u[uOff[VEL] + d];
1300444129b9SMatthew G. Knepley   }
1301444129b9SMatthew G. Knepley }
1302444129b9SMatthew G. Knepley 
1303444129b9SMatthew G. Knepley static void g3_conduct_wT(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1304444129b9SMatthew G. Knepley                           const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1305444129b9SMatthew G. Knepley                           const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1306444129b9SMatthew G. Knepley                           PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])
1307444129b9SMatthew G. Knepley {
1308444129b9SMatthew G. Knepley   const PetscReal Pe = PetscRealPart(constants[PECLET]);
1309444129b9SMatthew G. Knepley   const PetscReal k  = PetscRealPart(constants[K]);
1310444129b9SMatthew G. Knepley   PetscInt        d;
1311444129b9SMatthew G. Knepley 
1312444129b9SMatthew G. Knepley   // \nabla \phi_i \frac{k}{Pe} \nabla \phi_j
1313444129b9SMatthew G. Knepley   for (d = 0; d < dim; ++d) {
1314444129b9SMatthew G. Knepley     g3[d * dim + d] = k / Pe;
1315444129b9SMatthew G. Knepley   }
1316444129b9SMatthew G. Knepley }
1317444129b9SMatthew G. Knepley 
1318649ef022SMatthew Knepley static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
1319649ef022SMatthew Knepley {
1320444129b9SMatthew G. Knepley   PetscInt       mod, sol;
1321649ef022SMatthew Knepley   PetscErrorCode ierr;
1322649ef022SMatthew Knepley 
1323649ef022SMatthew Knepley   PetscFunctionBeginUser;
1324444129b9SMatthew G. Knepley   options->modType      = MOD_INCOMPRESSIBLE;
1325649ef022SMatthew Knepley   options->solType      = SOL_QUADRATIC;
1326444129b9SMatthew G. Knepley   options->hasNullSpace = PETSC_TRUE;
1327*367970cfSMatthew G. Knepley   options->dmCell       = NULL;
1328649ef022SMatthew Knepley 
1329649ef022SMatthew Knepley   ierr = PetscOptionsBegin(comm, "", "Low Mach flow Problem Options", "DMPLEX");CHKERRQ(ierr);
1330444129b9SMatthew G. Knepley   mod = options->modType;
1331444129b9SMatthew G. Knepley   ierr = PetscOptionsEList("-mod_type", "The model type", "ex76.c", modTypes, NUM_MOD_TYPES, modTypes[options->modType], &mod, NULL);CHKERRQ(ierr);
1332444129b9SMatthew G. Knepley   options->modType = (ModType) mod;
1333649ef022SMatthew Knepley   sol = options->solType;
1334444129b9SMatthew G. Knepley   ierr = PetscOptionsEList("-sol_type", "The solution type", "ex76.c", solTypes, NUM_SOL_TYPES, solTypes[options->solType], &sol, NULL);CHKERRQ(ierr);
1335649ef022SMatthew Knepley   options->solType = (SolType) sol;
13361e1ea65dSPierre Jolivet   ierr = PetscOptionsEnd();CHKERRQ(ierr);
1337649ef022SMatthew Knepley   PetscFunctionReturn(0);
1338649ef022SMatthew Knepley }
1339649ef022SMatthew Knepley 
1340444129b9SMatthew G. Knepley static PetscErrorCode SetupParameters(DM dm, AppCtx *user)
1341649ef022SMatthew Knepley {
1342649ef022SMatthew Knepley   PetscBag       bag;
1343649ef022SMatthew Knepley   Parameter     *p;
1344444129b9SMatthew G. Knepley   PetscReal      dir;
1345444129b9SMatthew G. Knepley   PetscInt       dim;
1346649ef022SMatthew Knepley   PetscErrorCode ierr;
1347649ef022SMatthew Knepley 
1348649ef022SMatthew Knepley   PetscFunctionBeginUser;
1349444129b9SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1350444129b9SMatthew G. Knepley   dir  = (PetscReal) (dim-1);
1351649ef022SMatthew Knepley   /* setup PETSc parameter bag */
1352649ef022SMatthew Knepley   ierr = PetscBagGetData(user->bag, (void **) &p);CHKERRQ(ierr);
1353649ef022SMatthew Knepley   ierr = PetscBagSetName(user->bag, "par", "Low Mach flow parameters");CHKERRQ(ierr);
1354649ef022SMatthew Knepley   bag  = user->bag;
1355444129b9SMatthew G. Knepley   ierr = PetscBagRegisterReal(bag, &p->Strouhal, 1.0, "S",     "Strouhal number");CHKERRQ(ierr);
1356444129b9SMatthew G. Knepley   ierr = PetscBagRegisterReal(bag, &p->Froude,   1.0, "Fr",    "Froude number");CHKERRQ(ierr);
1357444129b9SMatthew G. Knepley   ierr = PetscBagRegisterReal(bag, &p->Reynolds, 1.0, "Re",    "Reynolds number");CHKERRQ(ierr);
1358444129b9SMatthew G. Knepley   ierr = PetscBagRegisterReal(bag, &p->Peclet,   1.0, "Pe",    "Peclet number");CHKERRQ(ierr);
1359444129b9SMatthew G. Knepley   ierr = PetscBagRegisterReal(bag, &p->p_th,     1.0, "p_th",  "Thermodynamic pressure");CHKERRQ(ierr);
1360444129b9SMatthew G. Knepley   ierr = PetscBagRegisterReal(bag, &p->mu,       1.0, "mu",    "Dynamic viscosity");CHKERRQ(ierr);
1361649ef022SMatthew Knepley   ierr = PetscBagRegisterReal(bag, &p->nu,       1.0, "nu",    "Kinematic viscosity");CHKERRQ(ierr);
1362444129b9SMatthew G. Knepley   ierr = PetscBagRegisterReal(bag, &p->c_p,      1.0, "c_p",   "Specific heat at constant pressure");CHKERRQ(ierr);
1363444129b9SMatthew G. Knepley   ierr = PetscBagRegisterReal(bag, &p->k,        1.0, "k",     "Thermal conductivity");CHKERRQ(ierr);
1364649ef022SMatthew Knepley   ierr = PetscBagRegisterReal(bag, &p->alpha,    1.0, "alpha", "Thermal diffusivity");CHKERRQ(ierr);
1365649ef022SMatthew Knepley   ierr = PetscBagRegisterReal(bag, &p->T_in,     1.0, "T_in",  "Inlet temperature");CHKERRQ(ierr);
1366444129b9SMatthew G. Knepley   ierr = PetscBagRegisterReal(bag, &p->g_dir,    dir, "g_dir", "Gravity direction");CHKERRQ(ierr);
1367*367970cfSMatthew G. Knepley   ierr = PetscBagRegisterReal(bag, &p->epsilon,  1.0, "epsilon", "Perturbation strength");CHKERRQ(ierr);
1368649ef022SMatthew Knepley   PetscFunctionReturn(0);
1369649ef022SMatthew Knepley }
1370649ef022SMatthew Knepley 
1371649ef022SMatthew Knepley static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm)
1372649ef022SMatthew Knepley {
1373649ef022SMatthew Knepley   PetscErrorCode ierr;
1374649ef022SMatthew Knepley 
1375649ef022SMatthew Knepley   PetscFunctionBeginUser;
137630602db0SMatthew G. Knepley   ierr = DMCreate(comm, dm);CHKERRQ(ierr);
137730602db0SMatthew G. Knepley   ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr);
1378649ef022SMatthew Knepley   ierr = DMSetFromOptions(*dm);CHKERRQ(ierr);
1379649ef022SMatthew Knepley   ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr);
1380649ef022SMatthew Knepley   PetscFunctionReturn(0);
1381649ef022SMatthew Knepley }
1382649ef022SMatthew Knepley 
1383444129b9SMatthew G. Knepley static PetscErrorCode UniformBoundaryConditions(DM dm, DMLabel label, PetscSimplePointFunc exactFuncs[], PetscSimplePointFunc exactFuncs_t[], AppCtx *user)
1384444129b9SMatthew G. Knepley {
1385444129b9SMatthew G. Knepley   PetscDS        ds;
1386444129b9SMatthew G. Knepley   PetscInt       id;
1387444129b9SMatthew G. Knepley   void          *ctx;
1388444129b9SMatthew G. Knepley   PetscErrorCode ierr;
1389444129b9SMatthew G. Knepley 
1390444129b9SMatthew G. Knepley   PetscFunctionBeginUser;
1391444129b9SMatthew G. Knepley   ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
1392444129b9SMatthew G. Knepley   ierr = PetscBagGetData(user->bag, &ctx);CHKERRQ(ierr);
1393444129b9SMatthew G. Knepley   id   = 3;
1394444129b9SMatthew G. Knepley   ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "top wall velocity",    label, 1, &id, VEL, 0, NULL, (void (*)(void)) exactFuncs[VEL], (void (*)(void)) exactFuncs_t[VEL], ctx, NULL);CHKERRQ(ierr);
1395444129b9SMatthew G. Knepley   id   = 1;
1396444129b9SMatthew G. Knepley   ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "bottom wall velocity", label, 1, &id, VEL, 0, NULL, (void (*)(void)) exactFuncs[VEL], (void (*)(void)) exactFuncs_t[VEL], ctx, NULL);CHKERRQ(ierr);
1397444129b9SMatthew G. Knepley   id   = 2;
1398444129b9SMatthew G. Knepley   ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "right wall velocity",  label, 1, &id, VEL, 0, NULL, (void (*)(void)) exactFuncs[VEL], (void (*)(void)) exactFuncs_t[VEL], ctx, NULL);CHKERRQ(ierr);
1399444129b9SMatthew G. Knepley   id   = 4;
1400444129b9SMatthew G. Knepley   ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "left wall velocity",   label, 1, &id, VEL, 0, NULL, (void (*)(void)) exactFuncs[VEL], (void (*)(void)) exactFuncs_t[VEL], ctx, NULL);CHKERRQ(ierr);
1401444129b9SMatthew G. Knepley   id   = 3;
1402444129b9SMatthew G. Knepley   ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "top wall temp",    label, 1, &id, TEMP, 0, NULL, (void (*)(void)) exactFuncs[TEMP], (void (*)(void)) exactFuncs_t[TEMP], ctx, NULL);CHKERRQ(ierr);
1403444129b9SMatthew G. Knepley   id   = 1;
1404444129b9SMatthew G. Knepley   ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "bottom wall temp", label, 1, &id, TEMP, 0, NULL, (void (*)(void)) exactFuncs[TEMP], (void (*)(void)) exactFuncs_t[TEMP], ctx, NULL);CHKERRQ(ierr);
1405444129b9SMatthew G. Knepley   id   = 2;
1406444129b9SMatthew G. Knepley   ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "right wall temp",  label, 1, &id, TEMP, 0, NULL, (void (*)(void)) exactFuncs[TEMP], (void (*)(void)) exactFuncs_t[TEMP], ctx, NULL);CHKERRQ(ierr);
1407444129b9SMatthew G. Knepley   id   = 4;
1408444129b9SMatthew G. Knepley   ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "left wall temp",   label, 1, &id, TEMP, 0, NULL, (void (*)(void)) exactFuncs[TEMP], (void (*)(void)) exactFuncs_t[TEMP], ctx, NULL);CHKERRQ(ierr);
1409444129b9SMatthew G. Knepley   PetscFunctionReturn(0);
1410444129b9SMatthew G. Knepley }
1411444129b9SMatthew G. Knepley 
1412649ef022SMatthew Knepley static PetscErrorCode SetupProblem(DM dm, AppCtx *user)
1413649ef022SMatthew Knepley {
141445480ffeSMatthew G. Knepley   PetscSimplePointFunc exactFuncs[3];
141545480ffeSMatthew G. Knepley   PetscSimplePointFunc exactFuncs_t[3];
1416444129b9SMatthew G. Knepley   PetscDS              ds;
1417444129b9SMatthew G. Knepley   PetscWeakForm        wf;
141845480ffeSMatthew G. Knepley   DMLabel              label;
1419649ef022SMatthew Knepley   Parameter           *ctx;
1420444129b9SMatthew G. Knepley   PetscInt             id, bd;
1421649ef022SMatthew Knepley   PetscErrorCode       ierr;
1422649ef022SMatthew Knepley 
1423649ef022SMatthew Knepley   PetscFunctionBeginUser;
142445480ffeSMatthew G. Knepley   ierr = DMGetLabel(dm, "marker", &label);CHKERRQ(ierr);
1425444129b9SMatthew G. Knepley   ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
1426444129b9SMatthew G. Knepley   ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr);
1427444129b9SMatthew G. Knepley 
1428444129b9SMatthew G. Knepley   switch(user->modType) {
1429444129b9SMatthew G. Knepley     case MOD_INCOMPRESSIBLE:
1430444129b9SMatthew G. Knepley       ierr = PetscDSSetResidual(ds, VEL,  f0_v, f1_v);CHKERRQ(ierr);
1431444129b9SMatthew G. Knepley       ierr = PetscDSSetResidual(ds, PRES, f0_q, NULL);CHKERRQ(ierr);
1432444129b9SMatthew G. Knepley       ierr = PetscDSSetResidual(ds, TEMP, f0_w, f1_w);CHKERRQ(ierr);
1433444129b9SMatthew G. Knepley 
1434444129b9SMatthew G. Knepley       ierr = PetscDSSetJacobian(ds, VEL,  VEL,  g0_vu, g1_vu, NULL,  g3_vu);CHKERRQ(ierr);
1435444129b9SMatthew G. Knepley       ierr = PetscDSSetJacobian(ds, VEL,  PRES, NULL,  NULL,  g2_vp, NULL);CHKERRQ(ierr);
1436444129b9SMatthew G. Knepley       ierr = PetscDSSetJacobian(ds, PRES, VEL,  NULL,  g1_qu, NULL,  NULL);CHKERRQ(ierr);
1437444129b9SMatthew G. Knepley       ierr = PetscDSSetJacobian(ds, TEMP, VEL,  g0_wu, NULL,  NULL,  NULL);CHKERRQ(ierr);
1438444129b9SMatthew G. Knepley       ierr = PetscDSSetJacobian(ds, TEMP, TEMP, g0_wT, g1_wT, NULL,  g3_wT);CHKERRQ(ierr);
1439444129b9SMatthew G. Knepley 
1440649ef022SMatthew Knepley       switch(user->solType) {
1441649ef022SMatthew Knepley       case SOL_QUADRATIC:
1442444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, VEL,  0, 1, f0_quadratic_v, 0, NULL);CHKERRQ(ierr);
1443444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, TEMP, 0, 1, f0_quadratic_w, 0, NULL);CHKERRQ(ierr);
1444649ef022SMatthew Knepley 
1445444129b9SMatthew G. Knepley         exactFuncs[VEL]    = quadratic_u;
1446444129b9SMatthew G. Knepley         exactFuncs[PRES]   = quadratic_p;
1447444129b9SMatthew G. Knepley         exactFuncs[TEMP]   = quadratic_T;
1448444129b9SMatthew G. Knepley         exactFuncs_t[VEL]  = quadratic_u_t;
1449444129b9SMatthew G. Knepley         exactFuncs_t[PRES] = NULL;
1450444129b9SMatthew G. Knepley         exactFuncs_t[TEMP] = quadratic_T_t;
1451444129b9SMatthew G. Knepley 
1452444129b9SMatthew G. Knepley         ierr = UniformBoundaryConditions(dm, label, exactFuncs, exactFuncs_t, user);CHKERRQ(ierr);
1453649ef022SMatthew Knepley         break;
1454649ef022SMatthew Knepley       case SOL_CUBIC:
1455444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, VEL,  0, 1, f0_cubic_v, 0, NULL);CHKERRQ(ierr);
1456444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, TEMP, 0, 1, f0_cubic_w, 0, NULL);CHKERRQ(ierr);
1457649ef022SMatthew Knepley 
1458444129b9SMatthew G. Knepley         exactFuncs[VEL]    = cubic_u;
1459444129b9SMatthew G. Knepley         exactFuncs[PRES]   = cubic_p;
1460444129b9SMatthew G. Knepley         exactFuncs[TEMP]   = cubic_T;
1461444129b9SMatthew G. Knepley         exactFuncs_t[VEL]  = cubic_u_t;
1462444129b9SMatthew G. Knepley         exactFuncs_t[PRES] = NULL;
1463444129b9SMatthew G. Knepley         exactFuncs_t[TEMP] = cubic_T_t;
1464444129b9SMatthew G. Knepley 
1465444129b9SMatthew G. Knepley         ierr = UniformBoundaryConditions(dm, label, exactFuncs, exactFuncs_t, user);CHKERRQ(ierr);
1466649ef022SMatthew Knepley         break;
1467649ef022SMatthew Knepley       case SOL_CUBIC_TRIG:
1468444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, VEL,  0, 1, f0_cubic_trig_v, 0, NULL);CHKERRQ(ierr);
1469444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, TEMP, 0, 1, f0_cubic_trig_w, 0, NULL);CHKERRQ(ierr);
1470649ef022SMatthew Knepley 
1471444129b9SMatthew G. Knepley         exactFuncs[VEL]    = cubic_trig_u;
1472444129b9SMatthew G. Knepley         exactFuncs[PRES]   = cubic_trig_p;
1473444129b9SMatthew G. Knepley         exactFuncs[TEMP]   = cubic_trig_T;
1474444129b9SMatthew G. Knepley         exactFuncs_t[VEL]  = cubic_trig_u_t;
1475444129b9SMatthew G. Knepley         exactFuncs_t[PRES] = NULL;
1476444129b9SMatthew G. Knepley         exactFuncs_t[TEMP] = cubic_trig_T_t;
1477444129b9SMatthew G. Knepley 
1478444129b9SMatthew G. Knepley         ierr = UniformBoundaryConditions(dm, label, exactFuncs, exactFuncs_t, user);CHKERRQ(ierr);
1479649ef022SMatthew Knepley         break;
1480606d57d4SMatthew G. Knepley       case SOL_TAYLOR_GREEN:
1481444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, TEMP, 0, 1, f0_taylor_green_w, 0, NULL);CHKERRQ(ierr);
1482606d57d4SMatthew G. Knepley 
1483444129b9SMatthew G. Knepley         exactFuncs[VEL]    = taylor_green_u;
1484444129b9SMatthew G. Knepley         exactFuncs[PRES]   = taylor_green_p;
1485444129b9SMatthew G. Knepley         exactFuncs[TEMP]   = taylor_green_T;
1486444129b9SMatthew G. Knepley         exactFuncs_t[VEL]  = taylor_green_u_t;
1487444129b9SMatthew G. Knepley         exactFuncs_t[PRES] = taylor_green_p_t;
1488444129b9SMatthew G. Knepley         exactFuncs_t[TEMP] = taylor_green_T_t;
1489444129b9SMatthew G. Knepley 
1490444129b9SMatthew G. Knepley         ierr = UniformBoundaryConditions(dm, label, exactFuncs, exactFuncs_t, user);CHKERRQ(ierr);
1491606d57d4SMatthew G. Knepley         break;
1492444129b9SMatthew G. Knepley        default: SETERRQ2(PetscObjectComm((PetscObject) ds), PETSC_ERR_ARG_WRONG, "Unsupported solution type: %s (%D)", solTypes[PetscMin(user->solType, NUM_SOL_TYPES)], user->solType);
1493649ef022SMatthew Knepley       }
1494444129b9SMatthew G. Knepley       break;
1495444129b9SMatthew G. Knepley     case MOD_CONDUCTING:
1496444129b9SMatthew G. Knepley       ierr = PetscDSSetResidual(ds, VEL,  f0_conduct_v, f1_conduct_v);CHKERRQ(ierr);
1497444129b9SMatthew G. Knepley       ierr = PetscDSSetResidual(ds, PRES, f0_conduct_q, NULL);CHKERRQ(ierr);
1498444129b9SMatthew G. Knepley       ierr = PetscDSSetResidual(ds, TEMP, f0_conduct_w, f1_conduct_w);CHKERRQ(ierr);
1499649ef022SMatthew Knepley 
1500444129b9SMatthew G. Knepley       ierr = PetscDSSetJacobian(ds, VEL,  VEL,  g0_conduct_vu, g1_conduct_vu, NULL,          g3_conduct_vu);CHKERRQ(ierr);
1501444129b9SMatthew G. Knepley       ierr = PetscDSSetJacobian(ds, VEL,  PRES, NULL,          NULL,          g2_conduct_vp, NULL);CHKERRQ(ierr);
1502444129b9SMatthew G. Knepley       ierr = PetscDSSetJacobian(ds, VEL,  TEMP, g0_conduct_vT, NULL,          NULL,          NULL);CHKERRQ(ierr);
1503444129b9SMatthew G. Knepley       ierr = PetscDSSetJacobian(ds, PRES, VEL,  g0_conduct_qu, g1_conduct_qu, NULL,          NULL);CHKERRQ(ierr);
1504444129b9SMatthew G. Knepley       ierr = PetscDSSetJacobian(ds, PRES, TEMP, g0_conduct_qT, g1_conduct_qT, NULL,          NULL);CHKERRQ(ierr);
1505444129b9SMatthew G. Knepley       ierr = PetscDSSetJacobian(ds, TEMP, VEL,  g0_conduct_wu, NULL,          NULL,          NULL);CHKERRQ(ierr);
1506444129b9SMatthew G. Knepley       ierr = PetscDSSetJacobian(ds, TEMP, TEMP, g0_conduct_wT, g1_conduct_wT, NULL,          g3_conduct_wT);CHKERRQ(ierr);
1507649ef022SMatthew Knepley 
1508444129b9SMatthew G. Knepley       switch(user->solType) {
1509444129b9SMatthew G. Knepley       case SOL_QUADRATIC:
1510444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, VEL,  0, 1, f0_conduct_quadratic_v, 0, NULL);CHKERRQ(ierr);
1511444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, PRES, 0, 1, f0_conduct_quadratic_q, 0, NULL);CHKERRQ(ierr);
1512444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, TEMP, 0, 1, f0_conduct_quadratic_w, 0, NULL);CHKERRQ(ierr);
1513444129b9SMatthew G. Knepley 
1514444129b9SMatthew G. Knepley         exactFuncs[VEL]    = quadratic_u;
1515444129b9SMatthew G. Knepley         exactFuncs[PRES]   = quadratic_p;
1516444129b9SMatthew G. Knepley         exactFuncs[TEMP]   = quadratic_T;
1517444129b9SMatthew G. Knepley         exactFuncs_t[VEL]  = quadratic_u_t;
1518444129b9SMatthew G. Knepley         exactFuncs_t[PRES] = NULL;
1519444129b9SMatthew G. Knepley         exactFuncs_t[TEMP] = quadratic_T_t;
1520444129b9SMatthew G. Knepley 
1521444129b9SMatthew G. Knepley         ierr = UniformBoundaryConditions(dm, label, exactFuncs, exactFuncs_t, user);CHKERRQ(ierr);
1522444129b9SMatthew G. Knepley         break;
1523444129b9SMatthew G. Knepley       case SOL_PIPE:
1524444129b9SMatthew G. Knepley         user->hasNullSpace = PETSC_FALSE;
1525444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, VEL,  0, 1, f0_conduct_pipe_v, 0, NULL);CHKERRQ(ierr);
1526444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, PRES, 0, 1, f0_conduct_pipe_q, 0, NULL);CHKERRQ(ierr);
1527444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, TEMP, 0, 1, f0_conduct_pipe_w, 0, NULL);CHKERRQ(ierr);
1528444129b9SMatthew G. Knepley 
1529444129b9SMatthew G. Knepley         exactFuncs[VEL]    = pipe_u;
1530444129b9SMatthew G. Knepley         exactFuncs[PRES]   = pipe_p;
1531444129b9SMatthew G. Knepley         exactFuncs[TEMP]   = pipe_T;
1532444129b9SMatthew G. Knepley         exactFuncs_t[VEL]  = pipe_u_t;
1533444129b9SMatthew G. Knepley         exactFuncs_t[PRES] = pipe_p_t;
1534444129b9SMatthew G. Knepley         exactFuncs_t[TEMP] = pipe_T_t;
1535444129b9SMatthew G. Knepley 
1536444129b9SMatthew G. Knepley         ierr = PetscBagGetData(user->bag, (void **) &ctx);CHKERRQ(ierr);
1537444129b9SMatthew G. Knepley         id   = 2;
1538444129b9SMatthew G. Knepley         ierr = DMAddBoundary(dm, DM_BC_NATURAL, "right wall", label, 1, &id, 0, 0, NULL, NULL, NULL, ctx, &bd);CHKERRQ(ierr);
1539444129b9SMatthew G. Knepley         ierr = PetscDSGetBoundary(ds, bd, &wf, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
1540444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexBdResidual(wf, label, id, VEL, 0, 0, f0_conduct_bd_pipe_v, 0, NULL);CHKERRQ(ierr);
1541444129b9SMatthew G. Knepley         id   = 4;
1542444129b9SMatthew G. Knepley         ierr = DMAddBoundary(dm, DM_BC_NATURAL, "left wall", label, 1, &id, 0, 0, NULL, NULL, NULL, ctx, &bd);CHKERRQ(ierr);
1543444129b9SMatthew G. Knepley         ierr = PetscDSGetBoundary(ds, bd, &wf, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
1544444129b9SMatthew G. Knepley         ierr = PetscWeakFormSetIndexBdResidual(wf, label, id, VEL, 0, 0, f0_conduct_bd_pipe_v, 0, NULL);CHKERRQ(ierr);
1545444129b9SMatthew G. Knepley         id   = 4;
1546444129b9SMatthew G. Knepley         ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "left wall temperature",   label, 1, &id, TEMP, 0, NULL, (void (*)(void)) exactFuncs[TEMP], (void (*)(void)) exactFuncs_t[TEMP], ctx, NULL);CHKERRQ(ierr);
1547444129b9SMatthew G. Knepley         id   = 3;
1548444129b9SMatthew G. Knepley         ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "top wall velocity",       label, 1, &id, VEL,  0, NULL, (void (*)(void)) exactFuncs[VEL], (void (*)(void)) exactFuncs_t[VEL], ctx, NULL);CHKERRQ(ierr);
1549444129b9SMatthew G. Knepley         ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "top wall temperature",    label, 1, &id, TEMP, 0, NULL, (void (*)(void)) exactFuncs[TEMP], (void (*)(void)) exactFuncs_t[TEMP], ctx, NULL);CHKERRQ(ierr);
1550444129b9SMatthew G. Knepley         id   = 1;
1551444129b9SMatthew G. Knepley         ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "bottom wall velocity",    label, 1, &id, VEL,  0, NULL, (void (*)(void)) exactFuncs[VEL], (void (*)(void)) exactFuncs_t[VEL], ctx, NULL);CHKERRQ(ierr);
1552444129b9SMatthew G. Knepley         ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "bottom wall temperature", label, 1, &id, TEMP, 0, NULL, (void (*)(void)) exactFuncs[TEMP], (void (*)(void)) exactFuncs_t[TEMP], ctx, NULL);CHKERRQ(ierr);
1553444129b9SMatthew G. Knepley         break;
1554*367970cfSMatthew G. Knepley       case SOL_PIPE_WIGGLY:
1555*367970cfSMatthew G. Knepley         user->hasNullSpace = PETSC_FALSE;
1556*367970cfSMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, VEL,  0, 1, f0_conduct_pipe_wiggly_v, 0, NULL);CHKERRQ(ierr);
1557*367970cfSMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, PRES, 0, 1, f0_conduct_pipe_wiggly_q, 0, NULL);CHKERRQ(ierr);
1558*367970cfSMatthew G. Knepley         ierr = PetscWeakFormSetIndexResidual(wf, NULL, 0, TEMP, 0, 1, f0_conduct_pipe_wiggly_w, 0, NULL);CHKERRQ(ierr);
1559*367970cfSMatthew G. Knepley 
1560*367970cfSMatthew G. Knepley         exactFuncs[VEL]    = pipe_wiggly_u;
1561*367970cfSMatthew G. Knepley         exactFuncs[PRES]   = pipe_wiggly_p;
1562*367970cfSMatthew G. Knepley         exactFuncs[TEMP]   = pipe_wiggly_T;
1563*367970cfSMatthew G. Knepley         exactFuncs_t[VEL]  = pipe_wiggly_u_t;
1564*367970cfSMatthew G. Knepley         exactFuncs_t[PRES] = pipe_wiggly_p_t;
1565*367970cfSMatthew G. Knepley         exactFuncs_t[TEMP] = pipe_wiggly_T_t;
1566*367970cfSMatthew G. Knepley 
1567*367970cfSMatthew G. Knepley         ierr = PetscBagGetData(user->bag, (void **) &ctx);CHKERRQ(ierr);
1568*367970cfSMatthew G. Knepley         id   = 2;
1569*367970cfSMatthew G. Knepley         ierr = DMAddBoundary(dm, DM_BC_NATURAL, "right wall", label, 1, &id, 0, 0, NULL, NULL, NULL, ctx, &bd);CHKERRQ(ierr);
1570*367970cfSMatthew G. Knepley         ierr = PetscDSGetBoundary(ds, bd, &wf, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
1571*367970cfSMatthew G. Knepley         ierr = PetscWeakFormSetIndexBdResidual(wf, label, id, VEL, 0, 0, f0_conduct_bd_pipe_wiggly_v, 0, NULL);CHKERRQ(ierr);
1572*367970cfSMatthew G. Knepley         id   = 4;
1573*367970cfSMatthew G. Knepley         ierr = DMAddBoundary(dm, DM_BC_NATURAL, "left wall", label, 1, &id, 0, 0, NULL, NULL, NULL, ctx, &bd);CHKERRQ(ierr);
1574*367970cfSMatthew G. Knepley         ierr = PetscDSGetBoundary(ds, bd, &wf, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
1575*367970cfSMatthew G. Knepley         ierr = PetscWeakFormSetIndexBdResidual(wf, label, id, VEL, 0, 0, f0_conduct_bd_pipe_wiggly_v, 0, NULL);CHKERRQ(ierr);
1576*367970cfSMatthew G. Knepley         id   = 4;
1577*367970cfSMatthew G. Knepley         ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "left wall temperature",   label, 1, &id, TEMP, 0, NULL, (void (*)(void)) exactFuncs[TEMP], (void (*)(void)) exactFuncs_t[TEMP], ctx, NULL);CHKERRQ(ierr);
1578*367970cfSMatthew G. Knepley         id   = 3;
1579*367970cfSMatthew G. Knepley         ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "top wall velocity",       label, 1, &id, VEL,  0, NULL, (void (*)(void)) exactFuncs[VEL], (void (*)(void)) exactFuncs_t[VEL], ctx, NULL);CHKERRQ(ierr);
1580*367970cfSMatthew G. Knepley         ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "top wall temperature",    label, 1, &id, TEMP, 0, NULL, (void (*)(void)) exactFuncs[TEMP], (void (*)(void)) exactFuncs_t[TEMP], ctx, NULL);CHKERRQ(ierr);
1581*367970cfSMatthew G. Knepley         id   = 1;
1582*367970cfSMatthew G. Knepley         ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "bottom wall velocity",    label, 1, &id, VEL,  0, NULL, (void (*)(void)) exactFuncs[VEL], (void (*)(void)) exactFuncs_t[VEL], ctx, NULL);CHKERRQ(ierr);
1583*367970cfSMatthew G. Knepley         ierr = PetscDSAddBoundary(ds, DM_BC_ESSENTIAL, "bottom wall temperature", label, 1, &id, TEMP, 0, NULL, (void (*)(void)) exactFuncs[TEMP], (void (*)(void)) exactFuncs_t[TEMP], ctx, NULL);CHKERRQ(ierr);
1584*367970cfSMatthew G. Knepley         break;
1585444129b9SMatthew G. Knepley        default: SETERRQ2(PetscObjectComm((PetscObject) ds), PETSC_ERR_ARG_WRONG, "Unsupported solution type: %s (%D)", solTypes[PetscMin(user->solType, NUM_SOL_TYPES)], user->solType);
1586444129b9SMatthew G. Knepley       }
1587444129b9SMatthew G. Knepley       break;
1588444129b9SMatthew G. Knepley     default: SETERRQ2(PetscObjectComm((PetscObject) ds), PETSC_ERR_ARG_WRONG, "Unsupported model type: %s (%D)", solTypes[PetscMin(user->modType, NUM_MOD_TYPES)], user->modType);
1589444129b9SMatthew G. Knepley   }
1590649ef022SMatthew Knepley   /* Setup constants */
1591649ef022SMatthew Knepley   {
1592649ef022SMatthew Knepley     Parameter  *param;
1593*367970cfSMatthew G. Knepley     PetscScalar constants[13];
1594649ef022SMatthew Knepley 
1595649ef022SMatthew Knepley     ierr = PetscBagGetData(user->bag, (void **) &param);CHKERRQ(ierr);
1596649ef022SMatthew Knepley 
1597444129b9SMatthew G. Knepley     constants[STROUHAL] = param->Strouhal;
1598444129b9SMatthew G. Knepley     constants[FROUDE]   = param->Froude;
1599444129b9SMatthew G. Knepley     constants[REYNOLDS] = param->Reynolds;
1600444129b9SMatthew G. Knepley     constants[PECLET]   = param->Peclet;
1601444129b9SMatthew G. Knepley     constants[P_TH]     = param->p_th;
1602444129b9SMatthew G. Knepley     constants[MU]       = param->mu;
1603444129b9SMatthew G. Knepley     constants[NU]       = param->nu;
1604444129b9SMatthew G. Knepley     constants[C_P]      = param->c_p;
1605444129b9SMatthew G. Knepley     constants[K]        = param->k;
1606444129b9SMatthew G. Knepley     constants[ALPHA]    = param->alpha;
1607444129b9SMatthew G. Knepley     constants[T_IN]     = param->T_in;
1608444129b9SMatthew G. Knepley     constants[G_DIR]    = param->g_dir;
1609*367970cfSMatthew G. Knepley     constants[EPSILON]  = param->epsilon;
1610*367970cfSMatthew G. Knepley     ierr = PetscDSSetConstants(ds, 13, constants);CHKERRQ(ierr);
1611649ef022SMatthew Knepley   }
1612649ef022SMatthew Knepley 
1613444129b9SMatthew G. Knepley   ierr = PetscBagGetData(user->bag, (void **) &ctx);CHKERRQ(ierr);
1614444129b9SMatthew G. Knepley   ierr = PetscDSSetExactSolution(ds, VEL,  exactFuncs[VEL],  ctx);CHKERRQ(ierr);
1615444129b9SMatthew G. Knepley   ierr = PetscDSSetExactSolution(ds, PRES, exactFuncs[PRES], ctx);CHKERRQ(ierr);
1616444129b9SMatthew G. Knepley   ierr = PetscDSSetExactSolution(ds, TEMP, exactFuncs[TEMP], ctx);CHKERRQ(ierr);
1617444129b9SMatthew G. Knepley   ierr = PetscDSSetExactSolutionTimeDerivative(ds, VEL,  exactFuncs_t[VEL],  ctx);CHKERRQ(ierr);
1618444129b9SMatthew G. Knepley   ierr = PetscDSSetExactSolutionTimeDerivative(ds, PRES, exactFuncs_t[PRES], ctx);CHKERRQ(ierr);
1619444129b9SMatthew G. Knepley   ierr = PetscDSSetExactSolutionTimeDerivative(ds, TEMP, exactFuncs_t[TEMP], ctx);CHKERRQ(ierr);
1620649ef022SMatthew Knepley   PetscFunctionReturn(0);
1621649ef022SMatthew Knepley }
1622649ef022SMatthew Knepley 
1623*367970cfSMatthew G. Knepley static PetscErrorCode CreateCellDM(DM dm, AppCtx *user)
1624*367970cfSMatthew G. Knepley {
1625*367970cfSMatthew G. Knepley   PetscFE        fe, fediv;
1626*367970cfSMatthew G. Knepley   DMPolytopeType ct;
1627*367970cfSMatthew G. Knepley   PetscInt       dim, cStart;
1628*367970cfSMatthew G. Knepley   PetscBool      simplex;
1629*367970cfSMatthew G. Knepley   PetscErrorCode ierr;
1630*367970cfSMatthew G. Knepley 
1631*367970cfSMatthew G. Knepley   PetscFunctionBeginUser;
1632*367970cfSMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1633*367970cfSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr);
1634*367970cfSMatthew G. Knepley   ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr);
1635*367970cfSMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
1636*367970cfSMatthew G. Knepley 
1637*367970cfSMatthew G. Knepley   ierr = DMGetField(dm, VEL,  NULL, (PetscObject *) &fe);CHKERRQ(ierr);
1638*367970cfSMatthew G. Knepley   ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "div_", PETSC_DEFAULT, &fediv);CHKERRQ(ierr);
1639*367970cfSMatthew G. Knepley   ierr = PetscFECopyQuadrature(fe, fediv);CHKERRQ(ierr);
1640*367970cfSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) fediv, "divergence");CHKERRQ(ierr);
1641*367970cfSMatthew G. Knepley 
1642*367970cfSMatthew G. Knepley   ierr = DMDestroy(&user->dmCell);CHKERRQ(ierr);
1643*367970cfSMatthew G. Knepley   ierr = DMClone(dm, &user->dmCell);CHKERRQ(ierr);
1644*367970cfSMatthew G. Knepley   ierr = DMSetField(user->dmCell, 0, NULL, (PetscObject) fediv);CHKERRQ(ierr);
1645*367970cfSMatthew G. Knepley   ierr = DMCreateDS(user->dmCell);CHKERRQ(ierr);
1646*367970cfSMatthew G. Knepley   ierr = PetscFEDestroy(&fediv);CHKERRQ(ierr);
1647*367970cfSMatthew G. Knepley   PetscFunctionReturn(0);
1648*367970cfSMatthew G. Knepley }
1649*367970cfSMatthew G. Knepley 
1650*367970cfSMatthew G. Knepley static PetscErrorCode GetCellDM(DM dm, AppCtx *user, DM *dmCell)
1651*367970cfSMatthew G. Knepley {
1652*367970cfSMatthew G. Knepley   PetscInt       cStart, cEnd, cellStart = -1, cellEnd = -1;
1653*367970cfSMatthew G. Knepley   PetscErrorCode ierr;
1654*367970cfSMatthew G. Knepley 
1655*367970cfSMatthew G. Knepley   PetscFunctionBeginUser;
1656*367970cfSMatthew G. Knepley   ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
1657*367970cfSMatthew G. Knepley   if (user->dmCell) {ierr = DMPlexGetSimplexOrBoxCells(user->dmCell, 0, &cellStart, &cellEnd);CHKERRQ(ierr);}
1658*367970cfSMatthew G. Knepley   if (cStart != cellStart || cEnd != cellEnd) {ierr = CreateCellDM(dm, user);CHKERRQ(ierr);}
1659*367970cfSMatthew G. Knepley   *dmCell = user->dmCell;
1660*367970cfSMatthew G. Knepley   PetscFunctionReturn(0);
1661*367970cfSMatthew G. Knepley }
1662*367970cfSMatthew G. Knepley 
1663649ef022SMatthew Knepley static PetscErrorCode SetupDiscretization(DM dm, AppCtx *user)
1664649ef022SMatthew Knepley {
1665649ef022SMatthew Knepley   DM              cdm = dm;
1666*367970cfSMatthew G. Knepley   PetscFE         fe[3];
1667649ef022SMatthew Knepley   Parameter      *param;
1668649ef022SMatthew Knepley   DMPolytopeType  ct;
1669649ef022SMatthew Knepley   PetscInt        dim, cStart;
1670649ef022SMatthew Knepley   PetscBool       simplex;
1671649ef022SMatthew Knepley   PetscErrorCode  ierr;
1672649ef022SMatthew Knepley 
1673649ef022SMatthew Knepley   PetscFunctionBeginUser;
1674649ef022SMatthew Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1675649ef022SMatthew Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr);
1676649ef022SMatthew Knepley   ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr);
1677649ef022SMatthew Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
1678649ef022SMatthew Knepley   /* Create finite element */
1679a712f3bbSMatthew G. Knepley   ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, dim, simplex, "vel_", PETSC_DEFAULT, &fe[0]);CHKERRQ(ierr);
1680649ef022SMatthew Knepley   ierr = PetscObjectSetName((PetscObject) fe[0], "velocity");CHKERRQ(ierr);
1681649ef022SMatthew Knepley 
1682a712f3bbSMatthew G. Knepley   ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "pres_", PETSC_DEFAULT, &fe[1]);CHKERRQ(ierr);
1683649ef022SMatthew Knepley   ierr = PetscFECopyQuadrature(fe[0], fe[1]);CHKERRQ(ierr);
1684649ef022SMatthew Knepley   ierr = PetscObjectSetName((PetscObject) fe[1], "pressure");CHKERRQ(ierr);
1685649ef022SMatthew Knepley 
1686a712f3bbSMatthew G. Knepley   ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "temp_", PETSC_DEFAULT, &fe[2]);CHKERRQ(ierr);
1687649ef022SMatthew Knepley   ierr = PetscFECopyQuadrature(fe[0], fe[2]);CHKERRQ(ierr);
1688649ef022SMatthew Knepley   ierr = PetscObjectSetName((PetscObject) fe[2], "temperature");CHKERRQ(ierr);
1689649ef022SMatthew Knepley 
1690649ef022SMatthew Knepley   /* Set discretization and boundary conditions for each mesh */
1691444129b9SMatthew G. Knepley   ierr = DMSetField(dm, VEL,  NULL, (PetscObject) fe[VEL]);CHKERRQ(ierr);
1692444129b9SMatthew G. Knepley   ierr = DMSetField(dm, PRES, NULL, (PetscObject) fe[PRES]);CHKERRQ(ierr);
1693444129b9SMatthew G. Knepley   ierr = DMSetField(dm, TEMP, NULL, (PetscObject) fe[TEMP]);CHKERRQ(ierr);
1694649ef022SMatthew Knepley   ierr = DMCreateDS(dm);CHKERRQ(ierr);
1695649ef022SMatthew Knepley   ierr = SetupProblem(dm, user);CHKERRQ(ierr);
1696649ef022SMatthew Knepley   ierr = PetscBagGetData(user->bag, (void **) &param);CHKERRQ(ierr);
1697649ef022SMatthew Knepley   while (cdm) {
1698649ef022SMatthew Knepley     ierr = DMCopyDisc(dm, cdm);CHKERRQ(ierr);
1699649ef022SMatthew Knepley     ierr = DMGetCoarseDM(cdm, &cdm);CHKERRQ(ierr);
1700649ef022SMatthew Knepley   }
1701444129b9SMatthew G. Knepley   ierr = PetscFEDestroy(&fe[VEL]);CHKERRQ(ierr);
1702444129b9SMatthew G. Knepley   ierr = PetscFEDestroy(&fe[PRES]);CHKERRQ(ierr);
1703444129b9SMatthew G. Knepley   ierr = PetscFEDestroy(&fe[TEMP]);CHKERRQ(ierr);
1704649ef022SMatthew Knepley 
1705444129b9SMatthew G. Knepley   if (user->hasNullSpace) {
1706649ef022SMatthew Knepley     PetscObject  pressure;
1707649ef022SMatthew Knepley     MatNullSpace nullspacePres;
1708649ef022SMatthew Knepley 
1709444129b9SMatthew G. Knepley     ierr = DMGetField(dm, PRES, NULL, &pressure);CHKERRQ(ierr);
1710649ef022SMatthew Knepley     ierr = MatNullSpaceCreate(PetscObjectComm(pressure), PETSC_TRUE, 0, NULL, &nullspacePres);CHKERRQ(ierr);
1711649ef022SMatthew Knepley     ierr = PetscObjectCompose(pressure, "nullspace", (PetscObject) nullspacePres);CHKERRQ(ierr);
1712649ef022SMatthew Knepley     ierr = MatNullSpaceDestroy(&nullspacePres);CHKERRQ(ierr);
1713649ef022SMatthew Knepley   }
1714649ef022SMatthew Knepley   PetscFunctionReturn(0);
1715649ef022SMatthew Knepley }
1716649ef022SMatthew Knepley 
1717649ef022SMatthew Knepley static PetscErrorCode CreatePressureNullSpace(DM dm, PetscInt ofield, PetscInt nfield, MatNullSpace *nullSpace)
1718649ef022SMatthew Knepley {
1719649ef022SMatthew Knepley   Vec              vec;
1720649ef022SMatthew Knepley   PetscErrorCode (*funcs[3])(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *) = {zero, zero, zero};
1721649ef022SMatthew Knepley   PetscErrorCode   ierr;
1722649ef022SMatthew Knepley 
1723649ef022SMatthew Knepley   PetscFunctionBeginUser;
1724444129b9SMatthew G. Knepley   if (ofield != PRES) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Nullspace must be for pressure field at index %D, not %D", PRES, ofield);
1725649ef022SMatthew Knepley   funcs[nfield] = constant;
1726649ef022SMatthew Knepley   ierr = DMCreateGlobalVector(dm, &vec);CHKERRQ(ierr);
1727649ef022SMatthew Knepley   ierr = DMProjectFunction(dm, 0.0, funcs, NULL, INSERT_ALL_VALUES, vec);CHKERRQ(ierr);
1728649ef022SMatthew Knepley   ierr = VecNormalize(vec, NULL);CHKERRQ(ierr);
1729649ef022SMatthew Knepley   ierr = PetscObjectSetName((PetscObject) vec, "Pressure Null Space");CHKERRQ(ierr);
1730649ef022SMatthew Knepley   ierr = VecViewFromOptions(vec, NULL, "-pressure_nullspace_view");CHKERRQ(ierr);
1731649ef022SMatthew Knepley   ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject) dm), PETSC_FALSE, 1, &vec, nullSpace);CHKERRQ(ierr);
1732649ef022SMatthew Knepley   ierr = VecDestroy(&vec);CHKERRQ(ierr);
1733649ef022SMatthew Knepley   PetscFunctionReturn(0);
1734649ef022SMatthew Knepley }
1735649ef022SMatthew Knepley 
1736649ef022SMatthew Knepley static PetscErrorCode RemoveDiscretePressureNullspace_Private(TS ts, Vec u)
1737649ef022SMatthew Knepley {
1738649ef022SMatthew Knepley   DM             dm;
1739444129b9SMatthew G. Knepley   AppCtx        *user;
1740649ef022SMatthew Knepley   MatNullSpace   nullsp;
1741649ef022SMatthew Knepley   PetscErrorCode ierr;
1742649ef022SMatthew Knepley 
1743649ef022SMatthew Knepley   PetscFunctionBegin;
1744649ef022SMatthew Knepley   ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
17453ec1f749SStefano Zampini   ierr = DMGetApplicationContext(dm, &user);CHKERRQ(ierr);
1746444129b9SMatthew G. Knepley   if (!user->hasNullSpace) PetscFunctionReturn(0);
1747649ef022SMatthew Knepley   ierr = CreatePressureNullSpace(dm, 1, 1, &nullsp);CHKERRQ(ierr);
1748649ef022SMatthew Knepley   ierr = MatNullSpaceRemove(nullsp, u);CHKERRQ(ierr);
1749649ef022SMatthew Knepley   ierr = MatNullSpaceDestroy(&nullsp);CHKERRQ(ierr);
1750649ef022SMatthew Knepley   PetscFunctionReturn(0);
1751649ef022SMatthew Knepley }
1752649ef022SMatthew Knepley 
1753649ef022SMatthew Knepley /* Make the discrete pressure discretely divergence free */
1754649ef022SMatthew Knepley static PetscErrorCode RemoveDiscretePressureNullspace(TS ts)
1755649ef022SMatthew Knepley {
1756649ef022SMatthew Knepley   Vec            u;
1757649ef022SMatthew Knepley   PetscErrorCode ierr;
1758649ef022SMatthew Knepley 
1759649ef022SMatthew Knepley   PetscFunctionBegin;
1760649ef022SMatthew Knepley   ierr = TSGetSolution(ts, &u);CHKERRQ(ierr);
1761649ef022SMatthew Knepley   ierr = RemoveDiscretePressureNullspace_Private(ts, u);CHKERRQ(ierr);
1762649ef022SMatthew Knepley   PetscFunctionReturn(0);
1763649ef022SMatthew Knepley }
1764649ef022SMatthew Knepley 
1765*367970cfSMatthew G. Knepley static void divergence(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1766*367970cfSMatthew G. Knepley                        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1767*367970cfSMatthew G. Knepley                        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1768*367970cfSMatthew G. Knepley                        PetscReal t, const PetscReal X[], PetscInt numConstants, const PetscScalar constants[], PetscScalar divu[])
1769*367970cfSMatthew G. Knepley {
1770*367970cfSMatthew G. Knepley   PetscInt d;
1771*367970cfSMatthew G. Knepley 
1772*367970cfSMatthew G. Knepley   divu[0] = 0.;
1773*367970cfSMatthew G. Knepley   for (d = 0; d < dim; ++d) divu[0] += u_x[d*dim+d];
1774*367970cfSMatthew G. Knepley }
1775*367970cfSMatthew G. Knepley 
1776649ef022SMatthew Knepley static PetscErrorCode SetInitialConditions(TS ts, Vec u)
1777649ef022SMatthew Knepley {
1778444129b9SMatthew G. Knepley   AppCtx        *user;
1779649ef022SMatthew Knepley   DM             dm;
1780649ef022SMatthew Knepley   PetscReal      t;
1781649ef022SMatthew Knepley   PetscErrorCode ierr;
1782649ef022SMatthew Knepley 
1783649ef022SMatthew Knepley   PetscFunctionBegin;
1784649ef022SMatthew Knepley   ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
1785649ef022SMatthew Knepley   ierr = TSGetTime(ts, &t);CHKERRQ(ierr);
1786649ef022SMatthew Knepley   ierr = DMComputeExactSolution(dm, t, u, NULL);CHKERRQ(ierr);
17873ec1f749SStefano Zampini   ierr = DMGetApplicationContext(dm, &user);CHKERRQ(ierr);
1788649ef022SMatthew Knepley   ierr = RemoveDiscretePressureNullspace_Private(ts, u);CHKERRQ(ierr);
1789649ef022SMatthew Knepley   PetscFunctionReturn(0);
1790649ef022SMatthew Knepley }
1791649ef022SMatthew Knepley 
1792649ef022SMatthew Knepley static PetscErrorCode MonitorError(TS ts, PetscInt step, PetscReal crtime, Vec u, void *ctx)
1793649ef022SMatthew Knepley {
1794649ef022SMatthew Knepley   PetscErrorCode (*exactFuncs[3])(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx);
1795649ef022SMatthew Knepley   void            *ctxs[3];
1796a712f3bbSMatthew G. Knepley   PetscPointFunc   diagnostics[1] = {divergence};
1797*367970cfSMatthew G. Knepley   DM               dm, dmCell = NULL;
1798649ef022SMatthew Knepley   PetscDS          ds;
1799a712f3bbSMatthew G. Knepley   Vec              v, divu;
1800a712f3bbSMatthew G. Knepley   PetscReal        ferrors[3], massFlux;
1801649ef022SMatthew Knepley   PetscInt         f;
1802649ef022SMatthew Knepley   PetscErrorCode   ierr;
1803649ef022SMatthew Knepley 
1804649ef022SMatthew Knepley   PetscFunctionBeginUser;
1805649ef022SMatthew Knepley   ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
1806649ef022SMatthew Knepley   ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);
1807649ef022SMatthew Knepley 
1808649ef022SMatthew Knepley   for (f = 0; f < 3; ++f) {ierr = PetscDSGetExactSolution(ds, f, &exactFuncs[f], &ctxs[f]);CHKERRQ(ierr);}
1809649ef022SMatthew Knepley   ierr = DMComputeL2FieldDiff(dm, crtime, exactFuncs, ctxs, u, ferrors);CHKERRQ(ierr);
1810*367970cfSMatthew G. Knepley   ierr = GetCellDM(dm, (AppCtx *) ctx, &dmCell);CHKERRQ(ierr);
1811a712f3bbSMatthew G. Knepley   ierr = DMGetGlobalVector(dmCell, &divu);CHKERRQ(ierr);
1812a712f3bbSMatthew G. Knepley   ierr = DMProjectField(dmCell, crtime, u, diagnostics, INSERT_VALUES, divu);CHKERRQ(ierr);
1813a712f3bbSMatthew G. Knepley   ierr = VecViewFromOptions(divu, NULL, "-divu_vec_view");CHKERRQ(ierr);
1814a712f3bbSMatthew G. Knepley   ierr = VecNorm(divu, NORM_2, &massFlux);CHKERRQ(ierr);
1815a712f3bbSMatthew G. Knepley   ierr = PetscPrintf(PETSC_COMM_WORLD, "Timestep: %04d time = %-8.4g \t L_2 Error: [%2.3g, %2.3g, %2.3g] ||div u||: %2.3g\n", (int) step, (double) crtime, (double) ferrors[0], (double) ferrors[1], (double) ferrors[2], (double) massFlux);CHKERRQ(ierr);
1816649ef022SMatthew Knepley 
1817649ef022SMatthew Knepley   ierr = VecViewFromOptions(u, NULL, "-sol_vec_view");CHKERRQ(ierr);
1818649ef022SMatthew Knepley 
1819649ef022SMatthew Knepley   ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr);
1820a712f3bbSMatthew G. Knepley   ierr = DMProjectFunction(dm, crtime, exactFuncs, ctxs, INSERT_ALL_VALUES, v);CHKERRQ(ierr);
1821649ef022SMatthew Knepley   ierr = PetscObjectSetName((PetscObject) v, "Exact Solution");CHKERRQ(ierr);
1822649ef022SMatthew Knepley   ierr = VecViewFromOptions(v, NULL, "-exact_vec_view");CHKERRQ(ierr);
1823649ef022SMatthew Knepley   ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);
1824649ef022SMatthew Knepley 
1825a712f3bbSMatthew G. Knepley   ierr = VecViewFromOptions(divu, NULL, "-div_vec_view");CHKERRQ(ierr);
1826a712f3bbSMatthew G. Knepley   ierr = DMRestoreGlobalVector(dmCell, &divu);CHKERRQ(ierr);
1827a712f3bbSMatthew G. Knepley 
1828649ef022SMatthew Knepley   PetscFunctionReturn(0);
1829649ef022SMatthew Knepley }
1830649ef022SMatthew Knepley 
1831649ef022SMatthew Knepley int main(int argc, char **argv)
1832649ef022SMatthew Knepley {
1833649ef022SMatthew Knepley   DM              dm;   /* problem definition */
1834649ef022SMatthew Knepley   TS              ts;   /* timestepper */
1835649ef022SMatthew Knepley   Vec             u;    /* solution */
1836649ef022SMatthew Knepley   AppCtx          user; /* user-defined work context */
1837649ef022SMatthew Knepley   PetscReal       t;
1838649ef022SMatthew Knepley   PetscErrorCode  ierr;
1839649ef022SMatthew Knepley 
1840649ef022SMatthew Knepley   ierr = PetscInitialize(&argc, &argv, NULL,help);if (ierr) return ierr;
1841649ef022SMatthew Knepley   ierr = ProcessOptions(PETSC_COMM_WORLD, &user);CHKERRQ(ierr);
1842649ef022SMatthew Knepley   ierr = PetscBagCreate(PETSC_COMM_WORLD, sizeof(Parameter), &user.bag);CHKERRQ(ierr);
1843649ef022SMatthew Knepley   ierr = CreateMesh(PETSC_COMM_WORLD, &user, &dm);CHKERRQ(ierr);
1844444129b9SMatthew G. Knepley   ierr = SetupParameters(dm, &user);CHKERRQ(ierr);
1845444129b9SMatthew G. Knepley   ierr = TSCreate(PETSC_COMM_WORLD, &ts);CHKERRQ(ierr);
1846649ef022SMatthew Knepley   ierr = TSSetDM(ts, dm);CHKERRQ(ierr);
1847649ef022SMatthew Knepley   ierr = DMSetApplicationContext(dm, &user);CHKERRQ(ierr);
1848649ef022SMatthew Knepley   /* Setup problem */
1849649ef022SMatthew Knepley   ierr = SetupDiscretization(dm, &user);CHKERRQ(ierr);
1850649ef022SMatthew Knepley   ierr = DMPlexCreateClosureIndex(dm, NULL);CHKERRQ(ierr);
1851649ef022SMatthew Knepley 
1852649ef022SMatthew Knepley   ierr = DMCreateGlobalVector(dm, &u);CHKERRQ(ierr);
1853a712f3bbSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) u, "Numerical Solution");CHKERRQ(ierr);
1854444129b9SMatthew G. Knepley   if (user.hasNullSpace) {ierr = DMSetNullSpaceConstructor(dm, 1, CreatePressureNullSpace);CHKERRQ(ierr);}
1855649ef022SMatthew Knepley 
1856649ef022SMatthew Knepley   ierr = DMTSSetBoundaryLocal(dm, DMPlexTSComputeBoundary, &user);CHKERRQ(ierr);
1857649ef022SMatthew Knepley   ierr = DMTSSetIFunctionLocal(dm, DMPlexTSComputeIFunctionFEM, &user);CHKERRQ(ierr);
1858649ef022SMatthew Knepley   ierr = DMTSSetIJacobianLocal(dm, DMPlexTSComputeIJacobianFEM, &user);CHKERRQ(ierr);
1859649ef022SMatthew Knepley   ierr = TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP);CHKERRQ(ierr);
1860649ef022SMatthew Knepley   ierr = TSSetPreStep(ts, RemoveDiscretePressureNullspace);CHKERRQ(ierr);
1861649ef022SMatthew Knepley   ierr = TSSetFromOptions(ts);CHKERRQ(ierr);
1862649ef022SMatthew Knepley 
1863649ef022SMatthew Knepley   ierr = TSSetComputeInitialCondition(ts, SetInitialConditions);CHKERRQ(ierr); /* Must come after SetFromOptions() */
1864649ef022SMatthew Knepley   ierr = SetInitialConditions(ts, u);CHKERRQ(ierr);
1865649ef022SMatthew Knepley   ierr = TSGetTime(ts, &t);CHKERRQ(ierr);
1866649ef022SMatthew Knepley   ierr = DMSetOutputSequenceNumber(dm, 0, t);CHKERRQ(ierr);
1867649ef022SMatthew Knepley   ierr = DMTSCheckFromOptions(ts, u);CHKERRQ(ierr);
1868649ef022SMatthew Knepley   ierr = TSMonitorSet(ts, MonitorError, &user, NULL);CHKERRQ(ierr);CHKERRQ(ierr);
1869649ef022SMatthew Knepley 
1870649ef022SMatthew Knepley   ierr = TSSolve(ts, u);CHKERRQ(ierr);
1871649ef022SMatthew Knepley   ierr = DMTSCheckFromOptions(ts, u);CHKERRQ(ierr);
1872649ef022SMatthew Knepley 
1873649ef022SMatthew Knepley   ierr = VecDestroy(&u);CHKERRQ(ierr);
1874a712f3bbSMatthew G. Knepley   ierr = DMDestroy(&user.dmCell);CHKERRQ(ierr);
1875649ef022SMatthew Knepley   ierr = DMDestroy(&dm);CHKERRQ(ierr);
1876649ef022SMatthew Knepley   ierr = TSDestroy(&ts);CHKERRQ(ierr);
1877649ef022SMatthew Knepley   ierr = PetscBagDestroy(&user.bag);CHKERRQ(ierr);
1878649ef022SMatthew Knepley   ierr = PetscFinalize();
1879649ef022SMatthew Knepley   return ierr;
1880649ef022SMatthew Knepley }
1881649ef022SMatthew Knepley 
1882649ef022SMatthew Knepley /*TEST
1883649ef022SMatthew Knepley 
1884444129b9SMatthew G. Knepley   testset:
1885649ef022SMatthew Knepley     requires: triangle !single
1886444129b9SMatthew G. Knepley     args: -dm_plex_separate_marker \
1887a712f3bbSMatthew G. Knepley           -div_petscdualspace_lagrange_use_moments -div_petscdualspace_lagrange_moment_order 3 \
1888444129b9SMatthew G. Knepley           -snes_error_if_not_converged -snes_convergence_test correct_pressure \
1889649ef022SMatthew Knepley           -ksp_type fgmres -ksp_gmres_restart 10 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged \
1890444129b9SMatthew G. Knepley           -pc_type fieldsplit -pc_fieldsplit_0_fields 0,2 -pc_fieldsplit_1_fields 1 \
1891444129b9SMatthew G. Knepley           -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full \
1892649ef022SMatthew Knepley             -fieldsplit_0_pc_type lu \
1893649ef022SMatthew Knepley             -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type jacobi
1894649ef022SMatthew Knepley 
1895444129b9SMatthew G. Knepley     test:
1896444129b9SMatthew G. Knepley       suffix: 2d_tri_p2_p1_p1
1897444129b9SMatthew G. Knepley       args: -sol_type quadratic \
1898444129b9SMatthew G. Knepley             -vel_petscspace_degree 2 -pres_petscspace_degree 1 -temp_petscspace_degree 1 \
1899444129b9SMatthew G. Knepley             -dmts_check .001 -ts_max_steps 4 -ts_dt 0.1
1900444129b9SMatthew G. Knepley 
1901649ef022SMatthew Knepley     test:
1902649ef022SMatthew Knepley       # Using -dm_refine 5 -convest_num_refine 2 gives L_2 convergence rate: [0.89, 0.011, 1.0]
1903649ef022SMatthew Knepley       suffix: 2d_tri_p2_p1_p1_tconv
1904444129b9SMatthew G. Knepley       args: -sol_type cubic_trig \
1905649ef022SMatthew Knepley             -vel_petscspace_degree 2 -pres_petscspace_degree 1 -temp_petscspace_degree 1 \
1906444129b9SMatthew G. Knepley             -ts_max_steps 4 -ts_dt 0.1 -ts_convergence_estimate -convest_num_refine 1
1907649ef022SMatthew Knepley 
1908649ef022SMatthew Knepley     test:
1909649ef022SMatthew Knepley       # Using -dm_refine 3 -convest_num_refine 3 gives L_2 convergence rate: [3.0, 2.5, 1.9]
1910649ef022SMatthew Knepley       suffix: 2d_tri_p2_p1_p1_sconv
1911444129b9SMatthew G. Knepley       args: -sol_type cubic \
1912649ef022SMatthew Knepley             -vel_petscspace_degree 2 -pres_petscspace_degree 1 -temp_petscspace_degree 1 \
1913444129b9SMatthew G. Knepley             -ts_max_steps 1 -ts_dt 1e-4 -ts_convergence_estimate -ts_convergence_temporal 0 -convest_num_refine 1
1914649ef022SMatthew Knepley 
1915649ef022SMatthew Knepley     test:
1916649ef022SMatthew Knepley       suffix: 2d_tri_p3_p2_p2
1917444129b9SMatthew G. Knepley       args: -sol_type cubic \
1918649ef022SMatthew Knepley             -vel_petscspace_degree 3 -pres_petscspace_degree 2 -temp_petscspace_degree 2 \
1919444129b9SMatthew G. Knepley             -dmts_check .001 -ts_max_steps 4 -ts_dt 0.1
1920649ef022SMatthew Knepley 
1921606d57d4SMatthew G. Knepley     test:
1922606d57d4SMatthew G. Knepley       # Using -dm_refine 3 -convest_num_refine 3 gives L_2 convergence rate: [3.0, 2.1, 3.1]
1923606d57d4SMatthew G. Knepley       suffix: 2d_tri_p2_p1_p1_tg_sconv
1924444129b9SMatthew G. Knepley       args: -sol_type taylor_green \
1925606d57d4SMatthew G. Knepley             -vel_petscspace_degree 2 -pres_petscspace_degree 1 -temp_petscspace_degree 1 \
1926444129b9SMatthew G. Knepley             -ts_max_steps 1 -ts_dt 1e-8 -ts_convergence_estimate -ts_convergence_temporal 0 -convest_num_refine 1
1927606d57d4SMatthew G. Knepley 
1928606d57d4SMatthew G. Knepley     test:
1929606d57d4SMatthew G. Knepley       # Using -dm_refine 3 -convest_num_refine 2 gives L_2 convergence rate: [1.2, 1.5, 1.2]
1930606d57d4SMatthew G. Knepley       suffix: 2d_tri_p2_p1_p1_tg_tconv
1931444129b9SMatthew G. Knepley       args: -sol_type taylor_green \
1932606d57d4SMatthew G. Knepley             -vel_petscspace_degree 2 -pres_petscspace_degree 1 -temp_petscspace_degree 1 \
1933444129b9SMatthew G. Knepley             -ts_max_steps 4 -ts_dt 0.1 -ts_convergence_estimate -convest_num_refine 1
1934444129b9SMatthew G. Knepley 
1935444129b9SMatthew G. Knepley   testset:
1936444129b9SMatthew G. Knepley     requires: triangle !single
1937444129b9SMatthew G. Knepley     args: -dm_plex_separate_marker -mod_type conducting \
1938a712f3bbSMatthew G. Knepley           -div_petscdualspace_lagrange_use_moments -div_petscdualspace_lagrange_moment_order 3 \
1939444129b9SMatthew G. Knepley           -snes_error_if_not_converged -snes_max_linear_solve_fail 5 \
1940444129b9SMatthew G. Knepley           -ksp_type fgmres -ksp_max_it 2 -ksp_gmres_restart 10 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged \
1941444129b9SMatthew G. Knepley           -pc_type fieldsplit -pc_fieldsplit_0_fields 0,2 -pc_fieldsplit_1_fields 1 \
1942444129b9SMatthew G. Knepley           -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full \
1943606d57d4SMatthew G. Knepley             -fieldsplit_0_pc_type lu \
1944606d57d4SMatthew G. Knepley             -fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type jacobi
1945606d57d4SMatthew G. Knepley 
1946444129b9SMatthew G. Knepley     test:
1947444129b9SMatthew G. Knepley       # At this resolution, the rhs is inconsistent on some Newton steps
1948444129b9SMatthew G. Knepley       suffix: 2d_tri_p2_p1_p1_conduct
1949444129b9SMatthew G. Knepley       args: -sol_type quadratic \
1950444129b9SMatthew G. Knepley             -vel_petscspace_degree 2 -pres_petscspace_degree 1 -temp_petscspace_degree 1 \
1951444129b9SMatthew G. Knepley             -dmts_check .001 -ts_max_steps 4 -ts_dt 0.1 \
1952444129b9SMatthew G. Knepley             -pc_fieldsplit_schur_precondition full \
1953444129b9SMatthew G. Knepley               -fieldsplit_pressure_ksp_max_it 2 -fieldsplit_pressure_pc_type svd
1954444129b9SMatthew G. Knepley 
1955444129b9SMatthew G. Knepley     test:
1956444129b9SMatthew G. Knepley       suffix: 2d_tri_p2_p1_p2_conduct_pipe
1957444129b9SMatthew G. Knepley       args: -sol_type pipe \
1958444129b9SMatthew G. Knepley             -vel_petscspace_degree 2 -pres_petscspace_degree 1 -temp_petscspace_degree 2 \
1959444129b9SMatthew G. Knepley             -dmts_check .001 -ts_max_steps 4 -ts_dt 0.1
1960444129b9SMatthew G. Knepley 
1961*367970cfSMatthew G. Knepley     test:
1962*367970cfSMatthew G. Knepley       suffix: 2d_tri_p2_p1_p2_conduct_pipe_wiggly_sconv
1963*367970cfSMatthew G. Knepley       args: -sol_type pipe_wiggly -Fr 1e10 \
1964*367970cfSMatthew G. Knepley             -vel_petscspace_degree 2 -pres_petscspace_degree 1 -temp_petscspace_degree 2 \
1965*367970cfSMatthew G. Knepley             -ts_convergence_estimate -ts_convergence_temporal 0 -convest_num_refine 1 \
1966*367970cfSMatthew G. Knepley             -ts_max_steps 1 -ts_dt 1e10 \
1967*367970cfSMatthew G. Knepley             -ksp_atol 1e-12 -ksp_max_it 300 \
1968*367970cfSMatthew G. Knepley               -fieldsplit_pressure_ksp_atol 1e-14
1969*367970cfSMatthew G. Knepley 
1970649ef022SMatthew Knepley TEST*/
1971