xref: /honee/qfunctions/differential_filter.h (revision 475f0cac5d40259768f4556cf888e8f2448554cb)
1 // SPDX-FileCopyrightText: Copyright (c) 2017-2024, HONEE contributors.
2 // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause
3 //
4 /// @file
5 /// Implementation of differential filtering
6 #include <ceed/types.h>
7 
8 #include "differential_filter_enums.h"
9 #include "newtonian_state.h"
10 #include "newtonian_types.h"
11 #include "utils.h"
12 
13 enum DifferentialFilterDampingFunction { DIFF_FILTER_DAMP_NONE, DIFF_FILTER_DAMP_VAN_DRIEST, DIFF_FILTER_DAMP_MMS };
14 #ifndef CEED_RUNNING_JIT_PASS
15 extern const char *const DifferentialFilterDampingFunctions[];
16 #endif
17 
18 typedef struct DifferentialFilterContext_ *DifferentialFilterContext;
19 struct DifferentialFilterContext_ {
20   bool                                   grid_based_width;
21   CeedScalar                             width_scaling[3];
22   CeedScalar                             kernel_scaling;
23   CeedScalar                             friction_length;
24   enum DifferentialFilterDampingFunction damping_function;
25   CeedScalar                             damping_constant;
26   struct NewtonianIdealGasContext_       newt_ctx;
27 };
28 
DifferentialFilter_RHS(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out,StateVariable state_var)29 CEED_QFUNCTION_HELPER int DifferentialFilter_RHS(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, StateVariable state_var) {
30   const CeedScalar(*q)[CEED_Q_VLA]      = (const CeedScalar(*)[CEED_Q_VLA])in[0];
31   const CeedScalar(*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[1];
32   CeedScalar(*v0)[CEED_Q_VLA]           = (CeedScalar(*)[CEED_Q_VLA])out[0];
33   CeedScalar(*v1)[CEED_Q_VLA]           = (CeedScalar(*)[CEED_Q_VLA])out[1];
34 
35   DifferentialFilterContext context = (DifferentialFilterContext)ctx;
36   NewtonianIGProperties     gas     = context->newt_ctx.gas;
37 
38   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
39     const CeedScalar qi[5] = {q[0][i], q[1][i], q[2][i], q[3][i], q[4][i]};
40     const CeedScalar wdetJ = q_data[0][i];
41     const State      s     = StateFromQ(gas, qi, state_var);
42 
43     v0[DIFF_FILTER_PRESSURE][i]            = wdetJ * s.Y.pressure;
44     v0[DIFF_FILTER_VELOCITY_X][i]          = wdetJ * s.Y.velocity[0];
45     v0[DIFF_FILTER_VELOCITY_Y][i]          = wdetJ * s.Y.velocity[1];
46     v0[DIFF_FILTER_VELOCITY_Z][i]          = wdetJ * s.Y.velocity[2];
47     v0[DIFF_FILTER_TEMPERATURE][i]         = wdetJ * s.Y.temperature;
48     v1[DIFF_FILTER_VELOCITY_SQUARED_XX][i] = wdetJ * s.Y.velocity[0] * s.Y.velocity[0];
49     v1[DIFF_FILTER_VELOCITY_SQUARED_YY][i] = wdetJ * s.Y.velocity[1] * s.Y.velocity[1];
50     v1[DIFF_FILTER_VELOCITY_SQUARED_ZZ][i] = wdetJ * s.Y.velocity[2] * s.Y.velocity[2];
51     v1[DIFF_FILTER_VELOCITY_SQUARED_YZ][i] = wdetJ * s.Y.velocity[1] * s.Y.velocity[2];
52     v1[DIFF_FILTER_VELOCITY_SQUARED_XZ][i] = wdetJ * s.Y.velocity[0] * s.Y.velocity[2];
53     v1[DIFF_FILTER_VELOCITY_SQUARED_XY][i] = wdetJ * s.Y.velocity[0] * s.Y.velocity[1];
54   }
55   return 0;
56 }
57 
DifferentialFilter_RHS_Conserv(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)58 CEED_QFUNCTION(DifferentialFilter_RHS_Conserv)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
59   return DifferentialFilter_RHS(ctx, Q, in, out, STATEVAR_CONSERVATIVE);
60 }
61 
DifferentialFilter_RHS_Prim(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)62 CEED_QFUNCTION(DifferentialFilter_RHS_Prim)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
63   return DifferentialFilter_RHS(ctx, Q, in, out, STATEVAR_PRIMITIVE);
64 }
65 
DifferentialFilter_RHS_Entropy(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)66 CEED_QFUNCTION(DifferentialFilter_RHS_Entropy)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
67   return DifferentialFilter_RHS(ctx, Q, in, out, STATEVAR_ENTROPY);
68 }
69 
VanDriestWallDamping(const CeedScalar wall_dist_plus,const CeedScalar A_plus)70 CEED_QFUNCTION_HELPER CeedScalar VanDriestWallDamping(const CeedScalar wall_dist_plus, const CeedScalar A_plus) {
71   return -expm1(-wall_dist_plus / A_plus);
72 }
73 
DifferentialFilter_LHS_N(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out,const CeedInt N)74 CEED_QFUNCTION_HELPER int DifferentialFilter_LHS_N(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out, const CeedInt N) {
75   const CeedScalar(*q)[CEED_Q_VLA]          = (const CeedScalar(*)[CEED_Q_VLA])in[0];
76   const CeedScalar(*Grad_q)[CEED_Q_VLA]     = (const CeedScalar(*)[CEED_Q_VLA])in[1];
77   const CeedScalar(*A_ij_delta)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[2];
78   const CeedScalar(*x)[CEED_Q_VLA]          = (const CeedScalar(*)[CEED_Q_VLA])in[3];
79   const CeedScalar(*q_data)                 = in[4];
80   CeedScalar(*v)[CEED_Q_VLA]                = (CeedScalar(*)[CEED_Q_VLA])out[0];
81   CeedScalar(*Grad_v)[CEED_Q_VLA]           = (CeedScalar(*)[CEED_Q_VLA])out[1];
82 
83   DifferentialFilterContext context = (DifferentialFilterContext)ctx;
84 
85   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
86     CeedPragmaSIMD for (CeedInt j = 0; j < N; j++) {
87       const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]};
88       CeedScalar       wdetJ, dXdx[3][3];
89       QdataUnpack_3D(Q, i, q_data, &wdetJ, dXdx);
90 
91       CeedScalar Delta_ij[3][3] = {{0.}};
92       if (context->grid_based_width) {
93         CeedScalar       km_A_ij[6] = {A_ij_delta[0][i], A_ij_delta[1][i], A_ij_delta[2][i], A_ij_delta[3][i], A_ij_delta[4][i], A_ij_delta[5][i]};
94         const CeedScalar delta      = A_ij_delta[6][i];
95         ScaleN(km_A_ij, delta, 6);  // Dimensionalize the normalized anisotropy tensor
96         KMUnpack(km_A_ij, Delta_ij);
97       } else {
98         Delta_ij[0][0] = Delta_ij[1][1] = Delta_ij[2][2] = 1;
99       }
100 
101       CeedScalar scaling_matrix[3][3] = {{0}};
102       if (context->damping_function == DIFF_FILTER_DAMP_VAN_DRIEST) {
103         const CeedScalar damping_coeff = VanDriestWallDamping(x_i[1] / context->friction_length, context->damping_constant);
104         scaling_matrix[0][0]           = Max(1, damping_coeff * context->width_scaling[0]);
105         scaling_matrix[1][1]           = damping_coeff * context->width_scaling[1];
106         scaling_matrix[2][2]           = Max(1, damping_coeff * context->width_scaling[2]);
107       } else if (context->damping_function == DIFF_FILTER_DAMP_NONE) {
108         scaling_matrix[0][0] = context->width_scaling[0];
109         scaling_matrix[1][1] = context->width_scaling[1];
110         scaling_matrix[2][2] = context->width_scaling[2];
111       } else if (context->damping_function == DIFF_FILTER_DAMP_MMS) {
112         const CeedScalar damping_coeff = tanh(60 * x_i[1]);
113         scaling_matrix[0][0]           = 1;
114         scaling_matrix[1][1]           = damping_coeff;
115         scaling_matrix[2][2]           = 1;
116       }
117 
118       CeedScalar scaled_Delta_ij[3][3] = {{0.}};
119       MatMat3(scaling_matrix, Delta_ij, CEED_NOTRANSPOSE, CEED_NOTRANSPOSE, scaled_Delta_ij);
120       CopyMat3(scaled_Delta_ij, Delta_ij);
121 
122       CeedScalar alpha_ij[3][3] = {{0.}};
123       MatMat3(Delta_ij, Delta_ij, CEED_NOTRANSPOSE, CEED_NOTRANSPOSE, alpha_ij);
124       ScaleN((CeedScalar *)alpha_ij, context->kernel_scaling, 9);
125 
126       v[j][i] = wdetJ * q[j][i];
127       CeedScalar dq[3], dq_dXdx[3] = {0.}, dq_dXdx_a[3] = {0.};
128       for (int k = 0; k < 3; k++) {
129         dq[k] = Grad_q[0 * N + j][i] * dXdx[0][k] + Grad_q[1 * N + j][i] * dXdx[1][k] + Grad_q[2 * N + j][i] * dXdx[2][k];
130       }
131       MatVec3(dXdx, dq, CEED_NOTRANSPOSE, dq_dXdx);
132       MatVec3(alpha_ij, dq_dXdx, CEED_NOTRANSPOSE, dq_dXdx_a);
133       for (int k = 0; k < 3; k++) {
134         Grad_v[k * N + j][i] = wdetJ * dq_dXdx_a[k];
135       }
136     }
137   }
138   return 0;
139 }
140 
DifferentialFilter_LHS_1(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)141 CEED_QFUNCTION(DifferentialFilter_LHS_1)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
142   return DifferentialFilter_LHS_N(ctx, Q, in, out, 1);
143 }
144 
DifferentialFilter_LHS_5(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)145 CEED_QFUNCTION(DifferentialFilter_LHS_5)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
146   return DifferentialFilter_LHS_N(ctx, Q, in, out, 5);
147 }
148 
DifferentialFilter_LHS_6(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)149 CEED_QFUNCTION(DifferentialFilter_LHS_6)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
150   return DifferentialFilter_LHS_N(ctx, Q, in, out, 6);
151 }
152 
DifferentialFilter_LHS_11(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)153 CEED_QFUNCTION(DifferentialFilter_LHS_11)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
154   return DifferentialFilter_LHS_N(ctx, Q, in, out, 11);
155 }
156 
MMS_Solution(const CeedScalar x_i[3],const CeedScalar omega)157 CEED_QFUNCTION_HELPER CeedScalar MMS_Solution(const CeedScalar x_i[3], const CeedScalar omega) {
158   return sin(6 * omega * x_i[0]) + sin(6 * omega * x_i[1]);
159 }
160 
DifferentialFilter_MMS_RHS(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)161 CEED_QFUNCTION(DifferentialFilter_MMS_RHS)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
162   const CeedScalar(*q)[CEED_Q_VLA]      = (const CeedScalar(*)[CEED_Q_VLA])in[0];
163   const CeedScalar(*q_data)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[1];
164   CeedScalar(*v)[CEED_Q_VLA]            = (CeedScalar(*)[CEED_Q_VLA])out[0];
165 
166   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
167     const CeedScalar wdetJ = q_data[0][i];
168     v[0][i]                = wdetJ * q[0][i];
169   }
170   return 0;
171 }
172 
173 // @brief Generate initial condition such that the solution of the differential filtering is given by MMS_Solution() above
174 //
175 // This requires a *very* specific grid, as the anisotropic filtering is grid dependent.
176 // It's for a 75x75x1 grid on a [0,0.5]x3 domain.
177 // The grid is evenly distributed in x, but distributed based on the analytical mesh distribution \Delta_y = .001 + .01*tanh(6*y).
178 // The MMS test can optionally include a wall damping function (must also be enabled for the differential filtering itself).
179 // It can be run via:
180 // ./navierstokes -options_file tests-output/blasius_test.yaml -diff_filter_monitor -diff_filter_view cgns:filtered_solution.cgns -ts_max_steps 0
181 // -diff_filter_mms -diff_filter_kernel_scaling 1 -diff_filter_wall_damping_function mms -dm_plex_box_upper 0.5,0.5,0.5 -dm_plex_box_faces 75,75,1
182 // -mesh_transform platemesh -platemesh_y_node_locs_path tests-output/diff_filter_mms_y_spacing.dat -platemesh_top_angle 0
183 // -diff_filter_grid_based_width
DifferentialFilter_MMS_IC(void * ctx,CeedInt Q,const CeedScalar * const * in,CeedScalar * const * out)184 CEED_QFUNCTION(DifferentialFilter_MMS_IC)(void *ctx, CeedInt Q, const CeedScalar *const *in, CeedScalar *const *out) {
185   const CeedScalar(*x)[CEED_Q_VLA] = (const CeedScalar(*)[CEED_Q_VLA])in[0];
186   CeedScalar(*q0)[CEED_Q_VLA]      = (CeedScalar(*)[CEED_Q_VLA])out[0];
187 
188   CeedPragmaSIMD for (CeedInt i = 0; i < Q; i++) {
189     const CeedScalar x_i[3] = {x[0][i], x[1][i], x[2][i]};
190 
191     const CeedScalar aniso_scale_factor = 1;  // Must match the one passed in by -diff_filter_aniso_scale
192     const CeedScalar omega              = 2 * M_PI;
193     const CeedScalar omega6             = 6 * omega;
194     const CeedScalar phi_bar            = MMS_Solution(x_i, omega);
195     const CeedScalar dx                 = 0.5 / 75;
196     const CeedScalar dy_analytic        = .001 + .01 * tanh(6 * x_i[1]);
197     const CeedScalar dy                 = dy_analytic;
198     const CeedScalar d_dy_dy            = 0.06 * Square(1 / cosh(6 * x_i[1]));  // Change of \Delta_y w.r.t. y
199     CeedScalar       alpha[2]           = {Square(dx) * aniso_scale_factor, Square(dy) * aniso_scale_factor};
200     bool             damping            = true;
201     CeedScalar       dalpha1dy;
202     if (damping) {
203       CeedScalar damping_coeff   = tanh(60 * x_i[1]);
204       CeedScalar d_damping_coeff = 60 / Square(cosh(60 * x_i[1]));
205       dalpha1dy                  = aniso_scale_factor * 2 * (damping_coeff * dy) * (dy * d_damping_coeff + damping_coeff * d_dy_dy);
206       alpha[1] *= Square(damping_coeff);
207     } else {
208       dalpha1dy = aniso_scale_factor * 2 * dy * d_dy_dy;
209     }
210 
211     CeedScalar phi = phi_bar + alpha[0] * Square(omega6) * sin(6 * omega * x_i[0]) + alpha[1] * Square(omega6) * sin(omega6 * x_i[1]);
212     phi -= dalpha1dy * omega6 * cos(omega6 * x_i[1]);
213 
214     for (CeedInt j = 0; j < 5; j++) q0[j][i] = phi;
215   }
216   return 0;
217 }
218