Commit 01ea3cc7 authored by mattijs's avatar mattijs Committed by Andrew Heather
Browse files

ENH: metis: use PrecisionAdaptor to support 64 bit indices

parent da07aa9a
......@@ -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)
......
......@@ -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>();
};
......
......@@ -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());
}
}
// ************************************************************************* //
......@@ -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()
);
}
......
......@@ -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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment