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>
39 const double massFlux[nSpace],
43 for (
int I=0;I<nSpace;I++)
45 r = p - p_last - p_inc;
49 double* mesh_trial_ref,
50 double* mesh_grad_trial_ref,
55 double* u_grad_trial_ref,
57 double* u_grad_test_ref,
59 double* mesh_trial_trace_ref,
60 double* mesh_grad_trial_trace_ref,
62 double* u_trial_trace_ref,
63 double* u_grad_trial_trace_ref,
64 double* u_test_trace_ref,
65 double* u_grad_test_trace_ref,
67 double* boundaryJac_ref,
77 double* ebqe_massFlux,
80 int offset_u,
int stride_u,
81 double* elementResidual_u,
82 int nExteriorElementBoundaries_global,
83 int* exteriorElementBoundariesArray,
84 int* elementBoundaryElementsArray,
85 int* elementBoundaryLocalElementBoundariesArray,
89 for (
int i=0;i<nDOF_test_element;i++)
91 elementResidual_u[i]=0.0;
94 for (
int k=0;k<nQuadraturePoints_element;k++)
97 register int eN_k = eN*nQuadraturePoints_element+k,
98 eN_k_nSpace = eN_k*nSpace;
100 register double u=0.0,grad_u[nSpace],
105 jacInv[nSpace*nSpace],
106 u_grad_trial[nDOF_trial_element*nSpace],
107 u_test_dV[nDOF_trial_element],
108 u_grad_test_dV[nDOF_test_element*nSpace],
110 G[nSpace*nSpace],G_dd_G,tr_G;
114 ck.calculateMapping_element(eN,
125 dV = fabs(jacDet)*dV_ref[k];
126 ck.calculateG(jacInv,G,G_dd_G,tr_G);
128 ck.gradTrialFromRef(&u_grad_trial_ref[k*nDOF_trial_element*nSpace],jacInv,u_grad_trial);
130 ck.valFromElementDOF(element_u,&u_trial_ref[k*nDOF_trial_element],
u);
132 ck.gradFromElementDOF(element_u,u_grad_trial,grad_u);
134 for (
int j=0;j<nDOF_trial_element;j++)
136 u_test_dV[j] = u_test_ref[k*nDOF_trial_element+j]*dV;
137 for (
int I=0;I<nSpace;I++)
139 u_grad_test_dV[j*nSpace+I] = u_grad_trial[j*nSpace+I]*dV;
148 &q_massFlux[eN_k_nSpace],
154 for(
int i=0;i<nDOF_test_element;i++)
156 register int i_nSpace=i*nSpace;
157 elementResidual_u[i] +=
ck.Advection_weak(
f,&u_grad_test_dV[i_nSpace]) +
158 ck.Reaction_weak(
r,u_test_dV[i]);
161 for(
int I=0;I<nSpace;I++)
162 q_grad_u[eN_k_nSpace+I] = grad_u[I];
167 xt::pyarray<double>& mesh_trial_ref = args.
array<
double>(
"mesh_trial_ref");
168 xt::pyarray<double>& mesh_grad_trial_ref = args.
array<
double>(
"mesh_grad_trial_ref");
169 xt::pyarray<double>& mesh_dof = args.
array<
double>(
"mesh_dof");
170 xt::pyarray<int>& mesh_l2g = args.
array<
int>(
"mesh_l2g");
171 xt::pyarray<double>& dV_ref = args.
array<
double>(
"dV_ref");
172 xt::pyarray<double>& u_trial_ref = args.
array<
double>(
"u_trial_ref");
173 xt::pyarray<double>& u_grad_trial_ref = args.
array<
double>(
"u_grad_trial_ref");
174 xt::pyarray<double>& u_test_ref = args.
array<
double>(
"u_test_ref");
175 xt::pyarray<double>& u_grad_test_ref = args.
array<
double>(
"u_grad_test_ref");
176 xt::pyarray<double>& mesh_trial_trace_ref = args.
array<
double>(
"mesh_trial_trace_ref");
177 xt::pyarray<double>& mesh_grad_trial_trace_ref = args.
array<
double>(
"mesh_grad_trial_trace_ref");
178 xt::pyarray<double>& dS_ref = args.
array<
double>(
"dS_ref");
179 xt::pyarray<double>& u_trial_trace_ref = args.
array<
double>(
"u_trial_trace_ref");
180 xt::pyarray<double>& u_grad_trial_trace_ref = args.
array<
double>(
"u_grad_trial_trace_ref");
181 xt::pyarray<double>& u_test_trace_ref = args.
array<
double>(
"u_test_trace_ref");
182 xt::pyarray<double>& u_grad_test_trace_ref = args.
array<
double>(
"u_grad_test_trace_ref");
183 xt::pyarray<double>& normal_ref = args.
array<
double>(
"normal_ref");
184 xt::pyarray<double>& boundaryJac_ref = args.
array<
double>(
"boundaryJac_ref");
185 int nElements_global = args.
scalar<
int>(
"nElements_global");
186 xt::pyarray<int>& u_l2g = args.
array<
int>(
"u_l2g");
187 xt::pyarray<double>& u_dof = args.
array<
double>(
"u_dof");
188 xt::pyarray<double>& q_u = args.
array<
double>(
"q_u");
189 xt::pyarray<double>& q_grad_u = args.
array<
double>(
"q_grad_u");
190 xt::pyarray<double>& q_p_last = args.
array<
double>(
"q_p_last");
191 xt::pyarray<double>& q_p_inc = args.
array<
double>(
"q_p_inc");
192 xt::pyarray<double>& q_massFlux = args.
array<
double>(
"q_massFlux");
193 xt::pyarray<double>& ebqe_massFlux = args.
array<
double>(
"ebqe_massFlux");
194 xt::pyarray<double>& ebqe_u = args.
array<
double>(
"ebqe_u");
195 xt::pyarray<double>& ebqe_grad_u = args.
array<
double>(
"ebqe_grad_u");
196 int offset_u = args.
scalar<
int>(
"offset_u");
197 int stride_u = args.
scalar<
int>(
"stride_u");
198 xt::pyarray<double>& globalResidual = args.
array<
double>(
"globalResidual");
199 int nExteriorElementBoundaries_global = args.
scalar<
int>(
"nExteriorElementBoundaries_global");
200 xt::pyarray<int>& exteriorElementBoundariesArray = args.
array<
int>(
"exteriorElementBoundariesArray");
201 xt::pyarray<int>& elementBoundaryElementsArray = args.
array<
int>(
"elementBoundaryElementsArray");
202 xt::pyarray<int>& elementBoundaryLocalElementBoundariesArray = args.
array<
int>(
"elementBoundaryLocalElementBoundariesArray");
213 for(
int eN=0;eN<nElements_global;eN++)
216 register double elementResidual_u[nDOF_test_element],element_u[nDOF_trial_element];
217 for (
int i=0;i<nDOF_test_element;i++)
219 register int eN_i=eN*nDOF_test_element+i;
220 element_u[i] = u_dof.data()[u_l2g.data()[eN_i]];
223 mesh_grad_trial_ref.data(),
228 u_grad_trial_ref.data(),
230 u_grad_test_ref.data(),
231 mesh_trial_trace_ref.data(),
232 mesh_grad_trial_trace_ref.data(),
234 u_trial_trace_ref.data(),
235 u_grad_trial_trace_ref.data(),
236 u_test_trace_ref.data(),
237 u_grad_test_trace_ref.data(),
239 boundaryJac_ref.data(),
248 ebqe_massFlux.data(),
253 nExteriorElementBoundaries_global,
254 exteriorElementBoundariesArray.data(),
255 elementBoundaryElementsArray.data(),
256 elementBoundaryLocalElementBoundariesArray.data(),
262 for(
int i=0;i<nDOF_test_element;i++)
264 register int eN_i=eN*nDOF_test_element+i;
265 globalResidual.data()[offset_u+stride_u*u_l2g.data()[eN_i]]+=elementResidual_u[i];
274 for (
int ebNE = 0; ebNE < nExteriorElementBoundaries_global; ebNE++)
276 register int ebN = exteriorElementBoundariesArray.data()[ebNE],
277 eN = elementBoundaryElementsArray.data()[ebN*2+0],
278 ebN_local = elementBoundaryLocalElementBoundariesArray.data()[ebN*2+0];
280 register double elementResidual_u[nDOF_test_element];
281 double element_u[nDOF_trial_element];
282 for (
int i=0;i<nDOF_test_element;i++)
284 register int eN_i=eN*nDOF_test_element+i;
285 element_u[i] = u_dof.data()[u_l2g.data()[eN_i]];
286 elementResidual_u[i] = 0.0;
288 for (
int kb=0;kb<nQuadraturePoints_elementBoundary;kb++)
290 register int ebNE_kb = ebNE*nQuadraturePoints_elementBoundary+kb,
291 ebNE_kb_nSpace = ebNE_kb*nSpace,
292 ebN_local_kb = ebN_local*nQuadraturePoints_elementBoundary+kb,
293 ebN_local_kb_nSpace = ebN_local_kb*nSpace;
294 register double u_ext=0.0,
297 jac_ext[nSpace*nSpace],
299 jacInv_ext[nSpace*nSpace],
300 boundaryJac[nSpace*(nSpace-1)],
301 metricTensor[(nSpace-1)*(nSpace-1)],
304 u_test_dS[nDOF_test_element],
305 u_grad_trial_trace[nDOF_trial_element*nSpace],
306 normal[nSpace],x_ext,y_ext,z_ext,
307 G[nSpace*nSpace],G_dd_G,tr_G;
311 ck.calculateMapping_elementBoundary(eN,
317 mesh_trial_trace_ref.data(),
318 mesh_grad_trial_trace_ref.data(),
319 boundaryJac_ref.data(),
329 dS = metricTensorDetSqrt*dS_ref.data()[kb];
332 ck.calculateG(jacInv_ext,G,G_dd_G,tr_G);
335 ck.gradTrialFromRef(&u_grad_trial_trace_ref.data()[ebN_local_kb_nSpace*nDOF_trial_element],jacInv_ext,u_grad_trial_trace);
337 ck.valFromElementDOF(element_u,&u_trial_trace_ref.data()[ebN_local_kb*nDOF_test_element],u_ext);
338 ck.gradFromElementDOF(element_u,u_grad_trial_trace,grad_u_ext);
340 for (
int j=0;j<nDOF_trial_element;j++)
342 u_test_dS[j] = u_test_trace_ref.data()[ebN_local_kb*nDOF_test_element+j]*dS;
347 ebqe_u.data()[ebNE_kb] = u_ext;
348 for (
int I=0;I<nSpace;I++)
349 ebqe_grad_u.data()[ebNE_kb_nSpace+I] = grad_u_ext[I];
351 for (
int I=0;I<nSpace;I++)
352 adv_flux_ext += ebqe_massFlux.data()[ebNE_kb_nSpace+I]*normal[I];
356 for (
int i=0;i<nDOF_test_element;i++)
358 elementResidual_u[i] +=
ck.ExteriorElementBoundaryFlux(adv_flux_ext,u_test_dS[i]);
364 for (
int i=0;i<nDOF_test_element;i++)
366 int eN_i = eN*nDOF_test_element+i;
367 globalResidual.data()[offset_u+stride_u*u_l2g.data()[eN_i]] += elementResidual_u[i];
373 double* mesh_trial_ref,
374 double* mesh_grad_trial_ref,
379 double* u_grad_trial_ref,
381 double* u_grad_test_ref,
383 double* mesh_trial_trace_ref,
384 double* mesh_grad_trial_trace_ref,
386 double* u_trial_trace_ref,
387 double* u_grad_trial_trace_ref,
388 double* u_test_trace_ref,
389 double* u_grad_test_trace_ref,
391 double* boundaryJac_ref,
393 int nElements_global,
394 double* elementJacobian_u_u,
397 for (
int i=0;i<nDOF_test_element;i++)
398 for (
int j=0;j<nDOF_trial_element;j++)
400 elementJacobian_u_u[i*nDOF_trial_element+j]=0.0;
402 for (
int k=0;k<nQuadraturePoints_element;k++)
405 register double jac[nSpace*nSpace],
407 jacInv[nSpace*nSpace],
409 u_test_dV[nDOF_test_element],
414 ck.calculateMapping_element(eN,
425 dV = fabs(jacDet)*dV_ref[k];
426 for (
int j=0;j<nDOF_trial_element;j++)
428 u_test_dV[j] = u_test_ref[k*nDOF_trial_element+j]*dV;
430 for(
int i=0;i<nDOF_test_element;i++)
432 for(
int j=0;j<nDOF_trial_element;j++)
434 elementJacobian_u_u[i*nDOF_trial_element+j] +=
ck.ReactionJacobian_weak(1.0,
435 u_trial_ref[k*nDOF_trial_element+j],
443 xt::pyarray<double>& mesh_trial_ref = args.
array<
double>(
"mesh_trial_ref");
444 xt::pyarray<double>& mesh_grad_trial_ref = args.
array<
double>(
"mesh_grad_trial_ref");
445 xt::pyarray<double>& mesh_dof = args.
array<
double>(
"mesh_dof");
446 xt::pyarray<int>& mesh_l2g = args.
array<
int>(
"mesh_l2g");
447 xt::pyarray<double>& dV_ref = args.
array<
double>(
"dV_ref");
448 xt::pyarray<double>& u_trial_ref = args.
array<
double>(
"u_trial_ref");
449 xt::pyarray<double>& u_grad_trial_ref = args.
array<
double>(
"u_grad_trial_ref");
450 xt::pyarray<double>& u_test_ref = args.
array<
double>(
"u_test_ref");
451 xt::pyarray<double>& u_grad_test_ref = args.
array<
double>(
"u_grad_test_ref");
452 xt::pyarray<double>& mesh_trial_trace_ref = args.
array<
double>(
"mesh_trial_trace_ref");
453 xt::pyarray<double>& mesh_grad_trial_trace_ref = args.
array<
double>(
"mesh_grad_trial_trace_ref");
454 xt::pyarray<double>& dS_ref = args.
array<
double>(
"dS_ref");
455 xt::pyarray<double>& u_trial_trace_ref = args.
array<
double>(
"u_trial_trace_ref");
456 xt::pyarray<double>& u_grad_trial_trace_ref = args.
array<
double>(
"u_grad_trial_trace_ref");
457 xt::pyarray<double>& u_test_trace_ref = args.
array<
double>(
"u_test_trace_ref");
458 xt::pyarray<double>& u_grad_test_trace_ref = args.
array<
double>(
"u_grad_test_trace_ref");
459 xt::pyarray<double>& normal_ref = args.
array<
double>(
"normal_ref");
460 xt::pyarray<double>& boundaryJac_ref = args.
array<
double>(
"boundaryJac_ref");
461 int nElements_global = args.
scalar<
int>(
"nElements_global");
462 xt::pyarray<int>& csrRowIndeces_u_u = args.
array<
int>(
"csrRowIndeces_u_u");
463 xt::pyarray<int>& csrColumnOffsets_u_u = args.
array<
int>(
"csrColumnOffsets_u_u");
464 xt::pyarray<double>& globalJacobian = args.
array<
double>(
"globalJacobian");
468 for(
int eN=0;eN<nElements_global;eN++)
470 register double elementJacobian_u_u[nDOF_test_element*nDOF_trial_element];
472 mesh_grad_trial_ref.data(),
477 u_grad_trial_ref.data(),
479 u_grad_test_ref.data(),
480 mesh_trial_trace_ref.data(),
481 mesh_grad_trial_trace_ref.data(),
483 u_trial_trace_ref.data(),
484 u_grad_trial_trace_ref.data(),
485 u_test_trace_ref.data(),
486 u_grad_test_trace_ref.data(),
488 boundaryJac_ref.data(),
495 for (
int i=0;i<nDOF_test_element;i++)
497 int eN_i = eN*nDOF_test_element+i;
498 for (
int j=0;j<nDOF_trial_element;j++)
500 int eN_i_j = eN_i*nDOF_trial_element+j;
501 globalJacobian.data()[csrRowIndeces_u_u[eN_i] + csrColumnOffsets_u_u[eN_i_j]] += elementJacobian_u_u[i*nDOF_trial_element+j];
509 int nQuadraturePoints_elementIn,
510 int nDOF_mesh_trial_elementIn,
511 int nDOF_trial_elementIn,
512 int nDOF_test_elementIn,
513 int nQuadraturePoints_elementBoundaryIn,
517 return proteus::chooseAndAllocateDiscretization2D<cppPres_base,cppPres,CompKernel>(nSpaceIn,
518 nQuadraturePoints_elementIn,
519 nDOF_mesh_trial_elementIn,
520 nDOF_trial_elementIn,
522 nQuadraturePoints_elementBoundaryIn,
525 return proteus::chooseAndAllocateDiscretization<cppPres_base,cppPres,CompKernel>(nSpaceIn,
526 nQuadraturePoints_elementIn,
527 nDOF_mesh_trial_elementIn,
528 nDOF_trial_elementIn,
530 nQuadraturePoints_elementBoundaryIn,