From 0930621c681c47144cb9893f089e59c7e94ae96a Mon Sep 17 00:00:00 2001 From: Lisa Julia Nebel <lisa.nebel@dr-blatt.de> Date: Thu, 18 Jan 2024 11:55:43 +0100 Subject: [PATCH] Add test for building the AMG matrix hierarchy This tests makes sure the matrices in the hierarchy get created in a deterministic way when the flag 'useFixedOrder' of the coarseningCriterion is set to true. --- dune/istl/paamg/test/CMakeLists.txt | 5 ++ dune/istl/paamg/test/coarsentest.cc | 115 ++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 dune/istl/paamg/test/coarsentest.cc diff --git a/dune/istl/paamg/test/CMakeLists.txt b/dune/istl/paamg/test/CMakeLists.txt index 43bc9bc3c..1b71b0fc7 100644 --- a/dune/istl/paamg/test/CMakeLists.txt +++ b/dune/istl/paamg/test/CMakeLists.txt @@ -92,6 +92,11 @@ dune_add_test(SOURCES hierarchytest.cc TIMEOUT 600 CMAKE_GUARD MPI_FOUND) +dune_add_test(SOURCES coarsentest.cc + MPI_RANKS 1 2 4 + TIMEOUT 600 + CMAKE_GUARD MPI_FOUND) + dune_add_test(NAME pamgtest SOURCES parallelamgtest.cc MPI_RANKS 1 2 4 diff --git a/dune/istl/paamg/test/coarsentest.cc b/dune/istl/paamg/test/coarsentest.cc new file mode 100644 index 000000000..9f33fd81f --- /dev/null +++ b/dune/istl/paamg/test/coarsentest.cc @@ -0,0 +1,115 @@ +// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root +// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#include <config.h> + +#include <dune/common/parallel/mpihelper.hh> +#include <dune/istl/paamg/matrixhierarchy.hh> +#include <dune/istl/owneroverlapcopy.hh> +#include <dune/istl/schwarz.hh> +#include "anisotropic.hh" + +constexpr int blockSize = 10; + +using Communication = Dune::OwnerOverlapCopyCommunication<int,int>; +using ParallelIndexSet = Communication::ParallelIndexSet; +using MatrixBlock = Dune::FieldMatrix<double,blockSize,blockSize>; +using BCRSMat = Dune::BCRSMatrix<MatrixBlock>; +using VectorBlock = Dune::FieldVector<double,blockSize>; +using Vector = Dune::BlockVector<VectorBlock>; + +/** + * Check if the matrices A and B are the same. + * + * @param BCRSMat A + * @param BCRSMat B + * @return bool - True if A and B are the same, false if they are not. + */ +bool areSame(BCRSMat A, BCRSMat B) +{ + for (auto rowIt = A.begin(); rowIt != A.end(); ++rowIt) + for (auto colIt = rowIt->begin(); colIt != rowIt->end(); ++colIt) + for (size_t k = 0; k < blockSize; k++) + for (size_t l = 0; l < blockSize; l++) { + auto entryA = (*colIt)[k][l]; + try { + auto entryB = B[rowIt.index()][colIt.index()][k][l]; + } catch (Dune::ISTLError e) { + return false; // If the entry B[rowIt.index()][colIt.index()][k][l] does not exist, then the matrices are not the same. + } + if (std::abs((*colIt)[k][l]) > 1e-7 and std::abs(B[rowIt.index()][colIt.index()][k][l]) > 1e-7 + and std::abs((*colIt)[k][l] - B[rowIt.index()][colIt.index()][k][l])/(*colIt)[k][l] > 1e-7) { + return false; // Check if the entries are approximately the same. + } + } + return true; +} + +/** + * Builds two AMG matrix hierarchies and checks if they are equal. + * When setting up such matrix hierarchies on multiple processes, they get created in a non-deterministic way and the two matrix hierarchies might differ. + * + * @param int N Total number of unknowns + * @param int rank Rank of current process + * @param int noProcesses Number of all processes + * @return int - 0 if the hierarchies are the same, 1 if they are not. + */ +int testHierarchy(int N, int rank, int noProcesses) +{ + int n; + Communication pinfo(Dune::MPIHelper::getCommunicator()); + ParallelIndexSet& indices = pinfo.indexSet(); + + using RemoteIndices = Dune::RemoteIndices<ParallelIndexSet>; + RemoteIndices& remoteIndices = pinfo.remoteIndices(); + + BCRSMat mat = setupAnisotropic2d<MatrixBlock>(N, indices, Dune::MPIHelper::getCommunication(), &n); + + remoteIndices.rebuild<false>(); + + using OverlapFlags = Dune::NegateSet<Communication::OwnerSet>; + using Operator = Dune::OverlappingSchwarzOperator<BCRSMat,Vector,Vector,Communication>; + using Hierarchy = Dune::Amg::MatrixHierarchy<Operator,Communication>; + + Operator op(mat, pinfo); + Hierarchy hierarchyA( + Dune::stackobject_to_shared_ptr(op), + Dune::stackobject_to_shared_ptr(pinfo)); + + Hierarchy hierarchyB( + Dune::stackobject_to_shared_ptr(op), + Dune::stackobject_to_shared_ptr(pinfo)); + + using Criterion = Dune::Amg::CoarsenCriterion<Dune::Amg::SymmetricCriterion<BCRSMat,Dune::Amg::FirstDiagonal> >; + + Criterion criterionA(1000,10,1.2,1.6,Dune::Amg::AccumulationMode::successiveAccu,true); + Criterion criterionB(1000,10,1.2,1.6,Dune::Amg::AccumulationMode::successiveAccu,true); + + hierarchyA.template build<OverlapFlags>(criterionA); + hierarchyB.template build<OverlapFlags>(criterionB); + + MPI_Barrier(MPI_COMM_WORLD); + //Check if the second finest matrices are the same + auto finestMatrixA = hierarchyA.matrices().finest(); + finestMatrixA++; + auto finestMatrixB = hierarchyB.matrices().finest(); + finestMatrixB++; + if (!areSame(finestMatrixA->getmat(), finestMatrixB->getmat())) { + std::cerr << "During run with " << noProcesses << " processes: The matrix hierarchy on rank " << rank << " was created in a non-deterministic way." << std::endl; + return 1; + } + return 0; +} + + +int main(int argc, char** argv) +{ + Dune::MPIHelper& mpiHelper = Dune::MPIHelper::instance(argc, argv); + int N=10; + + if(argc>1) + N = atoi(argv[1]); + + return testHierarchy(N, mpiHelper.rank(), mpiHelper.size()); +} -- GitLab