xref: /libCEED/examples/fluids/qfunctions/blasius.h (revision 88626eed6564cd43033d3137230605fb5f962840)
1*88626eedSJames Wright // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2*88626eedSJames Wright // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3*88626eedSJames Wright //
4*88626eedSJames Wright // SPDX-License-Identifier: BSD-2-Clause
5*88626eedSJames Wright //
6*88626eedSJames Wright // This file is part of CEED:  http://github.com/ceed
7*88626eedSJames Wright 
8*88626eedSJames Wright /// @file
9*88626eedSJames Wright /// Operator for Navier-Stokes example using PETSc
10*88626eedSJames Wright 
11*88626eedSJames Wright 
12*88626eedSJames Wright #ifndef blasius_h
13*88626eedSJames Wright #define blasius_h
14*88626eedSJames Wright 
15*88626eedSJames Wright #include <math.h>
16*88626eedSJames Wright #include <ceed.h>
17*88626eedSJames Wright #include "../navierstokes.h"
18*88626eedSJames Wright 
19*88626eedSJames Wright #ifndef blasius_context_struct
20*88626eedSJames Wright #define blasius_context_struct
21*88626eedSJames Wright typedef struct BlasiusContext_ *BlasiusContext;
22*88626eedSJames Wright struct BlasiusContext_ {
23*88626eedSJames Wright   bool       implicit;  // !< Using implicit timesteping or not
24*88626eedSJames Wright   CeedScalar delta0;    // !< Boundary layer height at inflow
25*88626eedSJames Wright   CeedScalar Uinf;      // !< Velocity at boundary layer edge
26*88626eedSJames Wright   CeedScalar P0;        // !< Pressure at outflow
27*88626eedSJames Wright   CeedScalar theta0;    // !< Temperature at inflow
28*88626eedSJames Wright   struct NewtonianIdealGasContext_ newtonian_ctx;
29*88626eedSJames Wright };
30*88626eedSJames Wright #endif
31*88626eedSJames Wright 
32*88626eedSJames Wright #ifndef M_PI
33*88626eedSJames Wright #define M_PI    3.14159265358979323846
34*88626eedSJames Wright #endif
35*88626eedSJames Wright 
36*88626eedSJames Wright void CEED_QFUNCTION_HELPER(BlasiusSolution)(const CeedScalar y,
37*88626eedSJames Wright     const CeedScalar Uinf, const CeedScalar x0, const CeedScalar x,
38*88626eedSJames Wright     const CeedScalar rho, CeedScalar *u, CeedScalar *v, CeedScalar *t12,
39*88626eedSJames Wright     const NewtonianIdealGasContext newt_ctx) {
40*88626eedSJames Wright 
41*88626eedSJames Wright   CeedInt nprofs = 50;
42*88626eedSJames Wright   // *INDENT-OFF*
43*88626eedSJames Wright   CeedScalar eta_table[] = {
44*88626eedSJames Wright     0.000000000000000000e+00, 1.282051282051281937e-01, 2.564102564102563875e-01, 3.846153846153845812e-01, 5.128205128205127750e-01,
45*88626eedSJames Wright     6.410256410256409687e-01, 7.692307692307691624e-01, 8.974358974358973562e-01, 1.025641025641025550e+00, 1.153846153846153744e+00,
46*88626eedSJames Wright     1.282051282051281937e+00, 1.410256410256410131e+00, 1.538461538461538325e+00, 1.666666666666666519e+00, 1.794871794871794712e+00,
47*88626eedSJames Wright     1.923076923076922906e+00, 2.051282051282051100e+00, 2.179487179487179294e+00, 2.307692307692307487e+00, 2.435897435897435681e+00,
48*88626eedSJames Wright     2.564102564102563875e+00, 2.692307692307692069e+00, 2.820512820512820262e+00, 2.948717948717948456e+00, 3.076923076923076650e+00,
49*88626eedSJames Wright     3.205128205128204844e+00, 3.333333333333333037e+00, 3.461538461538461231e+00, 3.589743589743589425e+00, 3.717948717948717618e+00,
50*88626eedSJames Wright     3.846153846153845812e+00, 3.974358974358974006e+00, 4.102564102564102200e+00, 4.230769230769229949e+00, 4.358974358974358587e+00,
51*88626eedSJames Wright     4.487179487179487225e+00, 4.615384615384614975e+00, 4.743589743589742724e+00, 4.871794871794871362e+00, 5.000000000000000000e+00,
52*88626eedSJames Wright     5.500000000000000000e+00, 6.000000000000000000e+00, 6.500000000000000000e+00, 7.000000000000000000e+00, 7.500000000000000000e+00,
53*88626eedSJames Wright     8.000000000000000000e+00, 8.500000000000000000e+00, 9.000000000000000000e+00, 9.500000000000000000e+00, 1.000000000000000000e+01};
54*88626eedSJames Wright 
55*88626eedSJames Wright   CeedScalar f_table[] = {
56*88626eedSJames Wright     0.000000000000000000e+00, 2.728923405566200267e-03, 1.091524811461423369e-02, 2.455658828897525764e-02, 4.364674649279581820e-02,
57*88626eedSJames Wright     6.817382707725749835e-02, 9.811838418932711248e-02, 1.334516294237205192e-01, 1.741337304561980659e-01, 2.201122374410622862e-01,
58*88626eedSJames Wright     2.713206781625860375e-01, 3.276773654929600599e-01, 3.890844612583744255e-01, 4.554273387986328414e-01, 5.265742820946719416e-01,
59*88626eedSJames Wright     6.023765522220410062e-01, 6.826688421431770237e-01, 7.672701287583111318e-01, 8.559849171804534418e-01, 9.486048570979430661e-01,
60*88626eedSJames Wright     1.044910695686512625e+00, 1.144674516826549082e+00, 1.247662203367335465e+00, 1.353636048811749593e+00, 1.462357437868362364e+00,
61*88626eedSJames Wright     1.573589512396551759e+00, 1.687099740622293842e+00, 1.802662313062363353e+00, 1.920060297987626230e+00, 2.039087501786055245e+00,
62*88626eedSJames Wright     2.159549994377929050e+00, 2.281267275838891884e+00, 2.404073076539093190e+00, 2.527815798402052838e+00, 2.652358618452637540e+00,
63*88626eedSJames Wright     2.777579287003750341e+00, 2.903369661199559637e+00, 3.029635020019957992e+00, 3.156293209307130088e+00, 3.283273665161465349e+00,
64*88626eedSJames Wright     3.780571892998292771e+00, 4.279620922520262383e+00, 4.779322325882148448e+00, 5.279238811036782053e+00, 5.779218028455369804e+00,
65*88626eedSJames Wright     6.279213431354994768e+00, 6.779212528163703233e+00, 7.279212370655419484e+00, 7.779212346288013613e+00, 8.279212342945751146e+00};
66*88626eedSJames Wright 
67*88626eedSJames Wright   CeedScalar fp_table[] = {
68*88626eedSJames Wright     0.000000000000000000e+00, 4.257083277988830267e-02, 8.513297869782740501e-02, 1.276641169537044151e-01, 1.701271279078802878e-01,
69*88626eedSJames Wright     2.124702831905590783e-01, 2.546276046951935212e-01, 2.965194442747576264e-01, 3.380533304776729975e-01, 3.791251204629754179e-01,
70*88626eedSJames Wright     4.196204840172004791e-01, 4.594167322894788796e-01, 4.983849866855867838e-01, 5.363926638765821320e-01, 5.733062319885513514e-01,
71*88626eedSJames Wright     6.089941719927144392e-01, 6.433300586189647507e-01, 6.761956584341198839e-01, 7.074839307288774970e-01, 7.371018110314454530e-01,
72*88626eedSJames Wright     7.649726585225528064e-01, 7.910382579383948842e-01, 8.152602836158657773e-01, 8.376211573266827415e-01, 8.581242609418713307e-01,
73*88626eedSJames Wright     8.767934976651666767e-01, 8.936722290953328374e-01, 9.088216471306606037e-01, 9.223186672607004422e-01, 9.342534510898168332e-01,
74*88626eedSJames Wright     9.447266795705382414e-01, 9.538467037387058367e-01, 9.617266968332524035e-01, 9.684819213624265011e-01, 9.742272083384174719e-01,
75*88626eedSJames Wright     9.790747253056680810e-01, 9.831320868743089747e-01, 9.865008381344084754e-01, 9.892753192614093249e-01, 9.915419001656551323e-01,
76*88626eedSJames Wright     9.968788209317821503e-01, 9.989728724371175206e-01, 9.996990677381791812e-01, 9.999216041491896245e-01, 9.999818594083667023e-01,
77*88626eedSJames Wright     9.999962745365539307e-01, 9.999993214550036980e-01, 9.999998904550418954e-01, 9.999999843329338001e-01, 9.999999980166356384e-01};
78*88626eedSJames Wright 
79*88626eedSJames Wright   CeedScalar fpp_table[] = {
80*88626eedSJames Wright     3.320573362157903663e-01, 3.320379743512646420e-01, 3.319024760665882368e-01, 3.315350015070190337e-01, 3.308206767975666041e-01,
81*88626eedSJames Wright     3.296466995822193158e-01, 3.279038639411161471e-01, 3.254884713737624113e-01, 3.223045750196085746e-01, 3.182664816607024272e-01,
82*88626eedSJames Wright     3.133014118810801829e-01, 3.073521951089355775e-01, 3.003798556086043625e-01, 2.923659305537876785e-01, 2.833143548208253981e-01,
83*88626eedSJames Wright     2.732527514995234941e-01, 2.622329840371728227e-01, 2.503308560706500874e-01, 2.376448876931176457e-01, 2.242941499773744018e-01,
84*88626eedSJames Wright     2.104151994284793603e-01, 1.961582158440171031e-01, 1.816825052623964043e-01, 1.671515786102889534e-01, 1.527280512426029968e-01,
85*88626eedSJames Wright     1.385686249977987894e-01, 1.248194106805364800e-01, 1.116118251613979206e-01, 9.905925581301598670e-02, 8.725462988794610575e-02,
86*88626eedSJames Wright     7.626896310981794158e-02, 6.615089622448211415e-02, 5.692716644118058639e-02, 4.860390768479891377e-02, 4.116863313890323922e-02,
87*88626eedSJames Wright     3.459272784597366285e-02, 2.883426862493499582e-02, 2.384099224121952881e-02, 1.955324839409207718e-02, 1.590679868531958210e-02,
88*88626eedSJames Wright     6.578593141419011685e-03, 2.402039843751689954e-03, 7.741093231657678389e-04, 2.201689553063347941e-04, 5.526217815680267893e-05,
89*88626eedSJames Wright     1.224092624232004387e-05, 2.392841910090350858e-06, 4.127879363882133676e-07, 6.284244603762621373e-08, 8.442944409712819646e-09};
90*88626eedSJames Wright   // *INDENT-ON*
91*88626eedSJames Wright 
92*88626eedSJames Wright   CeedScalar nu = newt_ctx->mu / rho;
93*88626eedSJames Wright   CeedScalar eta = y*sqrt(Uinf/(nu*(x0+x)));
94*88626eedSJames Wright   CeedInt idx=-1;
95*88626eedSJames Wright 
96*88626eedSJames Wright   for(CeedInt i=0; i<nprofs; i++) {
97*88626eedSJames Wright     if (eta < eta_table[i]) {
98*88626eedSJames Wright       idx = i;
99*88626eedSJames Wright       break;
100*88626eedSJames Wright     }
101*88626eedSJames Wright   }
102*88626eedSJames Wright   CeedScalar f, fp, fpp;
103*88626eedSJames Wright 
104*88626eedSJames Wright   if (idx > 0) { // eta within the bounds of eta_table
105*88626eedSJames Wright     CeedScalar coeff = (eta - eta_table[idx-1]) / (eta_table[idx] - eta_table[idx
106*88626eedSJames Wright                        -1]);
107*88626eedSJames Wright 
108*88626eedSJames Wright     f   = f_table[idx-1]   + coeff*( f_table[idx]   - f_table[idx-1] );
109*88626eedSJames Wright     fp  = fp_table[idx-1]  + coeff*( fp_table[idx]  - fp_table[idx-1] );
110*88626eedSJames Wright     fpp = fpp_table[idx-1] + coeff*( fpp_table[idx] - fpp_table[idx-1] );
111*88626eedSJames Wright   } else { // eta outside bounds of eta_table
112*88626eedSJames Wright     f   = f_table[nprofs-1];
113*88626eedSJames Wright     fp  = fp_table[nprofs-1];
114*88626eedSJames Wright     fpp = fpp_table[nprofs-1];
115*88626eedSJames Wright     eta = eta_table[nprofs-1];
116*88626eedSJames Wright   }
117*88626eedSJames Wright 
118*88626eedSJames Wright   *u = Uinf*fp;
119*88626eedSJames Wright   *t12 = rho*nu*Uinf*fpp*sqrt(Uinf/(nu*(x0+x)));
120*88626eedSJames Wright   *v = 0.5*sqrt(nu*Uinf/(x0+x))*(eta*fp - f);
121*88626eedSJames Wright }
122*88626eedSJames Wright 
123*88626eedSJames Wright // *****************************************************************************
124*88626eedSJames Wright // This QFunction sets a Blasius boundary layer for the initial condition
125*88626eedSJames Wright // *****************************************************************************
126*88626eedSJames Wright CEED_QFUNCTION(ICsBlasius)(void *ctx, CeedInt Q,
127*88626eedSJames Wright                            const CeedScalar *const *in, CeedScalar *const *out) {
128*88626eedSJames Wright   // Inputs
129*88626eedSJames Wright   const CeedScalar (*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
130*88626eedSJames Wright 
131*88626eedSJames Wright   // Outputs
132*88626eedSJames Wright   CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
133*88626eedSJames Wright 
134*88626eedSJames Wright   const BlasiusContext context = (BlasiusContext)ctx;
135*88626eedSJames Wright   const CeedScalar cv     = context->newtonian_ctx.cv;
136*88626eedSJames Wright   const CeedScalar cp     = context->newtonian_ctx.cp;
137*88626eedSJames Wright   const CeedScalar gamma  = cp/cv;
138*88626eedSJames Wright   const CeedScalar mu     = context->newtonian_ctx.mu;
139*88626eedSJames Wright 
140*88626eedSJames Wright   const CeedScalar theta0 = context->theta0;
141*88626eedSJames Wright   const CeedScalar P0     = context->P0;
142*88626eedSJames Wright   const CeedScalar delta0 = context->delta0;
143*88626eedSJames Wright   const CeedScalar Uinf   = context->Uinf;
144*88626eedSJames Wright 
145*88626eedSJames Wright   const CeedScalar e_internal = cv * theta0;
146*88626eedSJames Wright   const CeedScalar rho        = P0 / ((gamma - 1) * e_internal);
147*88626eedSJames Wright   const CeedScalar x0         = Uinf*rho / (mu*25/ (delta0*delta0) );
148*88626eedSJames Wright   CeedScalar u, v, t12;
149*88626eedSJames Wright 
150*88626eedSJames Wright   // Quadrature Point Loop
151*88626eedSJames Wright   CeedPragmaSIMD
152*88626eedSJames Wright   for (CeedInt i=0; i<Q; i++) {
153*88626eedSJames Wright     const CeedScalar x[] = {X[0][i], X[1][i], X[2][i]};
154*88626eedSJames Wright 
155*88626eedSJames Wright     BlasiusSolution(x[1], Uinf, x0, x[0], rho, &u, &v, &t12,
156*88626eedSJames Wright                     &context->newtonian_ctx);
157*88626eedSJames Wright 
158*88626eedSJames Wright     q0[0][i] = rho;
159*88626eedSJames Wright     q0[1][i] = u * rho;
160*88626eedSJames Wright     q0[2][i] = v * rho;
161*88626eedSJames Wright     q0[3][i] = 0.;
162*88626eedSJames Wright     q0[4][i] = rho * e_internal + 0.5*(u*u + v*v)*rho;
163*88626eedSJames Wright   } // End of Quadrature Point Loop
164*88626eedSJames Wright   return 0;
165*88626eedSJames Wright }
166*88626eedSJames Wright 
167*88626eedSJames Wright // *****************************************************************************
168*88626eedSJames Wright CEED_QFUNCTION(Blasius_Inflow)(void *ctx, CeedInt Q,
169*88626eedSJames Wright                                const CeedScalar *const *in,
170*88626eedSJames Wright                                CeedScalar *const *out) {
171*88626eedSJames Wright   // *INDENT-OFF*
172*88626eedSJames Wright   // Inputs
173*88626eedSJames Wright   const CeedScalar (*q)[CEED_Q_VLA]          = (const CeedScalar(*)[CEED_Q_VLA])in[0],
174*88626eedSJames Wright                    (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[1],
175*88626eedSJames Wright                    (*X)[CEED_Q_VLA]          = (const CeedScalar(*)[CEED_Q_VLA])in[2];
176*88626eedSJames Wright 
177*88626eedSJames Wright   // Outputs
178*88626eedSJames Wright   CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
179*88626eedSJames Wright   // *INDENT-ON*
180*88626eedSJames Wright   const BlasiusContext context = (BlasiusContext)ctx;
181*88626eedSJames Wright   const bool implicit     = context->implicit;
182*88626eedSJames Wright   const CeedScalar mu     = context->newtonian_ctx.mu;
183*88626eedSJames Wright   const CeedScalar cv     = context->newtonian_ctx.cv;
184*88626eedSJames Wright   const CeedScalar cp     = context->newtonian_ctx.cp;
185*88626eedSJames Wright   const CeedScalar Rd     = cp - cv;
186*88626eedSJames Wright 
187*88626eedSJames Wright   const CeedScalar theta0 = context->theta0;
188*88626eedSJames Wright   const CeedScalar P0     = context->P0;
189*88626eedSJames Wright   const CeedScalar delta0 = context->delta0;
190*88626eedSJames Wright   const CeedScalar Uinf   = context->Uinf;
191*88626eedSJames Wright   const CeedScalar rho_0  = P0 / (Rd * theta0);
192*88626eedSJames Wright   const CeedScalar x0     = Uinf*rho_0 / (mu*25/ (delta0*delta0) );
193*88626eedSJames Wright 
194*88626eedSJames Wright   CeedPragmaSIMD
195*88626eedSJames Wright   // Quadrature Point Loop
196*88626eedSJames Wright   for (CeedInt i=0; i<Q; i++) {
197*88626eedSJames Wright     // Setup
198*88626eedSJames Wright     // -- Interp-to-Interp q_data
199*88626eedSJames Wright     // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q).
200*88626eedSJames Wright     // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q).
201*88626eedSJames Wright     // We can effect this by swapping the sign on this weight
202*88626eedSJames Wright     const CeedScalar wdetJb  = (implicit ? -1. : 1.) * q_data_sur[0][i];
203*88626eedSJames Wright 
204*88626eedSJames Wright     // Calcualte prescribed inflow values
205*88626eedSJames Wright     const CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]};
206*88626eedSJames Wright 
207*88626eedSJames Wright     // Find pressure using state inside the domain
208*88626eedSJames Wright     const CeedScalar rho = q[0][i];
209*88626eedSJames Wright     const CeedScalar P = rho * Rd * theta0; // interior rho with exterior T
210*88626eedSJames Wright 
211*88626eedSJames Wright     // Find inflow state using calculated P and prescribed velocity, theta0
212*88626eedSJames Wright     const CeedScalar e_internal = cv * theta0;
213*88626eedSJames Wright 
214*88626eedSJames Wright     CeedScalar velocity[3] = {0.};
215*88626eedSJames Wright     CeedScalar t12;
216*88626eedSJames Wright     BlasiusSolution(x[1], Uinf, x0, x[0], rho_0, &velocity[0], &velocity[1],
217*88626eedSJames Wright                     &t12, &context->newtonian_ctx);
218*88626eedSJames Wright 
219*88626eedSJames Wright     const CeedScalar E_kinetic = .5 * rho * (velocity[0]*velocity[0] +
220*88626eedSJames Wright                                  velocity[1]*velocity[1] +
221*88626eedSJames Wright                                  velocity[2]*velocity[2]);
222*88626eedSJames Wright     const CeedScalar E = rho * e_internal + E_kinetic;  // use interior rho
223*88626eedSJames Wright     // from T       and  u exterior
224*88626eedSJames Wright     // ---- Normal vect
225*88626eedSJames Wright     const CeedScalar norm[3] = {q_data_sur[1][i],
226*88626eedSJames Wright                                 q_data_sur[2][i],
227*88626eedSJames Wright                                 q_data_sur[3][i]
228*88626eedSJames Wright                                };
229*88626eedSJames Wright 
230*88626eedSJames Wright     // The Physics
231*88626eedSJames Wright     // Zero v so all future terms can safely sum into it
232*88626eedSJames Wright     for (int j=0; j<5; j++) v[j][i] = 0.;
233*88626eedSJames Wright 
234*88626eedSJames Wright     const CeedScalar u_normal = norm[0]*velocity[0] +
235*88626eedSJames Wright                                 norm[1]*velocity[1] +
236*88626eedSJames Wright                                 norm[2]*velocity[2];
237*88626eedSJames Wright 
238*88626eedSJames Wright     // The Physics
239*88626eedSJames Wright     // -- Density
240*88626eedSJames Wright     v[0][i] -= wdetJb * rho * u_normal; // interior rho
241*88626eedSJames Wright 
242*88626eedSJames Wright     // -- Momentum
243*88626eedSJames Wright     for (int j=0; j<3; j++)
244*88626eedSJames Wright       v[j+1][i] -= wdetJb * (rho * u_normal * velocity[j] + // interior rho
245*88626eedSJames Wright                              norm[j] * P); // mixed P
246*88626eedSJames Wright     v[2][i] -= wdetJb * t12  ;
247*88626eedSJames Wright 
248*88626eedSJames Wright     // -- Total Energy Density
249*88626eedSJames Wright     v[4][i] -= wdetJb * u_normal * (E + P);
250*88626eedSJames Wright     v[4][i] -= wdetJb * t12 * velocity[1];
251*88626eedSJames Wright 
252*88626eedSJames Wright   } // End Quadrature Point Loop
253*88626eedSJames Wright   return 0;
254*88626eedSJames Wright }
255*88626eedSJames Wright 
256*88626eedSJames Wright // *****************************************************************************
257*88626eedSJames Wright CEED_QFUNCTION(Blasius_Outflow)(void *ctx, CeedInt Q,
258*88626eedSJames Wright                                 const CeedScalar *const *in,
259*88626eedSJames Wright                                 CeedScalar *const *out) {
260*88626eedSJames Wright   // *INDENT-OFF*
261*88626eedSJames Wright   // Inputs
262*88626eedSJames Wright   const CeedScalar (*q)[CEED_Q_VLA]          = (const CeedScalar(*)[CEED_Q_VLA])in[0],
263*88626eedSJames Wright                    (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[1],
264*88626eedSJames Wright                    (*X)[CEED_Q_VLA]          = (const CeedScalar(*)[CEED_Q_VLA])in[2];
265*88626eedSJames Wright   // Outputs
266*88626eedSJames Wright   CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
267*88626eedSJames Wright   // *INDENT-ON*
268*88626eedSJames Wright 
269*88626eedSJames Wright   const BlasiusContext context = (BlasiusContext)ctx;
270*88626eedSJames Wright   const bool implicit     = context->implicit;
271*88626eedSJames Wright   const CeedScalar mu     = context->newtonian_ctx.mu;
272*88626eedSJames Wright   const CeedScalar cv     = context->newtonian_ctx.cv;
273*88626eedSJames Wright   const CeedScalar cp     = context->newtonian_ctx.cp;
274*88626eedSJames Wright   const CeedScalar Rd     = cp - cv;
275*88626eedSJames Wright 
276*88626eedSJames Wright   const CeedScalar theta0 = context->theta0;
277*88626eedSJames Wright   const CeedScalar P0     = context->P0;
278*88626eedSJames Wright   const CeedScalar rho_0  = P0 / (Rd*theta0);
279*88626eedSJames Wright   const CeedScalar delta0 = context->delta0;
280*88626eedSJames Wright   const CeedScalar Uinf   = context->Uinf;
281*88626eedSJames Wright   const CeedScalar x0     = Uinf*rho_0 / (mu*25/ (delta0*delta0) );
282*88626eedSJames Wright 
283*88626eedSJames Wright   CeedPragmaSIMD
284*88626eedSJames Wright   // Quadrature Point Loop
285*88626eedSJames Wright   for (CeedInt i=0; i<Q; i++) {
286*88626eedSJames Wright     // Setup
287*88626eedSJames Wright     // -- Interp in
288*88626eedSJames Wright     const CeedScalar rho      =  q[0][i];
289*88626eedSJames Wright     const CeedScalar u[3]     = {q[1][i] / rho,
290*88626eedSJames Wright                                  q[2][i] / rho,
291*88626eedSJames Wright                                  q[3][i] / rho
292*88626eedSJames Wright                                 };
293*88626eedSJames Wright     const CeedScalar E        =  q[4][i];
294*88626eedSJames Wright 
295*88626eedSJames Wright     // -- Interp-to-Interp q_data
296*88626eedSJames Wright     // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q).
297*88626eedSJames Wright     // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q).
298*88626eedSJames Wright     // We can effect this by swapping the sign on this weight
299*88626eedSJames Wright     const CeedScalar wdetJb  = (implicit ? -1. : 1.) * q_data_sur[0][i];
300*88626eedSJames Wright 
301*88626eedSJames Wright     // ---- Normal vect
302*88626eedSJames Wright     const CeedScalar norm[3] = {q_data_sur[1][i],
303*88626eedSJames Wright                                 q_data_sur[2][i],
304*88626eedSJames Wright                                 q_data_sur[3][i]
305*88626eedSJames Wright                                };
306*88626eedSJames Wright 
307*88626eedSJames Wright     // The Physics
308*88626eedSJames Wright     // Zero v so all future terms can safely sum into it
309*88626eedSJames Wright     for (int j=0; j<5; j++) v[j][i] = 0.;
310*88626eedSJames Wright 
311*88626eedSJames Wright     // Implementing outflow condition
312*88626eedSJames Wright     const CeedScalar P         = P0; // pressure
313*88626eedSJames Wright     const CeedScalar u_normal  = norm[0]*u[0] + norm[1]*u[1] +
314*88626eedSJames Wright                                  norm[2]*u[2]; // Normal velocity
315*88626eedSJames Wright 
316*88626eedSJames Wright     // Calculate prescribed outflow traction values
317*88626eedSJames Wright     const CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]};
318*88626eedSJames Wright     CeedScalar velocity[3] = {0.};
319*88626eedSJames Wright     CeedScalar t12;
320*88626eedSJames Wright     BlasiusSolution(x[1], Uinf, x0, x[0], rho_0, &velocity[0], &velocity[1],
321*88626eedSJames Wright                     &t12, &context->newtonian_ctx);
322*88626eedSJames Wright     // The Physics
323*88626eedSJames Wright     // -- Density
324*88626eedSJames Wright     v[0][i] -= wdetJb * rho * u_normal;
325*88626eedSJames Wright 
326*88626eedSJames Wright     // -- Momentum
327*88626eedSJames Wright     for (int j=0; j<3; j++)
328*88626eedSJames Wright       v[j+1][i] -= wdetJb *(rho * u_normal * u[j] + norm[j] * P);
329*88626eedSJames Wright     v[2][i] += wdetJb * t12  ;
330*88626eedSJames Wright 
331*88626eedSJames Wright     // -- Total Energy Density
332*88626eedSJames Wright     v[4][i] -= wdetJb * u_normal * (E + P);
333*88626eedSJames Wright     v[4][i] += wdetJb * t12 * velocity[1];
334*88626eedSJames Wright 
335*88626eedSJames Wright   } // End Quadrature Point Loop
336*88626eedSJames Wright   return 0;
337*88626eedSJames Wright }
338*88626eedSJames Wright #endif // blasius_h
339