12 #include "xtensor-python/pyarray.hpp"
14 namespace py = pybind11;
18 template<
int nSpace,
int nP,
int nQ,
int nEBQ>
29 template<
class CompKernelType,
31 int nQuadraturePoints_element,
32 int nDOF_mesh_trial_element,
33 int nDOF_trial_element,
34 int nDOF_test_element,
35 int nQuadraturePoints_elementBoundary
58 const int& isDOFBoundary,
59 const int& isDiffusiveFluxBoundary,
60 const double n[nSpace],
63 const double& bc_flux,
65 const double grad_potential[nSpace],
67 const double& penalty,
70 double diffusiveVelocityComponent_I;
73 if (isDiffusiveFluxBoundary == 1)
77 else if (isDOFBoundary == 1)
81 for (
int I = 0; I < nSpace; I++)
83 diffusiveVelocityComponent_I = 0.0;
84 for (
int m = rowptr[I]; m < rowptr[I+1]; m++)
86 diffusiveVelocityComponent_I -= a[m] * grad_potential[colind[m]];
87 max_a = fmax(max_a, a[m]);
89 flux += diffusiveVelocityComponent_I *
n[I];
91 penaltyFlux = max_a * penalty * (
u - bc_u);
96 std::cerr <<
"warning, diffusion term with no boundary condition set, setting diffusive flux to 0.0" << std::endl;
104 const int& isDOFBoundary,
105 const int& isDiffusiveFluxBoundary,
106 const double n[nSpace],
109 const double grad_v[nSpace],
110 const double& penalty)
115 if ((isDiffusiveFluxBoundary == 0) && (isDOFBoundary == 1))
117 for (
int I = 0; I < nSpace; I++)
120 for (
int m = rowptr[I]; m < rowptr[I + 1]; m++)
122 dvel_I -= a[m] * grad_v[colind[m]];
123 max_a = fmax(max_a, a[m]);
125 tmp += dvel_I *
n[I];
127 tmp += max_a * penalty *
v;
135 const double dH[nSpace],
144 for(
int I = 0; I < nSpace; I++)
145 nrm_v += dH[I] * dH[I];
148 oneByAbsdt = fabs(dmt);
149 tau = 1.0 / (2.0 * nrm_v / h + oneByAbsdt + 1.0e-8);
154 const double G[nSpace*nSpace],
156 const double Ai[nSpace],
161 for (
int I = 0; I < nSpace; I++)
162 for (
int J = 0; J < nSpace; J++)
163 v_d_Gv += Ai[I] * G[I * nSpace + J] * Ai[J];
164 tau_v = 1.0 / sqrt(Ct_sge * A0 * A0 + v_d_Gv + 1.0e-8);
169 const double& elementDiameter,
170 const double& strong_residual,
171 const double grad_u[nSpace],
180 for (
int I = 0; I < nSpace; I++)
181 n_grad_u += grad_u[I] * grad_u[I];
182 num = shockCapturingDiffusion * 0.5 * h * fabs(strong_residual);
183 den = sqrt(n_grad_u) + 1.0e-8;
189 const int& isFluxBoundary_u,
190 const double n[nSpace],
192 const double& bc_flux_u,
194 const double velocity[nSpace],
199 for (
int I = 0; I < nSpace; I++)
200 flow +=
n[I] * velocity[I];
201 if (isDOFBoundary_u == 1)
214 else if (isFluxBoundary_u == 1)
235 const int& isFluxBoundary_u,
236 const double n[nSpace],
237 const double velocity[nSpace],
241 for (
int I = 0; I < nSpace; I++)
243 flow +=
n[I] * velocity[I];
247 if (isDOFBoundary_u == 1)
258 else if (isFluxBoundary_u == 1)
273 double* embeddedBoundary_normal,
276 const double grad_u[nSpace],
285 double outward_normal[2]={0.0,0.0};
286 for (
int I=0;I<nSpace;I++)
287 outward_normal[I] = -embeddedBoundary_normal[I];
289 double D_s =
gf_s.D(0.,0.);
292 ham -= D_s * a * (outward_normal[0] * grad_u[0] + outward_normal[1] * grad_u[1]);
293 dham[0] -= D_s * a * outward_normal[0];
294 dham[1] -= D_s * a * outward_normal[1];
297 r += D_s*a*embeddedBoundary_penalty * (
u - u_s);
298 dr += D_s*a*embeddedBoundary_penalty;
301 f[0] += D_s * a * outward_normal[0] * (
u - u_s);
302 f[1] += D_s * a * outward_normal[1] * (
u - u_s);
303 df[0] += D_s * a * outward_normal[0];
304 df[1] += D_s * a * outward_normal[1];
308 xt::pyarray<double>& mesh_trial_ref,
309 xt::pyarray<double>& mesh_grad_trial_ref,
310 xt::pyarray<double>& mesh_dof,
311 xt::pyarray<int>& mesh_l2g,
312 xt::pyarray<double>& x_ref,
313 xt::pyarray<double>& dV_ref,
314 xt::pyarray<double>& u_trial_ref,
315 xt::pyarray<double>& u_grad_trial_ref,
316 xt::pyarray<double>& u_test_ref,
317 xt::pyarray<double>& u_grad_test_ref,
318 xt::pyarray<double>& elementDiameter,
319 xt::pyarray<double>& elementBoundaryDiameter,
320 xt::pyarray<double>& nodeDiametersArray,
321 xt::pyarray<double>& cfl,
327 xt::pyarray<double>& mesh_trial_trace_ref,
328 xt::pyarray<double>& mesh_grad_trial_trace_ref,
329 xt::pyarray<double>& dS_ref,
330 xt::pyarray<double>& u_trial_trace_ref,
331 xt::pyarray<double>& u_grad_trial_trace_ref,
332 xt::pyarray<double>& u_test_trace_ref,
333 xt::pyarray<double>& u_grad_test_trace_ref,
334 xt::pyarray<double>& normal_ref,
335 xt::pyarray<double>& boundaryJac_ref,
337 int nElements_global,
338 int nElementBoundaries_owned,
339 xt::pyarray<int>& u_l2g,
340 xt::pyarray<double>& u_dof,
341 xt::pyarray<int>& sd_rowptr,
342 xt::pyarray<int>& sd_colind,
343 xt::pyarray<double>& q_a,
344 xt::pyarray<double>& q_v,
345 xt::pyarray<double>& q_r,
346 int lag_shockCapturingDiffusion,
347 double shockCapturingDiffusion,
348 xt::pyarray<double>& q_numDiff_u,
349 xt::pyarray<double>& q_numDiff_u_last,
352 xt::pyarray<double>& elementResidual_u,
353 int nExteriorElementBoundaries_global,
354 xt::pyarray<int>& exteriorElementBoundariesArray,
355 xt::pyarray<int>& elementBoundariesArray,
356 xt::pyarray<int>& elementBoundaryElementsArray,
357 xt::pyarray<int>& elementBoundaryLocalElementBoundariesArray,
358 xt::pyarray<double>& element_u,
360 const bool embeddedBoundary,
361 const double embeddedBoundary_penalty,
362 xt::pyarray<double>& embeddedBoundary_normal_q,
363 xt::pyarray<double>& embeddedBoundary_u_q,
364 bool& element_active,
367 for (
int i = 0; i < nDOF_test_element; i++)
369 elementResidual_u.data()[i] = 0.0;
372 for (
int k = 0; k < nQuadraturePoints_element; k++)
376 int eN_k = eN * nQuadraturePoints_element + k;
377 int eN_k_3d = eN_k*3;
380 double grad_u[nSpace];
385 double f_s[nSpace]={0.,0.};
386 double df_s[nSpace]={0.,0.};
388 double dham_s[nSpace]={0.,0.};
391 double pdeResidual_u = 0.0;
392 double Lstar_u[nDOF_test_element];
393 double subgridError_u = 0.0;
397 double numDiff0 = 0.0;
398 double numDiff1 = 0.0;
403 double jac[nSpace*nSpace];
405 double jacInv[nSpace*nSpace];
406 double u_grad_trial[nDOF_trial_element * nSpace];
407 double u_test_dV[nDOF_trial_element];
408 double u_grad_test_dV[nDOF_test_element * nSpace];
413 double G[nSpace * nSpace];
419 ck.calculateMapping_element(eN,
423 mesh_trial_ref.data(),
424 mesh_grad_trial_ref.data(),
431 ck.calculateH_element(eN,
433 nodeDiametersArray.data(),
435 mesh_trial_ref.data(),
438 dV = fabs(jacDet) * dV_ref.data()[k];
440 ck.calculateG(jacInv, G, G_dd_G, tr_G);
442 ck.gradTrialFromRef(&u_grad_trial_ref.data()[k * nDOF_trial_element * nSpace], jacInv, u_grad_trial);
444 ck.valFromElementDOF(element_u.data(), &u_trial_ref.data()[k * nDOF_trial_element],
u);
446 ck.gradFromElementDOF(element_u.data(), u_grad_trial, grad_u);
448 for (
int j = 0; j < nDOF_trial_element; j++)
450 u_test_dV[j] = u_test_ref.data()[k * nDOF_trial_element + j] * dV;
451 for (
int I = 0; I < nSpace; I++)
453 u_grad_test_dV[j * nSpace + I] = u_grad_trial[j * nSpace + I] *dV;
461 a = &q_a.data()[eN_k * sd_rowptr.data()[nSpace]];
462 r = q_r.data()[eN_k];
463 for (
int I = 0; I < nSpace; I++)
465 f[I] = q_v.data()[eN_k * nSpace + I] *
u;
466 df[I] = q_v.data()[eN_k * nSpace + I];
468 const double H_s =
gf_s.H(0.,0.);
469 const double D_s =
gf_s.D(0.,0.);
470 if ( H_s != 0.0 || D_s != 0.0)
477 double level_set_normal[nSpace];
479 double norm_exact=0.0,norm_cut=0.0;
480 for (
int I=0;I<nSpace;I++)
482 sign += embeddedBoundary_normal_q.data()[eN_k_3d+I]*
gf_s.get_normal()[I];
483 level_set_normal[I] =
gf_s.get_normal()[I];
484 norm_cut += level_set_normal[I]*level_set_normal[I];
485 norm_exact += embeddedBoundary_normal_q.data()[eN_k_3d+I]*embeddedBoundary_normal_q.data()[eN_k_3d+I];
487 assert(std::fabs(1.0-norm_cut) < 1.0e-8);
488 assert(std::fabs(1.0-norm_exact) < 1.0e-8);
490 for (
int I=0;I<nSpace;I++)
491 level_set_normal[I]*=-1.0;
495 embeddedBoundary_u_q.data()[eN_k],
531 pdeResidual_u =
ck.Advection_strong(
df, grad_u) +
ck.Reaction_strong(
r);
533 for (
int i = 0; i < nDOF_test_element; i++)
537 int i_nSpace = i * nSpace;
538 Lstar_u[i] =
ck.Advection_adjoint(
df, &u_grad_test_dV[i_nSpace]);
549 tau = useMetrics * tau1 + (1.0 - useMetrics) * tau0;
551 subgridError_u = -tau * pdeResidual_u;
555 ck.calculateNumericalDiffusion(shockCapturingDiffusion, elementDiameter.data()[eN], pdeResidual_u, grad_u, numDiff0);
556 ck.calculateNumericalDiffusion(shockCapturingDiffusion, sc_uref, sc_alpha, G, G_dd_G, pdeResidual_u, grad_u, numDiff1);
557 q_numDiff_u.data()[eN_k] = useMetrics * numDiff1 + (1.0 - useMetrics) * numDiff0;
561 for (
int i = 0; i < nDOF_test_element; i++)
563 int i_nSpace=i*nSpace;
564 elementResidual_u.data()[i] += H_s*(
ck.Advection_weak(
f, &u_grad_test_dV[i_nSpace]) +
565 ck.Diffusion_weak(sd_rowptr.data(), sd_colind.data(), a, grad_u, &u_grad_test_dV[i_nSpace]) +
566 ck.Reaction_weak(
r, u_test_dV[i]) +
567 ck.SubgridError(subgridError_u, Lstar_u[i]) +
568 ck.NumericalDiffusion(q_numDiff_u_last.data()[eN_k], grad_u, &u_grad_test_dV[i_nSpace]));
569 if (embeddedBoundary)
571 elementResidual_u.data()[i] += (
ck.Advection_weak(f_s,&u_grad_test_dV[i_nSpace]) +
572 ck.Reaction_weak(r_s,u_test_dV[i]) +
573 ck.Hamiltonian_weak(ham_s,u_test_dV[i]));
581 xt::pyarray<double>& mesh_trial_ref = args.
array<
double>(
"mesh_trial_ref");
582 xt::pyarray<double>& mesh_grad_trial_ref = args.
array<
double>(
"mesh_grad_trial_ref");
583 xt::pyarray<double>& mesh_dof = args.
array<
double>(
"mesh_dof");
584 xt::pyarray<int>& mesh_l2g = args.
array<
int>(
"mesh_l2g");
585 xt::pyarray<double>& dV_ref = args.
array<
double>(
"dV_ref");
586 xt::pyarray<double>& u_trial_ref = args.
array<
double>(
"u_trial_ref");
587 xt::pyarray<double>& u_grad_trial_ref = args.
array<
double>(
"u_grad_trial_ref");
588 xt::pyarray<double>& u_test_ref = args.
array<
double>(
"u_test_ref");
589 xt::pyarray<double>& u_grad_test_ref = args.
array<
double>(
"u_grad_test_ref");
590 xt::pyarray<double>& elementDiameter = args.
array<
double>(
"elementDiameter");
591 xt::pyarray<double>& cfl = args.
array<
double>(
"cfl");
592 double Ct_sge = args.
scalar<
double>(
"Ct_sge");
593 double sc_uref = args.
scalar<
double>(
"sc_uref");
594 double sc_alpha = args.
scalar<
double>(
"sc_alpha");
595 double useMetrics = args.
scalar<
double>(
"useMetrics");
596 xt::pyarray<double>& mesh_trial_trace_ref = args.
array<
double>(
"mesh_trial_trace_ref");
597 xt::pyarray<double>& mesh_grad_trial_trace_ref = args.
array<
double>(
"mesh_grad_trial_trace_ref");
598 xt::pyarray<double>& dS_ref = args.
array<
double>(
"dS_ref");
599 xt::pyarray<double>& u_trial_trace_ref = args.
array<
double>(
"u_trial_trace_ref");
600 xt::pyarray<double>& u_grad_trial_trace_ref = args.
array<
double>(
"u_grad_trial_trace_ref");
601 xt::pyarray<double>& u_test_trace_ref = args.
array<
double>(
"u_test_trace_ref");
602 xt::pyarray<double>& u_grad_test_trace_ref = args.
array<
double>(
"u_grad_test_trace_ref");
603 xt::pyarray<double>& normal_ref = args.
array<
double>(
"normal_ref");
604 xt::pyarray<double>& boundaryJac_ref = args.
array<
double>(
"boundaryJac_ref");
605 int nElements_global = args.
scalar<
int>(
"nElements_global");
606 xt::pyarray<int>& u_l2g = args.
array<
int>(
"u_l2g");
607 xt::pyarray<double>& u_dof = args.
array<
double>(
"u_dof");
608 xt::pyarray<int>& sd_rowptr = args.
array<
int>(
"sd_rowptr");
609 xt::pyarray<int>& sd_colind = args.
array<
int>(
"sd_colind");
610 xt::pyarray<double>& q_a = args.
array<
double>(
"q_a");
611 xt::pyarray<double>& q_v = args.
array<
double>(
"q_v");
612 xt::pyarray<double>& q_r = args.
array<
double>(
"q_r");
613 int lag_shockCapturing = args.
scalar<
int>(
"lag_shockCapturing");
614 double shockCapturingDiffusion = args.
scalar<
double>(
"shockCapturingDiffusion");
615 xt::pyarray<double>& q_numDiff_u = args.
array<
double>(
"q_numDiff_u");
616 xt::pyarray<double>& q_numDiff_u_last = args.
array<
double>(
"q_numDiff_u_last");
617 int offset_u = args.
scalar<
int>(
"offset_u");
618 int stride_u = args.
scalar<
int>(
"stride_u");
619 xt::pyarray<double>& globalResidual = args.
array<
double>(
"globalResidual");
620 int nExteriorElementBoundaries_global = args.
scalar<
int>(
"nExteriorElementBoundaries_global");
621 xt::pyarray<int>& exteriorElementBoundariesArray = args.
array<
int>(
"exteriorElementBoundariesArray");
622 xt::pyarray<int>& elementBoundaryElementsArray = args.
array<
int>(
"elementBoundaryElementsArray");
623 xt::pyarray<int>& elementBoundaryLocalElementBoundariesArray = args.
array<
int>(
"elementBoundaryLocalElementBoundariesArray");
624 xt::pyarray<double>& ebqe_a = args.
array<
double>(
"ebqe_a");
625 xt::pyarray<double>& ebqe_v = args.
array<
double>(
"ebqe_v");
626 xt::pyarray<int>& isDOFBoundary_u = args.
array<
int>(
"isDOFBoundary_u");
627 xt::pyarray<double>& ebqe_bc_u_ext = args.
array<
double>(
"ebqe_bc_u_ext");
628 xt::pyarray<int>& isDiffusiveFluxBoundary_u = args.
array<
int>(
"isDiffusiveFluxBoundary_u");
629 xt::pyarray<int>& isAdvectiveFluxBoundary_u = args.
array<
int>(
"isAdvectiveFluxBoundary_u");
630 xt::pyarray<double>& ebqe_bc_flux_u_ext = args.
array<
double>(
"ebqe_bc_flux_u_ext");
631 xt::pyarray<double>& ebqe_bc_advectiveFlux_u_ext = args.
array<
double>(
"ebqe_bc_advectiveFlux_u_ext");
632 xt::pyarray<double>& ebqe_penalty_ext = args.
array<
double>(
"ebqe_penalty_ext");
633 const bool embeddedBoundary = args.
scalar<
int>(
"embeddedBoundary");
634 const double embeddedBoundary_penalty = args.
scalar<
double>(
"embeddedBoundary_penalty");
635 const double embeddedBoundary_ghost_penalty = args.
scalar<
double>(
"embedded_ghost_penalty");
636 xt::pyarray<double>& embeddedBoundary_sdf_nodes = args.
array<
double>(
"embeddedBoundary_sdf_nodes");
637 xt::pyarray<double>& embeddedBoundary_sdf_q = args.
array<
double>(
"embeddedBoundary_sdf_q");
638 xt::pyarray<double>& embeddedBoundary_normal_q = args.
array<
double>(
"embeddedBoundary_normal_q");
639 xt::pyarray<double>& embeddedBoundary_u_q = args.
array<
double>(
"embeddedBoundary_u_q");
640 xt::pyarray<double>& isActiveDOF = args.
array<
double>(
"isActiveDOF");
641 const double eb_adjoint_sigma = args.
scalar<
double>(
"eb_adjoint_sigma");
642 xt::pyarray<double>& x_ref = args.
array<
double>(
"x_ref");
643 xt::pyarray<int>& elementBoundariesArray = args.
array<
int>(
"elementBoundariesArray");
644 const int nElementBoundaries_owned = args.
scalar<
int>(
"nElementBoundaries_owned");
645 xt::pyarray<double>& elementBoundaryDiameter = args.
array<
double>(
"elementBoundaryDiameter");
646 xt::pyarray<double>& nodeDiametersArray = args.
array<
double>(
"nodeDiametersArray");
649 gf_s.useExact =
true;
666 for(
int eN=0;eN<nElements_global;eN++)
670 auto elementResidual_u = xt::pyarray<double>::from_shape({nDOF_test_element});
671 auto element_u = xt::pyarray<double>::from_shape({nDOF_trial_element});
672 bool element_active=
false;
674 for (
int i=0;i<nDOF_test_element;i++)
676 register int eN_i=eN*nDOF_test_element+i;
677 element_u.data()[i] = u_dof.data()[u_l2g.data()[eN_i]];
679 double element_phi_s[nDOF_mesh_trial_element];
680 for (
int j=0;j<nDOF_mesh_trial_element;j++)
682 register int eN_j = eN*nDOF_mesh_trial_element+j;
683 element_phi_s[j] = embeddedBoundary_sdf_nodes.data()[u_l2g.data()[eN_j]];
685 double element_nodes[nDOF_mesh_trial_element*3];
686 for (
int i=0;i<nDOF_mesh_trial_element;i++)
688 register int eN_i=eN*nDOF_mesh_trial_element+i;
690 element_nodes[i*3 + I] = mesh_dof.data()[mesh_l2g.data()[eN_i]*3 + I];
692 int icase_s =
gf_s.calculate(element_phi_s, element_nodes, x_ref.data(),
false);
696 for (
int ebN_element=0;ebN_element < nDOF_mesh_trial_element; ebN_element++)
698 const int ebN = elementBoundariesArray.data()[eN*nDOF_mesh_trial_element+ebN_element];
702 if (elementBoundaryElementsArray.data()[ebN*2+1] != -1 && (ebN < nElementBoundaries_owned))
727 elementBoundaryDiameter,
734 mesh_trial_trace_ref,
735 mesh_grad_trial_trace_ref,
738 u_grad_trial_trace_ref,
740 u_grad_test_trace_ref,
744 nElementBoundaries_owned,
753 shockCapturingDiffusion,
758 nExteriorElementBoundaries_global,
759 exteriorElementBoundariesArray,
760 elementBoundariesArray,
761 elementBoundaryElementsArray,
762 elementBoundaryLocalElementBoundariesArray,
766 embeddedBoundary_penalty,
767 embeddedBoundary_normal_q,
768 embeddedBoundary_u_q,
774 for(
int i=0;i<nDOF_test_element;i++)
776 register int eN_i=eN*nDOF_test_element+i;
778 globalResidual.data()[offset_u+stride_u*u_l2g.data()[eN_i]]+=elementResidual_u.data()[i];
780 isActiveDOF.data()[offset_u+stride_u*u_l2g.data()[eN_i]] = 1.0;
787 std::map<int,double> Dwp_Dn_jump, Dw_Dn_jump;
788 register double gamma_cutfem=embeddedBoundary_ghost_penalty,h_cutfem=elementBoundaryDiameter.data()[*it];
789 for (
int kb=0;kb<nQuadraturePoints_elementBoundary;kb++)
791 register double Du_Dn_jump=0.0, dS;
792 for (
int eN_side=0;eN_side < 2; eN_side++)
794 register int ebN = *it,
795 eN = elementBoundaryElementsArray.data()[ebN*2+eN_side];
796 for (
int i=0;i<nDOF_test_element;i++)
798 Dw_Dn_jump[u_l2g.data()[eN*nDOF_test_element+i]] = 0.0;
801 for (
int eN_side=0;eN_side < 2; eN_side++)
803 register int ebN = *it,
804 eN = elementBoundaryElementsArray.data()[ebN*2+eN_side],
805 ebN_local = elementBoundaryLocalElementBoundariesArray.data()[ebN*2+eN_side],
806 eN_nDOF_trial_element = eN*nDOF_trial_element,
807 ebN_local_kb = ebN_local*nQuadraturePoints_elementBoundary+kb,
808 ebN_local_kb_nSpace = ebN_local_kb*nSpace;
809 register double u_int=0.0,
810 grad_u_int[nSpace]={0.,0.},
811 jac_int[nSpace*nSpace],
813 jacInv_int[nSpace*nSpace],
814 boundaryJac[nSpace*(nSpace-1)],
815 metricTensor[(nSpace-1)*(nSpace-1)],
817 u_test_dS[nDOF_test_element],
818 u_grad_trial_trace[nDOF_trial_element*nSpace],
819 u_grad_test_dS[nDOF_trial_element*nSpace],
820 normal[2],x_int,y_int,z_int,xt_int,yt_int,zt_int,integralScaling,
821 G[nSpace*nSpace],G_dd_G,tr_G,h_phi,h_penalty,penalty,
822 force_x,force_y,force_z,force_p_x,force_p_y,force_p_z,force_v_x,force_v_y,force_v_z,r_x,r_y,r_z;
824 ck.calculateMapping_elementBoundary(eN,
830 mesh_trial_trace_ref.data(),
831 mesh_grad_trial_trace_ref.data(),
832 boundaryJac_ref.data(),
842 dS = metricTensorDetSqrt*dS_ref.data()[kb];
845 ck.gradTrialFromRef(&u_grad_trial_trace_ref.data()[ebN_local_kb_nSpace*nDOF_trial_element],jacInv_int,u_grad_trial_trace);
847 ck.valFromDOF(u_dof.data(),&u_l2g.data()[eN_nDOF_trial_element],&u_trial_trace_ref.data()[ebN_local_kb*nDOF_test_element],u_int);
848 ck.gradFromDOF(u_dof.data(),&u_l2g.data()[eN_nDOF_trial_element],u_grad_trial_trace,grad_u_int);
849 for (
int I=0;I<nSpace;I++)
851 Du_Dn_jump += grad_u_int[I]*normal[I];
853 for (
int i=0;i<nDOF_test_element;i++)
855 for (
int I=0;I<nSpace;I++)
856 Dw_Dn_jump[u_l2g.data()[eN_nDOF_trial_element+i]] += u_grad_trial_trace[i*nSpace+I]*normal[I];
859 for (std::map<int,double>::iterator w_it=Dw_Dn_jump.begin(); w_it!=Dw_Dn_jump.end(); ++w_it)
861 int i_global = w_it->first;
862 double Dw_Dn_jump_i = w_it->second;
863 globalResidual.data()[offset_u+stride_u*i_global]+=gamma_cutfem*h_cutfem*Du_Dn_jump*Dw_Dn_jump_i*dS;
879 for (
int ebNE = 0; ebNE < nExteriorElementBoundaries_global; ebNE++)
881 register int ebN = exteriorElementBoundariesArray.data()[ebNE],
882 eN = elementBoundaryElementsArray.data()[ebN*2+0],
883 ebN_local = elementBoundaryLocalElementBoundariesArray.data()[ebN*2+0],
884 eN_nDOF_trial_element = eN*nDOF_trial_element;
885 register double elementResidual_u[nDOF_test_element];
886 for (
int i=0;i<nDOF_test_element;i++)
888 elementResidual_u[i]=0.0;
890 for (
int kb=0;kb<nQuadraturePoints_elementBoundary;kb++)
892 register int ebNE_kb = ebNE*nQuadraturePoints_elementBoundary+kb,
893 ebNE_kb_nSpace = ebNE_kb*nSpace,
894 ebN_local_kb = ebN_local*nQuadraturePoints_elementBoundary+kb,
895 ebN_local_kb_nSpace = ebN_local_kb*nSpace;
896 register double u_ext=0.0,
914 jac_ext[nSpace*nSpace],
916 jacInv_ext[nSpace*nSpace],
917 boundaryJac[nSpace*(nSpace-1)],
918 metricTensor[(nSpace-1)*(nSpace-1)],
921 u_test_dS[nDOF_test_element],
922 u_grad_trial_trace[nDOF_trial_element*nSpace],
923 u_grad_test_dS[nDOF_trial_element*nSpace],
924 normal[nSpace],x_ext,y_ext,z_ext,xt_ext,yt_ext,zt_ext,integralScaling,
926 G[nSpace*nSpace],G_dd_G,tr_G;
931 ck.calculateMapping_elementBoundary(eN,
937 mesh_trial_trace_ref.data(),
938 mesh_grad_trial_trace_ref.data(),
939 boundaryJac_ref.data(),
962 dS = metricTensorDetSqrt*dS_ref.data()[kb];
965 ck.calculateG(jacInv_ext,G,G_dd_G,tr_G);
968 ck.gradTrialFromRef(&u_grad_trial_trace_ref.data()[ebN_local_kb_nSpace*nDOF_trial_element],jacInv_ext,u_grad_trial_trace);
970 ck.valFromDOF(u_dof.data(),&u_l2g.data()[eN_nDOF_trial_element],&u_trial_trace_ref.data()[ebN_local_kb*nDOF_test_element],u_ext);
971 ck.gradFromDOF(u_dof.data(),&u_l2g.data()[eN_nDOF_trial_element],u_grad_trial_trace,grad_u_ext);
973 for (
int j=0;j<nDOF_trial_element;j++)
975 u_test_dS[j] = u_test_trace_ref.data()[ebN_local_kb*nDOF_test_element+j]*dS;
976 for (
int I=0;I<nSpace;I++)
977 u_grad_test_dS[j*nSpace+I] = u_grad_trial_trace[j*nSpace+I]*dS;
982 bc_u_ext = isDOFBoundary_u.data()[ebNE_kb]*ebqe_bc_u_ext.data()[ebNE_kb]+(1-isDOFBoundary_u.data()[ebNE_kb])*u_ext;
987 a_ext = &ebqe_a.data()[ebNE_kb*sd_rowptr[nSpace]];
988 for (
int I=0;I<nSpace;I++)
990 f_ext[I] = ebqe_v.data()[ebNE_kb*nSpace+I]*u_ext;
991 df_ext[I] = ebqe_v.data()[ebNE_kb*nSpace+I];
992 bc_f_ext[I] = ebqe_v.data()[ebNE_kb*nSpace+I]*bc_u_ext;
993 bc_df_ext[I] = ebqe_v.data()[ebNE_kb*nSpace+I];
1028 isDOFBoundary_u.data()[ebNE_kb],
1029 isDiffusiveFluxBoundary_u.data()[ebNE_kb],
1033 ebqe_bc_flux_u_ext.data()[ebNE_kb],
1037 ebqe_penalty_ext.data()[ebNE_kb],
1040 isAdvectiveFluxBoundary_u.data()[ebNE_kb],
1043 ebqe_bc_flux_u_ext.data()[ebNE_kb],
1051 for (
int i=0;i<nDOF_test_element;i++)
1054 elementResidual_u[i] +=
ck.ExteriorElementBoundaryFlux(flux_diff_ext+flux_advect_ext,u_test_dS[i])+
1055 ck.ExteriorElementBoundaryDiffusionAdjoint(isDOFBoundary_u.data()[ebNE_kb],
1056 isDiffusiveFluxBoundary_u.data()[ebNE_kb],
1064 &u_grad_test_dS[i*nSpace]);
1070 for (
int i=0;i<nDOF_test_element;i++)
1072 int eN_i = eN*nDOF_test_element+i;
1073 globalResidual.data()[offset_u+stride_u*u_l2g.data()[eN_i]] += elementResidual_u[i];
1079 xt::pyarray<double>& mesh_trial_ref,
1080 xt::pyarray<double>& mesh_grad_trial_ref,
1081 xt::pyarray<double>& mesh_dof,
1082 xt::pyarray<int>& mesh_l2g,
1083 xt::pyarray<double>& x_ref,
1084 xt::pyarray<double>& dV_ref,
1085 xt::pyarray<double>& u_trial_ref,
1086 xt::pyarray<double>& u_grad_trial_ref,
1087 xt::pyarray<double>& u_test_ref,
1088 xt::pyarray<double>& u_grad_test_ref,
1089 xt::pyarray<double>& elementDiameter,
1090 xt::pyarray<double>& elementBoundaryDiameter,
1091 xt::pyarray<double>& nodeDiametersArray,
1092 xt::pyarray<double>& cfl,
1098 xt::pyarray<double>& mesh_trial_trace_ref,
1099 xt::pyarray<double>& mesh_grad_trial_trace_ref,
1100 xt::pyarray<double>& dS_ref,
1101 xt::pyarray<double>& u_trial_trace_ref,
1102 xt::pyarray<double>& u_grad_trial_trace_ref,
1103 xt::pyarray<double>& u_test_trace_ref,
1104 xt::pyarray<double>& u_grad_test_trace_ref,
1105 xt::pyarray<double>& normal_ref,
1106 xt::pyarray<double>& boundaryJac_ref,
1108 int nElements_global,
1109 int nElementBoundaries_owned,
1110 xt::pyarray<int>& u_l2g,
1111 xt::pyarray<double>& u_dof,
1112 xt::pyarray<int>& sd_rowptr,
1113 xt::pyarray<int>& sd_colind,
1114 xt::pyarray<double>& q_a,
1115 xt::pyarray<double>& q_v,
1116 xt::pyarray<double>& q_r,
1117 int lag_shockCapturing,
1118 double shockCapturingDiffusion,
1119 xt::pyarray<double>& q_numDiff_u,
1120 xt::pyarray<double>& q_numDiff_u_last,
1121 xt::pyarray<double>& elementJacobian_u_u,
1122 xt::pyarray<double>& element_u,
1124 const bool embeddedBoundary,
1125 const double embeddedBoundary_penalty,
1126 xt::pyarray<double>& embeddedBoundary_normal_q,
1127 xt::pyarray<double>& embeddedBoundary_u_q)
1129 for (
int i=0;i<nDOF_test_element;i++)
1130 for (
int j=0;j<nDOF_trial_element;j++)
1132 elementJacobian_u_u.data()[i*nDOF_trial_element+j]=0.0;
1134 for (
int k=0;k<nQuadraturePoints_element;k++)
1137 int eN_k = eN*nQuadraturePoints_element+k;
1138 int eN_k_3d = eN_k*3;
1140 register double u=0.0,
1145 f[nSpace],
df[nSpace],
1146 f_s[nSpace]={0.,0.},df_s[nSpace]={0.,0.},
1147 ham_s=0.0,dham_s[nSpace]={0.,0.},
1149 dpdeResidual_u_u[nDOF_trial_element],
1150 Lstar_u[nDOF_test_element],
1151 dsubgridError_u_u[nDOF_trial_element],
1152 tau=0.0,tau0=0.0,tau1=0.0,
1157 jacInv[nSpace*nSpace],
1158 u_grad_trial[nDOF_trial_element*nSpace],
1160 u_test_dV[nDOF_test_element],
1161 u_grad_test_dV[nDOF_test_element*nSpace],
1163 G[nSpace*nSpace],G_dd_G,tr_G;
1167 ck.calculateMapping_element(eN,
1171 mesh_trial_ref.data(),
1172 mesh_grad_trial_ref.data(),
1177 ck.calculateH_element(eN,
1179 nodeDiametersArray.data(),
1181 mesh_trial_ref.data(),
1184 dV = fabs(jacDet)*dV_ref.data()[k];
1186 ck.calculateG(jacInv,G,G_dd_G,tr_G);
1188 ck.gradTrialFromRef(&u_grad_trial_ref.data()[k*nDOF_trial_element*nSpace],jacInv,u_grad_trial);
1190 ck.valFromElementDOF(element_u.data(),&u_trial_ref.data()[k*nDOF_trial_element],
u);
1192 ck.gradFromElementDOF(element_u.data(),u_grad_trial,grad_u);
1194 for (
int j=0;j<nDOF_trial_element;j++)
1196 u_test_dV[j] = u_test_ref.data()[k*nDOF_trial_element+j]*dV;
1197 for (
int I=0;I<nSpace;I++)
1199 u_grad_test_dV[j*nSpace+I] = u_grad_trial[j*nSpace+I]*dV;
1206 a = &q_a.data()[eN_k*sd_rowptr.data()[nSpace]];
1207 for (
int I=0;I<nSpace;I++)
1208 df[I] = q_v.data()[eN_k*nSpace+I];
1210 const double H_s =
gf_s.H(0.,0.);
1211 const double D_s =
gf_s.D(0.,0.);
1212 if(embeddedBoundary)
1214 double level_set_normal[nSpace];
1216 double norm_exact=0.0,norm_cut=0.0;
1217 for (
int I=0;I<nSpace;I++)
1219 sign += embeddedBoundary_normal_q.data()[eN_k_3d+I]*
gf_s.get_normal()[I];
1220 level_set_normal[I] =
gf_s.get_normal()[I];
1221 norm_cut += level_set_normal[I]*level_set_normal[I];
1222 norm_exact += embeddedBoundary_normal_q.data()[eN_k_3d+I]*embeddedBoundary_normal_q.data()[eN_k_3d+I];
1224 assert(std::fabs(1.0-norm_cut) < 1.0e-8);
1225 assert(std::fabs(1.0-norm_exact) < 1.0e-8);
1227 for (
int I=0;I<nSpace;I++)
1228 level_set_normal[I]*=-1.0;
1232 embeddedBoundary_u_q.data()[eN_k],
1247 for (
int i=0;i<nDOF_test_element;i++)
1251 register int i_nSpace = i*nSpace;
1252 Lstar_u[i]=
ck.Advection_adjoint(
df,&u_grad_test_dV[i_nSpace]);
1255 for (
int j=0;j<nDOF_trial_element;j++)
1259 int j_nSpace = j*nSpace;
1260 dpdeResidual_u_u[j]=
ck.MassJacobian_strong(dm_t,u_trial_ref.data()[k*nDOF_trial_element+j]) +
1261 ck.AdvectionJacobian_strong(
df,&u_grad_trial[j_nSpace]);
1276 tau = useMetrics*tau1+(1.0-useMetrics)*tau0;
1278 for(
int j=0;j<nDOF_trial_element;j++)
1279 dsubgridError_u_u[j] = -tau*dpdeResidual_u_u[j];
1281 for(
int i=0;i<nDOF_test_element;i++)
1283 int i_nSpace=i*nSpace;
1284 for(
int j=0;j<nDOF_trial_element;j++)
1286 int j_nSpace = j*nSpace;
1287 elementJacobian_u_u.data()[i*nDOF_trial_element+j] += H_s*(
ck.AdvectionJacobian_weak(
df,u_trial_ref.data()[k*nDOF_trial_element+j],&u_grad_test_dV[i_nSpace]) +
1288 ck.SimpleDiffusionJacobian_weak(sd_rowptr.data(),sd_colind.data(),a,&u_grad_trial[j_nSpace],&u_grad_test_dV[i_nSpace]) +
1289 ck.ReactionJacobian_weak(dr,u_trial_ref.data()[k*nDOF_trial_element+j],u_test_dV[i]) +
1290 ck.SubgridErrorJacobian(dsubgridError_u_u[j],Lstar_u[i]) +
1291 ck.NumericalDiffusionJacobian(q_numDiff_u_last.data()[eN_k],&u_grad_trial[j_nSpace],&u_grad_test_dV[i_nSpace]));
1292 if (embeddedBoundary)
1294 elementJacobian_u_u.data()[i*nDOF_trial_element+j] += (
ck.AdvectionJacobian_weak(df_s,u_trial_ref.data()[k*nDOF_trial_element+j],&u_grad_test_dV[i_nSpace]) +
1295 ck.ReactionJacobian_weak(dr_s,u_trial_ref.data()[k*nDOF_trial_element+j], u_test_dV[i]) +
1296 ck.HamiltonianJacobian_weak(dham_s,&u_grad_trial[j_nSpace],u_test_dV[i]));
1307 xt::pyarray<double>& mesh_trial_ref = args.
array<
double>(
"mesh_trial_ref");
1308 xt::pyarray<double>& mesh_grad_trial_ref = args.
array<
double>(
"mesh_grad_trial_ref");
1309 xt::pyarray<double>& mesh_dof = args.
array<
double>(
"mesh_dof");
1310 xt::pyarray<int>& mesh_l2g = args.
array<
int>(
"mesh_l2g");
1311 xt::pyarray<double>& dV_ref = args.
array<
double>(
"dV_ref");
1312 xt::pyarray<double>& u_trial_ref = args.
array<
double>(
"u_trial_ref");
1313 xt::pyarray<double>& u_grad_trial_ref = args.
array<
double>(
"u_grad_trial_ref");
1314 xt::pyarray<double>& u_test_ref = args.
array<
double>(
"u_test_ref");
1315 xt::pyarray<double>& u_grad_test_ref = args.
array<
double>(
"u_grad_test_ref");
1316 xt::pyarray<double>& elementDiameter = args.
array<
double>(
"elementDiameter");
1317 xt::pyarray<double>& cfl = args.
array<
double>(
"cfl");
1318 double Ct_sge = args.
scalar<
double>(
"Ct_sge");
1319 double sc_uref = args.
scalar<
double>(
"sc_uref");
1320 double sc_alpha = args.
scalar<
double>(
"sc_alpha");
1321 double useMetrics = args.
scalar<
double>(
"useMetrics");
1322 xt::pyarray<double>& mesh_trial_trace_ref = args.
array<
double>(
"mesh_trial_trace_ref");
1323 xt::pyarray<double>& mesh_grad_trial_trace_ref = args.
array<
double>(
"mesh_grad_trial_trace_ref");
1324 xt::pyarray<double>& dS_ref = args.
array<
double>(
"dS_ref");
1325 xt::pyarray<double>& u_trial_trace_ref = args.
array<
double>(
"u_trial_trace_ref");
1326 xt::pyarray<double>& u_grad_trial_trace_ref = args.
array<
double>(
"u_grad_trial_trace_ref");
1327 xt::pyarray<double>& u_test_trace_ref = args.
array<
double>(
"u_test_trace_ref");
1328 xt::pyarray<double>& u_grad_test_trace_ref = args.
array<
double>(
"u_grad_test_trace_ref");
1329 xt::pyarray<double>& normal_ref = args.
array<
double>(
"normal_ref");
1330 xt::pyarray<double>& boundaryJac_ref = args.
array<
double>(
"boundaryJac_ref");
1331 int nElements_global = args.
scalar<
int>(
"nElements_global");
1332 xt::pyarray<int>& u_l2g = args.
array<
int>(
"u_l2g");
1333 xt::pyarray<double>& u_dof = args.
array<
double>(
"u_dof");
1334 xt::pyarray<int>& sd_rowptr = args.
array<
int>(
"sd_rowptr");
1335 xt::pyarray<int>& sd_colind = args.
array<
int>(
"sd_colind");
1336 xt::pyarray<double>& q_a = args.
array<
double>(
"q_a");
1337 xt::pyarray<double>& q_v = args.
array<
double>(
"q_v");
1338 xt::pyarray<double>& q_r = args.
array<
double>(
"q_r");
1339 int lag_shockCapturing = args.
scalar<
int>(
"lag_shockCapturing");
1340 double shockCapturingDiffusion = args.
scalar<
double>(
"shockCapturingDiffusion");
1341 xt::pyarray<double>& q_numDiff_u = args.
array<
double>(
"q_numDiff_u");
1342 xt::pyarray<double>& q_numDiff_u_last = args.
array<
double>(
"q_numDiff_u_last");
1343 xt::pyarray<int>& csrRowIndeces_u_u = args.
array<
int>(
"csrRowIndeces_u_u");
1344 xt::pyarray<int>& csrColumnOffsets_u_u = args.
array<
int>(
"csrColumnOffsets_u_u");
1345 xt::pyarray<double>& globalJacobian = args.
array<
double>(
"globalJacobian");
1346 int nExteriorElementBoundaries_global = args.
scalar<
int>(
"nExteriorElementBoundaries_global");
1347 xt::pyarray<int>& exteriorElementBoundariesArray = args.
array<
int>(
"exteriorElementBoundariesArray");
1348 xt::pyarray<int>& elementBoundaryElementsArray = args.
array<
int>(
"elementBoundaryElementsArray");
1349 xt::pyarray<int>& elementBoundaryLocalElementBoundariesArray = args.
array<
int>(
"elementBoundaryLocalElementBoundariesArray");
1350 xt::pyarray<double>& ebqe_a = args.
array<
double>(
"ebqe_a");
1351 xt::pyarray<double>& ebqe_v = args.
array<
double>(
"ebqe_v");
1352 xt::pyarray<int>& isDOFBoundary_u = args.
array<
int>(
"isDOFBoundary_u");
1353 xt::pyarray<double>& ebqe_bc_u_ext = args.
array<
double>(
"ebqe_bc_u_ext");
1354 xt::pyarray<int>& isDiffusiveFluxBoundary_u = args.
array<
int>(
"isDiffusiveFluxBoundary_u");
1355 xt::pyarray<int>& isAdvectiveFluxBoundary_u = args.
array<
int>(
"isAdvectiveFluxBoundary_u");
1356 xt::pyarray<double>& ebqe_bc_flux_u_ext = args.
array<
double>(
"ebqe_bc_flux_u_ext");
1357 xt::pyarray<double>& ebqe_bc_advectiveFlux_u_ext = args.
array<
double>(
"ebqe_bc_advectiveFlux_u_ext");
1358 xt::pyarray<int>& csrColumnOffsets_eb_u_u = args.
array<
int>(
"csrColumnOffsets_eb_u_u");
1359 xt::pyarray<double>& ebqe_penalty_ext = args.
array<
double>(
"ebqe_penalty_ext");
1360 const bool embeddedBoundary = args.
scalar<
int>(
"embeddedBoundary");
1361 const double embeddedBoundary_penalty = args.
scalar<
double>(
"embeddedBoundary_penalty");
1362 const double embeddedBoundary_ghost_penalty = args.
scalar<
double>(
"embedded_ghost_penalty");
1363 xt::pyarray<double>& embeddedBoundary_sdf_nodes = args.
array<
double>(
"embeddedBoundary_sdf_nodes");
1364 xt::pyarray<double>& embeddedBoundary_sdf_q = args.
array<
double>(
"embeddedBoundary_sdf_q");
1365 xt::pyarray<double>& embeddedBoundary_normal_q = args.
array<
double>(
"embeddedBoundary_normal_q");
1366 xt::pyarray<double>& embeddedBoundary_u_q = args.
array<
double>(
"embeddedBoundary_u_q");
1367 xt::pyarray<double>& isActiveDOF = args.
array<
double>(
"isActiveDOF");
1368 const double eb_adjoint_sigma = args.
scalar<
double>(
"eb_adjoint_sigma");
1369 xt::pyarray<double>& x_ref = args.
array<
double>(
"x_ref");
1370 xt::pyarray<int>& elementBoundariesArray = args.
array<
int>(
"elementBoundariesArray");
1371 const int nElementBoundaries_owned = args.
scalar<
int>(
"nElementBoundaries_owned");
1372 xt::pyarray<double>& elementBoundaryDiameter = args.
array<
double>(
"elementBoundaryDiameter");
1373 xt::pyarray<double>& nodeDiametersArray = args.
array<
double>(
"nodeDiametersArray");
1377 for(
int eN=0;eN<nElements_global;eN++)
1380 auto elementJacobian_u_u = xt::pyarray<double>::from_shape({nDOF_test_element*nDOF_trial_element});
1381 auto element_u = xt::pyarray<double>::from_shape({nDOF_trial_element});
1382 for (
int j=0;j<nDOF_trial_element;j++)
1384 register int eN_j = eN*nDOF_trial_element+j;
1385 element_u.data()[j] = u_dof.data()[u_l2g.data()[eN_j]];
1387 double element_phi_s[nDOF_mesh_trial_element];
1388 for (
int j=0;j<nDOF_mesh_trial_element;j++)
1390 register int eN_j = eN*nDOF_mesh_trial_element+j;
1391 element_phi_s[j] = embeddedBoundary_sdf_nodes.data()[u_l2g.data()[eN_j]];
1393 double element_nodes[nDOF_mesh_trial_element*3];
1394 for (
int i=0;i<nDOF_mesh_trial_element;i++)
1396 register int eN_i=eN*nDOF_mesh_trial_element+i;
1397 for(
int I=0;I<3;I++)
1398 element_nodes[i*3 + I] = mesh_dof.data()[mesh_l2g.data()[eN_i]*3 + I];
1400 int icase_s =
gf_s.calculate(element_phi_s, element_nodes, x_ref.data(),
false);
1403 mesh_grad_trial_ref,
1413 elementBoundaryDiameter,
1420 mesh_trial_trace_ref,
1421 mesh_grad_trial_trace_ref,
1424 u_grad_trial_trace_ref,
1426 u_grad_test_trace_ref,
1430 nElementBoundaries_owned,
1439 shockCapturingDiffusion,
1442 elementJacobian_u_u,
1446 embeddedBoundary_penalty,
1447 embeddedBoundary_normal_q,
1448 embeddedBoundary_u_q);
1452 for (
int i=0;i<nDOF_test_element;i++)
1454 int eN_i = eN*nDOF_test_element+i;
1455 for (
int j=0;j<nDOF_trial_element;j++)
1457 int eN_i_j = eN_i*nDOF_trial_element+j;
1458 globalJacobian.data()[csrRowIndeces_u_u.data()[eN_i] + csrColumnOffsets_u_u.data()[eN_i_j]] += elementJacobian_u_u.data()[i*nDOF_trial_element+j];
1464 std::map<int,double> Dw_Dn_jump;
1465 std::map<std::pair<int, int>,
int> u_u_nz;
1466 register double gamma_cutfem=embeddedBoundary_ghost_penalty,h_cutfem=elementBoundaryDiameter.data()[*it];
1467 int eN_nDOF_trial_element = elementBoundaryElementsArray.data()[(*it)*2+0]*nDOF_trial_element;
1468 for (
int kb=0;kb<nQuadraturePoints_elementBoundary;kb++)
1470 register double Dp_Dn_jump=0.0, Du_Dn_jump=0.0, Dv_Dn_jump=0.0,dS;
1471 for (
int eN_side=0;eN_side < 2; eN_side++)
1473 register int ebN = *it,
1474 eN = elementBoundaryElementsArray.data()[ebN*2+eN_side];
1475 for (
int i=0;i<nDOF_test_element;i++)
1476 Dw_Dn_jump[u_l2g.data()[eN*nDOF_test_element+i]] = 0.0;
1478 for (
int eN_side=0;eN_side < 2; eN_side++)
1480 register int ebN = *it,
1481 eN = elementBoundaryElementsArray.data()[ebN*2+eN_side],
1482 ebN_local = elementBoundaryLocalElementBoundariesArray.data()[ebN*2+eN_side],
1483 eN_nDOF_trial_element = eN*nDOF_trial_element,
1484 ebN_local_kb = ebN_local*nQuadraturePoints_elementBoundary+kb,
1485 ebN_local_kb_nSpace = ebN_local_kb*nSpace;
1488 grad_u_int[nSpace]={0.,0.},
1489 jac_int[nSpace*nSpace],
1491 jacInv_int[nSpace*nSpace],
1492 boundaryJac[nSpace*(nSpace-1)],
1493 metricTensor[(nSpace-1)*(nSpace-1)],
1494 metricTensorDetSqrt,
1495 u_test_dS[nDOF_test_element],
1496 u_grad_trial_trace[nDOF_trial_element*nSpace],
1497 u_grad_test_dS[nDOF_trial_element*nSpace],
1498 normal[2],x_int,y_int,z_int,xt_int,yt_int,zt_int,integralScaling,
1499 G[nSpace*nSpace],G_dd_G,tr_G,h_phi,h_penalty,penalty;
1501 ck.calculateMapping_elementBoundary(eN,
1507 mesh_trial_trace_ref.data(),
1508 mesh_grad_trial_trace_ref.data(),
1509 boundaryJac_ref.data(),
1515 metricTensorDetSqrt,
1519 dS = metricTensorDetSqrt*dS_ref.data()[kb];
1522 ck.gradTrialFromRef(&u_grad_trial_trace_ref.data()[ebN_local_kb_nSpace*nDOF_trial_element],jacInv_int,u_grad_trial_trace);
1523 for (
int i=0;i<nDOF_test_element;i++)
1525 int eN_i = eN*nDOF_test_element + i;
1526 for (
int I=0;I<nSpace;I++)
1527 Dw_Dn_jump[u_l2g.data()[eN_i]] += u_grad_trial_trace[i*nSpace+I]*normal[I];
1530 for (
int eN_side=0;eN_side < 2; eN_side++)
1532 register int ebN = *it,
1533 eN = elementBoundaryElementsArray.data()[ebN*2+eN_side];
1534 for (
int i=0;i<nDOF_test_element;i++)
1536 register int eN_i = eN*nDOF_test_element+i;
1537 for (
int eN_side2=0;eN_side2 < 2; eN_side2++)
1539 register int eN2 = elementBoundaryElementsArray.data()[ebN*2+eN_side2];
1540 for (
int j=0;j<nDOF_test_element;j++)
1542 int eN_i_j = eN_i*nDOF_test_element + j;
1543 int eN2_j = eN2*nDOF_test_element + j;
1547 i*nDOF_trial_element +
1549 std::pair<int,int> ij = std::make_pair(u_l2g.data()[eN_i], u_l2g.data()[eN2_j]);
1550 if (u_u_nz.count(ij))
1552 assert(u_u_nz[ij] == csrRowIndeces_u_u.data()[eN_i] + csrColumnOffsets_eb_u_u.data()[ebN_i_j]);
1555 u_u_nz[ij] = csrRowIndeces_u_u.data()[eN_i] + csrColumnOffsets_eb_u_u.data()[ebN_i_j];
1560 for (std::map<int,double>::iterator wi_it=Dw_Dn_jump.begin(); wi_it!=Dw_Dn_jump.end(); ++wi_it)
1561 for (std::map<int,double>::iterator wj_it=Dw_Dn_jump.begin(); wj_it!=Dw_Dn_jump.end(); ++wj_it)
1563 int i_global = wi_it->first,
1564 j_global = wj_it->first;
1565 double Dw_Dn_jump_i = wi_it->second,
1566 Dw_Dn_jump_j = wj_it->second;
1567 std::pair<int,int> ij = std::make_pair(i_global, j_global);
1568 globalJacobian.data()[u_u_nz.at(ij)] += gamma_cutfem*h_cutfem*Dw_Dn_jump_j*Dw_Dn_jump_i*dS;
1575 for (
int ebNE = 0; ebNE < nExteriorElementBoundaries_global; ebNE++)
1577 register int ebN = exteriorElementBoundariesArray.data()[ebNE];
1578 register int eN = elementBoundaryElementsArray.data()[ebN*2+0],
1579 ebN_local = elementBoundaryLocalElementBoundariesArray.data()[ebN*2+0],
1580 eN_nDOF_trial_element = eN*nDOF_trial_element;
1581 for (
int kb=0;kb<nQuadraturePoints_elementBoundary;kb++)
1583 register int ebNE_kb = ebNE*nQuadraturePoints_elementBoundary+kb,
1584 ebNE_kb_nSpace = ebNE_kb*nSpace,
1585 ebN_local_kb = ebN_local*nQuadraturePoints_elementBoundary+kb,
1586 ebN_local_kb_nSpace = ebN_local_kb*nSpace;
1588 register double u_ext=0.0,
1603 fluxJacobian_u_u[nDOF_trial_element],
1604 jac_ext[nSpace*nSpace],
1606 jacInv_ext[nSpace*nSpace],
1607 boundaryJac[nSpace*(nSpace-1)],
1608 metricTensor[(nSpace-1)*(nSpace-1)],
1609 metricTensorDetSqrt,
1611 u_test_dS[nDOF_test_element],
1612 u_grad_trial_trace[nDOF_trial_element*nSpace],
1613 u_grad_test_dS[nDOF_trial_element*nSpace],
1614 normal[nSpace],x_ext,y_ext,z_ext,xt_ext,yt_ext,zt_ext,integralScaling,
1616 G[nSpace*nSpace],G_dd_G,tr_G;
1617 ck.calculateMapping_elementBoundary(eN,
1623 mesh_trial_trace_ref.data(),
1624 mesh_grad_trial_trace_ref.data(),
1625 boundaryJac_ref.data(),
1631 metricTensorDetSqrt,
1635 dS = metricTensorDetSqrt*dS_ref.data()[kb];
1636 ck.calculateG(jacInv_ext,G,G_dd_G,tr_G);
1639 ck.gradTrialFromRef(&u_grad_trial_trace_ref.data()[ebN_local_kb_nSpace*nDOF_trial_element],jacInv_ext,u_grad_trial_trace);
1641 ck.valFromDOF(u_dof.data(),&u_l2g.data()[eN_nDOF_trial_element],&u_trial_trace_ref.data()[ebN_local_kb*nDOF_test_element],u_ext);
1642 ck.gradFromDOF(u_dof.data(),&u_l2g.data()[eN_nDOF_trial_element],u_grad_trial_trace,grad_u_ext);
1644 for (
int j=0;j<nDOF_trial_element;j++)
1646 u_test_dS[j] = u_test_trace_ref.data()[ebN_local_kb*nDOF_test_element+j]*dS;
1647 for (
int I=0;I<nSpace;I++)
1648 u_grad_test_dS[j*nSpace+I] = u_grad_trial_trace[j*nSpace+I]*dS;
1653 bc_u_ext = isDOFBoundary_u.data()[ebNE_kb]*ebqe_bc_u_ext.data()[ebNE_kb]+(1-isDOFBoundary_u.data()[ebNE_kb])*u_ext;
1654 a_ext = &ebqe_a.data()[ebNE_kb*sd_rowptr.data()[nSpace]];
1655 for (
int I=0;I<nSpace;I++)
1657 df_ext[I] = ebqe_v.data()[ebNE_kb*nSpace+I];
1658 bc_df_ext[I] = ebqe_v.data()[ebNE_kb*nSpace+I];
1664 isAdvectiveFluxBoundary_u.data()[ebNE_kb],
1671 for (
int j=0;j<nDOF_trial_element;j++)
1674 register int j_nSpace = j*nSpace,ebN_local_kb_j=ebN_local_kb*nDOF_trial_element+j;
1677 isDOFBoundary_u.data()[ebNE_kb],
1678 isDiffusiveFluxBoundary_u.data()[ebNE_kb],
1681 u_trial_trace_ref.data()[ebN_local_kb_j],
1682 &u_grad_trial_trace[j_nSpace],
1683 ebqe_penalty_ext.data()[ebNE_kb]) +
1684 ck.ExteriorNumericalAdvectiveFluxJacobian(dflux_u_u_ext,u_trial_trace_ref.data()[ebN_local_kb_j]);
1689 for (
int i=0;i<nDOF_test_element;i++)
1691 register int eN_i = eN*nDOF_test_element+i;
1692 register int i_nSpace = i*nSpace;
1693 for (
int j=0;j<nDOF_trial_element;j++)
1696 register int ebN_local_kb_j=ebN_local_kb*nDOF_trial_element+j;
1698 globalJacobian.data()[csrRowIndeces_u_u.data()[eN_i] + csrColumnOffsets_eb_u_u.data()[ebN_i_j]] += fluxJacobian_u_u[j]*u_test_dS[i]+
1699 ck.ExteriorElementBoundaryDiffusionAdjointJacobian(isDOFBoundary_u.data()[ebNE_kb],
1700 isDiffusiveFluxBoundary_u.data()[ebNE_kb],
1702 u_trial_trace_ref.data()[ebN_local_kb_j],
1707 &u_grad_test_dS[i_nSpace]);
1716 int nQuadraturePoints_elementIn,
1717 int nDOF_mesh_trial_elementIn,
1718 int nDOF_trial_elementIn,
1719 int nDOF_test_elementIn,
1720 int nQuadraturePoints_elementBoundaryIn,
1724 return proteus::chooseAndAllocateDiscretization2D<cADR_base,cADR,CompKernel>(nSpaceIn,
1725 nQuadraturePoints_elementIn,
1726 nDOF_mesh_trial_elementIn,
1727 nDOF_trial_elementIn,
1728 nDOF_test_elementIn,
1729 nQuadraturePoints_elementBoundaryIn,
1732 return proteus::chooseAndAllocateDiscretization<cADR_base,cADR,CompKernel>(nSpaceIn,
1733 nQuadraturePoints_elementIn,
1734 nDOF_mesh_trial_elementIn,
1735 nDOF_trial_elementIn,
1736 nDOF_test_elementIn,
1737 nQuadraturePoints_elementBoundaryIn,