From 23974f94bab1ef1be8ee71e9eea7d280aec43df9 Mon Sep 17 00:00:00 2001 From: Timo Koch <timo.koch@iws.uni-stuttgart.de> Date: Tue, 14 Apr 2020 16:24:15 +0200 Subject: [PATCH] [fvproblem] Move applyInitialSolution to a separate header --- dumux/assembly/CMakeLists.txt | 1 + dumux/assembly/initialsolution.hh | 111 ++++++++++++++++++++++++++++++ dumux/common/fvproblem.hh | 59 +--------------- 3 files changed, 115 insertions(+), 56 deletions(-) create mode 100644 dumux/assembly/initialsolution.hh diff --git a/dumux/assembly/CMakeLists.txt b/dumux/assembly/CMakeLists.txt index 65a7539064..2543a6631f 100644 --- a/dumux/assembly/CMakeLists.txt +++ b/dumux/assembly/CMakeLists.txt @@ -8,6 +8,7 @@ entitycolor.hh fvassembler.hh fvlocalassemblerbase.hh fvlocalresidual.hh +initialsolution.hh jacobianpattern.hh numericepsilon.hh partialreassembler.hh diff --git a/dumux/assembly/initialsolution.hh b/dumux/assembly/initialsolution.hh new file mode 100644 index 0000000000..dc8bf7ebf3 --- /dev/null +++ b/dumux/assembly/initialsolution.hh @@ -0,0 +1,111 @@ +// -*- 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 Assembly + * \brief Function to create initial solution vectors + */ +#ifndef DUMUX_ASSEMBLY_INITIAL_SOLUTION_HH +#define DUMUX_ASSEMBLY_INITIAL_SOLUTION_HH + +#include <vector> +#include <type_traits> + +#include <dumux/discretization/method.hh> + +namespace Dumux { + +/*! + * \file + * \ingroup Assembly + * \brief Set a solution vector to the initial solution provided by the problem + */ +template<class SolutionVector, class Problem> +void assembleInitialSolution(SolutionVector& sol, const Problem& problem) +{ + const auto& gg = problem.gridGeometry(); + using GridGeometry = std::decay_t<decltype(gg)>; + + // box method + if constexpr (GridGeometry::discMethod == DiscretizationMethod::box) + { + constexpr int dim = GridGeometry::GridView::dimension; + const auto numDofs = gg.vertexMapper().size(); + const auto numVert = gg.gridView().size(dim); + sol.resize(numDofs); + + // if there are more dofs than vertices (enriched nodal dofs), we have to + // call initial for all dofs at the nodes, coming from all neighboring elements. + if (numDofs != numVert) + { + std::vector<bool> dofVisited(numDofs, false); + for (const auto& element : elements(gg.gridView())) + { + for (int i = 0; i < element.subEntities(dim); ++i) + { + const auto dofIdxGlobal = gg.vertexMapper().subIndex(element, i, dim); + // forward to implementation if value at dof is not set yet + if (!dofVisited[dofIdxGlobal]) + { + sol[dofIdxGlobal] = problem.initial(element.template subEntity<dim>(i)); + dofVisited[dofIdxGlobal] = true; + } + } + } + } + + // otherwise we directly loop over the vertices + else + { + for (const auto& vertex : vertices(gg.gridView())) + sol[gg.vertexMapper().index(vertex)] = problem.initial(vertex); + } + } + + // staggered methods + else if constexpr (GridGeometry::discMethod == DiscretizationMethod::staggered) + { + problem.applyInitialSolution(sol); + } + + // default: cell-centered methods + else + { + sol.resize(gg.numDofs()); + for (const auto& element : elements(gg.gridView())) + sol[gg.elementMapper().index(element)] = problem.initial(element); + } +} + +/*! + * \file + * \ingroup Assembly + * \brief Create a solution vector filled with the initial solution provided by the problem + */ +template<class SolutionVector, class Problem> +SolutionVector makeInitialSolution(const Problem& problem) +{ + SolutionVector sol; + assembleInitialSolution(sol, problem); + return sol; +} + +} // end namespace Dumux + +#endif diff --git a/dumux/common/fvproblem.hh b/dumux/common/fvproblem.hh index 47e6f4313e..49dea16866 100644 --- a/dumux/common/fvproblem.hh +++ b/dumux/common/fvproblem.hh @@ -34,6 +34,8 @@ #include <dumux/common/parameters.hh> #include <dumux/discretization/method.hh> +#include <dumux/assembly/initialsolution.hh> + namespace Dumux { /*! @@ -510,8 +512,7 @@ public: */ void applyInitialSolution(SolutionVector& sol) const { - // set the initial values by forwarding to a specialized method - applyInitialSolutionImpl_(sol, std::integral_constant<bool, isBox>()); + assembleInitialSolution(sol, asImp_()); } /*! @@ -596,60 +597,6 @@ protected: { return *static_cast<const Implementation *>(this); } private: - /*! - * \brief Applies the initial solution for the box method - */ - void applyInitialSolutionImpl_(SolutionVector& sol, /*isBox=*/std::true_type) const - { - const auto numDofs = gridGeometry_->vertexMapper().size(); - const auto numVert = gridGeometry_->gridView().size(dim); - sol.resize(numDofs); - - // if there are more dofs than vertices (enriched nodal dofs), we have to - // call initial for all dofs at the nodes, coming from all neighboring elements. - if (numDofs != numVert) - { - std::vector<bool> dofVisited(numDofs, false); - for (const auto& element : elements(gridGeometry_->gridView())) - { - for (int i = 0; i < element.subEntities(dim); ++i) - { - const auto dofIdxGlobal = gridGeometry_->vertexMapper().subIndex(element, i, dim); - - // forward to implementation if value at dof is not set yet - if (!dofVisited[dofIdxGlobal]) - { - sol[dofIdxGlobal] = asImp_().initial(element.template subEntity<dim>(i)); - dofVisited[dofIdxGlobal] = true; - } - } - } - } - - // otherwise we directly loop over the vertices - else - { - for (const auto& vertex : vertices(gridGeometry_->gridView())) - { - const auto dofIdxGlobal = gridGeometry_->vertexMapper().index(vertex); - sol[dofIdxGlobal] = asImp_().initial(vertex); - } - } - } - - /*! - * \brief Applies the initial solution for cell-centered methods - */ - void applyInitialSolutionImpl_(SolutionVector& sol, /*isBox=*/std::false_type) const - { - sol.resize(gridGeometry_->numDofs()); - for (const auto& element : elements(gridGeometry_->gridView())) - { - const auto dofIdxGlobal = gridGeometry_->elementMapper().index(element); - sol[dofIdxGlobal] = asImp_().initial(element); - } - } - //! The finite volume grid geometry std::shared_ptr<const GridGeometry> gridGeometry_; -- GitLab