xref: /honee/qfunctions/channel.h (revision 4b96a86bba11b72cac7c28056075834ab8e47fc9)
1dc936754SJeremy L Thompson // Copyright (c) 2017-2024, 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
10d0cce58aSJeremy L Thompson #include <ceed.h>
11bb8a0c61SJames Wright #include <math.h>
122b916ea7SJeremy L Thompson 
13cbe60e31SLeila Ghaffari #include "newtonian_state.h"
14d0cce58aSJeremy L Thompson #include "newtonian_types.h"
15704b8bbeSJames Wright #include "utils.h"
16bb8a0c61SJames Wright 
17bb8a0c61SJames Wright typedef struct ChannelContext_ *ChannelContext;
18bb8a0c61SJames Wright struct ChannelContext_ {
19bb8a0c61SJames Wright   bool                             implicit;  // !< Using implicit timesteping or not
20bb8a0c61SJames Wright   CeedScalar                       theta0;    // !< Reference temperature
21bb8a0c61SJames Wright   CeedScalar                       P0;        // !< Reference Pressure
22bb8a0c61SJames Wright   CeedScalar                       umax;      // !< Centerline velocity
23bb8a0c61SJames Wright   CeedScalar                       center;    // !< Y Coordinate for center of channel
24bb8a0c61SJames Wright   CeedScalar                       H;         // !< Channel half-height
25bb8a0c61SJames Wright   CeedScalar                       B;         // !< Body-force driving the flow
26bb8a0c61SJames Wright   struct NewtonianIdealGasContext_ newtonian_ctx;
27bb8a0c61SJames Wright };
28bb8a0c61SJames Wright 
292b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER State Exact_Channel(CeedInt dim, CeedScalar time, const CeedScalar X[], CeedInt Nf, void *ctx) {
30bb8a0c61SJames Wright   const ChannelContext     context = (ChannelContext)ctx;
31bb8a0c61SJames Wright   const CeedScalar         theta0  = context->theta0;
32bb8a0c61SJames Wright   const CeedScalar         P0      = context->P0;
33bb8a0c61SJames Wright   const CeedScalar         umax    = context->umax;
34bb8a0c61SJames Wright   const CeedScalar         center  = context->center;
35bb8a0c61SJames Wright   const CeedScalar         H       = context->H;
36cbe60e31SLeila Ghaffari   NewtonianIdealGasContext gas     = &context->newtonian_ctx;
37cbe60e31SLeila Ghaffari   const CeedScalar         cp      = gas->cp;
38cbe60e31SLeila Ghaffari   const CeedScalar         mu      = gas->mu;
39cbe60e31SLeila Ghaffari   const CeedScalar         k       = gas->k;
40cbe60e31SLeila Ghaffari   // There is a gravity body force but it is excluded from
41cbe60e31SLeila Ghaffari   //   the potential energy due to periodicity.
42d1b9ef12SLeila Ghaffari   //     g = (g, 0, 0)
43d1b9ef12SLeila Ghaffari   //     x = (0, x_2, x_3)
44d1b9ef12SLeila Ghaffari   //     e_potential = dot(g, x) = 0
45d1b9ef12SLeila Ghaffari   const CeedScalar x[3] = {0, X[1], X[2]};
46bb8a0c61SJames Wright 
47bb8a0c61SJames Wright   const CeedScalar Pr    = mu / (cp * k);
48bb8a0c61SJames Wright   const CeedScalar Ec    = (umax * umax) / (cp * theta0);
492b916ea7SJeremy L Thompson   const CeedScalar theta = theta0 * (1 + (Pr * Ec / 3) * (1 - Square(Square((x[1] - center) / H))));
50cbe60e31SLeila Ghaffari   CeedScalar       Y[5]  = {0.};
51cbe60e31SLeila Ghaffari   Y[0]                   = P0;
52d1b9ef12SLeila Ghaffari   Y[1]                   = umax * (1 - Square((x[1] - center) / H));
53cbe60e31SLeila Ghaffari   Y[2]                   = 0.;
54cbe60e31SLeila Ghaffari   Y[3]                   = 0.;
55cbe60e31SLeila Ghaffari   Y[4]                   = theta;
56bb8a0c61SJames Wright 
57edcfef1bSKenneth E. Jansen   return StateFromY(gas, Y);
58bb8a0c61SJames Wright }
59bb8a0c61SJames Wright 
60bb8a0c61SJames Wright // *****************************************************************************
61cbe60e31SLeila Ghaffari // This QFunction set the initial condition
62bb8a0c61SJames Wright // *****************************************************************************
632b916ea7SJeremy L Thompson CEED_QFUNCTION(ICsChannel)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
64bb8a0c61SJames Wright   // Inputs
65bb8a0c61SJames Wright   const CeedScalar(*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
66bb8a0c61SJames Wright 
67bb8a0c61SJames Wright   // Outputs
68bb8a0c61SJames Wright   CeedScalar(*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
69bb8a0c61SJames Wright 
70cbe60e31SLeila Ghaffari   // Context
71cbe60e31SLeila Ghaffari   const ChannelContext context = (ChannelContext)ctx;
72cbe60e31SLeila Ghaffari 
73bb8a0c61SJames Wright   // Quadrature Point Loop
742b916ea7SJeremy L Thompson   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
75bb8a0c61SJames Wright     const CeedScalar x[]  = {X[0][i], X[1][i], X[2][i]};
76cbe60e31SLeila Ghaffari     State            s    = Exact_Channel(3, 0., x, 5, ctx);
77d1b9ef12SLeila Ghaffari     CeedScalar       q[5] = {0};
783636f6a4SJames Wright     switch (context->newtonian_ctx.state_var) {
793636f6a4SJames Wright       case STATEVAR_CONSERVATIVE:
80d1b9ef12SLeila Ghaffari         UnpackState_U(s.U, q);
813636f6a4SJames Wright         break;
823636f6a4SJames Wright       case STATEVAR_PRIMITIVE:
833636f6a4SJames Wright         UnpackState_Y(s.Y, q);
843636f6a4SJames Wright         break;
853636f6a4SJames Wright     }
86d1b9ef12SLeila Ghaffari 
872b916ea7SJeremy L Thompson     for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j];
88bb8a0c61SJames Wright 
89bb8a0c61SJames Wright   }  // End of Quadrature Point Loop
90bb8a0c61SJames Wright   return 0;
91bb8a0c61SJames Wright }
92bb8a0c61SJames Wright 
93bb8a0c61SJames Wright // *****************************************************************************
94d1b9ef12SLeila Ghaffari // This QFunction set the inflow boundary condition for conservative variables
95d1b9ef12SLeila Ghaffari // *****************************************************************************
962b916ea7SJeremy L Thompson CEED_QFUNCTION(Channel_Inflow)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
97bb8a0c61SJames Wright   // Inputs
983d65b166SJames Wright   const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
99ade49511SJames Wright   const CeedScalar(*q_data_sur)    = in[2];
1003d65b166SJames Wright   const CeedScalar(*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3];
101bb8a0c61SJames Wright 
102bb8a0c61SJames Wright   // Outputs
103bb8a0c61SJames Wright   CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
1043d65b166SJames Wright 
105bb8a0c61SJames Wright   const ChannelContext     context     = (ChannelContext)ctx;
106ade49511SJames Wright   const bool               is_implicit = context->implicit;
107d1b9ef12SLeila Ghaffari   NewtonianIdealGasContext gas         = &context->newtonian_ctx;
108d1b9ef12SLeila Ghaffari   const CeedScalar         cv          = gas->cv;
1093d65b166SJames Wright   const CeedScalar         gamma       = HeatCapacityRatio(&context->newtonian_ctx);
110bb8a0c61SJames Wright 
111bb8a0c61SJames Wright   // Quadrature Point Loop
1123d65b166SJames Wright   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
113ade49511SJames Wright     CeedScalar wdetJb, norm[3];
114ade49511SJames Wright     QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, NULL, norm);
115ade49511SJames Wright     wdetJb *= is_implicit ? -1. : 1.;
116bb8a0c61SJames Wright 
117d1b9ef12SLeila Ghaffari     // There is a gravity body force but it is excluded from
118d1b9ef12SLeila Ghaffari     //   the potential energy due to periodicity.
119d1b9ef12SLeila Ghaffari     //     g = (g, 0, 0)
120d1b9ef12SLeila Ghaffari     //     x = (0, x_2, x_3)
121d1b9ef12SLeila Ghaffari     //     e_potential = dot(g, x) = 0
122d1b9ef12SLeila Ghaffari     const CeedScalar x[3] = {0, X[1][i], X[2][i]};
123d1b9ef12SLeila Ghaffari 
124*4b96a86bSJames Wright     // Calculate prescribed inflow values
125d1b9ef12SLeila Ghaffari     State      s_exact    = Exact_Channel(3, 0., x, 5, ctx);
126bb8a0c61SJames Wright     CeedScalar q_exact[5] = {0.};
127d1b9ef12SLeila Ghaffari     UnpackState_U(s_exact.U, q_exact);
128bb8a0c61SJames Wright 
129bb8a0c61SJames Wright     // Find pressure using state inside the domain
130d1b9ef12SLeila Ghaffari     CeedScalar q_inside[5] = {0};
1312b916ea7SJeremy L Thompson     for (CeedInt j = 0; j < 5; j++) q_inside[j] = q[j][i];
132edcfef1bSKenneth E. Jansen     State            s_inside = StateFromU(gas, q_inside);
133d1b9ef12SLeila Ghaffari     const CeedScalar P        = s_inside.Y.pressure;
134bb8a0c61SJames Wright 
135bb8a0c61SJames Wright     // Find inflow state using calculated P and prescribed velocity, theta0
136d1b9ef12SLeila Ghaffari     const CeedScalar e_internal = cv * s_exact.Y.temperature;
137bb8a0c61SJames Wright     const CeedScalar rho_in     = P / ((gamma - 1) * e_internal);
1382b916ea7SJeremy L Thompson     const CeedScalar E_kinetic  = .5 * rho_in * Dot3(s_exact.Y.velocity, s_exact.Y.velocity);
139bb8a0c61SJames Wright     const CeedScalar E          = rho_in * e_internal + E_kinetic;
140d1b9ef12SLeila Ghaffari 
141bb8a0c61SJames Wright     // The Physics
142bb8a0c61SJames Wright     // Zero v so all future terms can safely sum into it
143493642f1SJames Wright     for (CeedInt j = 0; j < 5; j++) v[j][i] = 0.;
144bb8a0c61SJames Wright 
145d1b9ef12SLeila Ghaffari     const CeedScalar u_normal = Dot3(norm, s_exact.Y.velocity);
146bb8a0c61SJames Wright 
147bb8a0c61SJames Wright     // The Physics
148bb8a0c61SJames Wright     // -- Density
149bb8a0c61SJames Wright     v[0][i] -= wdetJb * rho_in * u_normal;
150bb8a0c61SJames Wright 
151bb8a0c61SJames Wright     // -- Momentum
1522b916ea7SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) v[j + 1][i] -= wdetJb * (rho_in * u_normal * s_exact.Y.velocity[j] + norm[j] * P);
153bb8a0c61SJames Wright 
154bb8a0c61SJames Wright     // -- Total Energy Density
155bb8a0c61SJames Wright     v[4][i] -= wdetJb * u_normal * (E + P);
156bb8a0c61SJames Wright 
157bb8a0c61SJames Wright   }  // End Quadrature Point Loop
158bb8a0c61SJames Wright   return 0;
159bb8a0c61SJames Wright }
160bb8a0c61SJames Wright 
161bb8a0c61SJames Wright // *****************************************************************************
162d1b9ef12SLeila Ghaffari // This QFunction set the outflow boundary condition for conservative variables
163d1b9ef12SLeila Ghaffari // *****************************************************************************
1642b916ea7SJeremy L Thompson CEED_QFUNCTION(Channel_Outflow)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
165bb8a0c61SJames Wright   // Inputs
1663d65b166SJames Wright   const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
167ade49511SJames Wright   const CeedScalar(*q_data_sur)    = in[2];
168dd64951cSJames Wright 
169bb8a0c61SJames Wright   // Outputs
170bb8a0c61SJames Wright   CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
171bb8a0c61SJames Wright 
172bb8a0c61SJames Wright   const ChannelContext context     = (ChannelContext)ctx;
173ade49511SJames Wright   const bool           is_implicit = context->implicit;
174bb8a0c61SJames Wright   const CeedScalar     P0          = context->P0;
175bb8a0c61SJames Wright 
176bb8a0c61SJames Wright   // Quadrature Point Loop
1773d65b166SJames Wright   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
178ade49511SJames Wright     CeedScalar wdetJb, norm[3];
179ade49511SJames Wright     QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, NULL, norm);
180ade49511SJames Wright     wdetJb *= is_implicit ? -1. : 1.;
181ade49511SJames Wright 
182bb8a0c61SJames Wright     const CeedScalar rho  = q[0][i];
1832b916ea7SJeremy L Thompson     const CeedScalar u[3] = {q[1][i] / rho, q[2][i] / rho, q[3][i] / rho};
184bb8a0c61SJames Wright     const CeedScalar E    = q[4][i];
185bb8a0c61SJames Wright 
186bb8a0c61SJames Wright     // The Physics
187bb8a0c61SJames Wright     // Zero v so all future terms can safely sum into it
188493642f1SJames Wright     for (CeedInt j = 0; j < 5; j++) v[j][i] = 0.;
189bb8a0c61SJames Wright 
190bb8a0c61SJames Wright     // Implementing outflow condition
191bb8a0c61SJames Wright     const CeedScalar P        = P0;             // pressure
192704b8bbeSJames Wright     const CeedScalar u_normal = Dot3(norm, u);  // Normal velocity
193bb8a0c61SJames Wright     // The Physics
194bb8a0c61SJames Wright     // -- Density
195bb8a0c61SJames Wright     v[0][i] -= wdetJb * rho * u_normal;
196bb8a0c61SJames Wright 
197bb8a0c61SJames Wright     // -- Momentum
1982b916ea7SJeremy L Thompson     for (CeedInt j = 0; j < 3; j++) v[j + 1][i] -= wdetJb * (rho * u_normal * u[j] + norm[j] * P);
199bb8a0c61SJames Wright 
200bb8a0c61SJames Wright     // -- Total Energy Density
201bb8a0c61SJames Wright     v[4][i] -= wdetJb * u_normal * (E + P);
202bb8a0c61SJames Wright 
203bb8a0c61SJames Wright   }  // End Quadrature Point Loop
204bb8a0c61SJames Wright   return 0;
205bb8a0c61SJames Wright }
206