Line | Branch | Exec | Source |
---|---|---|---|
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 | // | ||
7 | /** | ||
8 | * \file | ||
9 | * \ingroup OnePNCTests | ||
10 | * \brief Definition of a problem for a 1p3c problem: | ||
11 | * Component transport of N2, CO2 and H2 using the Maxwell-Stefan diffusion law. | ||
12 | */ | ||
13 | |||
14 | #ifndef DUMUX_1P3C_TEST_PROBLEM_HH | ||
15 | #define DUMUX_1P3C_TEST_PROBLEM_HH | ||
16 | #include <dumux/common/properties.hh> | ||
17 | #include <dumux/common/parameters.hh> | ||
18 | |||
19 | #include <dumux/common/boundarytypes.hh> | ||
20 | #include <dumux/common/numeqvector.hh> | ||
21 | #include <dumux/porousmediumflow/problem.hh> | ||
22 | |||
23 | #include <dumux/io/gnuplotinterface.hh> | ||
24 | namespace Dumux { | ||
25 | |||
26 | |||
27 | /*! | ||
28 | * \ingroup OnePNCTests | ||
29 | * \brief Definition of a problem for a 1p3c problem: | ||
30 | * Component transport of N2, CO2 and H2. | ||
31 | |||
32 | * The domain is closed on all sides. H2 constitutes the bulk gas phase. | ||
33 | * Initially, there is N2 and CO2 in the left half of the domain, | ||
34 | * while only N2 is present in the right half of the domain. | ||
35 | * Over time, the concentrations will equilibrate. | ||
36 | * | ||
37 | * This problem uses the \ref OnePNCModel model and the Maxwell-Stefan diffusion law. | ||
38 | * | ||
39 | */ | ||
40 | template <class TypeTag> | ||
41 | class MaxwellStefanOnePThreeCTestProblem : public PorousMediumFlowProblem<TypeTag> | ||
42 | { | ||
43 | using ParentType = PorousMediumFlowProblem<TypeTag>; | ||
44 | |||
45 | using Scalar = GetPropType<TypeTag, Properties::Scalar>; | ||
46 | using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices; | ||
47 | using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView; | ||
48 | using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>; | ||
49 | using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>; | ||
50 | using NumEqVector = Dumux::NumEqVector<PrimaryVariables>; | ||
51 | using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>; | ||
52 | using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>; | ||
53 | using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>; | ||
54 | using VolumeVariables = GetPropType<TypeTag, Properties::VolumeVariables>; | ||
55 | |||
56 | //! property that defines whether mole or mass fractions are used | ||
57 | static constexpr bool useMoles = getPropValue<TypeTag, Properties::UseMoles>(); | ||
58 | |||
59 | using Element = typename GridGeometry::GridView::template Codim<0>::Entity; | ||
60 | using GlobalPosition = typename Element::Geometry::GlobalCoordinate; | ||
61 | |||
62 | public: | ||
63 | 2 | MaxwellStefanOnePThreeCTestProblem(std::shared_ptr<const GridGeometry> gridGeometry) | |
64 |
17/54✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 2 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 2 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 2 times.
✗ Branch 28 not taken.
✓ Branch 30 taken 2 times.
✗ Branch 31 not taken.
✓ Branch 33 taken 2 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 2 times.
✗ Branch 37 not taken.
✓ Branch 39 taken 2 times.
✗ Branch 40 not taken.
✓ Branch 42 taken 2 times.
✗ Branch 43 not taken.
✓ Branch 45 taken 2 times.
✗ Branch 46 not taken.
✓ Branch 48 taken 2 times.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
|
6 | : ParentType(gridGeometry) |
65 | { | ||
66 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
2 | name_ = getParam<std::string>("Problem.Name"); |
67 | |||
68 | // stating in the terminal whether mole or mass fractions are used | ||
69 | if (useMoles) | ||
70 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
4 | std::cout<<"problem uses mole fractions" << '\n'; |
71 | else | ||
72 | std::cout<<"problem uses mass fractions" << '\n'; | ||
73 | |||
74 | 2 | plotOutput_ = false; | |
75 | 2 | } | |
76 | |||
77 | /*! | ||
78 | * \name Problem parameters | ||
79 | */ | ||
80 | // \{ | ||
81 | |||
82 | /*! | ||
83 | * \brief The problem name. | ||
84 | * This is used as a prefix for files generated by the simulation. | ||
85 | */ | ||
86 | const std::string& name() const | ||
87 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | { return name_; } |
88 | |||
89 | //! Called after every time step | ||
90 | 292 | void plotComponentsOverTime(const SolutionVector& curSol, Scalar time) | |
91 | { | ||
92 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 292 times.
|
292 | if (plotOutput_) |
93 | { | ||
94 | ✗ | Scalar x_co2_left = 0.0; | |
95 | ✗ | Scalar x_n2_left = 0.0; | |
96 | ✗ | Scalar x_co2_right = 0.0; | |
97 | ✗ | Scalar x_n2_right = 0.0; | |
98 | ✗ | Scalar x_h2_left = 0.0; | |
99 | ✗ | Scalar x_h2_right = 0.0; | |
100 | ✗ | Scalar i = 0.0; | |
101 | ✗ | Scalar j = 0.0; | |
102 | ✗ | if (!(time < 0.0)) | |
103 | { | ||
104 | ✗ | auto fvGeometry = localView(this->gridGeometry()); | |
105 | ✗ | for (const auto& element : elements(this->gridGeometry().gridView())) | |
106 | { | ||
107 | ✗ | fvGeometry.bindElement(element); | |
108 | ✗ | const auto elemSol = elementSolution(element, curSol, this->gridGeometry()); | |
109 | |||
110 | ✗ | for (auto&& scv : scvs(fvGeometry)) | |
111 | { | ||
112 | ✗ | const auto& globalPos = scv.dofPosition(); | |
113 | ✗ | VolumeVariables volVars; | |
114 | ✗ | volVars.update(elemSol, *this, element, scv); | |
115 | |||
116 | ✗ | if (globalPos[0] < 0.5) | |
117 | { | ||
118 | ✗ | x_co2_left += volVars.moleFraction(0,2); | |
119 | |||
120 | ✗ | x_n2_left += volVars.moleFraction(0,1); | |
121 | ✗ | x_h2_left += volVars.moleFraction(0,0); | |
122 | ✗ | i +=1; | |
123 | } | ||
124 | else | ||
125 | { | ||
126 | ✗ | x_co2_right += volVars.moleFraction(0,2); | |
127 | ✗ | x_n2_right += volVars.moleFraction(0,1); | |
128 | ✗ | x_h2_right += volVars.moleFraction(0,0); | |
129 | ✗ | j +=1; | |
130 | } | ||
131 | } | ||
132 | } | ||
133 | ✗ | x_co2_left /= i; | |
134 | ✗ | x_n2_left /= i; | |
135 | ✗ | x_h2_left /= i; | |
136 | ✗ | x_co2_right /= j; | |
137 | ✗ | x_n2_right /= j; | |
138 | ✗ | x_h2_right /= j; | |
139 | |||
140 | // do a gnuplot | ||
141 | ✗ | x_.push_back(time); // in seconds | |
142 | ✗ | y_.push_back(x_n2_left); | |
143 | ✗ | y2_.push_back(x_n2_right); | |
144 | ✗ | y3_.push_back(x_co2_left); | |
145 | ✗ | y4_.push_back(x_co2_right); | |
146 | ✗ | y5_.push_back(x_h2_left); | |
147 | ✗ | y6_.push_back(x_h2_right); | |
148 | |||
149 | ✗ | gnuplot_.resetPlot(); | |
150 | ✗ | gnuplot_.setXRange(0, std::min(time, 72000.0)); | |
151 | ✗ | gnuplot_.setYRange(0.4, 0.6); | |
152 | ✗ | gnuplot_.setXlabel("time [s]"); | |
153 | ✗ | gnuplot_.setYlabel("mole fraction mol/mol"); | |
154 | ✗ | gnuplot_.addDataSetToPlot(x_, y_, "N2_left.dat", "w l t 'N_2 left'"); | |
155 | ✗ | gnuplot_.addDataSetToPlot(x_, y2_, "N2_right.dat", "w l t 'N_2 right'"); | |
156 | ✗ | gnuplot_.plot("mole_fraction_N2"); | |
157 | |||
158 | ✗ | gnuplot2_.resetPlot(); | |
159 | ✗ | gnuplot2_.setXRange(0, std::min(time, 72000.0)); | |
160 | ✗ | gnuplot2_.setYRange(0.0, 0.6); | |
161 | ✗ | gnuplot2_.setXlabel("time [s]"); | |
162 | ✗ | gnuplot2_.setYlabel("mole fraction mol/mol"); | |
163 | ✗ | gnuplot2_.addDataSetToPlot(x_, y3_, "CO2_left.dat", "w l t 'CO_2 left'"); | |
164 | ✗ | gnuplot2_.addDataSetToPlot(x_, y4_, "CO2_right.dat", "w l t 'CO_2 right"); | |
165 | ✗ | gnuplot2_.plot("mole_fraction_CO2"); | |
166 | |||
167 | ✗ | gnuplot3_.resetPlot(); | |
168 | ✗ | gnuplot3_.setXRange(0, std::min(time, 72000.0)); | |
169 | ✗ | gnuplot3_.setYRange(0.0, 0.6); | |
170 | ✗ | gnuplot3_.setXlabel("time [s]"); | |
171 | ✗ | gnuplot3_.setYlabel("mole fraction mol/mol"); | |
172 | ✗ | gnuplot3_.addDataSetToPlot(x_, y5_, "H2_left.dat", "w l t 'H_2 left'"); | |
173 | ✗ | gnuplot3_.addDataSetToPlot(x_, y6_, "H2_right.dat", "w l t 'H_2 right'"); | |
174 | ✗ | gnuplot3_.plot("mole_fraction_H2"); | |
175 | } | ||
176 | } | ||
177 | 292 | } | |
178 | |||
179 | // \} | ||
180 | |||
181 | /*! | ||
182 | * \name Boundary conditions | ||
183 | */ | ||
184 | // \{ | ||
185 | |||
186 | /*! | ||
187 | * \brief Specifies which kind of boundary condition should be | ||
188 | * used for which equation on a given boundary segment. | ||
189 | * | ||
190 | * \param globalPos The position for which the bc type should be evaluated | ||
191 | */ | ||
192 | ✗ | BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const | |
193 | { | ||
194 | 201586 | BoundaryTypes values; | |
195 |
5/8✓ Branch 0 taken 58800 times.
✓ Branch 1 taken 372 times.
✓ Branch 2 taken 372 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 28706 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 113336 times.
|
201586 | values.setAllNeumann(); |
196 | ✗ | return values; | |
197 | } | ||
198 | |||
199 | /*! | ||
200 | * \brief Evaluates the boundary conditions for a Neumann boundary segment. | ||
201 | * | ||
202 | * \param globalPos The position for which the bc type should be evaluated | ||
203 | */ | ||
204 | ✗ | NumEqVector neumannAtPos(const GlobalPosition& globalPos) const | |
205 |
1/2✓ Branch 0 taken 113336 times.
✗ Branch 1 not taken.
|
1807176 | { return NumEqVector(0.0); } |
206 | |||
207 | // \} | ||
208 | |||
209 | /*! | ||
210 | * \name Volume terms | ||
211 | */ | ||
212 | // \{ | ||
213 | |||
214 | /*! | ||
215 | * \brief Evaluates the initial value for a control volume. | ||
216 | * | ||
217 | * \param globalPos The position for which the initial condition should be evaluated | ||
218 | */ | ||
219 | ✗ | PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const | |
220 | { | ||
221 | ✗ | PrimaryVariables initialValues(0.0); | |
222 | ✗ | if (globalPos[0] < 0.5) | |
223 | { | ||
224 | ✗ | initialValues[Indices::pressureIdx] = 1e5; | |
225 | ✗ | initialValues[FluidSystem::N2Idx] = 0.50086; | |
226 | ✗ | initialValues[FluidSystem::CO2Idx] = 0.49914; | |
227 | } | ||
228 | else | ||
229 | { | ||
230 | ✗ | initialValues[Indices::pressureIdx] = 1e5; | |
231 | ✗ | initialValues[FluidSystem::N2Idx] = 0.49879; | |
232 | ✗ | initialValues[FluidSystem::CO2Idx] = 0.0; | |
233 | } | ||
234 | ✗ | return initialValues; | |
235 | } | ||
236 | |||
237 | // \} | ||
238 | |||
239 | private: | ||
240 | std::string name_; | ||
241 | |||
242 | Dumux::GnuplotInterface<Scalar> gnuplot_; | ||
243 | Dumux::GnuplotInterface<Scalar> gnuplot2_; | ||
244 | Dumux::GnuplotInterface<Scalar> gnuplot3_; | ||
245 | |||
246 | std::vector<Scalar> x_; | ||
247 | std::vector<Scalar> y_; | ||
248 | std::vector<Scalar> y2_; | ||
249 | std::vector<Scalar> y3_; | ||
250 | std::vector<Scalar> y4_; | ||
251 | std::vector<Scalar> y5_; | ||
252 | std::vector<Scalar> y6_; | ||
253 | |||
254 | bool plotOutput_; | ||
255 | }; | ||
256 | |||
257 | } // end namespace Dumux | ||
258 | |||
259 | #endif | ||
260 |