3.1-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
test/porousmediumflow/2pnc/implicit/fuelcell/problem.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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
25#ifndef DUMUX_FUELCELL_PROBLEM_HH
26#define DUMUX_FUELCELL_PROBLEM_HH
27
28#include <dune/grid/yaspgrid.hh>
29
36#ifdef NONISOTHERMAL
38#else
40#endif
41#include "spatialparams.hh"
42
43namespace Dumux {
44
49template <class TypeTag>
50class FuelCellProblem;
51
52namespace Properties {
53// Create new type tags
54namespace TTag {
55#ifdef NONISOTHERMAL
56struct FuelCell { using InheritsFrom = std::tuple<TwoPNCNI>; };
57struct FuelCellNIBox { using InheritsFrom = std::tuple<FuelCell, BoxModel>; };
58#else
59struct FuelCell { using InheritsFrom = std::tuple<TwoPNC>; };
60struct FuelCellBox { using InheritsFrom = std::tuple<FuelCell, BoxModel>; };
61struct FuelCellCCTpfa { using InheritsFrom = std::tuple<FuelCell, CCTpfaModel>; };
62#endif
63} // end namespace TTag
64
65// Set the grid type
66template<class TypeTag>
67struct Grid<TypeTag, TTag::FuelCell> { using type = Dune::YaspGrid<2>; };
68
69// Set the problem property
70template<class TypeTag>
71struct Problem<TypeTag, TTag::FuelCell> { using type = FuelCellProblem<TypeTag>; };
72
73// Set the spatial parameters
74template<class TypeTag>
75struct SpatialParams<TypeTag, TTag::FuelCell>
76{
80};
81
82// Set the primary variable combination for the 2pnc model
83template<class TypeTag>
84struct Formulation<TypeTag, TTag::FuelCell>
85{ static constexpr auto value = TwoPFormulation::p1s0; };
86
87// Set fluid configuration
88template<class TypeTag>
89struct FluidSystem<TypeTag, TTag::FuelCell>
90{
91private:
93public:
95};
96} // end namespace Properties
97
105template <class TypeTag>
107{
109
116 using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView;
117 using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView;
118 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
120 using Element = typename GridView::template Codim<0>::Entity;
124 // Select the electrochemistry method
125#ifdef NONISOTHERMAL
127#else
129#endif
130 static constexpr int dim = GridView::dimension;
131 static constexpr int dimWorld = GridView::dimensionworld;
132 static constexpr bool isBox = GridGeometry::discMethod == DiscretizationMethod::box;
133 using GlobalPosition = typename SubControlVolume::GlobalPosition;
134
135 enum { dofCodim = isBox ? dim : 0 };
136public:
137 FuelCellProblem(std::shared_ptr<const GridGeometry> gridGeometry)
139 {
140 nTemperature_ = getParam<int>("Problem.NTemperature");
141 nPressure_ = getParam<int>("Problem.NPressure");
142 pressureLow_ = getParam<Scalar>("Problem.PressureLow");
143 pressureHigh_ = getParam<Scalar>("Problem.PressureHigh");
144 temperatureLow_ = getParam<Scalar>("Problem.TemperatureLow");
145 temperatureHigh_ = getParam<Scalar>("Problem.TemperatureHigh");
146 temperature_ = getParam<Scalar>("Problem.InitialTemperature");
147
148 name_ = getParam<std::string>("Problem.Name");
149
150 pO2Inlet_ = getParam<Scalar>("ElectroChemistry.pO2Inlet");
151
152 FluidSystem::init(/*Tmin=*/temperatureLow_,
153 /*Tmax=*/temperatureHigh_,
154 /*nT=*/nTemperature_,
155 /*pmin=*/pressureLow_,
156 /*pmax=*/pressureHigh_,
157 /*np=*/nPressure_);
158 }
159
169 const std::string& name() const
170 { return name_; }
171
177 Scalar temperature() const
178 { return temperature_; }
179
181 NumEqVector source(const Element &element,
182 const FVElementGeometry& fvGeometry,
183 const ElementVolumeVariables& elemVolVars,
184 const SubControlVolume &scv) const
185 {
186 NumEqVector values(0.0);
187 const auto& globalPos = scv.dofPosition();
188
189 //reaction sources from electro chemistry
190 if(inReactionLayer_(globalPos))
191 {
192 const auto& volVars = elemVolVars[scv];
193 auto currentDensity = ElectroChemistry::calculateCurrentDensity(volVars);
194 ElectroChemistry::reactionSource(values, currentDensity);
195 }
196
197 return values;
198 }
199
200
204 // \{
205
212 BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
213 {
214 BoundaryTypes bcTypes;
215 bcTypes.setAllNeumann();
216
217 if (onUpperBoundary_(globalPos)){
218 bcTypes.setAllDirichlet();
219 }
220 return bcTypes;
221 }
222
228 PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const
229 {
230 auto priVars = initial_(globalPos);
231
232 if(onUpperBoundary_(globalPos))
233 {
234 Scalar pn = 1.0e5;
235 priVars[Indices::pressureIdx] = pn;
236 priVars[Indices::switchIdx] = 0.3;//Sw for bothPhases
237 priVars[Indices::switchIdx+1] = pO2Inlet_/4.315e9; //moleFraction xlO2 for bothPhases
238#ifdef NONISOTHERMAL
239 priVars[Indices::temperatureIdx] = 293.15;
240#endif
241 }
242
243 return priVars;
244 }
245
256 PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const
257 { return initial_(globalPos); }
258
259
265 template<class VTKWriter>
266 void addVtkFields(VTKWriter& vtk)
267 {
268 const auto& gridView = this->gridGeometry().gridView();
269 currentDensity_.resize(gridView.size(dofCodim));
270 reactionSourceH2O_.resize(gridView.size(dofCodim));
271 reactionSourceO2_.resize(gridView.size(dofCodim));
272 Kxx_.resize(gridView.size(dofCodim));
273 Kyy_.resize(gridView.size(dofCodim));
274
275 vtk.addField(currentDensity_, "currentDensity [A/cm^2]");
276 vtk.addField(reactionSourceH2O_, "reactionSourceH2O [mol/(sm^2)]");
277 vtk.addField(reactionSourceO2_, "reactionSourceO2 [mol/(sm^2)]");
278 vtk.addField(Kxx_, "Kxx");
279 vtk.addField(Kyy_, "Kyy");
280 }
281
282 void updateVtkFields(const SolutionVector& curSol)
283 {
284 for (const auto& element : elements(this->gridGeometry().gridView()))
285 {
286 auto elemSol = elementSolution(element, curSol, this->gridGeometry());
287
288 auto fvGeometry = localView(this->gridGeometry());
289 fvGeometry.bindElement(element);
290
291 for (auto&& scv : scvs(fvGeometry))
292 {
293 VolumeVariables volVars;
294 volVars.update(elemSol, *this, element, scv);
295 const auto& globalPos = scv.dofPosition();
296 const auto dofIdxGlobal = scv.dofIndex();
297
298 if(inReactionLayer_(globalPos))
299 {
300 //reactionSource Output
301 PrimaryVariables source;
304
305 reactionSourceH2O_[dofIdxGlobal] = source[Indices::conti0EqIdx + FluidSystem::H2OIdx];
306 reactionSourceO2_[dofIdxGlobal] = source[Indices::conti0EqIdx + FluidSystem::O2Idx];
307
308 //Current Output in A/cm^2
309 currentDensity_[dofIdxGlobal] = i/10000;
310 }
311 else
312 {
313 reactionSourceH2O_[dofIdxGlobal] = 0.0;
314 reactionSourceO2_[dofIdxGlobal] = 0.0;
315 currentDensity_[dofIdxGlobal] = 0.0;
316 }
317 Kxx_[dofIdxGlobal] = volVars.permeability()[0][0];
318 Kyy_[dofIdxGlobal] = volVars.permeability()[1][1];
319 }
320 }
321 }
322
323private:
324
325 PrimaryVariables initial_(const GlobalPosition &globalPos) const
326 {
327 PrimaryVariables priVars(0.0);
328 priVars.setState(Indices::bothPhases);
329
330 Scalar pn = 1.0e5;
331 priVars[Indices::pressureIdx] = pn;
332 priVars[Indices::switchIdx] = 0.3;//Sw for bothPhases
333 priVars[Indices::switchIdx+1] = pO2Inlet_/4.315e9; //moleFraction xlO2 for bothPhases
334#ifdef NONISOTHERMAL
335 priVars[Indices::temperatureIdx] = 293.15;
336#endif
337
338 return priVars;
339 }
340
341 bool onUpperBoundary_(const GlobalPosition &globalPos) const
342 { return globalPos[1] > this->gridGeometry().bBoxMax()[1] - eps_; }
343
344 bool inReactionLayer_(const GlobalPosition& globalPos) const
345 { return globalPos[1] < 0.1*(this->gridGeometry().bBoxMax()[1] - this->gridGeometry().bBoxMin()[1]) + eps_; }
346
347 Scalar temperature_;
348 static constexpr Scalar eps_ = 1e-6;
349 int nTemperature_;
350 int nPressure_;
351 std::string name_ ;
352 Scalar pressureLow_, pressureHigh_;
353 Scalar temperatureLow_, temperatureHigh_;
354 Scalar pO2Inlet_;
355 std::vector<double> currentDensity_;
356 std::vector<double> reactionSourceH2O_;
357 std::vector<double> reactionSourceO2_;
358 std::vector<double> Kxx_;
359 std::vector<double> Kyy_;
360};
361
362} // end namespace Dumux
363
364#endif
Element solution classes and factory functions.
Defines a type tag and some properties for models using the box scheme.
Properties for all models using cell-centered finite volume scheme with TPFA.
Electrochemical model for a fuel cell application.
Electrochemical model for a fuel cell application.
A two-phase (water and air) fluid system with water, nitrogen and oxygen as components.
@ p1s0
first phase saturation and second phase pressure as primary variables
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:38
auto elementSolution(const Element &element, const SolutionVector &sol, const GridGeometry &gg) -> std::enable_if_t< GridGeometry::discMethod==DiscretizationMethod::box, BoxElementSolution< typename GridGeometry::LocalView, std::decay_t< decltype(std::declval< SolutionVector >()[0])> > >
Make an element solution for box schemes.
Definition: box/elementsolution.hh:115
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:149
Base class for all finite-volume problems.
Definition: common/fvproblem.hh:50
const GridGeometry & gridGeometry() const
The finite volume grid geometry.
Definition: common/fvproblem.hh:588
The DUNE grid type.
Definition: common/properties.hh:57
Property to specify the type of a problem which has to be solved.
Definition: common/properties.hh:69
The type of the spatial parameters object.
Definition: common/properties.hh:221
The type of the fluid system to use.
Definition: common/properties.hh:223
The formulation of the model.
Definition: common/properties.hh:237
This class calculates source terms and current densities for fuel cells with the electrochemical mode...
Definition: electrochemistry.hh:53
static void reactionSource(SourceValues &values, Scalar currentDensity, const std::string &paramGroup="")
Calculates reaction sources with an electrochemical model approach.
Definition: electrochemistry.hh:92
static Scalar calculateCurrentDensity(const VolumeVariables &volVars)
Newton solver for calculation of the current density.
Definition: electrochemistry.hh:122
Class calculating source terms and current densities for fuel cells with the electrochemical models s...
Definition: electrochemistryni.hh:42
A two-phase (water and air) fluid system with water, nitrogen and oxygen as components.
Definition: h2on2o2.hh:78
Base class for all fully implicit porous media problems.
Definition: dumux/porousmediumflow/problem.hh:39
Definition of a problem for water management in PEM fuel cells.
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:107
void updateVtkFields(const SolutionVector &curSol)
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:282
Scalar temperature() const
Returns the temperature within the domain.
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:177
BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
Specifies which kind of boundary condition should be used for which equation on a given boundary segm...
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:212
void addVtkFields(VTKWriter &vtk)
Adds additional VTK output data to the VTKWriter.
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:266
NumEqVector source(const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const SubControlVolume &scv) const
Evaluate the source term for all phases within a given sub-control-volume.
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:181
FuelCellProblem(std::shared_ptr< const GridGeometry > gridGeometry)
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:137
const std::string & name() const
The problem name.
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:169
PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const
Evaluates the boundary conditions for a Dirichlet boundary segment.
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:228
PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const
Evaluates the initial values for a control volume.
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:256
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:59
std::tuple< TwoPNC > InheritsFrom
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:59
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:60
std::tuple< FuelCell, BoxModel > InheritsFrom
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:60
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:61
std::tuple< FuelCell, CCTpfaModel > InheritsFrom
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:61
Dune::YaspGrid< 2 > type
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:67
GetPropType< TypeTag, Properties::GridGeometry > GridGeometry
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:77
GetPropType< TypeTag, Properties::Scalar > Scalar
Definition: test/porousmediumflow/2pnc/implicit/fuelcell/problem.hh:78
Definition of the spatial parameters for the FuelCell problem which uses the isothermal 2p2c box mode...
Definition: porousmediumflow/2pnc/implicit/fuelcell/spatialparams.hh:46
Adaption of the fully implicit scheme to the two-phase n-component fully implicit model.
Base class for all porous media problems.
Definition of the spatial parameters for the MaxwellStefan problem.