// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*****************************************************************************
* See the file COPYING for full copying permissions. *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see . *
*****************************************************************************/
/*!
* \file
*
* \brief Adaption of the BOX scheme to the non-isothermal
* compositional stokes model (with n components).
*/
#ifndef DUMUX_STOKESNCNI_MODEL_HH
#define DUMUX_STOKESNCNI_MODEL_HH
#include
#include
#include "stokesncnilocalresidual.hh"
#include "stokesncniproperties.hh"
namespace Dumux {
/*!
* \ingroup BoxStokesncniModel
* \brief Adaption of the BOX scheme to the non-isothermal compositional n-component Stokes model.
*
* This model implements a non-isothermal n-component Stokes flow of a fluid
* solving a momentum balance, a mass balance, a conservation equation for one component,
* and one balance equation for the energy.
*
* Momentum Balance:
* \f[
\frac{\partial \left(\varrho_g {\boldsymbol{v}}_g\right)}{\partial t}
+ \boldsymbol{\nabla} \boldsymbol{\cdot} \left(p_g {\bf {I}}
- \mu_g \left(\boldsymbol{\nabla} \boldsymbol{v}_g
+ \boldsymbol{\nabla} \boldsymbol{v}_g^T\right)\right)
- \varrho_g {\bf g} = 0,
* \f]
*
* Mass balance equation:
* \f[
\frac{\partial \varrho_g}{\partial t} + \boldsymbol{\nabla}\boldsymbol{\cdot}\left(\varrho_g {\boldsymbol{v}}_g\right) - q_g = 0
* \f]
*
* Component mass balance equation:
* \f[
\frac{\partial \left(\varrho_g X_g^\kappa\right)}{\partial t}
+ \boldsymbol{\nabla} \boldsymbol{\cdot} \left( \varrho_g {\boldsymbol{v}}_g X_g^\kappa
- D^\kappa_g \varrho_g \frac{M^\kappa}{M_g} \boldsymbol{\nabla} x_g^\kappa \right)
- q_g^\kappa = 0
* \f]
*
* Energy balance equation:
* \f[
\frac{\partial (\varrho_g u_g)}{\partial t}
+ \boldsymbol{\nabla} \boldsymbol{\cdot} \left( \varrho_g h_g {\boldsymbol{v}}_g
- \sum_\kappa \left[ h^\kappa_g D^\kappa_g \varrho_g \frac{M^\kappa}{M_g} \nabla x^\kappa_g \right]
- \lambda_g \boldsymbol{\nabla} T \right) - q_T = 0
* \f]
*
* This is discretized using a fully-coupled vertex
* centered finite volume (box) scheme as spatial and
* the implicit Euler method as temporal discretization.
*
*/
template
class StokesncniModel : public StokesncModel
{
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
enum { dim = GridView::dimension };
enum { transportCompIdx = Indices::transportCompIdx };
enum { phaseIdx = GET_PROP_VALUE(TypeTag, PhaseIdx) };
enum { useMoles = GET_PROP_VALUE(TypeTag, UseMoles) };
enum { numComponents = Indices::numComponents };
typedef typename GridView::template Codim<0>::Iterator ElementIterator;
typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
public:
//! \copydoc ImplicitModel::addOutputVtkFields
template
void addOutputVtkFields(const SolutionVector &sol,
MultiWriter &writer)
{
typedef Dune::BlockVector > ScalarField;
typedef Dune::BlockVector > VelocityField;
const Scalar scale_ = GET_PROP_VALUE(TypeTag, Scaling);
// create the required scalar fields
unsigned numVertices = this->gridView_().size(dim);
ScalarField &pn = *writer.allocateManagedBuffer(numVertices);
ScalarField &delP = *writer.allocateManagedBuffer(numVertices);
ScalarField &T = *writer.allocateManagedBuffer(numVertices);
ScalarField &h = *writer.allocateManagedBuffer(numVertices);
ScalarField *moleFraction[numComponents];
for (int i = 0; i < numComponents; ++i)
moleFraction[i] = writer.template allocateManagedBuffer(numVertices);
ScalarField *massFraction[numComponents];
for (int i = 0; i < numComponents; ++i)
massFraction[i] = writer.template allocateManagedBuffer(numVertices);
ScalarField &rho = *writer.allocateManagedBuffer(numVertices);
ScalarField &mu = *writer.allocateManagedBuffer(numVertices);
VelocityField &velocity = *writer.template allocateManagedBuffer (numVertices);
unsigned numElements = this->gridView_().size(0);
ScalarField &rank = *writer.allocateManagedBuffer(numElements);
FVElementGeometry fvGeometry;
VolumeVariables volVars;
ElementBoundaryTypes elemBcTypes;
ElementIterator eIt = this->gridView_().template begin<0>();
ElementIterator eEndIt = this->gridView_().template end<0>();
for (; eIt != eEndIt; ++eIt)
{
#if DUNE_VERSION_NEWER(DUNE_COMMON, 2, 4)
int idx = this->elementMapper().index(*eIt);
#else
int idx = this->elementMapper().map(*eIt);
#endif
rank[idx] = this->gridView_().comm().rank();
fvGeometry.update(this->gridView_(), *eIt);
elemBcTypes.update(this->problem_(), *eIt, fvGeometry);
#if DUNE_VERSION_NEWER(DUNE_COMMON, 2, 4)
int numLocalVerts = eIt->subEntities(dim);
#else
int numLocalVerts = eIt->template count();
#endif
for (int i = 0; i < numLocalVerts; ++i)
{
#if DUNE_VERSION_NEWER(DUNE_COMMON, 2, 4)
int vIdxGlobal = this->vertexMapper().subIndex(*eIt, i, dim);
#else
int vIdxGlobal = this->vertexMapper().map(*eIt, i, dim);
#endif
volVars.update(sol[vIdxGlobal],
this->problem_(),
*eIt,
fvGeometry,
i,
false);
pn[vIdxGlobal] = volVars.pressure()*scale_;
delP[vIdxGlobal] = volVars.pressure()*scale_ - 1e5;
for (int compIdx = 0; compIdx < numComponents; ++compIdx)
{
(*moleFraction[compIdx])[vIdxGlobal]= volVars.moleFraction(compIdx);
(*massFraction[compIdx])[vIdxGlobal]= volVars.massFraction(compIdx);
Valgrind::CheckDefined((*moleFraction[compIdx])[vIdxGlobal]);
Valgrind::CheckDefined((*massFraction[compIdx])[vIdxGlobal]);
}
T [vIdxGlobal] = volVars.temperature();
rho[vIdxGlobal] = volVars.density()*scale_*scale_*scale_;
mu[vIdxGlobal] = volVars.dynamicViscosity()*scale_;
h[vIdxGlobal] = volVars.enthalpy();
velocity[vIdxGlobal] = volVars.velocity();
velocity[vIdxGlobal] *= 1/scale_;
}
}
writer.attachVertexData(T, "temperature");
writer.attachVertexData(pn, "pg");
writer.attachVertexData(delP, "delP");
for (int j = 0; j < numComponents; ++j)
{
std::ostringstream moleFrac, massFrac;
moleFrac << "x_" << FluidSystem::phaseName(phaseIdx)
<< "^" << FluidSystem::componentName(j);
writer.attachVertexData(*moleFraction[j], moleFrac.str().c_str());
massFrac << "X_" << FluidSystem::phaseName(phaseIdx)
<< "^" << FluidSystem::componentName(j);
writer.attachVertexData(*massFraction[j], massFrac.str().c_str());
}
writer.attachVertexData(h, "h");
writer.attachVertexData(rho, "rho");
writer.attachVertexData(mu, "mu");
writer.attachVertexData(velocity, "v", dim);
}
};
}
#include "stokesncnipropertydefaults.hh"
#endif