ENH: metis: use PrecisionAdaptor to support 64 bit indices

This commit is contained in:
mattijs
2019-06-13 20:52:48 +01:00
committed by Andrew Heather
parent da07aa9ac0
commit 01ea3cc790
5 changed files with 92 additions and 81 deletions

View File

@ -36,6 +36,7 @@ Description
#ifndef PrecisionAdaptor_H #ifndef PrecisionAdaptor_H
#define PrecisionAdaptor_H #define PrecisionAdaptor_H
#include "tmpNrc.H"
#include "Field.H" #include "Field.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -44,34 +45,34 @@ namespace Foam
{ {
//- A const Field wrapper with possible data conversion //- 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 class ConstPrecisionAdaptor
: :
public tmp<Field<Type>> public tmpNrc<Container<Type>>
{ {
// Private Member Functions // Private Member Functions
//- Copy in field //- Copy in field
void copyInput(const Field<InputType>& input) void copyInput(const Container<InputType>& input)
{ {
this->clear(); this->clear();
Field<Type>* p = new Field<Type>(input.size()); Container<Type>* p = new Container<Type>(input.size());
this->reset(p); this->reset(p);
std::copy(input.cbegin(), input.cend(), p->begin()); std::copy(input.cbegin(), input.cend(), p->begin());
} }
//- Construct from tmp Field, copy/move as required //- 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) 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()) if (tinput.isTmp())
{ {
this->clear(); // Reset to tmp
this->swap(tinput); this->reset(tinput.ptr());
} }
else else
{ {
@ -89,15 +90,15 @@ class ConstPrecisionAdaptor
public: public:
//- The adapted field type //- The adapted field type
typedef Field<Type> FieldType; typedef Container<Type> FieldType;
// Constructors // Constructors
//- Construct from Field<InputType>, copying on input as required //- Construct from Container<InputType>, copying on input as required
ConstPrecisionAdaptor(const Field<InputType>& input) ConstPrecisionAdaptor(const Container<InputType>& input)
: :
tmp<Field<Type>>() tmpNrc<Container<Type>>()
{ {
if (std::is_same<Type, InputType>::value) if (std::is_same<Type, InputType>::value)
{ {
@ -110,31 +111,31 @@ public:
} }
//- Construct from tmp Field, copy/move as required //- Construct from tmp Container, copy/move as required
ConstPrecisionAdaptor(tmp<Field<InputType>>&& input) ConstPrecisionAdaptor(tmp<Container<InputType>>&& input)
: :
tmp<Field<Type>>() tmpNrc<Container<Type>>()
{ {
this->moveInput(input); this->moveInput(input);
} }
//- Construct from tmp Field, copy/move as required //- Construct from tmp Container, copy/move as required
ConstPrecisionAdaptor(const tmp<Field<InputType>>& input) 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 // Member Functions
//- Return the field //- Return the field
static const Field<Type>& get static const Container<Type>& get
( (
const Field<InputType>& input, const Container<InputType>& input,
Field<Type>& dst Container<Type>& dst
) )
{ {
if (std::is_same<Type, InputType>::value) if (std::is_same<Type, InputType>::value)
@ -152,25 +153,23 @@ public:
//- A Field wrapper with possible data conversion //- A Field wrapper with possible data conversion
template<class Type, class InputType> template<class Type, class InputType, template<class> class Container = Field>
class PrecisionAdaptor class PrecisionAdaptor
: :
public tmp<Field<Type>> public tmpNrc<Container<Type>>
{ {
// Private Data // Private Data
//- Reference to underlying field //- Reference to underlying field
Field<InputType>& ref_; Container<InputType>& ref_;
// Private Member Functions // Private Member Functions
//- Copy in field //- Copy in field
void copyInput(const Field<InputType>& input) void copyInput(const Container<InputType>& input)
{ {
this->clear(); Container<Type>* p = new Container<Type>(input.size());
Field<Type>* p = new Field<Type>(input.size());
this->reset(p); this->reset(p);
std::copy(input.cbegin(), input.cend(), p->begin()); std::copy(input.cbegin(), input.cend(), p->begin());
} }
@ -179,15 +178,15 @@ class PrecisionAdaptor
public: public:
//- The adapted field type //- The adapted field type
typedef Field<Type> FieldType; typedef Container<Type> FieldType;
// Constructors // Constructors
//- Construct from Field<InputType>, copying on input as required //- Construct from Container<InputType>, copying on input as required
PrecisionAdaptor(Field<InputType>& input) PrecisionAdaptor(Container<InputType>& input)
: :
tmp<Field<Type>>(), tmpNrc<Container<Type>>(),
ref_(input) ref_(input)
{ {
if (std::is_same<Type, InputType>::value) if (std::is_same<Type, InputType>::value)

View File

@ -42,6 +42,7 @@ See also
#include "refCount.H" #include "refCount.H"
#include "word.H" #include "word.H"
#include "tmp.H"
#include <utility> #include <utility>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -229,6 +230,9 @@ public:
//- Transfer ownership of the managed pointer. //- Transfer ownership of the managed pointer.
// Fatal for a null managed pointer or if the object is const. // Fatal for a null managed pointer or if the object is const.
inline void operator=(const tmpNrc<T>& t); inline void operator=(const tmpNrc<T>& t);
//- Conversion to tmp
inline operator tmp<T>();
}; };

View File

@ -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());
}
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -28,6 +28,7 @@ License
#include "metisDecomp.H" #include "metisDecomp.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"
#include "Time.H" #include "Time.H"
#include "PrecisionAdaptor.H"
// Probably not needed... // Probably not needed...
#define MPICH_SKIP_MPICXX #define MPICH_SKIP_MPICXX
@ -39,13 +40,13 @@ License
// //
// Metis has an 'idx_t' type, but the IDXTYPEWIDTH define is perhaps // Metis has an 'idx_t' type, but the IDXTYPEWIDTH define is perhaps
// more future-proof? // more future-proof?
#ifdef IDXTYPEWIDTH //#ifdef IDXTYPEWIDTH
static_assert //static_assert
( //(
sizeof(Foam::label) == (IDXTYPEWIDTH/8), // sizeof(Foam::label) == (IDXTYPEWIDTH/8),
"sizeof(Foam::label) == (IDXTYPEWIDTH/8), check your metis headers" // "sizeof(Foam::label) == (IDXTYPEWIDTH/8), check your metis headers"
); //);
#endif //#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -86,10 +87,10 @@ Foam::label Foam::metisDecomp::decomposeSerial
const dictionary* coeffsDictPtr = decompDict_.findDict("metisCoeffs"); const dictionary* coeffsDictPtr = decompDict_.findDict("metisCoeffs");
label numCells = xadj.size()-1; idx_t numCells = xadj.size()-1;
// Decomposition options // Decomposition options
List<label> options(METIS_NOPTIONS); List<idx_t> options(METIS_NOPTIONS);
METIS_SetDefaultOptions(options.begin()); METIS_SetDefaultOptions(options.begin());
// Processor weights initialised with no size, only used if specified in // Processor weights initialised with no size, only used if specified in
@ -97,10 +98,10 @@ Foam::label Foam::metisDecomp::decomposeSerial
Field<real_t> processorWeights; Field<real_t> processorWeights;
// Cell weights (so on the vertices of the dual) // 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) // 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 // Check for externally provided cellweights and if so initialise weights
// Note: min, not gMin since routine runs on master only. // Note: min, not gMin since routine runs on master only.
@ -184,51 +185,56 @@ Foam::label Foam::metisDecomp::decomposeSerial
} }
} }
label ncon = 1; idx_t ncon = 1;
label nProcs = nDomains_; 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 // 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 // Output: number of cut edges
label edgeCut = 0; idx_t edgeCut = 0;
if (method == "recursive") if (method == "recursive")
{ {
METIS_PartGraphRecursive METIS_PartGraphRecursive
( (
&numCells, // num vertices in graph &numCells, // num vertices in graph
&ncon, // num balancing constraints &ncon, // num balancing constraints
const_cast<labelUList&>(xadj).begin(), // indexing into adjncy xadj_metis.ref().begin(), // indexing into adjncy
const_cast<labelUList&>(adjncy).begin(), // neighbour info adjncy_metis.ref().begin(), // neighbour info
cellWeights.begin(),// vertex wts cellWeights.begin(), // vertex wts
nullptr, // vsize: total communication vol nullptr, // vsize: total communication vol
faceWeights.begin(),// edge wts faceWeights.begin(), // edge wts
&nProcs, // nParts &nProcs, // nParts
processorWeights.begin(), // tpwgts processorWeights.begin(), // tpwgts
nullptr, // ubvec: processor imbalance (default) nullptr, // ubvec: processor imbalance (default)
options.begin(), options.begin(),
&edgeCut, &edgeCut,
decomp.begin() decomp_metis.ref().begin()
); );
} }
else else
{ {
METIS_PartGraphKway METIS_PartGraphKway
( (
&numCells, // num vertices in graph &numCells, // num vertices in graph
&ncon, // num balancing constraints &ncon, // num balancing constraints
const_cast<labelUList&>(xadj).begin(), // indexing into adjncy xadj_metis.ref().begin(), // indexing into adjncy
const_cast<labelUList&>(adjncy).begin(), // neighbour info adjncy_metis.ref().begin(), // neighbour info
cellWeights.begin(),// vertex wts cellWeights.begin(), // vertex wts
nullptr, // vsize: total communication vol nullptr, // vsize: total communication vol
faceWeights.begin(),// edge wts faceWeights.begin(), // edge wts
&nProcs, // nParts &nProcs, // nParts
processorWeights.begin(), // tpwgts processorWeights.begin(), // tpwgts
nullptr, // ubvec: processor imbalance (default) nullptr, // ubvec: processor imbalance (default)
options.begin(), options.begin(),
&edgeCut, &edgeCut,
decomp.begin() decomp_metis.ref().begin()
); );
} }

View File

@ -107,7 +107,7 @@ have_metis()
# ---------------------------------- # ----------------------------------
local good label local label
# Ensure consistent sizes between OpenFOAM and metis header # Ensure consistent sizes between OpenFOAM and metis header
# Extract IDXTYPEWIDTH from metis.h: regex as per ThirdParty Allwmake # Extract IDXTYPEWIDTH from metis.h: regex as per ThirdParty Allwmake
@ -116,18 +116,6 @@ have_metis()
"$header") "$header")
: "${label:=unknown}" : "${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 # OK
echo "metis (label=$label) - $prefix" echo "metis (label=$label) - $prefix"
export HAVE_METIS=true export HAVE_METIS=true