16 namespace DGSEMIntegrator
19 template<
typename ContextType>
20 MFEM_HOST_DEVICE
inline
21 static mfem::real_t AssembleElementVolumeKernel(
const ContextType &ctx,
22 const mfem::real_t *el_u,
const mfem::real_t *elJac_d,
23 const mfem::real_t *elMetric_d, mfem::real_t *el_dudt)
26 const int Np_x = ctx.Np_x;
27 const int Np_y = ctx.Np_y;
28 const int Np_z = ctx.Np_z;
29 const int dim = ctx.dim;
30 const int neq = ctx.num_equations;
31 const int dof = Np_x * Np_y * Np_z;
32 const mfem::real_t *Dhat2_d = ctx.Dhat2_d;
37 mfem::real_t max_char_speed = 0.0;
42 for (
int k = 0; k < Np_z; k++)
43 for (
int j = 0; j < Np_y; j++)
44 for (
int i = 0; i < Np_x; i++)
46 int id1 = k * Np_y * Np_x + j * Np_x + i;
48 const mfem::real_t *met1 = elMetric_d+id1*dim*dim;
49 for (
int m = i + 1; m < Np_x; m++)
51 int id2 = k * Np_y * Np_x + j * Np_x + m;
53 const mfem::real_t *met2 = elMetric_d + id2*dim*dim;
55 const mfem::real_t cs = ctx.iflux.ComputeVolumeFlux(ctx.gas, state1, state2, met1, met2, f);
58 const mfem::real_t c1 = Dhat2_d[m + Np_x*i];
59 const mfem::real_t c2 = Dhat2_d[i + Np_x*m];
69 for (
int k = 0; k < Np_z; ++k)
70 for (
int j = 0; j < Np_y; ++j)
71 for (
int i = 0; i < Np_x; ++i)
73 const int id1 = k*Np_y*Np_x + j*Np_x + i;
75 const mfem::real_t *met1 = elMetric_d + id1*dim*dim + 1*dim;
77 for (
int m = j+1; m < Np_y; ++m)
79 const int id2 = k*Np_y*Np_x + m*Np_x + i;
81 const mfem::real_t *met2 = elMetric_d + id2*dim*dim + dim;
83 const mfem::real_t cs = ctx.iflux.ComputeVolumeFlux(ctx.gas, state1, state2, met1, met2, f);
86 const mfem::real_t c1 = Dhat2_d[m + Np_y*j];
87 const mfem::real_t c2 = Dhat2_d[j + Np_y*m];
96 for (
int k = 0; k < Np_z; ++k)
97 for (
int j = 0; j < Np_y; ++j)
98 for (
int i = 0; i < Np_x; ++i)
100 const int id1 = k*Np_y*Np_x + j*Np_x + i;
102 const mfem::real_t *met1 = elMetric_d + id1*dim*dim + 2*dim;
104 for (
int m = k+1; m < Np_z; ++m)
106 const int id2 = m*Np_y*Np_x + j*Np_x + i;
108 const mfem::real_t *met2 = elMetric_d + id2*dim*dim + 2*dim;
110 const mfem::real_t cs = ctx.iflux.ComputeVolumeFlux(ctx.gas, state1, state2, met1, met2, f);
113 const mfem::real_t c1 = Dhat2_d[m + Np_z*k];
114 const mfem::real_t c2 = Dhat2_d[k + Np_z*m];
123 return max_char_speed;
126 template<
typename ContextT>
127 MFEM_HOST_DEVICE
static mfem::real_t AssembleElementFaceKernel(
const ContextT &ctx,
const mfem::real_t *u_face,
128 const mfem::real_t *nor_face,
const mfem::real_t *w_minus,
129 const mfem::real_t *w_plus, mfem::real_t *rhs_face)
131 mfem::real_t max_char_speed = 0.0;
135 const int nfp = ctx.num_face_points;
136 const int neq = ctx.num_equations;
137 const int dim = ctx.dim;
142 for (
int i = 0; i < nfp; i++)
144 const mfem::real_t *nor_d = nor_face + i*dim;
145 const mfem::real_t wminus = -w_minus[i];
146 const mfem::real_t wplus = w_plus[i];
148 for(
int j = 0;j < neq;j++){
149 qMinus[j] = u_face[ctx.iface_idx(0,i,j)];
150 qPlus[j] = u_face[ctx.iface_idx(1,i,j)];
153 Kernels::rmax(max_char_speed, ctx.iflux.ComputeFaceFlux(ctx.gas, qMinus, qPlus,
155 for(
int j = 0;j < neq;j++){
156 rhs_face[ctx.iface_idx(0, i, j)] = wminus * point_flux[j];
157 rhs_face[ctx.iface_idx(1, i, j)] = wplus * point_flux[j];
160 return max_char_speed;
163 template<
typename ContextT>
164 MFEM_HOST_DEVICE
static mfem::real_t AssembleViscousElementFaceKernel(
const ContextT &ctx,
const mfem::real_t *u_face,
165 const mfem::real_t *nor_face,
const mfem::real_t *w_minus,
166 const mfem::real_t *w_plus,
const mfem::real_t *dprim_face_x,
167 const mfem::real_t *dprim_face_y,
const mfem::real_t*dprim_face_z,
168 const mfem::real_t *face_radius,
169 mfem::real_t *rhs_face)
171 mfem::real_t max_char_speed = 0.0;
179 const mfem::real_t *dprim_face[
Theseus::MAXDIM] = {dprim_face_x, dprim_face_y, dprim_face_z};
180 const int nfp = ctx.num_face_points;
181 const int neq = ctx.num_equations;
182 const int dim = ctx.dim;
187 for (
int i = 0; i < nfp; i++)
189 const mfem::real_t *nor_d = nor_face + i*dim;
190 const mfem::real_t wminus = -w_minus[i];
191 const mfem::real_t wplus = w_plus[i];
193 for(
int j = 0;j < neq;j++){
194 int minus_index = ctx.iface_idx(0, i, j);
195 int plus_index = ctx.iface_idx(1, i, j);
196 qMinus[j] = u_face[minus_index];
197 qPlus[j] = u_face[plus_index];
198 for(
int idim = 0;idim < dim;idim++){
199 gradPrim_minus[idim][j] = dprim_face[idim][minus_index];
200 gradPrim_plus[idim][j] = dprim_face[idim][plus_index];
204 Kernels::rmax(max_char_speed, ctx.iflux.ComputeFaceFlux(ctx.gas, qMinus, qPlus,
210 NavierStokesFlux::ComputeViscousFluxKernel(ctx.gas, qMinus,
213 gradPrim_minus[2], vflux_minus,
215 ctx.axisymmetric ? face_radius[i] : 0.0);
216 NavierStokesFlux::ComputeViscousFluxKernel(ctx.gas, qPlus,
219 gradPrim_plus[2], vflux_plus,
221 ctx.axisymmetric ? face_radius[i] : 0.0);
228 for(
int j = 0;j < neq;j++){
229 for(
int idim = 0;idim < dim;idim++){
230 mfem::real_t avg = 0.5*(vflux_minus[j][idim] + vflux_plus[j][idim]);
231 point_flux[j] -= nor_d[idim]*avg;
238 for(
int j = 0;j < neq;j++){
239 rhs_face[ctx.iface_idx(0, i, j)] = wminus * point_flux[j];
240 rhs_face[ctx.iface_idx(1, i, j)] = wplus * point_flux[j];
243 return max_char_speed;
246 template<
typename ContextT>
247 MFEM_HOST_DEVICE
inline static mfem::real_t ComputeFVFluxesKernel(
const ContextT &ctx,
248 const mfem::real_t *el_u,
249 const mfem::real_t *elJac,
250 const mfem::real_t *el_metric_xi,
251 const mfem::real_t *el_metric_eta,
252 const mfem::real_t *el_metric_zeta,
253 mfem::real_t *el_dudt)
255 const int dim = ctx.dim;
256 const int Np_x = ctx.Np_x;
257 const int Np_y = ctx.Np_y;
258 const int Np_z = ctx.Np_z;
259 const int neq = ctx.num_equations;
260 const int npe = Np_x * Np_y * Np_z;
261 const mfem::real_t *qWgt = ctx.subcell_weights_d;
263 mfem::real_t max_char_speed = 0.0;
269 for(
int i = 0;i < npe*neq;i++)
272 for (
int k = 0; k < Np_z; k++)
274 for (
int j = 0; j < Np_y; j++)
276 for(
int q = 0; q < neq;q++){
279 int id1 = k * Np_y * Np_x + j * Np_x;
281 for (
int i = 0; i < Np_x - 1; i++)
285 const mfem::real_t *nor = el_metric_xi + id2*dim;
288 Kernels::rmax(max_char_speed,
289 ctx.iflux.ComputeFaceFlux(ctx.gas, state1_local,
290 state2_local, nor, flux_num));
291 for(
int q = 0; q < neq;q++){
292 du_subcell[q] -= flux_num[q];
294 for(
int q = 0; q < neq;q++){
295 du_subcell[q] /= (elJac[id1] * qWgt[i]);
298 for(
int q = 0; q < neq;q++){
299 du_subcell[q] = flux_num[q];
301 for(
int q = 0;q < neq;q++){
302 state1_local[q] = state2_local[q];
306 for(
int q = 0;q < neq;q++){
307 du_subcell[q] /= (elJac[id1] * qWgt[Np_x-1]);
315 for (
int k = 0; k < Np_z; k++)
317 for (
int i = 0; i < Np_x; i++)
319 for(
int q = 0; q < neq;q++){
322 int id1 = k * Np_y * Np_x + i;
325 for (
int j = 0; j < Np_y - 1; j++)
327 int id2 = k * Np_y * Np_x + (j + 1) * Np_x + i;
330 const mfem::real_t *nor = el_metric_eta + id2*dim;
332 Kernels::rmax(max_char_speed,
333 ctx.iflux.ComputeFaceFlux(ctx.gas,
337 for(
int q = 0;q < neq;q++){
338 du_subcell[q] -= flux_num[q];
340 for(
int q = 0;q < neq;q++){
341 du_subcell[q] /= (elJac[id1] * qWgt[j]);
344 for(
int q = 0;q < neq;q++){
345 du_subcell[q] = flux_num[q];
346 state1_local[q] = state2_local[q];
350 for(
int q = 0;q < neq;q++){
351 du_subcell[q] /= (elJac[id1] * qWgt[Np_y - 1]);
358 for (
int j = 0; j < Np_y; j++)
360 for (
int i = 0; i < Np_x; i++)
362 for(
int q = 0; q < neq;q++){
365 int id1 = j * Np_x + i;
368 for (
int k = 0; k < Np_z - 1; k++)
370 int id2 = (k + 1) * Np_y * Np_x + j * Np_x + i;
373 const mfem::real_t *nor = el_metric_zeta + id2*dim;
375 Kernels::rmax(max_char_speed,
376 ctx.iflux.ComputeFaceFlux(ctx.gas, state1_local,
377 state2_local, nor, flux_num));
378 for(
int q = 0;q < neq;q++){
379 du_subcell[q] -= flux_num[q];
381 for(
int q = 0;q < neq;q++){
382 du_subcell[q] /= (elJac[id1] * qWgt[k]);
386 for(
int q = 0;q < neq;q++){
387 du_subcell[q] = flux_num[q];
388 state1_local[q] = state2_local[q];
392 for(
int q = 0;q < neq;q++){
393 du_subcell[q] /= (elJac[id1] * qWgt[Np_z - 1]);
400 return max_char_speed;
404 template<
typename ContextType>
405 MFEM_HOST_DEVICE
inline
406 static void AssembleViscousElementVolumeKernel(
const ContextType &ctx,
407 const mfem::real_t *el_u,
408 const mfem::real_t *elJac_d,
409 const mfem::real_t *elMetric_d,
410 const mfem::real_t *elRadius_d,
411 const mfem::real_t *el_gradprim_x,
412 const mfem::real_t *el_gradprim_y,
413 const mfem::real_t *el_gradprim_z,
414 mfem::real_t *el_dudt)
416 const int Np_x = ctx.Np_x;
417 const int Np_y = ctx.Np_y;
418 const int Np_z = ctx.Np_z;
419 const int dim = ctx.dim;
420 const int neq = ctx.num_equations;
421 const int dof = Np_x * Np_y * Np_z;
422 const mfem::real_t *Dhat_d = ctx.Dhat_d;
434 for (
int k = 0; k < Np_z; ++k)
436 for (
int j = 0; j < Np_y; ++j)
438 for (
int i = 0; i < Np_x; ++i)
440 const int id1 = k * Np_y * Np_x + j * Np_x + i;
441 const mfem::real_t J = elJac_d[id1];
442 const mfem::real_t jInv = 1.0/J;
447 for (
int l = 0; l < Np_x; ++l)
449 const int idl = k * Np_y * Np_x + j * Np_x + l;
450 const mfem::real_t c = Dhat_d[l + Np_x * i];
454 el_gradprim_z, dim, dof, neq, idl,
457 const mfem::real_t *adj_row = elMetric_d + idl * dim * dim + 0 * dim;
458 Theseus::NavierStokesFlux::compute_ref_viscous_flux(
459 ctx.gas, dim, neq, state, dqx, dqy, dqz, adj_row,
460 f_ref, ctx.axisymmetric,
461 ctx.axisymmetric ? elRadius_d[idl] : 0.0);
462 for (
int q = 0; q < neq; ++q)
464 dU_viscous[q] += c * f_ref[q];
471 for (
int l = 0; l < Np_y; ++l)
473 const int idl = k * Np_y * Np_x + l * Np_x + i;
474 const mfem::real_t c = Dhat_d[l + Np_y * j];
478 el_gradprim_z, dim, dof, neq, idl,
481 const mfem::real_t *adj_row = elMetric_d + idl * dim * dim + 1 * dim;
482 Theseus::NavierStokesFlux::compute_ref_viscous_flux(
483 ctx.gas, dim, neq, state, dqx, dqy, dqz, adj_row,
484 f_ref, ctx.axisymmetric,
485 ctx.axisymmetric ? elRadius_d[idl] : 0.0);
487 for (
int q = 0; q < neq; ++q)
489 dU_viscous[q] += c * f_ref[q];
497 for (
int l = 0; l < Np_z; ++l)
499 const int idl = l * Np_y * Np_x + j * Np_x + i;
500 const mfem::real_t c = Dhat_d[l + Np_z * k];
504 el_gradprim_z, dim, dof, neq, idl,
507 const mfem::real_t *adj_row = elMetric_d + idl * dim * dim + 2 * dim;
508 Theseus::NavierStokesFlux::compute_ref_viscous_flux(
509 ctx.gas, dim, neq, state, dqx, dqy, dqz, adj_row,
510 f_ref, ctx.axisymmetric,
511 ctx.axisymmetric ? elRadius_d[idl] : 0.0);
513 for (
int q = 0; q < neq; ++q)
515 dU_viscous[q] += c * f_ref[q];
520 if (ctx.axisymmetric)
524 el_gradprim_x, el_gradprim_y, el_gradprim_z, dim,
525 dof, neq, id1, dqx, dqy, dqz);
528 ctx.gas, state, dqx, dqy, dqz,
529 elRadius_d[id1], source))
532 ctx, el_u, el_gradprim_x, el_gradprim_y,
533 el_gradprim_z, elRadius_d, elJac_d, elMetric_d,
544 template <
typename ContextType>
545 MFEM_HOST_DEVICE
inline
546 static void AssembleGradElementVolumeKernel(
const ContextType &ctx,
547 const mfem::real_t *el_u,
548 const mfem::real_t *elJac_d,
549 const mfem::real_t *elMetric_d,
552 const int Np_x = ctx.Np_x;
553 const int Np_y = ctx.Np_y;
554 const int Np_z = ctx.Np_z;
555 const int neq = ctx.num_equations;
556 const int dim = ctx.dim;
557 const int dof = Np_x * Np_y * Np_z;
558 const mfem::real_t *D_d = ctx.D_d;
565 for (
int i = 0; i < Np_x; ++i)
569 for (
int q = 0; q < neq; ++q)
574 for (
int l = 0; l < Np_x; ++l)
577 const mfem::real_t c_xi = D_d[i*Np_x + l];
579 for (
int q = 0; q < neq; ++q)
581 dudxi[q] += el_u[id_x + q * dof] * c_xi;
585 const mfem::real_t invJ = 1.0 / elJac_d[id];
586 const mfem::real_t *adj = elMetric_d +
id * dim * dim;
588 for (
int q = 0; q < neq; ++q)
590 el_grad_u[0][
id + q * dof] = invJ * (dudxi[q] * adj[0]);
597 for (
int j = 0; j < Np_y; ++j)
599 for (
int i = 0; i < Np_x; ++i)
601 const int id = j * Np_x + i;
603 for (
int q = 0; q < neq; ++q)
610 for (
int l = 0; l < Np_x; ++l)
612 const int id_x = j * Np_x + l;
613 const int id_y = l * Np_x + i;
615 const mfem::real_t c_xi = D_d[l + Np_x * i];
616 const mfem::real_t c_eta = D_d[l + Np_x * j];
618 for (
int q = 0; q < neq; ++q)
620 dudxi[q] += el_u[id_x + q * dof] * c_xi;
621 dudeta[q] += el_u[id_y + q * dof] * c_eta;
625 const mfem::real_t invJ = 1.0 / elJac_d[id];
626 const mfem::real_t *adj = elMetric_d +
id * dim * dim;
631 for (
int q = 0; q < neq; ++q)
633 el_grad_u[0][
id + q * dof] = invJ * (dudxi[q] * adj[0] + dudeta[q] * adj[2]);
634 el_grad_u[1][
id + q * dof] = invJ * (dudxi[q] * adj[1] + dudeta[q] * adj[3]);
638 }
else if (dim == 3) {
644 for (
int k = 0; k < Np_z; ++k)
646 for (
int j = 0; j < Np_y; ++j)
648 for (
int i = 0; i < Np_x; ++i)
650 const int id = k * Np_x * Np_y + j * Np_x + i;
652 for (
int q = 0; q < neq; ++q)
660 for (
int l = 0; l < Np_x; ++l)
662 const int id_x = k * Np_x * Np_y + j * Np_x + l;
663 const int id_y = k * Np_x * Np_y + l * Np_x + i;
664 const int id_z = l * Np_x * Np_y + j * Np_x + i;
665 const mfem::real_t c_xi = D_d[l + Np_x * i];
666 const mfem::real_t c_eta = D_d[l + Np_x * j];
667 const mfem::real_t c_zeta = D_d[l + Np_x * k];
668 for (
int q = 0; q < neq; ++q)
670 dudxi[q] += el_u[id_x + q * dof] * c_xi;
671 dudeta[q] += el_u[id_y + q * dof] * c_eta;
672 dudzeta[q] += el_u[id_z + q * dof] * c_zeta;
676 const mfem::real_t invJ = 1.0 / elJac_d[id];
677 const mfem::real_t *adj = elMetric_d +
id * dim * dim;
683 for (
int q = 0; q < neq; ++q)
685 el_grad_u[0][
id + q * dof] = invJ * (dudxi[q] * adj[0] +
687 dudzeta[q] * adj[6]);
689 el_grad_u[1][
id + q * dof] = invJ * (dudxi[q] * adj[1] +
691 dudzeta[q] * adj[7]);
693 el_grad_u[2][
id + q * dof] = invJ * (dudxi[q] * adj[2] +
695 dudzeta[q] * adj[8]);
703 template <
typename ContextT>
704 MFEM_HOST_DEVICE
inline
705 static void AssembleGradInteriorFaceKernel(
const ContextT &ctx,
706 const mfem::real_t *u_face,
707 const mfem::real_t *nor_face,
708 const mfem::real_t *w_minus,
709 const mfem::real_t *w_plus,
712 const int nfp = ctx.num_face_points;
713 const int neq = ctx.num_equations;
714 const int dim = ctx.dim;
720 for (
int i = 0; i < nfp; ++i)
722 const mfem::real_t *nor_d = nor_face + i * dim;
724 const mfem::real_t wminus = w_minus[i];
725 const mfem::real_t wplus = w_plus[i];
727 for (
int q = 0; q < neq; ++q)
729 qMinus[q] = u_face[ctx.iface_idx(0, i, q)];
730 qPlus[q] = u_face[ctx.iface_idx(1, i, q)];
731 jump[q] = mfem::real_t(0.5) * (qPlus[q] - qMinus[q]);
734 for (
int idim = 0;idim < dim;idim++){
735 mfem::real_t *rhs_d = rhs_face[idim];
736 const mfem::real_t n_d = nor_d[idim];
737 for (
int q = 0; q < neq; ++q)
739 const mfem::real_t f_d = jump[q]*n_d;
740 rhs_d[ctx.iface_idx(0, i, q)] = wminus * f_d;
741 rhs_d[ctx.iface_idx(1, i, q)] = wplus * f_d;
747 template <
typename DeviceCacheT>
748 MFEM_HOST_DEVICE
inline
749 static void AssembleGradBoundaryPointKernel(
const DeviceCacheT &dc,
751 const mfem::real_t *u_face,
752 const mfem::real_t *nor_point,
753 const mfem::real_t scale,
757 const int dim = dc.dim;
758 const int nfp = dc.num_face_points;
759 const int neq = dc.num_equations;
769 for(
int idim = 0;idim < dim;idim++){
770 for(
int q = 0;q < neq;q++){
771 flux_dir[q] = fluxN[q]*nor_point[idim];