xref: /honee/qfunctions/diff_flux_projection.h (revision 8c85b83518484fc9eaa5bccfe38a7cce91b34691)
1*8c85b835SJames Wright // SPDX-FileCopyrightText: Copyright (c) 2017-2024, HONEE contributors.
2*8c85b835SJames Wright // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause
3*8c85b835SJames Wright 
4*8c85b835SJames Wright #include <ceed.h>
5*8c85b835SJames Wright 
6*8c85b835SJames Wright #include "newtonian_state.h"
7*8c85b835SJames Wright #include "utils.h"
8*8c85b835SJames Wright 
9*8c85b835SJames Wright // @brief Volume integral for RHS of divergence of diffusive flux projection
10*8c85b835SJames Wright CEED_QFUNCTION_HELPER int DivDiffusiveFluxVolumeRHS(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out,
11*8c85b835SJames Wright                                                     StateVariable state_var) {
12*8c85b835SJames Wright   const CeedScalar(*q)[CEED_Q_VLA]   = (const CeedScalar(*)[CEED_Q_VLA])in[0];
13*8c85b835SJames Wright   const CeedScalar(*Grad_q)          = in[1];
14*8c85b835SJames Wright   const CeedScalar(*q_data)          = in[2];
15*8c85b835SJames Wright   CeedScalar(*Grad_v)[4][CEED_Q_VLA] = (CeedScalar(*)[4][CEED_Q_VLA])out[0];
16*8c85b835SJames Wright 
17*8c85b835SJames Wright   const NewtonianIdealGasContext context               = (NewtonianIdealGasContext)ctx;
18*8c85b835SJames Wright   const StateConservative        ZeroInviscidFluxes[3] = {{0}};
19*8c85b835SJames Wright 
20*8c85b835SJames Wright   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
21*8c85b835SJames Wright     const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]};
22*8c85b835SJames Wright     const State      s     = StateFromQ(context, qi, state_var);
23*8c85b835SJames Wright     CeedScalar       wdetJ, dXdx[3][3];
24*8c85b835SJames Wright     CeedScalar       stress[3][3], Fe[3], Fdiff[5][3];
25*8c85b835SJames Wright 
26*8c85b835SJames Wright     QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx);
27*8c85b835SJames Wright     {  // Get stress and Fe
28*8c85b835SJames Wright       State      grad_s[3];
29*8c85b835SJames Wright       CeedScalar strain_rate[6], kmstress[6];
30*8c85b835SJames Wright 
31*8c85b835SJames Wright       StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_q, dXdx, grad_s);
32*8c85b835SJames Wright       KMStrainRate_State(grad_s, strain_rate);
33*8c85b835SJames Wright       NewtonianStress(context, strain_rate, kmstress);
34*8c85b835SJames Wright       KMUnpack(kmstress, stress);
35*8c85b835SJames Wright       ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe);
36*8c85b835SJames Wright     }
37*8c85b835SJames Wright 
38*8c85b835SJames Wright     FluxTotal(ZeroInviscidFluxes, stress, Fe, Fdiff);
39*8c85b835SJames Wright 
40*8c85b835SJames Wright     for (CeedInt j = 1; j < 5; j++) {  // Continuity has no diffusive flux, therefore skip
41*8c85b835SJames Wright       for (CeedInt k = 0; k < 3; k++) {
42*8c85b835SJames Wright         Grad_v[k][j - 1][i] = -wdetJ * Dot3(dXdx[k], Fdiff[j]);
43*8c85b835SJames Wright       }
44*8c85b835SJames Wright     }
45*8c85b835SJames Wright   }
46*8c85b835SJames Wright   return 0;
47*8c85b835SJames Wright }
48*8c85b835SJames Wright 
49*8c85b835SJames Wright CEED_QFUNCTION(DivDiffusiveFluxVolumeRHS_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
50*8c85b835SJames Wright   return DivDiffusiveFluxVolumeRHS(ctx, Q, in, out, STATEVAR_CONSERVATIVE);
51*8c85b835SJames Wright }
52*8c85b835SJames Wright 
53*8c85b835SJames Wright CEED_QFUNCTION(DivDiffusiveFluxVolumeRHS_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
54*8c85b835SJames Wright   return DivDiffusiveFluxVolumeRHS(ctx, Q, in, out, STATEVAR_PRIMITIVE);
55*8c85b835SJames Wright }
56*8c85b835SJames Wright 
57*8c85b835SJames Wright CEED_QFUNCTION(DivDiffusiveFluxVolumeRHS_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
58*8c85b835SJames Wright   return DivDiffusiveFluxVolumeRHS(ctx, Q, in, out, STATEVAR_ENTROPY);
59*8c85b835SJames Wright }
60*8c85b835SJames Wright 
61*8c85b835SJames Wright // @brief Boundary integral for RHS of divergence of diffusive flux projection
62*8c85b835SJames Wright CEED_QFUNCTION_HELPER int DivDiffusiveFluxBoundaryRHS(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out,
63*8c85b835SJames Wright                                                       StateVariable state_var) {
64*8c85b835SJames Wright   const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
65*8c85b835SJames Wright   const CeedScalar(*Grad_q)        = in[1];
66*8c85b835SJames Wright   const CeedScalar(*q_data)        = in[2];
67*8c85b835SJames Wright   CeedScalar(*v)[CEED_Q_VLA]       = (CeedScalar(*)[CEED_Q_VLA])out[0];
68*8c85b835SJames Wright 
69*8c85b835SJames Wright   const NewtonianIdealGasContext context               = (NewtonianIdealGasContext)ctx;
70*8c85b835SJames Wright   const StateConservative        ZeroInviscidFluxes[3] = {{0}};
71*8c85b835SJames Wright 
72*8c85b835SJames Wright   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
73*8c85b835SJames Wright     const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]};
74*8c85b835SJames Wright     const State      s     = StateFromQ(context, qi, state_var);
75*8c85b835SJames Wright     CeedScalar       wdetJ, dXdx[3][3], normal[3];
76*8c85b835SJames Wright     CeedScalar       stress[3][3], Fe[3], Fdiff[5];
77*8c85b835SJames Wright 
78*8c85b835SJames Wright     QdataBoundaryGradientUnpack_3D(Q, i, q_data, &wdetJ, dXdx, normal);
79*8c85b835SJames Wright     {  // Get stress and Fe
80*8c85b835SJames Wright       State      grad_s[3];
81*8c85b835SJames Wright       CeedScalar strain_rate[6], kmstress[6];
82*8c85b835SJames Wright 
83*8c85b835SJames Wright       StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_q, dXdx, grad_s);
84*8c85b835SJames Wright       KMStrainRate_State(grad_s, strain_rate);
85*8c85b835SJames Wright       NewtonianStress(context, strain_rate, kmstress);
86*8c85b835SJames Wright       KMUnpack(kmstress, stress);
87*8c85b835SJames Wright       ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe);
88*8c85b835SJames Wright     }
89*8c85b835SJames Wright 
90*8c85b835SJames Wright     FluxTotal_Boundary(ZeroInviscidFluxes, stress, Fe, normal, Fdiff);
91*8c85b835SJames Wright 
92*8c85b835SJames Wright     // Continuity has no diffusive flux, therefore skip
93*8c85b835SJames Wright     for (CeedInt j = 1; j < 5; j++) v[j - 1][i] = wdetJ * Fdiff[j];
94*8c85b835SJames Wright   }
95*8c85b835SJames Wright   return 0;
96*8c85b835SJames Wright }
97*8c85b835SJames Wright 
98*8c85b835SJames Wright CEED_QFUNCTION(DivDiffusiveFluxBoundaryRHS_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
99*8c85b835SJames Wright   return DivDiffusiveFluxBoundaryRHS(ctx, Q, in, out, STATEVAR_CONSERVATIVE);
100*8c85b835SJames Wright }
101*8c85b835SJames Wright 
102*8c85b835SJames Wright CEED_QFUNCTION(DivDiffusiveFluxBoundaryRHS_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
103*8c85b835SJames Wright   return DivDiffusiveFluxBoundaryRHS(ctx, Q, in, out, STATEVAR_PRIMITIVE);
104*8c85b835SJames Wright }
105*8c85b835SJames Wright 
106*8c85b835SJames Wright CEED_QFUNCTION(DivDiffusiveFluxBoundaryRHS_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
107*8c85b835SJames Wright   return DivDiffusiveFluxBoundaryRHS(ctx, Q, in, out, STATEVAR_ENTROPY);
108*8c85b835SJames Wright }
109*8c85b835SJames Wright 
110*8c85b835SJames Wright // @brief Integral for RHS of diffusive flux projection
111*8c85b835SJames Wright CEED_QFUNCTION_HELPER int DiffusiveFluxRHS(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) {
112*8c85b835SJames Wright   const CeedScalar(*q)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
113*8c85b835SJames Wright   const CeedScalar(*Grad_q)        = in[1];
114*8c85b835SJames Wright   const CeedScalar(*q_data)        = in[2];
115*8c85b835SJames Wright   CeedScalar(*v)[CEED_Q_VLA]       = (CeedScalar(*)[CEED_Q_VLA])out[0];
116*8c85b835SJames Wright 
117*8c85b835SJames Wright   const NewtonianIdealGasContext context               = (NewtonianIdealGasContext)ctx;
118*8c85b835SJames Wright   const StateConservative        ZeroInviscidFluxes[3] = {{0}};
119*8c85b835SJames Wright 
120*8c85b835SJames Wright   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
121*8c85b835SJames Wright     const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]};
122*8c85b835SJames Wright     const State      s     = StateFromQ(context, qi, state_var);
123*8c85b835SJames Wright     CeedScalar       wdetJ, dXdx[3][3];
124*8c85b835SJames Wright     CeedScalar       stress[3][3], Fe[3], Fdiff[5][3];
125*8c85b835SJames Wright 
126*8c85b835SJames Wright     QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx);
127*8c85b835SJames Wright     {  // Get stress and Fe
128*8c85b835SJames Wright       State      grad_s[3];
129*8c85b835SJames Wright       CeedScalar strain_rate[6], kmstress[6];
130*8c85b835SJames Wright 
131*8c85b835SJames Wright       StatePhysicalGradientFromReference(Q, i, context, s, state_var, Grad_q, dXdx, grad_s);
132*8c85b835SJames Wright       KMStrainRate_State(grad_s, strain_rate);
133*8c85b835SJames Wright       NewtonianStress(context, strain_rate, kmstress);
134*8c85b835SJames Wright       KMUnpack(kmstress, stress);
135*8c85b835SJames Wright       ViscousEnergyFlux(context, s.Y, grad_s, stress, Fe);
136*8c85b835SJames Wright     }
137*8c85b835SJames Wright 
138*8c85b835SJames Wright     FluxTotal(ZeroInviscidFluxes, stress, Fe, Fdiff);
139*8c85b835SJames Wright 
140*8c85b835SJames Wright     for (CeedInt j = 1; j < 5; j++) {  // Continuity has no diffusive flux, therefore skip
141*8c85b835SJames Wright       for (CeedInt k = 0; k < 3; k++) {
142*8c85b835SJames Wright         v[(j - 1) * 3 + k][i] = wdetJ * Fdiff[j][k];
143*8c85b835SJames Wright       }
144*8c85b835SJames Wright     }
145*8c85b835SJames Wright   }
146*8c85b835SJames Wright   return 0;
147*8c85b835SJames Wright }
148*8c85b835SJames Wright 
149*8c85b835SJames Wright CEED_QFUNCTION(DiffusiveFluxRHS_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
150*8c85b835SJames Wright   return DiffusiveFluxRHS(ctx, Q, in, out, STATEVAR_CONSERVATIVE);
151*8c85b835SJames Wright }
152*8c85b835SJames Wright 
153*8c85b835SJames Wright CEED_QFUNCTION(DiffusiveFluxRHS_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
154*8c85b835SJames Wright   return DiffusiveFluxRHS(ctx, Q, in, out, STATEVAR_PRIMITIVE);
155*8c85b835SJames Wright }
156*8c85b835SJames Wright 
157*8c85b835SJames Wright CEED_QFUNCTION(DiffusiveFluxRHS_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
158*8c85b835SJames Wright   return DiffusiveFluxRHS(ctx, Q, in, out, STATEVAR_ENTROPY);
159*8c85b835SJames Wright }
160*8c85b835SJames Wright 
161*8c85b835SJames Wright // @brief QFunction to calculate the divergence of the diffusive flux
162*8c85b835SJames Wright CEED_QFUNCTION_HELPER int ComputeDivDiffusiveFluxGeneric(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, const CeedInt dim,
163*8c85b835SJames Wright                                                          const CeedInt num_comps) {
164*8c85b835SJames Wright   const CeedScalar *grad_q   = in[0];
165*8c85b835SJames Wright   const CeedScalar(*q_data)  = in[1];
166*8c85b835SJames Wright   CeedScalar(*v)[CEED_Q_VLA] = (CeedScalar(*)[CEED_Q_VLA])out[0];
167*8c85b835SJames Wright 
168*8c85b835SJames Wright   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
169*8c85b835SJames Wright     CeedScalar dXdx[9];
170*8c85b835SJames Wright 
171*8c85b835SJames Wright     QdataUnpack_ND(dim, Q, i, q_data, NULL, dXdx);
172*8c85b835SJames Wright     CeedPragmaSIMD for (CeedInt n = 0; n < num_comps; n++) {
173*8c85b835SJames Wright       CeedScalar grad_qn[9];
174*8c85b835SJames Wright 
175*8c85b835SJames Wright       // Get gradient into dim x dim matrix form, with orientation [flux_direction][gradient_direction]
176*8c85b835SJames Wright       // Equivalent of GradUnpackN
177*8c85b835SJames Wright       const CeedInt offset = Q * n * dim;  // offset to reach nth component flux gradients
178*8c85b835SJames Wright       for (CeedInt g = 0; g < dim; g++) {
179*8c85b835SJames Wright         for (CeedInt f = 0; f < dim; f++) {
180*8c85b835SJames Wright           grad_qn[f * dim + g] = grad_q[offset + (Q * num_comps * dim) * g + Q * f + i];
181*8c85b835SJames Wright         }
182*8c85b835SJames Wright       }
183*8c85b835SJames Wright       v[n][i] = 0;
184*8c85b835SJames Wright       DivergenceND(grad_qn, dXdx, dim, &v[n][i]);
185*8c85b835SJames Wright     }
186*8c85b835SJames Wright   }
187*8c85b835SJames Wright   return 0;
188*8c85b835SJames Wright }
189*8c85b835SJames Wright 
190*8c85b835SJames Wright CEED_QFUNCTION(ComputeDivDiffusiveFlux3D_4)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
191*8c85b835SJames Wright   return ComputeDivDiffusiveFluxGeneric(ctx, Q, in, out, 3, 4);
192*8c85b835SJames Wright }
193