From affbd7236f8046372030044696c4447c8f656449 Mon Sep 17 00:00:00 2001 From: Yohann Bearzi <yohann.bearzi@kitware.com> Date: Fri, 23 Jun 2023 14:42:42 -0400 Subject: [PATCH] vtkDIYGhostUtilities: aborting when adjacency map is asymmetrical This scenario can happen if the user provides faulty global point ids. An asymmetrical adjacency map can cause a crash. So instead, we now double check symmetry while exchanging ghost data and abort if exchanges are not symmetrical Fixes #22191 --- Parallel/DIY/vtkDIYGhostUtilities.h | 3 +- Parallel/DIY/vtkDIYGhostUtilities.txx | 43 ++++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/Parallel/DIY/vtkDIYGhostUtilities.h b/Parallel/DIY/vtkDIYGhostUtilities.h index 990511660b8..fafe8b0b48b 100644 --- a/Parallel/DIY/vtkDIYGhostUtilities.h +++ b/Parallel/DIY/vtkDIYGhostUtilities.h @@ -973,7 +973,8 @@ protected: * This method exchanges ghosts between connected blocks. */ template <class DataSetT> - static void ExchangeGhosts(diy::Master& master, std::vector<DataSetT*>& inputs); + static bool ExchangeGhosts(diy::Master& master, diy::Assigner& assigner, + diy::RegularAllReducePartners& partners, std::vector<DataSetT*>& inputs); /** * This methods allocate a point and cell ghost array and fills it with 0. diff --git a/Parallel/DIY/vtkDIYGhostUtilities.txx b/Parallel/DIY/vtkDIYGhostUtilities.txx index 654c367a9ed..a39aa5e8bfa 100644 --- a/Parallel/DIY/vtkDIYGhostUtilities.txx +++ b/Parallel/DIY/vtkDIYGhostUtilities.txx @@ -393,7 +393,8 @@ void vtkDIYGhostUtilities::ExchangeBoundingBoxes( //---------------------------------------------------------------------------- template <class DataSetT> -void vtkDIYGhostUtilities::ExchangeGhosts(diy::Master& master, std::vector<DataSetT*>& inputs) +bool vtkDIYGhostUtilities::ExchangeGhosts(diy::Master& master, diy::Assigner& assigner, + diy::RegularAllReducePartners& partners, std::vector<DataSetT*>& inputs) { using BlockType = typename DataSetTypeToBlockTypeConverter<DataSetT>::BlockType; @@ -411,7 +412,8 @@ void vtkDIYGhostUtilities::ExchangeGhosts(diy::Master& master, std::vector<DataS master.exchange(); - master.foreach ([](BlockType* block, const diy::Master::ProxyWithLink& cp) { + bool error = false; + master.foreach ([&error](BlockType* block, const diy::Master::ProxyWithLink& cp) { std::vector<int> incoming; cp.incoming(incoming); for (const int& gid : incoming) @@ -419,10 +421,37 @@ void vtkDIYGhostUtilities::ExchangeGhosts(diy::Master& master, std::vector<DataS // we need this extra check because incoming is not empty when using only one block if (!cp.incoming(gid).empty()) { - vtkDIYGhostUtilities::DequeueGhosts(cp, gid, block->BlockStructures.at(gid)); + auto it = block->BlockStructures.find(gid); + if (it == block->BlockStructures.end()) + { + error = true; + } + else + { + vtkDIYGhostUtilities::DequeueGhosts(cp, gid, block->BlockStructures.at(gid)); + } } } }); + + diy::reduce(master, assigner, partners, + [&error](BlockType*, const diy::ReduceProxy& rp, const diy::RegularAllReducePartners&) { + for (int i = 0; i < rp.in_link().size(); ++i) + { + int gid = rp.in_link().target(i).gid; + + bool receivedError; + rp.dequeue(gid, &receivedError, 1); + error |= receivedError; + } + + for (int i = 0; i < rp.out_link().size(); ++i) + { + rp.enqueue(rp.out_link().target(i), &error, 1); + } + }); + + return !error; } //---------------------------------------------------------------------------- @@ -678,7 +707,13 @@ int vtkDIYGhostUtilities::GenerateGhostCells(std::vector<DataSetT*>& inputs, vtkLogEndScope("Relinking blocks using link map"); vtkLogStartScope(TRACE, "Exchanging ghost data between blocks"); - vtkDIYGhostUtilities::ExchangeGhosts(master, inputs); + if (!vtkDIYGhostUtilities::ExchangeGhosts(master, assigner, partners, inputs)) + { + vtkLog(ERROR, + "Could not connect adjacent datasets across partitions." + << " This is likely caused by an input with faulty point global ids. Aborting."); + return 0; + } vtkLogEndScope("Exchanging ghost data between blocks"); vtkLogStartScope(TRACE, "Allocating ghosts in outputs"); -- GitLab