8 #include "xtensor-python/pyarray.hpp"
10 namespace py = pybind11;
22 template<
class CompKernelType,
24 int nQuadraturePoints_element,
25 int nDOF_mesh_trial_element,
26 int nDOF_trial_element,
27 int nDOF_test_element,
28 int nQuadraturePoints_elementBoundary>
45 H = 0.5*(1.0 +
phi/eps + sin(M_PI*
phi/eps)/M_PI);
54 HI=
phi - eps + 0.5*(eps + 0.5*eps*eps/eps - eps*cos(M_PI*eps/eps)/(M_PI*M_PI)) - 0.5*((-eps) + 0.5*(-eps)*(-eps)/eps - eps*cos(M_PI*(-eps)/eps)/(M_PI*M_PI));
62 HI = 0.5*(
phi + 0.5*
phi*
phi/eps - eps*cos(M_PI*
phi/eps)/(M_PI*M_PI)) - 0.5*((-eps) + 0.5*(-eps)*(-eps)/eps - eps*cos(M_PI*(-eps)/eps)/(M_PI*M_PI));
75 d = 0.5*(1.0 + cos(M_PI*
phi/eps))/eps;
80 const double& epsDirac,
84 const double& porosity,
93 double* mesh_trial_ref,
94 double* mesh_grad_trial_ref,
99 double* u_grad_trial_ref,
101 double* u_grad_test_ref,
103 double* mesh_trial_trace_ref,
104 double* mesh_grad_trial_trace_ref,
106 double* u_trial_trace_ref,
107 double* u_grad_trial_trace_ref,
108 double* u_test_trace_ref,
109 double* u_grad_test_trace_ref,
111 double* boundaryJac_ref,
113 int nElements_global,
115 double epsFactHeaviside,
117 double epsFactDiffusion,
119 double* elementDiameter,
120 double* nodeDiametersArray,
123 double* q_normal_phi,
125 double* ebqe_normal_phi,
133 int offset_u,
int stride_u,
134 double* elementResidual_u,
135 int nExteriorElementBoundaries_global,
136 int* exteriorElementBoundariesArray,
137 int* elementBoundaryElementsArray,
138 int* elementBoundaryLocalElementBoundariesArray,
142 for (
int i=0;i<nDOF_test_element;i++)
144 elementResidual_u[i]=0.0;
146 double epsHeaviside,epsDirac,epsDiffusion,norm;
148 for (
int k=0;k<nQuadraturePoints_element;k++)
151 register int eN_k = eN*nQuadraturePoints_element+k,
152 eN_k_nSpace = eN_k*nSpace;
154 register double u=0.0,grad_u[nSpace],
158 jacInv[nSpace*nSpace],
159 u_grad_trial[nDOF_trial_element*nSpace],
160 u_test_dV[nDOF_trial_element],
161 u_grad_test_dV[nDOF_test_element*nSpace],
163 G[nSpace*nSpace],G_dd_G,tr_G,h_phi;
167 ck.calculateMapping_element(eN,
177 ck.calculateH_element(eN,
184 dV = fabs(jacDet)*dV_ref[k];
185 ck.calculateG(jacInv,G,G_dd_G,tr_G);
197 ck.gradTrialFromRef(&u_grad_trial_ref[k*nDOF_trial_element*nSpace],jacInv,u_grad_trial);
199 ck.valFromElementDOF(element_u,&u_trial_ref[k*nDOF_trial_element],
u);
201 ck.gradFromElementDOF(element_u,u_grad_trial,grad_u);
203 for (
int j=0;j<nDOF_trial_element;j++)
205 u_test_dV[j] = u_test_ref[k*nDOF_trial_element+j]*dV;
206 for (
int I=0;I<nSpace;I++)
208 u_grad_test_dV[j*nSpace+I] = u_grad_trial[j*nSpace+I]*dV;
217 epsHeaviside = epsFactHeaviside*(useMetrics*h_phi+(1.0-useMetrics)*elementDiameter[eN]);
218 epsDirac = epsFactDirac* (useMetrics*h_phi+(1.0-useMetrics)*elementDiameter[eN]);
219 epsDiffusion = epsFactDiffusion*(useMetrics*h_phi+(1.0-useMetrics)*elementDiameter[eN]);
232 for(
int i=0;i<nDOF_test_element;i++)
236 register int i_nSpace=i*nSpace;
238 elementResidual_u[i] +=
ck.Reaction_weak(
r,u_test_dV[i]) +
239 ck.NumericalDiffusion(epsDiffusion,grad_u,&u_grad_test_dV[i_nSpace]);
251 for (
int I=0;I<nSpace;I++)
252 norm += grad_u[I]*grad_u[I];
254 for(
int I=0;I<nSpace;I++)
255 q_n[eN_k_nSpace+I] = grad_u[I]/norm;
260 xt::pyarray<double>& mesh_trial_ref = args.
array<
double>(
"mesh_trial_ref");
261 xt::pyarray<double>& mesh_grad_trial_ref = args.
array<
double>(
"mesh_grad_trial_ref");
262 xt::pyarray<double>& mesh_dof = args.
array<
double>(
"mesh_dof");
263 xt::pyarray<int>& mesh_l2g = args.
array<
int>(
"mesh_l2g");
264 xt::pyarray<double>& dV_ref = args.
array<
double>(
"dV_ref");
265 xt::pyarray<double>& u_trial_ref = args.
array<
double>(
"u_trial_ref");
266 xt::pyarray<double>& u_grad_trial_ref = args.
array<
double>(
"u_grad_trial_ref");
267 xt::pyarray<double>& u_test_ref = args.
array<
double>(
"u_test_ref");
268 xt::pyarray<double>& u_grad_test_ref = args.
array<
double>(
"u_grad_test_ref");
269 xt::pyarray<double>& mesh_trial_trace_ref = args.
array<
double>(
"mesh_trial_trace_ref");
270 xt::pyarray<double>& mesh_grad_trial_trace_ref = args.
array<
double>(
"mesh_grad_trial_trace_ref");
271 xt::pyarray<double>& dS_ref = args.
array<
double>(
"dS_ref");
272 xt::pyarray<double>& u_trial_trace_ref = args.
array<
double>(
"u_trial_trace_ref");
273 xt::pyarray<double>& u_grad_trial_trace_ref = args.
array<
double>(
"u_grad_trial_trace_ref");
274 xt::pyarray<double>& u_test_trace_ref = args.
array<
double>(
"u_test_trace_ref");
275 xt::pyarray<double>& u_grad_test_trace_ref = args.
array<
double>(
"u_grad_test_trace_ref");
276 xt::pyarray<double>& normal_ref = args.
array<
double>(
"normal_ref");
277 xt::pyarray<double>& boundaryJac_ref = args.
array<
double>(
"boundaryJac_ref");
278 int nElements_global = args.
scalar<
int>(
"nElements_global");
279 double useMetrics = args.
scalar<
double>(
"useMetrics");
280 double epsFactHeaviside = args.
scalar<
double>(
"epsFactHeaviside");
281 double epsFactDirac = args.
scalar<
double>(
"epsFactDirac");
282 double epsFactDiffusion = args.
scalar<
double>(
"epsFactDiffusion");
283 xt::pyarray<int>& u_l2g = args.
array<
int>(
"u_l2g");
284 xt::pyarray<double>& elementDiameter = args.
array<
double>(
"elementDiameter");
285 xt::pyarray<double>& nodeDiametersArray = args.
array<
double>(
"nodeDiametersArray");
286 xt::pyarray<double>& u_dof = args.
array<
double>(
"u_dof");
287 xt::pyarray<double>& q_phi = args.
array<
double>(
"q_phi");
288 xt::pyarray<double>& q_normal_phi = args.
array<
double>(
"q_normal_phi");
289 xt::pyarray<double>& ebqe_phi = args.
array<
double>(
"ebqe_phi");
290 xt::pyarray<double>& ebqe_normal_phi = args.
array<
double>(
"ebqe_normal_phi");
291 xt::pyarray<double>& q_H = args.
array<
double>(
"q_H");
292 xt::pyarray<double>& q_u = args.
array<
double>(
"q_u");
293 xt::pyarray<double>& q_n = args.
array<
double>(
"q_n");
294 xt::pyarray<double>& ebqe_u = args.
array<
double>(
"ebqe_u");
295 xt::pyarray<double>& ebqe_n = args.
array<
double>(
"ebqe_n");
296 xt::pyarray<double>& q_r = args.
array<
double>(
"q_r");
297 xt::pyarray<double>& q_vos = args.
array<
double>(
"q_vos");
298 int offset_u = args.
scalar<
int>(
"offset_u");
299 int stride_u = args.
scalar<
int>(
"stride_u");
300 xt::pyarray<double>& globalResidual = args.
array<
double>(
"globalResidual");
301 int nExteriorElementBoundaries_global = args.
scalar<
int>(
"nExteriorElementBoundaries_global");
302 xt::pyarray<int>& exteriorElementBoundariesArray = args.
array<
int>(
"exteriorElementBoundariesArray");
303 xt::pyarray<int>& elementBoundaryElementsArray = args.
array<
int>(
"elementBoundaryElementsArray");
304 xt::pyarray<int>& elementBoundaryLocalElementBoundariesArray = args.
array<
int>(
"elementBoundaryLocalElementBoundariesArray");
315 for(
int eN=0;eN<nElements_global;eN++)
318 register double elementResidual_u[nDOF_test_element],element_u[nDOF_trial_element];
319 for (
int i=0;i<nDOF_test_element;i++)
321 register int eN_i=eN*nDOF_test_element+i;
322 element_u[i] = u_dof.data()[u_l2g.data()[eN_i]];
325 mesh_grad_trial_ref.data(),
330 u_grad_trial_ref.data(),
332 u_grad_test_ref.data(),
333 mesh_trial_trace_ref.data(),
334 mesh_grad_trial_trace_ref.data(),
336 u_trial_trace_ref.data(),
337 u_grad_trial_trace_ref.data(),
338 u_test_trace_ref.data(),
339 u_grad_test_trace_ref.data(),
341 boundaryJac_ref.data(),
348 elementDiameter.data(),
349 nodeDiametersArray.data(),
354 ebqe_normal_phi.data(),
364 nExteriorElementBoundaries_global,
365 exteriorElementBoundariesArray.data(),
366 elementBoundaryElementsArray.data(),
367 elementBoundaryLocalElementBoundariesArray.data(),
373 for(
int i=0;i<nDOF_test_element;i++)
375 register int eN_i=eN*nDOF_test_element+i;
377 globalResidual.data()[offset_u+stride_u*u_l2g.data()[eN_i]]+=elementResidual_u[i];
386 for (
int ebNE = 0; ebNE < nExteriorElementBoundaries_global; ebNE++)
388 register int ebN = exteriorElementBoundariesArray.data()[ebNE],
389 eN = elementBoundaryElementsArray.data()[ebN*2+0],
390 ebN_local = elementBoundaryLocalElementBoundariesArray.data()[ebN*2+0];
393 double element_u[nDOF_trial_element];
394 for (
int i=0;i<nDOF_test_element;i++)
396 register int eN_i=eN*nDOF_test_element+i;
397 element_u[i] = u_dof.data()[u_l2g.data()[eN_i]];
399 for (
int kb=0;kb<nQuadraturePoints_elementBoundary;kb++)
401 register int ebNE_kb = ebNE*nQuadraturePoints_elementBoundary+kb,
402 ebNE_kb_nSpace = ebNE_kb*nSpace,
403 ebN_local_kb = ebN_local*nQuadraturePoints_elementBoundary+kb,
404 ebN_local_kb_nSpace = ebN_local_kb*nSpace;
405 register double u_ext=0.0,
407 jac_ext[nSpace*nSpace],
409 jacInv_ext[nSpace*nSpace],
410 boundaryJac[nSpace*(nSpace-1)],
411 metricTensor[(nSpace-1)*(nSpace-1)],
413 u_grad_trial_trace[nDOF_trial_element*nSpace],
414 normal[nSpace],x_ext,y_ext,z_ext,
415 G[nSpace*nSpace],G_dd_G,tr_G,norm;
419 ck.calculateMapping_elementBoundary(eN,
425 mesh_trial_trace_ref.data(),
426 mesh_grad_trial_trace_ref.data(),
427 boundaryJac_ref.data(),
439 ck.calculateG(jacInv_ext,G,G_dd_G,tr_G);
442 ck.gradTrialFromRef(&u_grad_trial_trace_ref.data()[ebN_local_kb_nSpace*nDOF_trial_element],jacInv_ext,u_grad_trial_trace);
444 ck.valFromElementDOF(element_u,&u_trial_trace_ref.data()[ebN_local_kb*nDOF_test_element],u_ext);
445 ck.gradFromElementDOF(element_u,u_grad_trial_trace,grad_u_ext);
447 ebqe_u.data()[ebNE_kb] = u_ext;
449 for (
int I=0;I<nSpace;I++)
450 norm += grad_u_ext[I]*grad_u_ext[I];
452 for (
int I=0;I<nSpace;I++)
453 ebqe_n.data()[ebNE_kb_nSpace+I] = grad_u_ext[I]/norm;
461 double* mesh_trial_ref,
462 double* mesh_grad_trial_ref,
467 double* u_grad_trial_ref,
469 double* u_grad_test_ref,
471 double* mesh_trial_trace_ref,
472 double* mesh_grad_trial_trace_ref,
474 double* u_trial_trace_ref,
475 double* u_grad_trial_trace_ref,
476 double* u_test_trace_ref,
477 double* u_grad_test_trace_ref,
479 double* boundaryJac_ref,
481 int nElements_global,
483 double epsFactHeaviside,
485 double epsFactDiffusion,
487 double* elementDiameter,
488 double* nodeDiametersArray,
495 double* q_normal_phi,
498 double* elementJacobian_u_u,
502 for (
int i=0;i<nDOF_test_element;i++)
503 for (
int j=0;j<nDOF_trial_element;j++)
505 elementJacobian_u_u[i*nDOF_trial_element+j]=0.0;
507 double epsHeaviside,epsDirac,epsDiffusion;
508 for (
int k=0;k<nQuadraturePoints_element;k++)
510 int eN_k = eN*nQuadraturePoints_element+k;
513 register double u=0.0,
518 jacInv[nSpace*nSpace],
519 u_grad_trial[nDOF_trial_element*nSpace],
521 u_test_dV[nDOF_test_element],
522 u_grad_test_dV[nDOF_test_element*nSpace],
524 G[nSpace*nSpace],G_dd_G,tr_G,h_phi;
528 ck.calculateMapping_element(eN,
538 ck.calculateH_element(eN,
545 dV = fabs(jacDet)*dV_ref[k];
546 ck.calculateG(jacInv,G,G_dd_G,tr_G);
559 ck.gradTrialFromRef(&u_grad_trial_ref[k*nDOF_trial_element*nSpace],jacInv,u_grad_trial);
561 ck.valFromElementDOF(element_u,&u_trial_ref[k*nDOF_trial_element],
u);
563 ck.gradFromElementDOF(element_u,u_grad_trial,grad_u);
565 for (
int j=0;j<nDOF_trial_element;j++)
567 u_test_dV[j] = u_test_ref[k*nDOF_trial_element+j]*dV;
568 for (
int I=0;I<nSpace;I++)
570 u_grad_test_dV[j*nSpace+I] = u_grad_trial[j*nSpace+I]*dV;
576 epsHeaviside=epsFactHeaviside*(useMetrics*h_phi+(1.0-useMetrics)*elementDiameter[eN]);
577 epsDirac =epsFactDirac* (useMetrics*h_phi+(1.0-useMetrics)*elementDiameter[eN]);
578 epsDiffusion=epsFactDiffusion*(useMetrics*h_phi+(1.0-useMetrics)*elementDiameter[eN]);
588 for(
int i=0;i<nDOF_test_element;i++)
592 int i_nSpace=i*nSpace;
593 for(
int j=0;j<nDOF_trial_element;j++)
597 int j_nSpace = j*nSpace;
599 elementJacobian_u_u[i*nDOF_trial_element+j] +=
ck.ReactionJacobian_weak(dr,u_trial_ref[k*nDOF_trial_element+j],u_test_dV[i]) +
600 ck.NumericalDiffusionJacobian(epsDiffusion,&u_grad_trial[j_nSpace],&u_grad_test_dV[i_nSpace]);
607 xt::pyarray<double>& mesh_trial_ref = args.
array<
double>(
"mesh_trial_ref");
608 xt::pyarray<double>& mesh_grad_trial_ref = args.
array<
double>(
"mesh_grad_trial_ref");
609 xt::pyarray<double>& mesh_dof = args.
array<
double>(
"mesh_dof");
610 xt::pyarray<int>& mesh_l2g = args.
array<
int>(
"mesh_l2g");
611 xt::pyarray<double>& dV_ref = args.
array<
double>(
"dV_ref");
612 xt::pyarray<double>& u_trial_ref = args.
array<
double>(
"u_trial_ref");
613 xt::pyarray<double>& u_grad_trial_ref = args.
array<
double>(
"u_grad_trial_ref");
614 xt::pyarray<double>& u_test_ref = args.
array<
double>(
"u_test_ref");
615 xt::pyarray<double>& u_grad_test_ref = args.
array<
double>(
"u_grad_test_ref");
616 xt::pyarray<double>& mesh_trial_trace_ref = args.
array<
double>(
"mesh_trial_trace_ref");
617 xt::pyarray<double>& mesh_grad_trial_trace_ref = args.
array<
double>(
"mesh_grad_trial_trace_ref");
618 xt::pyarray<double>& dS_ref = args.
array<
double>(
"dS_ref");
619 xt::pyarray<double>& u_trial_trace_ref = args.
array<
double>(
"u_trial_trace_ref");
620 xt::pyarray<double>& u_grad_trial_trace_ref = args.
array<
double>(
"u_grad_trial_trace_ref");
621 xt::pyarray<double>& u_test_trace_ref = args.
array<
double>(
"u_test_trace_ref");
622 xt::pyarray<double>& u_grad_test_trace_ref = args.
array<
double>(
"u_grad_test_trace_ref");
623 xt::pyarray<double>& normal_ref = args.
array<
double>(
"normal_ref");
624 xt::pyarray<double>& boundaryJac_ref = args.
array<
double>(
"boundaryJac_ref");
625 int nElements_global = args.
scalar<
int>(
"nElements_global");
626 double useMetrics = args.
scalar<
double>(
"useMetrics");
627 double epsFactHeaviside = args.
scalar<
double>(
"epsFactHeaviside");
628 double epsFactDirac = args.
scalar<
double>(
"epsFactDirac");
629 double epsFactDiffusion = args.
scalar<
double>(
"epsFactDiffusion");
630 xt::pyarray<int>& u_l2g = args.
array<
int>(
"u_l2g");
631 xt::pyarray<double>& elementDiameter = args.
array<
double>(
"elementDiameter");
632 xt::pyarray<double>& nodeDiametersArray = args.
array<
double>(
"nodeDiametersArray");
633 xt::pyarray<double>& u_dof = args.
array<
double>(
"u_dof");
634 xt::pyarray<double>& q_phi = args.
array<
double>(
"q_phi");
635 xt::pyarray<double>& q_normal_phi = args.
array<
double>(
"q_normal_phi");
636 xt::pyarray<double>& q_H = args.
array<
double>(
"q_H");
637 xt::pyarray<double>& q_vos = args.
array<
double>(
"q_vos");
638 xt::pyarray<int>& csrRowIndeces_u_u = args.
array<
int>(
"csrRowIndeces_u_u");
639 xt::pyarray<int>& csrColumnOffsets_u_u = args.
array<
int>(
"csrColumnOffsets_u_u");
640 xt::pyarray<double>& globalJacobian = args.
array<
double>(
"globalJacobian");
644 for(
int eN=0;eN<nElements_global;eN++)
646 register double elementJacobian_u_u[nDOF_test_element*nDOF_trial_element],element_u[nDOF_trial_element];
647 for (
int j=0;j<nDOF_trial_element;j++)
649 register int eN_j = eN*nDOF_trial_element+j;
650 element_u[j] = u_dof.data()[u_l2g.data()[eN_j]];
653 mesh_grad_trial_ref.data(),
658 u_grad_trial_ref.data(),
660 u_grad_test_ref.data(),
661 mesh_trial_trace_ref.data(),
662 mesh_grad_trial_trace_ref.data(),
664 u_trial_trace_ref.data(),
665 u_grad_trial_trace_ref.data(),
666 u_test_trace_ref.data(),
667 u_grad_test_trace_ref.data(),
669 boundaryJac_ref.data(),
676 elementDiameter.data(),
677 nodeDiametersArray.data(),
689 for (
int i=0;i<nDOF_test_element;i++)
691 int eN_i = eN*nDOF_test_element+i;
692 for (
int j=0;j<nDOF_trial_element;j++)
694 int eN_i_j = eN_i*nDOF_trial_element+j;
696 globalJacobian.data()[csrRowIndeces_u_u[eN_i] + csrColumnOffsets_u_u[eN_i_j]] += elementJacobian_u_u[i*nDOF_trial_element+j];
704 int nQuadraturePoints_elementIn,
705 int nDOF_mesh_trial_elementIn,
706 int nDOF_trial_elementIn,
707 int nDOF_test_elementIn,
708 int nQuadraturePoints_elementBoundaryIn,
712 return proteus::chooseAndAllocateDiscretization2D<cppPresInit_base,cppPresInit,CompKernel>(nSpaceIn,
713 nQuadraturePoints_elementIn,
714 nDOF_mesh_trial_elementIn,
715 nDOF_trial_elementIn,
717 nQuadraturePoints_elementBoundaryIn,
720 return proteus::chooseAndAllocateDiscretization<cppPresInit_base,cppPresInit,CompKernel>(nSpaceIn,
721 nQuadraturePoints_elementIn,
722 nDOF_mesh_trial_elementIn,
723 nDOF_trial_elementIn,
725 nQuadraturePoints_elementBoundaryIn,