version 3.8
2pnc/primaryvariableswitch.hh
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// SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
13#ifndef DUMUX_2PNC_PRIMARY_VARIABLE_SWITCH_HH
14#define DUMUX_2PNC_PRIMARY_VARIABLE_SWITCH_HH
15
16#include <iostream>
17
20
21namespace Dumux {
22
28: public PrimaryVariableSwitch<TwoPNCPrimaryVariableSwitch>
29{
31 friend ParentType;
32public:
33 using ParentType::ParentType;
34
35protected:
36 // perform variable switch at a degree of freedom location
37 template<class VolumeVariables, class IndexType, class GlobalPosition>
38 bool update_(typename VolumeVariables::PrimaryVariables& priVars,
39 const VolumeVariables& volVars,
40 IndexType dofIdxGlobal,
41 const GlobalPosition& globalPos)
42 {
43 using Scalar = typename VolumeVariables::PrimaryVariables::value_type;
44
45 using FluidSystem = typename VolumeVariables::FluidSystem;
46 static constexpr int phase0Idx = FluidSystem::phase0Idx;
47 static constexpr int phase1Idx = FluidSystem::phase1Idx;
48 static constexpr int comp0Idx = FluidSystem::comp0Idx;
49 static constexpr int comp1Idx = FluidSystem::comp1Idx;
50
51 static constexpr auto numComponents = VolumeVariables::numFluidComponents();
52 static constexpr bool useMoles = VolumeVariables::useMoles();
53 static_assert(useMoles || numComponents < 3, "!useMoles is only implemented for numComponents < 3.");
54 static constexpr auto numMajorComponents = VolumeVariables::numFluidPhases();
55 static constexpr auto formulation = VolumeVariables::priVarFormulation();
56 static_assert( (formulation == TwoPFormulation::p0s1 || formulation == TwoPFormulation::p1s0),
57 "Chosen TwoPFormulation not supported!");
58
59 using Indices = typename VolumeVariables::Indices;
60 static constexpr int switchIdx = Indices::switchIdx;
61
62 // evaluate primary variable switch
63 bool wouldSwitch = false;
64 int phasePresence = priVars.state();
65 int newPhasePresence = phasePresence;
66
67 //check if a primary variable switch is necessary
68 if (phasePresence == Indices::bothPhases)
69 {
70 Scalar Smin = 0; //saturation threshold
71 if (this->wasSwitched_[dofIdxGlobal])
72 Smin = -0.01;
73
74 // if saturation of first phase is smaller 0: switch
75 if (volVars.saturation(phase0Idx) <= Smin)
76 {
77 wouldSwitch = true;
78 // first phase has to disappear
79 if (this->verbosity() > 1)
80 std::cout << "First phase (" << FluidSystem::phaseName(phase0Idx) << ")"
81 << " disappears at dof " << dofIdxGlobal
82 << ", coordinates: " << globalPos
83 << ", S_" << FluidSystem::phaseName(phase0Idx) << ": " << volVars.saturation(phase0Idx)
84 << std::endl;
85 newPhasePresence = Indices::secondPhaseOnly;
86
87 // switch not depending on formulation, switch "S0" to "x10"
88 if(useMoles) // mole-fraction formulation
89 priVars[switchIdx] = volVars.moleFraction(phase1Idx, comp0Idx);
90 else // mass-fraction formulation
91 priVars[switchIdx] = volVars.massFraction(phase1Idx, comp0Idx);
92
93 // switch all secondary components to mole fraction in nonwetting phase
94 if(useMoles) // mole-fraction formulation
95 for (int compIdx = numMajorComponents; compIdx < numComponents; ++compIdx)
96 priVars[compIdx] = volVars.moleFraction(phase1Idx, compIdx);
97 else // mass-fraction formulation
98 for (int compIdx = numMajorComponents; compIdx < numComponents; ++compIdx)
99 priVars[compIdx] = volVars.massFraction(phase1Idx, compIdx);
100 }
101
102 // if saturation of second phase is smaller than 0: switch
103 else if (volVars.saturation(phase1Idx) <= Smin)
104 {
105 wouldSwitch = true;
106 // second phase has to disappear
107 if (this->verbosity() > 1)
108 std::cout << "Second phase (" << FluidSystem::phaseName(phase1Idx) << ")"
109 << " disappears at dof " << dofIdxGlobal
110 << ", coordinates: " << globalPos
111 << ", S_" << FluidSystem::phaseName(phase1Idx) << ": " << volVars.saturation(phase1Idx)
112 << std::endl;
113 newPhasePresence = Indices::firstPhaseOnly;
114
115 // switch "S1" to "x01"
116 if(useMoles) // mole-fraction formulation
117 priVars[switchIdx] = volVars.moleFraction(phase0Idx, comp1Idx);
118 else // mass-fraction formulation
119 priVars[switchIdx] = volVars.massFraction(phase0Idx, comp1Idx);
120 }
121 }
122 else if (phasePresence == Indices::secondPhaseOnly)
123 {
124 Scalar x0Max = 1;
125 Scalar x0Sum = 0;
126 // Calculate sum of mole fractions in the hypothetical first phase
127 for (int compIdx = 0; compIdx < numComponents; compIdx++)
128 x0Sum += volVars.moleFraction(phase0Idx, compIdx);
129
130 if (x0Sum > x0Max)
131 wouldSwitch = true;
132 if (this->wasSwitched_[dofIdxGlobal])
133 x0Max *= 1.02;
134
135 // first phase appears if sum is larger than one
136 if (x0Sum/*sum of mole fractions*/ > x0Max/*1*/)
137 {
138 if (this->verbosity() > 1)
139 std::cout << "Second phase (" << FluidSystem::phaseName(phase0Idx) << ")"
140 << " appears at dof " << dofIdxGlobal
141 << ", coordinates: " << globalPos
142 << ", sum x^i_" << FluidSystem::phaseName(phase0Idx) << ": " << x0Sum
143 << std::endl;
144 newPhasePresence = Indices::bothPhases;
145
146 // saturation of the first phase set to 0.0001 (if formulation TwoPFormulation::p1s0 and vice versa)
147 if (formulation == TwoPFormulation::p1s0)
148 priVars[switchIdx] = 0.0001;
149 else
150 priVars[switchIdx] = 0.9999;
151
152 // switch all secondary components back to first component mole fraction
153 for (int compIdx = numMajorComponents; compIdx < numComponents; ++compIdx)
154 priVars[compIdx] = volVars.moleFraction(phase0Idx,compIdx);
155 }
156 }
157 else if (phasePresence == Indices::firstPhaseOnly)
158 {
159 Scalar x1Max = 1;
160 Scalar x1Sum = 0;
161
162 // Calculate sum of mole fractions in the hypothetical wetting phase
163 for (int compIdx = 0; compIdx < numComponents; compIdx++)
164 x1Sum += volVars.moleFraction(phase1Idx, compIdx);
165
166 if (x1Sum > x1Max)
167 wouldSwitch = true;
168 if (this->wasSwitched_[dofIdxGlobal])
169 x1Max *= 1.02;
170
171 // wetting phase appears if sum is larger than one
172 if (x1Sum > x1Max)
173 {
174 if (this->verbosity() > 1)
175 std::cout << "Second phase (" << FluidSystem::phaseName(phase1Idx) << ")"
176 << " appears at dof " << dofIdxGlobal
177 << ", coordinates: " << globalPos
178 << ", sum x^i_" << FluidSystem::phaseName(phase1Idx) << ": " << x1Sum
179 << std::endl;
180 newPhasePresence = Indices::bothPhases;
181 //saturation of the wetting phase set to 0.9999 (if formulation TwoPFormulation::pnsw and vice versa)
182 if (formulation == TwoPFormulation::p1s0)
183 priVars[switchIdx] = 0.9999;
184 else
185 priVars[switchIdx] = 0.0001;
186 }
187 }
188
189 priVars.setState(newPhasePresence);
190 this->wasSwitched_[dofIdxGlobal] = wouldSwitch;
191 return phasePresence != newPhasePresence;
192 }
193};
194
195} // end namespace Dumux
196
197#endif
The primary variable switch controlling the phase presence state variable.
Definition: compositional/primaryvariableswitch.hh:49
std::vector< bool > wasSwitched_
Definition: compositional/primaryvariableswitch.hh:433
int verbosity() const
The verbosity level.
Definition: compositional/primaryvariableswitch.hh:271
The primary variable switch controlling the phase presence state variable.
Definition: 2pnc/primaryvariableswitch.hh:29
bool update_(typename VolumeVariables::PrimaryVariables &priVars, const VolumeVariables &volVars, IndexType dofIdxGlobal, const GlobalPosition &globalPos)
Definition: 2pnc/primaryvariableswitch.hh:38
The primary variable switch base class for compositional models.
Defines an enumeration for the formulations accepted by the two-phase model.
@ p1s0
first phase saturation and second phase pressure as primary variables
@ p0s1
first phase pressure and second phase saturation as primary variables
std::string phasePresence() noexcept
I/O name of phase presence.
Definition: name.hh:135
Definition: adapt.hh:17