8 int findInterval(
const double* vertices,
int nv,
double x,
int* ival,
double tol)
10 int leftInt=0,rightInt=nv-2,failed=1,mid=0;
11 assert(rightInt >= leftInt);
13 if (fabs(x-vertices[leftInt]) < tol)
19 if (x <= vertices[leftInt]-tol)
25 if (fabs(x-vertices[rightInt+1]) < tol)
31 if (x >= vertices[rightInt+1]+tol)
38 while (leftInt <= rightInt)
40 mid = (int)(floor(0.5*(leftInt+rightInt)));
41 if (vertices[mid] <= x && x < vertices[mid+1])
47 else if (x < vertices[mid])
49 else if (x >= vertices[mid+1])
53 std::cout<<
"findInterval shouldn't be here leftInt= "<<leftInt<<
" rightInt= "<<rightInt<<std::endl;
70 int index=*start,findFailed=0;
71 double val,tol=1.0e-8;
73 if (findFailed && index == -1)
78 else if (findFailed && index == nv)
85 assert(0 <= index && index < nv-1);
86 assert(xv[index]-tol <= x && x<= xv[index+1]+tol);
88 assert(0 <= index && index < nv-1);
89 val = yv[index] + (yv[index+1]-yv[index])/(xv[index+1]-xv[index])*(x-xv[index]);
91 *dy = (yv[index+1]-yv[index])/(xv[index+1]-xv[index]);
96 extern "C" int RE_NCP1_getResidual_VGM(
double rho,
98 const double * gravity,
99 const double * alphaVG,
101 const double * thetaR,
102 const double * thetaSR,
104 const int * KWs_rowptr,
105 const int * KWs_colind,
108 int nQuadraturePoints_element,
109 int nElements_global,
110 int nElementBoundaries_element,
111 int nElementBoundaries_global,
112 int nExteriorElementBoundaries_global,
113 int nQuadraturePoints_elementBoundary,
114 const double * nodeArray,
115 const int * elementNodesArray,
116 const double * elementBarycentersArray,
117 const int * elementMaterialTypes,
118 const int * elementNeighborsArray,
119 const int * elementBoundariesArray,
120 const double * elementBoundaryBarycentersArray,
121 const double * elementBoundaryOuterNormalsArray,
122 const int * exteriorElementBoundariesArray,
123 const int * elementBoundaryElementsArray,
124 const double * q_detJ,
126 int nDOF_trial_element,
127 int nDOF_test_element,
128 const double * u_dof,
129 const double * u_l2g,
132 const double * q_m_beta_bdf,
139 double * q_elementResidual,
141 const int * isDOFBoundary_u,
142 const int * isFluxBoundary_u,
143 const double * ebqe_w_dS,
144 const double * ebqe_u,
145 const double * ebqe_flux
149 double * globalResidal,
152 assert (nSpace+1 == nQuadraturePoints_element);
153 assert (nElementBoundaries_element == nSpace+1);
154 assert (nDOF_trial_element == nSpace+1);
156 double krw,dkrw,thetaw,dthetaw,rhom;
158 const double nAvgWeight = 1.0/(nSpace+1.);
159 double volFactor = 1.0;
164 const int nnz = KWs_rowptr[nSpace];
165 double w[4],grad_w[4][3],grad_u[3];
169 for (
int eN = 0; eN < nElements_global; eN++)
171 const double volume = volFactor * fabs(q_detJ[eN*nQuadraturePoints_element]);
172 const int matID = elementMaterialTypes[eN];
173 const double weight = nAvgWeight*volume;
175 for (
int ebN=0; ebN < nElementBoundaries_element; ebN++)
177 const int eN_ebN = eN*nDOF_test_element+ebN;
178 const double u_j = u_dof[u_l2g[eN_ebN]];
179 const double psic = -u_j;
180 pskEvaluate_vgm_re(psic,
191 rhom = rho*exp(beta*u_j);
193 q_m[ebN_ebN] = rhom*thetaw;
194 const double m_t_ebN = alphaBDF*q_m + q_m_beta_bdf[eN_ebN];
196 q_elementResidual[eN_ebN] += weight*m_t_ebN;
197 globalResidual[offset_u+stride_u*u_l2g[eN_ebN]] += weight*m_t_ebN;
203 for (
int eN = 0; eN < nElements_global; eN++)
205 evaluateTestFunctionsAndGradientsOnElement(nSpace,
207 &elementBarycentersArray[eN*3],
209 elementBoundaryOuterNormalsArray,
213 for (
int I = 0; I < nSpace; I++)
216 for (
int j = 0; j < nDOF_trial_element; j++)
218 grad_u[I] += u_dof[u_l2g[eN*nDOF_trial_element+j]]*grad_w[j][I];
221 double kr_eN = 0.0,u_eN=0.0;
223 for (
int ebN=0; ebN < nElementBoundaries_element; ebN++)
225 const int eN_ebN = eN*nDOF_test_element+ebN;
226 kr_eN += q_kr[eN_ebN]*nAvgWeight;
227 u_eN += q_u[eN_ebN]*nAvgWeight;
230 const double phi_eN = u_eN;
231 for (
int I = 0; I < nSpace; I++)
232 phi_eN -= gravity[I]*elementBarycentersArray[eN*3+I];
235 for (
int ebN=0; ebN < nElementBoundaries_element; ebN++)
237 const int eN_neighbor = elementNeighborsArray[eN*nElementBoundaries_element + ebN];
239 double kr_up = kr_eN;
240 if (eN_neighbor >= 0)
242 const matID_neighbor = elementMaterialTypes[eN_neighbor];
244 for (
int ii=0; ii <
nnz; ii++)
245 KWs_ebN[ii] = 2.0*KWs[matID*
nnz+ii]*KWs[matID_neighbor*
nnz+ii]/(KWs[matID*
nnz+ii] + KWs[matID_neighbor*
nnz+ii] + 1.0e-20);
248 double kr_neig = 0.0,u_neig=0.0;
250 for (
int ebN_neig=0; ebN_neig < nElementBoundaries_element; ebN_neig++)
252 const int eN_ebN_neig = eN_neighbor*nDOF_test_element+ebN_neig;
253 kr_neig += q_kr[eN_ebN_neig]*nAvgWeight;
254 u_neig += q_u[eN_ebN_neig]*nAvgWeight;
257 const double phi_neig = u_neig;
258 for (
int I = 0; I < nSpace; I++)
259 phi_neig -= gravity[I]*elementBarycentersArray[eN_neighbor*3+I];
261 if (phi_neig > phi_eN)
268 for (
int ii=0; ii <
nnz; ii++)
269 KWs_ebN[ii] = KWs[matID*
nnz+ii];
273 for (
int i =0; i < nDOF_test_element; i++)
275 const int eN_i = eN*nDOF_test_element + i;
276 for (
int I = 0; I < nSpace; I++)
278 for (
int ii=KWs_rowptr[I]; ii < KWs_rowptr[I+1]; ii++)
280 q_elementResidual[eN_i] -= rho*rho*KWs_ebN[ii]*gravity[KWs_colind[ii]]*grad_w[i][I];
281 globalResidual[offset_u+stride_u*u_l2g[eN_i]] -= rho*rho*KWs_ebN[ii]*gravity[KWs_colind[ii]]*grad_w[i][I];
282 q_elementResidual[eN_i] += rho*KWs_ebN[ii]*grad_u[KWs_colind[ii]]*grad_w[i][I];
283 globalResidual[offset_u+stride_u*u_l2g[eN_i]] += rho*KWs_ebN[ii]*grad_u[KWs_colind[ii]]*grad_w[i][I];
297 double elementResidual[4];
298 for (
int ebNE = 0; ebNE < nExteriorElementBoundaries_global; ebNE++)
300 const int ebN = exteriorElementBoundariesArray[ebNE];
301 const int eN = elementBoundaryElementsArray[ebN*2+0];
303 for (
int kb = 0; kb < nQuadraturePoints_elementBoundary; kb++)
305 const int ebNE_kb = ebNE*nQuadraturePoints_elementBoundary + kb;
306 if (isFluxBoundary_u[ebNE_kb])
308 for (
int i = 0; i < nDOF_test_element; i++)
310 elementResidual[i] += ebqe_flux[ebNE_kb]*ebqe_w_dS[ebNE_kb];
314 for (
int i = 0; i < nDOF_test_element; i++)
316 q_elementResidual[eN*nDOF_test_element + i] += elementResidual[i];
317 globalResidual[offset_u+stride_u*u_l2g[eN*nDOF_test_element+i]] += elementResidual[i];
322 for (
int ebNE = 0; ebNE < nExteriorElementBoundaries_global; ebNE++)
324 const int ebN = exteriorElementBoundariesArray[ebNE];
325 const int eN = elementBoundaryElementsArray[ebN*2+0];
327 if (isDOFBoundary_u[ebNE*nQuadraturePoints_elementBoundary])
329 for (
int j = 0; j < nElementBoundaries_element; j++)
331 if (elementBoundariesArray[eN*nElementBoundaries_element + j] == ebN)
333 globalResidual[offset_u+stride_u*u_l2g[eN*nDOF_trial_element+j]] = u_dof[u_l2g[eN*nDOF_trial_element+j]] - ebqe_u[ebNE*nQuadraturePoints_elementBoundary];
353 const int* materialTypes,
359 const double* rwork_psk,
360 const double* rwork_psk_tol,
361 const double* rwork_density_w,
362 const double* rwork_density_n,
365 const double* ebq_global_qt,
367 const double* q_lambda_bar,
369 int nElements_global,
370 int nElementBoundaries_element,
371 int nInteriorElementBoundaries_global,
372 int nExteriorElementBoundaries_global,
373 int nQuadraturePoints_element,
374 int nQuadraturePoints_elementBoundary,
375 const int* interiorElementBoundariesArray,
376 const int* exteriorElementBoundariesArray,
377 const int* elementBoundaryElementsArray,
378 const int* elementBoundaryLocalElementBoundariesArray,
388 const int * isDOFBoundary,
407 switch (pskModelFlag)
413 psk =
new VGM(rwork_psk);
416 psk =
new VGB(rwork_psk);
419 psk =
new BCM(rwork_psk);
422 psk =
new BCB(rwork_psk);
425 std::cerr<<
"pskModelFlag= "<<pskModelFlag<<
" not recognized"<<std::endl;
433 const double rwork_density_w_x[1] = {1.0};
const double rwork_density_n_x[1] = {1.0};
434 ConstantDensity density_w_x(rwork_density_w_x),density_n_x(rwork_density_n_x);
435 const int nnz = rowptr[nSpace];
436 double f_left[3] = {0.,0.,0.};
double f_right[3] = {0.,0.,0.};
438 for (
int ebNI = 0; ebNI < nInteriorElementBoundaries_global; ebNI++)
440 const int ebN = interiorElementBoundariesArray[ebNI];
441 const int eN_left =elementBoundaryElementsArray[ebN*2+0];
442 const int eN_right =elementBoundaryElementsArray[ebN*2+1];
443 const int ebN_left =elementBoundaryLocalElementBoundariesArray[ebN*2+0];
444 const int ebN_right=elementBoundaryLocalElementBoundariesArray[ebN*2+1];
448 double u_left=0.0,u_right=0.0,vol_left=0.0,vol_right=0.0;
450 double maxSpeed_element=0.,maxSpeed_left=0.0,maxSpeed_right=0.0,tmp_left=0.0,tmp_right=0.0;
452 for (
int k = 0; k < nQuadraturePoints_element; k++)
454 u_left += q_u[eN_left*nQuadraturePoints_element+k]*dV[eN_left*nQuadraturePoints_element+k];
455 vol_left += dV[eN_left*nQuadraturePoints_element+k];
456 u_right += q_u[eN_right*nQuadraturePoints_element+k]*dV[eN_right*nQuadraturePoints_element+k];
457 vol_right+= dV[eN_right*nQuadraturePoints_element+k];
458 tmp_left = q_lambda_bar[eN_left*nQuadraturePoints_element+k];
459 tmp_right = q_lambda_bar[eN_right*nQuadraturePoints_element+k];
460 maxSpeed_left = fabs(tmp_left) > maxSpeed_left ? fabs(tmp_left) : maxSpeed_left;
461 maxSpeed_right= fabs(tmp_right) > maxSpeed_right ? fabs(tmp_right) : maxSpeed_right;
465 maxSpeed_element = maxSpeed_right > maxSpeed_left ? maxSpeed_right : maxSpeed_left;
470 const int matID_left = materialTypes[eN_left];
471 psk->
setParams(&rwork_psk[matID_left*nParams]);
473 fracFlow.
calc(*psk,density_w_x,density_n_x);
474 const double fw_left=fracFlow.
fw;
const double fn_left=fracFlow.
fn;
const double law_left=fracFlow.
lambdaw;
475 const double rho_n_left=density_n_x.
rho;
const double rho_w_left = density_w_x.rho;
477 const int matID_right = materialTypes[eN_right];
478 psk->
setParams(&rwork_psk[matID_right*nParams]);
480 fracFlow.
calc(*psk,density_w_x,density_n_x);
481 const double fw_right=fracFlow.
fw;
const double fn_right=fracFlow.
fn;
const double law_right=fracFlow.
lambdaw;
482 const double rho_n_right=density_n_x.
rho;
const double rho_w_right = density_w_x.rho;
485 for (
int k=0; k < nQuadraturePoints_elementBoundary; k++)
488 for (
int I=0; I < nSpace; I++)
490 f_left[I] = ebq_global_qt[ebN*nQuadraturePoints_elementBoundary*nSpace + k*nSpace + I]*fw_left;
492 f_right[I]= ebq_global_qt[ebN*nQuadraturePoints_elementBoundary*nSpace + k*nSpace + I]*fw_right;
493 for (
int m=rowptr[I]; m < rowptr[I+1]; m++)
495 const int J = colind[m];
496 f_left[I] -= Kbar[matID_left*
nnz+m]*law_left*fn_left*(b*rho_n_left-rho_w_left)*g[J];
497 f_right[I]-= Kbar[matID_right*
nnz+m]*law_right*fn_right*(b*rho_n_right-rho_w_right)*g[J];
501 double left_flux=0.0,right_flux=0.0;
502 for (
int I=0; I < nSpace; I++)
504 left_flux +=
n[eN_left*nElementBoundaries_element*nQuadraturePoints_elementBoundary*nSpace+
505 ebN_left*nQuadraturePoints_elementBoundary*nSpace+k*nSpace+I]
508 right_flux +=
n[eN_left*nElementBoundaries_element*nQuadraturePoints_elementBoundary*nSpace+
509 ebN_left*nQuadraturePoints_elementBoundary*nSpace+k*nSpace+I]
514 const double maxSpeed =maxSpeed_element*safetyFactor;
515 flux[ebN*nQuadraturePoints_elementBoundary+k] = 0.5*(left_flux+right_flux) -0.5*maxSpeed*(u_right-u_left);
521 for (
int ebNE = 0; ebNE < nExteriorElementBoundaries_global; ebNE++)
523 const int ebN = exteriorElementBoundariesArray[ebNE];
524 const int eN_left =elementBoundaryElementsArray[ebN*2+0];
525 const int ebN_left =elementBoundaryLocalElementBoundariesArray[ebN*2+0];
529 double u_left=0.0,u_right=0.0,vol_left=0.0;
531 double maxSpeed_element=0.,maxSpeed_left=0.0,maxSpeed_right=0.0,tmp_left=0.0,tmp_right=0.0;
533 for (
int k = 0; k < nQuadraturePoints_element; k++)
535 u_left += q_u[eN_left*nQuadraturePoints_element+k]*dV[eN_left*nQuadraturePoints_element+k];
536 vol_left += dV[eN_left*nQuadraturePoints_element+k];
537 tmp_left = q_lambda_bar[eN_left*nQuadraturePoints_element+k];
538 maxSpeed_left = fabs(tmp_left) > maxSpeed_left ? fabs(tmp_left) : maxSpeed_left;
543 maxSpeed_element = maxSpeed_left;
548 const int matID_left = materialTypes[eN_left];
549 psk->
setParams(&rwork_psk[matID_left*nParams]);
551 fracFlow.
calc(*psk,density_w_x,density_n_x);
552 const double fw_left=fracFlow.
fw;
const double fn_left=fracFlow.
fn;
const double law_left=fracFlow.
lambdaw;
553 const double rho_n_left=density_n_x.
rho;
const double rho_w_left = density_w_x.rho;
557 const int matID_right = materialTypes[eN_left];
558 psk->
setParams(&rwork_psk[matID_right*nParams]);
561 for (
int k=0; k < nQuadraturePoints_elementBoundary; k++)
564 for (
int I=0; I < nSpace; I++)
566 f_left[I] = ebq_global_qt[ebN*nQuadraturePoints_elementBoundary*nSpace + k*nSpace + I]*fw_left;
567 for (
int m=rowptr[I]; m < rowptr[I+1]; m++)
569 const int J = colind[m];
570 f_left[I] -= Kbar[matID_left*
nnz+m]*law_left*fn_left*(b*rho_n_left-rho_w_left)*g[J];
573 if (isDOFBoundary[ebNE*nQuadraturePoints_elementBoundary+k])
575 u_right = bc_u[ebNE*nQuadraturePoints_elementBoundary+k];
577 fracFlow.
calc(*psk,density_w_x,density_n_x);
578 const double fw_right=fracFlow.
fw;
const double fn_right=fracFlow.
fn;
const double law_right=fracFlow.
lambdaw;
579 const double rho_n_right=density_n_x.
rho;
const double rho_w_right = density_w_x.rho;
581 for (
int I=0; I < nSpace; I++)
584 f_right[I]= ebq_global_qt[ebN*nQuadraturePoints_elementBoundary*nSpace + k*nSpace + I]*fw_right;
585 for (
int m=rowptr[I]; m < rowptr[I+1]; m++)
587 const int J = colind[m];
588 f_right[I]-= Kbar[matID_right*
nnz+m]*law_right*fn_right*(b*rho_n_right-rho_w_right)*g[J];
595 for (
int I=0; I < nSpace; I++)
596 f_right[I] = f_left[I];
599 double left_flux=0.0,right_flux=0.0;
600 for (
int I=0; I < nSpace; I++)
602 left_flux +=
n[eN_left*nElementBoundaries_element*nQuadraturePoints_elementBoundary*nSpace+
603 ebN_left*nQuadraturePoints_elementBoundary*nSpace+k*nSpace+I]
606 right_flux +=
n[eN_left*nElementBoundaries_element*nQuadraturePoints_elementBoundary*nSpace+
607 ebN_left*nQuadraturePoints_elementBoundary*nSpace+k*nSpace+I]
612 const double maxSpeed =maxSpeed_element*safetyFactor;
613 flux[ebN*nQuadraturePoints_elementBoundary+k] = 0.5*(left_flux+right_flux) -0.5*maxSpeed*(u_right-u_left);