Parallel GGI performance improvements

This commit is contained in:
Hrvoje Jasak 2011-06-26 22:46:38 +01:00
parent d199b6b6d0
commit 137014f511
102 changed files with 2355 additions and 301 deletions

View file

@ -1,5 +1,9 @@
EXE_INC = \ EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude \ -I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/surfMesh/lnInclude -I$(LIB_SRC)/surfMesh/lnInclude
EXE_LIBS = -ltriSurface -lsurfMesh EXE_LIBS = \
-lmeshTools \
-ltriSurface \
-lsurfMesh

View file

@ -471,7 +471,7 @@ DebugSwitches
genericPatch 0; genericPatch 0;
geomCellLooper 0; geomCellLooper 0;
geometricSurfacePatch 0; geometricSurfacePatch 0;
ggi 0; GGIInterpolation 0;
global 0; global 0;
globalMeshData 0; globalMeshData 0;
globalPoints 0; globalPoints 0;

View file

@ -108,8 +108,8 @@ if ( ! $?WM_OSTYPE ) setenv WM_OSTYPE POSIX
# Compiler: set to Gcc, Gcc43 or Icc (for Intel's icc) # Compiler: set to Gcc, Gcc43 or Icc (for Intel's icc)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#if ( ! $?WM_COMPILER ) setenv WM_COMPILER Gcc #if ( ! $?WM_COMPILER ) setenv WM_COMPILER Gcc
setenv WM_COMPILER Gcc #setenv WM_COMPILER Gcc
#setenv WM_COMPILER Icc setenv WM_COMPILER Icc
setenv WM_COMPILER_ARCH setenv WM_COMPILER_ARCH
setenv WM_COMPILER_LIB_ARCH setenv WM_COMPILER_LIB_ARCH
@ -127,8 +127,8 @@ if ( ! $?WM_PRECISION_OPTION ) setenv WM_PRECISION_OPTION DP
# WM_COMPILE_OPTION = Opt | Debug | Prof # WM_COMPILE_OPTION = Opt | Debug | Prof
#if ( ! $?WM_COMPILE_OPTION ) setenv WM_COMPILE_OPTION Opt #if ( ! $?WM_COMPILE_OPTION ) setenv WM_COMPILE_OPTION Opt
setenv WM_COMPILE_OPTION Opt #setenv WM_COMPILE_OPTION Opt
#setenv WM_COMPILE_OPTION Debug setenv WM_COMPILE_OPTION Debug
# WM_MPLIB = | OPENMPI | MPICH | MPICH-GM | HPMPI | GAMMA | MPI | QSMPI # WM_MPLIB = | OPENMPI | MPICH | MPICH-GM | HPMPI | GAMMA | MPI | QSMPI
if ( ! $?WM_MPLIB ) setenv WM_MPLIB OPENMPI if ( ! $?WM_MPLIB ) setenv WM_MPLIB OPENMPI

View file

@ -15,6 +15,7 @@ set -x
wmakePrintBuild -check || /bin/rm -f OpenFOAM/Make/$WM_OPTIONS/global.? 2>/dev/null wmakePrintBuild -check || /bin/rm -f OpenFOAM/Make/$WM_OPTIONS/global.? 2>/dev/null
wmakeLnInclude OpenFOAM wmakeLnInclude OpenFOAM
wmakeLnInclude meshTools
wmakeLnInclude OSspecific/$WM_OSTYPE wmakeLnInclude OSspecific/$WM_OSTYPE
Pstream/Allwmake Pstream/Allwmake

View file

@ -308,6 +308,7 @@ primitiveShapes = meshes/primitiveShapes
$(primitiveShapes)/line/line.C $(primitiveShapes)/line/line.C
$(primitiveShapes)/plane/plane.C $(primitiveShapes)/plane/plane.C
$(primitiveShapes)/triangle/triangleFuncs.C
$(primitiveShapes)/triangle/intersection.C $(primitiveShapes)/triangle/intersection.C
meshShapes = meshes/meshShapes meshShapes = meshes/meshShapes
@ -495,6 +496,7 @@ $(pointBoundaryMesh)/pointBoundaryMesh.C
meshes/boundBox/boundBox.C meshes/boundBox/boundBox.C
meshTools = meshes/meshTools meshTools = meshes/meshTools
$(meshTools)/meshTools.C
$(meshTools)/matchPoints.C $(meshTools)/matchPoints.C
$(meshTools)/mergePoints.C $(meshTools)/mergePoints.C
@ -563,12 +565,33 @@ $(interpolations)/RBFInterpolation/RBFFunctions/Gauss/Gauss.C
$(interpolations)/RBFInterpolation/RBFFunctions/TPS/TPS.C $(interpolations)/RBFInterpolation/RBFFunctions/TPS/TPS.C
$(interpolations)/RBFInterpolation/RBFFunctions/IMQB/IMQB.C $(interpolations)/RBFInterpolation/RBFFunctions/IMQB/IMQB.C
algorithms/MeshWave/MeshWaveName.C algorithms/MeshWave/MeshWaveName.C
algorithms/MeshWave/FaceCellWaveName.C algorithms/MeshWave/FaceCellWaveName.C
algorithms/polygon/clipping/SutherlandHodgman.C algorithms/polygon/clipping/SutherlandHodgman.C
algorithms/polygon/pointInPolygon/HormannAgathos.C algorithms/polygon/pointInPolygon/HormannAgathos.C
algorithms/rotation/RodriguesRotation.C algorithms/rotation/RodriguesRotation.C
octree = algorithms/octree/octree
$(octree)/octreeName.C
$(octree)/octreeDataPoint.C
$(octree)/octreeDataPointTreeLeaf.C
$(octree)/octreeDataEdges.C
$(octree)/octreeDataCell.C
$(octree)/octreeDataFace.C
$(octree)/octreeDataBoundBox.C
$(octree)/treeBoundBox.C
$(octree)/treeNodeName.C
$(octree)/treeLeafName.C
$(octree)/pointIndexHitIOList.C
indexedOctree = algorithms/octree/indexedOctree
$(indexedOctree)/indexedOctreeName.C
$(indexedOctree)/treeDataCell.C
$(indexedOctree)/treeDataEdge.C
$(indexedOctree)/treeDataFace.C
$(indexedOctree)/treeDataPoint.C
graph/curve/curve.C graph/curve/curve.C
graph/graph.C graph/graph.C

View file

@ -120,8 +120,8 @@ public:
// Search // Search
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface. //- Get type (inside,outside,mixed,unknown) of point w.r.t. surface
// Only makes sense for closed surfaces. // Only makes sense for closed surfaces
label getVolumeType label getVolumeType
( (
const indexedOctree<treeDataCell>&, const indexedOctree<treeDataCell>&,

View file

@ -77,8 +77,8 @@ bool Foam::treeDataPoint::overlaps
} }
// Calculate nearest point to sample. Updates (if any) nearestDistSqr, minIndex, // Calculate nearest point to sample. Updates (if any) nearestDistSqr,
// nearestPoint. // minIndex, nearestPoint.
void Foam::treeDataPoint::findNearest void Foam::treeDataPoint::findNearest
( (
const labelList& indices, const labelList& indices,

View file

@ -338,7 +338,7 @@ Foam::label Foam::octree<Type>::findNearest
template <class Type> template <class Type>
Foam::labelList Foam::octree<Type>::findBox(const boundBox& bb) const Foam::labelList Foam::octree<Type>::findBox(const treeBoundBox& bb) const
{ {
// Storage for labels of shapes inside bb. Size estimate. // Storage for labels of shapes inside bb. Size estimate.
labelHashSet elements(100); labelHashSet elements(100);

View file

@ -339,7 +339,7 @@ public:
//- Find (in no particular order) indices of all shapes inside or //- Find (in no particular order) indices of all shapes inside or
// overlapping bounding box (i.e. all shapes not outside box) // overlapping bounding box (i.e. all shapes not outside box)
labelList findBox(const boundBox& bb) const; labelList findBox(const treeBoundBox& bb) const;
//- Find intersected shape along line. pointIndexHit contains index //- Find intersected shape along line. pointIndexHit contains index
// of nearest shape intersected and the intersection point. Uses // of nearest shape intersected and the intersection point. Uses

View file

@ -0,0 +1,210 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "octreeDataBoundBox.H"
#include "labelList.H"
#include "polyMesh.H"
#include "octree.H"
#include "polyPatch.H"
#include "triangleFuncs.H"
#include "linePointRef.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
defineTypeNameAndDebug(Foam::octreeDataBoundBox, 0);
Foam::scalar Foam::octreeDataBoundBox::tol
(
debug::tolerances("octreeDataBoundBoxTol", 1e-6)
);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::octreeDataBoundBox::octreeDataBoundBox
(
const treeBoundBoxList& bbL
)
:
allBb_(bbL)
{}
Foam::octreeDataBoundBox::octreeDataBoundBox(const octreeDataBoundBox& shapes)
:
allBb_(shapes.allBb())
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::octreeDataBoundBox::~octreeDataBoundBox()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::label Foam::octreeDataBoundBox::getSampleType
(
const octree<octreeDataBoundBox>& oc,
const point& sample
) const
{
return octree<octreeDataBoundBox>::UNKNOWN;
}
bool Foam::octreeDataBoundBox::overlaps
(
const label index,
const treeBoundBox& sampleBb
) const
{
return sampleBb.overlaps(allBb_[index]);
}
bool Foam::octreeDataBoundBox::contains(const label, const point&) const
{
notImplemented
(
"octreeDataBoundBox::contains(const label, const point&)"
);
return false;
}
bool Foam::octreeDataBoundBox::intersects
(
const label index,
const point& start,
const point& end,
point& intersectionPoint
) const
{
notImplemented
(
"octreeDataBoundBox::intersects(const label, const point&)"
);
return false;
}
bool Foam::octreeDataBoundBox::findTightest
(
const label index,
const point& sample,
treeBoundBox& tightest
) const
{
// Get furthest away vertex
point myNear, myFar;
allBb_[index].calcExtremities(sample, myNear, myFar);
const point dist = myFar - sample;
scalar myFarDist = mag(dist);
point tightestNear, tightestFar;
tightest.calcExtremities(sample, tightestNear, tightestFar);
scalar tightestFarDist = mag(tightestFar - sample);
if (tightestFarDist < myFarDist)
{
// Keep current tightest.
return false;
}
else
{
// Construct bb around sample and myFar
const point dist2(fabs(dist.x()), fabs(dist.y()), fabs(dist.z()));
tightest.min() = sample - dist2;
tightest.max() = sample + dist2;
return true;
}
}
// Determine numerical value of sign of sample compared to shape at index
Foam::scalar Foam::octreeDataBoundBox::calcSign
(
const label index,
const point& sample,
point& n
) const
{
n = vector::zero;
return 1;
}
// Calculate nearest point on/in shapei
Foam::scalar Foam::octreeDataBoundBox::calcNearest
(
const label index,
const point& sample,
point& nearest
) const
{
notImplemented
(
"octreeDataBoundBox::calcNearest"
"(const label index, const point& sample, point& nearest)"
);
return GREAT;
}
// Calculate nearest point on/in shapei
Foam::scalar Foam::octreeDataBoundBox::calcNearest
(
const label index,
const linePointRef& ln,
point& linePt,
point& shapePt
) const
{
notImplemented
(
"octreeDataBoundBox::calcNearest"
"(const label, const linePointRef&, point&, point&)"
);
return GREAT;
}
void Foam::octreeDataBoundBox::write(Ostream& os, const label index) const
{
os << allBb_[index];
}
// ************************************************************************* //

View file

@ -0,0 +1,213 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright held by original author
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::octreeDataBoundBox
Description
Holds data for octree to work on simple bounding boxes
For example, calculate (in calcNearest) the correct intersection point
with a bounding box.
Using bounding boxes simplify the usage of octree when only
primitivePatches entities are available (eg: from inside ggi interpolators)
SourceFiles
octreeDataBoundBox.C
Author
Martin Beaudoin, Hydro-Quebec, (2010)
\*---------------------------------------------------------------------------*/
#ifndef octreeDataBoundBox_H
#define octreeDataBoundBox_H
#include "treeBoundBoxList.H"
#include "faceList.H"
#include "point.H"
#include "className.H"
#include "linePointRef.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class primitiveMesh;
template<class Type> class octree;
class polyPatch;
/*---------------------------------------------------------------------------*\
Class octreeDataBoundBox Declaration
\*---------------------------------------------------------------------------*/
class octreeDataBoundBox
{
// Static data
//- Tolerance on linear dimensions
static scalar tol;
// Private data
//- Bounding boxes
treeBoundBoxList allBb_;
// Private Member Functions
public:
// Declare name of the class and its debug switch
ClassName("octreeDataBoundBox");
// Constructors
//- Construct from list of precomputed of bound boxes
explicit octreeDataBoundBox
(
const treeBoundBoxList& bbL
);
//- Construct as copy
octreeDataBoundBox(const octreeDataBoundBox&);
// Destructor
~octreeDataBoundBox();
// Member Functions
// Access
const treeBoundBoxList& allBb() const
{
return allBb_;
}
label size() const
{
return allBb_.size();
}
// Search
//- Get type of sample
label getSampleType
(
const octree<octreeDataBoundBox>&,
const point&
) const;
//- Does (bb of) shape at index overlap bb
bool overlaps
(
const label index,
const treeBoundBox& sampleBb
) const;
//- Does shape at index contain sample
bool contains
(
const label index,
const point& sample
) const;
//- Segment (from start to end) intersection with shape
// at index. If intersects returns true and sets intersectionPoint
bool intersects
(
const label index,
const point& start,
const point& end,
point& intersectionPoint
) const;
//- Sets newTightest to bounding box (and returns true) if
// nearer to sample than tightest bounding box. Otherwise
// returns false.
bool findTightest
(
const label index,
const point& sample,
treeBoundBox& tightest
) const;
//- Given index get unit normal and calculate (numerical) sign
// of sample.
// Used to determine accuracy of calcNearest or inside/outside.
scalar calcSign
(
const label index,
const point& sample,
vector& n
) const;
//- Calculates nearest (to sample) point in shape.
// Returns point and mag(nearest - sample). Returns GREAT if
// sample does not project onto (triangle decomposition) of face.
scalar calcNearest
(
const label index,
const point& sample,
point& nearest
) const;
//- Calculates nearest (to line segment) point in shape.
// Returns distance and both point.
scalar calcNearest
(
const label index,
const linePointRef& ln,
point& linePt, // nearest point on line
point& shapePt // nearest point on shape
) const;
// Write
//- Write shape at index
void write(Ostream& os, const label index) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View file

@ -545,6 +545,7 @@ bool Foam::octreeDataFace::overlaps
return true; return true;
} }
} }
return false; return false;
} }
@ -555,6 +556,7 @@ bool Foam::octreeDataFace::contains(const label, const point&) const
( (
"octreeDataFace::contains(const label, const point&)" "octreeDataFace::contains(const label, const point&)"
); );
return false; return false;
} }

View file

@ -260,13 +260,13 @@ public:
) const; ) const;
//- Overlaps other boundingbox? //- Overlaps other boundingbox?
inline bool overlaps(const treeBoundBox&) const; inline bool overlaps(const boundBox&) const;
//- Overlaps boundingSphere (centre + sqr(radius))? //- Overlaps boundingSphere (centre + sqr(radius))?
bool overlaps(const point&, const scalar radiusSqr) const; bool overlaps(const point&, const scalar radiusSqr) const;
//- Intersects segment; set point to intersection position and face, //- Intersects segment; set point to intersection position and face
// return true if intersection found. // Will return true if intersection found.
// (pt argument used during calculation even if not intersecting). // (pt argument used during calculation even if not intersecting).
// Calculates intersections from outside supplied vector // Calculates intersections from outside supplied vector
// (overallStart, overallVec). This is so when // (overallStart, overallVec). This is so when
@ -333,6 +333,12 @@ public:
// and guarantees in any direction s*mag(span) minimum width // and guarantees in any direction s*mag(span) minimum width
inline treeBoundBox extend(Random&, const scalar s) const; inline treeBoundBox extend(Random&, const scalar s) const;
//- Return slightly wider bounding box
// Extends all dimensions with s*span
// MB, 28/May/2011
inline treeBoundBox extend(const scalar s) const;
// Friend Operators // Friend Operators
friend bool operator==(const treeBoundBox&, const treeBoundBox&); friend bool operator==(const treeBoundBox&, const treeBoundBox&);

View file

@ -309,7 +309,7 @@ inline void Foam::treeBoundBox::searchOrder
// true if bb's intersect or overlap. // true if bb's intersect or overlap.
// Note: <= to make sure we catch all. // Note: <= to make sure we catch all.
inline bool Foam::treeBoundBox::overlaps(const treeBoundBox& bb) const inline bool Foam::treeBoundBox::overlaps(const boundBox& bb) const
{ {
return boundBox::overlaps(bb); return boundBox::overlaps(bb);
} }
@ -347,6 +347,28 @@ inline Foam::treeBoundBox Foam::treeBoundBox::extend
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // //- Return slightly wider bounding box, without a random gen param
// So we are sure to stay away from very small offsets like rndGen == 0
// MB, 28/May/2011
inline Foam::treeBoundBox Foam::treeBoundBox::extend(const scalar s) const
{
treeBoundBox bb(*this);
vector span(bb.max() - bb.min());
// Make 3D
scalar magSpan = Foam::mag(span);
for (direction dir = 0; dir < vector::nComponents; dir++)
{
span[dir] = Foam::max(s*magSpan, span[dir]);
}
bb.min() -= cmptMultiply(s*vector::one, span);
bb.max() += cmptMultiply(s*vector::one, span);
return bb;
}
// ************************************************************************* // // ************************************************************************* //

View file

@ -334,7 +334,7 @@ template <class Type>
bool Foam::treeLeaf<Type>::findBox bool Foam::treeLeaf<Type>::findBox
( (
const Type& shapes, const Type& shapes,
const boundBox& box, const treeBoundBox& box,
labelHashSet& elements labelHashSet& elements
) const ) const
{ {

View file

@ -235,7 +235,7 @@ public:
bool findBox bool findBox
( (
const Type& shapes, const Type& shapes,
const boundBox& bb, const treeBoundBox& bb,
labelHashSet& elements labelHashSet& elements
) const; ) const;
@ -276,7 +276,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "octreeDataPointTreeLeaf.H" #include "octreeDataPointTreeLeaf.H"
#include "octreeDataTriSurfaceTreeLeaf.H" //#include "octreeDataTriSurfaceTreeLeaf.H" HJ, header moved to triSurfaceMesh.H
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View file

@ -764,7 +764,7 @@ bool Foam::treeNode<Type>::findTightest
// Estimate for best place to start searching // Estimate for best place to start searching
label sampleOctant = this->bb().subOctant(midpoint(), sample, onEdge); label sampleOctant = this->bb().subOctant(midpoint(), sample, onEdge);
// Go into all suboctants (one containing sample first) and update tightest. // Go into all suboctants (one containing sample first) and update tightest
// Order of visiting is if e.g. sampleOctant = 5: // Order of visiting is if e.g. sampleOctant = 5:
// 5 1 2 3 4 0 6 7 // 5 1 2 3 4 0 6 7
for (label octantI=0; octantI<8; octantI++) for (label octantI=0; octantI<8; octantI++)
@ -846,7 +846,7 @@ bool Foam::treeNode<Type>::findNearest
// Estimate for best place to start searching // Estimate for best place to start searching
label sampleOctant = this->bb().subOctant(midpoint(), sample, onEdge); label sampleOctant = this->bb().subOctant(midpoint(), sample, onEdge);
// Go into all suboctants (one containing sample first) and update tightest. // Go into all suboctants (one containing sample first) and update tightest
// Order of visiting is if e.g. sampleOctant = 5: // Order of visiting is if e.g. sampleOctant = 5:
// 5 1 2 3 4 0 6 7 // 5 1 2 3 4 0 6 7
for (label octantI=0; octantI<8; octantI++) for (label octantI=0; octantI<8; octantI++)
@ -1004,7 +1004,7 @@ template <class Type>
bool Foam::treeNode<Type>::findBox bool Foam::treeNode<Type>::findBox
( (
const Type& shapes, const Type& shapes,
const boundBox& box, const treeBoundBox& box,
labelHashSet& elements labelHashSet& elements
) const ) const
{ {
@ -1018,7 +1018,7 @@ bool Foam::treeNode<Type>::findBox
onEdge onEdge
); );
// Go into all suboctants (one containing sample first) and update tightest. // Go into all suboctants (one containing sample first) and update tightest
// Order of visiting is if e.g. sampleOctant = 5: // Order of visiting is if e.g. sampleOctant = 5:
// 5 1 2 3 4 0 6 7 // 5 1 2 3 4 0 6 7
for (label octantI=0; octantI<8; octantI++) for (label octantI=0; octantI<8; octantI++)

View file

@ -271,7 +271,7 @@ public:
bool findBox bool findBox
( (
const Type& shapes, const Type& shapes,
const boundBox& bb, const treeBoundBox& bb,
labelHashSet& elements labelHashSet& elements
) const; ) const;

View file

@ -279,7 +279,7 @@ public:
//- Am I the master process //- Am I the master process
static bool master() static bool master()
{ {
return myProcNo_ == 0; return myProcNo_ == masterNo();
} }
//- Process index of the master //- Process index of the master

View file

@ -25,9 +25,10 @@ License
Description Description
Gather data from all processors onto single processor according to some Gather data from all processors onto single processor according to some
communication schedule (usually linear-to-master or tree-to-master). communication schedule (usually linear-to-master or tree-to-master).
The gathered data will be a list with element procID the data from processor The gathered data will be a list with element procID the data from
procID. Before calling every processor should insert its value into processor procID. Before calling every processor should insert
Values[Pstream::myProcNo()]. its value into Values[Pstream::myProcNo()].
Note: after gather every processor only knows its own data and that of the Note: after gather every processor only knows its own data and that of the
processors below it. Only the 'master' of the communication schedule holds processors below it. Only the 'master' of the communication schedule holds
a fully filled List. Use scatter to distribute the data. a fully filled List. Use scatter to distribute the data.

View file

@ -60,6 +60,38 @@ void GGIInterpolation<MasterPatch, SlavePatch>::interpolate
} }
template<class MasterPatch, class SlavePatch>
template<class Type>
void GGIInterpolation<MasterPatch, SlavePatch>::maskedInterpolate
(
const Field<Type>& ff,
Field<Type>& result,
const labelList& mask,
const labelListList& addr,
const scalarListList& weights
)
{
forAll (mask, maskI)
{
// Pick the masked face
const label faceI = mask[maskI];
const labelList& curAddr = addr[faceI];
const scalarList& curWeights = weights[faceI];
// Clear condensed list entry: masked faces only
result[maskI] = pTraits<Type>::zero;
forAll (curAddr, i)
{
// Put the result into condensed list: masked faces only
result[maskI] += ff[curAddr[i]]*curWeights[i];
}
}
}
template<class MasterPatch, class SlavePatch> template<class MasterPatch, class SlavePatch>
template<class Type> template<class Type>
void GGIInterpolation<MasterPatch, SlavePatch>::bridge void GGIInterpolation<MasterPatch, SlavePatch>::bridge
@ -76,6 +108,44 @@ void GGIInterpolation<MasterPatch, SlavePatch>::bridge
} }
template<class MasterPatch, class SlavePatch>
template<class Type>
void GGIInterpolation<MasterPatch, SlavePatch>::maskedBridge
(
const Field<Type>& bridgeField,
Field<Type>& ff,
const labelList& mask,
const labelList& addr
)
{
// Note: tricky algorithm
// In order for a face to be bridged it needs to be both in the
// mask and in selection of faces that are bridged (addr).
// This implies an n-squared search, but we can use the fact that
// both lists are ordered.
label curAddrI = 0;
forAll (mask, maskI)
{
// Pick the masked face
const label faceI = mask[maskI];
for (; curAddrI < addr.size(); curAddrI++)
{
if (faceI == addr[curAddrI])
{
// Found masked bridged face
// Put the result into condensed list: masked faces only
ff[maskI] = bridgeField[faceI];
break;
}
}
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class MasterPatch, class SlavePatch> template<class MasterPatch, class SlavePatch>
@ -161,6 +231,84 @@ GGIInterpolation<MasterPatch, SlavePatch>::masterToSlave
} }
template<class MasterPatch, class SlavePatch>
template<class Type>
void GGIInterpolation<MasterPatch, SlavePatch>::maskedMasterToSlave
(
const Field<Type>& ff,
Field<Type>& result,
const labelList& mask
) const
{
if (ff.size() != masterPatch_.size())
{
FatalErrorIn
(
"void GGIInterpolation::maskedMasterToSlave\n"
"(\n"
" const Field<Type>& ff,\n"
" Field<Type>& result,\n"
" const labelList& mask\n"
") const"
) << "given field does not correspond to patch. Patch size: "
<< masterPatch_.size() << " field size: " << ff.size()
<< abort(FatalError);
}
if (result.size() != mask.size())
{
FatalErrorIn
(
"void GGIInterpolation::maskedMasterToSlave\n"
"(\n"
" const Field<Type>& ff,\n"
" Field<Type>& result,\n"
" const labelList& mask\n"
") const"
) << "result field does not correspond to mask. Field size: "
<< result.size() << " mask size: " << mask.size()
<< abort(FatalError);
}
if (this->doTransform() && pTraits<Type>::rank > 0)
{
// Transform master data to slave
Field<Type> transformFF;
if (reverseT_.size() == 1)
{
// Constant transform
transformFF = transform(reverseT_[0], ff);
}
else
{
// Full patch transform
transformFF = transform(reverseT_, ff);
}
GGIInterpolation<MasterPatch, SlavePatch>::maskedInterpolate
(
transformFF,
result,
mask,
this->slaveAddr(),
this->slaveWeights()
);
}
else
{
GGIInterpolation<MasterPatch, SlavePatch>::maskedInterpolate
(
ff,
result,
mask,
this->slaveAddr(),
this->slaveWeights()
);
}
}
template<class MasterPatch, class SlavePatch> template<class MasterPatch, class SlavePatch>
template<class Type> template<class Type>
tmp<Field<Type> > tmp<Field<Type> >
@ -244,6 +392,83 @@ GGIInterpolation<MasterPatch, SlavePatch>::slaveToMaster
} }
template<class MasterPatch, class SlavePatch>
template<class Type>
void GGIInterpolation<MasterPatch, SlavePatch>::maskedSlaveToMaster
(
const Field<Type>& ff,
Field<Type>& result,
const labelList& mask
) const
{
if (ff.size() != slavePatch_.size())
{
FatalErrorIn
(
"void GGIInterpolation::maskedSlaveToMaster"
"(\n"
" const Field<Type>& ff,\n"
" Field<Type>& result,\n"
" const labelList& mask\n"
") const"
) << "given field does not correspond to patch. Patch size: "
<< slavePatch_.size() << " field size: " << ff.size()
<< abort(FatalError);
}
if (result.size() != mask.size())
{
FatalErrorIn
(
"void GGIInterpolation::maskedSlaveToMaster\n"
"(\n"
" const Field<Type>& ff,\n"
" Field<Type>& result,\n"
" const labelList& mask\n"
") const"
) << "result field does not correspond to mask. Field size: "
<< result.size() << " mask size: " << mask.size()
<< abort(FatalError);
}
if (this->doTransform() && pTraits<Type>::rank > 0)
{
// Transform slave data to master
Field<Type> transformFF;
if (forwardT_.size() == 1)
{
// Constant transform
transformFF = transform(forwardT_[0], ff);
}
else
{
// Full patch transform
transformFF = transform(forwardT_, ff);
}
GGIInterpolation<MasterPatch, SlavePatch>::maskedInterpolate
(
transformFF,
result,
mask,
this->masterAddr(),
this->masterWeights()
);
}
else
{
GGIInterpolation<MasterPatch, SlavePatch>::maskedInterpolate
(
ff,
result,
mask,
this->masterAddr(),
this->masterWeights()
);
}
}
template<class MasterPatch, class SlavePatch> template<class MasterPatch, class SlavePatch>
template<class Type> template<class Type>
void GGIInterpolation<MasterPatch, SlavePatch>::bridgeMaster void GGIInterpolation<MasterPatch, SlavePatch>::bridgeMaster
@ -275,6 +500,42 @@ void GGIInterpolation<MasterPatch, SlavePatch>::bridgeMaster
} }
template<class MasterPatch, class SlavePatch>
template<class Type>
void GGIInterpolation<MasterPatch, SlavePatch>::maskedBridgeMaster
(
const Field<Type>& bridgeField,
Field<Type>& ff,
const labelList& mask
) const
{
if
(
bridgeField.size() != masterPatch_.size()
|| ff.size() != mask.size()
)
{
FatalErrorIn
(
"void GGIInterpolation<MasterPatch, SlavePatch>::"
"maskedBridgeMaster\n"
"(\n"
" const Field<Type>& bridgeField,\n"
" Field<Type>& ff,\n"
" const labelList& mask\n"
") const"
) << "given field does not correspond to patch. Patch size: "
<< masterPatch_.size()
<< " bridge field size: " << bridgeField.size()
<< " field size: " << ff.size()
<< " mask size: " << mask.size()
<< abort(FatalError);
}
maskedBridge(bridgeField, ff, mask, uncoveredMasterFaces());
}
template<class MasterPatch, class SlavePatch> template<class MasterPatch, class SlavePatch>
template<class Type> template<class Type>
void GGIInterpolation<MasterPatch, SlavePatch>::bridgeSlave void GGIInterpolation<MasterPatch, SlavePatch>::bridgeSlave
@ -286,14 +547,16 @@ void GGIInterpolation<MasterPatch, SlavePatch>::bridgeSlave
if if
( (
bridgeField.size() != slavePatch_.size() bridgeField.size() != slavePatch_.size()
|| ff.size() != slavePatch_.size()) || ff.size() != slavePatch_.size()
)
{ {
FatalErrorIn FatalErrorIn
( (
"void GGIInterpolation<MasterPatch, SlavePatch>::bridgeSlave\n" "void GGIInterpolation<MasterPatch, SlavePatch>::"
"bridgeSlave\n"
"(\n" "(\n"
" const Field<Type>& bridgeField,\n" " const Field<Type>& bridgeField,\n"
" Field<Type>& ff\n" " Field<Type>& ff"
") const" ") const"
) << "given field does not correspond to patch. Patch size: " ) << "given field does not correspond to patch. Patch size: "
<< slavePatch_.size() << slavePatch_.size()
@ -306,6 +569,42 @@ void GGIInterpolation<MasterPatch, SlavePatch>::bridgeSlave
} }
template<class MasterPatch, class SlavePatch>
template<class Type>
void GGIInterpolation<MasterPatch, SlavePatch>::maskedBridgeSlave
(
const Field<Type>& bridgeField,
Field<Type>& ff,
const labelList& mask
) const
{
if
(
bridgeField.size() != slavePatch_.size()
|| ff.size() != mask.size()
)
{
FatalErrorIn
(
"void GGIInterpolation<MasterPatch, SlavePatch>::"
"maskedBridgeSlave\n"
"(\n"
" const Field<Type>& bridgeField,\n"
" Field<Type>& ff\n,"
" const labelList& mask\n"
") const"
) << "given field does not correspond to patch. Patch size: "
<< slavePatch_.size()
<< " bridge field size: " << bridgeField.size()
<< " field size: " << ff.size()
<< " mask size: " << mask.size()
<< abort(FatalError);
}
maskedBridge(bridgeField, ff, mask, uncoveredSlaveFaces());
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam } // End namespace Foam

View file

@ -85,6 +85,7 @@ public:
{ {
THREE_D_DISTANCE, THREE_D_DISTANCE,
AABB, AABB,
BB_OCTREE,
N_SQUARED N_SQUARED
}; };
@ -192,6 +193,39 @@ class GGIInterpolation
//- Facet normal featureCos criteria //- Facet normal featureCos criteria
static const scalar featureCosTol_; static const scalar featureCosTol_;
//- Facet bound box extension factor
static const scalar faceBoundBoxExtendSpanFraction_;
//- The next 3 attributes are parameters controlling the creation
// of an octree search engine for the GGI facets neighbourhood
// determination.
//
// Tests using GGI patches of up to ~100K facets have shown that
// the following values gave the best compromise between the
// "octree creation time" vs "octree search time":
//
// octreeSearchMinNLevel_ : 3
// octreeSearchMaxLeafRatio_ : 3
// octreeSearchMaxShapeRatio_ : 1
//
// For GGI patches larger than ~100K facets, your mileage may vary.
// So these 3 control parameters are adjustable using the following
// global optimization switches:
//
// GGIOctreeSearchMinNLevel
// GGIOctreeSearchMaxLeafRatio
// GGIOctreeSearchMaxShapeRatio
//
//- Octree search: minNlevel parameter for octree constructor
static const label octreeSearchMinNLevel_;
//- Octree search: maxLeafRatio parameter for octree constructor
static const scalar octreeSearchMaxLeafRatio_;
//- Octree search: maxShapeRatio parameter for octree constructor
static const scalar octreeSearchMaxShapeRatio_;
// Private Member Functions // Private Member Functions
@ -210,6 +244,10 @@ class GGIInterpolation
//- Evaluate faces neighborhood based of faces Axis Aligned BB //- Evaluate faces neighborhood based of faces Axis Aligned BB
void findNeighboursAABB(labelListList& result) const; void findNeighboursAABB(labelListList& result) const;
//- Evaluate faces neighborhood based of faces BB and an octree
// search engine
void findNeighboursBBOctree(labelListList& result) const;
//- Projects a list of points onto a plane located at //- Projects a list of points onto a plane located at
// planeOrig, oriented along planeNormal // planeOrig, oriented along planeNormal
tmp<pointField> projectPointsOnPlane tmp<pointField> projectPointsOnPlane
@ -326,6 +364,18 @@ class GGIInterpolation
const scalarListList& weights const scalarListList& weights
); );
//- Interpolate given source and target, addressing and weights
// for masked faces only
template<class Type>
static void maskedInterpolate
(
const Field<Type>& ff,
Field<Type>& result,
const labelList& mask,
const labelListList& addr,
const scalarListList& weights
);
//- Bridge uncovered faces given addressing //- Bridge uncovered faces given addressing
template<class Type> template<class Type>
static void bridge static void bridge
@ -335,6 +385,17 @@ class GGIInterpolation
const labelList& addr const labelList& addr
); );
//- Bridge uncovered faces given addressing
// for masked faces only
template<class Type>
static void maskedBridge
(
const Field<Type>& bridgeField,
Field<Type>& ff,
const labelList& mask,
const labelList& addr
);
//- Is a transform required? //- Is a transform required?
inline bool doTransform() const inline bool doTransform() const
{ {
@ -360,8 +421,8 @@ public:
const tensorField& forwardT, const tensorField& forwardT,
const tensorField& reverseT, const tensorField& reverseT,
const vectorField& forwardSep, const vectorField& forwardSep,
const scalar masterFaceNonOverlapFaceTol = 0.0, const scalar masterFaceNonOverlapFaceTol = 0,
const scalar slaveFaceNonOverlapFaceTol = 0.0, const scalar slaveFaceNonOverlapFaceTol = 0,
const bool rescaleGGIWeightingFactors = true, const bool rescaleGGIWeightingFactors = true,
const quickReject reject = AABB const quickReject reject = AABB
); );
@ -399,22 +460,45 @@ public:
//- Interpolate from master to slave //- Interpolate from master to slave
template<class Type> template<class Type>
tmp<Field<Type> > masterToSlave(const Field<Type>& pf) const; tmp<Field<Type> > masterToSlave(const Field<Type>& ff) const;
template<class Type> template<class Type>
tmp<Field<Type> > masterToSlave tmp<Field<Type> > masterToSlave
( (
const tmp<Field<Type> >& tpf const tmp<Field<Type> >& tff
) const; ) const;
//- Interpolate from master to slave, only for marked master faces
// Addressing picks the faces from patch that are selected
// for collection into the result field
template<class Type>
void maskedMasterToSlave
(
const Field<Type>& ff,
Field<Type>& result,
const labelList& mask
) const;
//- Interpolate from slave to master //- Interpolate from slave to master
template<class Type> template<class Type>
tmp<Field<Type> > slaveToMaster(const Field<Type>& pf) const; tmp<Field<Type> > slaveToMaster(const Field<Type>& ff) const;
template<class Type> template<class Type>
tmp<Field<Type> > slaveToMaster tmp<Field<Type> > slaveToMaster
( (
const tmp<Field<Type> >& tpf const tmp<Field<Type> >& tff
) const;
//- Interpolate from slave to master, only for marked slave faces
// Addressing picks the faces from patch that are selected
// for collection into the result field
template<class Type>
void maskedSlaveToMaster
(
const Field<Type>& ff,
Field<Type>& result,
const labelList& mask
) const; ) const;
@ -426,6 +510,15 @@ public:
Field<Type>& ff Field<Type>& ff
) const; ) const;
//- Bridge uncovered master patch field, only for marked master faces
template<class Type>
void maskedBridgeMaster
(
const Field<Type>& bridgeField,
Field<Type>& ff,
const labelList& mask
) const;
//- Bridge uncovered slave patch field //- Bridge uncovered slave patch field
template<class Type> template<class Type>
void bridgeSlave void bridgeSlave
@ -434,6 +527,15 @@ public:
Field<Type>& ff Field<Type>& ff
) const; ) const;
//- Bridge uncovered slave patch field, only for marked slave faces
template<class Type>
void maskedBridgeSlave
(
const Field<Type>& bridgeField,
Field<Type>& ff,
const labelList& mask
) const;
// Edit // Edit

View file

@ -34,12 +34,45 @@ Author
#include "boundBox.H" #include "boundBox.H"
#include "plane.H" #include "plane.H"
#include "transformField.H" #include "transformField.H"
#include "octree.H"
#include "octreeDataBoundBox.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
template<class MasterPatch, class SlavePatch>
const scalar
GGIInterpolation<MasterPatch, SlavePatch>::faceBoundBoxExtendSpanFraction_
(
debug::tolerances("GGIFaceBoundBoxExtendSpanFraction", 1.0e-2)
);
template<class MasterPatch, class SlavePatch>
const label
GGIInterpolation<MasterPatch, SlavePatch>::octreeSearchMinNLevel_
(
debug::optimisationSwitch("GGIOctreeSearchMinNLevel", 3)
);
template<class MasterPatch, class SlavePatch>
const scalar
GGIInterpolation<MasterPatch, SlavePatch>::octreeSearchMaxLeafRatio_
(
debug::optimisationSwitch("GGIOctreeSearchMaxLeafRatio", 3)
);
template<class MasterPatch, class SlavePatch>
const scalar
GGIInterpolation<MasterPatch, SlavePatch>::octreeSearchMaxShapeRatio_
(
debug::optimisationSwitch("GGIOctreeSearchMaxShapeRatio", 1)
);
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// From: http://www.gamasutra.com/features/20000330/bobic_02.htm // From: http://www.gamasutra.com/features/20000330/bobic_02.htm
@ -382,6 +415,148 @@ void GGIInterpolation<MasterPatch, SlavePatch>::findNeighboursAABB
} }
} }
// This algorithm find the faces in proximity of another face based
// on the face BB (Bounding Box) and an octree of bounding boxes.
template<class MasterPatch, class SlavePatch>
void GGIInterpolation<MasterPatch, SlavePatch>::findNeighboursBBOctree
(
labelListList& result
) const
{
List<DynamicList<label> > candidateMasterNeighbors(masterPatch_.size());
// Initialize the list of master patch faces bounding box
treeBoundBoxList lmasterFaceBB(masterPatch_.size());
forAll (masterPatch_, faceMi)
{
pointField facePoints
(
masterPatch_[faceMi].points(masterPatch_.points())
);
// Construct face BB with an extension of face span defined by the
// global tolerance factor faceBoundBoxExtendSpanFraction_
// (1% by default)
treeBoundBox bbFaceMaster(facePoints);
lmasterFaceBB[faceMi] =
bbFaceMaster.extend(faceBoundBoxExtendSpanFraction_);
}
// Initialize the list of slave patch faces bounding box
treeBoundBoxList lslaveFaceBB(slavePatch_.size());
forAll (slavePatch_, faceSi)
{
pointField facePoints
(
slavePatch_[faceSi].points(slavePatch_.points())
);
// possible transformation and separation for cyclic patches
if (doTransform())
{
if (forwardT_.size() == 1)
{
transform(facePoints, forwardT_[0], facePoints);
}
else
{
transform(facePoints, forwardT_[faceSi], facePoints);
}
}
if (doSeparation())
{
if (forwardSep_.size() == 1)
{
facePoints += forwardSep_[0];
}
else
{
facePoints += forwardSep_[faceSi];
}
}
// Construct face BB with an extension of face span defined by the
// global tolerance factor faceBoundBoxExtendSpanFraction_
// (1% by default)
treeBoundBox bbFaceSlave(facePoints);
lslaveFaceBB[faceSi] =
bbFaceSlave.extend(faceBoundBoxExtendSpanFraction_);
}
// Create the slave octreeData, using the boundBox flavor
octreeDataBoundBox slaveDataBB(lslaveFaceBB);
// Overall slave patch BB
treeBoundBox slaveOverallBB(slavePatch_.points());
// Create the slave patch octree
octree<octreeDataBoundBox> slavePatchOctree
(
slaveOverallBB, // overall search domain
slaveDataBB,
octreeSearchMinNLevel_, // min number of levels
octreeSearchMaxLeafRatio_, // max avg. size of leaves
octreeSearchMaxShapeRatio_ // max avg. duplicity.
);
const vectorField& masterFaceNormals = masterPatch_.faceNormals();
vectorField slaveNormals = slavePatch_.faceNormals();
// Transform slave normals to master plane if needed
if (doTransform())
{
if (forwardT_.size() == 1)
{
transform(slaveNormals, forwardT_[0], slaveNormals);
}
else
{
transform(slaveNormals, forwardT_, slaveNormals);
}
}
// Visit each master patch face BB and find the potential neighbours
// using the slave patch octree
forAll (lmasterFaceBB, faceMi)
{
// List of candidate neighbours
labelList overlappedFaces =
slavePatchOctree.findBox(lmasterFaceBB[faceMi]);
forAll (overlappedFaces, ovFi)
{
label faceSi = overlappedFaces[ovFi];
// Compute and verify featureCos between the two face normals
// before adding to the list of candidates
scalar featureCos =
masterFaceNormals[faceMi] & slaveNormals[faceSi];
if (mag(featureCos) > featureCosTol_)
{
candidateMasterNeighbors[faceMi].append(faceSi);
}
}
}
// Repack the list
result.setSize(masterPatch_.size());
forAll (result, i)
{
result[i].transfer(candidateMasterNeighbors[i].shrink());
}
return;
}
// Projects a list of points onto a plane located at planeOrig, // Projects a list of points onto a plane located at planeOrig,
@ -664,8 +839,8 @@ bool GGIInterpolation<MasterPatch, SlavePatch>::detect2dPolygonsOverlap
// accept to discard an intersecting area roughly 10e-6 times the // accept to discard an intersecting area roughly 10e-6 times the
// surface of the smallest polygon, so 1 PPM. // surface of the smallest polygon, so 1 PPM.
// //
// Which means also that our GGI weighting factors will never be smaller // Which means also that our GGI weighting factors will never be
// than roughly 10e-6, because this is the fraction of // smaller than roughly 10e-6, because this is the fraction of
// the intersection surface area we choose to discard. // the intersection surface area we choose to discard.
scalar _epsilon = tolFactor* scalar _epsilon = tolFactor*
@ -691,12 +866,14 @@ bool GGIInterpolation<MasterPatch, SlavePatch>::detect2dPolygonsOverlap
{ {
// We have not found any separating axes by exploring from // We have not found any separating axes by exploring from
// poly1, let's switch by exploring from poly2 instead // poly1, let's switch by exploring from poly2 instead
isOverlapping = detect2dPolygonsOverlap(poly2, poly1, tolFactor, false); isOverlapping =
detect2dPolygonsOverlap(poly2, poly1, tolFactor, false);
} }
return isOverlapping; return isOverlapping;
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam } // End namespace Foam

View file

@ -87,7 +87,11 @@ void GGIInterpolation<MasterPatch, SlavePatch>::calcAddressing() const
if (debug) if (debug)
{ {
Info << "Evaluation of GGI weighting factors:" << endl; InfoIn
(
"void GGIInterpolation<MasterPatch, SlavePatch>::"
"calcAddressing() const"
) << "Evaluation of GGI weighting factors:" << endl;
} }
// Create the dynamic lists to hold the addressing // Create the dynamic lists to hold the addressing
@ -112,14 +116,19 @@ void GGIInterpolation<MasterPatch, SlavePatch>::calcAddressing() const
// The candidates master neighbours // The candidates master neighbours
// Choice of algorithm: // Choice of algorithm:
// 1) Axis-aligned bounding box // 1) Axis-aligned bounding box
// 2) 3-D vector distance // 2) Octree search with bounding box
// 3) n-Squared search // 3) 3-D vector distance
// 4) n-Squared search
labelListList candidateMasterNeighbors; labelListList candidateMasterNeighbors;
if (reject_ == AABB) if (reject_ == AABB)
{ {
findNeighboursAABB(candidateMasterNeighbors); findNeighboursAABB(candidateMasterNeighbors);
} }
else if (reject_ == BB_OCTREE)
{
findNeighboursBBOctree(candidateMasterNeighbors);
}
else if (reject_ == THREE_D_DISTANCE) else if (reject_ == THREE_D_DISTANCE)
{ {
findNeighbours3D(candidateMasterNeighbors); findNeighbours3D(candidateMasterNeighbors);
@ -500,7 +509,7 @@ void GGIInterpolation<MasterPatch, SlavePatch>::calcAddressing() const
// other. A good case: the ercoftac conical diffuser, Case0... GGI // other. A good case: the ercoftac conical diffuser, Case0... GGI
// located right between the cylindrical and conical parts, rotate the // located right between the cylindrical and conical parts, rotate the
// cylindrical by 15 degrees. For this case, we will need to devise a // cylindrical by 15 degrees. For this case, we will need to devise a
// decent strategy in order to intelligently take care of this // decent strategy in order to intelligently take care of these
// "missing weights" // "missing weights"
// //
// The purpose of the ::rescaleWeightingFactors() method is mainly for // The purpose of the ::rescaleWeightingFactors() method is mainly for
@ -584,6 +593,7 @@ void GGIInterpolation<MasterPatch, SlavePatch>::rescaleWeightingFactors() const
} }
} }
// Find non-overlapping faces from both master and slave patches // Find non-overlapping faces from both master and slave patches
// The default non-overlapping criteria is total absence of neighbours. // The default non-overlapping criteria is total absence of neighbours.
// Later on, ths criteria will be based on minimum surface intersection, or // Later on, ths criteria will be based on minimum surface intersection, or

View file

@ -107,12 +107,29 @@ void Foam::ggiGAMGInterfaceField::updateInterfaceMatrix
const unallocLabelList& faceCells = ggiInterface_.faceCells(); const unallocLabelList& faceCells = ggiInterface_.faceCells();
// New treatment. HJ, 26/Jun/2011
if (zonePnf.size() != faceCells.size())
{
FatalErrorIn("ggiGAMGInterfaceField::updateInterfaceMatrix")
<< "Bananas!!!"
<< abort(FatalError);
}
forAll(faceCells, elemI)
{
result[faceCells[elemI]] -= coeffs[elemI]*zonePnf[elemI];
}
// Old treatment
#if(0)
const labelList& za = ggiInterface_.zoneAddressing(); const labelList& za = ggiInterface_.zoneAddressing();
forAll(faceCells, elemI) forAll(faceCells, elemI)
{ {
result[faceCells[elemI]] -= coeffs[elemI]*zonePnf[za[elemI]]; result[faceCells[elemI]] -= coeffs[elemI]*zonePnf[za[elemI]];
} }
#endif
} }

View file

@ -41,6 +41,49 @@ namespace Foam
} }
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::ggiGAMGInterface::initFastReduce() const
{
// Init should be executed only once
initReduce_ = true;
// Establish parallel comms pattern
if (!localParallel() && Pstream::parRun())
{
// Only master handles communication
if (Pstream::master())
{
receiveAddr_.setSize(Pstream::nProcs());
sendAddr_.setSize(Pstream::nProcs());
receiveAddr_[0] = zoneAddressing();
for (label procI = 1; procI < Pstream::nProcs(); procI++)
{
// Note: must use normal comms because the size of the
// communicated lists is unknown on the receiving side
// HJ, 4/Jun/2011
// Opt: reconsider mode of communication
IPstream ip(Pstream::scheduled, procI);
receiveAddr_[procI] = labelList(ip);
sendAddr_[procI] = labelList(ip);
}
}
else
{
// Opt: reconsider mode of communication
OPstream op(Pstream::scheduled, Pstream::masterNo());
op << zoneAddressing() << shadowInterface().zoneAddressing();
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::ggiGAMGInterface::ggiGAMGInterface Foam::ggiGAMGInterface::ggiGAMGInterface
@ -54,7 +97,10 @@ Foam::ggiGAMGInterface::ggiGAMGInterface
GAMGInterface(lduMesh), GAMGInterface(lduMesh),
fineGgiInterface_(refCast<const ggiLduInterface>(fineInterface)), fineGgiInterface_(refCast<const ggiLduInterface>(fineInterface)),
zoneSize_(0), zoneSize_(0),
zoneAddressing_() zoneAddressing_(),
initReduce_(false),
receiveAddr_(),
sendAddr_()
{ {
// Note. // Note.
// All processors will do the same coarsening and then filter // All processors will do the same coarsening and then filter
@ -644,6 +690,7 @@ const Foam::labelListList& Foam::ggiGAMGInterface::addressing() const
FatalErrorIn("const labelListList& ggiGAMGInterface::addressing() const") FatalErrorIn("const labelListList& ggiGAMGInterface::addressing() const")
<< "Requested fine addressing at coarse level" << "Requested fine addressing at coarse level"
<< abort(FatalError); << abort(FatalError);
return labelListList::null(); return labelListList::null();
} }
@ -659,6 +706,7 @@ const Foam::scalarListList& Foam::ggiGAMGInterface::weights() const
FatalErrorIn("const labelListList& ggiGAMGInterface::weights() const") FatalErrorIn("const labelListList& ggiGAMGInterface::weights() const")
<< "Requested fine addressing at coarse level" << "Requested fine addressing at coarse level"
<< abort(FatalError); << abort(FatalError);
return scalarListList::null(); return scalarListList::null();
} }
@ -681,9 +729,8 @@ void Foam::ggiGAMGInterface::initTransfer
const unallocLabelList& interfaceData const unallocLabelList& interfaceData
) const ) const
{ {
// Label transfer is straight local // Label transfer is local
labelTransferBuffer_ = interfaceData; labelTransferBuffer_ = interfaceData;
// labelTransferBuffer_ = expand(interfaceData);
} }
@ -706,9 +753,6 @@ void Foam::ggiGAMGInterface::initInternalFieldTransfer
{ {
// Label transfer is local without global reduction // Label transfer is local without global reduction
labelTransferBuffer_ = interfaceInternalField(iF); labelTransferBuffer_ = interfaceInternalField(iF);
// labelList pif = interfaceInternalField(iF);
// labelTransferBuffer_ = expand(pif);
} }
@ -730,8 +774,14 @@ void Foam::ggiGAMGInterface::initInternalFieldTransfer
{ {
scalarField pif = interfaceInternalField(iF); scalarField pif = interfaceInternalField(iF);
// New treatment. HJ, 26/Jun/2011
fieldTransferBuffer_ = fastReduce(pif);
// Old treatment
#if(0)
// Expand the field, executing a reduce operation in init // Expand the field, executing a reduce operation in init
fieldTransferBuffer_ = expand(pif); fieldTransferBuffer_ = expand(pif);
#endif
} }

View file

@ -69,6 +69,18 @@ class ggiGAMGInterface
labelList zoneAddressing_; labelList zoneAddressing_;
// Parallel communication optimisation, stored on master processor
//- Has reduce been initialised?
mutable bool initReduce_;
//- List of zone faces indices received from each processor
mutable labelListList receiveAddr_;
//- List of zone faces indices to send to each processor
mutable labelListList sendAddr_;
// Private Member Functions // Private Member Functions
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct
@ -77,8 +89,19 @@ class ggiGAMGInterface
//- Disallow default bitwise assignment //- Disallow default bitwise assignment
void operator=(const ggiGAMGInterface&); void operator=(const ggiGAMGInterface&);
//- Init fast reduce
void initFastReduce() const;
//- Fast reduce
// Note: contains global communications
// New, HJ, 24/Jun/2011
template<class Type>
tmp<Field<Type> > fastReduce(const UList<Type>&) const;
//- Expand data to zone size //- Expand data to zone size
// Note: contains global reduce. HJ, 15/May/2009 // Note: contains global reduce. HJ, 15/May/2009
// Obsolete. HJ, 24/Jun/2011
template<class Type> template<class Type>
tmp<Field<Type> > expand(const UList<Type>&) const; tmp<Field<Type> > expand(const UList<Type>&) const;

View file

@ -33,6 +33,174 @@ namespace Foam
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
tmp<Field<Type> > ggiGAMGInterface::fastReduce(const UList<Type>& ff) const
{
// Algorithm
// Local processor contains faceCells part of the zone and requires
// zoneAddressing part.
// For fast communications, each processor will send the faceCells and
// zoneAddressing to the master. Master will assemble global zone
// and send off messages to all processors containing only
// the required data
// HJ, 24/Jun/2011
if (ff.size() != this->size())
{
FatalErrorIn
(
"tmp<Field<Type> > ggiGAMGInterface::fastReduce"
"("
" const UList<Type>& ff"
") const"
) << "Wrong field size. ff: " << ff.size()
<< " interface: " << this->size()
<< abort(FatalError);
}
if (localParallel() || !Pstream::parRun())
{
// Field remains identical: no parallel communications required
tmp<Field<Type> > tresult(new Field<Type>(ff));
return tresult;
}
// Execute reduce if not already done
if (!initReduce_)
{
initFastReduce();
}
if (Pstream::master())
{
// Master collects information and distributes data.
Field<Type> expandField(zoneSize(), pTraits<Type>::zero);
// Insert master processor
const labelList& za = zoneAddressing();
forAll (za, i)
{
expandField[za[i]] = ff[i];
}
// Master receives and inserts data from all processors for which
// receiveAddr contains entries
for (label procI = 1; procI < Pstream::nProcs(); procI++)
{
const labelList& curRAddr = receiveAddr_[procI];
if (!curRAddr.empty())
{
Field<Type> receiveBuf(curRAddr.size());
// Opt: reconsider mode of communication
IPstream::read
(
Pstream::blocking,
procI,
reinterpret_cast<char*>(receiveBuf.begin()),
receiveBuf.byteSize()
);
// Insert received information
forAll (curRAddr, i)
{
expandField[curRAddr[i]] = receiveBuf[i];
}
}
}
// Expanded field complete, send required data to other processors
for (label procI = 1; procI < Pstream::nProcs(); procI++)
{
const labelList& curSAddr = sendAddr_[procI];
if (!curSAddr.empty())
{
Field<Type> sendBuf(curSAddr.size());
forAll (curSAddr, i)
{
sendBuf[i] = expandField[curSAddr[i]];
}
// Opt: reconsider mode of communication
OPstream::write
(
Pstream::blocking,
procI,
reinterpret_cast<const char*>(sendBuf.begin()),
sendBuf.byteSize()
);
}
}
// Note: different from ggi patch: field reduction happens within
// fastReduce. HJ, 26/Jun/2011
const labelList& sza = shadowInterface().zoneAddressing();
tmp<Field<Type> > tredField
(
new Field<Type>(sza.size(), pTraits<Type>::zero)
);
Field<Type>& redField = tredField();
// Select elements from shadow zone addressing
forAll (sza, i)
{
redField[i] = expandField[sza[i]];
}
return tredField;
}
else
{
// Send local data to master and receive remote data
// If patch is empty, communication is avoided
// HJ, 4/Jun/2011
if (size())
{
// Opt: reconsider mode of communication
OPstream::write
(
Pstream::blocking,
Pstream::masterNo(),
reinterpret_cast<const char*>(ff.begin()),
ff.byteSize()
);
}
// Prepare to receive remote data
const labelList& za = zoneAddressing();
tmp<Field<Type> > treceiveBuf
(
new Field<Type>(za.size(), pTraits<Type>::zero)
);
Field<Type>& receiveBuf = treceiveBuf();
if (!za.empty())
{
// Opt: reconsider mode of communication
IPstream::read
(
Pstream::blocking,
Pstream::masterNo(),
reinterpret_cast<char*>(receiveBuf.begin()),
receiveBuf.byteSize()
);
// Note: different from ggi patch: field reduction happens within
// fastReduce. HJ, 26/Jun/2011
}
return treceiveBuf;
}
}
template<class Type> template<class Type>
tmp<Field<Type> > ggiGAMGInterface::expand(const UList<Type>& pd) const tmp<Field<Type> > ggiGAMGInterface::expand(const UList<Type>& pd) const
{ {

View file

@ -144,6 +144,19 @@ void Foam::polyBoundaryMesh::clearAddressing()
void Foam::polyBoundaryMesh::calcGeometry() void Foam::polyBoundaryMesh::calcGeometry()
{ {
// Calculation of addressing, with communication
// HJ, 12/Jun/2011
forAll(*this, patchi)
{
operator[](patchi).initAddressing();
}
forAll(*this, patchi)
{
operator[](patchi).calcAddressing();
}
// Calculation of geometry with communications
forAll(*this, patchi) forAll(*this, patchi)
{ {
operator[](patchi).initGeometry(); operator[](patchi).initGeometry();

View file

@ -78,7 +78,10 @@ class polyBoundaryMesh
//- Create identity map //- Create identity map
static labelList ident(const label len); static labelList ident(const label len);
//- Calculate the geometry for the patches (transformation tensors etc.) //- Calculate the geometry for the patches,
// eg transformation tensors etc.
// Enhanced for parallel addressing calculations
// HJ, 11/Jun/2011
void calcGeometry(); void calcGeometry();
//- Disallow construct as copy //- Disallow construct as copy

View file

@ -86,6 +86,12 @@ protected:
const scalar absTol = matchTol_ const scalar absTol = matchTol_
) const; ) const;
//- Initialise the calculation of the patch addressing
virtual void initAddressing() = 0;
//- Calculate the patch addressing
virtual void calcAddressing() = 0;
//- Initialise the calculation of the patch geometry //- Initialise the calculation of the patch geometry
virtual void initGeometry() = 0; virtual void initGeometry() = 0;

View file

@ -950,6 +950,18 @@ Foam::cyclicPolyPatch::~cyclicPolyPatch()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::cyclicPolyPatch::initAddressing()
{
polyPatch::initAddressing();
}
void Foam::cyclicPolyPatch::calcAddressing()
{
polyPatch::calcAddressing();
}
void Foam::cyclicPolyPatch::initGeometry() void Foam::cyclicPolyPatch::initGeometry()
{ {
polyPatch::initGeometry(); polyPatch::initGeometry();
@ -959,6 +971,7 @@ void Foam::cyclicPolyPatch::initGeometry()
void Foam::cyclicPolyPatch::calcGeometry() void Foam::cyclicPolyPatch::calcGeometry()
{ {
polyPatch::calcGeometry(); polyPatch::calcGeometry();
calcTransforms(); calcTransforms();
} }

View file

@ -178,6 +178,12 @@ protected:
// Protected Member functions // Protected Member functions
//- Initialise the calculation of the patch addressing
virtual void initAddressing();
//- Calculate the patch addressing
virtual void calcAddressing();
//- Initialise the calculation of the patch geometry //- Initialise the calculation of the patch geometry
virtual void initGeometry(); virtual void initGeometry();

View file

@ -51,6 +51,15 @@ namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
bool Foam::ggiPolyPatch::active() const
{
polyPatchID shadow(shadowName_, boundaryMesh());
faceZoneID zone(zoneName_, boundaryMesh().mesh().faceZones());
return shadow.active() && zone.active();
}
void Foam::ggiPolyPatch::calcZoneAddressing() const void Foam::ggiPolyPatch::calcZoneAddressing() const
{ {
// Calculate patch-to-zone addressing // Calculate patch-to-zone addressing
@ -61,18 +70,24 @@ void Foam::ggiPolyPatch::calcZoneAddressing() const
<< abort(FatalError); << abort(FatalError);
} }
if (debug)
{
Pout<< "ggiPolyPatch::calcZoneAddressing() const for patch "
<< index() << endl;
}
// Calculate patch-to-zone addressing // Calculate patch-to-zone addressing
zoneAddressingPtr_ = new labelList(size()); zoneAddressingPtr_ = new labelList(size());
labelList& addr = *zoneAddressingPtr_; labelList& zAddr = *zoneAddressingPtr_;
const faceZone& myZone = zone(); const faceZone& myZone = zone();
for (label i = 0; i < size(); i++) for (label i = 0; i < size(); i++)
{ {
addr[i] = myZone.whichFace(start() + i); zAddr[i] = myZone.whichFace(start() + i);
} }
// Check zone addressing // Check zone addressing
if (addr.size() > 0 && min(addr) < 0) if (zAddr.size() > 0 && min(zAddr) < 0)
{ {
FatalErrorIn("void ggiPolyPatch::calcZoneAddressing() const") FatalErrorIn("void ggiPolyPatch::calcZoneAddressing() const")
<< "Problem with patch-to zone addressing: some patch faces " << "Problem with patch-to zone addressing: some patch faces "
@ -82,6 +97,85 @@ void Foam::ggiPolyPatch::calcZoneAddressing() const
} }
void Foam::ggiPolyPatch::calcRemoteZoneAddressing() const
{
// Calculate patch-to-zone addressing
if (remoteZoneAddressingPtr_)
{
FatalErrorIn("void ggiPolyPatch::calcRemoteZoneAddressing() const")
<< "Patch to remote zone addressing already calculated"
<< abort(FatalError);
}
if (debug)
{
Pout<< "ggiPolyPatch::calcRemoteZoneAddressing() const for patch "
<< index() << endl;
}
// Once zone addressing is established, visit the opposite side and find
// out which face data is needed for interpolation
boolList usedShadows(shadow().zone().size(), false);
const labelList& zAddr = zoneAddressing();
if (master())
{
const labelListList& addr = patchToPatch().masterAddr();
forAll (zAddr, mfI)
{
const labelList& nbrs = addr[zAddr[mfI]];
forAll (nbrs, nbrI)
{
usedShadows[nbrs[nbrI]] = true;
}
}
}
else
{
const labelListList& addr = patchToPatch().slaveAddr();
forAll (zAddr, mfI)
{
const labelList& nbrs = addr[zAddr[mfI]];
forAll (nbrs, nbrI)
{
usedShadows[nbrs[nbrI]] = true;
}
}
}
// Count and pick up shadow indices
label nShadows = 0;
forAll (usedShadows, sI)
{
if (usedShadows[sI])
{
nShadows++;
}
}
remoteZoneAddressingPtr_ = new labelList(nShadows);
labelList& rza = *remoteZoneAddressingPtr_;
// Reset counter for re-use
nShadows = 0;
forAll (usedShadows, sI)
{
if (usedShadows[sI])
{
rza[nShadows] = sI;
nShadows++;
}
}
}
void Foam::ggiPolyPatch::calcPatchToPatch() const void Foam::ggiPolyPatch::calcPatchToPatch() const
{ {
// Create patch-to-patch interpolation // Create patch-to-patch interpolation
@ -98,31 +192,29 @@ void Foam::ggiPolyPatch::calcPatchToPatch() const
patchToPatchPtr_ = patchToPatchPtr_ =
new ggiZoneInterpolation new ggiZoneInterpolation
( (
zone()(), zone()(), // This zone reference
shadow().zone()(), shadow().zone()(), // This shadow zone reference
forwardT(), forwardT(),
reverseT(), reverseT(),
shadow().separation(), // Slave-to-master separation. Bug fix shadow().separation(), // Slave-to-master separation. Bug fix
0, // Non-overlapping face tolerances 0, // Non-overlapping face tolerances
0, // HJ, 24/Oct/2008 0, // HJ, 24/Oct/2008
true, // Rescale weighting factors. Bug fix, MB. true, // Rescale weighting factors. Bug fix, MB.
ggiInterpolation::AABB // ggiInterpolation::AABB
ggiInterpolation::BB_OCTREE // Octree search, MB.
); );
// Abort immediatly if uncovered faces are present and the option // Abort immediately if uncovered faces are present and the option
// bridgeOverlap is not set. // bridgeOverlap is not set.
if if
( (
( (
patchToPatch().uncoveredMasterFaces().size() > 0 patchToPatch().uncoveredMasterFaces().size() > 0
&& && !bridgeOverlap()
!bridgeOverlap()
) )
|| || (
(
patchToPatch().uncoveredSlaveFaces().size() > 0 patchToPatch().uncoveredSlaveFaces().size() > 0
&& && !shadow().bridgeOverlap()
!shadow().bridgeOverlap()
) )
) )
{ {
@ -144,43 +236,6 @@ void Foam::ggiPolyPatch::calcPatchToPatch() const
} }
void Foam::ggiPolyPatch::calcLocalParallel() const
{
// Calculate patch-to-zone addressing
if (localParallelPtr_)
{
FatalErrorIn("void ggiPolyPatch::calcLocalParallel() const")
<< "Local parallel switch already calculated"
<< abort(FatalError);
}
localParallelPtr_ = new bool(false);
bool& emptyOrComplete = *localParallelPtr_;
// Calculate localisation on master and shadow
emptyOrComplete =
(zone().size() == size() && shadow().zone().size() == shadow().size())
|| (size() == 0 && shadow().size() == 0);
reduce(emptyOrComplete, andOp<bool>());
if (debug && Pstream::parRun())
{
Info<< "GGI patch Master: " << name()
<< " Slave: " << shadowName() << " is ";
if (emptyOrComplete)
{
Info<< "local parallel" << endl;
}
else
{
Info<< "split between multiple processors" << endl;
}
}
}
void Foam::ggiPolyPatch::calcReconFaceCellCentres() const void Foam::ggiPolyPatch::calcReconFaceCellCentres() const
{ {
// Create neighbouring face centres using interpolation // Create neighbouring face centres using interpolation
@ -209,12 +264,162 @@ void Foam::ggiPolyPatch::calcReconFaceCellCentres() const
} }
void Foam::ggiPolyPatch::calcLocalParallel() const
{
// Calculate patch-to-zone addressing
if (localParallelPtr_)
{
FatalErrorIn("void ggiPolyPatch::calcLocalParallel() const")
<< "Local parallel switch already calculated"
<< abort(FatalError);
}
localParallelPtr_ = new bool(false);
bool& emptyOrComplete = *localParallelPtr_;
// If running in serial, all GGIs are local parallel
// HJ, 1/Jun/2011
if (!Pstream::parRun())
{
return;
}
// Calculate localisation on master and shadow
emptyOrComplete =
(zone().size() == size() && shadow().zone().size() == shadow().size())
|| (size() == 0 && shadow().size() == 0);
reduce(emptyOrComplete, andOp<bool>());
if (debug && Pstream::parRun())
{
Info<< "GGI patch Master: " << name()
<< " Slave: " << shadowName() << " is ";
if (emptyOrComplete)
{
Info<< "local parallel" << endl;
}
else
{
Info<< "split between multiple processors" << endl;
}
}
}
void Foam::ggiPolyPatch::calcSendReceive() const
{
// Note: all processors will execute calcSendReceive but only master will
// hold the information. Therefore, pointers on slave processors
// will remain meaningless, but for purposes of consistency
// (of the calc-call) they will be set to zero-sized array
// HJ, 4/Jun/2011
if (receiveAddrPtr_ || sendAddrPtr_)
{
FatalErrorIn("void ggiPolyPatch::calcSendReceive() const")
<< "Send-receive addressing already calculated"
<< abort(FatalError);
}
if (debug)
{
Pout<< "ggiPolyPatch::calcSendReceive() const for patch "
<< index() << endl;
}
if (!Pstream::parRun())
{
FatalErrorIn("void ggiPolyPatch::calcSendReceive() const")
<< "Requested calculation of send-receive addressing for a "
<< "serial run. This is not allowed"
<< abort(FatalError);
}
// Master will receive and store the maps
if (Pstream::master())
{
receiveAddrPtr_ = new labelListList(Pstream::nProcs());
labelListList& rAddr = *receiveAddrPtr_;
sendAddrPtr_ = new labelListList(Pstream::nProcs());
labelListList& sAddr = *sendAddrPtr_;
// Insert master
rAddr[0] = zoneAddressing();
for (label procI = 1; procI < Pstream::nProcs(); procI++)
{
// Note: must use normal comms because the size of the
// communicated lists is unknown on the receiving side
// HJ, 4/Jun/2011
// Opt: reconsider mode of communication
IPstream ip(Pstream::scheduled, procI);
rAddr[procI] = labelList(ip);
sAddr[procI] = labelList(ip);
}
}
else
{
// Create dummy pointers: only master processor stores maps
receiveAddrPtr_ = new labelListList();
sendAddrPtr_ = new labelListList();
// Send information to master
const labelList& za = zoneAddressing();
const labelList& ra = remoteZoneAddressing();
// Note: must use normal comms because the size of the
// communicated lists is unknown on the receiving side
// HJ, 4/Jun/2011
// Opt: reconsider mode of communication
OPstream op(Pstream::scheduled, Pstream::masterNo());
// Send local and remote addressing to master
op << za << ra;
}
}
const Foam::labelListList& Foam::ggiPolyPatch::receiveAddr() const
{
if (!receiveAddrPtr_)
{
calcSendReceive();
}
return *receiveAddrPtr_;
}
const Foam::labelListList& Foam::ggiPolyPatch::sendAddr() const
{
if (!sendAddrPtr_)
{
calcSendReceive();
}
return *sendAddrPtr_;
}
void Foam::ggiPolyPatch::clearGeom() void Foam::ggiPolyPatch::clearGeom()
{ {
deleteDemandDrivenData(patchToPatchPtr_);
deleteDemandDrivenData(zoneAddressingPtr_);
deleteDemandDrivenData(reconFaceCellCentresPtr_); deleteDemandDrivenData(reconFaceCellCentresPtr_);
// Remote addressing and send-receive maps depend on the local
// position. Therefore, it needs to be recalculated at mesh motion.
// Local zone addressing does not change with mesh motion
// HJ, 23/Jun/2011
deleteDemandDrivenData(remoteZoneAddressingPtr_);
deleteDemandDrivenData(receiveAddrPtr_);
deleteDemandDrivenData(sendAddrPtr_);
} }
@ -222,6 +427,8 @@ void Foam::ggiPolyPatch::clearOut()
{ {
clearGeom(); clearGeom();
deleteDemandDrivenData(zoneAddressingPtr_);
deleteDemandDrivenData(patchToPatchPtr_);
deleteDemandDrivenData(localParallelPtr_); deleteDemandDrivenData(localParallelPtr_);
} }
@ -245,8 +452,11 @@ Foam::ggiPolyPatch::ggiPolyPatch
zoneIndex_(-1), zoneIndex_(-1),
patchToPatchPtr_(NULL), patchToPatchPtr_(NULL),
zoneAddressingPtr_(NULL), zoneAddressingPtr_(NULL),
remoteZoneAddressingPtr_(NULL),
reconFaceCellCentresPtr_(NULL),
localParallelPtr_(NULL), localParallelPtr_(NULL),
reconFaceCellCentresPtr_(NULL) receiveAddrPtr_(NULL),
sendAddrPtr_(NULL)
{} {}
@ -270,8 +480,11 @@ Foam::ggiPolyPatch::ggiPolyPatch
zoneIndex_(-1), zoneIndex_(-1),
patchToPatchPtr_(NULL), patchToPatchPtr_(NULL),
zoneAddressingPtr_(NULL), zoneAddressingPtr_(NULL),
remoteZoneAddressingPtr_(NULL),
reconFaceCellCentresPtr_(NULL),
localParallelPtr_(NULL), localParallelPtr_(NULL),
reconFaceCellCentresPtr_(NULL) receiveAddrPtr_(NULL),
sendAddrPtr_(NULL)
{} {}
@ -291,8 +504,11 @@ Foam::ggiPolyPatch::ggiPolyPatch
zoneIndex_(-1), zoneIndex_(-1),
patchToPatchPtr_(NULL), patchToPatchPtr_(NULL),
zoneAddressingPtr_(NULL), zoneAddressingPtr_(NULL),
remoteZoneAddressingPtr_(NULL),
reconFaceCellCentresPtr_(NULL),
localParallelPtr_(NULL), localParallelPtr_(NULL),
reconFaceCellCentresPtr_(NULL) receiveAddrPtr_(NULL),
sendAddrPtr_(NULL)
{} {}
@ -310,8 +526,11 @@ Foam::ggiPolyPatch::ggiPolyPatch
zoneIndex_(-1), zoneIndex_(-1),
patchToPatchPtr_(NULL), patchToPatchPtr_(NULL),
zoneAddressingPtr_(NULL), zoneAddressingPtr_(NULL),
remoteZoneAddressingPtr_(NULL),
reconFaceCellCentresPtr_(NULL),
localParallelPtr_(NULL), localParallelPtr_(NULL),
reconFaceCellCentresPtr_(NULL) receiveAddrPtr_(NULL),
sendAddrPtr_(NULL)
{} {}
@ -333,8 +552,11 @@ Foam::ggiPolyPatch::ggiPolyPatch
zoneIndex_(-1), zoneIndex_(-1),
patchToPatchPtr_(NULL), patchToPatchPtr_(NULL),
zoneAddressingPtr_(NULL), zoneAddressingPtr_(NULL),
remoteZoneAddressingPtr_(NULL),
reconFaceCellCentresPtr_(NULL),
localParallelPtr_(NULL), localParallelPtr_(NULL),
reconFaceCellCentresPtr_(NULL) receiveAddrPtr_(NULL),
sendAddrPtr_(NULL)
{} {}
@ -437,6 +659,17 @@ const Foam::labelList& Foam::ggiPolyPatch::zoneAddressing() const
} }
const Foam::labelList& Foam::ggiPolyPatch::remoteZoneAddressing() const
{
if (!remoteZoneAddressingPtr_)
{
calcRemoteZoneAddressing();
}
return *remoteZoneAddressingPtr_;
}
bool Foam::ggiPolyPatch::localParallel() const bool Foam::ggiPolyPatch::localParallel() const
{ {
// Calculate patch-to-zone addressing // Calculate patch-to-zone addressing
@ -483,8 +716,45 @@ const Foam::vectorField& Foam::ggiPolyPatch::reconFaceCellCentres() const
} }
void Foam::ggiPolyPatch::initAddressing()
{
if (active())
{
// Force zone addressing first
zoneAddressing();
remoteZoneAddressing();
if (Pstream::parRun() && !localParallel())
{
sendAddr();
}
}
polyPatch::initAddressing();
}
void Foam::ggiPolyPatch::calcAddressing()
{
polyPatch::calcAddressing();
}
void Foam::ggiPolyPatch::initGeometry() void Foam::ggiPolyPatch::initGeometry()
{ {
// Communication is allowed either before or after processor
// patch comms. HJ, 11/Jul/2011
if (active())
{
calcTransforms();
// Note: Only master calculates recon; slave uses master interpolation
if (master())
{
reconFaceCellCentres();
}
}
polyPatch::initGeometry(); polyPatch::initGeometry();
} }
@ -497,18 +767,40 @@ void Foam::ggiPolyPatch::calcGeometry()
// reconFaceCellCentres in order to correctly set the transformation // reconFaceCellCentres in order to correctly set the transformation
// in the interpolation routines. // in the interpolation routines.
// HJ, 3/Jul/2009 // HJ, 3/Jul/2009
calcTransforms();
// Reconstruct the cell face centres
if (patchToPatchPtr_ && master())
{
reconFaceCellCentres();
}
} }
void Foam::ggiPolyPatch::initMovePoints(const pointField& p) void Foam::ggiPolyPatch::initMovePoints(const pointField& p)
{ {
clearGeom();
// Calculate transforms on mesh motion?
calcTransforms();
// Update interpolation for new relative position of GGI interfaces
if (patchToPatchPtr_)
{
patchToPatchPtr_->movePoints();
}
// Recalculate send and receive maps
if (active())
{
// Force zone addressing first
zoneAddressing();
remoteZoneAddressing();
if (Pstream::parRun() && !localParallel())
{
sendAddr();
}
}
if (active() && master())
{
reconFaceCellCentres();
}
polyPatch::initMovePoints(p); polyPatch::initMovePoints(p);
} }
@ -516,7 +808,6 @@ void Foam::ggiPolyPatch::initMovePoints(const pointField& p)
void Foam::ggiPolyPatch::movePoints(const pointField& p) void Foam::ggiPolyPatch::movePoints(const pointField& p)
{ {
polyPatch::movePoints(p); polyPatch::movePoints(p);
clearGeom();
} }

View file

@ -85,25 +85,43 @@ class ggiPolyPatch
//- Patch-to-zone addressing //- Patch-to-zone addressing
mutable labelList* zoneAddressingPtr_; mutable labelList* zoneAddressingPtr_;
//- Is the patch localised on a single processor //- Remote zone addressing: data needed for interpolation
// (single processor in a parallel run)? mutable labelList* remoteZoneAddressingPtr_;
// Used for parallel optimisation
mutable bool* localParallelPtr_;
//- Reconstructed patch neighbour cell centres //- Reconstructed patch neighbour cell centres
mutable vectorField* reconFaceCellCentresPtr_; mutable vectorField* reconFaceCellCentresPtr_;
// Parallel communication optimisation, stored on master processor
//- Is the patch localised on a single processor
// (single processor in a parallel run)?
// Used for parallel optimisation
mutable bool* localParallelPtr_;
//- List of zone faces indices received from each processor
mutable labelListList* receiveAddrPtr_;
//- List of zone faces indices to send to each processor
mutable labelListList* sendAddrPtr_;
// Private member functions // Private member functions
//- Is the GGI active& (zone and shadow present)
bool active() const;
//- Calculate patch-to-zone addressing //- Calculate patch-to-zone addressing
virtual void calcZoneAddressing() const; virtual void calcZoneAddressing() const;
//- Calculate remote patch-to-zone addressing
virtual void calcRemoteZoneAddressing() const;
//- Calculate interpolation //- Calculate interpolation
virtual void calcPatchToPatch() const; virtual void calcPatchToPatch() const;
//- Calculate local parallel switch
void calcLocalParallel() const; // Geometry
//- Calculate reconstructed cell centres //- Calculate reconstructed cell centres
void calcReconFaceCellCentres() const; void calcReconFaceCellCentres() const;
@ -111,6 +129,25 @@ class ggiPolyPatch
//- Force calculation of transformation tensors //- Force calculation of transformation tensors
virtual void calcTransforms(); virtual void calcTransforms();
// Parallel communication optimisation, stored on master processor
//- Calculate local parallel switch
void calcLocalParallel() const;
//- Calculate send and receive addressing
void calcSendReceive() const;
//- Return receive addressing
const labelListList& receiveAddr() const;
//- Return send addressing
const labelListList& sendAddr() const;
// Memory management
//- Clear geometry //- Clear geometry
void clearGeom(); void clearGeom();
@ -122,6 +159,12 @@ protected:
// Protected Member functions // Protected Member functions
//- Initialise the calculation of the patch addressing
virtual void initAddressing();
//- Calculate the patch addressing
virtual void calcAddressing();
//- Initialise the calculation of the patch geometry //- Initialise the calculation of the patch geometry
virtual void initGeometry(); virtual void initGeometry();
@ -281,6 +324,9 @@ public:
//- Return patch-to-zone addressing //- Return patch-to-zone addressing
const labelList& zoneAddressing() const; const labelList& zoneAddressing() const;
//- Return remote patch-to-zone addressing
const labelList& remoteZoneAddressing() const;
//- Is the patch localised on a single processor //- Is the patch localised on a single processor
bool localParallel() const; bool localParallel() const;
@ -289,13 +335,21 @@ public:
const ggiZoneInterpolation& patchToPatch() const; const ggiZoneInterpolation& patchToPatch() const;
//- Expand face field to full zone size, including reduction //- Expand face field to full zone size, including reduction
// New. HJ, 12/Jun/2011
template<class Type>
tmp<Field<Type> > fastExpand(const Field<Type>& pf) const;
//- Expand face field to full zone size, including reduction
// Obsolete. HJ, 12/Jun/2011
template<class Type> template<class Type>
tmp<Field<Type> > expand(const Field<Type>& pf) const; tmp<Field<Type> > expand(const Field<Type>& pf) const;
//- Filter zone field to patch size //- Filter zone field to patch size
// Obsolete. HJ, 12/Jun/2011
template<class Type> template<class Type>
tmp<Field<Type> > filter(const Field<Type>& zf) const; tmp<Field<Type> > filter(const Field<Type>& zf) const;
//- Interpolate face field: given field on a the shadow side, //- Interpolate face field: given field on a the shadow side,
// create an interpolated field on this side // create an interpolated field on this side
template<class Type> template<class Type>

View file

@ -28,26 +28,193 @@ Author
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "ggiPolyPatch.H" #include "ggiPolyPatch.H"
#include "OSspecific.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// New. HJ, 12/Jun/2011
template<class Type> template<class Type>
Foam::tmp<Foam::Field<Type> > Foam::ggiPolyPatch::expand Foam::tmp<Foam::Field<Type> > Foam::ggiPolyPatch::fastExpand
( (
const Field<Type>& pf const Field<Type>& ff
) const ) const
{ {
// Check and expand the field from patch size to zone size // Check and expand the field from patch size to zone size
if (pf.size() != size()) // with communication
// Algorithm:
// 1) Master processor holds maps of all zone addressing (data provided)
// and all remote zone addressing (data required)
// 2) Each processor will send the locally active data to the master
// 3) Master assembles all the data
// 4) Master sends to all processors the data they need to receive
//
// Notes:
// A) If the size of zone addressing is zero, data is not sent
// B) Communicated data on each processor has the size of live faces
// C) Expanded data will be equal to actual data fronm other processors
// only for the faces marked in remote; for other faces, it will be
// equal to zero
// D) On processor zero, complete data is available
// HJ, 4/Jun/2011
if (ff.size() != size())
{
FatalErrorIn
(
"tmp<Field<Type> > ggiPolyPatch::fastExpand"
"("
" const Field<Type>& ff"
") const"
) << "Incorrect patch field size. Field size: "
<< ff.size() << " patch size: " << size()
<< abort(FatalError);
}
if (localParallel())
{
FatalErrorIn
(
"tmp<Field<Type> > ggiPolyPatch::fastExpand"
"("
" const Field<Type>& ff"
") const"
) << "Requested expand on local parallel. This is not allowed"
<< abort(FatalError);
}
// Expand the field to zone size
tmp<Field<Type> > texpandField
(
new Field<Type>(zone().size(), pTraits<Type>::zero)
);
Field<Type>& expandField = texpandField();
if (Pstream::master())
{
// Insert master processor
const labelList& za = zoneAddressing();
forAll (za, i)
{
expandField[za[i]] = ff[i];
}
// Master receives and inserts data from all processors for which
// receiveAddr contains entries
for (label procI = 1; procI < Pstream::nProcs(); procI++)
{
const labelList& curRAddr = receiveAddr()[procI];
if (!curRAddr.empty())
{
Field<Type> receiveBuf(curRAddr.size());
// Opt: reconsider mode of communication
IPstream::read
(
Pstream::blocking,
procI,
reinterpret_cast<char*>(receiveBuf.begin()),
receiveBuf.byteSize()
);
// Insert received information
forAll (curRAddr, i)
{
expandField[curRAddr[i]] = receiveBuf[i];
}
}
}
// Expanded field complete, send required data to other processors
for (label procI = 1; procI < Pstream::nProcs(); procI++)
{
const labelList& curSAddr = sendAddr()[procI];
if (!curSAddr.empty())
{
Field<Type> sendBuf(curSAddr.size());
forAll (curSAddr, i)
{
sendBuf[i] = expandField[curSAddr[i]];
}
// Opt: reconsider mode of communication
OPstream::write
(
Pstream::blocking,
procI,
reinterpret_cast<const char*>(sendBuf.begin()),
sendBuf.byteSize()
);
}
}
}
else
{
// Send local data to master and receive remote data
// If patch is empty, communication is avoided
// HJ, 4/Jun/2011
if (size())
{
// Opt: reconsider mode of communication
OPstream::write
(
Pstream::blocking,
Pstream::masterNo(),
reinterpret_cast<const char*>(ff.begin()),
ff.byteSize()
);
}
// Prepare to receive remote data
const labelList& rza = remoteZoneAddressing();
if (!rza.empty())
{
Field<Type> receiveBuf(rza.size());
// Opt: reconsider mode of communication
IPstream::read
(
Pstream::blocking,
Pstream::masterNo(),
reinterpret_cast<char*>(receiveBuf.begin()),
receiveBuf.byteSize()
);
// Insert the data into expanded field
forAll (rza, i)
{
expandField[rza[i]] = receiveBuf[i];
}
}
}
return texpandField;
}
// Obsolete. HJ, 12/Jun/2011
template<class Type>
Foam::tmp<Foam::Field<Type> > Foam::ggiPolyPatch::expand
(
const Field<Type>& ff
) const
{
// Check and expand the field from patch size to zone size
if (ff.size() != size())
{ {
FatalErrorIn FatalErrorIn
( (
"tmp<Field<Type> > ggiPolyPatch::expand" "tmp<Field<Type> > ggiPolyPatch::expand"
"(" "("
" const Field<Type>& pf" " const Field<Type>& ff"
") const" ") const"
) << "Incorrect patch field size. Field size: " ) << "Incorrect patch field size. Field size: "
<< pf.size() << " patch size: " << size() << ff.size() << " patch size: " << size()
<< abort(FatalError); << abort(FatalError);
} }
@ -63,7 +230,7 @@ Foam::tmp<Foam::Field<Type> > Foam::ggiPolyPatch::expand
forAll (addr, i) forAll (addr, i)
{ {
expandField[addr[i]] = pf[i]; expandField[addr[i]] = ff[i];
} }
// Parallel data exchange: update surface field on all processors // Parallel data exchange: update surface field on all processors
@ -79,6 +246,7 @@ Foam::tmp<Foam::Field<Type> > Foam::ggiPolyPatch::expand
} }
// Obsolete. HJ, 12/Jun/2011
template<class Type> template<class Type>
Foam::tmp<Foam::Field<Type> > Foam::ggiPolyPatch::filter Foam::tmp<Foam::Field<Type> > Foam::ggiPolyPatch::filter
( (
@ -121,25 +289,82 @@ Foam::tmp<Foam::Field<Type> > Foam::ggiPolyPatch::filter
template<class Type> template<class Type>
Foam::tmp<Foam::Field<Type> > Foam::ggiPolyPatch::interpolate Foam::tmp<Foam::Field<Type> > Foam::ggiPolyPatch::interpolate
( (
const Field<Type>& pf const Field<Type>& ff
) const ) const
{ {
// Check and expand the field from patch size to zone size // Check and expand the field from patch size to zone size
if (pf.size() != shadow().size()) if (ff.size() != shadow().size())
{ {
FatalErrorIn FatalErrorIn
( (
"tmp<Field<Type> > ggiPolyPatch::interpolate" "tmp<Field<Type> > ggiPolyPatch::interpolate"
"(" "("
" const Field<Type>& pf" " const Field<Type>& ff"
") const" ") const"
) << "Incorrect slave patch field size. Field size: " ) << "Incorrect slave patch field size. Field size: "
<< pf.size() << " patch size: " << shadow().size() << ff.size() << " patch size: " << shadow().size()
<< abort(FatalError); << abort(FatalError);
} }
# if 1
// New. HJ, 12/Jun/2011
if (localParallel())
{
// No expansion or filtering needed. HJ, 4/Jun/2011
// Interpolate field
if (master())
{
return patchToPatch().slaveToMaster(ff);
}
else
{
return patchToPatch().masterToSlave(ff);
}
}
else
{
// Note: fast expand is always done on the local side
// HJ, 24/Jun/2011
Field<Type> expandField = fastExpand(ff);
tmp<Field<Type> > tresult(new Field<Type>(size()));
Field<Type>& result = tresult();
if (master())
{
patchToPatch().maskedSlaveToMaster
(
expandField,
result,
zoneAddressing()
);
}
else
{
patchToPatch().maskedMasterToSlave
(
expandField,
result,
zoneAddressing()
);
}
return tresult;
}
# else
// Old treatment
// Obsolete. HJ, 12/Jun/2011
// Expand the field to zone size // Expand the field to zone size
Field<Type> expandField = shadow().expand(pf); // Note: with full fields it is the shadow side that does
// the expand. This is different than fastExpand because
// the addressing is stored remotely.
// HJ, 24/Jun/2011
Field<Type> expandField = shadow().expand(ff);
Field<Type> zoneField; Field<Type> zoneField;
@ -154,17 +379,19 @@ Foam::tmp<Foam::Field<Type> > Foam::ggiPolyPatch::interpolate
} }
return this->filter(zoneField); return this->filter(zoneField);
# endif
} }
template<class Type> template<class Type>
Foam::tmp<Foam::Field<Type> > Foam::ggiPolyPatch::interpolate Foam::tmp<Foam::Field<Type> > Foam::ggiPolyPatch::interpolate
( (
const tmp<Field<Type> >& tpf const tmp<Field<Type> >& tff
) const ) const
{ {
tmp<Field<Type> > tint = interpolate(tpf()); tmp<Field<Type> > tint = interpolate(tff());
tpf.clear(); tff.clear();
return tint; return tint;
} }
@ -178,7 +405,43 @@ void Foam::ggiPolyPatch::bridge
{ {
if (bridgeOverlap()) if (bridgeOverlap())
{ {
// Parallelisation # ifdef FAST_PARALLEL_GGI
if (localParallel())
{
if (master())
{
patchToPatch().bridgeMaster(bridgeField, ff);
}
else
{
patchToPatch().bridgeSlave(bridgeField, ff);
}
}
else
{
// Note: since bridging is only a local operation
if (master())
{
patchToPatch().maskedBridgeMaster
(
bridgeField,
ff,
zoneAddressing()
);
}
else
{
patchToPatch().maskedBridgeSlave
(
bridgeField,
ff,
zoneAddressing()
);
}
}
# else
// Expand the field to zone size // Expand the field to zone size
Field<Type> expandBridge = this->expand(bridgeField); Field<Type> expandBridge = this->expand(bridgeField);
@ -200,15 +463,8 @@ void Foam::ggiPolyPatch::bridge
{ {
ff[i] = expandField[addr[i]]; ff[i] = expandField[addr[i]];
} }
}
else # endif
{
// HJ, temporary
InfoIn
(
"void bridge(const Field<Type>& bridgeField, "
"Field<Type>& ff) const"
) << "Bridging is switched off " << endl;
} }
} }

View file

@ -147,6 +147,12 @@ protected:
// Protected Member functions // Protected Member functions
//- Initialise the calculation of the patch addressing
virtual void initAddressing();
//- Calculate the patch addressing
virtual void calcAddressing();
//- Initialise the calculation of the patch geometry //- Initialise the calculation of the patch geometry
virtual void initGeometry(); virtual void initGeometry();

View file

@ -175,8 +175,7 @@ void Foam::overlapGgiPolyPatch::calcPatchToPatch() const
if if
( (
patchToPatch().uncoveredMasterFaces().size() > 0 patchToPatch().uncoveredMasterFaces().size() > 0
|| || patchToPatch().uncoveredSlaveFaces().size() > 0
patchToPatch().uncoveredSlaveFaces().size() > 0
) )
{ {
FatalErrorIn("void overlapGgiPolyPatch::calcPatchToPatch() const") FatalErrorIn("void overlapGgiPolyPatch::calcPatchToPatch() const")
@ -309,6 +308,18 @@ Foam::overlapGgiPolyPatch::reconFaceCellCentres() const
} }
void Foam::overlapGgiPolyPatch::initAddressing()
{
polyPatch::initAddressing();
}
void Foam::overlapGgiPolyPatch::calcAddressing()
{
polyPatch::calcAddressing();
}
void Foam::overlapGgiPolyPatch::initGeometry() void Foam::overlapGgiPolyPatch::initGeometry()
{ {
polyPatch::initGeometry(); polyPatch::initGeometry();

View file

@ -135,6 +135,18 @@ Foam::processorPolyPatch::~processorPolyPatch()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::processorPolyPatch::initAddressing()
{
polyPatch::initAddressing();
}
void Foam::processorPolyPatch::calcAddressing()
{
polyPatch::calcAddressing();
}
void Foam::processorPolyPatch::initGeometry() void Foam::processorPolyPatch::initGeometry()
{ {
if (Pstream::parRun()) if (Pstream::parRun())

View file

@ -92,6 +92,12 @@ protected:
// Protected Member functions // Protected Member functions
//- Initialise the calculation of the patch addressing
virtual void initAddressing();
//- Calculate the patch addressing
virtual void calcAddressing();
//- Initialise the calculation of the patch geometry //- Initialise the calculation of the patch geometry
void initGeometry(); void initGeometry();

View file

@ -79,7 +79,8 @@ void Foam::regionCouplePolyPatch::calcInterpolation() const
{ {
FatalErrorIn("void regionCouplePolyPatch::calcInterpolation() const") FatalErrorIn("void regionCouplePolyPatch::calcInterpolation() const")
<< "Shadow of regionCouple patch " << name() << "Shadow of regionCouple patch " << name()
<< " named " << shadowPatchName() << " is not a regionCouple." << nl << " named " << shadowPatchName()
<< " is not a regionCouple." << nl
<< "This is not allowed. Please check your mesh definition." << "This is not allowed. Please check your mesh definition."
<< abort(FatalError); << abort(FatalError);
} }
@ -153,10 +154,17 @@ void Foam::regionCouplePolyPatch::calcReconFaceCellCentres() const
} }
void Foam::regionCouplePolyPatch::clearGeom() const
{
deleteDemandDrivenData(reconFaceCellCentresPtr_);
}
void Foam::regionCouplePolyPatch::clearOut() const void Foam::regionCouplePolyPatch::clearOut() const
{ {
clearGeom();
deleteDemandDrivenData(patchToPatchPtr_); deleteDemandDrivenData(patchToPatchPtr_);
deleteDemandDrivenData(reconFaceCellCentresPtr_);
} }
@ -173,14 +181,14 @@ Foam::regionCouplePolyPatch::regionCouplePolyPatch
const word& shadowRegionName, const word& shadowRegionName,
const word& shadowPatchName, const word& shadowPatchName,
const bool attached, const bool attached,
const bool attachedWalls const bool isWall
) )
: :
coupledPolyPatch(name, size, start, index, bm), coupledPolyPatch(name, size, start, index, bm),
shadowRegionName_(shadowRegionName), shadowRegionName_(shadowRegionName),
shadowPatchName_(shadowPatchName), shadowPatchName_(shadowPatchName),
attached_(attached), attached_(attached),
attachedWalls_(attachedWalls), isWall_(isWall),
shadowIndex_(-1), shadowIndex_(-1),
patchToPatchPtr_(NULL), patchToPatchPtr_(NULL),
reconFaceCellCentresPtr_(NULL) reconFaceCellCentresPtr_(NULL)
@ -200,7 +208,7 @@ Foam::regionCouplePolyPatch::regionCouplePolyPatch
shadowRegionName_(dict.lookup("shadowRegion")), shadowRegionName_(dict.lookup("shadowRegion")),
shadowPatchName_(dict.lookup("shadowPatch")), shadowPatchName_(dict.lookup("shadowPatch")),
attached_(dict.lookup("attached")), attached_(dict.lookup("attached")),
attachedWalls_(dict.lookup("attachedWalls")), isWall_(dict.lookup("isWall")),
shadowIndex_(-1), shadowIndex_(-1),
patchToPatchPtr_(NULL), patchToPatchPtr_(NULL),
reconFaceCellCentresPtr_(NULL) reconFaceCellCentresPtr_(NULL)
@ -218,7 +226,7 @@ Foam::regionCouplePolyPatch::regionCouplePolyPatch
shadowRegionName_(pp.shadowRegionName_), shadowRegionName_(pp.shadowRegionName_),
shadowPatchName_(pp.shadowPatchName_), shadowPatchName_(pp.shadowPatchName_),
attached_(pp.attached_), attached_(pp.attached_),
attachedWalls_(pp.attachedWalls_), isWall_(pp.isWall_),
shadowIndex_(-1), shadowIndex_(-1),
patchToPatchPtr_(NULL), patchToPatchPtr_(NULL),
reconFaceCellCentresPtr_(NULL) reconFaceCellCentresPtr_(NULL)
@ -239,7 +247,7 @@ Foam::regionCouplePolyPatch::regionCouplePolyPatch
shadowRegionName_(pp.shadowRegionName_), shadowRegionName_(pp.shadowRegionName_),
shadowPatchName_(pp.shadowPatchName_), shadowPatchName_(pp.shadowPatchName_),
attached_(pp.attached_), attached_(pp.attached_),
attachedWalls_(pp.attachedWalls_), isWall_(pp.isWall_),
shadowIndex_(-1), shadowIndex_(-1),
patchToPatchPtr_(NULL), patchToPatchPtr_(NULL),
reconFaceCellCentresPtr_(NULL) reconFaceCellCentresPtr_(NULL)
@ -278,7 +286,11 @@ void Foam::regionCouplePolyPatch::attach() const
{ {
attached_ = true; attached_ = true;
shadow().attach(); shadow().attach();
clearOut();
// Patch-to-patch interpolation does not need to be cleared,
// only face/cell centres and interpolation factors
// HJ, 6/Jun/2011
clearGeom();
} }
} }
@ -289,7 +301,11 @@ void Foam::regionCouplePolyPatch::detach() const
{ {
attached_ = false; attached_ = false;
shadow().detach(); shadow().detach();
clearOut();
// Patch-to-patch interpolation does not need to be cleared,
// only face/cell centres and interpolation factors
// HJ, 6/Jun/2011
clearGeom();
} }
} }
@ -336,6 +352,18 @@ Foam::regionCouplePolyPatch::reconFaceCellCentres() const
} }
void Foam::regionCouplePolyPatch::initAddressing()
{
polyPatch::initAddressing();
}
void Foam::regionCouplePolyPatch::calcAddressing()
{
polyPatch::calcAddressing();
}
void Foam::regionCouplePolyPatch::initGeometry() void Foam::regionCouplePolyPatch::initGeometry()
{ {
polyPatch::initGeometry(); polyPatch::initGeometry();
@ -344,6 +372,7 @@ void Foam::regionCouplePolyPatch::initGeometry()
void Foam::regionCouplePolyPatch::calcGeometry() void Foam::regionCouplePolyPatch::calcGeometry()
{ {
polyPatch::calcGeometry();
// Reconstruct the cell face centres // Reconstruct the cell face centres
// reconFaceCellCentres(); // reconFaceCellCentres();
} }
@ -432,6 +461,8 @@ void Foam::regionCouplePolyPatch::write(Ostream& os) const
<< shadowPatchName_ << token::END_STATEMENT << nl; << shadowPatchName_ << token::END_STATEMENT << nl;
os.writeKeyword("attached") os.writeKeyword("attached")
<< attached_ << token::END_STATEMENT << nl; << attached_ << token::END_STATEMENT << nl;
os.writeKeyword("isWall")
<< isWall_ << token::END_STATEMENT << nl;
} }

View file

@ -70,7 +70,7 @@ class regionCouplePolyPatch
mutable Switch attached_; mutable Switch attached_;
//- Are the region attached walls //- Are the region attached walls
mutable Switch attachedWalls_; Switch isWall_;
//- Shadow patch index. Delayed evaluation for construction //- Shadow patch index. Delayed evaluation for construction
mutable label shadowIndex_; mutable label shadowIndex_;
@ -93,6 +93,12 @@ protected:
// Protected Member functions // Protected Member functions
//- Initialise the calculation of the patch addressing
virtual void initAddressing();
//- Calculate the patch addressing
virtual void calcAddressing();
//- Initialise the calculation of the patch geometry //- Initialise the calculation of the patch geometry
virtual void initGeometry(); virtual void initGeometry();
@ -121,9 +127,13 @@ protected:
//- Calculate reconstructed cell centres //- Calculate reconstructed cell centres
void calcReconFaceCellCentres() const; void calcReconFaceCellCentres() const;
//- Clear geometry
void clearGeom() const;
//- Clear out //- Clear out
void clearOut() const; void clearOut() const;
public: public:
//- Runtime type information //- Runtime type information
@ -237,10 +247,10 @@ public:
return attached_; return attached_;
} }
//AJ: read from dictionary if coupled patch is also a wall // Return true if patch is considered a wall
bool isWall() const bool isWall() const
{ {
return attachedWalls_; return isWall_;
} }
//- Attach regions //- Attach regions

View file

@ -115,6 +115,14 @@ protected:
// The polyPatch geometry initialisation is called by polyBoundaryMesh // The polyPatch geometry initialisation is called by polyBoundaryMesh
friend class polyBoundaryMesh; friend class polyBoundaryMesh;
//- Initialise the calculation of the patch addressing
virtual void initAddressing()
{}
//- Calculate the patch addressing
virtual void calcAddressing()
{}
//- Initialise the calculation of the patch geometry //- Initialise the calculation of the patch geometry
virtual void initGeometry() virtual void initGeometry()
{} {}

View file

@ -119,7 +119,7 @@ public:
const treeBoundBox& cubeBb const treeBoundBox& cubeBb
); );
//- Does triangle intersect plane. Return bool and set intersection segment. //- Does triangle intersect plane. Return bool and set intersection segment
static bool intersect static bool intersect
( (
const point& va0, const point& va0,
@ -133,7 +133,7 @@ public:
point& pInter1 point& pInter1
); );
//- Do triangles intersect. Return bool and set intersection segment. //- Do triangles intersect. Return bool and set intersection segment
static bool intersect static bool intersect
( (
const point& va0, const point& va0,

View file

@ -203,7 +203,7 @@ void Foam::mixerGgiFvMesh::calcMovingMasks() const
forAll (staticPatches, patchI) forAll (staticPatches, patchI)
{ {
const label staticSliderID = const label staticSliderID =
boundaryMesh().findPatchID(movingPatches[patchI]); boundaryMesh().findPatchID(staticPatches[patchI]);
if (staticSliderID < 0) if (staticSliderID < 0)
{ {

View file

@ -1764,7 +1764,9 @@ void Foam::slidingInterface::coupleInterface(polyTopoChange& ref) const
"polyTopoChange& ref) const" "polyTopoChange& ref) const"
) << "Face " << curFaceID << " reduced to less than " ) << "Face " << curFaceID << " reduced to less than "
<< "3 points. Topological/cutting error B." << nl << "3 points. Topological/cutting error B." << nl
<< "Old face: " << oldFace << " new face: " << newFaceLabels << "Old face: " << oldFace << " new face: "
<< newFaceLabels << nl
<< "old points: " << oldFace.points(points)
<< abort(FatalError); << abort(FatalError);
} }

View file

@ -44,7 +44,7 @@ SRFVelocityFvPatchVectorField::SRFVelocityFvPatchVectorField
) )
: :
fixedValueFvPatchVectorField(p, iF), fixedValueFvPatchVectorField(p, iF),
relative_(0), relative_(false),
inletValue_(p.size(), vector::zero) inletValue_(p.size(), vector::zero)
{} {}

View file

@ -30,6 +30,7 @@ Description
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
if (mesh.moving())
{ {
volScalarField contErr = fvc::div(phi + fvc::meshPhi(U)); volScalarField contErr = fvc::div(phi + fvc::meshPhi(U));
@ -47,5 +48,10 @@ Description
<< ", cumulative = " << cumulativeContErr << ", cumulative = " << cumulativeContErr
<< endl; << endl;
} }
else
{
# include "continuityErrs.H"
}
// ************************************************************************* // // ************************************************************************* //

View file

@ -53,4 +53,5 @@ else
# include "continuityErrs.H" # include "continuityErrs.H"
} }
// ************************************************************************* // // ************************************************************************* //

View file

@ -30,7 +30,6 @@ License
#include "volFields.H" #include "volFields.H"
#include "surfaceFields.H" #include "surfaceFields.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::totalPressureFvPatchScalarField::totalPressureFvPatchScalarField Foam::totalPressureFvPatchScalarField::totalPressureFvPatchScalarField

View file

@ -16,31 +16,11 @@ primitiveMeshGeometry/primitiveMeshGeometry.C
meshSearch/meshSearch.C meshSearch/meshSearch.C
meshTools/meshTools.C
PointEdgeWave/PointEdgeWaveName.C PointEdgeWave/PointEdgeWaveName.C
PointEdgeWave/pointEdgePoint.C PointEdgeWave/pointEdgePoint.C
regionSplit/regionSplit.C regionSplit/regionSplit.C
octree/octreeName.C
octree/octreeDataPoint.C
octree/octreeDataPointTreeLeaf.C
octree/octreeDataEdges.C
octree/octreeDataCell.C
octree/octreeDataFace.C
octree/treeBoundBox.C
octree/treeNodeName.C
octree/treeLeafName.C
octree/pointIndexHitIOList.C
indexedOctree/indexedOctreeName.C
indexedOctree/treeDataCell.C
indexedOctree/treeDataEdge.C
indexedOctree/treeDataFace.C
indexedOctree/treeDataPoint.C
indexedOctree/treeDataTriSurface.C
searchableSurface = searchableSurface searchableSurface = searchableSurface
$(searchableSurface)/distributedTriSurfaceMesh.C $(searchableSurface)/distributedTriSurfaceMesh.C
$(searchableSurface)/searchableBox.C $(searchableSurface)/searchableBox.C
@ -127,7 +107,6 @@ $(intersectedSurface)/edgeSurface.C
triSurface/triSurfaceSearch/triSurfaceSearch.C triSurface/triSurfaceSearch/triSurfaceSearch.C
triSurface/octreeData/octreeDataTriSurface.C triSurface/octreeData/octreeDataTriSurface.C
triSurface/octreeData/octreeDataTriSurfaceTreeLeaf.C triSurface/octreeData/octreeDataTriSurfaceTreeLeaf.C
triSurface/triangleFuncs/triangleFuncs.C
triSurface/surfaceFeatures/surfaceFeatures.C triSurface/surfaceFeatures/surfaceFeatures.C
triSurface/triSurfaceTools/triSurfaceTools.C triSurface/triSurfaceTools/triSurfaceTools.C
triSurface/triSurfaceTools/geompack/geompack.C triSurface/triSurfaceTools/geompack/geompack.C

View file

@ -46,6 +46,7 @@ SourceFiles
#include "objectRegistry.H" #include "objectRegistry.H"
#include "indexedOctree.H" #include "indexedOctree.H"
#include "treeDataTriSurface.H" #include "treeDataTriSurface.H"
#include "octreeDataTriSurfaceTreeLeaf.H"
#include "treeDataEdge.H" #include "treeDataEdge.H"
#include "EdgeMap.H" #include "EdgeMap.H"

View file

@ -129,7 +129,7 @@ Foam::rotatedBoxToCell::rotatedBoxToCell
) )
: :
topoSetSource(mesh), topoSetSource(mesh),
origin_(origin_), origin_(origin),
i_(i), i_(i),
j_(j), j_(j),
k_(k) k_(k)

View file

@ -73,6 +73,7 @@ class triSurfaceTools
RED, RED,
GREEN GREEN
}; };
static void calcRefineStatus static void calcRefineStatus
( (
const triSurface& surf, const triSurface& surf,
@ -118,8 +119,8 @@ class triSurfaceTools
label edgeI label edgeI
); );
// Return value of faceUsed for faces using vertI (local numbering). // Return value of faceUsed for faces using vertI (local numbering)
// Used internally. // Used internally
static label vertexUsesFace static label vertexUsesFace
( (
const triSurface& surf, const triSurface& surf,

View file

@ -1,2 +1,6 @@
EXE_INC = \ EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-DCELL_DECOMP -DCELL_DECOMP
EXE_LIBS = \
-lmeshTools

View file

@ -1 +1,6 @@
EXE_INC = -DFACE_DECOMP EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-DFACE_DECOMP
EXE_LIBS = \
-lmeshTools

View file

@ -7,6 +7,7 @@ meshTriangulation/meshTriangulation.C
triSurface/triSurface.C triSurface/triSurface.C
triSurface/triSurfaceAddressing.C triSurface/triSurfaceAddressing.C
triSurface/stitchTriangles.C triSurface/stitchTriangles.C
triSurface/treeDataTriSurface/treeDataTriSurface.C
interfaces = triSurface/interfaces interfaces = triSurface/interfaces
$(interfaces)/STL/writeSTL.C $(interfaces)/STL/writeSTL.C

View file

@ -1,3 +1,4 @@
EXE_INC = \ EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(WM_THIRD_PARTY_DIR)/zlib-1.2.3 -I$(WM_THIRD_PARTY_DIR)/zlib-1.2.3

View file

@ -1,6 +1,6 @@
/*--------------------------------*- C++ -*----------------------------------*\ /*--------------------------------*- C++ -*----------------------------------*\
| ========= | | | ========= | |
| \\ / F ield | OpenFOAM Extend Project: Open Source CFD | | \\ / F ield | OpenFOAM Extend Project: Open source CFD |
| \\ / O peration | Version: 1.6-ext | | \\ / O peration | Version: 1.6-ext |
| \\ / A nd | Web: www.extend-project.de | | \\ / A nd | Web: www.extend-project.de |
| \\/ M anipulation | | | \\/ M anipulation | |
@ -10,6 +10,7 @@ FoamFile
version 2.0; version 2.0;
format ascii; format ascii;
class polyBoundaryMesh; class polyBoundaryMesh;
location "constant/polyMesh";
object boundary; object boundary;
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -22,21 +23,18 @@ inlet
nFaces 20; nFaces 20;
startFace 1540; startFace 1540;
} }
outlet outlet
{ {
type patch; type patch;
nFaces 20; nFaces 20;
startFace 1560; startFace 1560;
} }
fixedWalls fixedWalls
{ {
type wall; type wall;
nFaces 80; nFaces 80;
startFace 1580; startFace 1580;
} }
defaultFaces defaultFaces
{ {
type empty; type empty;

View file

@ -39,6 +39,7 @@ right
shadowRegion solid; shadowRegion solid;
shadowPatch left; shadowPatch left;
attached on; attached on;
isWall yes;
} }
bottom bottom

View file

@ -32,6 +32,7 @@ left
shadowRegion region0; shadowRegion region0;
shadowPatch right; shadowPatch right;
attached on; attached on;
isWall yes; // Not relevant
} }
right right