From c3edb0f7edf9f2e94ef933011675f1215df6743f Mon Sep 17 00:00:00 2001 From: Bernd Flemisch <bernd@iws.uni-stuttgart.de> Date: Mon, 6 Apr 2020 17:52:36 +0200 Subject: [PATCH] [multidomain][box][bugfix] Fix residual norm calculation for parallel+nonoverlapping+box --- dumux/multidomain/fvassembler.hh | 42 +++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/dumux/multidomain/fvassembler.hh b/dumux/multidomain/fvassembler.hh index 401ad03d74..f2141beed7 100644 --- a/dumux/multidomain/fvassembler.hh +++ b/dumux/multidomain/fvassembler.hh @@ -220,17 +220,51 @@ public: } //! compute the residual and return it's vector norm - //! TODO: this needs to be adapted in parallel Scalar residualNorm(const SolutionVector& curSol) { ResidualType residual; setResidualSize(residual); assembleResidual(residual, curSol); - // calculate the square norm of the residual - const Scalar result2 = residual.two_norm2(); + // for box communicate the residual with the neighboring processes + using namespace Dune::Hybrid; + forEach(integralRange(Dune::Hybrid::size(residual)), [&](const auto domainId) + { + const auto gridGeometry = std::get<domainId>(gridGeometryTuple_); + if (GridGeometry<domainId>::discMethod == DiscretizationMethod::box + && gridGeometry->gridView().comm().size() > 1) + { + using VertexMapper = typename GridGeometry<domainId>::VertexMapper; + using SolutionVector = std::remove_reference_t<decltype(residual[domainId])>; + using DataHandle = VectorCommDataHandleSum<VertexMapper, SolutionVector, + GridGeometry<domainId>::GridView::dimension>; + DataHandle sumResidualHandle(gridGeometry->vertexMapper(), residual[domainId]); + gridGeometry->gridView().communicate(sumResidualHandle, + Dune::InteriorBorder_InteriorBorder_Interface, + Dune::ForwardCommunication); + } + }); + + // calculate the squared norm of the residual + Scalar resultSquared = 0.0; + + // add up the result across processes + using namespace Dune::Hybrid; + forEach(integralRange(Dune::Hybrid::size(residual)), [&](const auto domainId) + { + Scalar localNormSquared = residual[domainId].two_norm2(); + + const auto gridGeometry = std::get<domainId>(gridGeometryTuple_); + if (gridGeometry->gridView().comm().size() > 1) + { + localNormSquared = gridGeometry->gridView().comm().sum(localNormSquared); + } + + resultSquared += localNormSquared; + }); + using std::sqrt; - return sqrt(result2); + return sqrt(resultSquared); } /*! -- GitLab