proteus  1.8.1
C/C++/Fortran libraries
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  */
8 int 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
96 extern "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 
FractionalFlowVariables::fn
double fn
Definition: pskRelations.h:609
densityRelations.h
ConstantDensity
Definition: densityRelations.h:27
w
#define w(x)
Definition: jf.h:22
SubsurfaceTransportCoefficients.h
VGB
Definition: pskRelations.h:479
DensityRelation::rho
double rho
Definition: densityRelations.h:23
FractionalFlowVariables
Definition: pskRelations.h:597
n
Int n
Definition: Headers.h:28
calculateRusanovFluxSaturationEquationIncomp_PWC
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)
Definition: SubsurfaceTransportCoefficients.cpp:345
SimplePSK
Definition: pskRelations.h:106
PskRelation::calc
void calc(const double &Sw)
Definition: pskRelations.h:62
FractionalFlowVariables::lambdaw
double lambdaw
Definition: pskRelations.h:601
FractionalFlowVariables::fw
double fw
Definition: pskRelations.h:607
BCM
Definition: pskRelations.h:516
PskRelation::setParams
virtual void setParams(const double *rwork, const int *iwork=0)
Definition: pskRelations.h:50
PskRelation::setTolerances
virtual void setTolerances(const double *rwork_tol)
Definition: pskRelations.h:56
findInterval
int findInterval(const double *vertices, int nv, double x, int *ival, double tol)
Definition: SubsurfaceTransportCoefficients.cpp:8
pskRelations.h
FractionalFlowVariables::calc
void calc(const PskRelation &psk, const DensityRelation &density_w, const DensityRelation &density_n)
Definition: pskRelations.h:617
VGM
Definition: pskRelations.h:220
BCB
Definition: pskRelations.h:559
piecewiseLinearTableLookup
void piecewiseLinearTableLookup(double x, int nv, int *start, double *y, double *dy, const double *xv, const double *yv)
Definition: SubsurfaceTransportCoefficients.cpp:62
nnz
#define nnz
Definition: Richards.h:9
PskRelation
Definition: pskRelations.h:20