NcpFlash.hpp
Go to the documentation of this file.
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  Copyright (C) 2011-2013 by Andreas Lauser
5 
6  This file is part of the Open Porous Media project (OPM).
7 
8  OPM is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 2 of the License, or
11  (at your option) any later version.
12 
13  OPM is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with OPM. If not, see <http://www.gnu.org/licenses/>.
20 */
25 #ifndef OPM_NCP_FLASH_HPP
26 #define OPM_NCP_FLASH_HPP
27 
28 #include <dune/common/fvector.hh>
29 #include <dune/common/fmatrix.hh>
30 
34 #include <opm/common/ErrorMacros.hpp>
35 #include <opm/common/Exceptions.hpp>
38 
39 #include <limits>
40 #include <iostream>
41 
42 namespace Opm {
43 
83 template <class Scalar, class FluidSystem>
84 class NcpFlash
85 {
86  enum { numPhases = FluidSystem::numPhases };
87  enum { numComponents = FluidSystem::numComponents };
88 
89  typedef typename FluidSystem::ParameterCache ParameterCache;
90 
91  static const int numEq = numPhases*(numComponents + 1);
92 
93 public:
97  template <class FluidState, class Evaluation = typename FluidState::Scalar>
98  static void guessInitial(FluidState &fluidState,
99  ParameterCache &paramCache,
100  const Dune::FieldVector<Evaluation, numComponents>& globalMolarities)
101  {
102  // the sum of all molarities
103  Evaluation sumMoles = 0;
104  for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx)
105  sumMoles += globalMolarities[compIdx];
106 
107  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
108  // composition
109  for (unsigned compIdx = 0; compIdx < numComponents; ++ compIdx)
110  fluidState.setMoleFraction(phaseIdx,
111  compIdx,
112  globalMolarities[compIdx]/sumMoles);
113 
114  // pressure. use atmospheric pressure as initial guess
115  fluidState.setPressure(phaseIdx, 1.0135e5);
116 
117  // saturation. assume all fluids to be equally distributed
118  fluidState.setSaturation(phaseIdx, 1.0/numPhases);
119  }
120 
121  // set the fugacity coefficients of all components in all phases
122  paramCache.updateAll(fluidState);
123  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
124  for (unsigned compIdx = 0; compIdx < numComponents; ++ compIdx) {
125  const typename FluidState::Scalar phi =
126  FluidSystem::fugacityCoefficient(fluidState, paramCache, phaseIdx, compIdx);
127  fluidState.setFugacityCoefficient(phaseIdx, compIdx, phi);
128  }
129  }
130  }
131 
138  template <class MaterialLaw, class FluidState>
139  static void solve(FluidState &fluidState,
140  ParameterCache &paramCache,
141  const typename MaterialLaw::Params &matParams,
142  const Dune::FieldVector<typename FluidState::Scalar, numComponents>& globalMolarities,
143  Scalar tolerance = 0.0)
144  {
145  typedef typename FluidState::Scalar Evaluation;
146  typedef Dune::FieldMatrix<Evaluation, numEq, numEq> Matrix;
147  typedef Dune::FieldVector<Evaluation, numEq> Vector;
148 
149  Dune::FMatrixPrecision<Scalar>::set_singular_limit(1e-35);
150 
151  if (tolerance <= 0.0) {
152  tolerance = std::min<Scalar>(1e-10,
153  Opm::geometricMean(Scalar(1.0),
154  std::numeric_limits<Scalar>::epsilon()));
155  }
156 
158  // Newton method
160 
161  // Jacobian matrix
162  Matrix J;
163  // solution, i.e. phase composition
164  Vector deltaX;
165  // right hand side
166  Vector b;
167 
169  Valgrind::SetUndefined(deltaX);
171 
172  // make the fluid state consistent with the fluid system.
173  completeFluidState_<MaterialLaw>(fluidState,
174  paramCache,
175  matParams);
176 
177  /*
178  std::cout << "--------------------\n";
179  std::cout << "globalMolarities: ";
180  for (unsigned compIdx = 0; compIdx < numComponents; ++ compIdx)
181  std::cout << globalMolarities[compIdx] << " ";
182  std::cout << "\n";
183  */
184  const int nMax = 50; // <- maximum number of newton iterations
185  for (int nIdx = 0; nIdx < nMax; ++nIdx) {
186  // calculate Jacobian matrix and right hand side
187  linearize_<MaterialLaw>(J,
188  b,
189  fluidState,
190  paramCache,
191  matParams,
192  globalMolarities);
195 
196  // Solve J*x = b
197  deltaX = 0;
198 
199  try { J.solve(deltaX, b); }
200  catch (Dune::FMatrixError e)
201  {
202  /*
203  printFluidState_(fluidState);
204  std::cout << "error: " << e << "\n";
205  std::cout << "b: " << b << "\n";
206  std::cout << "J: " << J << "\n";
207  */
208 
209  throw Opm::NumericalProblem(e.what());
210  }
211  Valgrind::CheckDefined(deltaX);
212 
213  /*
214  printFluidState_(fluidState);
215  std::cout << "J:\n";
216  for (int i = 0; i < numEq; ++i) {
217  for (int j = 0; j < numEq; ++j) {
218  std::ostringstream os;
219  os << J[i][j];
220 
221  std::string s(os.str());
222  do {
223  s += " ";
224  } while (s.size() < 20);
225  std::cout << s;
226  }
227  std::cout << "\n";
228  }
229 
230  std::cout << "deltaX: " << deltaX << "\n";
231  std::cout << "---------------\n";
232  */
233 
234  // update the fluid quantities.
235  //update_<MaterialLaw>(fluidState, paramCache, matParams, deltaX);
236  Scalar relError = update_<MaterialLaw>(fluidState, paramCache, matParams, deltaX);
237 
238  if (relError < 1e-9)
239  return;
240  }
241 
242  /*
243  printFluidState_(fluidState);
244  std::cout << "globalMolarities: ";
245  for (unsigned compIdx = 0; compIdx < numComponents; ++ compIdx)
246  std::cout << globalMolarities[compIdx] << " ";
247  std::cout << "\n";
248  */
249 
250  OPM_THROW(NumericalProblem,
251  "Flash calculation failed."
252  " {c_alpha^kappa} = {" << globalMolarities << "}, T = "
253  << fluidState.temperature(/*phaseIdx=*/0));
254  }
255 
263  template <class FluidState, class ComponentVector>
264  static void solve(FluidState &fluidState,
265  const ComponentVector &globalMolarities,
266  Scalar tolerance = 0.0)
267  {
268  ParameterCache paramCache;
269  paramCache.updateAll(fluidState);
270 
271  typedef NullMaterialTraits<Scalar, numPhases> MaterialTraits;
272  typedef NullMaterial<MaterialTraits> MaterialLaw;
273  typedef typename MaterialLaw::Params MaterialLawParams;
274 
275  MaterialLawParams matParams;
276  solve<MaterialLaw>(fluidState, paramCache, matParams, globalMolarities, tolerance);
277  }
278 
279 
280 protected:
281  template <class FluidState>
282  static void printFluidState_(const FluidState &fluidState)
283  {
284  std::cout << "saturations: ";
285  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
286  std::cout << fluidState.saturation(phaseIdx) << " ";
287  std::cout << "\n";
288 
289  std::cout << "pressures: ";
290  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
291  std::cout << fluidState.pressure(phaseIdx) << " ";
292  std::cout << "\n";
293 
294  std::cout << "densities: ";
295  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
296  std::cout << fluidState.density(phaseIdx) << " ";
297  std::cout << "\n";
298 
299  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
300  std::cout << "composition " << FluidSystem::phaseName(phaseIdx) << "Phase: ";
301  for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
302  std::cout << fluidState.moleFraction(phaseIdx, compIdx) << " ";
303  }
304  std::cout << "\n";
305  }
306 
307  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
308  std::cout << "fugacities " << FluidSystem::phaseName(phaseIdx) << "Phase: ";
309  for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
310  std::cout << fluidState.fugacity(phaseIdx, compIdx) << " ";
311  }
312  std::cout << "\n";
313  }
314 
315  std::cout << "global component molarities: ";
316  for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
317  Scalar sum = 0;
318  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
319  sum += fluidState.saturation(phaseIdx)*fluidState.molarity(phaseIdx, compIdx);
320  }
321  std::cout << sum << " ";
322  }
323  std::cout << "\n";
324  }
325 
326  template <class MaterialLaw,
327  class FluidState,
328  class Matrix,
329  class Vector,
330  class ComponentVector>
331  static void linearize_(Matrix &J,
332  Vector &b,
333  FluidState &fluidState,
334  ParameterCache &paramCache,
335  const typename MaterialLaw::Params &matParams,
336  const ComponentVector &globalMolarities)
337  {
338  typedef typename FluidState::Scalar Evaluation;
339 
340  FluidState origFluidState(fluidState);
341  ParameterCache origParamCache(paramCache);
342 
343  Vector tmp;
344 
345  // reset jacobian
346  J = 0;
347 
349  calculateDefect_(b, fluidState, fluidState, globalMolarities);
351 
353  // assemble jacobian matrix
355  for (unsigned pvIdx = 0; pvIdx < numEq; ++ pvIdx) {
357  // approximately calculate partial derivatives of the
358  // fugacity defect of all components in regard to the mole
359  // fraction of the i-th component. This is done via
360  // forward differences
361 
362  // deviate the mole fraction of the i-th component
363  const Evaluation& x_i = getQuantity_(fluidState, pvIdx);
364  const Scalar eps = std::numeric_limits<Scalar>::epsilon()*1e7/(quantityWeight_(fluidState, pvIdx));
365 
366  setQuantity_<MaterialLaw>(fluidState, paramCache, matParams, pvIdx, x_i + eps);
367 
368  // compute derivative of the defect
369  calculateDefect_(tmp, origFluidState, fluidState, globalMolarities);
370  tmp -= b;
371  for (unsigned i = 0; i < numEq; ++ i)
372  tmp[i] /= eps;
373 
374  // store derivative in jacobian matrix
375  for (unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx)
376  J[eqIdx][pvIdx] = tmp[eqIdx];
377 
378  // fluid state and parameter cache to their original values
379  fluidState = origFluidState;
380  paramCache = origParamCache;
381 
382  // end forward differences
384  }
385  }
386 
387  template <class FluidState, class Vector, class ComponentVector>
388  static void calculateDefect_(Vector &b,
389  const FluidState &fluidStateEval,
390  const FluidState &fluidState,
391  const ComponentVector &globalMolarities)
392  {
393  typedef typename FluidState::Scalar Evaluation;
394 
395  unsigned eqIdx = 0;
396 
397  // fugacity of any component must be equal in all phases
398  for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
399  for (unsigned phaseIdx = 1; phaseIdx < numPhases; ++phaseIdx) {
400  b[eqIdx] =
401  fluidState.fugacity(/*phaseIdx=*/0, compIdx)
402  - fluidState.fugacity(phaseIdx, compIdx);
403  ++eqIdx;
404  }
405  }
406 
407  assert(eqIdx == numComponents*(numPhases - 1));
408 
409  // the fact saturations must sum up to 1 is included implicitly and also,
410  // capillary pressures are treated implicitly!
411 
412  // global molarities are given
413  for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
414  b[eqIdx] = 0.0;
415  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
416  b[eqIdx] +=
417  fluidState.saturation(phaseIdx)
418  * fluidState.molarity(phaseIdx, compIdx);
419  }
420 
421  b[eqIdx] -= globalMolarities[compIdx];
422  ++eqIdx;
423  }
424 
425  // model assumptions (-> non-linear complementarity functions) must be adhered
426  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
427  Evaluation sumMoleFracEval = 0.0;
428  for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx)
429  sumMoleFracEval += fluidStateEval.moleFraction(phaseIdx, compIdx);
430 
431  if (1.0 - sumMoleFracEval > fluidStateEval.saturation(phaseIdx)) {
432  b[eqIdx] = fluidState.saturation(phaseIdx);
433  }
434  else {
435  Evaluation sumMoleFrac = 0.0;
436  for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx)
437  sumMoleFrac += fluidState.moleFraction(phaseIdx, compIdx);
438  b[eqIdx] = 1.0 - sumMoleFrac;
439  }
440 
441  ++eqIdx;
442  }
443  }
444 
445  template <class MaterialLaw, class FluidState, class Vector>
446  static Scalar update_(FluidState &fluidState,
447  ParameterCache &paramCache,
448  const typename MaterialLaw::Params &matParams,
449  const Vector &deltaX)
450  {
451  typedef typename FluidState::Scalar Evaluation;
452  typedef Opm::MathToolbox<Evaluation> Toolbox;
453 
454  // make sure we don't swallow non-finite update vectors
455 #ifndef NDEBUG
456  assert(deltaX.dimension == numEq);
457  for (unsigned i = 0; i < numEq; ++i)
458  assert(std::isfinite(Toolbox::value(deltaX[i])));
459 #endif
460 
461  Scalar relError = 0;
462  for (unsigned pvIdx = 0; pvIdx < numEq; ++ pvIdx) {
463  const Evaluation& tmp = getQuantity_(fluidState, pvIdx);
464  Evaluation delta = deltaX[pvIdx];
465 
466  relError = std::max<Scalar>(relError,
467  std::abs(Toolbox::value(delta))
468  * quantityWeight_(fluidState, pvIdx));
469 
470  if (isSaturationIdx_(pvIdx)) {
471  // dampen to at most 25% change in saturation per iteration
472  delta = Toolbox::min(0.25, Toolbox::max(-0.25, delta));
473  }
474  else if (isMoleFracIdx_(pvIdx)) {
475  // dampen to at most 20% change in mole fraction per iteration
476  delta = Toolbox::min(0.20, Toolbox::max(-0.20, delta));
477  }
478  else if (isPressureIdx_(pvIdx)) {
479  // dampen to at most 50% change in pressure per iteration
480  delta = Toolbox::min(0.5*fluidState.pressure(0),
481  Toolbox::max(-0.5*fluidState.pressure(0), delta));
482  }
483 
484  setQuantityRaw_(fluidState, pvIdx, tmp - delta);
485  }
486 
487  /*
488  // make sure all saturations, pressures and mole fractions are non-negative
489  Scalar sumSat = 0;
490  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
491  Scalar value = fluidState.saturation(phaseIdx);
492  if (value < -0.05) {
493  value = -0.05;
494  fluidState.setSaturation(phaseIdx, value);
495  }
496  sumSat += value;
497 
498  value = fluidState.pressure(phaseIdx);
499  if (value < 0)
500  fluidState.setPressure(phaseIdx, 0.0);
501 
502  for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
503  value = fluidState.moleFraction(phaseIdx, compIdx);
504  if (value < 0)
505  fluidState.setMoleFraction(phaseIdx, compIdx, 0.0);
506  }
507  }
508 
509  // last saturation
510  if (sumSat > 1.05) {
511  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
512  Scalar value = fluidState.saturation(phaseIdx)/(0.95*sumSat);
513  fluidState.setSaturation(phaseIdx, value);
514  }
515  }
516  */
517 
518  completeFluidState_<MaterialLaw>(fluidState, paramCache, matParams);
519 
520  return relError;
521  }
522 
523  template <class MaterialLaw, class FluidState>
524  static void completeFluidState_(FluidState &fluidState,
525  ParameterCache &paramCache,
526  const typename MaterialLaw::Params &matParams)
527  {
528  typedef typename FluidState::Scalar Evaluation;
529 
530  // calculate the saturation of the last phase as a function of
531  // the other saturations
532  Evaluation sumSat = 0.0;
533  for (unsigned phaseIdx = 0; phaseIdx < numPhases - 1; ++phaseIdx)
534  sumSat += fluidState.saturation(phaseIdx);
535  fluidState.setSaturation(/*phaseIdx=*/numPhases - 1, 1.0 - sumSat);
536 
537  // update the pressures using the material law (saturations
538  // and first pressure are already set because it is implicitly
539  // solved for.)
540  Dune::FieldVector<Scalar, numPhases> pC;
541  MaterialLaw::capillaryPressures(pC, matParams, fluidState);
542  for (unsigned phaseIdx = 1; phaseIdx < numPhases; ++phaseIdx)
543  fluidState.setPressure(phaseIdx,
544  fluidState.pressure(0)
545  + (pC[phaseIdx] - pC[0]));
546 
547  // update the parameter cache
548  paramCache.updateAll(fluidState, /*except=*/ParameterCache::Temperature);
549 
550  // update all densities and fugacity coefficients
551  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
552  const Evaluation& rho = FluidSystem::density(fluidState, paramCache, phaseIdx);
553  fluidState.setDensity(phaseIdx, rho);
554 
555  for (unsigned compIdx = 0; compIdx < numComponents; ++ compIdx) {
556  const Evaluation& phi = FluidSystem::fugacityCoefficient(fluidState, paramCache, phaseIdx, compIdx);
557  fluidState.setFugacityCoefficient(phaseIdx, compIdx, phi);
558  }
559  }
560  }
561 
562  static bool isPressureIdx_(unsigned pvIdx)
563  { return pvIdx == 0; }
564 
565  static bool isSaturationIdx_(unsigned pvIdx)
566  { return 1 <= pvIdx && pvIdx < numPhases; }
567 
568  static bool isMoleFracIdx_(unsigned pvIdx)
569  { return numPhases <= pvIdx && pvIdx < numPhases + numPhases*numComponents; }
570 
571  // retrieves a quantity from the fluid state
572  template <class FluidState>
573  static const typename FluidState::Scalar& getQuantity_(const FluidState &fluidState, unsigned pvIdx)
574  {
575  assert(pvIdx < numEq);
576 
577  // first pressure
578  if (pvIdx < 1) {
579  unsigned phaseIdx = 0;
580  return fluidState.pressure(phaseIdx);
581  }
582  // first M - 1 saturations
583  else if (pvIdx < numPhases) {
584  unsigned phaseIdx = pvIdx - 1;
585  return fluidState.saturation(phaseIdx);
586  }
587  // mole fractions
588  else // if (pvIdx < numPhases + numPhases*numComponents)
589  {
590  unsigned phaseIdx = (pvIdx - numPhases)/numComponents;
591  unsigned compIdx = (pvIdx - numPhases)%numComponents;
592  return fluidState.moleFraction(phaseIdx, compIdx);
593  }
594  }
595 
596  // set a quantity in the fluid state
597  template <class MaterialLaw, class FluidState>
598  static void setQuantity_(FluidState &fluidState,
599  ParameterCache &paramCache,
600  const typename MaterialLaw::Params &matParams,
601  unsigned pvIdx,
602  const typename FluidState::Scalar& value)
603  {
604  typedef typename FluidState::Scalar Evaluation;
605 
606  assert(0 <= pvIdx && pvIdx < numEq);
607 
608  if (pvIdx < 1) { // <- first pressure
609  Evaluation delta = value - fluidState.pressure(0);
610 
611  // set all pressures. here we assume that the capillary
612  // pressure does not depend on absolute pressure.
613  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
614  fluidState.setPressure(phaseIdx, fluidState.pressure(phaseIdx) + delta);
615  paramCache.updateAllPressures(fluidState);
616 
617  // update all densities and fugacity coefficients
618  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
619  const Evaluation& rho = FluidSystem::density(fluidState, paramCache, phaseIdx);
621  fluidState.setDensity(phaseIdx, rho);
622 
623  for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
624  const Evaluation& phi = FluidSystem::fugacityCoefficient(fluidState, paramCache, phaseIdx, compIdx);
626  fluidState.setFugacityCoefficient(phaseIdx, compIdx, phi);
627  }
628  }
629  }
630  else if (pvIdx < numPhases) { // <- first M - 1 saturations
631  const Evaluation& delta = value - fluidState.saturation(/*phaseIdx=*/pvIdx - 1);
632  Valgrind::CheckDefined(delta);
633  fluidState.setSaturation(/*phaseIdx=*/pvIdx - 1, value);
634 
635  // set last saturation (-> minus the change of the saturation of the other
636  // phase)
637  fluidState.setSaturation(/*phaseIdx=*/numPhases - 1,
638  fluidState.saturation(numPhases - 1) - delta);
639 
640  // update all fluid pressures using the capillary pressure law
641  Dune::FieldVector<Evaluation, numPhases> pC;
642  MaterialLaw::capillaryPressures(pC, matParams, fluidState);
644  for (unsigned phaseIdx = 1; phaseIdx < numPhases; ++phaseIdx)
645  fluidState.setPressure(phaseIdx,
646  fluidState.pressure(0)
647  + (pC[phaseIdx] - pC[0]));
648  paramCache.updateAllPressures(fluidState);
649 
650  // update all densities and fugacity coefficients
651  for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
652  const Evaluation& rho = FluidSystem::density(fluidState, paramCache, phaseIdx);
654  fluidState.setDensity(phaseIdx, rho);
655 
656  for (unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
657  const Evaluation& phi = FluidSystem::fugacityCoefficient(fluidState, paramCache, phaseIdx, compIdx);
659  fluidState.setFugacityCoefficient(phaseIdx, compIdx, phi);
660  }
661  }
662  }
663  else if (pvIdx < numPhases + numPhases*numComponents) // <- mole fractions
664  {
665  unsigned phaseIdx = (pvIdx - numPhases)/numComponents;
666  unsigned compIdx = (pvIdx - numPhases)%numComponents;
667 
668  Valgrind::CheckDefined(value);
669  fluidState.setMoleFraction(phaseIdx, compIdx, value);
670  paramCache.updateSingleMoleFraction(fluidState, phaseIdx, compIdx);
671 
672  // update the density of the phase
673  const Evaluation& rho = FluidSystem::density(fluidState, paramCache, phaseIdx);
675  fluidState.setDensity(phaseIdx, rho);
676 
677  // if the phase's fugacity coefficients are composition
678  // dependent, update them as well.
679  if (!FluidSystem::isIdealMixture(phaseIdx)) {
680  for (unsigned fugCompIdx = 0; fugCompIdx < numComponents; ++fugCompIdx) {
681  const Evaluation& phi = FluidSystem::fugacityCoefficient(fluidState, paramCache, phaseIdx, fugCompIdx);
683  fluidState.setFugacityCoefficient(phaseIdx, fugCompIdx, phi);
684  }
685  }
686  }
687  else {
688  assert(false);
689  }
690  }
691 
692  // set a quantity in the fluid state
693  template <class FluidState>
694  static void setQuantityRaw_(FluidState &fluidState,
695  unsigned pvIdx,
696  const typename FluidState::Scalar& value)
697  {
698  assert(pvIdx < numEq);
699 
700  Valgrind::CheckDefined(value);
701  // first pressure
702  if (pvIdx < 1) {
703  unsigned phaseIdx = 0;
704  fluidState.setPressure(phaseIdx, value);
705  }
706  // first M - 1 saturations
707  else if (pvIdx < numPhases) {
708  unsigned phaseIdx = pvIdx - 1;
709  fluidState.setSaturation(phaseIdx, value);
710  }
711  // mole fractions
712  else // if (pvIdx < numPhases + numPhases*numComponents)
713  {
714  unsigned phaseIdx = (pvIdx - numPhases)/numComponents;
715  unsigned compIdx = (pvIdx - numPhases)%numComponents;
716  fluidState.setMoleFraction(phaseIdx, compIdx, value);
717  }
718  }
719 
720  template <class FluidState>
721  static Scalar quantityWeight_(const FluidState &/*fluidState*/, unsigned pvIdx)
722  {
723  // first pressure
724  if (pvIdx < 1)
725  return 1/1e5;
726  // first M - 1 saturations
727  else if (pvIdx < numPhases)
728  return 1.0;
729  // mole fractions
730  else // if (pvIdx < numPhases + numPhases*numComponents)
731  return 1.0;
732  }
733 };
734 
735 } // namespace Opm
736 
737 #endif
static void setQuantity_(FluidState &fluidState, ParameterCache &paramCache, const typename MaterialLaw::Params &matParams, unsigned pvIdx, const typename FluidState::Scalar &value)
Definition: NcpFlash.hpp:598
static bool isMoleFracIdx_(unsigned pvIdx)
Definition: NcpFlash.hpp:568
void SetUndefined(const T &value OPM_UNUSED)
Make the memory on which an object resides undefined in valgrind runs.
Definition: Valgrind.hpp:138
static Scalar update_(FluidState &fluidState, ParameterCache &paramCache, const typename MaterialLaw::Params &matParams, const Vector &deltaX)
Definition: NcpFlash.hpp:446
static void calculateDefect_(Vector &b, const FluidState &fluidStateEval, const FluidState &fluidState, const ComponentVector &globalMolarities)
Definition: NcpFlash.hpp:388
bool CheckDefined(const T &value OPM_UNUSED)
Make valgrind complain if any of the memory occupied by an object is undefined.
Definition: Valgrind.hpp:74
static bool isPressureIdx_(unsigned pvIdx)
Definition: NcpFlash.hpp:562
Definition: MathToolbox.hpp:39
Definition: Air_Mesitylene.hpp:31
static void setQuantityRaw_(FluidState &fluidState, unsigned pvIdx, const typename FluidState::Scalar &value)
Definition: NcpFlash.hpp:694
A generic traits class which does not provide any indices.
Definition: MaterialTraits.hpp:41
Implements some common averages.
Some templates to wrap the valgrind client request macros.
Evaluation< Scalar, VarSetTag, numVars > max(const Evaluation< Scalar, VarSetTag, numVars > &x1, const Evaluation< Scalar, VarSetTag, numVars > &x2)
Definition: Math.hpp:114
static void solve(FluidState &fluidState, const ComponentVector &globalMolarities, Scalar tolerance=0.0)
Calculates the chemical equilibrium from the component fugacities in a phase.
Definition: NcpFlash.hpp:264
static void completeFluidState_(FluidState &fluidState, ParameterCache &paramCache, const typename MaterialLaw::Params &matParams)
Definition: NcpFlash.hpp:524
Scalar geometricMean(Scalar x, Scalar y)
Computes the geometric average of two values.
Definition: Means.hpp:55
static void guessInitial(FluidState &fluidState, ParameterCache &paramCache, const Dune::FieldVector< Evaluation, numComponents > &globalMolarities)
Guess initial values for all quantities.
Definition: NcpFlash.hpp:98
static void solve(FluidState &fluidState, ParameterCache &paramCache, const typename MaterialLaw::Params &matParams, const Dune::FieldVector< typename FluidState::Scalar, numComponents > &globalMolarities, Scalar tolerance=0.0)
Calculates the chemical equilibrium from the component fugacities in a phase.
Definition: NcpFlash.hpp:139
Implements a dummy linear saturation-capillary pressure relation which just disables capillary pressu...
Definition: NullMaterial.hpp:45
static void linearize_(Matrix &J, Vector &b, FluidState &fluidState, ParameterCache &paramCache, const typename MaterialLaw::Params &matParams, const ComponentVector &globalMolarities)
Definition: NcpFlash.hpp:331
Evaluation< Scalar, VarSetTag, numVars > abs(const Evaluation< Scalar, VarSetTag, numVars > &)
Definition: Math.hpp:41
Implements a dummy linear saturation-capillary pressure relation which just disables capillary pressu...
Evaluation< Scalar, VarSetTag, numVars > min(const Evaluation< Scalar, VarSetTag, numVars > &x1, const Evaluation< Scalar, VarSetTag, numVars > &x2)
Definition: Math.hpp:61
This file contains helper classes for the material laws.
Determines the phase compositions, pressures and saturations given the total mass of all components...
Definition: NcpFlash.hpp:84
static void printFluidState_(const FluidState &fluidState)
Definition: NcpFlash.hpp:282
static bool isSaturationIdx_(unsigned pvIdx)
Definition: NcpFlash.hpp:565
static const FluidState::Scalar & getQuantity_(const FluidState &fluidState, unsigned pvIdx)
Definition: NcpFlash.hpp:573
static Scalar quantityWeight_(const FluidState &, unsigned pvIdx)
Definition: NcpFlash.hpp:721
A traits class which provides basic mathematical functions for arbitrary scalar floating point values...