1ae2b091fSJames Wright // SPDX-FileCopyrightText: Copyright (c) 2017-2024, HONEE contributors.
2ae2b091fSJames Wright // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause
3bb8a0c61SJames Wright
4bb8a0c61SJames Wright /// @file
5ea615d4cSJames Wright /// Operator for HONEE
63e17a7a1SJames Wright #include <ceed/types.h>
72b916ea7SJeremy L Thompson
8cbe60e31SLeila Ghaffari #include "newtonian_state.h"
9d0cce58aSJeremy L Thompson #include "newtonian_types.h"
10704b8bbeSJames Wright #include "utils.h"
11bb8a0c61SJames Wright
12bb8a0c61SJames Wright typedef struct ChannelContext_ *ChannelContext;
13bb8a0c61SJames Wright struct ChannelContext_ {
14bb8a0c61SJames Wright bool implicit; // !< Using implicit timesteping or not
15bb8a0c61SJames Wright CeedScalar theta0; // !< Reference temperature
16bb8a0c61SJames Wright CeedScalar P0; // !< Reference Pressure
17bb8a0c61SJames Wright CeedScalar umax; // !< Centerline velocity
18bb8a0c61SJames Wright CeedScalar center; // !< Y Coordinate for center of channel
19bb8a0c61SJames Wright CeedScalar H; // !< Channel half-height
20bb8a0c61SJames Wright CeedScalar B; // !< Body-force driving the flow
21*cde3d787SJames Wright struct NewtonianIdealGasContext_ newt_ctx;
22bb8a0c61SJames Wright };
23bb8a0c61SJames Wright
Exact_Channel(CeedInt dim,CeedScalar time,const CeedScalar X[],CeedInt Nf,void * ctx)242b916ea7SJeremy L Thompson CEED_QFUNCTION_HELPER State Exact_Channel(CeedInt dim, CeedScalar time, const CeedScalar X[], CeedInt Nf, void *ctx) {
25bb8a0c61SJames Wright const ChannelContext context = (ChannelContext)ctx;
26bb8a0c61SJames Wright const CeedScalar theta0 = context->theta0;
27bb8a0c61SJames Wright const CeedScalar P0 = context->P0;
28bb8a0c61SJames Wright const CeedScalar umax = context->umax;
29bb8a0c61SJames Wright const CeedScalar center = context->center;
30bb8a0c61SJames Wright const CeedScalar H = context->H;
31*cde3d787SJames Wright NewtonianIGProperties gas = context->newt_ctx.gas;
32*cde3d787SJames Wright const CeedScalar cp = gas.cp;
33*cde3d787SJames Wright const CeedScalar mu = gas.mu;
34*cde3d787SJames Wright const CeedScalar k = gas.k;
35cbe60e31SLeila Ghaffari // There is a gravity body force but it is excluded from
36cbe60e31SLeila Ghaffari // the potential energy due to periodicity.
37d1b9ef12SLeila Ghaffari // g = (g, 0, 0)
38d1b9ef12SLeila Ghaffari // x = (0, x_2, x_3)
39d1b9ef12SLeila Ghaffari // e_potential = dot(g, x) = 0
40d1b9ef12SLeila Ghaffari const CeedScalar x[3] = {0, X[1], X[2]};
41bb8a0c61SJames Wright
42bb8a0c61SJames Wright const CeedScalar Pr = mu / (cp * k);
43bb8a0c61SJames Wright const CeedScalar Ec = (umax * umax) / (cp * theta0);
442b916ea7SJeremy L Thompson const CeedScalar theta = theta0 * (1 + (Pr * Ec / 3) * (1 - Square(Square((x[1] - center) / H))));
45cbe60e31SLeila Ghaffari CeedScalar Y[5] = {0.};
46cbe60e31SLeila Ghaffari Y[0] = P0;
47d1b9ef12SLeila Ghaffari Y[1] = umax * (1 - Square((x[1] - center) / H));
48cbe60e31SLeila Ghaffari Y[2] = 0.;
49cbe60e31SLeila Ghaffari Y[3] = 0.;
50cbe60e31SLeila Ghaffari Y[4] = theta;
51bb8a0c61SJames Wright
52edcfef1bSKenneth E. Jansen return StateFromY(gas, Y);
53bb8a0c61SJames Wright }
54bb8a0c61SJames Wright
55bb8a0c61SJames Wright // *****************************************************************************
56cbe60e31SLeila Ghaffari // This QFunction set the initial condition
57bb8a0c61SJames Wright // *****************************************************************************
ICsChannel(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)582b916ea7SJeremy L Thompson CEED_QFUNCTION(ICsChannel)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
59bb8a0c61SJames Wright const CeedScalar(*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
60bb8a0c61SJames Wright CeedScalar(*q0)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
61bb8a0c61SJames Wright
62cbe60e31SLeila Ghaffari const ChannelContext context = (ChannelContext)ctx;
63*cde3d787SJames Wright NewtonianIGProperties gas = context->newt_ctx.gas;
64cbe60e31SLeila Ghaffari
652b916ea7SJeremy L Thompson CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
66bb8a0c61SJames Wright const CeedScalar x[] = {X[0][i], X[1][i], X[2][i]};
67cbe60e31SLeila Ghaffari State s = Exact_Channel(3, 0., x, 5, ctx);
68a541e550SJames Wright CeedScalar q[5];
69*cde3d787SJames Wright StateToQ(gas, s, q, context->newt_ctx.state_var);
702b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q0[j][i] = q[j];
71b193fadcSJames Wright }
72bb8a0c61SJames Wright return 0;
73bb8a0c61SJames Wright }
74bb8a0c61SJames Wright
75bb8a0c61SJames Wright // *****************************************************************************
76d1b9ef12SLeila Ghaffari // This QFunction set the inflow boundary condition for conservative variables
77d1b9ef12SLeila Ghaffari // *****************************************************************************
Channel_Inflow(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)782b916ea7SJeremy L Thompson CEED_QFUNCTION(Channel_Inflow)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
793d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
80ade49511SJames Wright const CeedScalar(*q_data_sur) = in[2];
813d65b166SJames Wright const CeedScalar(*X)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[3];
82bb8a0c61SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
833d65b166SJames Wright
84bb8a0c61SJames Wright const ChannelContext context = (ChannelContext)ctx;
85ade49511SJames Wright const bool is_implicit = context->implicit;
86*cde3d787SJames Wright NewtonianIGProperties gas = context->newt_ctx.gas;
87*cde3d787SJames Wright const CeedScalar gamma = HeatCapacityRatio(gas);
88bb8a0c61SJames Wright
893d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
90ade49511SJames Wright CeedScalar wdetJb, norm[3];
91ade49511SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, NULL, norm);
92ade49511SJames Wright wdetJb *= is_implicit ? -1. : 1.;
93bb8a0c61SJames Wright
94d1b9ef12SLeila Ghaffari // There is a gravity body force but it is excluded from
95d1b9ef12SLeila Ghaffari // the potential energy due to periodicity.
96d1b9ef12SLeila Ghaffari // g = (g, 0, 0)
97d1b9ef12SLeila Ghaffari // x = (0, x_2, x_3)
98d1b9ef12SLeila Ghaffari // e_potential = dot(g, x) = 0
99d1b9ef12SLeila Ghaffari const CeedScalar x[3] = {0, X[1][i], X[2][i]};
100d1b9ef12SLeila Ghaffari
1014b96a86bSJames Wright // Calculate prescribed inflow values
102d1b9ef12SLeila Ghaffari State s_exact = Exact_Channel(3, 0., x, 5, ctx);
103bb8a0c61SJames Wright CeedScalar q_exact[5] = {0.};
104d1b9ef12SLeila Ghaffari UnpackState_U(s_exact.U, q_exact);
105bb8a0c61SJames Wright
106bb8a0c61SJames Wright // Find pressure using state inside the domain
107d1b9ef12SLeila Ghaffari CeedScalar q_inside[5] = {0};
1082b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 5; j++) q_inside[j] = q[j][i];
109edcfef1bSKenneth E. Jansen State s_inside = StateFromU(gas, q_inside);
110d1b9ef12SLeila Ghaffari const CeedScalar P = s_inside.Y.pressure;
111bb8a0c61SJames Wright
112bb8a0c61SJames Wright // Find inflow state using calculated P and prescribed velocity, theta0
113*cde3d787SJames Wright const CeedScalar e_internal = gas.cv * s_exact.Y.temperature;
114bb8a0c61SJames Wright const CeedScalar rho_in = P / ((gamma - 1) * e_internal);
1152b916ea7SJeremy L Thompson const CeedScalar E_kinetic = .5 * rho_in * Dot3(s_exact.Y.velocity, s_exact.Y.velocity);
116bb8a0c61SJames Wright const CeedScalar E = rho_in * e_internal + E_kinetic;
117d1b9ef12SLeila Ghaffari
118bb8a0c61SJames Wright // The Physics
119bb8a0c61SJames Wright // Zero v so all future terms can safely sum into it
120493642f1SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = 0.;
121bb8a0c61SJames Wright
122d1b9ef12SLeila Ghaffari const CeedScalar u_normal = Dot3(norm, s_exact.Y.velocity);
123bb8a0c61SJames Wright
124bb8a0c61SJames Wright // The Physics
125bb8a0c61SJames Wright // -- Density
126bb8a0c61SJames Wright v[0][i] -= wdetJb * rho_in * u_normal;
127bb8a0c61SJames Wright
128bb8a0c61SJames Wright // -- Momentum
1292b916ea7SJeremy 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);
130bb8a0c61SJames Wright
131bb8a0c61SJames Wright // -- Total Energy Density
132bb8a0c61SJames Wright v[4][i] -= wdetJb * u_normal * (E + P);
133512c8ec7SJames Wright }
134bb8a0c61SJames Wright return 0;
135bb8a0c61SJames Wright }
136bb8a0c61SJames Wright
137bb8a0c61SJames Wright // *****************************************************************************
138d1b9ef12SLeila Ghaffari // This QFunction set the outflow boundary condition for conservative variables
139d1b9ef12SLeila Ghaffari // *****************************************************************************
Channel_Outflow(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)1402b916ea7SJeremy L Thompson CEED_QFUNCTION(Channel_Outflow)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
1413d65b166SJames Wright const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
142ade49511SJames Wright const CeedScalar(*q_data_sur) = in[2];
143bb8a0c61SJames Wright CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
144bb8a0c61SJames Wright
145bb8a0c61SJames Wright const ChannelContext context = (ChannelContext)ctx;
146ade49511SJames Wright const bool is_implicit = context->implicit;
147bb8a0c61SJames Wright
1483d65b166SJames Wright CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
149ade49511SJames Wright CeedScalar wdetJb, norm[3];
150ade49511SJames Wright QdataBoundaryUnpack_3D(Q, i, q_data_sur, &wdetJb, NULL, norm);
151ade49511SJames Wright wdetJb *= is_implicit ? -1. : 1.;
152ade49511SJames Wright
153bb8a0c61SJames Wright const CeedScalar rho = q[0][i];
1542b916ea7SJeremy L Thompson const CeedScalar u[3] = {q[1][i] / rho, q[2][i] / rho, q[3][i] / rho};
155bb8a0c61SJames Wright const CeedScalar E = q[4][i];
156bb8a0c61SJames Wright
157bb8a0c61SJames Wright // The Physics
158bb8a0c61SJames Wright // Zero v so all future terms can safely sum into it
159493642f1SJames Wright for (CeedInt j = 0; j < 5; j++) v[j][i] = 0.;
160bb8a0c61SJames Wright
161bb8a0c61SJames Wright // Implementing outflow condition
162512c8ec7SJames Wright const CeedScalar P = context->P0; // pressure
163704b8bbeSJames Wright const CeedScalar u_normal = Dot3(norm, u); // Normal velocity
164bb8a0c61SJames Wright // The Physics
165bb8a0c61SJames Wright // -- Density
166bb8a0c61SJames Wright v[0][i] -= wdetJb * rho * u_normal;
167bb8a0c61SJames Wright
168bb8a0c61SJames Wright // -- Momentum
1692b916ea7SJeremy L Thompson for (CeedInt j = 0; j < 3; j++) v[j + 1][i] -= wdetJb * (rho * u_normal * u[j] + norm[j] * P);
170bb8a0c61SJames Wright
171bb8a0c61SJames Wright // -- Total Energy Density
172bb8a0c61SJames Wright v[4][i] -= wdetJb * u_normal * (E + P);
173512c8ec7SJames Wright }
174bb8a0c61SJames Wright return 0;
175bb8a0c61SJames Wright }
176