xref: /honee/qfunctions/blasius.h (revision 9abe94a0d9920df039ccf0028534fa8654e67461)
1bb8a0c61SJames Wright // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2bb8a0c61SJames Wright // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3bb8a0c61SJames Wright //
4bb8a0c61SJames Wright // SPDX-License-Identifier: BSD-2-Clause
5bb8a0c61SJames Wright //
6bb8a0c61SJames Wright // This file is part of CEED:  http://github.com/ceed
7bb8a0c61SJames Wright 
8bb8a0c61SJames Wright /// @file
9bb8a0c61SJames Wright /// Operator for Navier-Stokes example using PETSc
10bb8a0c61SJames Wright 
11bb8a0c61SJames Wright 
12bb8a0c61SJames Wright #ifndef blasius_h
13bb8a0c61SJames Wright #define blasius_h
14bb8a0c61SJames Wright 
15bb8a0c61SJames Wright #include <math.h>
16bb8a0c61SJames Wright #include <ceed.h>
1715a3537eSJed Brown #include "newtonian_types.h"
18bb8a0c61SJames Wright 
19bb8a0c61SJames Wright typedef struct BlasiusContext_ *BlasiusContext;
20bb8a0c61SJames Wright struct BlasiusContext_ {
21bb8a0c61SJames Wright   bool       implicit;  // !< Using implicit timesteping or not
222acc7cbcSKenneth E. Jansen   bool       weakT;     // !< flag to set Temperature weakly at inflow
23bb8a0c61SJames Wright   CeedScalar delta0;    // !< Boundary layer height at inflow
24bb8a0c61SJames Wright   CeedScalar Uinf;      // !< Velocity at boundary layer edge
25bb8a0c61SJames Wright   CeedScalar P0;        // !< Pressure at outflow
26bb8a0c61SJames Wright   CeedScalar theta0;    // !< Temperature at inflow
27bb8a0c61SJames Wright   struct NewtonianIdealGasContext_ newtonian_ctx;
28bb8a0c61SJames Wright };
29bb8a0c61SJames Wright 
30bb8a0c61SJames Wright #ifndef M_PI
31bb8a0c61SJames Wright #define M_PI    3.14159265358979323846
32bb8a0c61SJames Wright #endif
33bb8a0c61SJames Wright 
34bb8a0c61SJames Wright void CEED_QFUNCTION_HELPER(BlasiusSolution)(const CeedScalar y,
35bb8a0c61SJames Wright     const CeedScalar Uinf, const CeedScalar x0, const CeedScalar x,
36bb8a0c61SJames Wright     const CeedScalar rho, CeedScalar *u, CeedScalar *v, CeedScalar *t12,
37bb8a0c61SJames Wright     const NewtonianIdealGasContext newt_ctx) {
38bb8a0c61SJames Wright 
39bb8a0c61SJames Wright   CeedInt nprofs = 50;
40bb8a0c61SJames Wright   // *INDENT-OFF*
41bb8a0c61SJames Wright   CeedScalar eta_table[] = {
42bb8a0c61SJames Wright     0.000000000000000000e+00, 1.282051282051281937e-01, 2.564102564102563875e-01, 3.846153846153845812e-01, 5.128205128205127750e-01,
43bb8a0c61SJames Wright     6.410256410256409687e-01, 7.692307692307691624e-01, 8.974358974358973562e-01, 1.025641025641025550e+00, 1.153846153846153744e+00,
44bb8a0c61SJames Wright     1.282051282051281937e+00, 1.410256410256410131e+00, 1.538461538461538325e+00, 1.666666666666666519e+00, 1.794871794871794712e+00,
45bb8a0c61SJames Wright     1.923076923076922906e+00, 2.051282051282051100e+00, 2.179487179487179294e+00, 2.307692307692307487e+00, 2.435897435897435681e+00,
46bb8a0c61SJames Wright     2.564102564102563875e+00, 2.692307692307692069e+00, 2.820512820512820262e+00, 2.948717948717948456e+00, 3.076923076923076650e+00,
47bb8a0c61SJames Wright     3.205128205128204844e+00, 3.333333333333333037e+00, 3.461538461538461231e+00, 3.589743589743589425e+00, 3.717948717948717618e+00,
48bb8a0c61SJames Wright     3.846153846153845812e+00, 3.974358974358974006e+00, 4.102564102564102200e+00, 4.230769230769229949e+00, 4.358974358974358587e+00,
49bb8a0c61SJames Wright     4.487179487179487225e+00, 4.615384615384614975e+00, 4.743589743589742724e+00, 4.871794871794871362e+00, 5.000000000000000000e+00,
50bb8a0c61SJames Wright     5.500000000000000000e+00, 6.000000000000000000e+00, 6.500000000000000000e+00, 7.000000000000000000e+00, 7.500000000000000000e+00,
51bb8a0c61SJames Wright     8.000000000000000000e+00, 8.500000000000000000e+00, 9.000000000000000000e+00, 9.500000000000000000e+00, 1.000000000000000000e+01};
52bb8a0c61SJames Wright 
53bb8a0c61SJames Wright   CeedScalar f_table[] = {
54bb8a0c61SJames Wright     0.000000000000000000e+00, 2.728923405566200267e-03, 1.091524811461423369e-02, 2.455658828897525764e-02, 4.364674649279581820e-02,
55bb8a0c61SJames Wright     6.817382707725749835e-02, 9.811838418932711248e-02, 1.334516294237205192e-01, 1.741337304561980659e-01, 2.201122374410622862e-01,
56bb8a0c61SJames Wright     2.713206781625860375e-01, 3.276773654929600599e-01, 3.890844612583744255e-01, 4.554273387986328414e-01, 5.265742820946719416e-01,
57bb8a0c61SJames Wright     6.023765522220410062e-01, 6.826688421431770237e-01, 7.672701287583111318e-01, 8.559849171804534418e-01, 9.486048570979430661e-01,
58bb8a0c61SJames Wright     1.044910695686512625e+00, 1.144674516826549082e+00, 1.247662203367335465e+00, 1.353636048811749593e+00, 1.462357437868362364e+00,
59bb8a0c61SJames Wright     1.573589512396551759e+00, 1.687099740622293842e+00, 1.802662313062363353e+00, 1.920060297987626230e+00, 2.039087501786055245e+00,
60bb8a0c61SJames Wright     2.159549994377929050e+00, 2.281267275838891884e+00, 2.404073076539093190e+00, 2.527815798402052838e+00, 2.652358618452637540e+00,
61bb8a0c61SJames Wright     2.777579287003750341e+00, 2.903369661199559637e+00, 3.029635020019957992e+00, 3.156293209307130088e+00, 3.283273665161465349e+00,
62bb8a0c61SJames Wright     3.780571892998292771e+00, 4.279620922520262383e+00, 4.779322325882148448e+00, 5.279238811036782053e+00, 5.779218028455369804e+00,
63bb8a0c61SJames Wright     6.279213431354994768e+00, 6.779212528163703233e+00, 7.279212370655419484e+00, 7.779212346288013613e+00, 8.279212342945751146e+00};
64bb8a0c61SJames Wright 
65bb8a0c61SJames Wright   CeedScalar fp_table[] = {
66bb8a0c61SJames Wright     0.000000000000000000e+00, 4.257083277988830267e-02, 8.513297869782740501e-02, 1.276641169537044151e-01, 1.701271279078802878e-01,
67bb8a0c61SJames Wright     2.124702831905590783e-01, 2.546276046951935212e-01, 2.965194442747576264e-01, 3.380533304776729975e-01, 3.791251204629754179e-01,
68bb8a0c61SJames Wright     4.196204840172004791e-01, 4.594167322894788796e-01, 4.983849866855867838e-01, 5.363926638765821320e-01, 5.733062319885513514e-01,
69bb8a0c61SJames Wright     6.089941719927144392e-01, 6.433300586189647507e-01, 6.761956584341198839e-01, 7.074839307288774970e-01, 7.371018110314454530e-01,
70bb8a0c61SJames Wright     7.649726585225528064e-01, 7.910382579383948842e-01, 8.152602836158657773e-01, 8.376211573266827415e-01, 8.581242609418713307e-01,
71bb8a0c61SJames Wright     8.767934976651666767e-01, 8.936722290953328374e-01, 9.088216471306606037e-01, 9.223186672607004422e-01, 9.342534510898168332e-01,
72bb8a0c61SJames Wright     9.447266795705382414e-01, 9.538467037387058367e-01, 9.617266968332524035e-01, 9.684819213624265011e-01, 9.742272083384174719e-01,
73bb8a0c61SJames Wright     9.790747253056680810e-01, 9.831320868743089747e-01, 9.865008381344084754e-01, 9.892753192614093249e-01, 9.915419001656551323e-01,
74bb8a0c61SJames Wright     9.968788209317821503e-01, 9.989728724371175206e-01, 9.996990677381791812e-01, 9.999216041491896245e-01, 9.999818594083667023e-01,
75bb8a0c61SJames Wright     9.999962745365539307e-01, 9.999993214550036980e-01, 9.999998904550418954e-01, 9.999999843329338001e-01, 9.999999980166356384e-01};
76bb8a0c61SJames Wright 
77bb8a0c61SJames Wright   CeedScalar fpp_table[] = {
78bb8a0c61SJames Wright     3.320573362157903663e-01, 3.320379743512646420e-01, 3.319024760665882368e-01, 3.315350015070190337e-01, 3.308206767975666041e-01,
79bb8a0c61SJames Wright     3.296466995822193158e-01, 3.279038639411161471e-01, 3.254884713737624113e-01, 3.223045750196085746e-01, 3.182664816607024272e-01,
80bb8a0c61SJames Wright     3.133014118810801829e-01, 3.073521951089355775e-01, 3.003798556086043625e-01, 2.923659305537876785e-01, 2.833143548208253981e-01,
81bb8a0c61SJames Wright     2.732527514995234941e-01, 2.622329840371728227e-01, 2.503308560706500874e-01, 2.376448876931176457e-01, 2.242941499773744018e-01,
82bb8a0c61SJames Wright     2.104151994284793603e-01, 1.961582158440171031e-01, 1.816825052623964043e-01, 1.671515786102889534e-01, 1.527280512426029968e-01,
83bb8a0c61SJames Wright     1.385686249977987894e-01, 1.248194106805364800e-01, 1.116118251613979206e-01, 9.905925581301598670e-02, 8.725462988794610575e-02,
84bb8a0c61SJames Wright     7.626896310981794158e-02, 6.615089622448211415e-02, 5.692716644118058639e-02, 4.860390768479891377e-02, 4.116863313890323922e-02,
85bb8a0c61SJames Wright     3.459272784597366285e-02, 2.883426862493499582e-02, 2.384099224121952881e-02, 1.955324839409207718e-02, 1.590679868531958210e-02,
86bb8a0c61SJames Wright     6.578593141419011685e-03, 2.402039843751689954e-03, 7.741093231657678389e-04, 2.201689553063347941e-04, 5.526217815680267893e-05,
87bb8a0c61SJames Wright     1.224092624232004387e-05, 2.392841910090350858e-06, 4.127879363882133676e-07, 6.284244603762621373e-08, 8.442944409712819646e-09};
88bb8a0c61SJames Wright   // *INDENT-ON*
89bb8a0c61SJames Wright 
90bb8a0c61SJames Wright   CeedScalar nu = newt_ctx->mu / rho;
91bb8a0c61SJames Wright   CeedScalar eta = y*sqrt(Uinf/(nu*(x0+x)));
92bb8a0c61SJames Wright   CeedInt idx=-1;
93bb8a0c61SJames Wright 
94bb8a0c61SJames Wright   for(CeedInt i=0; i<nprofs; i++) {
95bb8a0c61SJames Wright     if (eta < eta_table[i]) {
96bb8a0c61SJames Wright       idx = i;
97bb8a0c61SJames Wright       break;
98bb8a0c61SJames Wright     }
99bb8a0c61SJames Wright   }
100bb8a0c61SJames Wright   CeedScalar f, fp, fpp;
101bb8a0c61SJames Wright 
102bb8a0c61SJames Wright   if (idx > 0) { // eta within the bounds of eta_table
103bb8a0c61SJames Wright     CeedScalar coeff = (eta - eta_table[idx-1]) / (eta_table[idx] - eta_table[idx
104bb8a0c61SJames Wright                        -1]);
105bb8a0c61SJames Wright 
106bb8a0c61SJames Wright     f   = f_table[idx-1]   + coeff*( f_table[idx]   - f_table[idx-1] );
107bb8a0c61SJames Wright     fp  = fp_table[idx-1]  + coeff*( fp_table[idx]  - fp_table[idx-1] );
108bb8a0c61SJames Wright     fpp = fpp_table[idx-1] + coeff*( fpp_table[idx] - fpp_table[idx-1] );
109bb8a0c61SJames Wright   } else { // eta outside bounds of eta_table
110bb8a0c61SJames Wright     f   = f_table[nprofs-1];
111bb8a0c61SJames Wright     fp  = fp_table[nprofs-1];
112bb8a0c61SJames Wright     fpp = fpp_table[nprofs-1];
113bb8a0c61SJames Wright     eta = eta_table[nprofs-1];
114bb8a0c61SJames Wright   }
115bb8a0c61SJames Wright 
116bb8a0c61SJames Wright   *u = Uinf*fp;
117bb8a0c61SJames Wright   *t12 = rho*nu*Uinf*fpp*sqrt(Uinf/(nu*(x0+x)));
118bb8a0c61SJames Wright   *v = 0.5*sqrt(nu*Uinf/(x0+x))*(eta*fp - f);
119bb8a0c61SJames Wright }
120bb8a0c61SJames Wright 
121bb8a0c61SJames Wright // *****************************************************************************
122bb8a0c61SJames Wright // This QFunction sets a Blasius boundary layer for the initial condition
123bb8a0c61SJames Wright // *****************************************************************************
124bb8a0c61SJames Wright CEED_QFUNCTION(ICsBlasius)(void *ctx, CeedInt Q,
125bb8a0c61SJames Wright                            const CeedScalar *const *in, CeedScalar *const *out) {
126bb8a0c61SJames Wright   // Inputs
127bb8a0c61SJames Wright   const CeedScalar (*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
128bb8a0c61SJames Wright 
129bb8a0c61SJames Wright   // Outputs
130bb8a0c61SJames Wright   CeedScalar (*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
131bb8a0c61SJames Wright 
132bb8a0c61SJames Wright   const BlasiusContext context = (BlasiusContext)ctx;
133bb8a0c61SJames Wright   const CeedScalar cv     = context->newtonian_ctx.cv;
134bb8a0c61SJames Wright   const CeedScalar cp     = context->newtonian_ctx.cp;
135bb8a0c61SJames Wright   const CeedScalar gamma  = cp/cv;
136bb8a0c61SJames Wright   const CeedScalar mu     = context->newtonian_ctx.mu;
137bb8a0c61SJames Wright 
138bb8a0c61SJames Wright   const CeedScalar theta0 = context->theta0;
139bb8a0c61SJames Wright   const CeedScalar P0     = context->P0;
140bb8a0c61SJames Wright   const CeedScalar delta0 = context->delta0;
141bb8a0c61SJames Wright   const CeedScalar Uinf   = context->Uinf;
142bb8a0c61SJames Wright 
143bb8a0c61SJames Wright   const CeedScalar e_internal = cv * theta0;
144bb8a0c61SJames Wright   const CeedScalar rho        = P0 / ((gamma - 1) * e_internal);
145bb8a0c61SJames Wright   const CeedScalar x0         = Uinf*rho / (mu*25/ (delta0*delta0) );
146bb8a0c61SJames Wright   CeedScalar u, v, t12;
147bb8a0c61SJames Wright 
148bb8a0c61SJames Wright   // Quadrature Point Loop
149bb8a0c61SJames Wright   CeedPragmaSIMD
150bb8a0c61SJames Wright   for (CeedInt i=0; i<Q; i++) {
151bb8a0c61SJames Wright     const CeedScalar x[] = {X[0][i], X[1][i], X[2][i]};
152bb8a0c61SJames Wright 
153bb8a0c61SJames Wright     BlasiusSolution(x[1], Uinf, x0, x[0], rho, &u, &v, &t12,
154bb8a0c61SJames Wright                     &context->newtonian_ctx);
155bb8a0c61SJames Wright 
156bb8a0c61SJames Wright     q0[0][i] = rho;
157bb8a0c61SJames Wright     q0[1][i] = u * rho;
158bb8a0c61SJames Wright     q0[2][i] = v * rho;
159bb8a0c61SJames Wright     q0[3][i] = 0.;
160bb8a0c61SJames Wright     q0[4][i] = rho * e_internal + 0.5*(u*u + v*v)*rho;
161bb8a0c61SJames Wright   } // End of Quadrature Point Loop
162bb8a0c61SJames Wright   return 0;
163bb8a0c61SJames Wright }
164bb8a0c61SJames Wright 
165bb8a0c61SJames Wright // *****************************************************************************
166bb8a0c61SJames Wright CEED_QFUNCTION(Blasius_Inflow)(void *ctx, CeedInt Q,
167bb8a0c61SJames Wright                                const CeedScalar *const *in,
168bb8a0c61SJames Wright                                CeedScalar *const *out) {
169bb8a0c61SJames Wright   // *INDENT-OFF*
170bb8a0c61SJames Wright   // Inputs
171bb8a0c61SJames Wright   const CeedScalar (*q)[CEED_Q_VLA]          = (const CeedScalar(*)[CEED_Q_VLA])in[0],
172bb8a0c61SJames Wright                    (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[1],
173bb8a0c61SJames Wright                    (*X)[CEED_Q_VLA]          = (const CeedScalar(*)[CEED_Q_VLA])in[2];
174bb8a0c61SJames Wright 
175bb8a0c61SJames Wright   // Outputs
176bb8a0c61SJames Wright   CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
177bb8a0c61SJames Wright   // *INDENT-ON*
178bb8a0c61SJames Wright   const BlasiusContext context = (BlasiusContext)ctx;
179bb8a0c61SJames Wright   const bool implicit     = context->implicit;
180bb8a0c61SJames Wright   const CeedScalar mu     = context->newtonian_ctx.mu;
181bb8a0c61SJames Wright   const CeedScalar cv     = context->newtonian_ctx.cv;
182bb8a0c61SJames Wright   const CeedScalar cp     = context->newtonian_ctx.cp;
183bb8a0c61SJames Wright   const CeedScalar Rd     = cp - cv;
1842acc7cbcSKenneth E. Jansen   const CeedScalar gamma  = cp/cv;
185bb8a0c61SJames Wright 
186bb8a0c61SJames Wright   const CeedScalar theta0 = context->theta0;
187bb8a0c61SJames Wright   const CeedScalar P0     = context->P0;
188bb8a0c61SJames Wright   const CeedScalar delta0 = context->delta0;
189bb8a0c61SJames Wright   const CeedScalar Uinf   = context->Uinf;
1902acc7cbcSKenneth E. Jansen   const bool weakT        = context->weakT;
191bb8a0c61SJames Wright   const CeedScalar rho_0  = P0 / (Rd * theta0);
192bb8a0c61SJames Wright   const CeedScalar x0     = Uinf*rho_0 / (mu*25/ (delta0*delta0) );
193bb8a0c61SJames Wright 
194bb8a0c61SJames Wright   CeedPragmaSIMD
195bb8a0c61SJames Wright   // Quadrature Point Loop
196bb8a0c61SJames Wright   for (CeedInt i=0; i<Q; i++) {
197bb8a0c61SJames Wright     // Setup
198bb8a0c61SJames Wright     // -- Interp-to-Interp q_data
199bb8a0c61SJames Wright     // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q).
200bb8a0c61SJames Wright     // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q).
201bb8a0c61SJames Wright     // We can effect this by swapping the sign on this weight
202bb8a0c61SJames Wright     const CeedScalar wdetJb  = (implicit ? -1. : 1.) * q_data_sur[0][i];
203bb8a0c61SJames Wright 
2042acc7cbcSKenneth E. Jansen     // Calculate inflow values
205bb8a0c61SJames Wright     const CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]};
206bb8a0c61SJames Wright     CeedScalar velocity[3] = {0.};
207bb8a0c61SJames Wright     CeedScalar t12;
208bb8a0c61SJames Wright     BlasiusSolution(x[1], Uinf, x0, x[0], rho_0, &velocity[0], &velocity[1],
209bb8a0c61SJames Wright                     &t12, &context->newtonian_ctx);
210bb8a0c61SJames Wright 
2112acc7cbcSKenneth E. Jansen     // enabling user to choose between weak T and weak rho inflow
2122acc7cbcSKenneth E. Jansen     CeedScalar rho,E_internal, P, E_kinetic;
2132acc7cbcSKenneth E. Jansen     if (weakT) {
2142acc7cbcSKenneth E. Jansen       // rho should be from the current solution
2152acc7cbcSKenneth E. Jansen       rho = q[0][i];
2162acc7cbcSKenneth E. Jansen       // Temperature is being set weakly (theta0) and for constant cv this sets E_internal
2172acc7cbcSKenneth E. Jansen       E_internal = rho * cv * theta0;
2182acc7cbcSKenneth E. Jansen       // Find pressure using
2192acc7cbcSKenneth E. Jansen       P = rho*Rd*theta0; // interior rho with exterior T
220f0b65372SJed Brown       E_kinetic = .5 * rho * Dot3(velocity, velocity);
2212acc7cbcSKenneth E. Jansen     } else {
2222acc7cbcSKenneth E. Jansen       //  Fixing rho weakly on the inflow to a value  consistent with theta0 and P0
2232acc7cbcSKenneth E. Jansen       rho =  rho_0;
224f0b65372SJed Brown       E_kinetic = .5 * rho * Dot3(velocity, velocity);
2252acc7cbcSKenneth E. Jansen       E_internal = q[4][i] - E_kinetic; // uses set rho and u but E from solution
2262acc7cbcSKenneth E. Jansen       P = E_internal * (gamma - 1.);
2272acc7cbcSKenneth E. Jansen     }
2282acc7cbcSKenneth E. Jansen     const CeedScalar E = E_internal + E_kinetic;
229bb8a0c61SJames Wright     // ---- Normal vect
230bb8a0c61SJames Wright     const CeedScalar norm[3] = {q_data_sur[1][i],
231bb8a0c61SJames Wright                                 q_data_sur[2][i],
232bb8a0c61SJames Wright                                 q_data_sur[3][i]
233bb8a0c61SJames Wright                                };
234bb8a0c61SJames Wright 
235bb8a0c61SJames Wright     // The Physics
236bb8a0c61SJames Wright     // Zero v so all future terms can safely sum into it
237bb8a0c61SJames Wright     for (int j=0; j<5; j++) v[j][i] = 0.;
238bb8a0c61SJames Wright 
239f0b65372SJed Brown     const CeedScalar u_normal = Dot3(norm, velocity);
240*9abe94a0SJed Brown     const CeedScalar viscous_flux[3] = {-t12 *norm[1], -t12 *norm[0], 0};
241bb8a0c61SJames Wright 
242bb8a0c61SJames Wright     // The Physics
243bb8a0c61SJames Wright     // -- Density
244bb8a0c61SJames Wright     v[0][i] -= wdetJb * rho * u_normal; // interior rho
245bb8a0c61SJames Wright 
246bb8a0c61SJames Wright     // -- Momentum
247bb8a0c61SJames Wright     for (int j=0; j<3; j++)
248*9abe94a0SJed Brown       v[j+1][i] -= wdetJb * (rho * u_normal * velocity[j] // interior rho
249*9abe94a0SJed Brown                              + norm[j] * P // mixed P
250*9abe94a0SJed Brown                              + viscous_flux[j]);
251bb8a0c61SJames Wright 
252bb8a0c61SJames Wright     // -- Total Energy Density
253*9abe94a0SJed Brown     v[4][i] -= wdetJb * (u_normal * (E + P) + Dot3(viscous_flux, velocity));
254bb8a0c61SJames Wright 
255bb8a0c61SJames Wright   } // End Quadrature Point Loop
256bb8a0c61SJames Wright   return 0;
257bb8a0c61SJames Wright }
258bb8a0c61SJames Wright 
259f0b65372SJed Brown CEED_QFUNCTION(Blasius_Inflow_Jacobian)(void *ctx, CeedInt Q,
260f0b65372SJed Brown                                         const CeedScalar *const *in,
261f0b65372SJed Brown                                         CeedScalar *const *out) {
262f0b65372SJed Brown   // *INDENT-OFF*
263f0b65372SJed Brown   // Inputs
264f0b65372SJed Brown   const CeedScalar (*dq)[CEED_Q_VLA]         = (const CeedScalar(*)[CEED_Q_VLA])in[0],
265f0b65372SJed Brown                    (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[1],
266f0b65372SJed Brown                    (*X)[CEED_Q_VLA]          = (const CeedScalar(*)[CEED_Q_VLA])in[2];
267f0b65372SJed Brown 
268f0b65372SJed Brown   // Outputs
269f0b65372SJed Brown   CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
270f0b65372SJed Brown   // *INDENT-ON*
271f0b65372SJed Brown   const BlasiusContext context = (BlasiusContext)ctx;
272f0b65372SJed Brown   const bool implicit     = context->implicit;
273f0b65372SJed Brown   const CeedScalar mu     = context->newtonian_ctx.mu;
274f0b65372SJed Brown   const CeedScalar cv     = context->newtonian_ctx.cv;
275f0b65372SJed Brown   const CeedScalar cp     = context->newtonian_ctx.cp;
276f0b65372SJed Brown   const CeedScalar Rd     = cp - cv;
277f0b65372SJed Brown   const CeedScalar gamma  = cp/cv;
278f0b65372SJed Brown 
279f0b65372SJed Brown   const CeedScalar theta0 = context->theta0;
280f0b65372SJed Brown   const CeedScalar P0     = context->P0;
281f0b65372SJed Brown   const CeedScalar delta0 = context->delta0;
282f0b65372SJed Brown   const CeedScalar Uinf   = context->Uinf;
283f0b65372SJed Brown   const bool weakT        = context->weakT;
284f0b65372SJed Brown   const CeedScalar rho_0  = P0 / (Rd * theta0);
285f0b65372SJed Brown   const CeedScalar x0     = Uinf*rho_0 / (mu*25/ (delta0*delta0) );
286f0b65372SJed Brown 
287f0b65372SJed Brown   CeedPragmaSIMD
288f0b65372SJed Brown   // Quadrature Point Loop
289f0b65372SJed Brown   for (CeedInt i=0; i<Q; i++) {
290f0b65372SJed Brown     // Setup
291f0b65372SJed Brown     // -- Interp-to-Interp q_data
292f0b65372SJed Brown     // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q).
293f0b65372SJed Brown     // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q).
294f0b65372SJed Brown     // We can effect this by swapping the sign on this weight
295f0b65372SJed Brown     const CeedScalar wdetJb  = (implicit ? -1. : 1.) * q_data_sur[0][i];
296f0b65372SJed Brown 
297f0b65372SJed Brown     // Calculate inflow values
298f0b65372SJed Brown     const CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]};
299f0b65372SJed Brown     CeedScalar velocity[3] = {0};
300f0b65372SJed Brown     CeedScalar t12;
301f0b65372SJed Brown     BlasiusSolution(x[1], Uinf, x0, x[0], rho_0, &velocity[0], &velocity[1],
302f0b65372SJed Brown                     &t12, &context->newtonian_ctx);
303f0b65372SJed Brown 
304f0b65372SJed Brown     // enabling user to choose between weak T and weak rho inflow
305f0b65372SJed Brown     CeedScalar drho, dE, dP;
306f0b65372SJed Brown     if (weakT) {
307f0b65372SJed Brown       // rho should be from the current solution
308f0b65372SJed Brown       drho = dq[0][i];
309f0b65372SJed Brown       CeedScalar dE_internal = drho * cv * theta0;
310f0b65372SJed Brown       CeedScalar dE_kinetic = .5 * drho * Dot3(velocity, velocity);
311f0b65372SJed Brown       dE = dE_internal + dE_kinetic;
312f0b65372SJed Brown       dP = drho * Rd * theta0; // interior rho with exterior T
313f0b65372SJed Brown     } else { // rho specified, E_internal from solution
314f0b65372SJed Brown       drho = 0;
315f0b65372SJed Brown       dE = dq[4][i];
316f0b65372SJed Brown       dP = dE * (gamma - 1.);
317f0b65372SJed Brown     }
318f0b65372SJed Brown     const CeedScalar norm[3] = {q_data_sur[1][i],
319f0b65372SJed Brown                                 q_data_sur[2][i],
320f0b65372SJed Brown                                 q_data_sur[3][i]
321f0b65372SJed Brown                                };
322f0b65372SJed Brown 
323f0b65372SJed Brown     const CeedScalar u_normal = Dot3(norm, velocity);
324f0b65372SJed Brown 
325f0b65372SJed Brown     v[0][i] = - wdetJb * drho * u_normal;
326f0b65372SJed Brown     for (int j=0; j<3; j++)
327f0b65372SJed Brown       v[j+1][i] = -wdetJb * (drho * u_normal * velocity[j] + norm[j] * dP);
328f0b65372SJed Brown     v[4][i] = - wdetJb * u_normal * (dE + dP);
329f0b65372SJed Brown   } // End Quadrature Point Loop
330f0b65372SJed Brown   return 0;
331f0b65372SJed Brown }
332f0b65372SJed Brown 
333bb8a0c61SJames Wright // *****************************************************************************
334bb8a0c61SJames Wright CEED_QFUNCTION(Blasius_Outflow)(void *ctx, CeedInt Q,
335bb8a0c61SJames Wright                                 const CeedScalar *const *in,
336bb8a0c61SJames Wright                                 CeedScalar *const *out) {
337bb8a0c61SJames Wright   // *INDENT-OFF*
338bb8a0c61SJames Wright   // Inputs
339bb8a0c61SJames Wright   const CeedScalar (*q)[CEED_Q_VLA]          = (const CeedScalar(*)[CEED_Q_VLA])in[0],
340bb8a0c61SJames Wright                    (*q_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[1],
341bb8a0c61SJames Wright                    (*X)[CEED_Q_VLA]          = (const CeedScalar(*)[CEED_Q_VLA])in[2];
342bb8a0c61SJames Wright   // Outputs
343f0b65372SJed Brown   CeedScalar (*v)[CEED_Q_VLA]            = (CeedScalar(*)[CEED_Q_VLA])out[0],
344f0b65372SJed Brown              (*jac_data_sur)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[1];
345bb8a0c61SJames Wright   // *INDENT-ON*
346bb8a0c61SJames Wright 
347bb8a0c61SJames Wright   const BlasiusContext context = (BlasiusContext)ctx;
348bb8a0c61SJames Wright   const bool implicit     = context->implicit;
349bb8a0c61SJames Wright   const CeedScalar mu     = context->newtonian_ctx.mu;
350bb8a0c61SJames Wright   const CeedScalar cv     = context->newtonian_ctx.cv;
351bb8a0c61SJames Wright   const CeedScalar cp     = context->newtonian_ctx.cp;
352bb8a0c61SJames Wright   const CeedScalar Rd     = cp - cv;
353bb8a0c61SJames Wright 
354bb8a0c61SJames Wright   const CeedScalar theta0 = context->theta0;
355bb8a0c61SJames Wright   const CeedScalar P0     = context->P0;
356bb8a0c61SJames Wright   const CeedScalar rho_0  = P0 / (Rd*theta0);
357bb8a0c61SJames Wright   const CeedScalar delta0 = context->delta0;
358bb8a0c61SJames Wright   const CeedScalar Uinf   = context->Uinf;
359bb8a0c61SJames Wright   const CeedScalar x0     = Uinf*rho_0 / (mu*25/ (delta0*delta0) );
360bb8a0c61SJames Wright 
361bb8a0c61SJames Wright   CeedPragmaSIMD
362bb8a0c61SJames Wright   // Quadrature Point Loop
363bb8a0c61SJames Wright   for (CeedInt i=0; i<Q; i++) {
364bb8a0c61SJames Wright     // Setup
365bb8a0c61SJames Wright     // -- Interp in
366bb8a0c61SJames Wright     const CeedScalar rho      =  q[0][i];
367bb8a0c61SJames Wright     const CeedScalar u[3]     = {q[1][i] / rho,
368bb8a0c61SJames Wright                                  q[2][i] / rho,
369bb8a0c61SJames Wright                                  q[3][i] / rho
370bb8a0c61SJames Wright                                 };
371bb8a0c61SJames Wright     const CeedScalar E        =  q[4][i];
372bb8a0c61SJames Wright 
373bb8a0c61SJames Wright     // -- Interp-to-Interp q_data
374bb8a0c61SJames Wright     // For explicit mode, the surface integral is on the RHS of ODE q_dot = f(q).
375bb8a0c61SJames Wright     // For implicit mode, it gets pulled to the LHS of implicit ODE/DAE g(q_dot, q).
376bb8a0c61SJames Wright     // We can effect this by swapping the sign on this weight
377bb8a0c61SJames Wright     const CeedScalar wdetJb  = (implicit ? -1. : 1.) * q_data_sur[0][i];
378bb8a0c61SJames Wright 
379bb8a0c61SJames Wright     // ---- Normal vect
380bb8a0c61SJames Wright     const CeedScalar norm[3] = {q_data_sur[1][i],
381bb8a0c61SJames Wright                                 q_data_sur[2][i],
382bb8a0c61SJames Wright                                 q_data_sur[3][i]
383bb8a0c61SJames Wright                                };
384bb8a0c61SJames Wright 
385bb8a0c61SJames Wright     // Implementing outflow condition
386bb8a0c61SJames Wright     const CeedScalar P         = P0; // pressure
387f0b65372SJed Brown     const CeedScalar u_normal  = Dot3(norm, u); // Normal velocity
388bb8a0c61SJames Wright 
389bb8a0c61SJames Wright     // Calculate prescribed outflow traction values
390bb8a0c61SJames Wright     const CeedScalar x[3] = {X[0][i], X[1][i], X[2][i]};
391bb8a0c61SJames Wright     CeedScalar velocity[3] = {0.};
392bb8a0c61SJames Wright     CeedScalar t12;
393bb8a0c61SJames Wright     BlasiusSolution(x[1], Uinf, x0, x[0], rho_0, &velocity[0], &velocity[1],
394bb8a0c61SJames Wright                     &t12, &context->newtonian_ctx);
395*9abe94a0SJed Brown     const CeedScalar viscous_flux[3] = {-t12 *norm[1], -t12 *norm[0], 0};
396*9abe94a0SJed Brown 
397bb8a0c61SJames Wright     // -- Density
398*9abe94a0SJed Brown     v[0][i] = -wdetJb * rho * u_normal;
399bb8a0c61SJames Wright 
400bb8a0c61SJames Wright     // -- Momentum
401bb8a0c61SJames Wright     for (int j=0; j<3; j++)
402*9abe94a0SJed Brown       v[j+1][i] = -wdetJb * (rho * u_normal * u[j]
403*9abe94a0SJed Brown                              + norm[j] * P + viscous_flux[j]);
404bb8a0c61SJames Wright 
405bb8a0c61SJames Wright     // -- Total Energy Density
406*9abe94a0SJed Brown     v[4][i] = -wdetJb * (u_normal * (E + P)
407*9abe94a0SJed Brown                          + Dot3(viscous_flux, velocity));
408bb8a0c61SJames Wright 
409f0b65372SJed Brown     // Save values for Jacobian
410f0b65372SJed Brown     jac_data_sur[0][i] = rho;
411f0b65372SJed Brown     jac_data_sur[1][i] = u[0];
412f0b65372SJed Brown     jac_data_sur[2][i] = u[1];
413f0b65372SJed Brown     jac_data_sur[3][i] = u[2];
414f0b65372SJed Brown     jac_data_sur[4][i] = E;
415bb8a0c61SJames Wright   } // End Quadrature Point Loop
416bb8a0c61SJames Wright   return 0;
417bb8a0c61SJames Wright }
418f0b65372SJed Brown 
419f0b65372SJed Brown CEED_QFUNCTION(Blasius_Outflow_Jacobian)(void *ctx, CeedInt Q,
420f0b65372SJed Brown     const CeedScalar *const *in,
421f0b65372SJed Brown     CeedScalar *const *out) {
422f0b65372SJed Brown   // *INDENT-OFF*
423f0b65372SJed Brown   // Inputs
424f0b65372SJed Brown   const CeedScalar (*dq)[CEED_Q_VLA]           = (const CeedScalar(*)[CEED_Q_VLA])in[0],
425f0b65372SJed Brown                    (*q_data_sur)[CEED_Q_VLA]   = (const CeedScalar(*)[CEED_Q_VLA])in[1],
426f0b65372SJed Brown                    (*jac_data_sur)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2];
427f0b65372SJed Brown   // Outputs
428f0b65372SJed Brown   CeedScalar (*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
429f0b65372SJed Brown   // *INDENT-ON*
430f0b65372SJed Brown 
431f0b65372SJed Brown   const BlasiusContext context = (BlasiusContext)ctx;
432f0b65372SJed Brown   const bool implicit     = context->implicit;
433f0b65372SJed Brown 
434f0b65372SJed Brown   CeedPragmaSIMD
435f0b65372SJed Brown   // Quadrature Point Loop
436f0b65372SJed Brown   for (CeedInt i=0; i<Q; i++) {
437f0b65372SJed Brown     const CeedScalar rho = jac_data_sur[0][i];
438f0b65372SJed Brown     const CeedScalar u[3] = {jac_data_sur[1][i], jac_data_sur[2][i], jac_data_sur[3][i]};
439f0b65372SJed Brown     const CeedScalar E = jac_data_sur[4][i];
440f0b65372SJed Brown 
441f0b65372SJed Brown     const CeedScalar drho      =  dq[0][i];
442f0b65372SJed Brown     const CeedScalar dmomentum[3] = {dq[1][i], dq[2][i], dq[3][i]};
443f0b65372SJed Brown     const CeedScalar dE        =  dq[4][i];
444f0b65372SJed Brown 
445f0b65372SJed Brown     const CeedScalar wdetJb  = (implicit ? -1. : 1.) * q_data_sur[0][i];
446f0b65372SJed Brown     const CeedScalar norm[3] = {q_data_sur[1][i],
447f0b65372SJed Brown                                 q_data_sur[2][i],
448f0b65372SJed Brown                                 q_data_sur[3][i]
449f0b65372SJed Brown                                };
450f0b65372SJed Brown 
451f0b65372SJed Brown     CeedScalar du[3];
452f0b65372SJed Brown     for (int j=0; j<3; j++) du[j] = (dmomentum[j] - u[j] * drho) / rho;
453f0b65372SJed Brown     const CeedScalar u_normal  = Dot3(norm, u);
454f0b65372SJed Brown     const CeedScalar du_normal = Dot3(norm, du);
455f0b65372SJed Brown     const CeedScalar dmomentum_normal = drho * u_normal + rho * du_normal;
456f0b65372SJed Brown     const CeedScalar P = context->P0;
457f0b65372SJed Brown     const CeedScalar dP = 0;
458f0b65372SJed Brown 
459f0b65372SJed Brown     v[0][i] = -wdetJb * dmomentum_normal;
460f0b65372SJed Brown     for (int j=0; j<3; j++)
461f0b65372SJed Brown       v[j+1][i] = -wdetJb * (dmomentum_normal * u[j] + rho * u_normal * du[j]);
462f0b65372SJed Brown     v[4][i] = -wdetJb * (du_normal * (E + P) + u_normal * (dE + dP));
463f0b65372SJed Brown   } // End Quadrature Point Loop
464f0b65372SJed Brown   return 0;
465f0b65372SJed Brown }
466f0b65372SJed Brown 
467bb8a0c61SJames Wright #endif // blasius_h
468