From 4f8edb17bad905c9491dce268e54661fe0cbf026 Mon Sep 17 00:00:00 2001 From: mattijs <mattijs> Date: Thu, 13 Jun 2019 20:52:48 +0100 Subject: [PATCH] ENH: metis: use PrecisionAdaptor to support 64 bit indices --- .../Field/PrecisionAdaptor/PrecisionAdaptor.H | 65 ++++++++-------- src/OpenFOAM/memory/tmp/tmpNrc.H | 4 + src/OpenFOAM/memory/tmp/tmpNrcI.H | 14 ++++ .../decompose/metisDecomp/metisDecomp.C | 76 ++++++++++--------- wmake/scripts/have_metis | 14 +--- 5 files changed, 92 insertions(+), 81 deletions(-) diff --git a/src/OpenFOAM/fields/Fields/Field/PrecisionAdaptor/PrecisionAdaptor.H b/src/OpenFOAM/fields/Fields/Field/PrecisionAdaptor/PrecisionAdaptor.H index 0c33ed73886..39c9deae2bd 100644 --- a/src/OpenFOAM/fields/Fields/Field/PrecisionAdaptor/PrecisionAdaptor.H +++ b/src/OpenFOAM/fields/Fields/Field/PrecisionAdaptor/PrecisionAdaptor.H @@ -36,6 +36,7 @@ Description #ifndef PrecisionAdaptor_H #define PrecisionAdaptor_H +#include "tmpNrc.H" #include "Field.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -44,34 +45,34 @@ namespace Foam { //- A const Field wrapper with possible data conversion -template<class Type, class InputType> +template<class Type, class InputType, template<class> class Container = Field> class ConstPrecisionAdaptor : - public tmp<Field<Type>> + public tmpNrc<Container<Type>> { // Private Member Functions //- Copy in field - void copyInput(const Field<InputType>& input) + void copyInput(const Container<InputType>& input) { this->clear(); - Field<Type>* p = new Field<Type>(input.size()); + Container<Type>* p = new Container<Type>(input.size()); this->reset(p); std::copy(input.cbegin(), input.cend(), p->begin()); } //- Construct from tmp Field, copy/move as required - void moveInput(tmp<Field<InputType>>& input) + void moveInput(tmp<Container<InputType>>& input) { if (std::is_same<Type, InputType>::value) { - auto& tinput = reinterpret_cast<tmp<FieldType>&>(input); + auto& tinput = reinterpret_cast<tmp<Container<Type>>&>(input); if (tinput.isTmp()) { - this->clear(); - this->swap(tinput); + // Reset to tmp + this->reset(tinput.ptr()); } else { @@ -89,15 +90,15 @@ class ConstPrecisionAdaptor public: //- The adapted field type - typedef Field<Type> FieldType; + typedef Container<Type> FieldType; // Constructors - //- Construct from Field<InputType>, copying on input as required - ConstPrecisionAdaptor(const Field<InputType>& input) + //- Construct from Container<InputType>, copying on input as required + ConstPrecisionAdaptor(const Container<InputType>& input) : - tmp<Field<Type>>() + tmpNrc<Container<Type>>() { if (std::is_same<Type, InputType>::value) { @@ -110,31 +111,31 @@ public: } - //- Construct from tmp Field, copy/move as required - ConstPrecisionAdaptor(tmp<Field<InputType>>&& input) + //- Construct from tmp Container, copy/move as required + ConstPrecisionAdaptor(tmp<Container<InputType>>&& input) : - tmp<Field<Type>>() + tmpNrc<Container<Type>>() { this->moveInput(input); } - //- Construct from tmp Field, copy/move as required - ConstPrecisionAdaptor(const tmp<Field<InputType>>& input) + //- Construct from tmp Container, copy/move as required + ConstPrecisionAdaptor(const tmp<Container<InputType>>& input) : - tmp<Field<Type>>() + tmpNrc<Container<Type>>() { - this->moveInput(const_cast<tmp<Field<InputType>>&>(input)); + this->moveInput(const_cast<tmp<Container<InputType>>&>(input)); } // Member Functions //- Return the field - static const Field<Type>& get + static const Container<Type>& get ( - const Field<InputType>& input, - Field<Type>& dst + const Container<InputType>& input, + Container<Type>& dst ) { if (std::is_same<Type, InputType>::value) @@ -152,25 +153,23 @@ public: //- A Field wrapper with possible data conversion -template<class Type, class InputType> +template<class Type, class InputType, template<class> class Container = Field> class PrecisionAdaptor : - public tmp<Field<Type>> + public tmpNrc<Container<Type>> { // Private Data //- Reference to underlying field - Field<InputType>& ref_; + Container<InputType>& ref_; // Private Member Functions //- Copy in field - void copyInput(const Field<InputType>& input) + void copyInput(const Container<InputType>& input) { - this->clear(); - - Field<Type>* p = new Field<Type>(input.size()); + Container<Type>* p = new Container<Type>(input.size()); this->reset(p); std::copy(input.cbegin(), input.cend(), p->begin()); } @@ -179,15 +178,15 @@ class PrecisionAdaptor public: //- The adapted field type - typedef Field<Type> FieldType; + typedef Container<Type> FieldType; // Constructors - //- Construct from Field<InputType>, copying on input as required - PrecisionAdaptor(Field<InputType>& input) + //- Construct from Container<InputType>, copying on input as required + PrecisionAdaptor(Container<InputType>& input) : - tmp<Field<Type>>(), + tmpNrc<Container<Type>>(), ref_(input) { if (std::is_same<Type, InputType>::value) diff --git a/src/OpenFOAM/memory/tmp/tmpNrc.H b/src/OpenFOAM/memory/tmp/tmpNrc.H index d5a3b7b6f79..7617af37124 100644 --- a/src/OpenFOAM/memory/tmp/tmpNrc.H +++ b/src/OpenFOAM/memory/tmp/tmpNrc.H @@ -42,6 +42,7 @@ See also #include "refCount.H" #include "word.H" +#include "tmp.H" #include <utility> // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -229,6 +230,9 @@ public: //- Transfer ownership of the managed pointer. // Fatal for a null managed pointer or if the object is const. inline void operator=(const tmpNrc<T>& t); + + //- Conversion to tmp + inline operator tmp<T>(); }; diff --git a/src/OpenFOAM/memory/tmp/tmpNrcI.H b/src/OpenFOAM/memory/tmp/tmpNrcI.H index 4f8148b0396..1e3a7136d79 100644 --- a/src/OpenFOAM/memory/tmp/tmpNrcI.H +++ b/src/OpenFOAM/memory/tmp/tmpNrcI.H @@ -427,4 +427,18 @@ inline void Foam::tmpNrc<T>::operator=(const tmpNrc<T>& t) } +template<class T> +inline Foam::tmpNrc<T>::operator tmp<T>() +{ + if (isTmp()) + { + return tmp<T>(ptr()); + } + else + { + return tmp<T>(cref()); + } +} + + // ************************************************************************* // diff --git a/src/parallel/decompose/metisDecomp/metisDecomp.C b/src/parallel/decompose/metisDecomp/metisDecomp.C index 0509a28a3b4..ce4ea4c7a76 100644 --- a/src/parallel/decompose/metisDecomp/metisDecomp.C +++ b/src/parallel/decompose/metisDecomp/metisDecomp.C @@ -28,6 +28,7 @@ License #include "metisDecomp.H" #include "addToRunTimeSelectionTable.H" #include "Time.H" +#include "PrecisionAdaptor.H" // Probably not needed... #define MPICH_SKIP_MPICXX @@ -39,13 +40,13 @@ License // // Metis has an 'idx_t' type, but the IDXTYPEWIDTH define is perhaps // more future-proof? -#ifdef IDXTYPEWIDTH -static_assert -( - sizeof(Foam::label) == (IDXTYPEWIDTH/8), - "sizeof(Foam::label) == (IDXTYPEWIDTH/8), check your metis headers" -); -#endif +//#ifdef IDXTYPEWIDTH +//static_assert +//( +// sizeof(Foam::label) == (IDXTYPEWIDTH/8), +// "sizeof(Foam::label) == (IDXTYPEWIDTH/8), check your metis headers" +//); +//#endif // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -86,10 +87,10 @@ Foam::label Foam::metisDecomp::decomposeSerial const dictionary* coeffsDictPtr = decompDict_.findDict("metisCoeffs"); - label numCells = xadj.size()-1; + idx_t numCells = xadj.size()-1; // Decomposition options - List<label> options(METIS_NOPTIONS); + List<idx_t> options(METIS_NOPTIONS); METIS_SetDefaultOptions(options.begin()); // Processor weights initialised with no size, only used if specified in @@ -97,10 +98,10 @@ Foam::label Foam::metisDecomp::decomposeSerial Field<real_t> processorWeights; // Cell weights (so on the vertices of the dual) - List<label> cellWeights; + List<idx_t> cellWeights; // Face weights (so on the edges of the dual) - List<label> faceWeights; + List<idx_t> faceWeights; // Check for externally provided cellweights and if so initialise weights // Note: min, not gMin since routine runs on master only. @@ -184,51 +185,56 @@ Foam::label Foam::metisDecomp::decomposeSerial } } - label ncon = 1; - label nProcs = nDomains_; + idx_t ncon = 1; + idx_t nProcs = nDomains_; + + // Addressing + ConstPrecisionAdaptor<idx_t, label, List> xadj_metis(xadj); + ConstPrecisionAdaptor<idx_t, label, List> adjncy_metis(adjncy); // Output: cell -> processor addressing - decomp.setSize(numCells); + PrecisionAdaptor<idx_t, label, List> decomp_metis(decomp); + decomp_metis.ref().setSize(numCells); // Output: number of cut edges - label edgeCut = 0; + idx_t edgeCut = 0; if (method == "recursive") { METIS_PartGraphRecursive ( - &numCells, // num vertices in graph - &ncon, // num balancing constraints - const_cast<labelUList&>(xadj).begin(), // indexing into adjncy - const_cast<labelUList&>(adjncy).begin(), // neighbour info - cellWeights.begin(),// vertex wts - nullptr, // vsize: total communication vol - faceWeights.begin(),// edge wts - &nProcs, // nParts + &numCells, // num vertices in graph + &ncon, // num balancing constraints + xadj_metis.ref().begin(), // indexing into adjncy + adjncy_metis.ref().begin(), // neighbour info + cellWeights.begin(), // vertex wts + nullptr, // vsize: total communication vol + faceWeights.begin(), // edge wts + &nProcs, // nParts processorWeights.begin(), // tpwgts - nullptr, // ubvec: processor imbalance (default) + nullptr, // ubvec: processor imbalance (default) options.begin(), &edgeCut, - decomp.begin() + decomp_metis.ref().begin() ); } else { METIS_PartGraphKway ( - &numCells, // num vertices in graph - &ncon, // num balancing constraints - const_cast<labelUList&>(xadj).begin(), // indexing into adjncy - const_cast<labelUList&>(adjncy).begin(), // neighbour info - cellWeights.begin(),// vertex wts - nullptr, // vsize: total communication vol - faceWeights.begin(),// edge wts - &nProcs, // nParts + &numCells, // num vertices in graph + &ncon, // num balancing constraints + xadj_metis.ref().begin(), // indexing into adjncy + adjncy_metis.ref().begin(), // neighbour info + cellWeights.begin(), // vertex wts + nullptr, // vsize: total communication vol + faceWeights.begin(), // edge wts + &nProcs, // nParts processorWeights.begin(), // tpwgts - nullptr, // ubvec: processor imbalance (default) + nullptr, // ubvec: processor imbalance (default) options.begin(), &edgeCut, - decomp.begin() + decomp_metis.ref().begin() ); } diff --git a/wmake/scripts/have_metis b/wmake/scripts/have_metis index a72c1ecdf50..52d1235c320 100644 --- a/wmake/scripts/have_metis +++ b/wmake/scripts/have_metis @@ -107,7 +107,7 @@ have_metis() # ---------------------------------- - local good label + local label # Ensure consistent sizes between OpenFOAM and metis header # Extract IDXTYPEWIDTH from metis.h: regex as per ThirdParty Allwmake @@ -116,18 +116,6 @@ have_metis() "$header") : "${label:=unknown}" - if [ "$WM_LABEL_SIZE" = "$label" ] - then - good=true - else - if [ -n "$warn" ] - then - echo "$warn (label=$WM_LABEL_SIZE, ${header##*/} has '$label')" - fi - no_metis - return 1 - fi - # OK echo "metis (label=$label) - $prefix" export HAVE_METIS=true -- GitLab