From 2e884452830ab5ae69d19f3884c9120234250ad6 Mon Sep 17 00:00:00 2001 From: Kilian Weishaupt <kilian.weishaupt@iws.uni-stuttgart.de> Date: Mon, 5 Dec 2016 16:21:40 +0100 Subject: [PATCH] [staggeredGrid][localJacobian] Add derivative of cc dofs w.r.t cc dofs *Naive implementation *Remove unused stuff --- dumux/implicit/staggered/localjacobian.hh | 280 +++++++----------- dumux/implicit/staggered/localresidual.hh | 22 +- .../staggered/staggeredtestproblem.hh | 5 +- 3 files changed, 123 insertions(+), 184 deletions(-) diff --git a/dumux/implicit/staggered/localjacobian.hh b/dumux/implicit/staggered/localjacobian.hh index 4d11f25824..3302a894c8 100644 --- a/dumux/implicit/staggered/localjacobian.hh +++ b/dumux/implicit/staggered/localjacobian.hh @@ -94,7 +94,10 @@ class StaggeredLocalJacobian : public ImplicitLocalJacobian<TypeTag> typename DofTypeIndices::CellCenterIdx cellCenterIdx; typename DofTypeIndices::FaceIdx faceIdx; - using AssemblyMap = std::vector<std::vector<std::vector<IndexType>>>; + using CellCenterPrimaryVariables = typename GET_PROP_TYPE(TypeTag, CellCenterPrimaryVariables); + using FacePrimaryVariables = typename GET_PROP_TYPE(TypeTag, FacePrimaryVariables); + using GlobalFaceVars = typename GET_PROP_TYPE(TypeTag, GlobalFaceVars); + public: @@ -145,14 +148,13 @@ public: ElementBoundaryTypes elemBcTypes; elemBcTypes.update(this->problem_(), element, fvGeometry); - auto& curGlobalFaceVars = this->model_().curGlobalFaceVars(); + auto curGlobalFaceVars = this->model_().curGlobalFaceVars(); auto& prevGlobalFaceVars = this->model_().prevGlobalFaceVars(); // calculate the local residual if (isGhost) { -// this->residual_ = 0.0; -// residual[cellCenterIdx][globalI_] = 0.0; + DUNE_THROW(Dune::NotImplemented, "Support for ghost cells not implemented"); } else { @@ -160,200 +162,123 @@ public: prevElemVolVars, curElemVolVars, prevGlobalFaceVars, curGlobalFaceVars, elemBcTypes, elemFluxVarsCache); -// this->localResidual().eval(element, fvGeometry, prevElemVolVars, curElemVolVars, elemBcTypes, elemFluxVarsCache); -// this->residual_ = this->localResidual().residual(); // store residual in global container as well -// residual[cellCenterIdx][globalI_] = this->localResidual().residual(0); + residual[cellCenterIdx][globalI_] = this->localResidual().ccResidual(); + + for(auto&& scvf : scvfs(fvGeometry)) + { + residual[faceIdx][scvf.dofIndexSelf()] += this->localResidual().faceResidual(scvf.localFaceIdx()); + } } this->model_().updatePVWeights(fvGeometry); // calculate derivatives of all dofs in stencil with respect to the dofs in the element - evalPartialDerivatives_(element, fvGeometry, prevElemVolVars, curElemVolVars, elemFluxVarsCache, elemBcTypes, matrix, residual, isGhost); - - // TODO: calculate derivatives in the case of an extended source stencil - // const auto& extendedSourceStencil = model_().stencils(element).extendedSourceStencil(); - // for (auto&& globalJ : extendedSourceStencil) - // { - // for (int pvIdx = 0; pvIdx < numEq; pvIdx++) - // { - // evalPartialDerivativeSource_(partialDeriv, globalJ, pvIdx, neighborToFluxVars[globalJ]); - - // // update the local stiffness matrix with the partial derivatives - // updateLocalJacobian_(j, pvIdx, partialDeriv); - // } - // ++j; - // } + evalPartialDerivatives_(element, fvGeometry, prevElemVolVars, curElemVolVars, prevGlobalFaceVars, curGlobalFaceVars, elemFluxVarsCache, elemBcTypes, matrix, residual, isGhost); } - const AssemblyMap& assemblyMap() const - { return assemblyMap_; } - private: void evalPartialDerivatives_(const Element& element, const FVElementGeometry& fvGeometry, const ElementVolumeVariables& prevElemVolVars, ElementVolumeVariables& curElemVolVars, + const GlobalFaceVars& prevGlobalFaceVars, + GlobalFaceVars& curGlobalFaceVars, ElementFluxVariablesCache& elemFluxVarsCache, const ElementBoundaryTypes& elemBcTypes, JacobianMatrix& matrix, SolutionVector& residual, const bool isGhost) { - // get stencil informations -// const auto& neighborStencil = this->model_().stencils(element).neighborStencil(); -// const auto numNeighbors = neighborStencil.size(); - - // the localresidual class used for the flux calculations -// LocalResidual localRes; -// localRes.init(this->problem_()); -// -// // container to store the neighboring elements -// std::vector<Element> neighborElements; -// // neighborElements.reserve(numNeighbors); -// -// // get the elements and calculate the flux into the element in the undeflected state -// Dune::BlockVector<PrimaryVariables> origFlux(numNeighbors); -// origFlux = 0.0; -// -// unsigned int j = 0; -// for (auto globalJ : neighborStencil) -// { -// auto elementJ = fvGeometry.globalFvGeometry().element(globalJ); -// neighborElements.push_back(elementJ); -// -// for (auto fluxVarIdx : assemblyMap_[globalI_][j]) -// { -// auto&& scvf = fvGeometry.scvf(fluxVarIdx); -// origFlux[j] += localRes.evalFlux_(elementJ, fvGeometry, curElemVolVars, scvf, elemFluxVarsCache[scvf]); -// } -// -// ++j; -// } -// -// auto&& scv = fvGeometry.scv(globalI_); -// auto& curVolVars = getCurVolVars(curElemVolVars, scv); -// // save a copy of the original vol vars -// VolumeVariables origVolVars(curVolVars); -// -// // derivatives in the neighbors with repect to the current elements -// Dune::BlockVector<PrimaryVariables> neighborDeriv(numNeighbors); -// for (int pvIdx = 0; pvIdx < numEq; pvIdx++) -// { -// // derivatives of element dof with respect to itself -// PrimaryVariables partialDeriv(0.0); -// -// if (isGhost) -// partialDeriv[pvIdx] = 1.0; -// -// neighborDeriv = 0.0; -// PrimaryVariables priVars(this->model_().curSol()[globalI_]); -// -// Scalar eps = this->numericEpsilon(scv, curVolVars, pvIdx); -// Scalar delta = 0; -// -// if (numericDifferenceMethod_ >= 0) -// { -// // we are not using backward differences, i.e. we need to -// // calculate f(x + \epsilon) -// -// // deflect primary variables -// priVars[pvIdx] += eps; -// delta += eps; -// -// // update the volume variables and bind the flux var cache again -// curVolVars.update(priVars, this->problem_(), element, scv); -// elemFluxVarsCache.bind(element, fvGeometry, curElemVolVars); -// -// if (!isGhost) -// { -// // calculate the residual with the deflected primary variables -// this->localResidual().eval(element, fvGeometry, prevElemVolVars, curElemVolVars, elemBcTypes, elemFluxVarsCache); -// -// // store the residual and the storage term -// partialDeriv = this->localResidual().residual(0); -// } -// -// // calculate the fluxes into element with the deflected primary variables -// for (std::size_t k = 0; k < numNeighbors; ++k) -// { -// for (auto fluxVarIdx : assemblyMap_[globalI_][k]) -// { -// auto&& scvf = fvGeometry.scvf(fluxVarIdx); -// neighborDeriv[k] += localRes.evalFlux_(neighborElements[k], fvGeometry, curElemVolVars, scvf, elemFluxVarsCache[scvf]); -// } -// } -// } -// else -// { -// // we are using backward differences, i.e. we don't need -// // to calculate f(x + \epsilon) and we can recycle the -// // (already calculated) residual f(x) -// if (!isGhost) -// partialDeriv = this->residual(0); -// neighborDeriv = origFlux; -// } -// -// if (numericDifferenceMethod_ <= 0) -// { -// // we are not using forward differences, i.e. we -// // need to calculate f(x - \epsilon) -// -// // deflect the primary variables -// priVars[pvIdx] -= delta + eps; -// delta += eps; -// -// // update the volume variables and bind the flux var cache again -// curVolVars.update(priVars, this->problem_(), element, scv); -// elemFluxVarsCache.bind(element, fvGeometry, curElemVolVars); -// -// if (!isGhost) -// { -// // calculate the residual with the deflected primary variables -// this->localResidual().eval(element, fvGeometry, prevElemVolVars, curElemVolVars, elemBcTypes, elemFluxVarsCache); -// -// // subtract the residual from the derivative storage -// partialDeriv -= this->localResidual().residual(0); -// } -// -// // calculate the fluxes into element with the deflected primary variables -// for (std::size_t k = 0; k < numNeighbors; ++k) -// { -// for (auto fluxVarIdx : assemblyMap_[globalI_][k]) -// { -// auto&& scvf = fvGeometry.scvf(fluxVarIdx); -// neighborDeriv[k] -= localRes.evalFlux_(neighborElements[k], fvGeometry, curElemVolVars, scvf, elemFluxVarsCache[scvf]); -// } -// } -// } -// else -// { -// // we are using forward differences, i.e. we don't need to -// // calculate f(x - \epsilon) and we can recycle the -// // (already calculated) residual f(x) -// if (!isGhost) -// partialDeriv -= this->residual(0); -// neighborDeriv -= origFlux; -// } -// -// // divide difference in residuals by the magnitude of the -// // deflections between the two function evaluation -// if (!isGhost) -// partialDeriv /= delta; -// neighborDeriv /= delta; -// -// // restore the original state of the scv's volume variables -// curVolVars = origVolVars; -// -// // update the global jacobian matrix with the current partial derivatives -// this->updateGlobalJacobian_(matrix, globalI_, globalI_, pvIdx, partialDeriv); -// -// j = 0; -// for (auto globalJ : neighborStencil) -// this->updateGlobalJacobian_(matrix, globalJ, globalI_, pvIdx, neighborDeriv[j++]); -// } + // compute the derivatives of the cell center dofs with respect to cell center dofs + dCCdCC_(element, fvGeometry, prevElemVolVars, curElemVolVars, prevGlobalFaceVars, curGlobalFaceVars, elemFluxVarsCache, elemBcTypes, matrix, residual, isGhost); + + + printmatrix(std::cout, matrix[cellCenterIdx][cellCenterIdx], "A11 neu", ""); } + /*! + * \brief Computes the derivatives of the cell center dofs with respect to cell center dofs + */ + void dCCdCC_(const Element& element, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& prevElemVolVars, + ElementVolumeVariables& curElemVolVars, + const GlobalFaceVars& prevGlobalFaceVars, + const GlobalFaceVars& curGlobalFaceVars, + ElementFluxVariablesCache& elemFluxVarsCache, + const ElementBoundaryTypes& elemBcTypes, + JacobianMatrix& matrix, + SolutionVector& residual, + const bool isGhost) + { + // set the actual dof index + auto globalI = this->problem_().elementMapper().index(element); + + + // build derivatives with for cell center dofs w.r.t. cell center dofs + const auto& cellCenterToCellCenterStencil = this->model_().stencils(element).cellCenterToCellCenterStencil(); + + for(const auto& globalJ : cellCenterToCellCenterStencil) + { + // get the volVars of the element with respect to which we are going to build the derivative + auto&& scv = fvGeometry.scv(globalJ); + const auto elementJ = fvGeometry.globalFvGeometry().element(globalJ); + curElemVolVars.bind(elementJ, fvGeometry, this->model_().curSol()); + auto& curVolVars = getCurVolVars(curElemVolVars, scv); + VolumeVariables origVolVars(curVolVars); + + CellCenterPrimaryVariables priVars(this->model_().curSol()[cellCenterIdx][globalJ]); + + + for(int pvIdx = 0; pvIdx < priVars.size(); ++pvIdx) + { + const Scalar eps = 1e-4; // TODO: do properly + priVars += eps; + + curVolVars.update(priVars, this->problem_(), elementJ, scv); + + this->localResidual().eval(element, fvGeometry, + prevElemVolVars, curElemVolVars, + prevGlobalFaceVars, curGlobalFaceVars, + elemBcTypes, elemFluxVarsCache); + + auto partialDeriv = (this->localResidual().ccResidual() - residual[cellCenterIdx][globalI]); + partialDeriv /= eps; + + // update the global jacobian matrix with the current partial derivatives + this->updateGlobalJacobian_(matrix[cellCenterIdx][cellCenterIdx], globalI, globalJ, pvIdx, partialDeriv); + + // restore the original volVars + curVolVars = origVolVars; + } + } + } + + /*! + * \brief Updates the current global Jacobian matrix with the + * partial derivatives of all equations in regard to the + * primary variable 'pvIdx' at dof 'col'. Specialization for cc methods. + */ + template<class SubMatrix, class CCOrFacePrimaryVariables> + void updateGlobalJacobian_(SubMatrix& matrix, + const int globalI, + const int globalJ, + const int pvIdx, + const CCOrFacePrimaryVariables &partialDeriv) + { + for (int eqIdx = 0; eqIdx < numEq; eqIdx++) + { + // A[i][col][eqIdx][pvIdx] is the rate of change of + // the residual of equation 'eqIdx' at dof 'i' + // depending on the primary variable 'pvIdx' at dof + // 'col'. + matrix[globalI][globalJ][eqIdx][pvIdx] = partialDeriv[eqIdx]; + Valgrind::CheckDefined(matrix[globalI][globalJ][eqIdx][pvIdx]); + } + } + + //! If the global vol vars caching is enabled we have to modify the global volvar object template<class T = TypeTag> typename std::enable_if<GET_PROP_VALUE(T, EnableGlobalVolumeVariablesCache), VolumeVariables>::type& @@ -368,7 +293,6 @@ private: IndexType globalI_; int numericDifferenceMethod_; - AssemblyMap assemblyMap_; }; } diff --git a/dumux/implicit/staggered/localresidual.hh b/dumux/implicit/staggered/localresidual.hh index 56d1545366..cfb1cd2e05 100644 --- a/dumux/implicit/staggered/localresidual.hh +++ b/dumux/implicit/staggered/localresidual.hh @@ -168,15 +168,20 @@ public: // resize the vectors for all terms const auto numScv = fvGeometry.numScv(); const auto numScvf = fvGeometry.numScvf(); - ccResidual_.resize(numScv, 0.0); - ccStorageTerm_.resize(numScv, 0.0); + ccResidual_.resize(numScv); + ccStorageTerm_.resize(numScv); + + ccResidual_ = 0.0; + ccStorageTerm_ = 0.0; faceResiduals_.resize(numScvf); faceStorageTerms_.resize(numScvf); for(int i = 0; i < numScvf; ++i) { - faceResiduals_[i].resize(1, 0.0); - faceStorageTerms_[i].resize(1, 0.0); + faceResiduals_[i].resize(1); + faceStorageTerms_[i].resize(1); + faceResiduals_[i] = 0.0; + faceStorageTerms_[i] = 0.0; } asImp_().evalVolumeTerms_(element, fvGeometry, prevElemVolVars, curElemVolVars, prevFaceVars, curFaceVars, bcTypes); @@ -196,6 +201,15 @@ public: Problem& problem() { return *problemPtr_; } + const auto& ccResidual() const + { return ccResidual_[0]; } + + const auto& faceResiduals() const + { return faceResiduals_; } + + const auto& faceResidual(const int faceIdx) const + { return faceResiduals_[faceIdx][0]; } + protected: diff --git a/test/freeflow/staggered/staggeredtestproblem.hh b/test/freeflow/staggered/staggeredtestproblem.hh index f607210c28..d70c47043b 100644 --- a/test/freeflow/staggered/staggeredtestproblem.hh +++ b/test/freeflow/staggered/staggeredtestproblem.hh @@ -216,7 +216,7 @@ public: CellCenterPrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const { CellCenterPrimaryVariables values(0); - values[pressureIdx] = 1.0e+5*(2.0 - globalPos[dimWorld-1]); + values[0] = 1.0e+5; return values; } @@ -249,7 +249,8 @@ public: CellCenterPrimaryVariables initialCCValuesAtPos(const GlobalPosition &globalPos) const { CellCenterPrimaryVariables priVars(0); - priVars[pressureIdx] = 1.0e+5; + priVars[0] = 1.0e+5; //TODO: fix indices + std::cout << "init from problem; " << priVars << std::endl; return priVars; } -- GitLab