Commit 33be2327 authored by Bernd Flemisch's avatar Bernd Flemisch
Browse files

[nonisothermal] remove deprecated nonisothermal models

Reviewed by Alex.



git-svn-id: svn://svn.iws.uni-stuttgart.de/DUMUX/dumux/trunk@13576 2fb0f335-1f38-0410-981e-8018bf24f1b0
parent 51cfe0da
......@@ -54,13 +54,10 @@ NEW_TYPE_TAG(TwoP);
NEW_TYPE_TAG(BoxTwoP, INHERITS_FROM(BoxModel, TwoP));
NEW_TYPE_TAG(CCTwoP, INHERITS_FROM(CCModel, TwoP));
// TODO: remove the following ifndef after the old 2pni model has been removed
#ifndef DUMUX_2PNI_PROPERTIES_HH
//! The type tags for the corresponding non-isothermal problems
NEW_TYPE_TAG(TwoPNI, INHERITS_FROM(TwoP, NonIsothermal));
NEW_TYPE_TAG(BoxTwoPNI, INHERITS_FROM(BoxModel, TwoPNI));
NEW_TYPE_TAG(CCTwoPNI, INHERITS_FROM(CCModel, TwoPNI));
#endif
//////////////////////////////////////////////////////////////////
// Property tags
......
......@@ -47,13 +47,10 @@ NEW_TYPE_TAG(TwoPTwoC);
NEW_TYPE_TAG(BoxTwoPTwoC, INHERITS_FROM(BoxModel, TwoPTwoC));
NEW_TYPE_TAG(CCTwoPTwoC, INHERITS_FROM(CCModel, TwoPTwoC));
// TODO: remove the following ifndef after the old 2p2cni model has been removed
#ifndef DUMUX_2P2CNI_PROPERTIES_HH
//! The type tags for the corresponding non-isothermal problems
NEW_TYPE_TAG(TwoPTwoCNI, INHERITS_FROM(TwoPTwoC, NonIsothermal));
NEW_TYPE_TAG(BoxTwoPTwoCNI, INHERITS_FROM(BoxModel, TwoPTwoCNI));
NEW_TYPE_TAG(CCTwoPTwoCNI, INHERITS_FROM(CCModel, TwoPTwoCNI));
#endif
//////////////////////////////////////////////////////////////////
// Property tags
......
// -*- 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 <http://www.gnu.org/licenses/>. *
*****************************************************************************/
/*!
* \file
* \brief This file contains data which is required to calculate
* the heat fluxes over a face of a finite volume.
*
* This means temperature gradients and the normal matrix
* heat flux.
*/
#ifndef DUMUX_2P2CNI_FLUX_VARIABLES_HH
#define DUMUX_2P2CNI_FLUX_VARIABLES_HH
#include "2p2cniproperties.hh"
#include <dumux/common/math.hh>
#include <dumux/implicit/2p2c/2p2cfluxvariables.hh>
namespace Dumux
{
/*!
* \ingroup TwoPTwoCNIModel
* \ingroup ImplicitFluxVariables
* \brief This template class contains data which is required to
* calculate the heat fluxes over a face of a finite
* volume for the non-isothermal two-phase two-component model.
* The mass fluxes are computed in the parent class.
*
* This means temperature gradients and the normal matrix
* heat flux.
*/
template <class TypeTag>
class TwoPTwoCNIFluxVariables : public TwoPTwoCFluxVariables<TypeTag>
{
typedef TwoPTwoCFluxVariables<TypeTag> ParentType;
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
typedef typename GET_PROP_TYPE(TypeTag, ThermalConductivityModel) ThermalConductivityModel;
typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
typedef typename GridView::template Codim<0>::Entity Element;
enum { dimWorld = GridView::dimensionworld };
enum { dim = GridView::dimension };
typedef Dune::FieldVector<Scalar, dim> DimVector;
typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
enum {
wPhaseIdx = Indices::wPhaseIdx,
nPhaseIdx = Indices::nPhaseIdx
};
public:
/*!
* \brief The constructor
*
* \param problem The problem
* \param element The finite element
* \param fvGeometry The finite-volume geometry in the fully implicit scheme
* \param faceIdx The local index of the sub-control-volume face
* \param elemVolVars The volume variables of the current element
* \param onBoundary Distinguishes if we are on a sub-control-volume face or on a boundary face
*/
TwoPTwoCNIFluxVariables(const Problem &problem,
const Element &element,
const FVElementGeometry &fvGeometry,
const int faceIdx,
const ElementVolumeVariables &elemVolVars,
bool onBoundary = false)
: ParentType(problem, element, fvGeometry, faceIdx, elemVolVars, onBoundary)
{
faceIdx_ = faceIdx;
calculateValues_(problem, element, elemVolVars);
}
/*!
* \brief The total heat flux \f$\mathrm{[J/s]}\f$ due to heat conduction
* of the rock matrix over the sub-control volume face in
* direction of the face normal.
*/
Scalar normalMatrixHeatFlux() const
{ return normalMatrixHeatFlux_; }
/*!
* \brief The local temperature gradient at the IP of the considered scv face.
*/
GlobalPosition temperatureGradient() const
{ return temperatureGrad_; }
/*!
* \brief The harmonically averaged effective thermal conductivity.
*/
Scalar effThermalConductivity() const
{ return lambdaEff_; }
protected:
void calculateValues_(const Problem &problem,
const Element &element,
const ElementVolumeVariables &elemVolVars)
{
// calculate temperature gradient using finite element
// gradients
temperatureGrad_ = 0;
GlobalPosition tmp(0.0);
for (unsigned int idx = 0; idx < this->face().numFap; idx++)
{
tmp = this->face().grad[idx];
// index for the element volume variables
int volVarsIdx = this->face().fapIndices[idx];
tmp *= elemVolVars[volVarsIdx].temperature();
temperatureGrad_ += tmp;
}
lambdaEff_ = 0;
calculateEffThermalConductivity_(problem, element, elemVolVars);
// project the heat flux vector on the face's normal vector
normalMatrixHeatFlux_ = temperatureGrad_* this->face().normal;
normalMatrixHeatFlux_ *= -lambdaEff_;
}
void calculateEffThermalConductivity_(const Problem &problem,
const Element &element,
const ElementVolumeVariables &elemVolVars)
{
const unsigned i = this->face().i;
const unsigned j = this->face().j;
Scalar lambdaI, lambdaJ;
if (GET_PROP_VALUE(TypeTag, ImplicitIsBox))
{
lambdaI =
ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[i].saturation(wPhaseIdx),
elemVolVars[i].thermalConductivity(wPhaseIdx),
elemVolVars[i].thermalConductivity(nPhaseIdx),
problem.spatialParams().thermalConductivitySolid(element, this->fvGeometry_, i),
problem.spatialParams().porosity(element, this->fvGeometry_, i));
lambdaJ =
ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[j].saturation(wPhaseIdx),
elemVolVars[j].thermalConductivity(wPhaseIdx),
elemVolVars[j].thermalConductivity(nPhaseIdx),
problem.spatialParams().thermalConductivitySolid(element, this->fvGeometry_, j),
problem.spatialParams().porosity(element, this->fvGeometry_, j));
}
else
{
const Element& elementI = *this->fvGeometry_.neighbors[i];
FVElementGeometry fvGeometryI;
fvGeometryI.subContVol[0].global = elementI.geometry().center();
lambdaI =
ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[i].saturation(wPhaseIdx),
elemVolVars[i].thermalConductivity(wPhaseIdx),
elemVolVars[i].thermalConductivity(nPhaseIdx),
problem.spatialParams().thermalConductivitySolid(elementI, fvGeometryI, 0),
problem.spatialParams().porosity(elementI, fvGeometryI, 0));
const Element& elementJ = *this->fvGeometry_.neighbors[j];
FVElementGeometry fvGeometryJ;
fvGeometryJ.subContVol[0].global = elementJ.geometry().center();
lambdaJ =
ThermalConductivityModel::effectiveThermalConductivity(elemVolVars[j].saturation(wPhaseIdx),
elemVolVars[j].thermalConductivity(wPhaseIdx),
elemVolVars[j].thermalConductivity(nPhaseIdx),
problem.spatialParams().thermalConductivitySolid(elementJ, fvGeometryJ, 0),
problem.spatialParams().porosity(elementJ, fvGeometryJ, 0));
}
// -> harmonic mean
lambdaEff_ = harmonicMean(lambdaI, lambdaJ);
}
private:
Scalar lambdaEff_;
Scalar normalMatrixHeatFlux_;
GlobalPosition temperatureGrad_;
int faceIdx_;
};
} // end namespace
#endif
// -*- 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 <http://www.gnu.org/licenses/>. *
*****************************************************************************/
/*!
* \file
* \brief Defines the indices used by the non-isothermal two-phase two-component model
*/
#ifndef DUMUX_2P2CNI_INDICES_HH
#define DUMUX_2P2CNI_INDICES_HH
#include "2p2cniproperties.hh"
#include <dumux/implicit/2p2c/2p2cindices.hh>
namespace Dumux
{
/*!
* \ingroup TwoPTwoCNIModel
* \ingroup ImplicitIndices
* \brief Indices for the non-isothermal two-phase two-component model
*
* \tparam formulation The formulation, either pwsn or pnsw.
* \tparam PVOffset The first index in a primary variable vector.
*/
template <class TypeTag, int formulation, int PVOffset>
class TwoPTwoCNIIndices : public TwoPTwoCIndices<TypeTag, formulation, PVOffset>
{
public:
static const int temperatureIdx = PVOffset + 2; //! The index for temperature in primary variable vectors.
static const int energyEqIdx = PVOffset + 2; //! The index for energy in equation vectors.
};
}
#endif
// -*- 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 <http://www.gnu.org/licenses/>. *
*****************************************************************************/
/*!
* \file
*
* \brief Element-wise calculation of the Jacobian matrix for problems
* using the non-isothermal two-phase two-component fully implicit model.
*
*/
#ifndef DUMUX_NEW_2P2CNI_LOCAL_RESIDUAL_HH
#define DUMUX_NEW_2P2CNI_LOCAL_RESIDUAL_HH
#include "2p2cniproperties.hh"
#include <dumux/implicit/2p2c/2p2clocalresidual.hh>
namespace Dumux
{
/*!
* \ingroup TwoPTwoCNIModel
* \ingroup ImplicitLocalResidual
* \brief Element-wise calculation of the Jacobian matrix for problems
* using the two-phase two-component fully implicit model.
*/
template<class TypeTag>
class TwoPTwoCNILocalResidual : public TwoPTwoCLocalResidual<TypeTag>
{
typedef TwoPTwoCLocalResidual<TypeTag> ParentType;
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
enum {
numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
energyEqIdx = Indices::energyEqIdx,
temperatureIdx = Indices::temperatureIdx,
wPhaseIdx = Indices::wPhaseIdx,
nPhaseIdx = Indices::nPhaseIdx
};
public:
/*!
* \brief Constructor. Sets the upwind weight.
*/
TwoPTwoCNILocalResidual()
{
// retrieve the upwind weight for the mass conservation equations. Use the value
// specified via the property system as default, and overwrite
// it by the run-time parameter from the Dune::ParameterTree
massUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
};
/*!
* \brief Evaluate the amount of all conservation quantities
* (e.g. phase mass) within a sub-control volume.
*
* The result should be averaged over the volume (e.g. phase mass
* inside a sub control volume divided by the volume)
*
* \param storage The storage of the conservation quantity (mass or energy) within the sub-control volume
* \param scvIdx The sub-control-volume index
* \param usePrevSol Evaluate function with solution of current or previous time step
*/
void computeStorage(PrimaryVariables &storage, const int scvIdx, bool usePrevSol) const
{
// compute the storage term for phase mass
ParentType::computeStorage(storage, scvIdx, usePrevSol);
// if flag usePrevSol is set, the solution from the previous
// time step is used, otherwise the current solution is
// used. The secondary variables are used accordingly. This
// is required to compute the derivative of the storage term
// using the implicit Euler method.
const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_() : this->curVolVars_();
const VolumeVariables &volVars = elemVolVars[scvIdx];
// compute the energy storage
storage[energyEqIdx] =
volVars.porosity()*(volVars.density(wPhaseIdx) *
volVars.internalEnergy(wPhaseIdx) *
volVars.saturation(wPhaseIdx)
+
volVars.density(nPhaseIdx) *
volVars.internalEnergy(nPhaseIdx) *
volVars.saturation(nPhaseIdx))
+
// heat capacity is already multiplied by the density
// of the porous material and the porosity in the problem file
volVars.temperature()*volVars.heatCapacity();
}
/*!
* \brief Evaluates the advective mass flux and the heat flux
* over a face of a sub-control volume and writes the result into
* the flux vector.
*
* \param flux The advective flux over the sub-control-volume face for each component
* \param fluxVars The flux variables at the current sub-control-volume face
*
* This method is called by compute flux (base class).
*/
void computeAdvectiveFlux(PrimaryVariables &flux,
const FluxVariables &fluxVars) const
{
// advective mass flux
ParentType::computeAdvectiveFlux(flux, fluxVars);
// advective heat flux in all phases
flux[energyEqIdx] = 0;
for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
// vertex data of the upstream and the downstream vertices
const VolumeVariables &up = this->curVolVars_(fluxVars.upstreamIdx(phaseIdx));
const VolumeVariables &dn = this->curVolVars_(fluxVars.downstreamIdx(phaseIdx));
flux[energyEqIdx] +=
fluxVars.volumeFlux(phaseIdx) * (massUpwindWeight_ * // upstream vertex
( up.density(phaseIdx) *
up.enthalpy(phaseIdx))
+
(1-massUpwindWeight_) * // downstream vertex
( dn.density(phaseIdx) *
dn.enthalpy(phaseIdx)) );
}
}
/*!
* \brief Adds the diffusive heat flux to the flux vector over
* the face of a sub-control volume.
*
* \param flux The diffusive flux over the sub-control-volume face for each conservation quantity (mass, energy)
* \param fluxVars The flux variables at the current sub-control-volume face
*
* This method is called by compute flux (base class).
*/
void computeDiffusiveFlux(PrimaryVariables &flux,
const FluxVariables &fluxVars) const
{
// diffusive mass flux
ParentType::computeDiffusiveFlux(flux, fluxVars);
// diffusive heat flux
flux[temperatureIdx] +=
fluxVars.normalMatrixHeatFlux();
}
private:
Scalar massUpwindWeight_;
};
}
#endif
// -*- 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 <http://www.gnu.org/licenses/>. *
*****************************************************************************/
/*!
* \file
*
* \brief Adaption of the fully implicit scheme to the non-isothermal
* two-phase two-component flow model.
*/
#ifndef DUMUX_NEW_2P2CNI_MODEL_HH
#define DUMUX_NEW_2P2CNI_MODEL_HH
#include "2p2cniproperties.hh"
#include <dumux/implicit/2p2c/2p2cmodel.hh>
namespace Dumux {
/*!
* \ingroup TwoPTwoCNIModel
* \brief Adaption of the fully implicit scheme to the non-isothermal
* two-phase two-component flow model.
*
* This model implements a non-isothermal two-phase flow of two compressible and partly miscible fluids
* \f$\alpha \in \{ w, n \}\f$. Thus each component \f$\kappa \in \{ w, a \}\f$ can be present in
* each phase.
* Using the standard multiphase Darcy approach a mass balance equation is
* solved:
* \f{eqnarray*}
&& \phi \frac{\partial (\sum_\alpha \varrho_\alpha X_\alpha^\kappa S_\alpha )}{\partial t}
- \sum_\alpha \text{div} \left\{ \varrho_\alpha X_\alpha^\kappa
\frac{k_{r\alpha}}{\mu_\alpha} \mathbf{K}
(\textbf{grad}\, p_\alpha - \varrho_{\alpha} \mbox{\bf g}) \right\}\\
&-& \sum_\alpha \text{div} \left\{ D_{\alpha,\text{pm}}^\kappa \varrho_{\alpha} \frac{M^\kappa}{M_\alpha}
\textbf{grad} x^\kappa_{\alpha} \right\}
- \sum_\alpha q_\alpha^\kappa = 0 \qquad \kappa \in \{w, a\} \, ,
\alpha \in \{w, n\}
* \f}
* For the energy balance, local thermal equilibrium is assumed which results in one
* energy conservation equation for the porous solid matrix and the fluids:
* \f{eqnarray*}
&& \phi \frac{\partial \left( \sum_\alpha \varrho_\alpha u_\alpha S_\alpha \right)}{\partial t}
+ \left( 1 - \phi \right) \frac{\partial (\varrho_s c_s T)}{\partial t}
- \sum_\alpha \text{div} \left\{ \varrho_\alpha h_\alpha
\frac{k_{r\alpha}}{\mu_\alpha} \mathbf{K} \left( \textbf{grad}\,
p_\alpha
- \varrho_\alpha \mathbf{g} \right) \right\} \\
&-& \text{div} \left( \lambda_\text{pm} \textbf{grad} \, T \right)
- q^h = 0 \qquad \alpha \in \{w, n\}
\f}
*
* All equations are discretized using a vertex-centered finite volume (box)
* or cell-centered finite volume scheme as spatial
* and the implicit Euler method as time discretization.
*
* By using constitutive relations for the capillary pressure \f$p_c =
* p_n - p_w\f$ and relative permeability \f$k_{r\alpha}\f$ and taking
* advantage of the fact that \f$S_w + S_n = 1\f$ and \f$X^\kappa_w + X^\kappa_n = 1\f$, the number of
* unknowns can be reduced to two.
* If both phases are present the primary variables are, like in the nonisothermal two-phase model, either \f$p_w\f$, \f$S_n\f$ and
* temperature or \f$p_n\f$, \f$S_w\f$ and temperature. The formulation which ought to be used can be
* specified by setting the <tt>Formulation</tt> property to either
* <tt>TwoPTwoCIndices::pWsN</tt> or <tt>TwoPTwoCIndices::pNsW</tt>. By
* default, the model uses \f$p_w\f$ and \f$S_n\f$.
* In case that only one phase (nonwetting or wetting phase) is present the second primary
* variable represents a mass fraction. The correct assignment of the second
* primary variable is performed by a phase state dependent primary variable switch.
* The phase state is stored for all nodes of the system. The following cases can be distinguished:
* <ul>
* <li>
* Both phases are present: The saturation is used (either\f$S_n\f$ or \f$S_w\f$, dependent on the chosen formulation).
* </li>
* <li>
* Only wetting phase is present: The mass fraction of air in the wetting phase \f$X^a_w\f$ is used.
* </li>
* <li>
* Only non-wetting phase is present: The mass fraction of water in the non-wetting phase, \f$X^w_n\f$, is used.
* </li>
* </ul>
*/
template<class TypeTag>
class TwoPTwoCNIModel : public TwoPTwoCModel<TypeTag>
{
};
}
#include "2p2cnipropertydefaults.hh"
#endif
// -*- 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 <http://www.gnu.org/licenses/>. *
*****************************************************************************/
/*!
* \ingroup Properties
* \ingroup ImplicitProperties
* \ingroup TwoPTwoCNIModel
* \file
*
* \brief Defines the properties required for the non-isothermal two-phase
* two-component fully implicit model.
*/
#ifndef DUMUX_2P2CNI_PROPERTIES_HH
#define DUMUX_2P2CNI_PROPERTIES_HH
#warning You are including the old 2p2cni model which will be removed after 2.6. See CHANGELOG for details.
#include <dumux/implicit/2p2c/2p2cproperties.hh>
namespace Dumux
{
namespace Properties
{
//////////////////////////////////////////////////////////////////
// Type tags
//////////////////////////////////////////////////////////////////