xref: /libCEED/examples/fluids/qfunctions/newtonian_state.h (revision 5bce47c78373471bb00dacdcfd196665461caef2)
1 // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2 // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3 //
4 // SPDX-License-Identifier: BSD-2-Clause
5 //
6 // This file is part of CEED:  http://github.com/ceed
7 
8 /// @file
9 /// Structs and helper functions regarding the state of a newtonian simulation
10 
11 
12 #ifndef newtonian_state_h
13 #define newtonian_state_h
14 
15 #include <ceed.h>
16 #include <math.h>
17 #include "newtonian_types.h"
18 #include "utils.h"
19 
20 typedef struct {
21   CeedScalar pressure;
22   CeedScalar velocity[3];
23   CeedScalar temperature;
24 } StatePrimitive;
25 
26 typedef struct {
27   CeedScalar density;
28   CeedScalar momentum[3];
29   CeedScalar E_total;
30 } StateConservative;
31 
32 typedef struct {
33   StateConservative U;
34   StatePrimitive Y;
35 } State;
36 
37 CEED_QFUNCTION_HELPER void UnpackState_U(StateConservative s, CeedScalar U[5]) {
38   U[0] = s.density;
39   for (int i=0; i<3; i++) U[i+1] = s.momentum[i];
40   U[4] = s.E_total;
41 }
42 
43 CEED_QFUNCTION_HELPER void UnpackState_Y(StatePrimitive s, CeedScalar Y[5]) {
44   Y[0] = s.pressure;
45   for (int i=0; i<3; i++) Y[i+1] = s.velocity[i];
46   Y[4] = s.temperature;
47 }
48 
49 CEED_QFUNCTION_HELPER StatePrimitive StatePrimitiveFromConservative(
50   NewtonianIdealGasContext gas, StateConservative U, const CeedScalar x[3]) {
51   StatePrimitive Y;
52   for (CeedInt i=0; i<3; i++) Y.velocity[i] = U.momentum[i] / U.density;
53   CeedScalar e_kinetic = .5 * Dot3(Y.velocity, Y.velocity);
54   CeedScalar e_potential = -Dot3(gas->g, x);
55   CeedScalar e_total = U.E_total / U.density;
56   CeedScalar e_internal = e_total - e_kinetic - e_potential;
57   Y.temperature = e_internal / gas->cv;
58   Y.pressure = (gas->cp / gas->cv - 1) * U.density * e_internal;
59   return Y;
60 }
61 
62 CEED_QFUNCTION_HELPER StatePrimitive StatePrimitiveFromConservative_fwd(
63   NewtonianIdealGasContext gas, State s, StateConservative dU,
64   const CeedScalar x[3], const CeedScalar dx[3]) {
65   StatePrimitive dY;
66   for (CeedInt i=0; i<3; i++) {
67     dY.velocity[i] = (dU.momentum[i] - s.Y.velocity[i] * dU.density) / s.U.density;
68   }
69   CeedScalar e_kinetic = .5 * Dot3(s.Y.velocity, s.Y.velocity);
70   CeedScalar de_kinetic = Dot3(dY.velocity, s.Y.velocity);
71   CeedScalar e_potential = -Dot3(gas->g, x);
72   CeedScalar de_potential = -Dot3(gas->g, dx);
73   CeedScalar e_total = s.U.E_total / s.U.density;
74   CeedScalar de_total = (dU.E_total - e_total * dU.density) / s.U.density;
75   CeedScalar e_internal = e_total - e_kinetic - e_potential;
76   CeedScalar de_internal = de_total - de_kinetic - de_potential;
77   dY.temperature = de_internal / gas->cv;
78   dY.pressure = (gas->cp / gas->cv - 1)
79                 * (dU.density * e_internal + s.U.density * de_internal);
80   return dY;
81 }
82 
83 CEED_QFUNCTION_HELPER StateConservative StateConservativeFromPrimitive(
84   NewtonianIdealGasContext gas, StatePrimitive Y, const CeedScalar x[3]) {
85   StateConservative U;
86   CeedScalar R = gas->cp - gas->cv;
87   U.density = Y.pressure / (R * Y.temperature);
88   for (int i=0; i<3; i++) U.momentum[i] = U.density*Y.velocity[i];
89   CeedScalar e_internal = gas->cv * Y.temperature;
90   CeedScalar e_kinetic = .5 * Dot3(Y.velocity, Y.velocity);
91   CeedScalar e_potential = -Dot3(gas->g, x);
92   CeedScalar e_total = e_internal + e_kinetic + e_potential;
93   U.E_total = U.density*e_total;
94   return U;
95 }
96 
97 CEED_QFUNCTION_HELPER StateConservative StateConservativeFromPrimitive_fwd(
98   NewtonianIdealGasContext gas, State s, StatePrimitive dY,
99   const CeedScalar x[3], const CeedScalar dx[3]) {
100   StateConservative dU;
101   CeedScalar R = gas->cp - gas->cv;
102   dU.density = (dY.pressure * s.Y.temperature - s.Y.pressure * dY.temperature) /
103                (R * s.Y.temperature * s.Y.temperature);
104   for (int i=0; i<3; i++) {
105     dU.momentum[i] = dU.density * s.Y.velocity[i] + s.U.density * dY.velocity[i];
106   }
107   CeedScalar e_kinetic = .5 * Dot3(s.Y.velocity, s.Y.velocity);
108   CeedScalar de_kinetic = Dot3(dY.velocity, s.Y.velocity);
109   CeedScalar e_potential = -Dot3(gas->g, x);
110   CeedScalar de_potential = -Dot3(gas->g, dx);
111   CeedScalar e_internal = gas->cv * s.Y.temperature;
112   CeedScalar de_internal = gas->cv * dY.temperature;
113   CeedScalar e_total = e_internal + e_kinetic + e_potential;
114   CeedScalar de_total = de_internal + de_kinetic + de_potential;
115   dU.E_total = dU.density*e_total + s.U.density*de_total;
116   return dU;
117 }
118 
119 CEED_QFUNCTION_HELPER State StateFromU(NewtonianIdealGasContext gas,
120                                        const CeedScalar U[5], const CeedScalar x[3]) {
121   State s;
122   s.U.density = U[0];
123   s.U.momentum[0] = U[1];
124   s.U.momentum[1] = U[2];
125   s.U.momentum[2] = U[3];
126   s.U.E_total = U[4];
127   s.Y = StatePrimitiveFromConservative(gas, s.U, x);
128   return s;
129 }
130 
131 CEED_QFUNCTION_HELPER State StateFromU_fwd(NewtonianIdealGasContext gas,
132     State s, const CeedScalar dU[5],
133     const CeedScalar x[3], const CeedScalar dx[3]) {
134   State ds;
135   ds.U.density = dU[0];
136   ds.U.momentum[0] = dU[1];
137   ds.U.momentum[1] = dU[2];
138   ds.U.momentum[2] = dU[3];
139   ds.U.E_total = dU[4];
140   ds.Y = StatePrimitiveFromConservative_fwd(gas, s, ds.U, x, dx);
141   return ds;
142 }
143 
144 CEED_QFUNCTION_HELPER State StateFromY(NewtonianIdealGasContext gas,
145                                        const CeedScalar Y[5], const CeedScalar x[3]) {
146   State s;
147   s.Y.pressure    = Y[0];
148   s.Y.velocity[0] = Y[1];
149   s.Y.velocity[1] = Y[2];
150   s.Y.velocity[2] = Y[3];
151   s.Y.temperature = Y[4];
152   s.U = StateConservativeFromPrimitive(gas, s.Y, x);
153   return s;
154 }
155 
156 CEED_QFUNCTION_HELPER State StateFromY_fwd(NewtonianIdealGasContext gas,
157     State s, const CeedScalar dY[5],
158     const CeedScalar x[3], const CeedScalar dx[3]) {
159   State ds;
160   ds.Y.pressure    = dY[0];
161   ds.Y.velocity[0] = dY[1];
162   ds.Y.velocity[1] = dY[2];
163   ds.Y.velocity[2] = dY[3];
164   ds.Y.temperature = dY[4];
165   ds.U = StateConservativeFromPrimitive_fwd(gas, s, ds.Y, x, dx);
166   return ds;
167 }
168 
169 CEED_QFUNCTION_HELPER void FluxInviscid(NewtonianIdealGasContext gas, State s,
170                                         StateConservative Flux[3]) {
171   for (CeedInt i=0; i<3; i++) {
172     Flux[i].density = s.U.momentum[i];
173     for (CeedInt j=0; j<3; j++)
174       Flux[i].momentum[j] = s.U.momentum[i] * s.Y.velocity[j]
175                             + s.Y.pressure * (i == j);
176     Flux[i].E_total = (s.U.E_total + s.Y.pressure) * s.Y.velocity[i];
177   }
178 }
179 
180 CEED_QFUNCTION_HELPER void FluxInviscid_fwd(NewtonianIdealGasContext gas,
181     State s, State ds, StateConservative dFlux[3]) {
182   for (CeedInt i=0; i<3; i++) {
183     dFlux[i].density = ds.U.momentum[i];
184     for (CeedInt j=0; j<3; j++)
185       dFlux[i].momentum[j] = ds.U.momentum[i] * s.Y.velocity[j] +
186                              s.U.momentum[i] * ds.Y.velocity[j] + ds.Y.pressure * (i == j);
187     dFlux[i].E_total = (ds.U.E_total + ds.Y.pressure) * s.Y.velocity[i] +
188                        (s.U.E_total + s.Y.pressure) * ds.Y.velocity[i];
189   }
190 }
191 
192 CEED_QFUNCTION_HELPER void FluxInviscidStrong(NewtonianIdealGasContext gas,
193     State s, State ds[3], CeedScalar strong_conv[5]) {
194   for (CeedInt i=0; i<5; i++) strong_conv[i] = 0;
195   for (CeedInt i=0; i<3; i++) {
196     StateConservative dF[3];
197     FluxInviscid_fwd(gas, s, ds[i], dF);
198     CeedScalar dF_i[5];
199     UnpackState_U(dF[i], dF_i);
200     for (CeedInt j=0; j<5; j++)
201       strong_conv[j] += dF_i[j];
202   }
203 }
204 
205 CEED_QFUNCTION_HELPER void FluxTotal(StateConservative F_inviscid[3],
206                                      CeedScalar stress[3][3], CeedScalar Fe[3], CeedScalar Flux[5][3]) {
207   for (CeedInt j=0; j<3; j++) {
208     Flux[0][j] = F_inviscid[j].density;
209     for (CeedInt k=0; k<3; k++)
210       Flux[k+1][j] = F_inviscid[j].momentum[k] - stress[k][j];
211     Flux[4][j] = F_inviscid[j].E_total + Fe[j];
212   }
213 }
214 
215 CEED_QFUNCTION_HELPER void FluxTotal_Boundary(
216   const StateConservative F_inviscid[3], const CeedScalar stress[3][3],
217   const CeedScalar Fe[3], const CeedScalar normal[3], CeedScalar Flux[5]) {
218 
219   for(CeedInt j=0; j<5; j++) Flux[j] = 0.;
220   for (CeedInt j=0; j<3; j++) {
221     Flux[0] += F_inviscid[j].density * normal[j];
222     for (CeedInt k=0; k<3; k++) {
223       Flux[k+1] += (F_inviscid[j].momentum[k] - stress[k][j]) * normal[j];
224     }
225     Flux[4] += (F_inviscid[j].E_total + Fe[j]) * normal[j];
226   }
227 }
228 
229 // Kelvin-Mandel notation
230 CEED_QFUNCTION_HELPER void KMStrainRate(const State grad_s[3],
231                                         CeedScalar strain_rate[6]) {
232   const CeedScalar weight = 1 / sqrt(2.);
233   strain_rate[0] = grad_s[0].Y.velocity[0];
234   strain_rate[1] = grad_s[1].Y.velocity[1];
235   strain_rate[2] = grad_s[2].Y.velocity[2];
236   strain_rate[3] = weight * (grad_s[2].Y.velocity[1] + grad_s[1].Y.velocity[2]);
237   strain_rate[4] = weight * (grad_s[2].Y.velocity[0] + grad_s[0].Y.velocity[2]);
238   strain_rate[5] = weight * (grad_s[1].Y.velocity[0] + grad_s[0].Y.velocity[1]);
239 }
240 
241 CEED_QFUNCTION_HELPER void NewtonianStress(NewtonianIdealGasContext gas,
242     const CeedScalar strain_rate[6], CeedScalar stress[6]) {
243   CeedScalar div_u = strain_rate[0] + strain_rate[1] + strain_rate[2];
244   for (CeedInt i=0; i<6; i++) {
245     stress[i] = gas->mu * (2 * strain_rate[i] + gas->lambda * div_u * (i < 3));
246   }
247 }
248 
249 CEED_QFUNCTION_HELPER void ViscousEnergyFlux(NewtonianIdealGasContext gas,
250     StatePrimitive Y, const State grad_s[3], const CeedScalar stress[3][3],
251     CeedScalar Fe[3]) {
252   for (CeedInt i=0; i<3; i++) {
253     Fe[i] = - Y.velocity[0] * stress[0][i]
254             - Y.velocity[1] * stress[1][i]
255             - Y.velocity[2] * stress[2][i]
256             - gas->k * grad_s[i].Y.temperature;
257   }
258 }
259 
260 CEED_QFUNCTION_HELPER void ViscousEnergyFlux_fwd(NewtonianIdealGasContext gas,
261     StatePrimitive Y, StatePrimitive dY, const State grad_ds[3],
262     const CeedScalar stress[3][3],
263     const CeedScalar dstress[3][3],
264     CeedScalar dFe[3]) {
265   for (CeedInt i=0; i<3; i++) {
266     dFe[i] = - Y.velocity[0] * dstress[0][i] - dY.velocity[0] * stress[0][i]
267              - Y.velocity[1] * dstress[1][i] - dY.velocity[1] * stress[1][i]
268              - Y.velocity[2] * dstress[2][i] - dY.velocity[2] * stress[2][i]
269              - gas->k * grad_ds[i].Y.temperature;
270   }
271 }
272 
273 #endif // newtonian_state_h
274