Computes the dynamic Smagorinsky constant (Cs) for the LES model.
This function implements the dynamic procedure for calculating the Smagorinsky constant at each grid point. It involves test-filtering the velocity field and strain rate tensor to determine the constant locally. The calculation can be computationally expensive and is typically run less frequently than every time step, controlled by simCtx->dynamic_freq.
Computes the dynamic Smagorinsky constant (Cs) for the LES model.
Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/les.h.
31{
32 PetscErrorCode ierr;
34
35 PetscFunctionBeginUser;
37
38
39
40
41
43 ierr = VecSet(user->
CS, 0.0); CHKERRQ(ierr);
46 PetscFunctionReturn(0);
47 }
48
49
50
53 ierr = VecSet(user->
CS, simCtx->
Const_CS); CHKERRQ(ierr);
55 PetscFunctionReturn(0);
56 }
57
58
59
60 DM da = user->
da, fda = user->
fda;
61 DMDALocalInfo info;
62 PetscInt i, j, k, p, q, r;
63 PetscInt xs, xe, ys, ye, zs, ze;
64 PetscInt mx, my, mz;
65 PetscInt lxs, lxe, lys, lye, lzs, lze;
66
67
68
69 Vec lSx, lSy, lSz, lS_abs;
70 Vec lLM, lMM;
71
72
73 ierr = DMDAGetLocalInfo(da, &info); CHKERRQ(ierr);
74 mx = info.mx; my = info.my; mz = info.mz;
75 xs = info.xs; xe = xs + info.xm;
76 ys = info.ys; ye = ys + info.ym;
77 zs = info.zs; ze = zs + info.zm;
78
79
80 lxs = xs; lxe = xe; lys = ys; lye = ye; lzs = zs; lze = ze;
81 if (xs==0) lxs = xs+1;
82 if (ys==0) lys = ys+1;
83 if (zs==0) lzs = zs+1;
84 if (xe==mx) lxe = xe-1;
85 if (ye==my) lye = ye-1;
86 if (ze==mz) lze = ze-1;
87
88
89 ierr = VecDuplicate(user->
lUcont, &lSx); CHKERRQ(ierr);
90 ierr = VecDuplicate(user->
lUcont, &lSy); CHKERRQ(ierr);
91 ierr = VecDuplicate(user->
lUcont, &lSz); CHKERRQ(ierr);
92 ierr = VecDuplicate(user->
lP, &lS_abs); CHKERRQ(ierr);
93 ierr = VecDuplicate(user->
lP, &lLM); CHKERRQ(ierr);
94 ierr = VecDuplicate(user->
lP, &lMM); CHKERRQ(ierr);
95 ierr = VecSet(lLM, 0.0); CHKERRQ(ierr);
96 ierr = VecSet(lMM, 0.0); CHKERRQ(ierr);
97
98
99 Cmpnts ***ucat, ***csi, ***eta, ***zet;
100 PetscReal ***nvert, ***Cs_arr, ***aj, ***S_abs_arr, ***LM_arr, ***MM_arr;
101 Cmpnts ***Sx_arr, ***Sy_arr, ***Sz_arr;
102
103 ierr = DMDAVecGetArray(fda, user->
lUcat, &ucat); CHKERRQ(ierr);
104 ierr = DMDAVecGetArrayRead(fda, user->
lCsi, (
Cmpnts***)&csi); CHKERRQ(ierr);
105 ierr = DMDAVecGetArrayRead(fda, user->
lEta, (
Cmpnts***)&eta); CHKERRQ(ierr);
106 ierr = DMDAVecGetArrayRead(fda, user->
lZet, (
Cmpnts***)&zet); CHKERRQ(ierr);
107 ierr = DMDAVecGetArrayRead(da, user->
lNvert, (PetscReal***)&nvert); CHKERRQ(ierr);
108 ierr = DMDAVecGetArrayRead(da, user->
lAj, (PetscReal***)&aj); CHKERRQ(ierr);
109 ierr = DMDAVecGetArray(da, user->
CS, &Cs_arr); CHKERRQ(ierr);
110
111 ierr = DMDAVecGetArray(fda, lSx, &Sx_arr); CHKERRQ(ierr);
112 ierr = DMDAVecGetArray(fda, lSy, &Sy_arr); CHKERRQ(ierr);
113 ierr = DMDAVecGetArray(fda, lSz, &Sz_arr); CHKERRQ(ierr);
114 ierr = DMDAVecGetArray(da, lS_abs, &S_abs_arr); CHKERRQ(ierr);
115 ierr = DMDAVecGetArray(da, lLM, &LM_arr); CHKERRQ(ierr);
116 ierr = DMDAVecGetArray(da, lMM, &MM_arr); CHKERRQ(ierr);
117
118
119 for (k=lzs; k<lze; k++)
120 for (j=lys; j<lye; j++)
121 for (i=lxs; i<lxe; i++) {
122 if( nvert[k][j][i] > 1.1) continue;
123
126
128 double Sxy = 0.5 * (dudx.
y + dvdx.
x);
129 double Sxz = 0.5 * (dudx.
z + dwdx.
x);
131 double Syz = 0.5 * (dvdx.
z + dwdx.
y);
133 double Syx = Sxy, Szx = Sxz, Szy = Syz;
134
135 S_abs_arr[k][j][i] = sqrt( 2.0 * (Sxx*Sxx + Sxy*Sxy + Sxz*Sxz +
136 Syx*Syx + Syy*Syy + Syz*Syz +
137 Szx*Szx + Szy*Szy + Szz*Szz) );
138
139
140 Sx_arr[k][j][i] = dudx;
141 Sy_arr[k][j][i] = dvdx;
142 Sz_arr[k][j][i] = dwdx;
143 }
144
145
146 for (k=lzs; k<lze; k++)
147 for (j=lys; j<lye; j++)
148 for (i=lxs; i<lxe; i++) {
149 if(nvert[k][j][i] > 1.1) {
150 LM_arr[k][j][i] = 0.0;
151 MM_arr[k][j][i] = 0.0;
152 continue;
153 }
154
155
156 double u[3][3][3], v[3][3][3], w[3][3][3];
157 double S_abs_stencil[3][3][3];
158 double S11[3][3][3], S12[3][3][3], S13[3][3][3];
159 double S22[3][3][3], S23[3][3][3], S33[3][3][3];
160 double weights[3][3][3];
161
162 for(r=-1; r<=1; r++)
163 for(q=-1; q<=1; q++)
164 for(p=-1; p<=1; p++) {
165 int R=r+1, Q=q+1, P=p+1;
166 int KK=k+r, JJ=j+q, II=i+p;
167
168 u[R][Q][P] = ucat[KK][JJ][II].
x;
169 v[R][Q][P] = ucat[KK][JJ][II].
y;
170 w[R][Q][P] = ucat[KK][JJ][II].
z;
171
172
173 S11[R][Q][P] = Sx_arr[KK][JJ][II].
x;
174 S12[R][Q][P] = 0.5 * (Sx_arr[KK][JJ][II].
y + Sy_arr[KK][JJ][II].
x);
175 S13[R][Q][P] = 0.5 * (Sx_arr[KK][JJ][II].
z + Sz_arr[KK][JJ][II].
x);
176 S22[R][Q][P] = Sy_arr[KK][JJ][II].
y;
177 S23[R][Q][P] = 0.5 * (Sy_arr[KK][JJ][II].
z + Sz_arr[KK][JJ][II].
y);
178 S33[R][Q][P] = Sz_arr[KK][JJ][II].
z;
179
180 S_abs_stencil[R][Q][P] = S_abs_arr[KK][JJ][II];
181 weights[R][Q][P] = aj[KK][JJ][II];
182 }
183
184
188
195
197
198
199 double uu[3][3][3], uv[3][3][3], uw[3][3][3], vv[3][3][3], vw[3][3][3], ww[3][3][3];
200 for(r=0; r<3; r++) for(q=0; q<3; q++) for(p=0; p<3; p++) {
201 uu[r][q][p] = u[r][q][p] * u[r][q][p];
202 uv[r][q][p] = u[r][q][p] * v[r][q][p];
203 uw[r][q][p] = u[r][q][p] * w[r][q][p];
204 vv[r][q][p] = v[r][q][p] * v[r][q][p];
205 vw[r][q][p] = v[r][q][p] * w[r][q][p];
206 ww[r][q][p] = w[r][q][p] * w[r][q][p];
207 }
214
215
216 double L11 = uu_filt - u_filt * u_filt;
217 double L12 = uv_filt - u_filt * v_filt;
218 double L13 = uw_filt - u_filt * w_filt;
219 double L22 = vv_filt - v_filt * v_filt;
220 double L23 = vw_filt - v_filt * w_filt;
221 double L33 = ww_filt - w_filt * w_filt;
222
223
224 double grid_filter_width, test_filter_width;
226 grid_filter_width = pow(1.0 / aj[k][j][i], 1.0/3.0);
227 test_filter_width = 2.0 * grid_filter_width;
228
229 double alpha = pow(test_filter_width / grid_filter_width, 2.0);
230
231 double M11 = -2.0 * grid_filter_width * grid_filter_width * (alpha * S_abs_filt * S11_filt - S_abs_filt * S11_filt);
232 double M12 = -2.0 * grid_filter_width * grid_filter_width * (alpha * S_abs_filt * S12_filt - S_abs_filt * S12_filt);
233 double M13 = -2.0 * grid_filter_width * grid_filter_width * (alpha * S_abs_filt * S13_filt - S_abs_filt * S13_filt);
234 double M22 = -2.0 * grid_filter_width * grid_filter_width * (alpha * S_abs_filt * S22_filt - S_abs_filt * S22_filt);
235 double M23 = -2.0 * grid_filter_width * grid_filter_width * (alpha * S_abs_filt * S23_filt - S_abs_filt * S23_filt);
236 double M33 = -2.0 * grid_filter_width * grid_filter_width * (alpha * S_abs_filt * S33_filt - S_abs_filt * S33_filt);
237
238
239 LM_arr[k][j][i] = L11*M11 + 2*L12*M12 + 2*L13*M13 + L22*M22 + 2*L23*M23 + L33*M33;
240 MM_arr[k][j][i] = M11*M11 + 2*M12*M12 + 2*M13*M13 + M22*M22 + 2*M23*M23 + M33*M33;
241 }
242
243
244
245
246
247
248
249
250 for (k=lzs; k<lze; k++)
251 for (j=lys; j<lye; j++)
252 for (i=lxs; i<lxe; i++) {
253 if(nvert[k][j][i] > 1.1) {
254 Cs_arr[k][j][i] = 0.0;
255 continue;
256 }
257
258 double C_sq = 0.0;
260 C_sq = LM_arr[k][j][i] / MM_arr[k][j][i];
261 }
262
263
264 double Cs_val = (C_sq > 0.0) ? sqrt(C_sq) : 0.0;
265 Cs_arr[k][j][i] = PetscMin(PetscMax(Cs_val, 0.0), simCtx->
max_cs);
266 }
267
268
269
270
271 ierr = DMDAVecRestoreArray(fda, user->
lUcat, &ucat); CHKERRQ(ierr);
272 ierr = DMDAVecRestoreArrayRead(fda, user->
lCsi, (
Cmpnts***)&csi); CHKERRQ(ierr);
273 ierr = DMDAVecRestoreArrayRead(fda, user->
lEta, (
Cmpnts***)&eta); CHKERRQ(ierr);
274 ierr = DMDAVecRestoreArrayRead(fda, user->
lZet, (
Cmpnts***)&zet); CHKERRQ(ierr);
275 ierr = DMDAVecRestoreArrayRead(da, user->
lNvert, (PetscReal***)&nvert); CHKERRQ(ierr);
276 ierr = DMDAVecRestoreArrayRead(da, user->
lAj, (PetscReal***)&aj); CHKERRQ(ierr);
277 ierr = DMDAVecRestoreArray(da, user->
CS, &Cs_arr); CHKERRQ(ierr);
278 ierr = DMDAVecRestoreArray(fda, lSx, &Sx_arr); CHKERRQ(ierr);
279 ierr = DMDAVecRestoreArray(fda, lSy, &Sy_arr); CHKERRQ(ierr);
280 ierr = DMDAVecRestoreArray(fda, lSz, &Sz_arr); CHKERRQ(ierr);
281 ierr = DMDAVecRestoreArray(da, lS_abs, &S_abs_arr); CHKERRQ(ierr);
282 ierr = DMDAVecRestoreArray(da, lLM, &LM_arr); CHKERRQ(ierr);
283 ierr = DMDAVecRestoreArray(da, lMM, &MM_arr); CHKERRQ(ierr);
284
285
286 ierr = VecDestroy(&lSx); CHKERRQ(ierr);
287 ierr = VecDestroy(&lSy); CHKERRQ(ierr);
288 ierr = VecDestroy(&lSz); CHKERRQ(ierr);
289 ierr = VecDestroy(&lS_abs); CHKERRQ(ierr);
290 ierr = VecDestroy(&lLM); CHKERRQ(ierr);
291 ierr = VecDestroy(&lMM); CHKERRQ(ierr);
292
293
294 ierr = DMGlobalToLocalBegin(da, user->
CS, INSERT_VALUES, user->
lCs); CHKERRQ(ierr);
295 ierr = DMGlobalToLocalEnd(da, user->
CS, INSERT_VALUES, user->
lCs); CHKERRQ(ierr);
296
297 PetscReal max_norm;
298 ierr = VecMax(user->
CS, NULL, &max_norm); CHKERRQ(ierr);
300
302 PetscFunctionReturn(0);
303}
double ApplyLESTestFilter(const SimCtx *simCtx, double values[3][3][3], double weights[3][3][3])
Applies a numerical "test filter" to a 3x3x3 stencil of data points.
PetscErrorCode ComputeCellCharacteristicLengthScale(PetscReal ajc, Cmpnts csi, Cmpnts eta, Cmpnts zet, double *dx, double *dy, double *dz)
Computes characteristic length scales (dx, dy, dz) for a curvilinear cell.
#define GLOBAL
Scope for global logging across all processes.
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
@ LOG_INFO
Informational messages about program execution.
@ LOG_DEBUG
Detailed debugging information.
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
PetscErrorCode ComputeVectorFieldDerivatives(UserCtx *user, PetscInt i, PetscInt j, PetscInt k, Cmpnts ***field_data, Cmpnts *dudx, Cmpnts *dvdx, Cmpnts *dwdx)
Computes the derivatives of a cell-centered vector field at a specific grid point.
SimCtx * simCtx
Back-pointer to the master simulation context.
A 3D point or vector with PetscScalar components.
The master context for the entire simulation.