From e1c26bf5fa45ee429e5a082a71d15934c8899f9e Mon Sep 17 00:00:00 2001 From: Timo Koch <timo.koch@iws.uni-stuttgart.de> Date: Sun, 21 Feb 2016 23:53:51 +0100 Subject: [PATCH] [electrochem] Generalize electrochemistry * Make current density publicly available * Use standard grid creator * Implement reaction source term for box and cell-centered --- .../electrochemistry/electrochemistry.hh | 57 +++++++++++-------- .../electrochemistry/electrochemistryni.hh | 55 ++++++++++-------- .../2pnc/implicit/fuelcellproblem.hh | 7 +-- .../2pnc/implicit/test_2pnc.input | 56 +++++++----------- .../2pnc/implicit/test_box2pnc.cc | 20 +------ 5 files changed, 86 insertions(+), 109 deletions(-) diff --git a/dumux/material/chemistry/electrochemistry/electrochemistry.hh b/dumux/material/chemistry/electrochemistry/electrochemistry.hh index 86b91d100d..c67e8b5559 100644 --- a/dumux/material/chemistry/electrochemistry/electrochemistry.hh +++ b/dumux/material/chemistry/electrochemistry/electrochemistry.hh @@ -26,6 +26,7 @@ #include <cmath> +#include <dune/common/deprecated.hh> #include <dumux/common/basicproperties.hh> #include <dumux/common/exceptions.hh> #include <dumux/material/constants.hh> @@ -97,6 +98,12 @@ class ElectroChemistry energyEqIdx = FluidSystem::numComponents //energy equation }; + enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; + enum { dofCodim = isBox ? GridView::dimension : 0 }; + + using GlobalPosition = typename Dune::FieldVector<Scalar, GridView::dimensionworld>; + using CellVector = typename Dune::FieldVector<Scalar, GridView::dimension>; + public: /*! * \brief Calculates reaction sources with an electrochemical model approach. @@ -107,31 +114,22 @@ public: * For this method, the \a values parameter stores source values */ static void reactionSource(PrimaryVariables &values, - const VolumeVariables &volVars) + Scalar currentDensity) { - static Scalar transportNumberH2O = GET_RUNTIME_PARAM(TypeTag, Scalar, ElectroChemistry.TransportNumberH20); - static Scalar maxIter = GET_RUNTIME_PARAM(TypeTag, Scalar, ElectroChemistry.MaxIterations); - static Scalar gridYMin = 0.0; - static Scalar gridYMax = GET_RUNTIME_PARAM(TypeTag, Scalar, Grid.UpperRightY); - static Scalar nCellsY = GET_RUNTIME_PARAM(TypeTag, Scalar, Grid.NumberOfCellsY); - - //initialise current density - Scalar currentDensity = 0.0; - - //call internal method to calculate the current density - currentDensity = calculateCurrentDensity_(volVars, maxIter); - //correction to account for actually relevant reaction area //current density has to be devided by the half length of the box - Scalar lengthBox = (gridYMax - gridYMin)/nCellsY; - - if(electroChemistryModel == ElectroChemistryModel::Acosta) - currentDensity = currentDensity/lengthBox; + //\todo Do we have multiply with the electrochemically active surface area (ECSA) here instead? + static Scalar gridYMax = GET_RUNTIME_PARAM(TypeTag, GlobalPosition, Grid.UpperRight)[1]; + static Scalar nCellsY = GET_RUNTIME_PARAM(TypeTag, CellVector, Grid.Cells)[1]; + + // Warning: This assumes the reaction layer is always just one cell (cell-centered) or half a box (box) thick + const auto lengthBox = gridYMax/nCellsY; + if (isBox) + currentDensity *= 2.0/lengthBox; else - currentDensity = currentDensity*2/lengthBox; + currentDensity *= 1.0/lengthBox; - //conversion from [A/cm^2] to [A/m^2] - currentDensity = currentDensity*10000; + static Scalar transportNumberH2O = GET_RUNTIME_PARAM(TypeTag, Scalar, ElectroChemistry.TransportNumberH20); //calculation of flux terms with faraday equation values[contiH2OEqIdx] = currentDensity/(2*Constant::F); //reaction term in reaction layer @@ -139,13 +137,20 @@ public: values[contiO2EqIdx] = -currentDensity/(4*Constant::F); //O2-equation } -protected: + DUNE_DEPRECATED_MSG("First compute the currentDensity with calculateCurrentDensity(const VolumeVariables&) and then use the method reactionSource(PrimaryVariables&, Scalar) instead") + static void reactionSource(PrimaryVariables &values, + const VolumeVariables &volVars) + { + reactionSource(values, calculateCurrentDensity(volVars)); + } /*! * \brief Newton solver for calculation of the current density. + * \returns The current density in A/m^2 */ - static Scalar calculateCurrentDensity_(const VolumeVariables &volVars, Scalar maxIter) + static Scalar calculateCurrentDensity(const VolumeVariables &volVars) { + static Scalar maxIter = GET_RUNTIME_PARAM(TypeTag, Scalar, ElectroChemistry.MaxIterations); static Scalar specificResistance = GET_RUNTIME_PARAM(TypeTag, Scalar, ElectroChemistry.SpecificResistance); static Scalar reversibleVoltage = GET_RUNTIME_PARAM(TypeTag, Scalar, ElectroChemistry.ReversibleVoltage); static Scalar cellVoltage = GET_RUNTIME_PARAM(TypeTag, Scalar, ElectroChemistry.CellVoltage); @@ -201,9 +206,15 @@ protected: } } - return currentDensity; + //conversion from [A/cm^2] to [A/m^2] + return currentDensity*10000; } +protected: + DUNE_DEPRECATED_MSG("This is now a public member function (the name lost the underscore postfix.)") + static Scalar calculateCurrentDensity_(const VolumeVariables &volVars) + { calculateCurrentDensity(volVars); } + private: /*! diff --git a/dumux/material/chemistry/electrochemistry/electrochemistryni.hh b/dumux/material/chemistry/electrochemistry/electrochemistryni.hh index b55df00a82..6db0f53fa9 100644 --- a/dumux/material/chemistry/electrochemistry/electrochemistryni.hh +++ b/dumux/material/chemistry/electrochemistry/electrochemistryni.hh @@ -52,6 +52,7 @@ class ElectroChemistryNI : public ElectroChemistry<TypeTag, electroChemistryMode typedef ElectroChemistry<TypeTag, electroChemistryModel> ParentType; typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem; typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables; typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; @@ -72,6 +73,12 @@ class ElectroChemistryNI : public ElectroChemistry<TypeTag, electroChemistryMode energyEqIdx = FluidSystem::numComponents, //energy equation }; + enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) }; + enum { dofCodim = isBox ? GridView::dimension : 0 }; + + using GlobalPosition = typename Dune::FieldVector<Scalar, GridView::dimensionworld>; + using CellVector = typename Dune::FieldVector<Scalar, GridView::dimension>; + public: /*! * \brief Calculates reaction sources with an electrochemical model approach. @@ -82,42 +89,40 @@ public: * For this method, the \a values parameter stores source values */ static void reactionSource(PrimaryVariables &values, - const VolumeVariables &volVars) + Scalar currentDensity) { - static Scalar transportNumberH2O = GET_RUNTIME_PARAM(TypeTag, Scalar, ElectroChemistry.TransportNumberH20); - static Scalar maxIter = GET_RUNTIME_PARAM(TypeTag, Scalar, ElectroChemistry.MaxIterations); - static Scalar gridYMin = 0.0; - static Scalar gridYMax = GET_RUNTIME_PARAM(TypeTag, Scalar, Grid.UpperRightY); - static Scalar nCellsY = GET_RUNTIME_PARAM(TypeTag, Scalar, Grid.NumberOfCellsY); - static Scalar thermoneutralVoltage = GET_RUNTIME_PARAM(TypeTag, Scalar, ElectroChemistry.ThermoneutralVoltage); - static Scalar cellVoltage = GET_RUNTIME_PARAM(TypeTag, Scalar, ElectroChemistry.CellVoltage); - - //initialise current density - Scalar currentDensity = 0.0; - - //call internal method to calculate the current density - currentDensity = ParentType::calculateCurrentDensity_(volVars, maxIter); - //correction to account for actually relevant reaction area //current density has to be devided by the half length of the box - Scalar lengthBox = (gridYMax - gridYMin)/nCellsY; - - if(electroChemistryModel == ElectroChemistryModel::Acosta) - currentDensity = currentDensity/lengthBox; + //\todo Do we have multiply with the electrochemically active surface area (ECSA) here instead? + static Scalar gridYMax = GET_RUNTIME_PARAM(TypeTag, GlobalPosition, Grid.UpperRight)[1]; + static Scalar nCellsY = GET_RUNTIME_PARAM(TypeTag, CellVector, Grid.Cells)[1]; + + // Warning: This assumes the reaction layer is always just one cell (cell-centered) or half a box (box) thick + const auto lengthBox = gridYMax/nCellsY; + if (isBox) + currentDensity *= 2.0/lengthBox; else - currentDensity = currentDensity*2/lengthBox; + currentDensity *= 1.0/lengthBox; - //conversion from [A/cm^2] to [A/m^2] - currentDensity = currentDensity*10000; + static Scalar transportNumberH2O = GET_RUNTIME_PARAM(TypeTag, Scalar, ElectroChemistry.TransportNumberH20); + static Scalar thermoneutralVoltage = GET_RUNTIME_PARAM(TypeTag, Scalar, ElectroChemistry.ThermoneutralVoltage); + static Scalar cellVoltage = GET_RUNTIME_PARAM(TypeTag, Scalar, ElectroChemistry.CellVoltage); //calculation of flux terms with faraday equation values[contiH2OEqIdx] = currentDensity/(2*Constant::F); //reaction term in reaction layer - values[contiH2OEqIdx] += currentDensity/Constant::F*transportNumberH2O; //osmotic term in membrane + values[contiH2OEqIdx] += currentDensity/Constant::F*transportNumberH2O; //osmotic term in membrane values[contiO2EqIdx] = -currentDensity/(4*Constant::F); //O2-equation values[energyEqIdx] = (thermoneutralVoltage - cellVoltage)*currentDensity; //energy equation } + + DUNE_DEPRECATED_MSG("First compute the currentDensity with calculateCurrentDensity(const VolumeVariables&) and then use the method reactionSource(PrimaryVariables&, Scalar) instead") + static void reactionSource(PrimaryVariables &values, + const VolumeVariables &volVars) + { + reactionSource(values, this->calculateCurrentDensity(volVars)); + } }; -}// end namespace -#endif +}// end namespace +#endif diff --git a/test/porousmediumflow/2pnc/implicit/fuelcellproblem.hh b/test/porousmediumflow/2pnc/implicit/fuelcellproblem.hh index a06a097eb0..1f8501e8ed 100644 --- a/test/porousmediumflow/2pnc/implicit/fuelcellproblem.hh +++ b/test/porousmediumflow/2pnc/implicit/fuelcellproblem.hh @@ -24,7 +24,6 @@ #ifndef DUMUX_FUELCELL_PROBLEM_HH #define DUMUX_FUELCELL_PROBLEM_HH -#include <dumux/io/cubegridcreator.hh> #include <dumux/porousmediumflow/2pnc/implicit/model.hh> #include <dumux/porousmediumflow/implicit/problem.hh> #include <dumux/material/fluidsystems/h2on2o2.hh> @@ -46,11 +45,7 @@ NEW_TYPE_TAG(FuelCellBoxProblem, INHERITS_FROM(BoxModel, FuelCellProblem)); NEW_TYPE_TAG(FuelCellCCProblem, INHERITS_FROM(CCModel, FuelCellProblem)); // Set the grid type -#if HAVE_UG -SET_TYPE_PROP(FuelCellProblem, Grid, Dune::UGGrid<2>); -#endif -// Set the grid creator -SET_TYPE_PROP(FuelCellProblem, GridCreator, Dumux::CubeGridCreator<TypeTag>); +SET_TYPE_PROP(FuelCellProblem, Grid, Dune::YaspGrid<2>); // Set the problem property SET_TYPE_PROP(FuelCellProblem, Problem, Dumux::FuelCellProblem<TypeTag>); // Set the primary variable combination for the 2pnc model diff --git a/test/porousmediumflow/2pnc/implicit/test_2pnc.input b/test/porousmediumflow/2pnc/implicit/test_2pnc.input index 2bc445b56c..387623cb1d 100644 --- a/test/porousmediumflow/2pnc/implicit/test_2pnc.input +++ b/test/porousmediumflow/2pnc/implicit/test_2pnc.input @@ -1,19 +1,15 @@ -# Parameter file for test case 2pncmin. +# Parameter file for test case 2pnc. # Everything behind a '#' is a comment. -# Type "./test_2pncmin --help" for more information. +# Type "./test_2pnc --help" for more information. [TimeManager] -DtInitial = 5e-1 # initial time step size [s] -MaxTimeStepSize = 1000 # maximum time step size -TEnd= 1e3 # duration of the simulation [s] +DtInitial = 5e-1 # [s] initial time step size +MaxTimeStepSize = 1000 # [s] maximum time step size +TEnd= 1e3 # [s] duration of the simulation [Grid] -#Number of cells in X and Y directions -NumberOfCellsX = 21 -NumberOfCellsY = 6 -#Extend of entire domain -UpperRightX = 2.0e-3 # x-coordinate of the upper-right corner of the grid [m] -UpperRightY = 5.5e-4 # y-coordinate of the upper-right corner of the grid [m] +UpperRight = 2.0e-3 5.5e-4 # [m] upper right corner coordinates +Cells = 21 6 # [-] number of cells in x,y-direction [Problem] Name = fuelcell @@ -29,29 +25,17 @@ TemperatureHigh = 314.15 # [K] upper temperature limit for tabularization InitialTemperature = 310 # [K] initial temperature for tabularization [ElectroChemistry] -SpecificResistance = 0.25 #[Ohm*cm^2] -ReversibleVoltage = 1.191 #[V] -CellVoltage = 0.5 #[V] -ThermoneutralVoltage = 1.4836 #[V] -RefCurrentDensity = 1.87e-8 #[A/cm] for calculating exchange current density at reference conditions -RefO2PartialPressure = 5.0e5 #[Pa] for calculating exchange current density at reference conditions -RefTemperature = 353.25 #[K] for calculating exchange current density at reference conditions -ActivationBarrier = 73.0e3 #[J/mol] -TransferCoefficient = 0.5 #[-] (alpha) -NumElectrons = 2 #[-] number of electrons transferred in reaction +SpecificResistance = 0.25 # [Ohm*cm^2] +ReversibleVoltage = 1.191 # [V] +CellVoltage = 0.5 # [V] +ThermoneutralVoltage = 1.4836 # [V] +RefCurrentDensity = 1.87e-8 # [A/cm^2] for calculating exchange current density at reference conditions +RefO2PartialPressure = 5.0e5 # [Pa] for calculating exchange current density at reference conditions +RefTemperature = 353.25 # [K] for calculating exchange current density at reference conditions +ActivationBarrier = 73.0e3 # [J/mol] +TransferCoefficient = 0.5 # [-] (alpha) +NumElectrons = 2 # [-] number of electrons transferred in reaction SurfaceIncreasingFactor = 60 -TransportNumberH20 = 0.2327 #[-] account for osmotic H20 transport term from membrane, value Lena Walter -pO2Inlet = 0.3e5 #[Pa] partial pressure of oxygen at gas channel inlet -MaxIterations = 300 #[-] Maximum number for iterations for solving electrochemical system - -[Newton] -RelTolerance = 1e-8 -TargetSteps = 10 -MaxSteps = 15 -WriteConvergence = false -MaxTimeStepDivisions = 20 - -[LinearSolver] -ResidualReduction = 1e-8 -Verbosity = 0 -MaxIterations = 100 \ No newline at end of file +TransportNumberH20 = 0.2327 # [-] account for osmotic H20 transport term from membrane, value Lena Walter +pO2Inlet = 0.3e5 # [Pa] partial pressure of oxygen at gas channel inlet +MaxIterations = 300 # [-] Maximum number for iterations for solving electrochemical system diff --git a/test/porousmediumflow/2pnc/implicit/test_box2pnc.cc b/test/porousmediumflow/2pnc/implicit/test_box2pnc.cc index 6c99ad2656..826b60d121 100644 --- a/test/porousmediumflow/2pnc/implicit/test_box2pnc.cc +++ b/test/porousmediumflow/2pnc/implicit/test_box2pnc.cc @@ -41,19 +41,7 @@ void usage(const char *progName, const std::string &errorMsg) errorMessageOut += " [options]\n"; errorMessageOut += errorMsg; errorMessageOut += "\n\nThe list of mandatory options for this program is:\n" - "\t-TimeManager.TEnd End of the simulation [s] \n" - "\t-TimeManager.DtInitial Initial timestep size [s] \n" - "\t-Grid.File Name of the file containing the grid \n" - "\t definition in DGF format\n" - "\t-FluidSystem.NTemperature Number of tabularization entries [-] \n" - "\t-FluidSystem.NPressure Number of tabularization entries [-] \n" - "\t-FluidSystem.PressureLow Low end for tabularization of fluid properties [Pa] \n" - "\t-FluidSystem.PressureHigh High end for tabularization of fluid properties [Pa] \n" - "\t-FluidSystem.TemperatureLow Low end for tabularization of fluid properties [Pa] \n" - "\t-FluidSystem.TemperatureHigh High end for tabularization of fluid properties [Pa] \n" - "\t-SimulationControl.Name The name of the output files [-] \n" - "\t-InitialConditions.Temperature Initial temperature in the reservoir [K] \n" - "\t-InitialConditions.DepthBOR Depth below ground surface [m] \n"; + "\t-ParameterFile Parameter file (Input file) \n"; std::cout << errorMessageOut << "\n"; @@ -62,12 +50,6 @@ void usage(const char *progName, const std::string &errorMsg) int main(int argc, char** argv) { -#if HAVE_UG typedef TTAG(FuelCellBoxProblem) ProblemTypeTag; return Dumux::start<ProblemTypeTag>(argc, argv, usage); -#else -#warning You need UGGrid to run this test. - std::cerr << "You need UGGrid to run this test." << std::endl; - return 77; -#endif } -- GitLab