Commit 29c68ffa authored by Andreas Lauser's avatar Andreas Lauser
Browse files

*vangenuchten, box jacobian assembler, box local jacobian, box local residual: various changes

- box jacobian assembler: Do no longer use the PDELab grid operator space to assemble the jacobian.
- vangenuchten: fix typos to make it compile again
- box local jacobian: evaluate local residual inside local jacobian to increase efficiency slightly
- box local residual: correct comment about fluxes

git-svn-id: svn://svn.iws.uni-stuttgart.de/DUMUX/dumux/trunk@4693 2fb0f335-1f38-0410-981e-8018bf24f1b0
parent 7c6132c3
...@@ -592,11 +592,10 @@ public: ...@@ -592,11 +592,10 @@ public:
int numEdges; //!< number of edges int numEdges; //!< number of edges
int numFaces; //!< number of faces (0 in < 3D) int numFaces; //!< number of faces (0 in < 3D)
const LocalFEMSpace feMap_; static const LocalFEMSpace feMap_;
bool computeGradientAtScvCenters; bool computeGradientAtScvCenters;
BoxFVElementGeometry() BoxFVElementGeometry()
: feMap_()
{ {
computeGradientAtScvCenters = false; computeGradientAtScvCenters = false;
} }
...@@ -843,6 +842,9 @@ public: ...@@ -843,6 +842,9 @@ public:
} }
}; };
template<class TypeTag>
const typename BoxFVElementGeometry<TypeTag>::LocalFEMSpace BoxFVElementGeometry<TypeTag>::feMap_;
} }
#endif #endif
......
...@@ -126,15 +126,15 @@ public: ...@@ -126,15 +126,15 @@ public:
// set the current grid element and update the element's // set the current grid element and update the element's
// finite volume geometry // finite volume geometry
elemPtr_ = &element; elemPtr_ = &element;
fvElemGeom_.update(gridView_(), element);
reset_(); reset_();
int elemColor = jacAsm_().elementColor(element); int elemColor = jacAsm_().elementColor(element);
if (elemColor == Green) { if (elemColor == Green) {
// Green elements don't need to be reassembled // Green elements don't need to be reassembled
return; return;
} }
fvElemGeom_.update(gridView_(), elem_());
bcTypes_.update(problem_(), elem_(), fvElemGeom_); bcTypes_.update(problem_(), elem_(), fvElemGeom_);
// this is pretty much a HACK because the internal state of // this is pretty much a HACK because the internal state of
...@@ -156,18 +156,14 @@ public: ...@@ -156,18 +156,14 @@ public:
elem_(), elem_(),
fvElemGeom_, fvElemGeom_,
false /* isOldSol? */); false /* isOldSol? */);
if (numDiffMethod != 0) { // calculate the local residual
// for forward and backward differences we need the local localResidual().eval(elem_(),
// residual at the evaluation point. For efficiency we fvElemGeom_,
// only calculate this once. prevVolVars_,
localResidual().eval(elem_(), curVolVars_,
fvElemGeom_, bcTypes_);
prevVolVars_, residual_ = localResidual().residual();
curVolVars_,
bcTypes_);
evalPointResid_ = localResidual().residual();
};
// calculate the local jacobian matrix // calculate the local jacobian matrix
ElementSolutionVector partialDeriv(numVertices); ElementSolutionVector partialDeriv(numVertices);
for (int j = 0; j < numVertices; j++) { for (int j = 0; j < numVertices; j++) {
...@@ -186,13 +182,15 @@ public: ...@@ -186,13 +182,15 @@ public:
} }
/*! /*!
* \brief Returns a reference to the local residual. * \brief Returns a reference to the object which calculates the
* local residual.
*/ */
const LocalResidual &localResidual() const const LocalResidual &localResidual() const
{ return localResidual_; } { return localResidual_; }
/*! /*!
* \brief Returns a reference to the local residual. * \brief Returns a reference to the object which calculates the
* local residual.
*/ */
LocalResidual &localResidual() LocalResidual &localResidual()
{ return localResidual_; } { return localResidual_; }
...@@ -209,6 +207,15 @@ public: ...@@ -209,6 +207,15 @@ public:
const MatrixBlock &mat(int i, int j) const const MatrixBlock &mat(int i, int j) const
{ return A_[i][j]; } { return A_[i][j]; }
/*!
* \brief Returns the residual of the equations at vertex i.
*
* \param i The local vertex (or sub-contol volume) index on which
* the equations are defined
*/
const PrimaryVariables &residual(int i) const
{ return residual_[i]; }
protected: protected:
Implementation &asImp_() Implementation &asImp_()
{ return *static_cast<Implementation*>(this); } { return *static_cast<Implementation*>(this); }
...@@ -312,7 +319,7 @@ protected: ...@@ -312,7 +319,7 @@ protected:
} }
else { else {
// backward differences // backward differences
dest = evalPointResid_; dest = residual_;
} }
...@@ -337,7 +344,7 @@ protected: ...@@ -337,7 +344,7 @@ protected:
} }
else { else {
// forward differences // forward differences
dest -= evalPointResid_; dest -= residual_;
} }
dest /= delta; dest /= delta;
...@@ -395,8 +402,8 @@ protected: ...@@ -395,8 +402,8 @@ protected:
} }
const Element *elemPtr_; const Element *elemPtr_;
FVElementGeometry fvElemGeom_; FVElementGeometry fvElemGeom_;
ElementBoundaryTypes bcTypes_; ElementBoundaryTypes bcTypes_;
// The problem we would like to solve // The problem we would like to solve
...@@ -406,11 +413,12 @@ protected: ...@@ -406,11 +413,12 @@ protected:
// levels // levels
ElementVolumeVariables prevVolVars_; ElementVolumeVariables prevVolVars_;
ElementVolumeVariables curVolVars_; ElementVolumeVariables curVolVars_;
ElementSolutionVector evalPointResid_; // residual at evaluation point
LocalResidual localResidual_; LocalResidual localResidual_;
LocalBlockMatrix A_; LocalBlockMatrix A_;
}; ElementSolutionVector residual_;
};
} }
#endif #endif
...@@ -119,19 +119,22 @@ public: ...@@ -119,19 +119,22 @@ public:
*/ */
void eval(const Element &element) void eval(const Element &element)
{ {
FVElementGeometry fvGeom; FVElementGeometry fvElemGeom;
fvGeom.update(gridView_(), element); fvElemGeom.update(gridView_(), element);
fvElemGeomPtr_ = &fvElemGeom;
ElementVolumeVariables volVarsPrev, volVarsCur; ElementVolumeVariables volVarsPrev, volVarsCur;
volVarsPrev.update(problem_(), volVarsPrev.update(problem_(),
element, element,
fvGeom, fvElemGeom_(),
true /* oldSol? */); true /* oldSol? */);
volVarsCur.update(problem_(), volVarsCur.update(problem_(),
element, element,
fvGeom, fvElemGeom_(),
false /* oldSol? */); false /* oldSol? */);
ElementBoundaryTypes bcTypes; ElementBoundaryTypes bcTypes;
bcTypes.update(problem_(), element, fvGeom); bcTypes.update(problem_(), element, fvElemGeom_());
// this is pretty much a HACK because the internal state of // this is pretty much a HACK because the internal state of
// the problem is not supposed to be changed during the // the problem is not supposed to be changed during the
...@@ -140,7 +143,7 @@ public: ...@@ -140,7 +143,7 @@ public:
// not thread save.) The real solution are context objects! // not thread save.) The real solution are context objects!
problem_().updateCouplingParams(element); problem_().updateCouplingParams(element);
asImp_().eval(element, fvGeom, volVarsPrev, volVarsCur, bcTypes); asImp_().eval(element, fvElemGeom_(), volVarsPrev, volVarsCur, bcTypes);
} }
/*! /*!
...@@ -154,21 +157,26 @@ public: ...@@ -154,21 +157,26 @@ public:
*/ */
void evalStorage(const Element &element) void evalStorage(const Element &element)
{ {
FVElementGeometry fvGeom; elemPtr_ = &element;
fvGeom.update(gridView_(), element);
FVElementGeometry fvElemGeom;
fvElemGeom.update(gridView_(), element);
fvElemGeomPtr_ = &fvElemGeom;
ElementBoundaryTypes bcTypes; ElementBoundaryTypes bcTypes;
bcTypes.update(problem_(), element, fvGeom); bcTypes.update(problem_(), element, fvElemGeom_());
bcTypesPtr_ = &bcTypes;
// no previous volume variables!
prevVolVarsPtr_ = 0;
ElementVolumeVariables volVars; ElementVolumeVariables volVars;
volVars.update(problem_(), element, fvGeom, false); volVars.update(problem_(), element, fvElemGeom_(), false);
curVolVarsPtr_ = &volVars;
residual_.resize(fvGeom.numVertices); residual_.resize(fvElemGeom_().numVertices);
residual_ = 0; residual_ = 0;
elemPtr_ = &element;
fvElemGeomPtr_ = &fvGeom;
bcTypesPtr_ = &bcTypes;
prevVolVarsPtr_ = 0;
curVolVarsPtr_ = &volVars;
asImp_().evalStorage_(); asImp_().evalStorage_();
} }
...@@ -183,23 +191,21 @@ public: ...@@ -183,23 +191,21 @@ public:
void evalFluxes(const Element &element, void evalFluxes(const Element &element,
const ElementVolumeVariables &curVolVars) const ElementVolumeVariables &curVolVars)
{ {
FVElementGeometry fvGeom; elemPtr_ = &element;
fvGeom.update(gridView_(), element); fvElemGeomPtr_ = &model_().fvElemGeom(element);
ElementBoundaryTypes bcTypes; ElementBoundaryTypes bcTypes;
bcTypes.update(problem_(), element, fvGeom); bcTypes.update(problem_(), element, fvElemGeom_());
residual_.resize(fvGeom.numVertices); residual_.resize(fvElemGeom_().numVertices);
residual_ = 0; residual_ = 0;
elemPtr_ = &element;
fvElemGeomPtr_ = &fvGeom;
bcTypesPtr_ = &bcTypes; bcTypesPtr_ = &bcTypes;
prevVolVarsPtr_ = 0; prevVolVarsPtr_ = 0;
curVolVarsPtr_ = &curVolVars; curVolVarsPtr_ = &curVolVars;
asImp_().evalFluxes_(); asImp_().evalFluxes_();
} }
/*! /*!
* \brief Compute the local residual, i.e. the deviation of the * \brief Compute the local residual, i.e. the deviation of the
* equations from zero. * equations from zero.
...@@ -418,15 +424,16 @@ protected: ...@@ -418,15 +424,16 @@ protected:
// //
// dStorage/dt = Flux + Source // dStorage/dt = Flux + Source
// //
// Re-arranging this, we get // where the 'Flux' and the 'Source' terms represent the
// mass per second which _ENTER_ the finite
// volume. Re-arranging this, we get
// //
// dStorage/dt - Source - Flux = 0 // dStorage/dt - Source - Flux = 0
// //
// The residual already contains the "dStorage/dt - // Since the flux calculated by computeFlux() goes _OUT_
// Source" term, so we have to subtract the flux // of sub-control volume i and _INTO_ sub-control volume
// term. Since the calculated flux goes from sub-control // j, we need to add the flux to finite volume i and
// volume i to sub-control volume j, we need to add the // subtract it from finite volume j
// flux to j and subtract it from i
residual_[i] += flux; residual_[i] += flux;
residual_[j] -= flux; residual_[j] -= flux;
} }
...@@ -613,6 +620,7 @@ protected: ...@@ -613,6 +620,7 @@ protected:
const ElementBoundaryTypes *bcTypesPtr_; const ElementBoundaryTypes *bcTypesPtr_;
}; };
} }
#endif #endif
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "pdelabboxlocaloperator.hh" #include "pdelabboxlocaloperator.hh"
namespace Dumux { namespace Dumux {
namespace PDELab { namespace PDELab {
/*! /*!
...@@ -42,6 +41,7 @@ class BoxAssembler ...@@ -42,6 +41,7 @@ class BoxAssembler
typedef typename GET_PROP_TYPE(TypeTag, PTAG(VertexMapper)) VertexMapper; typedef typename GET_PROP_TYPE(TypeTag, PTAG(VertexMapper)) VertexMapper;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementMapper)) ElementMapper; typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementMapper)) ElementMapper;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(Constraints)) Constraints; typedef typename GET_PROP_TYPE(TypeTag, PTAG(Constraints)) Constraints;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(ScalarGridFunctionSpace)) ScalarGridFunctionSpace; typedef typename GET_PROP_TYPE(TypeTag, PTAG(ScalarGridFunctionSpace)) ScalarGridFunctionSpace;
typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridFunctionSpace)) GridFunctionSpace; typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridFunctionSpace)) GridFunctionSpace;
...@@ -60,6 +60,7 @@ class BoxAssembler ...@@ -60,6 +60,7 @@ class BoxAssembler
typedef typename GridView::IntersectionIterator IntersectionIterator; typedef typename GridView::IntersectionIterator IntersectionIterator;
typedef typename GridView::template Codim<dim>::Entity Vertex; typedef typename GridView::template Codim<dim>::Entity Vertex;
typedef typename GridView::template Codim<dim>::EntityPointer VertexPointer;
typedef typename GridView::template Codim<dim>::Iterator VertexIterator; typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
typedef SolutionVector Vector; typedef SolutionVector Vector;
...@@ -123,7 +124,6 @@ public: ...@@ -123,7 +124,6 @@ public:
*/ */
void init(Problem& problem) void init(Problem& problem)
{ {
inJacobianAssemble_ = false;
problemPtr_ = &problem; problemPtr_ = &problem;
fem_ = new FEM(); fem_ = new FEM();
//cn_ = new Constraints(*problemPtr_); //cn_ = new Constraints(*problemPtr_);
...@@ -148,17 +148,7 @@ public: ...@@ -148,17 +148,7 @@ public:
matrix_ = new Matrix(*gridOperatorSpace_); matrix_ = new Matrix(*gridOperatorSpace_);
*matrix_ = 0; *matrix_ = 0;
reuseMatrix_ = false; reuseMatrix_ = false;
// calculate the ghost vertices
VertexIterator vIt = gridView_().template begin<dim>();
VertexIterator vEndIt = gridView_().template end<dim>();
for (; vIt != vEndIt; ++vIt) {
if (vIt->partitionType() == Dune::GhostEntity) {
int vIdx = vertexMapper_().map(*vIt);
ghostIndices_.push_back(vIdx);
}
};
int numVerts = gridView_().size(dim); int numVerts = gridView_().size(dim);
int numElems = gridView_().size(0); int numElems = gridView_().size(0);
residual_.resize(numVerts); residual_.resize(numVerts);
...@@ -196,8 +186,26 @@ public: ...@@ -196,8 +186,26 @@ public:
*/ */
void assemble() void assemble()
{ {
// assemble the global jacobian matrix (*matrix_) = 0.0;
residual_ = 0.0;
ElementIterator elemIt = gridView_().template begin<0>();
ElementIterator elemEndIt = gridView_().template end<0>();
for (; elemIt != elemEndIt; ++elemIt) {
const Element &elem = *elemIt;
if (elem.partitionType() == Dune::GhostEntity)
assembleGhostElement_(elem);
else
assembleElement_(elem);
};
return;
#if 0
// assemble the global jacobian matrix
if (!reuseMatrix_) { if (!reuseMatrix_) {
// we actually need to reassemle!
if (enablePartialReassemble) { if (enablePartialReassemble) {
// move the evaluation points of red vertices // move the evaluation points of red vertices
for (int i = 0; i < vertexColor_.size(); ++i) { for (int i = 0; i < vertexColor_.size(); ++i) {
...@@ -208,18 +216,16 @@ public: ...@@ -208,18 +216,16 @@ public:
reassembleTolerance_ = nextReassembleTolerance_; reassembleTolerance_ = nextReassembleTolerance_;
// we actually need to reassemle!
resetMatrix_(); resetMatrix_();
inJacobianAssemble_ = true; assemble_();
gridOperatorSpace_->jacobian(model_().curSol(), *matrix_);
inJacobianAssemble_ = false;
} }
reuseMatrix_ = false; reuseMatrix_ = false;
// calculate the global residual // calculate the global residual
residual_ = 0; residual_ = 0;
gridOperatorSpace_->residual(model_().curSol(), residual_); //gridOperatorSpace_->residual(model_().curSol(), residual_);
#if 0
typedef typename Matrix::block_type BlockType; typedef typename Matrix::block_type BlockType;
// set the entries for the ghost nodes // set the entries for the ghost nodes
BlockType Id(0.0); BlockType Id(0.0);
...@@ -234,6 +240,8 @@ public: ...@@ -234,6 +240,8 @@ public:
residual_[globI] = 0; residual_[globI] = 0;
model_().curSol()[globI] = 0; model_().curSol()[globI] = 0;
} }
#endif
#endif
} }
/*! /*!
...@@ -484,9 +492,53 @@ public: ...@@ -484,9 +492,53 @@ public:
private: private:
// assemble a non-ghost element
void assembleElement_(const Element &elem)
{
model_().localJacobian().assemble(elem);
int numVertices = elem.template count<dim>();
for (int i=0; i < numVertices; ++ i) {
int globI = vertexMapper_().map(elem, i, dim);
// update the global residual
residual_[globI] += model_().localJacobian().residual(i);
// update the global jacobian
for (int j=0; j < numVertices; ++ j) {
int globJ = vertexMapper_().map(elem, j, dim);
(*matrix_)[globI][globJ] +=
model_().localJacobian().mat(i,j);
}
}
}
// "assemble" a ghost element
void assembleGhostElement_(const Element &elem)
{
int n = elem.template count<dim>();
for (int i=0; i < n; ++i) {
const VertexPointer vp = elem.template subEntity<dim>(i);
if (vp->partitionType() != Dune::GhostEntity)
continue; // ignore a ghost cell's non-ghost vertices
// set main diagonal entries for the vertex
int vIdx = vertexMapper_().map(*vp);
typedef typename Matrix::block_type BlockType;
BlockType &J = (*matrix_)[vIdx][vIdx];
for (int j = 0; j < BlockType::rows; ++j)
J[j][j] = 1.0;
// set residual for the vertex
residual_[vIdx] = 0;
}
}
void resetMatrix_() void resetMatrix_()
{ {
if (!enablePartialReassemble) { if (!enablePartialReassemble) {
// If partial reassembly of the jacobian is not enabled,
// we can just reset everything!
(*matrix_) = 0; (*matrix_) = 0;
return; return;
} }
...@@ -507,7 +559,7 @@ private: ...@@ -507,7 +559,7 @@ private:
//printSparseMatrix(std::cout, *matrix_, "J", "row"); //printSparseMatrix(std::cout, *matrix_, "J", "row");
} }
Problem &problem_() Problem &problem_()
{ return *problemPtr_; } { return *problemPtr_; }
const Problem &problem_() const const Problem &problem_() const
...@@ -534,7 +586,6 @@ private: ...@@ -534,7 +586,6 @@ private:
Matrix *matrix_; Matrix *matrix_;
bool reuseMatrix_; bool reuseMatrix_;
bool inJacobianAssemble_;