Skip to content
Snippets Groups Projects
Commit 7514de5f authored by Kilian Weishaupt's avatar Kilian Weishaupt
Browse files

[staggered] Add Newton convergence writer

parent a3458521
No related branches found
No related tags found
1 merge request!1529Improve Newton convergence writer, add implementation for staggered
// -*- 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 3 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
* \ingroup Nonlinear
* \brief This class provides the infrastructure to write the
* convergence behaviour of the newton method for the
* staggered discretization scheme into a VTK file.
*/
#ifndef DUMUX_STAGGERED_NEWTON_CONVERGENCE_WRITER_HH
#define DUMUX_STAGGERED_NEWTON_CONVERGENCE_WRITER_HH
#include <string>
#include <dune/grid/io/file/vtk/vtksequencewriter.hh>
#include <dumux/io/vtksequencewriter.hh>
#include <dumux/io/pointcloudvtkwriter.hh>
#include "newtonconvergencewriter.hh"
namespace Dumux {
/*!
* \ingroup Nonlinear
* \brief Writes the intermediate solutions for every Newton iteration (for staggered grid scheme)
* \note To use this create a shared_ptr to an instance of this class in the main file
* and pass it to newton.solve(x, convergencewriter). You can use the reset method
* to write out multiple Newton solves with a unique id, if you don't call use all
* Newton iterations just come after each other in the pvd file.
*/
template <class FVGridGeometry, class SolutionVector>
class StaggeredNewtonConvergenceWriter : public ConvergenceWriterInterface<SolutionVector>
{
using GridView = typename FVGridGeometry::GridView;
using CellCenterSolutionVector = typename std::decay_t<decltype(std::declval<SolutionVector>()[FVGridGeometry::cellCenterIdx()])>;
using FaceSolutionVector = typename std::decay_t<decltype(std::declval<SolutionVector>()[FVGridGeometry::faceIdx()])>;
using Scalar = typename CellCenterSolutionVector::block_type::value_type;
static constexpr auto numEqCellCenter = CellCenterSolutionVector::block_type::dimension;
static constexpr auto numEqFace = FaceSolutionVector::block_type::dimension;
using Element = typename GridView::template Codim<0>::Entity;
using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
static_assert(FVGridGeometry::discMethod == DiscretizationMethod::staggered,
"This convergence writer does only work for the staggered method, use the NewtonConvergenceWriter instead");
public:
/*!
* \brief Constructor
* \param fvGridGeometry The finite volume geometry on the grid view
* \param name Base name of the vtk output
*/
StaggeredNewtonConvergenceWriter(const FVGridGeometry& fvGridGeometry,
const std::string& name = "newton_convergence")
: fvGridGeometry_(fvGridGeometry)
, ccWriter_(fvGridGeometry.gridView(), name, "", "")
, faceWriter_(std::make_shared<PointCloudVtkWriter<Scalar, GlobalPosition>>(coordinates_))
, faceSequenceWriter_(faceWriter_, name + "-face", "","",
fvGridGeometry.gridView().comm().rank(),
fvGridGeometry.gridView().comm().size())
{
resize();
for (int eqIdx = 0; eqIdx < numEqCellCenter; ++eqIdx)
{
ccWriter_.addCellData(xCellCenter_[eqIdx], "x_" + std::to_string(eqIdx));
ccWriter_.addCellData(deltaCellCenter_[eqIdx], "delta_" + std::to_string(eqIdx));
ccWriter_.addCellData(defCellCenter_[eqIdx], "defect_" + std::to_string(eqIdx));
}
}
//! Resizes the output fields. This has to be called whenever the grid changes
void resize()
{
const auto numCellCenterDofs = fvGridGeometry_.numCellCenterDofs();
const auto numFaceDofs = fvGridGeometry_.numFaceDofs();
// resize the cell center output fields
for (int eqIdx = 0; eqIdx < numEqCellCenter; ++eqIdx)
{
defCellCenter_[eqIdx].resize(numCellCenterDofs);
deltaCellCenter_[eqIdx].resize(numCellCenterDofs);
xCellCenter_[eqIdx].resize(numCellCenterDofs);
}
// resize the face output fields
for (int eqIdx = 0; eqIdx < numEqFace; ++eqIdx)
{
defFace_[eqIdx].resize(numFaceDofs);
deltaFace_[eqIdx].resize(numFaceDofs);
xFace_[eqIdx].resize(numFaceDofs);
}
coordinates_.resize(numFaceDofs);
for (auto&& facet : facets(fvGridGeometry_.gridView()))
{
const auto dofIdxGlobal = fvGridGeometry_.gridView().indexSet().index(facet);
coordinates_[dofIdxGlobal] = facet.geometry().center();
}
}
//! Reset the convergence writer for a possible next Newton step
//! You may set a different id in case you don't want the output to be overwritten by the next step
void reset(std::size_t newId = 0UL)
{ id_ = newId; iteration_ = 0UL; }
void write(const SolutionVector& uLastIter,
const SolutionVector& deltaU,
const SolutionVector& residual) override
{
assert(uLastIter.size() == deltaU.size() && uLastIter.size() == residual.size());
for (std::size_t dofIdxGlobal = 0; dofIdxGlobal < deltaU[FVGridGeometry::cellCenterIdx()].size(); ++dofIdxGlobal)
{
for (int eqIdx = 0; eqIdx < numEqCellCenter; ++eqIdx)
{
xCellCenter_[eqIdx][dofIdxGlobal] = uLastIter[FVGridGeometry::cellCenterIdx()][dofIdxGlobal][eqIdx];
deltaCellCenter_[eqIdx][dofIdxGlobal] = - deltaU[FVGridGeometry::cellCenterIdx()][dofIdxGlobal][eqIdx];
defCellCenter_[eqIdx][dofIdxGlobal] = residual[FVGridGeometry::cellCenterIdx()][dofIdxGlobal][eqIdx];
}
}
for (int eqIdx = 0; eqIdx < numEqFace; ++eqIdx)
{
faceWriter_->addPointData(xFace_[eqIdx], "x_" + std::to_string(eqIdx));
faceWriter_->addPointData(deltaFace_[eqIdx], "delta_" + std::to_string(eqIdx));
faceWriter_->addPointData(defFace_[eqIdx], "defect_" + std::to_string(eqIdx));
}
for (std::size_t dofIdxGlobal = 0; dofIdxGlobal < deltaU[FVGridGeometry::faceIdx()].size(); ++dofIdxGlobal)
{
for (int eqIdx = 0; eqIdx < numEqFace; ++eqIdx)
{
xFace_[eqIdx][dofIdxGlobal] = uLastIter[FVGridGeometry::faceIdx()][dofIdxGlobal][eqIdx];
deltaFace_[eqIdx][dofIdxGlobal] = - deltaU[FVGridGeometry::faceIdx()][dofIdxGlobal][eqIdx];
defFace_[eqIdx][dofIdxGlobal] = residual[FVGridGeometry::faceIdx()][dofIdxGlobal][eqIdx];
}
}
ccWriter_.write(static_cast<double>(id_) + static_cast<double>(iteration_)/1000);
faceSequenceWriter_.write(static_cast<double>(id_) + static_cast<double>(iteration_)/1000);
++iteration_;
}
private:
std::size_t id_ = 0UL;
std::size_t iteration_ = 0UL;
const FVGridGeometry& fvGridGeometry_;
Dune::VTKSequenceWriter<GridView> ccWriter_;
std::vector<GlobalPosition> coordinates_;
std::shared_ptr<PointCloudVtkWriter<Scalar, GlobalPosition>> faceWriter_;
VTKSequenceWriter<PointCloudVtkWriter<Scalar, GlobalPosition>> faceSequenceWriter_;
std::array<std::vector<Scalar>, numEqCellCenter> defCellCenter_;
std::array<std::vector<Scalar>, numEqCellCenter> deltaCellCenter_;
std::array<std::vector<Scalar>, numEqCellCenter> xCellCenter_;
std::array<std::vector<Scalar>, numEqFace> defFace_;
std::array<std::vector<Scalar>, numEqFace> deltaFace_;
std::array<std::vector<Scalar>, numEqFace> xFace_;
};
} // end namespace Dumux
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment