proteus 1.9.0
C/C++/Fortran libraries
Loading...
Searching...
No Matches
SubsurfaceTransportCoefficients.cpp
Go to the documentation of this file.
2#include "pskRelations.h"
3#include "densityRelations.h"
4
5/*simple piecewise linear interpolation from a table
6 assumes xv are increasing
7 */
8int findInterval(const double* vertices, int nv, double x, int* ival, double tol)
9{
10 int leftInt=0,rightInt=nv-2,failed=1,mid=0;
11 assert(rightInt >= leftInt);
12 /*take care of easy cases first*/
13 if (fabs(x-vertices[leftInt]) < tol)
14 {
15 *ival=leftInt;
16 failed=0;
17 return failed;
18 }
19 if (x <= vertices[leftInt]-tol)
20 {
21 *ival=-1;
22 failed=1;
23 return failed;
24 }
25 if (fabs(x-vertices[rightInt+1]) < tol)
26 {
27 *ival=rightInt;
28 failed=0;
29 return failed;
30 }
31 if (x >= vertices[rightInt+1]+tol)
32 {
33 *ival = nv;
34 failed=1;
35 return failed;
36 }
37 /*otherwise, should have x in (left,right)*/
38 while (leftInt <= rightInt)
39 {
40 mid = (int)(floor(0.5*(leftInt+rightInt)));
41 if (vertices[mid] <= x && x < vertices[mid+1])/*x in interval mid*/
42 {
43 *ival = mid;
44 failed = 0;
45 return failed;
46 }
47 else if (x < vertices[mid])/*x to the left of mid*/
48 rightInt = mid-1;
49 else if (x >= vertices[mid+1]) /*x to the right of mid*/
50 leftInt = mid+1;
51 else
52 {
53 std::cout<<"findInterval shouldn't be here leftInt= "<<leftInt<<" rightInt= "<<rightInt<<std::endl;
54 assert(0);
55 failed = 1;
56 return failed;
57 }
58 }
59 failed = 1;
60 return failed;
61}
63 int nv,
64 int* start,
65 double* y,
66 double* dy,
67 const double* xv,
68 const double* yv)
69{
70 int index=*start,findFailed=0;
71 double val,tol=1.0e-8;
72 findFailed = findInterval(xv,nv,x,&index,tol);
73 if (findFailed && index == -1)
74 {
75 /*extrapolate off left, could use endpoint instead*/
76 index=0;
77 }
78 else if (findFailed && index == nv)
79 {
80 /*extrapolate off right, could use endpoint instead*/
81 index = nv-2;
82 }
83 else
84 {
85 assert(0 <= index && index < nv-1);
86 assert(xv[index]-tol <= x && x<= xv[index+1]+tol);
87 }
88 assert(0 <= index && index < nv-1);
89 val = yv[index] + (yv[index+1]-yv[index])/(xv[index+1]-xv[index])*(x-xv[index]);
90 *y = val;
91 *dy = (yv[index+1]-yv[index])/(xv[index+1]-xv[index]);
92 *start = index;
93}
94
95#ifdef TRY_RE_NCP1
96extern "C" int RE_NCP1_getResidual_VGM(double rho, //physical coefficients
97 double beta,
98 const double * gravity,
99 const double * alphaVG,
100 const double * nVG,
101 const double * thetaR,
102 const double * thetaSR,
103 const double * KWs,
104 const int * KWs_rowptr,
105 const int * KWs_colind,
106 //mesh info
107 int nSpace,
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,
125 //solution info
126 int nDOF_trial_element,
127 int nDOF_test_element,
128 const double * u_dof,
129 const double * u_l2g,
130 //time integration
131 double alphaBDF,
132 const double * q_m_beta_bdf,
133 //storage to make upwinding simpler
134 double * q_kr,
135 //output for post-processing, time integration
136 double * q_m,
137 double * q_u,
138 double * q_cfl,
139 double * q_elementResidual,
140 //boundary integral info, need to simplify
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
146 //residual info
147 int offset_u,
148 int stride_u,
149 double * globalResidal,
150 )
151{
152 assert (nSpace+1 == nQuadraturePoints_element);
153 assert (nElementBoundaries_element == nSpace+1);
154 assert (nDOF_trial_element == nSpace+1);
155 //temporaries
156 double krw,dkrw,thetaw,dthetaw,rhom;
157 double KWs_ebN[9];
158 const double nAvgWeight = 1.0/(nSpace+1.);
159 double volFactor = 1.0;
160 if (nSpace == 2)
161 volFactor = 0.5;
162 if (nSpace == 3)
163 volFactor = 1.0/6.0;
164 const int nnz = KWs_rowptr[nSpace];
165 double w[4],grad_w[4][3],grad_u[3];
166
167 //evaluate mass term and element psk relations in first loop
168 //store kr for upwinding, then loop again for spatial integrals
169 for (int eN = 0; eN < nElements_global; eN++)
170 {
171 const double volume = volFactor * fabs(q_detJ[eN*nQuadraturePoints_element]);//affine
172 const int matID = elementMaterialTypes[eN];
173 const double weight = nAvgWeight*volume;
174
175 for (int ebN=0; ebN < nElementBoundaries_element; ebN++)
176 {
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,
181 alphaVG[matID],
182 nVG[matID],
183 thetaR[matID],
184 thetaSR[matID],
185 krw,thetaw,
186 dkrw,dthetaw);
187
188 q_kr[eN_ebN] = krw;
189 q_u[eN_ebN] = u_j;
190 //(diagonal) mass term
191 rhom = rho*exp(beta*u_j);
192 //save for time history
193 q_m[ebN_ebN] = rhom*thetaw;
194 const double m_t_ebN = alphaBDF*q_m + q_m_beta_bdf[eN_ebN];
195
196 q_elementResidual[eN_ebN] += weight*m_t_ebN;
197 globalResidual[offset_u+stride_u*u_l2g[eN_ebN]] += weight*m_t_ebN;
198
199 }//ebN
200 }//eN
201
202 //stiffness term
203 for (int eN = 0; eN < nElements_global; eN++)
204 {
205 evaluateTestFunctionsAndGradientsOnElement(nSpace,
206 eN,
207 &elementBarycentersArray[eN*3],
208 nodeArray,
209 elementBoundaryOuterNormalsArray,
210 w,
211 grad_w);
212 //constant on an element
213 for (int I = 0; I < nSpace; I++)
214 {
215 grad_u[I] = 0.0;
216 for (int j = 0; j < nDOF_trial_element; j++)
217 {
218 grad_u[I] += u_dof[u_l2g[eN*nDOF_trial_element+j]]*grad_w[j][I];
219 }
220 }
221 double kr_eN = 0.0,u_eN=0.0;
222 //averages for kr, upwinding
223 for (int ebN=0; ebN < nElementBoundaries_element; ebN++)
224 {
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;
228 }
229 //for upwinding
230 const double phi_eN = u_eN;
231 for (int I = 0; I < nSpace; I++)
232 phi_eN -= gravity[I]*elementBarycentersArray[eN*3+I];
233 //loop over each element, determine their contribution to each residual
234 //equation's stiffness term
235 for (int ebN=0; ebN < nElementBoundaries_element; ebN++)
236 {
237 const int eN_neighbor = elementNeighborsArray[eN*nElementBoundaries_element + ebN];
238 //by default current element is upwind
239 double kr_up = kr_eN;
240 if (eN_neighbor >= 0)
241 {
242 const matID_neighbor = elementMaterialTypes[eN_neighbor];
243 //harmonic average for intrinsic perm
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);
246
247 //averages for kr, upwinding
248 double kr_neig = 0.0,u_neig=0.0;
249
250 for (int ebN_neig=0; ebN_neig < nElementBoundaries_element; ebN_neig++)
251 {
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;
255 }
256
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];
260
261 if (phi_neig > phi_eN)
262 {
263 kr_up = kr_neig;
264 }
265 }//interior face
266 else //exterior face
267 {
268 for (int ii=0; ii < nnz; ii++)
269 KWs_ebN[ii] = KWs[matID*nnz+ii];
270 //todo could upwind using Dirichlet bc
271 }
272 //loop through element residuals and accumulate contribution of this face to advection and stiffness integrals
273 for (int i =0; i < nDOF_test_element; i++)
274 {
275 const int eN_i = eN*nDOF_test_element + i;
276 for (int I = 0; I < nSpace; I++)
277 {
278 for (int ii=KWs_rowptr[I]; ii < KWs_rowptr[I+1]; ii++)
279 {
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];
284
285 }//ii
286 }//I
287 }//test functions
288 }//element boundaries
289 }//eN stiffness integrals
290
291 //boundary conditions, Dirichlet done strongly
292 //could assume ebN agrees with global dof,
293 //but need q_elementResidual for post-processing
294 //could use ebN --> eN,ebN_local mapping to get which test function is
295 //nonzero on the element
296 //todo need to decide about how to get element boundary areas
297 double elementResidual[4];
298 for (int ebNE = 0; ebNE < nExteriorElementBoundaries_global; ebNE++)
299 {
300 const int ebN = exteriorElementBoundariesArray[ebNE];
301 const int eN = elementBoundaryElementsArray[ebN*2+0];
302
303 for (int kb = 0; kb < nQuadraturePoints_elementBoundary; kb++)
304 {
305 const int ebNE_kb = ebNE*nQuadraturePoints_elementBoundary + kb;
306 if (isFluxBoundary_u[ebNE_kb])
307 {
308 for (int i = 0; i < nDOF_test_element; i++)
309 {
310 elementResidual[i] += ebqe_flux[ebNE_kb]*ebqe_w_dS[ebNE_kb];
311 }
312 }
313 }//kb
314 for (int i = 0; i < nDOF_test_element; i++)
315 {
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];
318 }
319 }//ebNE
320
321 //apply dirichlet bc's strongly?
322 for (int ebNE = 0; ebNE < nExteriorElementBoundaries_global; ebNE++)
323 {
324 const int ebN = exteriorElementBoundariesArray[ebNE];
325 const int eN = elementBoundaryElementsArray[ebN*2+0];
326 //assume bc's constant on a face
327 if (isDOFBoundary_u[ebNE*nQuadraturePoints_elementBoundary])
328 {
329 for (int j = 0; j < nElementBoundaries_element; j++)
330 {
331 if (elementBoundariesArray[eN*nElementBoundaries_element + j] == ebN)
332 {
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];
334 }
335 }
336 }
337 }
338}
339//end TRY_RE_NCP1
340#endif
341//--------------------------------------------------
342//calculate Rusanov flux at global boundaries using
343//piecewise constant information
344//--------------------------------------------------
346 int nSpace,
347 //physical information
348 //psk type
349 int pskModelFlag,
350 int nParams,
351 const int* rowptr,
352 const int* colind,
353 const int* materialTypes,
354 double muw,
355 double mun,
356 const double* omega,
357 const double* Kbar,
358 double b,
359 const double* rwork_psk,
360 const double* rwork_psk_tol,
361 const double* rwork_density_w,
362 const double* rwork_density_n,
363 const double* g,
364 //velocity at interface
365 const double* ebq_global_qt,
366 //bounds on characteristic speed for elements
367 const double* q_lambda_bar,
368 //mesh information
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,
379 const double* n,
380 //solution information
381 const double * q_u,
382 //element quadrature
383 const double* dV,
384 //int nDOF_trial_element,
385 //const int* u_l2g,
386 //const double* u_dof,
387 //boundary information
388 const int * isDOFBoundary,
389 const double* bc_u,
390 //output
391 double* flux)
392{
393 //loop over interior faces, compute average solution value for right and left
394 //assumes characteristic speed bound has been computed on each element at
395 //quadrature points
396 //assuming incompressible fractional flow formulation
397 //apply rusanov flux formula to calculate numerical flux at face assuming oriented
398 //in direction of 'left' aka 0 element neighbor
399 //
400 //loop over exterior faces, repeat averaging step and
401 //apply rusanov flux at dof boundaries using bc condition assumed constant over face
402 //as 'right' state
403
404 int failed =0;
405 //coefficients for 2-phase flow incompressible (slightly compressible should be same)
406 PskRelation* psk;
407 switch (pskModelFlag)
408 {
409 case 0:
410 psk = new SimplePSK(rwork_psk);
411 break;
412 case 1:
413 psk = new VGM(rwork_psk);
414 break;
415 case 2:
416 psk = new VGB(rwork_psk);
417 break;
418 case 3:
419 psk = new BCM(rwork_psk);
420 break;
421 case 4:
422 psk = new BCB(rwork_psk);
423 break;
424 default:
425 std::cerr<<"pskModelFlag= "<<pskModelFlag<<" not recognized"<<std::endl;
426 assert (false);
427 break;
428 }//psk model selection
429 psk->setTolerances(rwork_psk_tol);
430 FractionalFlowVariables fracFlow(muw,mun);
431 //normalized densities \rho_{\alpha} = \varrho_{\alpha}/\varrho_{\alpha,0}
432 // for spatial term, assuming slight compressiblity so assume \rho_{\alpha} = 1
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.};
437
438 for (int ebNI = 0; ebNI < nInteriorElementBoundaries_global; ebNI++)
439 {
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];
445
446 //compute:
447 // left and right states
448 double u_left=0.0,u_right=0.0,vol_left=0.0,vol_right=0.0;
449 // max speeds on element
450 double maxSpeed_element=0.,maxSpeed_left=0.0,maxSpeed_right=0.0,tmp_left=0.0,tmp_right=0.0;
451
452 for (int k = 0; k < nQuadraturePoints_element; k++)
453 {
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;
462 }
463 u_left /= vol_left;
464 u_right/= vol_right;
465 maxSpeed_element = maxSpeed_right > maxSpeed_left ? maxSpeed_right : maxSpeed_left;
466
467 //compute fluxes at left and right state assuming two-phase saturation equation
468 //since just using averages compute values and save them
469 //left
470 const int matID_left = materialTypes[eN_left];
471 psk->setParams(&rwork_psk[matID_left*nParams]);
472 psk->calc(u_left);
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;
476 //right
477 const int matID_right = materialTypes[eN_right];
478 psk->setParams(&rwork_psk[matID_right*nParams]);
479 psk->calc(u_right);
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;
483
484 //stuck with quadrature point loop for now
485 for (int k=0; k < nQuadraturePoints_elementBoundary; k++)
486 {
487 //redundant except for qt
488 for (int I=0; I < nSpace; I++)
489 {
490 f_left[I] = ebq_global_qt[ebN*nQuadraturePoints_elementBoundary*nSpace + k*nSpace + I]*fw_left;
491 //todo think through sign
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++)
494 {
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];
498 }
499 }
500
501 double left_flux=0.0,right_flux=0.0;
502 for (int I=0; I < nSpace; I++)
503 {
504 left_flux += n[eN_left*nElementBoundaries_element*nQuadraturePoints_elementBoundary*nSpace+
505 ebN_left*nQuadraturePoints_elementBoundary*nSpace+k*nSpace+I]
506 *
507 f_left[I];
508 right_flux += n[eN_left*nElementBoundaries_element*nQuadraturePoints_elementBoundary*nSpace+
509 ebN_left*nQuadraturePoints_elementBoundary*nSpace+k*nSpace+I]
510 *
511 f_right[I];
512 }
513
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);
516 }//k
517
518 }//ebNI
519
520 //exterior element boundaries
521 for (int ebNE = 0; ebNE < nExteriorElementBoundaries_global; ebNE++)
522 {
523 const int ebN = exteriorElementBoundariesArray[ebNE];
524 const int eN_left =elementBoundaryElementsArray[ebN*2+0];
525 const int ebN_left =elementBoundaryLocalElementBoundariesArray[ebN*2+0];
526
527 //compute:
528 // left and right states
529 double u_left=0.0,u_right=0.0,vol_left=0.0;
530 // max speeds on element
531 double maxSpeed_element=0.,maxSpeed_left=0.0,maxSpeed_right=0.0,tmp_left=0.0,tmp_right=0.0;
532
533 for (int k = 0; k < nQuadraturePoints_element; k++)
534 {
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;
539 }
540 u_left /= vol_left;
541
542 //todo compute bounds for speed using dirichlet information
543 maxSpeed_element = maxSpeed_left;
544
545 //compute fluxes at left and right state assuming two-phase saturation equation
546 //since just using averages compute values and save them
547 //left
548 const int matID_left = materialTypes[eN_left];
549 psk->setParams(&rwork_psk[matID_left*nParams]);
550 psk->calc(u_left);
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;
554
555
556 //right
557 const int matID_right = materialTypes[eN_left];
558 psk->setParams(&rwork_psk[matID_right*nParams]);
559
560 //stuck with quadrature point loop for now
561 for (int k=0; k < nQuadraturePoints_elementBoundary; k++)
562 {
563 //redundant except for qt
564 for (int I=0; I < nSpace; I++)
565 {
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++)
568 {
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];
571 }
572 }
573 if (isDOFBoundary[ebNE*nQuadraturePoints_elementBoundary+k])
574 {
575 u_right = bc_u[ebNE*nQuadraturePoints_elementBoundary+k];
576 psk->calc(u_right);
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;
580
581 for (int I=0; I < nSpace; I++)
582 {
583 //todo think through sign
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++)
586 {
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];
589 }
590 }
591 }
592 else
593 {
594 u_right=u_left;
595 for (int I=0; I < nSpace; I++)
596 f_right[I] = f_left[I];
597 }
598
599 double left_flux=0.0,right_flux=0.0;
600 for (int I=0; I < nSpace; I++)
601 {
602 left_flux += n[eN_left*nElementBoundaries_element*nQuadraturePoints_elementBoundary*nSpace+
603 ebN_left*nQuadraturePoints_elementBoundary*nSpace+k*nSpace+I]
604 *
605 f_left[I];
606 right_flux += n[eN_left*nElementBoundaries_element*nQuadraturePoints_elementBoundary*nSpace+
607 ebN_left*nQuadraturePoints_elementBoundary*nSpace+k*nSpace+I]
608 *
609 f_right[I];
610 }
611
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);
614 }//k
615
616 }//ebNE
617
618 //clean up
619 delete psk;
620
621 return failed;
622}
623
Int n
Definition Headers.h:28
int calculateRusanovFluxSaturationEquationIncomp_PWC(double safetyFactor, int nSpace, int pskModelFlag, int nParams, const int *rowptr, const int *colind, const int *materialTypes, double muw, double mun, const double *omega, const double *Kbar, double b, const double *rwork_psk, const double *rwork_psk_tol, const double *rwork_density_w, const double *rwork_density_n, const double *g, const double *ebq_global_qt, const double *q_lambda_bar, int nElements_global, int nElementBoundaries_element, int nInteriorElementBoundaries_global, int nExteriorElementBoundaries_global, int nQuadraturePoints_element, int nQuadraturePoints_elementBoundary, const int *interiorElementBoundariesArray, const int *exteriorElementBoundariesArray, const int *elementBoundaryElementsArray, const int *elementBoundaryLocalElementBoundariesArray, const double *n, const double *q_u, const double *dV, const int *isDOFBoundary, const double *bc_u, double *flux)
int findInterval(const double *vertices, int nv, double x, int *ival, double tol)
void piecewiseLinearTableLookup(double x, int nv, int *start, double *y, double *dy, const double *xv, const double *yv)
BCB(const double *rwork, const int *iwork=0)
BCM(const double *rwork, const int *iwork=0)
void calc(const PskRelation &psk, const DensityRelation &density_w, const DensityRelation &density_n)
void calc(const double &Sw)
virtual void setParams(const double *rwork, const int *iwork=0)
virtual void setTolerances(const double *rwork_tol)
SimplePSK(const double *rwork, const int *iwork=0)
VGB(const double *rwork, const int *iwork=0)
#define w(x)
Definition jf.h:22
#define nnz
Definition m_comp_co2.h:19
Richards free-function PSK closures (moved here from proteus/richards/psk_models.h).