16 namespace DGSEMIntegrator
19 template<
typename ContextType>
20 MFEM_HOST_DEVICE
inline
21 static void 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;
41 for (
int k = 0; k < Np_z; k++)
42 for (
int j = 0; j < Np_y; j++)
43 for (
int i = 0; i < Np_x; i++)
45 int id1 = k * Np_y * Np_x + j * Np_x + i;
47 const mfem::real_t *met1 = elMetric_d+id1*dim*dim;
48 for (
int m = i + 1; m < Np_x; m++)
50 int id2 = k * Np_y * Np_x + j * Np_x + m;
52 const mfem::real_t *met2 = elMetric_d + id2*dim*dim;
54 ctx.iflux.ComputeVolumeFlux(ctx.gas, state1, state2,
57 const mfem::real_t c1 = Dhat2_d[m + Np_x*i];
58 const mfem::real_t c2 = Dhat2_d[i + Np_x*m];
68 for (
int k = 0; k < Np_z; ++k)
69 for (
int j = 0; j < Np_y; ++j)
70 for (
int i = 0; i < Np_x; ++i)
72 const int id1 = k*Np_y*Np_x + j*Np_x + i;
74 const mfem::real_t *met1 = elMetric_d + id1*dim*dim + 1*dim;
76 for (
int m = j+1; m < Np_y; ++m)
78 const int id2 = k*Np_y*Np_x + m*Np_x + i;
80 const mfem::real_t *met2 = elMetric_d + id2*dim*dim + dim;
82 ctx.iflux.ComputeVolumeFlux(ctx.gas, state1, state2,
85 const mfem::real_t c1 = Dhat2_d[m + Np_y*j];
86 const mfem::real_t c2 = Dhat2_d[j + Np_y*m];
95 for (
int k = 0; k < Np_z; ++k)
96 for (
int j = 0; j < Np_y; ++j)
97 for (
int i = 0; i < Np_x; ++i)
99 const int id1 = k*Np_y*Np_x + j*Np_x + i;
101 const mfem::real_t *met1 = elMetric_d + id1*dim*dim + 2*dim;
103 for (
int m = k+1; m < Np_z; ++m)
105 const int id2 = m*Np_y*Np_x + j*Np_x + i;
107 const mfem::real_t *met2 = elMetric_d + id2*dim*dim + 2*dim;
109 ctx.iflux.ComputeVolumeFlux(ctx.gas, state1, state2,
112 const mfem::real_t c1 = Dhat2_d[m + Np_z*k];
113 const mfem::real_t c2 = Dhat2_d[k + Np_z*m];
124 template<
typename ContextType>
125 MFEM_HOST_DEVICE
inline
126 static void AssembleVolumePointKernel(
127 const ContextType &ctx,
const mfem::real_t *el_u,
128 const mfem::real_t *elJac_d,
const mfem::real_t *elMetric_d,
129 const int point, mfem::real_t *el_dudt)
131 const int Np_x = ctx.Np_x;
132 const int Np_y = ctx.Np_y;
133 const int Np_z = ctx.Np_z;
134 const int dim = ctx.dim;
135 const int neq = ctx.num_equations;
136 const int dof = ctx.ndof_scalar_el;
137 const mfem::real_t *Dhat2_d = ctx.Dhat2_d;
138 const int i = point % Np_x;
139 const int j = (point / Np_x) % Np_y;
140 const int k = point / (Np_x*Np_y);
147 for (
int m = 0; m < Np_x; ++m)
149 if (m == i) {
continue; }
150 const int lower = m < i ? m : i;
151 const int upper = m < i ? i : m;
152 const int lower_point = k*Np_y*Np_x + j*Np_x + lower;
153 const int upper_point = k*Np_y*Np_x + j*Np_x + upper;
156 ctx.iflux.ComputeVolumeFlux(ctx.gas, state_lower, state_upper,
157 elMetric_d + lower_point*dim*dim,
158 elMetric_d + upper_point*dim*dim, flux);
159 const mfem::real_t coefficient = Dhat2_d[m + Np_x*i];
160 for (
int q = 0; q < neq; ++q)
162 point_rate[q] += coefficient*flux[q];
168 for (
int m = 0; m < Np_y; ++m)
170 if (m == j) {
continue; }
171 const int lower = m < j ? m : j;
172 const int upper = m < j ? j : m;
173 const int lower_point = k*Np_y*Np_x + lower*Np_x + i;
174 const int upper_point = k*Np_y*Np_x + upper*Np_x + i;
176 el_u, dof, neq, lower_point, state_lower);
178 el_u, dof, neq, upper_point, state_upper);
179 ctx.iflux.ComputeVolumeFlux(
180 ctx.gas, state_lower, state_upper,
181 elMetric_d + lower_point*dim*dim + dim,
182 elMetric_d + upper_point*dim*dim + dim, flux);
183 const mfem::real_t coefficient = Dhat2_d[m + Np_y*j];
184 for (
int q = 0; q < neq; ++q)
186 point_rate[q] += coefficient*flux[q];
193 for (
int m = 0; m < Np_z; ++m)
195 if (m == k) {
continue; }
196 const int lower = m < k ? m : k;
197 const int upper = m < k ? k : m;
198 const int lower_point = lower*Np_y*Np_x + j*Np_x + i;
199 const int upper_point = upper*Np_y*Np_x + j*Np_x + i;
201 el_u, dof, neq, lower_point, state_lower);
203 el_u, dof, neq, upper_point, state_upper);
204 ctx.iflux.ComputeVolumeFlux(
205 ctx.gas, state_lower, state_upper,
206 elMetric_d + lower_point*dim*dim + 2*dim,
207 elMetric_d + upper_point*dim*dim + 2*dim, flux);
208 const mfem::real_t coefficient = Dhat2_d[m + Np_z*k];
209 for (
int q = 0; q < neq; ++q)
211 point_rate[q] += coefficient*flux[q];
217 point_rate, dof, neq, point, -1.0/elJac_d[point], el_dudt);
220 template<
typename ContextT>
221 MFEM_HOST_DEVICE
static void AssembleFacePointKernel(
const ContextT &ctx,
222 const mfem::real_t *u_face,
223 const mfem::real_t *nor_point,
224 const mfem::real_t w_minus,
225 const mfem::real_t w_plus,
227 mfem::real_t *rhs_face)
232 const int neq = ctx.num_equations;
233 for(
int q = 0; q < neq; ++q){
234 qMinus[q] = u_face[ctx.iface_idx(0, fp, q)];
235 qPlus[q] = u_face[ctx.iface_idx(1, fp, q)];
238 ctx.iflux.ComputeFaceFlux(ctx.gas, qMinus, qPlus, nor_point, point_flux);
240 for(
int q = 0; q < neq; ++q){
241 rhs_face[ctx.iface_idx(0, fp, q)] = -w_minus * point_flux[q];
242 rhs_face[ctx.iface_idx(1, fp, q)] = w_plus * point_flux[q];
247 template<
typename ContextT>
248 MFEM_HOST_DEVICE
static void AssembleElementFaceKernel(
const ContextT &ctx,
const mfem::real_t *u_face,
249 const mfem::real_t *nor_face,
const mfem::real_t *w_minus,
250 const mfem::real_t *w_plus, mfem::real_t *rhs_face)
252 const int nfp = ctx.num_face_points;
253 const int dim = ctx.dim;
254 for (
int fp = 0; fp < nfp; ++fp)
256 AssembleFacePointKernel(ctx, u_face, nor_face + fp*dim,
257 w_minus[fp], w_plus[fp], fp, rhs_face);
261 template<
typename ContextT>
262 MFEM_HOST_DEVICE
static void AssembleViscousFacePointKernel(
263 const ContextT &ctx,
const mfem::real_t *u_face,
264 const mfem::real_t *nor_point,
const mfem::real_t w_minus,
265 const mfem::real_t w_plus,
const mfem::real_t *dprim_face_x,
266 const mfem::real_t *dprim_face_y,
const mfem::real_t *dprim_face_z,
267 const mfem::real_t radius,
const int fp, mfem::real_t *rhs_face)
277 dprim_face_x, dprim_face_y, dprim_face_z};
278 const int neq = ctx.num_equations;
279 const int dim = ctx.dim;
281 for(
int q = 0; q < neq; ++q){
282 const int minus_index = ctx.iface_idx(0, fp, q);
283 const int plus_index = ctx.iface_idx(1, fp, q);
284 qMinus[q] = u_face[minus_index];
285 qPlus[q] = u_face[plus_index];
286 for(
int idim = 0; idim < dim; ++idim){
287 gradPrim_minus[idim][q] = dprim_face[idim][minus_index];
288 gradPrim_plus[idim][q] = dprim_face[idim][plus_index];
292 ctx.iflux.ComputeFaceFlux(ctx.gas, qMinus, qPlus, nor_point, point_flux);
294 NavierStokesFlux::ComputeViscousFluxKernel(
295 ctx.gas, qMinus, gradPrim_minus[0], gradPrim_minus[1],
296 gradPrim_minus[2], vflux_minus, ctx.axisymmetric,
297 ctx.axisymmetric ? radius : 0.0);
298 NavierStokesFlux::ComputeViscousFluxKernel(
299 ctx.gas, qPlus, gradPrim_plus[0], gradPrim_plus[1],
300 gradPrim_plus[2], vflux_plus, ctx.axisymmetric,
301 ctx.axisymmetric ? radius : 0.0);
303 for(
int q = 0; q < neq; ++q){
304 for(
int idim = 0; idim < dim; ++idim){
305 const mfem::real_t avg =
306 0.5*(vflux_minus[q][idim] + vflux_plus[q][idim]);
307 point_flux[q] -= nor_point[idim]*avg;
311 for(
int q = 0; q < neq; ++q){
312 rhs_face[ctx.iface_idx(0, fp, q)] = -w_minus * point_flux[q];
313 rhs_face[ctx.iface_idx(1, fp, q)] = w_plus * point_flux[q];
318 template<
typename ContextT>
319 MFEM_HOST_DEVICE
static void AssembleViscousElementFaceKernel(
const ContextT &ctx,
const mfem::real_t *u_face,
320 const mfem::real_t *nor_face,
const mfem::real_t *w_minus,
321 const mfem::real_t *w_plus,
const mfem::real_t *dprim_face_x,
322 const mfem::real_t *dprim_face_y,
const mfem::real_t*dprim_face_z,
323 const mfem::real_t *face_radius,
324 mfem::real_t *rhs_face)
326 const int nfp = ctx.num_face_points;
327 const int dim = ctx.dim;
328 for (
int fp = 0; fp < nfp; ++fp)
330 const mfem::real_t radius =
331 ctx.axisymmetric ? face_radius[fp] : 0.0;
332 AssembleViscousFacePointKernel(
333 ctx, u_face, nor_face + fp*dim, w_minus[fp], w_plus[fp],
334 dprim_face_x, dprim_face_y, dprim_face_z, radius, fp, rhs_face);
338 template<
typename ContextT>
339 MFEM_HOST_DEVICE
inline static void ComputeFVFluxesKernel(
const ContextT &ctx,
340 const mfem::real_t *el_u,
341 const mfem::real_t *elJac,
342 const mfem::real_t *el_metric_xi,
343 const mfem::real_t *el_metric_eta,
344 const mfem::real_t *el_metric_zeta,
345 mfem::real_t *el_dudt)
347 const int dim = ctx.dim;
348 const int Np_x = ctx.Np_x;
349 const int Np_y = ctx.Np_y;
350 const int Np_z = ctx.Np_z;
351 const int neq = ctx.num_equations;
352 const int npe = Np_x * Np_y * Np_z;
353 const mfem::real_t *qWgt = ctx.subcell_weights_d;
360 for(
int i = 0;i < npe*neq;i++)
363 for (
int k = 0; k < Np_z; k++)
365 for (
int j = 0; j < Np_y; j++)
367 for(
int q = 0; q < neq;q++){
370 int id1 = k * Np_y * Np_x + j * Np_x;
372 for (
int i = 0; i < Np_x - 1; i++)
376 const mfem::real_t *nor = el_metric_xi + id2*dim;
378 ctx.iflux.ComputeFaceFlux(ctx.gas, state1_local,
379 state2_local, nor, flux_num);
380 for(
int q = 0; q < neq;q++){
381 du_subcell[q] -= flux_num[q];
383 for(
int q = 0; q < neq;q++){
384 du_subcell[q] /= (elJac[id1] * qWgt[i]);
387 for(
int q = 0; q < neq;q++){
388 du_subcell[q] = flux_num[q];
390 for(
int q = 0;q < neq;q++){
391 state1_local[q] = state2_local[q];
395 for(
int q = 0;q < neq;q++){
396 du_subcell[q] /= (elJac[id1] * qWgt[Np_x-1]);
404 for (
int k = 0; k < Np_z; k++)
406 for (
int i = 0; i < Np_x; i++)
408 for(
int q = 0; q < neq;q++){
411 int id1 = k * Np_y * Np_x + i;
414 for (
int j = 0; j < Np_y - 1; j++)
416 int id2 = k * Np_y * Np_x + (j + 1) * Np_x + i;
419 const mfem::real_t *nor = el_metric_eta + id2*dim;
420 ctx.iflux.ComputeFaceFlux(ctx.gas, state1_local,
421 state2_local, nor, flux_num);
422 for(
int q = 0;q < neq;q++){
423 du_subcell[q] -= flux_num[q];
425 for(
int q = 0;q < neq;q++){
426 du_subcell[q] /= (elJac[id1] * qWgt[j]);
429 for(
int q = 0;q < neq;q++){
430 du_subcell[q] = flux_num[q];
431 state1_local[q] = state2_local[q];
435 for(
int q = 0;q < neq;q++){
436 du_subcell[q] /= (elJac[id1] * qWgt[Np_y - 1]);
443 for (
int j = 0; j < Np_y; j++)
445 for (
int i = 0; i < Np_x; i++)
447 for(
int q = 0; q < neq;q++){
450 int id1 = j * Np_x + i;
453 for (
int k = 0; k < Np_z - 1; k++)
455 int id2 = (k + 1) * Np_y * Np_x + j * Np_x + i;
458 const mfem::real_t *nor = el_metric_zeta + id2*dim;
459 ctx.iflux.ComputeFaceFlux(ctx.gas, state1_local,
460 state2_local, nor, flux_num);
461 for(
int q = 0;q < neq;q++){
462 du_subcell[q] -= flux_num[q];
464 for(
int q = 0;q < neq;q++){
465 du_subcell[q] /= (elJac[id1] * qWgt[k]);
469 for(
int q = 0;q < neq;q++){
470 du_subcell[q] = flux_num[q];
471 state1_local[q] = state2_local[q];
475 for(
int q = 0;q < neq;q++){
476 du_subcell[q] /= (elJac[id1] * qWgt[Np_z - 1]);
486 template<
typename ContextType>
487 MFEM_HOST_DEVICE
inline
488 static void AssembleViscousVolumePointKernel(
489 const ContextType &ctx,
const mfem::real_t *el_u,
490 const mfem::real_t *elJac_d,
const mfem::real_t *elMetric_d,
491 const mfem::real_t *elRadius_d,
492 const mfem::real_t *el_gradprim_x,
493 const mfem::real_t *el_gradprim_y,
494 const mfem::real_t *el_gradprim_z,
495 const int point, mfem::real_t *el_dudt)
497 const int Np_x = ctx.Np_x;
498 const int Np_y = ctx.Np_y;
499 const int Np_z = ctx.Np_z;
500 const int dim = ctx.dim;
501 const int neq = ctx.num_equations;
502 const int dof = ctx.ndof_scalar_el;
503 const mfem::real_t *Dhat_d = ctx.Dhat_d;
504 const int i = point % Np_x;
505 const int j = (point / Np_x) % Np_y;
506 const int k = point / (Np_x*Np_y);
515 for (
int l = 0; l < Np_x; ++l)
517 const int sample = k*Np_y*Np_x + j*Np_x + l;
518 const mfem::real_t coefficient = Dhat_d[l + Np_x*i];
521 el_gradprim_x, el_gradprim_y, el_gradprim_z, dim, dof, neq,
522 sample, dqx, dqy, dqz);
523 Theseus::NavierStokesFlux::compute_ref_viscous_flux(
524 ctx.gas, dim, neq, state, dqx, dqy, dqz,
525 elMetric_d + sample*dim*dim, f_ref, ctx.axisymmetric,
526 ctx.axisymmetric ? elRadius_d[sample] : 0.0);
527 for (
int q = 0; q < neq; ++q)
529 dU_viscous[q] += coefficient*f_ref[q];
535 for (
int l = 0; l < Np_y; ++l)
537 const int sample = k*Np_y*Np_x + l*Np_x + i;
538 const mfem::real_t coefficient = Dhat_d[l + Np_y*j];
541 el_gradprim_x, el_gradprim_y, el_gradprim_z, dim, dof, neq,
542 sample, dqx, dqy, dqz);
543 Theseus::NavierStokesFlux::compute_ref_viscous_flux(
544 ctx.gas, dim, neq, state, dqx, dqy, dqz,
545 elMetric_d + sample*dim*dim + dim, f_ref,
547 ctx.axisymmetric ? elRadius_d[sample] : 0.0);
548 for (
int q = 0; q < neq; ++q)
550 dU_viscous[q] += coefficient*f_ref[q];
557 for (
int l = 0; l < Np_z; ++l)
559 const int sample = l*Np_y*Np_x + j*Np_x + i;
560 const mfem::real_t coefficient = Dhat_d[l + Np_z*k];
563 el_gradprim_x, el_gradprim_y, el_gradprim_z, dim, dof, neq,
564 sample, dqx, dqy, dqz);
565 Theseus::NavierStokesFlux::compute_ref_viscous_flux(
566 ctx.gas, dim, neq, state, dqx, dqy, dqz,
567 elMetric_d + sample*dim*dim + 2*dim, f_ref,
569 ctx.axisymmetric ? elRadius_d[sample] : 0.0);
570 for (
int q = 0; q < neq; ++q)
572 dU_viscous[q] += coefficient*f_ref[q];
578 dU_viscous, dof, neq, point, 1.0/elJac_d[point], el_dudt);
579 if (ctx.axisymmetric)
583 el_gradprim_x, el_gradprim_y, el_gradprim_z, dim, dof, neq,
584 point, dqx, dqy, dqz);
587 ctx.gas, state, dqx, dqy, dqz, elRadius_d[point], source))
590 ctx, el_u, el_gradprim_x, el_gradprim_y, el_gradprim_z,
591 elRadius_d, elJac_d, elMetric_d, point, source);
597 template<
typename ContextType>
598 MFEM_HOST_DEVICE
inline
599 static void AssembleViscousElementVolumeKernel(
const ContextType &ctx,
600 const mfem::real_t *el_u,
601 const mfem::real_t *elJac_d,
602 const mfem::real_t *elMetric_d,
603 const mfem::real_t *elRadius_d,
604 const mfem::real_t *el_gradprim_x,
605 const mfem::real_t *el_gradprim_y,
606 const mfem::real_t *el_gradprim_z,
607 mfem::real_t *el_dudt)
609 const int Np_x = ctx.Np_x;
610 const int Np_y = ctx.Np_y;
611 const int Np_z = ctx.Np_z;
612 const int dim = ctx.dim;
613 const int neq = ctx.num_equations;
614 const int dof = Np_x * Np_y * Np_z;
615 const mfem::real_t *Dhat_d = ctx.Dhat_d;
627 for (
int k = 0; k < Np_z; ++k)
629 for (
int j = 0; j < Np_y; ++j)
631 for (
int i = 0; i < Np_x; ++i)
633 const int id1 = k * Np_y * Np_x + j * Np_x + i;
634 const mfem::real_t J = elJac_d[id1];
635 const mfem::real_t jInv = 1.0/J;
640 for (
int l = 0; l < Np_x; ++l)
642 const int idl = k * Np_y * Np_x + j * Np_x + l;
643 const mfem::real_t c = Dhat_d[l + Np_x * i];
647 el_gradprim_z, dim, dof, neq, idl,
650 const mfem::real_t *adj_row = elMetric_d + idl * dim * dim + 0 * dim;
651 Theseus::NavierStokesFlux::compute_ref_viscous_flux(
652 ctx.gas, dim, neq, state, dqx, dqy, dqz, adj_row,
653 f_ref, ctx.axisymmetric,
654 ctx.axisymmetric ? elRadius_d[idl] : 0.0);
655 for (
int q = 0; q < neq; ++q)
657 dU_viscous[q] += c * f_ref[q];
664 for (
int l = 0; l < Np_y; ++l)
666 const int idl = k * Np_y * Np_x + l * Np_x + i;
667 const mfem::real_t c = Dhat_d[l + Np_y * j];
671 el_gradprim_z, dim, dof, neq, idl,
674 const mfem::real_t *adj_row = elMetric_d + idl * dim * dim + 1 * dim;
675 Theseus::NavierStokesFlux::compute_ref_viscous_flux(
676 ctx.gas, dim, neq, state, dqx, dqy, dqz, adj_row,
677 f_ref, ctx.axisymmetric,
678 ctx.axisymmetric ? elRadius_d[idl] : 0.0);
680 for (
int q = 0; q < neq; ++q)
682 dU_viscous[q] += c * f_ref[q];
690 for (
int l = 0; l < Np_z; ++l)
692 const int idl = l * Np_y * Np_x + j * Np_x + i;
693 const mfem::real_t c = Dhat_d[l + Np_z * k];
697 el_gradprim_z, dim, dof, neq, idl,
700 const mfem::real_t *adj_row = elMetric_d + idl * dim * dim + 2 * dim;
701 Theseus::NavierStokesFlux::compute_ref_viscous_flux(
702 ctx.gas, dim, neq, state, dqx, dqy, dqz, adj_row,
703 f_ref, ctx.axisymmetric,
704 ctx.axisymmetric ? elRadius_d[idl] : 0.0);
706 for (
int q = 0; q < neq; ++q)
708 dU_viscous[q] += c * f_ref[q];
713 if (ctx.axisymmetric)
717 el_gradprim_x, el_gradprim_y, el_gradprim_z, dim,
718 dof, neq, id1, dqx, dqy, dqz);
721 ctx.gas, state, dqx, dqy, dqz,
722 elRadius_d[id1], source))
725 ctx, el_u, el_gradprim_x, el_gradprim_y,
726 el_gradprim_z, elRadius_d, elJac_d, elMetric_d,
737 template <
typename ContextType>
738 MFEM_HOST_DEVICE
inline
739 static void AssembleGradVolumePointKernel(
740 const ContextType &ctx,
const mfem::real_t *el_u,
741 const mfem::real_t *elJac_d,
const mfem::real_t *elMetric_d,
744 const int Np_x = ctx.Np_x;
745 const int Np_y = ctx.Np_y;
746 const int neq = ctx.num_equations;
747 const int dim = ctx.dim;
748 const int dof = ctx.ndof_scalar_el;
749 const mfem::real_t *D_d = ctx.D_d;
751 const int i = point % Np_x;
752 const int j = (point / Np_x) % Np_y;
753 const int k = point / (Np_x * Np_y);
759 for (
int l = 0; l < Np_x; ++l)
761 const int sample = k*Np_y*Np_x + j*Np_x + l;
762 const mfem::real_t coefficient = D_d[l + Np_x*i];
763 for (
int q = 0; q < neq; ++q)
765 dudxi[q] += el_u[sample + q*dof] * coefficient;
771 for (
int l = 0; l < Np_y; ++l)
773 const int sample = k*Np_y*Np_x + l*Np_x + i;
774 const mfem::real_t coefficient = D_d[l + Np_y*j];
775 for (
int q = 0; q < neq; ++q)
777 dudeta[q] += el_u[sample + q*dof] * coefficient;
784 for (
int l = 0; l < ctx.Np_z; ++l)
786 const int sample = l*Np_y*Np_x + j*Np_x + i;
787 const mfem::real_t coefficient = D_d[l + ctx.Np_z*k];
788 for (
int q = 0; q < neq; ++q)
790 dudzeta[q] += el_u[sample + q*dof] * coefficient;
795 const mfem::real_t invJ = 1.0 / elJac_d[point];
796 const mfem::real_t *adj = elMetric_d + point*dim*dim;
797 for (
int q = 0; q < neq; ++q)
801 el_grad_u[0][point + q*dof] = invJ*dudxi[q]*adj[0];
805 el_grad_u[0][point + q*dof] =
806 invJ*(dudxi[q]*adj[0] + dudeta[q]*adj[2]);
807 el_grad_u[1][point + q*dof] =
808 invJ*(dudxi[q]*adj[1] + dudeta[q]*adj[3]);
812 el_grad_u[0][point + q*dof] =
813 invJ*(dudxi[q]*adj[0] + dudeta[q]*adj[3] +
815 el_grad_u[1][point + q*dof] =
816 invJ*(dudxi[q]*adj[1] + dudeta[q]*adj[4] +
818 el_grad_u[2][point + q*dof] =
819 invJ*(dudxi[q]*adj[2] + dudeta[q]*adj[5] +
825 template <
typename ContextType>
826 MFEM_HOST_DEVICE
inline
827 static void AssembleGradElementVolumeKernel(
const ContextType &ctx,
828 const mfem::real_t *el_u,
829 const mfem::real_t *elJac_d,
830 const mfem::real_t *elMetric_d,
833 const int Np_x = ctx.Np_x;
834 const int Np_y = ctx.Np_y;
835 const int Np_z = ctx.Np_z;
836 const int neq = ctx.num_equations;
837 const int dim = ctx.dim;
838 const int dof = Np_x * Np_y * Np_z;
839 const mfem::real_t *D_d = ctx.D_d;
846 for (
int i = 0; i < Np_x; ++i)
850 for (
int q = 0; q < neq; ++q)
855 for (
int l = 0; l < Np_x; ++l)
858 const mfem::real_t c_xi = D_d[i*Np_x + l];
860 for (
int q = 0; q < neq; ++q)
862 dudxi[q] += el_u[id_x + q * dof] * c_xi;
866 const mfem::real_t invJ = 1.0 / elJac_d[id];
867 const mfem::real_t *adj = elMetric_d +
id * dim * dim;
869 for (
int q = 0; q < neq; ++q)
871 el_grad_u[0][
id + q * dof] = invJ * (dudxi[q] * adj[0]);
878 for (
int j = 0; j < Np_y; ++j)
880 for (
int i = 0; i < Np_x; ++i)
882 const int id = j * Np_x + i;
884 for (
int q = 0; q < neq; ++q)
891 for (
int l = 0; l < Np_x; ++l)
893 const int id_x = j * Np_x + l;
894 const int id_y = l * Np_x + i;
896 const mfem::real_t c_xi = D_d[l + Np_x * i];
897 const mfem::real_t c_eta = D_d[l + Np_x * j];
899 for (
int q = 0; q < neq; ++q)
901 dudxi[q] += el_u[id_x + q * dof] * c_xi;
902 dudeta[q] += el_u[id_y + q * dof] * c_eta;
906 const mfem::real_t invJ = 1.0 / elJac_d[id];
907 const mfem::real_t *adj = elMetric_d +
id * dim * dim;
912 for (
int q = 0; q < neq; ++q)
914 el_grad_u[0][
id + q * dof] = invJ * (dudxi[q] * adj[0] + dudeta[q] * adj[2]);
915 el_grad_u[1][
id + q * dof] = invJ * (dudxi[q] * adj[1] + dudeta[q] * adj[3]);
919 }
else if (dim == 3) {
925 for (
int k = 0; k < Np_z; ++k)
927 for (
int j = 0; j < Np_y; ++j)
929 for (
int i = 0; i < Np_x; ++i)
931 const int id = k * Np_x * Np_y + j * Np_x + i;
933 for (
int q = 0; q < neq; ++q)
941 for (
int l = 0; l < Np_x; ++l)
943 const int id_x = k * Np_x * Np_y + j * Np_x + l;
944 const int id_y = k * Np_x * Np_y + l * Np_x + i;
945 const int id_z = l * Np_x * Np_y + j * Np_x + i;
946 const mfem::real_t c_xi = D_d[l + Np_x * i];
947 const mfem::real_t c_eta = D_d[l + Np_x * j];
948 const mfem::real_t c_zeta = D_d[l + Np_x * k];
949 for (
int q = 0; q < neq; ++q)
951 dudxi[q] += el_u[id_x + q * dof] * c_xi;
952 dudeta[q] += el_u[id_y + q * dof] * c_eta;
953 dudzeta[q] += el_u[id_z + q * dof] * c_zeta;
957 const mfem::real_t invJ = 1.0 / elJac_d[id];
958 const mfem::real_t *adj = elMetric_d +
id * dim * dim;
964 for (
int q = 0; q < neq; ++q)
966 el_grad_u[0][
id + q * dof] = invJ * (dudxi[q] * adj[0] +
968 dudzeta[q] * adj[6]);
970 el_grad_u[1][
id + q * dof] = invJ * (dudxi[q] * adj[1] +
972 dudzeta[q] * adj[7]);
974 el_grad_u[2][
id + q * dof] = invJ * (dudxi[q] * adj[2] +
976 dudzeta[q] * adj[8]);
984 template <
typename ContextT>
985 MFEM_HOST_DEVICE
inline
986 static void AssembleGradInteriorFacePointKernel(
988 const mfem::real_t *u_face,
989 const mfem::real_t *nor_point,
990 const mfem::real_t w_minus,
991 const mfem::real_t w_plus,
995 const int neq = ctx.num_equations;
996 const int dim = ctx.dim;
1000 for (
int q = 0; q < neq; ++q)
1002 jump[q] = mfem::real_t(0.5) *
1003 (u_face[ctx.iface_idx(1, fp, q)] -
1004 u_face[ctx.iface_idx(0, fp, q)]);
1007 for (
int idim = 0; idim < dim; ++idim){
1008 mfem::real_t *rhs_d = rhs_face[idim];
1009 const mfem::real_t n_d = nor_point[idim];
1010 for (
int q = 0; q < neq; ++q)
1012 const mfem::real_t f_d = jump[q]*n_d;
1013 rhs_d[ctx.iface_idx(0, fp, q)] = w_minus * f_d;
1014 rhs_d[ctx.iface_idx(1, fp, q)] = w_plus * f_d;
1019 template <
typename ContextT>
1020 MFEM_HOST_DEVICE
inline
1021 static void AssembleGradInteriorFaceKernel(
const ContextT &ctx,
1022 const mfem::real_t *u_face,
1023 const mfem::real_t *nor_face,
1024 const mfem::real_t *w_minus,
1025 const mfem::real_t *w_plus,
1028 const int nfp = ctx.num_face_points;
1029 const int dim = ctx.dim;
1031 for (
int fp = 0; fp < nfp; ++fp)
1033 AssembleGradInteriorFacePointKernel(
1034 ctx, u_face, nor_face + fp*dim, w_minus[fp], w_plus[fp], fp,
1039 template <
typename DeviceCacheT>
1040 MFEM_HOST_DEVICE
inline
1041 static void AssembleGradBoundaryPointKernel(
const DeviceCacheT &dc,
1043 const mfem::real_t *u_face,
1044 const mfem::real_t *nor_point,
1045 const mfem::real_t scale,
1049 const int dim = dc.dim;
1050 const int nfp = dc.num_face_points;
1051 const int neq = dc.num_equations;
1061 for(
int idim = 0;idim < dim;idim++){
1062 for(
int q = 0;q < neq;q++){
1063 flux_dir[q] = fluxN[q]*nor_point[idim];