mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
mapFields: Reinstated mapFields from OpenFOAM-2.2.x and renamed the current mapFields -> mapFieldsPar
This required the addition of the meshToMesh class in the sampling library from OpenFOAM-2.2.x which is now named meshToMesh0.
This commit is contained in:
@ -0,0 +1,382 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "cellVolumeWeightMethod.H"
|
||||
#include "indexedOctree.H"
|
||||
#include "treeDataCell.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(cellVolumeWeightMethod, 0);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
meshToMeshMethod,
|
||||
cellVolumeWeightMethod,
|
||||
components
|
||||
);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
bool Foam::cellVolumeWeightMethod::findInitialSeeds
|
||||
(
|
||||
const labelList& srcCellIDs,
|
||||
const boolList& mapFlag,
|
||||
const label startSeedI,
|
||||
label& srcSeedI,
|
||||
label& tgtSeedI
|
||||
) const
|
||||
{
|
||||
const cellList& srcCells = src_.cells();
|
||||
const faceList& srcFaces = src_.faces();
|
||||
const pointField& srcPts = src_.points();
|
||||
|
||||
for (label i = startSeedI; i < srcCellIDs.size(); i++)
|
||||
{
|
||||
label srcI = srcCellIDs[i];
|
||||
|
||||
if (mapFlag[srcI])
|
||||
{
|
||||
const pointField
|
||||
pts(srcCells[srcI].points(srcFaces, srcPts).xfer());
|
||||
|
||||
forAll(pts, ptI)
|
||||
{
|
||||
const point& pt = pts[ptI];
|
||||
label tgtI = tgt_.cellTree().findInside(pt);
|
||||
|
||||
if (tgtI != -1 && intersect(srcI, tgtI))
|
||||
{
|
||||
srcSeedI = srcI;
|
||||
tgtSeedI = tgtI;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "could not find starting seed" << endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Foam::cellVolumeWeightMethod::calculateAddressing
|
||||
(
|
||||
labelListList& srcToTgtCellAddr,
|
||||
scalarListList& srcToTgtCellWght,
|
||||
labelListList& tgtToSrcCellAddr,
|
||||
scalarListList& tgtToSrcCellWght,
|
||||
const label srcSeedI,
|
||||
const label tgtSeedI,
|
||||
const labelList& srcCellIDs,
|
||||
boolList& mapFlag,
|
||||
label& startSeedI
|
||||
)
|
||||
{
|
||||
label srcCellI = srcSeedI;
|
||||
label tgtCellI = tgtSeedI;
|
||||
|
||||
List<DynamicList<label> > srcToTgtAddr(src_.nCells());
|
||||
List<DynamicList<scalar> > srcToTgtWght(src_.nCells());
|
||||
|
||||
List<DynamicList<label> > tgtToSrcAddr(tgt_.nCells());
|
||||
List<DynamicList<scalar> > tgtToSrcWght(tgt_.nCells());
|
||||
|
||||
// list of tgt cell neighbour cells
|
||||
DynamicList<label> nbrTgtCells(10);
|
||||
|
||||
// list of tgt cells currently visited for srcCellI to avoid multiple hits
|
||||
DynamicList<label> visitedTgtCells(10);
|
||||
|
||||
// list to keep track of tgt cells used to seed src cells
|
||||
labelList seedCells(src_.nCells(), -1);
|
||||
seedCells[srcCellI] = tgtCellI;
|
||||
|
||||
const scalarField& srcVol = src_.cellVolumes();
|
||||
|
||||
do
|
||||
{
|
||||
nbrTgtCells.clear();
|
||||
visitedTgtCells.clear();
|
||||
|
||||
// append initial target cell and neighbours
|
||||
nbrTgtCells.append(tgtCellI);
|
||||
appendNbrCells(tgtCellI, tgt_, visitedTgtCells, nbrTgtCells);
|
||||
|
||||
do
|
||||
{
|
||||
tgtCellI = nbrTgtCells.remove();
|
||||
visitedTgtCells.append(tgtCellI);
|
||||
|
||||
scalar vol = interVol(srcCellI, tgtCellI);
|
||||
|
||||
// accumulate addressing and weights for valid intersection
|
||||
if (vol/srcVol[srcCellI] > tolerance_)
|
||||
{
|
||||
// store src/tgt cell pair
|
||||
srcToTgtAddr[srcCellI].append(tgtCellI);
|
||||
srcToTgtWght[srcCellI].append(vol);
|
||||
|
||||
tgtToSrcAddr[tgtCellI].append(srcCellI);
|
||||
tgtToSrcWght[tgtCellI].append(vol);
|
||||
|
||||
appendNbrCells(tgtCellI, tgt_, visitedTgtCells, nbrTgtCells);
|
||||
|
||||
// accumulate intersection volume
|
||||
V_ += vol;
|
||||
}
|
||||
}
|
||||
while (!nbrTgtCells.empty());
|
||||
|
||||
mapFlag[srcCellI] = false;
|
||||
|
||||
// find new source seed cell
|
||||
setNextCells
|
||||
(
|
||||
startSeedI,
|
||||
srcCellI,
|
||||
tgtCellI,
|
||||
srcCellIDs,
|
||||
mapFlag,
|
||||
visitedTgtCells,
|
||||
seedCells
|
||||
);
|
||||
}
|
||||
while (srcCellI != -1);
|
||||
|
||||
// transfer addressing into persistent storage
|
||||
forAll(srcToTgtCellAddr, i)
|
||||
{
|
||||
srcToTgtCellAddr[i].transfer(srcToTgtAddr[i]);
|
||||
srcToTgtCellWght[i].transfer(srcToTgtWght[i]);
|
||||
}
|
||||
|
||||
forAll(tgtToSrcCellAddr, i)
|
||||
{
|
||||
tgtToSrcCellAddr[i].transfer(tgtToSrcAddr[i]);
|
||||
tgtToSrcCellWght[i].transfer(tgtToSrcWght[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::cellVolumeWeightMethod::setNextCells
|
||||
(
|
||||
label& startSeedI,
|
||||
label& srcCellI,
|
||||
label& tgtCellI,
|
||||
const labelList& srcCellIDs,
|
||||
const boolList& mapFlag,
|
||||
const DynamicList<label>& visitedCells,
|
||||
labelList& seedCells
|
||||
) const
|
||||
{
|
||||
const labelList& srcNbrCells = src_.cellCells()[srcCellI];
|
||||
|
||||
// set possible seeds for later use by querying all src cell neighbours
|
||||
// with all visited target cells
|
||||
bool valuesSet = false;
|
||||
forAll(srcNbrCells, i)
|
||||
{
|
||||
label cellS = srcNbrCells[i];
|
||||
|
||||
if (mapFlag[cellS] && seedCells[cellS] == -1)
|
||||
{
|
||||
forAll(visitedCells, j)
|
||||
{
|
||||
label cellT = visitedCells[j];
|
||||
|
||||
if (intersect(cellS, cellT))
|
||||
{
|
||||
seedCells[cellS] = cellT;
|
||||
|
||||
if (!valuesSet)
|
||||
{
|
||||
srcCellI = cellS;
|
||||
tgtCellI = cellT;
|
||||
valuesSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set next src and tgt cells if not set above
|
||||
if (valuesSet)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// try to use existing seed
|
||||
bool foundNextSeed = false;
|
||||
for (label i = startSeedI; i < srcCellIDs.size(); i++)
|
||||
{
|
||||
label cellS = srcCellIDs[i];
|
||||
|
||||
if (mapFlag[cellS])
|
||||
{
|
||||
if (!foundNextSeed)
|
||||
{
|
||||
startSeedI = i;
|
||||
foundNextSeed = true;
|
||||
}
|
||||
|
||||
if (seedCells[cellS] != -1)
|
||||
{
|
||||
srcCellI = cellS;
|
||||
tgtCellI = seedCells[cellS];
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// perform new search to find match
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Advancing front stalled: searching for new "
|
||||
<< "target cell" << endl;
|
||||
}
|
||||
|
||||
bool restart =
|
||||
findInitialSeeds
|
||||
(
|
||||
srcCellIDs,
|
||||
mapFlag,
|
||||
startSeedI,
|
||||
srcCellI,
|
||||
tgtCellI
|
||||
);
|
||||
|
||||
if (restart)
|
||||
{
|
||||
// successfully found new starting seed-pair
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if we have got to here, there are no more src/tgt cell intersections
|
||||
srcCellI = -1;
|
||||
tgtCellI = -1;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::cellVolumeWeightMethod::cellVolumeWeightMethod
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt
|
||||
)
|
||||
:
|
||||
meshToMeshMethod(src, tgt)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::cellVolumeWeightMethod::~cellVolumeWeightMethod()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::cellVolumeWeightMethod::calculate
|
||||
(
|
||||
labelListList& srcToTgtAddr,
|
||||
scalarListList& srcToTgtWght,
|
||||
labelListList& tgtToSrcAddr,
|
||||
scalarListList& tgtToSrcWght
|
||||
)
|
||||
{
|
||||
bool ok = initialise
|
||||
(
|
||||
srcToTgtAddr,
|
||||
srcToTgtWght,
|
||||
tgtToSrcAddr,
|
||||
tgtToSrcWght
|
||||
);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// (potentially) participating source mesh cells
|
||||
const labelList srcCellIDs(maskCells());
|
||||
|
||||
// list to keep track of whether src cell can be mapped
|
||||
boolList mapFlag(src_.nCells(), false);
|
||||
UIndirectList<bool>(mapFlag, srcCellIDs) = true;
|
||||
|
||||
// find initial point in tgt mesh
|
||||
label srcSeedI = -1;
|
||||
label tgtSeedI = -1;
|
||||
label startSeedI = 0;
|
||||
|
||||
bool startWalk =
|
||||
findInitialSeeds
|
||||
(
|
||||
srcCellIDs,
|
||||
mapFlag,
|
||||
startSeedI,
|
||||
srcSeedI,
|
||||
tgtSeedI
|
||||
);
|
||||
|
||||
if (startWalk)
|
||||
{
|
||||
calculateAddressing
|
||||
(
|
||||
srcToTgtAddr,
|
||||
srcToTgtWght,
|
||||
tgtToSrcAddr,
|
||||
tgtToSrcWght,
|
||||
srcSeedI,
|
||||
tgtSeedI,
|
||||
srcCellIDs,
|
||||
mapFlag,
|
||||
startSeedI
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if meshes are collocated, after inflating the source mesh bounding
|
||||
// box tgt mesh cells may be transferred, but may still not overlap
|
||||
// with the source mesh
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,138 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::cellVolumeWeightMethod
|
||||
|
||||
Description
|
||||
Cell-volume-weighted mesh-to-mesh interpolation class
|
||||
|
||||
Volume conservative.
|
||||
|
||||
SourceFiles
|
||||
cellVolumeWeightMethod.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef cellVolumeWeightMethod_H
|
||||
#define cellVolumeWeightMethod_H
|
||||
|
||||
#include "meshToMeshMethod.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class cellVolumeWeightMethod Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class cellVolumeWeightMethod
|
||||
:
|
||||
public meshToMeshMethod
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Find indices of overlapping cells in src and tgt meshes - returns
|
||||
// true if found a matching pair
|
||||
bool findInitialSeeds
|
||||
(
|
||||
const labelList& srcCellIDs,
|
||||
const boolList& mapFlag,
|
||||
const label startSeedI,
|
||||
label& srcSeedI,
|
||||
label& tgtSeedI
|
||||
) const;
|
||||
|
||||
//- Calculate the mesh-to-mesh addressing and weights
|
||||
void calculateAddressing
|
||||
(
|
||||
labelListList& srcToTgtCellAddr,
|
||||
scalarListList& srcToTgtCellWght,
|
||||
labelListList& tgtToSrcCellAddr,
|
||||
scalarListList& tgtToSrcCellWght,
|
||||
const label srcSeedI,
|
||||
const label tgtSeedI,
|
||||
const labelList& srcCellIDs,
|
||||
boolList& mapFlag,
|
||||
label& startSeedI
|
||||
);
|
||||
|
||||
//- Set the next cells in the advancing front algorithm
|
||||
void setNextCells
|
||||
(
|
||||
label& startSeedI,
|
||||
label& srcCellI,
|
||||
label& tgtCellI,
|
||||
const labelList& srcCellIDs,
|
||||
const boolList& mapFlag,
|
||||
const DynamicList<label>& visitedCells,
|
||||
labelList& seedCells
|
||||
) const;
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
cellVolumeWeightMethod(const cellVolumeWeightMethod&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const cellVolumeWeightMethod&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("cellVolumeWeight");
|
||||
|
||||
//- Construct from source and target meshes
|
||||
cellVolumeWeightMethod(const polyMesh& src, const polyMesh& tgt);
|
||||
|
||||
//- Destructor
|
||||
virtual ~cellVolumeWeightMethod();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Evaluate
|
||||
|
||||
//- Calculate addressing and weights
|
||||
virtual void calculate
|
||||
(
|
||||
labelListList& srcToTgtAddr,
|
||||
scalarListList& srcToTgtWght,
|
||||
labelListList& tgtToTgtAddr,
|
||||
scalarListList& tgtToTgtWght
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
324
src/sampling/meshToMesh/calcMethod/direct/directMethod.C
Normal file
324
src/sampling/meshToMesh/calcMethod/direct/directMethod.C
Normal file
@ -0,0 +1,324 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "directMethod.H"
|
||||
#include "indexedOctree.H"
|
||||
#include "treeDataCell.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(directMethod, 0);
|
||||
addToRunTimeSelectionTable(meshToMeshMethod, directMethod, components);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
bool Foam::directMethod::intersect
|
||||
(
|
||||
const label srcCellI,
|
||||
const label tgtCellI
|
||||
) const
|
||||
{
|
||||
return tgt_.pointInCell
|
||||
(
|
||||
src_.cellCentres()[srcCellI],
|
||||
tgtCellI,
|
||||
polyMesh::FACE_PLANES
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::directMethod::findInitialSeeds
|
||||
(
|
||||
const labelList& srcCellIDs,
|
||||
const boolList& mapFlag,
|
||||
const label startSeedI,
|
||||
label& srcSeedI,
|
||||
label& tgtSeedI
|
||||
) const
|
||||
{
|
||||
const cellList& srcCells = src_.cells();
|
||||
const faceList& srcFaces = src_.faces();
|
||||
const pointField& srcPts = src_.points();
|
||||
|
||||
for (label i = startSeedI; i < srcCellIDs.size(); i++)
|
||||
{
|
||||
label srcI = srcCellIDs[i];
|
||||
|
||||
if (mapFlag[srcI])
|
||||
{
|
||||
const pointField
|
||||
pts(srcCells[srcI].points(srcFaces, srcPts).xfer());
|
||||
|
||||
forAll(pts, ptI)
|
||||
{
|
||||
const point& pt = pts[ptI];
|
||||
label tgtI = tgt_.cellTree().findInside(pt);
|
||||
|
||||
if (tgtI != -1 && intersect(srcI, tgtI))
|
||||
{
|
||||
srcSeedI = srcI;
|
||||
tgtSeedI = tgtI;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "could not find starting seed" << endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Foam::directMethod::calculateAddressing
|
||||
(
|
||||
labelListList& srcToTgtCellAddr,
|
||||
scalarListList& srcToTgtCellWght,
|
||||
labelListList& tgtToSrcCellAddr,
|
||||
scalarListList& tgtToSrcCellWght,
|
||||
const label srcSeedI,
|
||||
const label tgtSeedI,
|
||||
const labelList& srcCellIDs, // not used
|
||||
boolList& mapFlag,
|
||||
label& startSeedI
|
||||
)
|
||||
{
|
||||
// store a list of src cells already mapped
|
||||
labelList srcTgtSeed(src_.nCells(), -1);
|
||||
|
||||
List<DynamicList<label> > srcToTgt(src_.nCells());
|
||||
List<DynamicList<label> > tgtToSrc(tgt_.nCells());
|
||||
|
||||
DynamicList<label> srcSeeds(10);
|
||||
|
||||
const scalarField& srcVc = src_.cellVolumes();
|
||||
const scalarField& tgtVc = tgt_.cellVolumes();
|
||||
|
||||
label srcCellI = srcSeedI;
|
||||
label tgtCellI = tgtSeedI;
|
||||
|
||||
do
|
||||
{
|
||||
// store src/tgt cell pair
|
||||
srcToTgt[srcCellI].append(tgtCellI);
|
||||
tgtToSrc[tgtCellI].append(srcCellI);
|
||||
|
||||
// mark source cell srcSeedI as matched
|
||||
mapFlag[srcCellI] = false;
|
||||
|
||||
// accumulate intersection volume
|
||||
V_ += srcVc[srcCellI];
|
||||
|
||||
// find new source seed cell
|
||||
appendToDirectSeeds
|
||||
(
|
||||
mapFlag,
|
||||
srcTgtSeed,
|
||||
srcSeeds,
|
||||
srcCellI,
|
||||
tgtCellI
|
||||
);
|
||||
}
|
||||
while (srcCellI >= 0);
|
||||
|
||||
// transfer addressing into persistent storage
|
||||
forAll(srcToTgtCellAddr, i)
|
||||
{
|
||||
srcToTgtCellWght[i] = scalarList(srcToTgt[i].size(), srcVc[i]);
|
||||
srcToTgtCellAddr[i].transfer(srcToTgt[i]);
|
||||
}
|
||||
|
||||
forAll(tgtToSrcCellAddr, i)
|
||||
{
|
||||
tgtToSrcCellWght[i] = scalarList(tgtToSrc[i].size(), tgtVc[i]);
|
||||
tgtToSrcCellAddr[i].transfer(tgtToSrc[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::directMethod::appendToDirectSeeds
|
||||
(
|
||||
boolList& mapFlag,
|
||||
labelList& srcTgtSeed,
|
||||
DynamicList<label>& srcSeeds,
|
||||
label& srcSeedI,
|
||||
label& tgtSeedI
|
||||
) const
|
||||
{
|
||||
const labelList& srcNbr = src_.cellCells()[srcSeedI];
|
||||
const labelList& tgtNbr = tgt_.cellCells()[tgtSeedI];
|
||||
|
||||
const vectorField& srcCentre = src_.cellCentres();
|
||||
|
||||
forAll(srcNbr, i)
|
||||
{
|
||||
label srcI = srcNbr[i];
|
||||
|
||||
if (mapFlag[srcI] && (srcTgtSeed[srcI] == -1))
|
||||
{
|
||||
// source cell srcI not yet mapped
|
||||
|
||||
// identfy if target cell exists for source cell srcI
|
||||
bool found = false;
|
||||
forAll(tgtNbr, j)
|
||||
{
|
||||
label tgtI = tgtNbr[j];
|
||||
|
||||
if
|
||||
(
|
||||
tgt_.pointInCell
|
||||
(
|
||||
srcCentre[srcI],
|
||||
tgtI,
|
||||
polyMesh::FACE_PLANES
|
||||
)
|
||||
)
|
||||
{
|
||||
// new match - append to lists
|
||||
found = true;
|
||||
|
||||
srcTgtSeed[srcI] = tgtI;
|
||||
srcSeeds.append(srcI);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
// no match available for source cell srcI
|
||||
mapFlag[srcI] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (srcSeeds.size())
|
||||
{
|
||||
srcSeedI = srcSeeds.remove();
|
||||
tgtSeedI = srcTgtSeed[srcSeedI];
|
||||
}
|
||||
else
|
||||
{
|
||||
srcSeedI = -1;
|
||||
tgtSeedI = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::directMethod::directMethod
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt
|
||||
)
|
||||
:
|
||||
meshToMeshMethod(src, tgt)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::directMethod::~directMethod()
|
||||
{}
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::directMethod::calculate
|
||||
(
|
||||
labelListList& srcToTgtAddr,
|
||||
scalarListList& srcToTgtWght,
|
||||
labelListList& tgtToSrcAddr,
|
||||
scalarListList& tgtToSrcWght
|
||||
)
|
||||
{
|
||||
bool ok = initialise
|
||||
(
|
||||
srcToTgtAddr,
|
||||
srcToTgtWght,
|
||||
tgtToSrcAddr,
|
||||
tgtToSrcWght
|
||||
);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// (potentially) participating source mesh cells
|
||||
const labelList srcCellIDs(maskCells());
|
||||
|
||||
// list to keep track of whether src cell can be mapped
|
||||
boolList mapFlag(src_.nCells(), false);
|
||||
UIndirectList<bool>(mapFlag, srcCellIDs) = true;
|
||||
|
||||
// find initial point in tgt mesh
|
||||
label srcSeedI = -1;
|
||||
label tgtSeedI = -1;
|
||||
label startSeedI = 0;
|
||||
|
||||
bool startWalk =
|
||||
findInitialSeeds
|
||||
(
|
||||
srcCellIDs,
|
||||
mapFlag,
|
||||
startSeedI,
|
||||
srcSeedI,
|
||||
tgtSeedI
|
||||
);
|
||||
|
||||
if (startWalk)
|
||||
{
|
||||
calculateAddressing
|
||||
(
|
||||
srcToTgtAddr,
|
||||
srcToTgtWght,
|
||||
tgtToSrcAddr,
|
||||
tgtToSrcWght,
|
||||
srcSeedI,
|
||||
tgtSeedI,
|
||||
srcCellIDs,
|
||||
mapFlag,
|
||||
startSeedI
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if meshes are collocated, after inflating the source mesh bounding
|
||||
// box tgt mesh cells may be transferred, but may still not overlap
|
||||
// with the source mesh
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
143
src/sampling/meshToMesh/calcMethod/direct/directMethod.H
Normal file
143
src/sampling/meshToMesh/calcMethod/direct/directMethod.H
Normal file
@ -0,0 +1,143 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::directMethod
|
||||
|
||||
Description
|
||||
Direct (one-to-one cell correspondence) mesh-to-mesh interpolation class
|
||||
|
||||
Volume conservative.
|
||||
|
||||
SourceFiles
|
||||
directMethod.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef directMethod_H
|
||||
#define directMethod_H
|
||||
|
||||
#include "meshToMeshMethod.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class directMethod Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class directMethod
|
||||
:
|
||||
public meshToMeshMethod
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Return the true if cells intersect
|
||||
virtual bool intersect
|
||||
(
|
||||
const label srcCellI,
|
||||
const label tgtCellI
|
||||
) const;
|
||||
|
||||
//- Find indices of overlapping cells in src and tgt meshes - returns
|
||||
// true if found a matching pair
|
||||
virtual bool findInitialSeeds
|
||||
(
|
||||
const labelList& srcCellIDs,
|
||||
const boolList& mapFlag,
|
||||
const label startSeedI,
|
||||
label& srcSeedI,
|
||||
label& tgtSeedI
|
||||
) const;
|
||||
|
||||
//- Calculate the mesh-to-mesh addressing and weights
|
||||
virtual void calculateAddressing
|
||||
(
|
||||
labelListList& srcToTgtCellAddr,
|
||||
scalarListList& srcToTgtCellWght,
|
||||
labelListList& tgtToSrcCellAddr,
|
||||
scalarListList& tgtToSrcCellWght,
|
||||
const label srcSeedI,
|
||||
const label tgtSeedI,
|
||||
const labelList& srcCellIDs,
|
||||
boolList& mapFlag,
|
||||
label& startSeedI
|
||||
);
|
||||
|
||||
//- Append to list of src mesh seed indices
|
||||
virtual void appendToDirectSeeds
|
||||
(
|
||||
boolList& mapFlag,
|
||||
labelList& srcTgtSeed,
|
||||
DynamicList<label>& srcSeeds,
|
||||
label& srcSeedI,
|
||||
label& tgtSeedI
|
||||
) const;
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
directMethod(const directMethod&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const directMethod&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("direct");
|
||||
|
||||
//- Construct from source and target meshes
|
||||
directMethod(const polyMesh& src, const polyMesh& tgt);
|
||||
|
||||
//- Destructor
|
||||
virtual ~directMethod();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Evaluate
|
||||
|
||||
//- Calculate addressing and weights
|
||||
virtual void calculate
|
||||
(
|
||||
labelListList& srcToTgtAddr,
|
||||
scalarListList& srcToTgtWght,
|
||||
labelListList& tgtToTgtAddr,
|
||||
scalarListList& tgtToTgtWght
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
426
src/sampling/meshToMesh/calcMethod/mapNearest/mapNearestMethod.C
Normal file
426
src/sampling/meshToMesh/calcMethod/mapNearest/mapNearestMethod.C
Normal file
@ -0,0 +1,426 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "mapNearestMethod.H"
|
||||
#include "pointIndexHit.H"
|
||||
#include "indexedOctree.H"
|
||||
#include "treeDataCell.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(mapNearestMethod, 0);
|
||||
addToRunTimeSelectionTable(meshToMeshMethod, mapNearestMethod, components);
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
bool Foam::mapNearestMethod::findInitialSeeds
|
||||
(
|
||||
const labelList& srcCellIDs,
|
||||
const boolList& mapFlag,
|
||||
const label startSeedI,
|
||||
label& srcSeedI,
|
||||
label& tgtSeedI
|
||||
) const
|
||||
{
|
||||
const vectorField& srcCcs = src_.cellCentres();
|
||||
|
||||
for (label i = startSeedI; i < srcCellIDs.size(); i++)
|
||||
{
|
||||
label srcI = srcCellIDs[i];
|
||||
|
||||
if (mapFlag[srcI])
|
||||
{
|
||||
const point& srcCc = srcCcs[srcI];
|
||||
pointIndexHit hit =
|
||||
tgt_.cellTree().findNearest(srcCc, GREAT);
|
||||
|
||||
if (hit.hit())
|
||||
{
|
||||
srcSeedI = srcI;
|
||||
tgtSeedI = hit.index();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"bool Foam::mapNearestMethod::findInitialSeeds"
|
||||
"("
|
||||
"const labelList&, "
|
||||
"const boolList&, "
|
||||
"const label, "
|
||||
"label&, "
|
||||
"label&"
|
||||
") const"
|
||||
)
|
||||
<< "Unable to find nearest target cell"
|
||||
<< " for source cell " << srcI
|
||||
<< " with centre " << srcCc
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "could not find starting seed" << endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Foam::mapNearestMethod::calculateAddressing
|
||||
(
|
||||
labelListList& srcToTgtCellAddr,
|
||||
scalarListList& srcToTgtCellWght,
|
||||
labelListList& tgtToSrcCellAddr,
|
||||
scalarListList& tgtToSrcCellWght,
|
||||
const label srcSeedI,
|
||||
const label tgtSeedI,
|
||||
const labelList& srcCellIDs,
|
||||
boolList& mapFlag,
|
||||
label& startSeedI
|
||||
)
|
||||
{
|
||||
List<DynamicList<label> > srcToTgt(src_.nCells());
|
||||
List<DynamicList<label> > tgtToSrc(tgt_.nCells());
|
||||
|
||||
const scalarField& srcVc = src_.cellVolumes();
|
||||
const scalarField& tgtVc = tgt_.cellVolumes();
|
||||
|
||||
{
|
||||
label srcCellI = srcSeedI;
|
||||
label tgtCellI = tgtSeedI;
|
||||
|
||||
do
|
||||
{
|
||||
// find nearest tgt cell
|
||||
findNearestCell(src_, tgt_, srcCellI, tgtCellI);
|
||||
|
||||
// store src/tgt cell pair
|
||||
srcToTgt[srcCellI].append(tgtCellI);
|
||||
tgtToSrc[tgtCellI].append(srcCellI);
|
||||
|
||||
// mark source cell srcCellI and tgtCellI as matched
|
||||
mapFlag[srcCellI] = false;
|
||||
|
||||
// accumulate intersection volume
|
||||
V_ += srcVc[srcCellI];
|
||||
|
||||
// find new source cell
|
||||
setNextNearestCells
|
||||
(
|
||||
startSeedI,
|
||||
srcCellI,
|
||||
tgtCellI,
|
||||
mapFlag,
|
||||
srcCellIDs
|
||||
);
|
||||
}
|
||||
while (srcCellI >= 0);
|
||||
}
|
||||
|
||||
// for the case of multiple source cells per target cell, select the
|
||||
// nearest source cell only and discard the others
|
||||
const vectorField& srcCc = src_.cellCentres();
|
||||
const vectorField& tgtCc = tgt_.cellCentres();
|
||||
|
||||
forAll(tgtToSrc, targetCellI)
|
||||
{
|
||||
if (tgtToSrc[targetCellI].size() > 1)
|
||||
{
|
||||
const vector& tgtC = tgtCc[targetCellI];
|
||||
|
||||
DynamicList<label>& srcCells = tgtToSrc[targetCellI];
|
||||
|
||||
label srcCellI = srcCells[0];
|
||||
scalar d = magSqr(tgtC - srcCc[srcCellI]);
|
||||
|
||||
for (label i = 1; i < srcCells.size(); i++)
|
||||
{
|
||||
label srcI = srcCells[i];
|
||||
scalar dNew = magSqr(tgtC - srcCc[srcI]);
|
||||
if (dNew < d)
|
||||
{
|
||||
d = dNew;
|
||||
srcCellI = srcI;
|
||||
}
|
||||
}
|
||||
|
||||
srcCells.clear();
|
||||
srcCells.append(srcCellI);
|
||||
}
|
||||
}
|
||||
|
||||
// If there are more target cells than source cells, some target cells
|
||||
// might not yet be mapped
|
||||
forAll(tgtToSrc, tgtCellI)
|
||||
{
|
||||
if (tgtToSrc[tgtCellI].empty())
|
||||
{
|
||||
label srcCellI = findMappedSrcCell(tgtCellI, tgtToSrc);
|
||||
|
||||
findNearestCell(tgt_, src_, tgtCellI, srcCellI);
|
||||
|
||||
tgtToSrc[tgtCellI].append(srcCellI);
|
||||
}
|
||||
}
|
||||
|
||||
// transfer addressing into persistent storage
|
||||
forAll(srcToTgtCellAddr, i)
|
||||
{
|
||||
srcToTgtCellWght[i] = scalarList(srcToTgt[i].size(), srcVc[i]);
|
||||
srcToTgtCellAddr[i].transfer(srcToTgt[i]);
|
||||
}
|
||||
|
||||
forAll(tgtToSrcCellAddr, i)
|
||||
{
|
||||
tgtToSrcCellWght[i] = scalarList(tgtToSrc[i].size(), tgtVc[i]);
|
||||
tgtToSrcCellAddr[i].transfer(tgtToSrc[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::mapNearestMethod::findNearestCell
|
||||
(
|
||||
const polyMesh& mesh1,
|
||||
const polyMesh& mesh2,
|
||||
const label cell1,
|
||||
label& cell2
|
||||
) const
|
||||
{
|
||||
const vectorField& Cc1 = mesh1.cellCentres();
|
||||
const vectorField& Cc2 = mesh2.cellCentres();
|
||||
|
||||
const vector& p1 = Cc1[cell1];
|
||||
|
||||
DynamicList<label> cells2(10);
|
||||
cells2.append(cell2);
|
||||
|
||||
DynamicList<label> visitedCells(10);
|
||||
|
||||
scalar d = GREAT;
|
||||
|
||||
do
|
||||
{
|
||||
label c2 = cells2.remove();
|
||||
visitedCells.append(c2);
|
||||
|
||||
scalar dTest = magSqr(Cc2[c2] - p1);
|
||||
if (dTest < d)
|
||||
{
|
||||
cell2 = c2;
|
||||
d = dTest;
|
||||
appendNbrCells(cell2, mesh2, visitedCells, cells2);
|
||||
}
|
||||
|
||||
} while (cells2.size() > 0);
|
||||
}
|
||||
|
||||
|
||||
void Foam::mapNearestMethod::setNextNearestCells
|
||||
(
|
||||
label& startSeedI,
|
||||
label& srcCellI,
|
||||
label& tgtCellI,
|
||||
boolList& mapFlag,
|
||||
const labelList& srcCellIDs
|
||||
) const
|
||||
{
|
||||
const labelList& srcNbr = src_.cellCells()[srcCellI];
|
||||
|
||||
srcCellI = -1;
|
||||
forAll(srcNbr, i)
|
||||
{
|
||||
label cellI = srcNbr[i];
|
||||
if (mapFlag[cellI])
|
||||
{
|
||||
srcCellI = cellI;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (label i = startSeedI; i < srcCellIDs.size(); i++)
|
||||
{
|
||||
label cellI = srcCellIDs[i];
|
||||
if (mapFlag[cellI])
|
||||
{
|
||||
startSeedI = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
(void)findInitialSeeds
|
||||
(
|
||||
srcCellIDs,
|
||||
mapFlag,
|
||||
startSeedI,
|
||||
srcCellI,
|
||||
tgtCellI
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::mapNearestMethod::findMappedSrcCell
|
||||
(
|
||||
const label tgtCellI,
|
||||
const List<DynamicList<label> >& tgtToSrc
|
||||
) const
|
||||
{
|
||||
DynamicList<label> testCells(10);
|
||||
DynamicList<label> visitedCells(10);
|
||||
|
||||
testCells.append(tgtCellI);
|
||||
|
||||
do
|
||||
{
|
||||
// search target tgtCellI neighbours for match with source cell
|
||||
label tgtI = testCells.remove();
|
||||
|
||||
if (findIndex(visitedCells, tgtI) == -1)
|
||||
{
|
||||
visitedCells.append(tgtI);
|
||||
|
||||
if (tgtToSrc[tgtI].size())
|
||||
{
|
||||
return tgtToSrc[tgtI][0];
|
||||
}
|
||||
else
|
||||
{
|
||||
const labelList& nbrCells = tgt_.cellCells()[tgtI];
|
||||
|
||||
forAll(nbrCells, i)
|
||||
{
|
||||
if (findIndex(visitedCells, nbrCells[i]) == -1)
|
||||
{
|
||||
testCells.append(nbrCells[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (testCells.size());
|
||||
|
||||
// did not find any match - should not be possible to get here!
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::mapNearestMethod::mapNearestMethod
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt
|
||||
)
|
||||
:
|
||||
meshToMeshMethod(src, tgt)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::mapNearestMethod::~mapNearestMethod()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::mapNearestMethod::calculate
|
||||
(
|
||||
labelListList& srcToTgtAddr,
|
||||
scalarListList& srcToTgtWght,
|
||||
labelListList& tgtToSrcAddr,
|
||||
scalarListList& tgtToSrcWght
|
||||
)
|
||||
{
|
||||
bool ok = initialise
|
||||
(
|
||||
srcToTgtAddr,
|
||||
srcToTgtWght,
|
||||
tgtToSrcAddr,
|
||||
tgtToSrcWght
|
||||
);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// (potentially) participating source mesh cells
|
||||
const labelList srcCellIDs(maskCells());
|
||||
|
||||
// list to keep track of whether src cell can be mapped
|
||||
boolList mapFlag(src_.nCells(), false);
|
||||
UIndirectList<bool>(mapFlag, srcCellIDs) = true;
|
||||
|
||||
// find initial point in tgt mesh
|
||||
label srcSeedI = -1;
|
||||
label tgtSeedI = -1;
|
||||
label startSeedI = 0;
|
||||
|
||||
bool startWalk =
|
||||
findInitialSeeds
|
||||
(
|
||||
srcCellIDs,
|
||||
mapFlag,
|
||||
startSeedI,
|
||||
srcSeedI,
|
||||
tgtSeedI
|
||||
);
|
||||
|
||||
if (startWalk)
|
||||
{
|
||||
calculateAddressing
|
||||
(
|
||||
srcToTgtAddr,
|
||||
srcToTgtWght,
|
||||
tgtToSrcAddr,
|
||||
tgtToSrcWght,
|
||||
srcSeedI,
|
||||
tgtSeedI,
|
||||
srcCellIDs,
|
||||
mapFlag,
|
||||
startSeedI
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if meshes are collocated, after inflating the source mesh bounding
|
||||
// box tgt mesh cells may be transferred, but may still not overlap
|
||||
// with the source mesh
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
156
src/sampling/meshToMesh/calcMethod/mapNearest/mapNearestMethod.H
Normal file
156
src/sampling/meshToMesh/calcMethod/mapNearest/mapNearestMethod.H
Normal file
@ -0,0 +1,156 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::mapNearestMethod
|
||||
|
||||
Description
|
||||
Map nearest mesh-to-mesh interpolation class
|
||||
|
||||
Not volume conservative.
|
||||
- cells outside other meshes bounding box do not get mapped
|
||||
(initial filtering)
|
||||
- all remaining cells will be mapped (with weight 1!)
|
||||
- so take care when mapping meshes with different bounding boxes!
|
||||
|
||||
SourceFiles
|
||||
mapNearestMethod.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef mapNearestMethod_H
|
||||
#define mapNearestMethod_H
|
||||
|
||||
#include "meshToMeshMethod.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class mapNearestMethod Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class mapNearestMethod
|
||||
:
|
||||
public meshToMeshMethod
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Find indices of overlapping cells in src and tgt meshes - returns
|
||||
// true if found a matching pair
|
||||
virtual bool findInitialSeeds
|
||||
(
|
||||
const labelList& srcCellIDs,
|
||||
const boolList& mapFlag,
|
||||
const label startSeedI,
|
||||
label& srcSeedI,
|
||||
label& tgtSeedI
|
||||
) const;
|
||||
|
||||
//- Calculate the mesh-to-mesh addressing and weights
|
||||
virtual void calculateAddressing
|
||||
(
|
||||
labelListList& srcToTgtCellAddr,
|
||||
scalarListList& srcToTgtCellWght,
|
||||
labelListList& tgtToSrcCellAddr,
|
||||
scalarListList& tgtToSrcCellWght,
|
||||
const label srcSeedI,
|
||||
const label tgtSeedI,
|
||||
const labelList& srcCellIDs,
|
||||
boolList& mapFlag,
|
||||
label& startSeedI
|
||||
);
|
||||
|
||||
//- Find the nearest cell on mesh2 for cell1 on mesh1
|
||||
virtual void findNearestCell
|
||||
(
|
||||
const polyMesh& mesh1,
|
||||
const polyMesh& mesh2,
|
||||
const label cell1,
|
||||
label& cell2
|
||||
) const;
|
||||
|
||||
//- Set the next cells for the marching front algorithm
|
||||
virtual void setNextNearestCells
|
||||
(
|
||||
label& startSeedI,
|
||||
label& srcCellI,
|
||||
label& tgtCellI,
|
||||
boolList& mapFlag,
|
||||
const labelList& srcCellIDs
|
||||
) const;
|
||||
|
||||
//- Find a source cell mapped to target cell tgtCellI
|
||||
virtual label findMappedSrcCell
|
||||
(
|
||||
const label tgtCellI,
|
||||
const List<DynamicList<label> >& tgtToSrc
|
||||
) const;
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
mapNearestMethod(const mapNearestMethod&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const mapNearestMethod&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("mapNearest");
|
||||
|
||||
//- Construct from source and target meshes
|
||||
mapNearestMethod(const polyMesh& src, const polyMesh& tgt);
|
||||
|
||||
//- Destructor
|
||||
virtual ~mapNearestMethod();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Evaluate
|
||||
|
||||
//- Calculate addressing and weights
|
||||
virtual void calculate
|
||||
(
|
||||
labelListList& srcToTgtAddr,
|
||||
scalarListList& srcToTgtWght,
|
||||
labelListList& tgtToTgtAddr,
|
||||
scalarListList& tgtToTgtWght
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,260 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "meshToMeshMethod.H"
|
||||
#include "tetOverlapVolume.H"
|
||||
#include "OFstream.H"
|
||||
#include "Time.H"
|
||||
#include "treeBoundBox.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(meshToMeshMethod, 0);
|
||||
defineRunTimeSelectionTable(meshToMeshMethod, components);
|
||||
}
|
||||
|
||||
Foam::scalar Foam::meshToMeshMethod::tolerance_ = 1e-6;
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::labelList Foam::meshToMeshMethod::maskCells() const
|
||||
{
|
||||
boundBox intersectBb
|
||||
(
|
||||
max(src_.bounds().min(), tgt_.bounds().min()),
|
||||
min(src_.bounds().max(), tgt_.bounds().max())
|
||||
);
|
||||
|
||||
intersectBb.inflate(0.01);
|
||||
|
||||
const cellList& srcCells = src_.cells();
|
||||
const faceList& srcFaces = src_.faces();
|
||||
const pointField& srcPts = src_.points();
|
||||
|
||||
DynamicList<label> cells(src_.nCells());
|
||||
forAll(srcCells, srcI)
|
||||
{
|
||||
boundBox cellBb(srcCells[srcI].points(srcFaces, srcPts), false);
|
||||
if (intersectBb.overlaps(cellBb))
|
||||
{
|
||||
cells.append(srcI);
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "participating source mesh cells: " << cells.size() << endl;
|
||||
}
|
||||
|
||||
return cells;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::meshToMeshMethod::intersect
|
||||
(
|
||||
const label srcCellI,
|
||||
const label tgtCellI
|
||||
) const
|
||||
{
|
||||
scalar threshold = tolerance_*src_.cellVolumes()[srcCellI];
|
||||
|
||||
tetOverlapVolume overlapEngine;
|
||||
|
||||
treeBoundBox bbTgtCell(tgt_.points(), tgt_.cellPoints()[tgtCellI]);
|
||||
|
||||
return overlapEngine.cellCellOverlapMinDecomp
|
||||
(
|
||||
src_,
|
||||
srcCellI,
|
||||
tgt_,
|
||||
tgtCellI,
|
||||
bbTgtCell,
|
||||
threshold
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Foam::scalar Foam::meshToMeshMethod::interVol
|
||||
(
|
||||
const label srcCellI,
|
||||
const label tgtCellI
|
||||
) const
|
||||
{
|
||||
tetOverlapVolume overlapEngine;
|
||||
|
||||
treeBoundBox bbTgtCell(tgt_.points(), tgt_.cellPoints()[tgtCellI]);
|
||||
|
||||
scalar vol = overlapEngine.cellCellOverlapVolumeMinDecomp
|
||||
(
|
||||
src_,
|
||||
srcCellI,
|
||||
tgt_,
|
||||
tgtCellI,
|
||||
bbTgtCell
|
||||
);
|
||||
|
||||
return vol;
|
||||
}
|
||||
|
||||
|
||||
void Foam::meshToMeshMethod::appendNbrCells
|
||||
(
|
||||
const label cellI,
|
||||
const polyMesh& mesh,
|
||||
const DynamicList<label>& visitedCells,
|
||||
DynamicList<label>& nbrCellIDs
|
||||
) const
|
||||
{
|
||||
const labelList& nbrCells = mesh.cellCells()[cellI];
|
||||
|
||||
// filter out cells already visited from cell neighbours
|
||||
forAll(nbrCells, i)
|
||||
{
|
||||
label nbrCellI = nbrCells[i];
|
||||
|
||||
if
|
||||
(
|
||||
(findIndex(visitedCells, nbrCellI) == -1)
|
||||
&& (findIndex(nbrCellIDs, nbrCellI) == -1)
|
||||
)
|
||||
{
|
||||
nbrCellIDs.append(nbrCellI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::meshToMeshMethod::initialise
|
||||
(
|
||||
labelListList& srcToTgtAddr,
|
||||
scalarListList& srcToTgtWght,
|
||||
labelListList& tgtToSrcAddr,
|
||||
scalarListList& tgtToSrcWght
|
||||
) const
|
||||
{
|
||||
srcToTgtAddr.setSize(src_.nCells());
|
||||
srcToTgtWght.setSize(src_.nCells());
|
||||
tgtToSrcAddr.setSize(tgt_.nCells());
|
||||
tgtToSrcWght.setSize(tgt_.nCells());
|
||||
|
||||
if (!src_.nCells())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!tgt_.nCells())
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "mesh interpolation: hhave " << src_.nCells() << " source "
|
||||
<< " cells but no target cells" << endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::meshToMeshMethod::meshToMeshMethod
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt
|
||||
)
|
||||
:
|
||||
src_(src),
|
||||
tgt_(tgt),
|
||||
V_(0.0)
|
||||
{
|
||||
if (!src_.nCells() || !tgt_.nCells())
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "mesh interpolation: cells not on processor: Source cells = "
|
||||
<< src_.nCells() << ", target cells = " << tgt_.nCells()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::meshToMeshMethod::~meshToMeshMethod()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::meshToMeshMethod::writeConnectivity
|
||||
(
|
||||
const polyMesh& mesh1,
|
||||
const polyMesh& mesh2,
|
||||
const labelListList& mesh1ToMesh2Addr
|
||||
) const
|
||||
{
|
||||
Pout<< "Source size = " << mesh1.nCells() << endl;
|
||||
Pout<< "Target size = " << mesh2.nCells() << endl;
|
||||
|
||||
word fName("addressing_" + mesh1.name() + "_to_" + mesh2.name());
|
||||
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
fName = fName + "_proc" + Foam::name(Pstream::myProcNo());
|
||||
}
|
||||
|
||||
OFstream os(src_.time().path()/fName + ".obj");
|
||||
|
||||
label vertI = 0;
|
||||
forAll(mesh1ToMesh2Addr, i)
|
||||
{
|
||||
const labelList& addr = mesh1ToMesh2Addr[i];
|
||||
forAll(addr, j)
|
||||
{
|
||||
label cellI = addr[j];
|
||||
const vector& c0 = mesh1.cellCentres()[i];
|
||||
|
||||
const cell& c = mesh2.cells()[cellI];
|
||||
const pointField pts(c.points(mesh2.faces(), mesh2.points()));
|
||||
forAll(pts, j)
|
||||
{
|
||||
const point& p = pts[j];
|
||||
os << "v " << p.x() << ' ' << p.y() << ' ' << p.z() << nl;
|
||||
vertI++;
|
||||
os << "v " << c0.x() << ' ' << c0.y() << ' ' << c0.z()
|
||||
<< nl;
|
||||
vertI++;
|
||||
os << "l " << vertI - 1 << ' ' << vertI << nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,196 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::meshToMeshMethod
|
||||
|
||||
Description
|
||||
Base class for mesh-to-mesh calculation methods
|
||||
|
||||
SourceFiles
|
||||
meshToMeshMethod.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef meshToMeshMethod_H
|
||||
#define meshToMeshMethod_H
|
||||
|
||||
#include "polyMesh.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class meshToMeshMethod Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class meshToMeshMethod
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Reference to the source mesh
|
||||
const polyMesh& src_;
|
||||
|
||||
//- Reference to the target mesh
|
||||
const polyMesh& tgt_;
|
||||
|
||||
//- Cell total volume in overlap region [m3]
|
||||
scalar V_;
|
||||
|
||||
//- Tolerance used in volume overlap calculations
|
||||
static scalar tolerance_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Return src cell IDs for the overlap region
|
||||
labelList maskCells() const;
|
||||
|
||||
//- Return the true if cells intersect
|
||||
virtual bool intersect
|
||||
(
|
||||
const label srcCellI,
|
||||
const label tgtCellI
|
||||
) const;
|
||||
|
||||
//- Return the intersection volume between two cells
|
||||
virtual scalar interVol
|
||||
(
|
||||
const label srcCellI,
|
||||
const label tgtCellI
|
||||
) const;
|
||||
|
||||
//- Append target cell neihgbour cells to cellIDs list
|
||||
virtual void appendNbrCells
|
||||
(
|
||||
const label tgtCellI,
|
||||
const polyMesh& mesh,
|
||||
const DynamicList<label>& visitedTgtCells,
|
||||
DynamicList<label>& nbrTgtCellIDs
|
||||
) const;
|
||||
|
||||
virtual bool initialise
|
||||
(
|
||||
labelListList& srcToTgtAddr,
|
||||
scalarListList& srcToTgtWght,
|
||||
labelListList& tgtToTgtAddr,
|
||||
scalarListList& tgtToTgtWght
|
||||
) const;
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
meshToMeshMethod(const meshToMeshMethod&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const meshToMeshMethod&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("meshToMeshMethod");
|
||||
|
||||
//- Declare runtime constructor selection table
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
meshToMeshMethod,
|
||||
components,
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt
|
||||
),
|
||||
(src, tgt)
|
||||
);
|
||||
|
||||
//- Construct from source and target meshes
|
||||
meshToMeshMethod(const polyMesh& src, const polyMesh& tgt);
|
||||
|
||||
//- Selector
|
||||
static autoPtr<meshToMeshMethod> New
|
||||
(
|
||||
const word& methodName,
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~meshToMeshMethod();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Evaluate
|
||||
|
||||
//- Calculate addressing and weights
|
||||
virtual void calculate
|
||||
(
|
||||
labelListList& srcToTgtAddr,
|
||||
scalarListList& srcToTgtWght,
|
||||
labelListList& tgtToTgtAddr,
|
||||
scalarListList& tgtToTgtWght
|
||||
) = 0;
|
||||
|
||||
|
||||
// Access
|
||||
|
||||
//- Return const access to the source mesh
|
||||
inline const polyMesh& src() const;
|
||||
|
||||
//- Return const access to the target mesh
|
||||
inline const polyMesh& tgt() const;
|
||||
|
||||
//- Return const access to the overlap volume
|
||||
inline scalar V() const;
|
||||
|
||||
|
||||
// Check
|
||||
|
||||
//- Write the connectivity (debugging)
|
||||
void writeConnectivity
|
||||
(
|
||||
const polyMesh& mesh1,
|
||||
const polyMesh& mesh2,
|
||||
const labelListList& mesh1ToMesh2Addr
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "meshToMeshMethodI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,44 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
const Foam::polyMesh& Foam::meshToMeshMethod::src() const
|
||||
{
|
||||
return src_;
|
||||
}
|
||||
|
||||
|
||||
const Foam::polyMesh& Foam::meshToMeshMethod::tgt() const
|
||||
{
|
||||
return tgt_;
|
||||
}
|
||||
|
||||
|
||||
Foam::scalar Foam::meshToMeshMethod::V() const
|
||||
{
|
||||
return V_;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,65 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "meshToMeshMethod.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::meshToMeshMethod> Foam::meshToMeshMethod::New
|
||||
(
|
||||
const word& methodName,
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt
|
||||
)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "Selecting AMIMethod " << methodName << endl;
|
||||
}
|
||||
|
||||
componentsConstructorTable::iterator cstrIter =
|
||||
componentsConstructorTablePtr_->find(methodName);
|
||||
|
||||
if (cstrIter == componentsConstructorTablePtr_->end())
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"Foam::autoPtr<Foam::meshToMeshMethod> Foam::meshToMeshMethod::New"
|
||||
"("
|
||||
"const word&, "
|
||||
"const polyMesh&, "
|
||||
"const polyMesh&"
|
||||
")"
|
||||
) << "Unknown meshToMesh type "
|
||||
<< methodName << nl << nl
|
||||
<< "Valid meshToMesh types are:" << nl
|
||||
<< componentsConstructorTablePtr_->sortedToc() << exit(FatalError);
|
||||
}
|
||||
|
||||
return autoPtr<meshToMeshMethod>(cstrIter()(src, tgt));
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
672
src/sampling/meshToMesh/meshToMesh.C
Normal file
672
src/sampling/meshToMesh/meshToMesh.C
Normal file
@ -0,0 +1,672 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2012-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "meshToMesh.H"
|
||||
#include "Time.H"
|
||||
#include "globalIndex.H"
|
||||
#include "meshToMeshMethod.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(meshToMesh, 0);
|
||||
|
||||
template<>
|
||||
const char* Foam::NamedEnum
|
||||
<
|
||||
Foam::meshToMesh::interpolationMethod,
|
||||
3
|
||||
>::names[] =
|
||||
{
|
||||
"direct",
|
||||
"mapNearest",
|
||||
"cellVolumeWeight"
|
||||
};
|
||||
|
||||
const NamedEnum<meshToMesh::interpolationMethod, 3>
|
||||
meshToMesh::interpolationMethodNames_;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::labelList Foam::meshToMesh::maskCells
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt
|
||||
) const
|
||||
{
|
||||
boundBox intersectBb
|
||||
(
|
||||
max(src.bounds().min(), tgt.bounds().min()),
|
||||
min(src.bounds().max(), tgt.bounds().max())
|
||||
);
|
||||
|
||||
intersectBb.inflate(0.01);
|
||||
|
||||
const cellList& srcCells = src.cells();
|
||||
const faceList& srcFaces = src.faces();
|
||||
const pointField& srcPts = src.points();
|
||||
|
||||
DynamicList<label> cells(src.size());
|
||||
forAll(srcCells, srcI)
|
||||
{
|
||||
boundBox cellBb(srcCells[srcI].points(srcFaces, srcPts), false);
|
||||
if (intersectBb.overlaps(cellBb))
|
||||
{
|
||||
cells.append(srcI);
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "participating source mesh cells: " << cells.size() << endl;
|
||||
}
|
||||
|
||||
return cells;
|
||||
}
|
||||
|
||||
|
||||
void Foam::meshToMesh::normaliseWeights
|
||||
(
|
||||
const word& descriptor,
|
||||
const labelListList& addr,
|
||||
scalarListList& wght
|
||||
) const
|
||||
{
|
||||
const label nCell = returnReduce(wght.size(), sumOp<label>());
|
||||
|
||||
if (nCell > 0)
|
||||
{
|
||||
forAll(wght, cellI)
|
||||
{
|
||||
scalarList& w = wght[cellI];
|
||||
scalar s = sum(w);
|
||||
|
||||
forAll(w, i)
|
||||
{
|
||||
// note: normalise by s instead of cell volume since
|
||||
// 1-to-1 methods duplicate contributions in parallel
|
||||
w[i] /= s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::meshToMesh::calcAddressing
|
||||
(
|
||||
const word& methodName,
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt
|
||||
)
|
||||
{
|
||||
autoPtr<meshToMeshMethod> methodPtr
|
||||
(
|
||||
meshToMeshMethod::New
|
||||
(
|
||||
methodName,
|
||||
src,
|
||||
tgt
|
||||
)
|
||||
);
|
||||
|
||||
methodPtr->calculate
|
||||
(
|
||||
srcToTgtCellAddr_,
|
||||
srcToTgtCellWght_,
|
||||
tgtToSrcCellAddr_,
|
||||
tgtToSrcCellWght_
|
||||
);
|
||||
|
||||
V_ = methodPtr->V();
|
||||
|
||||
if (debug)
|
||||
{
|
||||
methodPtr->writeConnectivity(src, tgt, srcToTgtCellAddr_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::meshToMesh::calculate(const word& methodName)
|
||||
{
|
||||
Info<< "Creating mesh-to-mesh addressing for " << srcRegion_.name()
|
||||
<< " and " << tgtRegion_.name() << " regions using "
|
||||
<< methodName << endl;
|
||||
|
||||
singleMeshProc_ = calcDistribution(srcRegion_, tgtRegion_);
|
||||
|
||||
if (singleMeshProc_ == -1)
|
||||
{
|
||||
// create global indexing for src and tgt meshes
|
||||
globalIndex globalSrcCells(srcRegion_.nCells());
|
||||
globalIndex globalTgtCells(tgtRegion_.nCells());
|
||||
|
||||
// Create processor map of overlapping cells. This map gets
|
||||
// (possibly remote) cells from the tgt mesh such that they (together)
|
||||
// cover all of the src mesh
|
||||
autoPtr<mapDistribute> mapPtr = calcProcMap(srcRegion_, tgtRegion_);
|
||||
const mapDistribute& map = mapPtr();
|
||||
|
||||
pointField newTgtPoints;
|
||||
faceList newTgtFaces;
|
||||
labelList newTgtFaceOwners;
|
||||
labelList newTgtFaceNeighbours;
|
||||
labelList newTgtCellIDs;
|
||||
|
||||
distributeAndMergeCells
|
||||
(
|
||||
map,
|
||||
tgtRegion_,
|
||||
globalTgtCells,
|
||||
newTgtPoints,
|
||||
newTgtFaces,
|
||||
newTgtFaceOwners,
|
||||
newTgtFaceNeighbours,
|
||||
newTgtCellIDs
|
||||
);
|
||||
|
||||
|
||||
// create a new target mesh
|
||||
polyMesh newTgt
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"newTgt." + Foam::name(Pstream::myProcNo()),
|
||||
tgtRegion_.time().timeName(),
|
||||
tgtRegion_.time(),
|
||||
IOobject::NO_READ
|
||||
),
|
||||
xferMove(newTgtPoints),
|
||||
xferMove(newTgtFaces),
|
||||
xferMove(newTgtFaceOwners),
|
||||
xferMove(newTgtFaceNeighbours),
|
||||
false // no parallel comms
|
||||
);
|
||||
|
||||
// create some dummy patch info
|
||||
List<polyPatch*> patches(1);
|
||||
patches[0] = new polyPatch
|
||||
(
|
||||
"defaultFaces",
|
||||
newTgt.nFaces() - newTgt.nInternalFaces(),
|
||||
newTgt.nInternalFaces(),
|
||||
0,
|
||||
newTgt.boundaryMesh(),
|
||||
word::null
|
||||
);
|
||||
|
||||
newTgt.addPatches(patches);
|
||||
|
||||
// force calculation of tet-base points used for point-in-cell
|
||||
(void)newTgt.tetBasePtIs();
|
||||
|
||||
// force construction of cell tree
|
||||
// (void)newTgt.cellTree();
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Created newTgt mesh:" << nl
|
||||
<< " old cells = " << tgtRegion_.nCells()
|
||||
<< ", new cells = " << newTgt.nCells() << nl
|
||||
<< " old faces = " << tgtRegion_.nFaces()
|
||||
<< ", new faces = " << newTgt.nFaces() << endl;
|
||||
|
||||
if (debug > 1)
|
||||
{
|
||||
Pout<< "Writing newTgt mesh: " << newTgt.name() << endl;
|
||||
newTgt.write();
|
||||
}
|
||||
}
|
||||
|
||||
calcAddressing(methodName, srcRegion_, newTgt);
|
||||
|
||||
// per source cell the target cell address in newTgt mesh
|
||||
forAll(srcToTgtCellAddr_, i)
|
||||
{
|
||||
labelList& addressing = srcToTgtCellAddr_[i];
|
||||
forAll(addressing, addrI)
|
||||
{
|
||||
addressing[addrI] = newTgtCellIDs[addressing[addrI]];
|
||||
}
|
||||
}
|
||||
|
||||
// convert target addresses in newTgtMesh into global cell numbering
|
||||
forAll(tgtToSrcCellAddr_, i)
|
||||
{
|
||||
labelList& addressing = tgtToSrcCellAddr_[i];
|
||||
forAll(addressing, addrI)
|
||||
{
|
||||
addressing[addrI] = globalSrcCells.toGlobal(addressing[addrI]);
|
||||
}
|
||||
}
|
||||
|
||||
// set up as a reverse distribute
|
||||
mapDistribute::distribute
|
||||
(
|
||||
Pstream::nonBlocking,
|
||||
List<labelPair>(),
|
||||
tgtRegion_.nCells(),
|
||||
map.constructMap(),
|
||||
map.subMap(),
|
||||
tgtToSrcCellAddr_,
|
||||
ListPlusEqOp<label>(),
|
||||
labelList()
|
||||
);
|
||||
|
||||
// set up as a reverse distribute
|
||||
mapDistribute::distribute
|
||||
(
|
||||
Pstream::nonBlocking,
|
||||
List<labelPair>(),
|
||||
tgtRegion_.nCells(),
|
||||
map.constructMap(),
|
||||
map.subMap(),
|
||||
tgtToSrcCellWght_,
|
||||
ListPlusEqOp<scalar>(),
|
||||
scalarList()
|
||||
);
|
||||
|
||||
// weights normalisation
|
||||
normaliseWeights
|
||||
(
|
||||
"source",
|
||||
srcToTgtCellAddr_,
|
||||
srcToTgtCellWght_
|
||||
);
|
||||
|
||||
normaliseWeights
|
||||
(
|
||||
"target",
|
||||
tgtToSrcCellAddr_,
|
||||
tgtToSrcCellWght_
|
||||
);
|
||||
|
||||
// cache maps and reset addresses
|
||||
List<Map<label> > cMap;
|
||||
srcMapPtr_.reset
|
||||
(
|
||||
new mapDistribute(globalSrcCells, tgtToSrcCellAddr_, cMap)
|
||||
);
|
||||
tgtMapPtr_.reset
|
||||
(
|
||||
new mapDistribute(globalTgtCells, srcToTgtCellAddr_, cMap)
|
||||
);
|
||||
|
||||
// collect volume intersection contributions
|
||||
reduce(V_, sumOp<scalar>());
|
||||
}
|
||||
else
|
||||
{
|
||||
calcAddressing(methodName, srcRegion_, tgtRegion_);
|
||||
|
||||
normaliseWeights
|
||||
(
|
||||
"source",
|
||||
srcToTgtCellAddr_,
|
||||
srcToTgtCellWght_
|
||||
);
|
||||
|
||||
normaliseWeights
|
||||
(
|
||||
"target",
|
||||
tgtToSrcCellAddr_,
|
||||
tgtToSrcCellWght_
|
||||
);
|
||||
}
|
||||
|
||||
Info<< " Overlap volume: " << V_ << endl;
|
||||
}
|
||||
|
||||
|
||||
Foam::AMIPatchToPatchInterpolation::interpolationMethod
|
||||
Foam::meshToMesh::interpolationMethodAMI(const interpolationMethod method)
|
||||
{
|
||||
switch (method)
|
||||
{
|
||||
case imDirect:
|
||||
{
|
||||
return AMIPatchToPatchInterpolation::imDirect;
|
||||
break;
|
||||
}
|
||||
case imMapNearest:
|
||||
{
|
||||
return AMIPatchToPatchInterpolation::imMapNearest;
|
||||
break;
|
||||
}
|
||||
case imCellVolumeWeight:
|
||||
{
|
||||
return AMIPatchToPatchInterpolation::imFaceAreaWeight;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"Foam::AMIPatchToPatchInterpolation::interpolationMethod"
|
||||
"Foam::meshToMesh::interpolationMethodAMI"
|
||||
"("
|
||||
"const interpolationMethod method"
|
||||
") const"
|
||||
)
|
||||
<< "Unhandled enumeration " << method
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
return AMIPatchToPatchInterpolation::imDirect;
|
||||
}
|
||||
|
||||
|
||||
void Foam::meshToMesh::calculatePatchAMIs(const word& AMIMethodName)
|
||||
{
|
||||
if (!patchAMIs_.empty())
|
||||
{
|
||||
FatalErrorIn("meshToMesh::calculatePatchAMIs()")
|
||||
<< "patch AMI already calculated"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
patchAMIs_.setSize(srcPatchID_.size());
|
||||
|
||||
forAll(srcPatchID_, i)
|
||||
{
|
||||
label srcPatchI = srcPatchID_[i];
|
||||
label tgtPatchI = tgtPatchID_[i];
|
||||
|
||||
const polyPatch& srcPP = srcRegion_.boundaryMesh()[srcPatchI];
|
||||
const polyPatch& tgtPP = tgtRegion_.boundaryMesh()[tgtPatchI];
|
||||
|
||||
Info<< "Creating AMI between source patch " << srcPP.name()
|
||||
<< " and target patch " << tgtPP.name()
|
||||
<< " using " << AMIMethodName
|
||||
<< endl;
|
||||
|
||||
Info<< incrIndent;
|
||||
|
||||
patchAMIs_.set
|
||||
(
|
||||
i,
|
||||
new AMIPatchToPatchInterpolation
|
||||
(
|
||||
srcPP,
|
||||
tgtPP,
|
||||
faceAreaIntersect::tmMesh,
|
||||
false,
|
||||
AMIMethodName,
|
||||
-1,
|
||||
true // flip target patch since patch normals are aligned
|
||||
)
|
||||
);
|
||||
|
||||
Info<< decrIndent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::meshToMesh::constructNoCuttingPatches
|
||||
(
|
||||
const word& methodName,
|
||||
const word& AMIMethodName,
|
||||
const bool interpAllPatches
|
||||
)
|
||||
{
|
||||
if (interpAllPatches)
|
||||
{
|
||||
const polyBoundaryMesh& srcBM = srcRegion_.boundaryMesh();
|
||||
const polyBoundaryMesh& tgtBM = tgtRegion_.boundaryMesh();
|
||||
|
||||
DynamicList<label> srcPatchID(srcBM.size());
|
||||
DynamicList<label> tgtPatchID(tgtBM.size());
|
||||
forAll(srcBM, patchI)
|
||||
{
|
||||
const polyPatch& pp = srcBM[patchI];
|
||||
if (!polyPatch::constraintType(pp.type()))
|
||||
{
|
||||
srcPatchID.append(pp.index());
|
||||
|
||||
label tgtPatchI = tgtBM.findPatchID(pp.name());
|
||||
|
||||
if (tgtPatchI != -1)
|
||||
{
|
||||
tgtPatchID.append(tgtPatchI);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"Foam::meshToMesh::meshToMesh"
|
||||
"("
|
||||
"const polyMesh&, "
|
||||
"const polyMesh&, "
|
||||
"const interpolationMethod&, "
|
||||
"bool"
|
||||
")"
|
||||
) << "Source patch " << pp.name()
|
||||
<< " not found in target mesh. "
|
||||
<< "Available target patches are " << tgtBM.names()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
srcPatchID_.transfer(srcPatchID);
|
||||
tgtPatchID_.transfer(tgtPatchID);
|
||||
}
|
||||
|
||||
// calculate volume addressing and weights
|
||||
calculate(methodName);
|
||||
|
||||
// calculate patch addressing and weights
|
||||
calculatePatchAMIs(AMIMethodName);
|
||||
}
|
||||
|
||||
|
||||
void Foam::meshToMesh::constructFromCuttingPatches
|
||||
(
|
||||
const word& methodName,
|
||||
const word& AMIMethodName,
|
||||
const HashTable<word>& patchMap,
|
||||
const wordList& cuttingPatches
|
||||
)
|
||||
{
|
||||
srcPatchID_.setSize(patchMap.size());
|
||||
tgtPatchID_.setSize(patchMap.size());
|
||||
|
||||
label i = 0;
|
||||
forAllConstIter(HashTable<word>, patchMap, iter)
|
||||
{
|
||||
const word& tgtPatchName = iter.key();
|
||||
const word& srcPatchName = iter();
|
||||
|
||||
const polyPatch& srcPatch = srcRegion_.boundaryMesh()[srcPatchName];
|
||||
const polyPatch& tgtPatch = tgtRegion_.boundaryMesh()[tgtPatchName];
|
||||
|
||||
srcPatchID_[i] = srcPatch.index();
|
||||
tgtPatchID_[i] = tgtPatch.index();
|
||||
i++;
|
||||
}
|
||||
|
||||
// calculate volume addressing and weights
|
||||
calculate(methodName);
|
||||
|
||||
// calculate patch addressing and weights
|
||||
calculatePatchAMIs(AMIMethodName);
|
||||
|
||||
// set IDs of cutting patches on target mesh
|
||||
cuttingPatches_.setSize(cuttingPatches.size());
|
||||
forAll(cuttingPatches_, i)
|
||||
{
|
||||
const word& patchName = cuttingPatches[i];
|
||||
cuttingPatches_[i] = tgtRegion_.boundaryMesh().findPatchID(patchName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::meshToMesh::meshToMesh
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt,
|
||||
const interpolationMethod& method,
|
||||
bool interpAllPatches
|
||||
)
|
||||
:
|
||||
srcRegion_(src),
|
||||
tgtRegion_(tgt),
|
||||
srcPatchID_(),
|
||||
tgtPatchID_(),
|
||||
patchAMIs_(),
|
||||
cuttingPatches_(),
|
||||
srcToTgtCellAddr_(),
|
||||
tgtToSrcCellAddr_(),
|
||||
srcToTgtCellWght_(),
|
||||
tgtToSrcCellWght_(),
|
||||
V_(0.0),
|
||||
singleMeshProc_(-1),
|
||||
srcMapPtr_(NULL),
|
||||
tgtMapPtr_(NULL)
|
||||
{
|
||||
constructNoCuttingPatches
|
||||
(
|
||||
interpolationMethodNames_[method],
|
||||
AMIPatchToPatchInterpolation::interpolationMethodToWord
|
||||
(
|
||||
interpolationMethodAMI(method)
|
||||
),
|
||||
interpAllPatches
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Foam::meshToMesh::meshToMesh
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt,
|
||||
const word& methodName,
|
||||
const word& AMIMethodName,
|
||||
bool interpAllPatches
|
||||
)
|
||||
:
|
||||
srcRegion_(src),
|
||||
tgtRegion_(tgt),
|
||||
srcPatchID_(),
|
||||
tgtPatchID_(),
|
||||
patchAMIs_(),
|
||||
cuttingPatches_(),
|
||||
srcToTgtCellAddr_(),
|
||||
tgtToSrcCellAddr_(),
|
||||
srcToTgtCellWght_(),
|
||||
tgtToSrcCellWght_(),
|
||||
V_(0.0),
|
||||
singleMeshProc_(-1),
|
||||
srcMapPtr_(NULL),
|
||||
tgtMapPtr_(NULL)
|
||||
{
|
||||
constructNoCuttingPatches(methodName, AMIMethodName, interpAllPatches);
|
||||
}
|
||||
|
||||
|
||||
Foam::meshToMesh::meshToMesh
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt,
|
||||
const interpolationMethod& method,
|
||||
const HashTable<word>& patchMap,
|
||||
const wordList& cuttingPatches
|
||||
)
|
||||
:
|
||||
srcRegion_(src),
|
||||
tgtRegion_(tgt),
|
||||
srcPatchID_(),
|
||||
tgtPatchID_(),
|
||||
patchAMIs_(),
|
||||
cuttingPatches_(),
|
||||
srcToTgtCellAddr_(),
|
||||
tgtToSrcCellAddr_(),
|
||||
srcToTgtCellWght_(),
|
||||
tgtToSrcCellWght_(),
|
||||
V_(0.0),
|
||||
singleMeshProc_(-1),
|
||||
srcMapPtr_(NULL),
|
||||
tgtMapPtr_(NULL)
|
||||
{
|
||||
constructFromCuttingPatches
|
||||
(
|
||||
interpolationMethodNames_[method],
|
||||
AMIPatchToPatchInterpolation::interpolationMethodToWord
|
||||
(
|
||||
interpolationMethodAMI(method)
|
||||
),
|
||||
patchMap,
|
||||
cuttingPatches
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Foam::meshToMesh::meshToMesh
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt,
|
||||
const word& methodName, // internal mapping
|
||||
const word& AMIMethodName, // boundary mapping
|
||||
const HashTable<word>& patchMap,
|
||||
const wordList& cuttingPatches
|
||||
)
|
||||
:
|
||||
srcRegion_(src),
|
||||
tgtRegion_(tgt),
|
||||
srcPatchID_(),
|
||||
tgtPatchID_(),
|
||||
patchAMIs_(),
|
||||
cuttingPatches_(),
|
||||
srcToTgtCellAddr_(),
|
||||
tgtToSrcCellAddr_(),
|
||||
srcToTgtCellWght_(),
|
||||
tgtToSrcCellWght_(),
|
||||
V_(0.0),
|
||||
singleMeshProc_(-1),
|
||||
srcMapPtr_(NULL),
|
||||
tgtMapPtr_(NULL)
|
||||
{
|
||||
constructFromCuttingPatches
|
||||
(
|
||||
methodName,
|
||||
AMIMethodName,
|
||||
patchMap,
|
||||
cuttingPatches
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::meshToMesh::~meshToMesh()
|
||||
{}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
543
src/sampling/meshToMesh/meshToMesh.H
Normal file
543
src/sampling/meshToMesh/meshToMesh.H
Normal file
@ -0,0 +1,543 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2012-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::meshToMesh
|
||||
|
||||
Description
|
||||
Class to calculate the cell-addressing between two overlapping meshes
|
||||
|
||||
Mapping is performed using a run-time selectable interpolation mothod
|
||||
|
||||
SeeAlso
|
||||
meshToMeshMethod
|
||||
|
||||
SourceFiles
|
||||
meshToMesh.C
|
||||
meshToMeshParallelOps.C
|
||||
meshToMeshTemplates.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef meshToMesh_H
|
||||
#define meshToMesh_H
|
||||
|
||||
#include "polyMesh.H"
|
||||
#include "boundBox.H"
|
||||
#include "mapDistribute.H"
|
||||
#include "volFieldsFwd.H"
|
||||
#include "NamedEnum.H"
|
||||
#include "AMIPatchToPatchInterpolation.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class meshToMesh Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class meshToMesh
|
||||
{
|
||||
public:
|
||||
|
||||
// Public data types
|
||||
|
||||
//- Enumeration specifying interpolation method
|
||||
enum interpolationMethod
|
||||
{
|
||||
imDirect,
|
||||
imMapNearest,
|
||||
imCellVolumeWeight
|
||||
};
|
||||
|
||||
static const NamedEnum<interpolationMethod, 3>
|
||||
interpolationMethodNames_;
|
||||
|
||||
private:
|
||||
|
||||
// Private data
|
||||
|
||||
//- Reference to the source mesh
|
||||
const polyMesh& srcRegion_;
|
||||
|
||||
//- Reference to the target mesh
|
||||
const polyMesh& tgtRegion_;
|
||||
|
||||
//- List of target patch IDs per source patch (local index)
|
||||
List<label> srcPatchID_;
|
||||
|
||||
//- List of source patch IDs per target patch (local index)
|
||||
List<label> tgtPatchID_;
|
||||
|
||||
//- List of AMIs between source and target patches
|
||||
PtrList<AMIPatchToPatchInterpolation> patchAMIs_;
|
||||
|
||||
//- Cutting patches whose values are set using a zero-gradient condition
|
||||
List<label> cuttingPatches_;
|
||||
|
||||
//- Source to target cell addressing
|
||||
labelListList srcToTgtCellAddr_;
|
||||
|
||||
//- Target to source cell addressing
|
||||
labelListList tgtToSrcCellAddr_;
|
||||
|
||||
//- Source to target cell interplation weights
|
||||
scalarListList srcToTgtCellWght_;
|
||||
|
||||
//- Target to source cell interpolation weights
|
||||
scalarListList tgtToSrcCellWght_;
|
||||
|
||||
//- Cell total volume in overlap region [m3]
|
||||
scalar V_;
|
||||
|
||||
//- Index of processor that holds all of both sides. -1 in all other
|
||||
// cases
|
||||
label singleMeshProc_;
|
||||
|
||||
//- Source map pointer - parallel running only
|
||||
autoPtr<mapDistribute> srcMapPtr_;
|
||||
|
||||
//- Target map pointer - parallel running only
|
||||
autoPtr<mapDistribute> tgtMapPtr_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Helper function to add a constant offset to a list
|
||||
template<class Type>
|
||||
void add(UList<Type>& fld, const label offset) const;
|
||||
|
||||
//- Return src cell IDs for the overlap region
|
||||
labelList maskCells(const polyMesh& src, const polyMesh& tgt) const;
|
||||
|
||||
//- Normalise the interpolation weights
|
||||
void normaliseWeights
|
||||
(
|
||||
const word& descriptor,
|
||||
const labelListList& addr,
|
||||
scalarListList& wght
|
||||
) const;
|
||||
|
||||
//- Calculate the addressing between overlapping regions of src and tgt
|
||||
// meshes
|
||||
void calcAddressing
|
||||
(
|
||||
const word& methodName,
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt
|
||||
);
|
||||
|
||||
//- Calculate - main driver function
|
||||
void calculate(const word& methodName);
|
||||
|
||||
//- Calculate patch overlap
|
||||
void calculatePatchAMIs(const word& amiMethodName);
|
||||
|
||||
//- Constructor helper
|
||||
void constructNoCuttingPatches
|
||||
(
|
||||
const word& methodName,
|
||||
const word& AMIMethodName,
|
||||
const bool interpAllPatches
|
||||
);
|
||||
|
||||
//- Constructor helper
|
||||
void constructFromCuttingPatches
|
||||
(
|
||||
const word& methodName,
|
||||
const word& AMIMethodName,
|
||||
const HashTable<word>& patchMap,
|
||||
const wordList& cuttingPatches
|
||||
);
|
||||
|
||||
//- Return the list of AMIs between source and target patches
|
||||
inline const PtrList<AMIPatchToPatchInterpolation>&
|
||||
patchAMIs() const;
|
||||
|
||||
|
||||
// Parallel operations
|
||||
|
||||
//- Determine whether the meshes are split across multiple pocessors
|
||||
label calcDistribution
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt
|
||||
) const;
|
||||
|
||||
//- Determine which processor bounding-boxes overlap
|
||||
label calcOverlappingProcs
|
||||
(
|
||||
const List<boundBox>& procBb,
|
||||
const boundBox& bb,
|
||||
boolList& overlaps
|
||||
) const;
|
||||
|
||||
//- Calculate the mapping between processors
|
||||
autoPtr<mapDistribute> calcProcMap
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt
|
||||
) const;
|
||||
|
||||
//- Distribute mesh info from 'my' processor to others
|
||||
void distributeCells
|
||||
(
|
||||
const mapDistribute& map,
|
||||
const polyMesh& tgtMesh,
|
||||
const globalIndex& globalI,
|
||||
List<pointField>& points,
|
||||
List<label>& nInternalFaces,
|
||||
List<faceList>& faces,
|
||||
List<labelList>& faceOwner,
|
||||
List<labelList>& faceNeighbour,
|
||||
List<labelList>& cellIDs,
|
||||
List<labelList>& nbrProcIDs,
|
||||
List<labelList>& procLocalFaceIDs
|
||||
) const;
|
||||
|
||||
//- Collect pieces of tgt mesh from other procssors and restructure
|
||||
void distributeAndMergeCells
|
||||
(
|
||||
const mapDistribute& map,
|
||||
const polyMesh& tgt,
|
||||
const globalIndex& globalI,
|
||||
pointField& tgtPoints,
|
||||
faceList& tgtFaces,
|
||||
labelList& tgtFaceOwners,
|
||||
labelList& tgtFaceNeighbours,
|
||||
labelList& tgtCellIDs
|
||||
) const;
|
||||
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
meshToMesh(const meshToMesh&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const meshToMesh&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("meshToMesh");
|
||||
|
||||
|
||||
//- Construct from source and target meshes
|
||||
meshToMesh
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt,
|
||||
const interpolationMethod& method,
|
||||
const bool interpAllPatches = true
|
||||
);
|
||||
|
||||
//- Construct from source and target meshes, generic mapping methods
|
||||
meshToMesh
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt,
|
||||
const word& methodName, // internal mapping
|
||||
const word& AMIMethodName, // boundary mapping
|
||||
const bool interpAllPatches = true
|
||||
);
|
||||
|
||||
//- Construct from source and target meshes
|
||||
meshToMesh
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt,
|
||||
const interpolationMethod& method,
|
||||
const HashTable<word>& patchMap,
|
||||
const wordList& cuttingPatches
|
||||
);
|
||||
|
||||
|
||||
//- Construct from source and target meshes, generic mapping methods
|
||||
meshToMesh
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt,
|
||||
const word& methodName, // internal mapping
|
||||
const word& AMIMethodName, // boundary mapping
|
||||
const HashTable<word>& patchMap,
|
||||
const wordList& cuttingPatches
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~meshToMesh();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Return const access to the source mesh
|
||||
inline const polyMesh& srcRegion() const;
|
||||
|
||||
//- Return const access to the target mesh
|
||||
inline const polyMesh& tgtRegion() const;
|
||||
|
||||
//- Return const access to the source to target cell addressing
|
||||
inline const labelListList& srcToTgtCellAddr() const;
|
||||
|
||||
//- Return const access to the target to source cell addressing
|
||||
inline const labelListList& tgtToSrcCellAddr() const;
|
||||
|
||||
//- Return const access to the source to target cell weights
|
||||
inline const scalarListList& srcToTgtCellWght() const;
|
||||
|
||||
//- Return const access to the target to source cell weights
|
||||
inline const scalarListList& tgtToSrcCellWght() const;
|
||||
|
||||
//- Return const access to the overlap volume
|
||||
inline scalar V() const;
|
||||
|
||||
//- Conversion between mesh and patch interpolation methods
|
||||
static AMIPatchToPatchInterpolation::interpolationMethod
|
||||
interpolationMethodAMI
|
||||
(
|
||||
const interpolationMethod method
|
||||
);
|
||||
|
||||
|
||||
// Evaluation
|
||||
|
||||
// Source-to-target field mapping
|
||||
|
||||
//- Map field from src to tgt mesh with defined operation
|
||||
// Values passed in via 'result' are used to initialise the
|
||||
// return value
|
||||
template<class Type, class CombineOp>
|
||||
void mapSrcToTgt
|
||||
(
|
||||
const UList<Type>& srcFld,
|
||||
const CombineOp& cop,
|
||||
List<Type>& result
|
||||
) const;
|
||||
|
||||
//- Return the src field mapped to the tgt mesh with a defined
|
||||
// operation. Initial values of the result are set to zero
|
||||
template<class Type, class CombineOp>
|
||||
tmp<Field<Type> > mapSrcToTgt
|
||||
(
|
||||
const Field<Type>& srcFld,
|
||||
const CombineOp& cop
|
||||
) const;
|
||||
|
||||
//- Convenience function to map a tmp field to the tgt mesh
|
||||
// with a defined operation
|
||||
template<class Type, class CombineOp>
|
||||
tmp<Field<Type> > mapSrcToTgt
|
||||
(
|
||||
const tmp<Field<Type> >& tsrcFld,
|
||||
const CombineOp& cop
|
||||
) const;
|
||||
|
||||
//- Convenience function to map a field to the tgt mesh with a
|
||||
// default operation (plusEqOp)
|
||||
template<class Type>
|
||||
tmp<Field<Type> > mapSrcToTgt
|
||||
(
|
||||
const Field<Type>& srcFld
|
||||
) const;
|
||||
|
||||
//- Convenience function to map a tmp field to the tgt mesh
|
||||
// with a default operation (plusEqOp)
|
||||
template<class Type>
|
||||
tmp<Field<Type> > mapSrcToTgt
|
||||
(
|
||||
const tmp<Field<Type> >& tsrcFld
|
||||
) const;
|
||||
|
||||
|
||||
// Target-to-source field mapping
|
||||
|
||||
//- Map field from tgt to src mesh with defined operation
|
||||
// Values passed in via 'result' are used to initialise the
|
||||
// return value
|
||||
template<class Type, class CombineOp>
|
||||
void mapTgtToSrc
|
||||
(
|
||||
const UList<Type>& tgtFld,
|
||||
const CombineOp& cop,
|
||||
List<Type>& result
|
||||
) const;
|
||||
|
||||
//- Return the tgt field mapped to the src mesh with a defined
|
||||
// operation. Initial values of the result are set to zero
|
||||
template<class Type, class CombineOp>
|
||||
tmp<Field<Type> > mapTgtToSrc
|
||||
(
|
||||
const Field<Type>& tgtFld,
|
||||
const CombineOp& cop
|
||||
) const;
|
||||
|
||||
//- Convenience function to map a tmp field to the src mesh
|
||||
// with a defined operation
|
||||
template<class Type, class CombineOp>
|
||||
tmp<Field<Type> > mapTgtToSrc
|
||||
(
|
||||
const tmp<Field<Type> >& ttgtFld,
|
||||
const CombineOp& cop
|
||||
) const;
|
||||
|
||||
//- Convenience function to map a field to the src mesh with a
|
||||
// default operation (plusEqOp)
|
||||
template<class Type>
|
||||
tmp<Field<Type> > mapTgtToSrc
|
||||
(
|
||||
const Field<Type>& tgtFld
|
||||
) const;
|
||||
|
||||
//- Convenience function to map a tmp field to the src mesh
|
||||
// with a default operation (plusEqOp)
|
||||
template<class Type>
|
||||
tmp<Field<Type> > mapTgtToSrc
|
||||
(
|
||||
const tmp<Field<Type> >& ttgtFld
|
||||
) const;
|
||||
|
||||
|
||||
// Source-to-target volume field mapping
|
||||
|
||||
//- Interpolate a field with a defined operation. Values
|
||||
// passed in via 'result' are used to initialise the return
|
||||
// value
|
||||
template<class Type, class CombineOp>
|
||||
void mapSrcToTgt
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field,
|
||||
const CombineOp& cop,
|
||||
GeometricField<Type, fvPatchField, volMesh>& result
|
||||
) const;
|
||||
|
||||
//- Interpolate a field with a defined operation. The initial
|
||||
// values of the result are set to zero
|
||||
template<class Type, class CombineOp>
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh> > mapSrcToTgt
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field,
|
||||
const CombineOp& cop
|
||||
) const;
|
||||
|
||||
//- Interpolate a tmp field with a defined operation. The
|
||||
// initial values of the result are set to zero
|
||||
template<class Type, class CombineOp>
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh> > mapSrcToTgt
|
||||
(
|
||||
const tmp<GeometricField<Type, fvPatchField, volMesh> >&
|
||||
tfield,
|
||||
const CombineOp& cop
|
||||
) const;
|
||||
|
||||
//- Convenience function to map a field with a default
|
||||
// operation (plusEqOp)
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh> > mapSrcToTgt
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field
|
||||
) const;
|
||||
|
||||
//- Convenience function to map a tmp field with a default
|
||||
// operation (plusEqOp)
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh> > mapSrcToTgt
|
||||
(
|
||||
const tmp<GeometricField<Type, fvPatchField, volMesh> >&
|
||||
tfield
|
||||
) const;
|
||||
|
||||
|
||||
// Target-to-source volume field mapping
|
||||
|
||||
//- Interpolate a field with a defined operation. Values
|
||||
// passed in via 'result' are used to initialise the return
|
||||
// value
|
||||
template<class Type, class CombineOp>
|
||||
void mapTgtToSrc
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field,
|
||||
const CombineOp& cop,
|
||||
GeometricField<Type, fvPatchField, volMesh>& result
|
||||
) const;
|
||||
|
||||
//- Interpolate a field with a defined operation. The initial
|
||||
// values of the result are set to zero
|
||||
template<class Type, class CombineOp>
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh> > mapTgtToSrc
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field,
|
||||
const CombineOp& cop
|
||||
) const;
|
||||
|
||||
//- Interpolate a tmp field with a defined operation. The
|
||||
// initial values of the result are set to zero
|
||||
template<class Type, class CombineOp>
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh> > mapTgtToSrc
|
||||
(
|
||||
const tmp<GeometricField<Type, fvPatchField, volMesh> >&
|
||||
tfield,
|
||||
const CombineOp& cop
|
||||
) const;
|
||||
|
||||
//- Convenience function to map a field with a default
|
||||
// operation (plusEqOp)
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh> > mapTgtToSrc
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field
|
||||
) const;
|
||||
|
||||
//- Convenience function to map a tmp field with a default
|
||||
// operation (plusEqOp)
|
||||
template<class Type>
|
||||
tmp<GeometricField<Type, fvPatchField, volMesh> > mapTgtToSrc
|
||||
(
|
||||
const tmp<GeometricField<Type, fvPatchField, volMesh> >&
|
||||
tfield
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "meshToMeshI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "meshToMeshTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
83
src/sampling/meshToMesh/meshToMeshI.H
Normal file
83
src/sampling/meshToMesh/meshToMeshI.H
Normal file
@ -0,0 +1,83 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2012-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "meshToMesh.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
inline const Foam::polyMesh& Foam::meshToMesh::srcRegion() const
|
||||
{
|
||||
return srcRegion_;
|
||||
}
|
||||
|
||||
|
||||
inline const Foam::polyMesh& Foam::meshToMesh::tgtRegion() const
|
||||
{
|
||||
return tgtRegion_;
|
||||
}
|
||||
|
||||
|
||||
inline const Foam::labelListList&
|
||||
Foam::meshToMesh::srcToTgtCellAddr() const
|
||||
{
|
||||
return srcToTgtCellAddr_;
|
||||
}
|
||||
|
||||
|
||||
inline const Foam::labelListList&
|
||||
Foam::meshToMesh::tgtToSrcCellAddr() const
|
||||
{
|
||||
return tgtToSrcCellAddr_;
|
||||
}
|
||||
|
||||
|
||||
inline const Foam::scalarListList&
|
||||
Foam::meshToMesh::srcToTgtCellWght() const
|
||||
{
|
||||
return srcToTgtCellWght_;
|
||||
}
|
||||
|
||||
|
||||
inline const Foam::scalarListList&
|
||||
Foam::meshToMesh::tgtToSrcCellWght() const
|
||||
{
|
||||
return tgtToSrcCellWght_;
|
||||
}
|
||||
|
||||
|
||||
inline Foam::scalar Foam::meshToMesh::V() const
|
||||
{
|
||||
return V_;
|
||||
}
|
||||
|
||||
|
||||
inline const Foam::PtrList<Foam::AMIPatchToPatchInterpolation>&
|
||||
Foam::meshToMesh::patchAMIs() const
|
||||
{
|
||||
return patchAMIs_;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
884
src/sampling/meshToMesh/meshToMeshParallelOps.C
Normal file
884
src/sampling/meshToMesh/meshToMeshParallelOps.C
Normal file
@ -0,0 +1,884 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2012-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "meshToMesh.H"
|
||||
#include "OFstream.H"
|
||||
#include "Time.H"
|
||||
#include "globalIndex.H"
|
||||
#include "mergePoints.H"
|
||||
#include "processorPolyPatch.H"
|
||||
#include "SubField.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::label Foam::meshToMesh::calcDistribution
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt
|
||||
) const
|
||||
{
|
||||
label procI = 0;
|
||||
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
List<label> cellsPresentOnProc(Pstream::nProcs(), 0);
|
||||
if ((src.nCells() > 0) || (tgt.nCells() > 0))
|
||||
{
|
||||
cellsPresentOnProc[Pstream::myProcNo()] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellsPresentOnProc[Pstream::myProcNo()] = 0;
|
||||
}
|
||||
|
||||
Pstream::gatherList(cellsPresentOnProc);
|
||||
Pstream::scatterList(cellsPresentOnProc);
|
||||
|
||||
label nHaveCells = sum(cellsPresentOnProc);
|
||||
|
||||
if (nHaveCells > 1)
|
||||
{
|
||||
procI = -1;
|
||||
if (debug)
|
||||
{
|
||||
Info<< "meshToMesh::calcDistribution: "
|
||||
<< "Meshes split across multiple processors" << endl;
|
||||
}
|
||||
}
|
||||
else if (nHaveCells == 1)
|
||||
{
|
||||
procI = findIndex(cellsPresentOnProc, 1);
|
||||
if (debug)
|
||||
{
|
||||
Info<< "meshToMesh::calcDistribution: "
|
||||
<< "Meshes local to processor" << procI << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return procI;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::meshToMesh::calcOverlappingProcs
|
||||
(
|
||||
const List<boundBox>& procBb,
|
||||
const boundBox& bb,
|
||||
boolList& overlaps
|
||||
) const
|
||||
{
|
||||
overlaps = false;
|
||||
|
||||
label nOverlaps = 0;
|
||||
|
||||
forAll(procBb, procI)
|
||||
{
|
||||
const boundBox& bbp = procBb[procI];
|
||||
|
||||
if (bbp.overlaps(bb))
|
||||
{
|
||||
overlaps[procI] = true;
|
||||
nOverlaps++;
|
||||
}
|
||||
}
|
||||
|
||||
return nOverlaps;
|
||||
}
|
||||
|
||||
|
||||
Foam::autoPtr<Foam::mapDistribute> Foam::meshToMesh::calcProcMap
|
||||
(
|
||||
const polyMesh& src,
|
||||
const polyMesh& tgt
|
||||
) const
|
||||
{
|
||||
// get decomposition of cells on src mesh
|
||||
List<boundBox> procBb(Pstream::nProcs());
|
||||
|
||||
if (src.nCells() > 0)
|
||||
{
|
||||
// bounding box for my mesh - do not parallel reduce
|
||||
procBb[Pstream::myProcNo()] = boundBox(src.points(), false);
|
||||
|
||||
// slightly increase size of bounding boxes to allow for cases where
|
||||
// bounding boxes are perfectly alligned
|
||||
procBb[Pstream::myProcNo()].inflate(0.01);
|
||||
}
|
||||
else
|
||||
{
|
||||
procBb[Pstream::myProcNo()] = boundBox();
|
||||
}
|
||||
|
||||
|
||||
Pstream::gatherList(procBb);
|
||||
Pstream::scatterList(procBb);
|
||||
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "Determining extent of src mesh per processor:" << nl
|
||||
<< "\tproc\tbb" << endl;
|
||||
forAll(procBb, procI)
|
||||
{
|
||||
Info<< '\t' << procI << '\t' << procBb[procI] << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// determine which cells of tgt mesh overlaps src mesh per proc
|
||||
const cellList& cells = tgt.cells();
|
||||
const faceList& faces = tgt.faces();
|
||||
const pointField& points = tgt.points();
|
||||
|
||||
labelListList sendMap;
|
||||
|
||||
{
|
||||
// per processor indices into all segments to send
|
||||
List<DynamicList<label> > dynSendMap(Pstream::nProcs());
|
||||
label iniSize = floor(tgt.nCells()/Pstream::nProcs());
|
||||
|
||||
forAll(dynSendMap, procI)
|
||||
{
|
||||
dynSendMap[procI].setCapacity(iniSize);
|
||||
}
|
||||
|
||||
// work array - whether src processor bb overlaps the tgt cell bounds
|
||||
boolList procBbOverlaps(Pstream::nProcs());
|
||||
forAll(cells, cellI)
|
||||
{
|
||||
const cell& c = cells[cellI];
|
||||
|
||||
// determine bounding box of tgt cell
|
||||
boundBox cellBb(point::max, point::min);
|
||||
forAll(c, faceI)
|
||||
{
|
||||
const face& f = faces[c[faceI]];
|
||||
forAll(f, fp)
|
||||
{
|
||||
cellBb.min() = min(cellBb.min(), points[f[fp]]);
|
||||
cellBb.max() = max(cellBb.max(), points[f[fp]]);
|
||||
}
|
||||
}
|
||||
|
||||
// find the overlapping tgt cells on each src processor
|
||||
(void)calcOverlappingProcs(procBb, cellBb, procBbOverlaps);
|
||||
|
||||
forAll(procBbOverlaps, procI)
|
||||
{
|
||||
if (procBbOverlaps[procI])
|
||||
{
|
||||
dynSendMap[procI].append(cellI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convert dynamicList to labelList
|
||||
sendMap.setSize(Pstream::nProcs());
|
||||
forAll(sendMap, procI)
|
||||
{
|
||||
sendMap[procI].transfer(dynSendMap[procI]);
|
||||
}
|
||||
}
|
||||
|
||||
// debug printing
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Of my " << cells.size() << " target cells I need to send to:"
|
||||
<< nl << "\tproc\tcells" << endl;
|
||||
forAll(sendMap, procI)
|
||||
{
|
||||
Pout<< '\t' << procI << '\t' << sendMap[procI].size() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// send over how many tgt cells I need to receive from each processor
|
||||
labelListList sendSizes(Pstream::nProcs());
|
||||
sendSizes[Pstream::myProcNo()].setSize(Pstream::nProcs());
|
||||
forAll(sendMap, procI)
|
||||
{
|
||||
sendSizes[Pstream::myProcNo()][procI] = sendMap[procI].size();
|
||||
}
|
||||
Pstream::gatherList(sendSizes);
|
||||
Pstream::scatterList(sendSizes);
|
||||
|
||||
|
||||
// determine order of receiving
|
||||
labelListList constructMap(Pstream::nProcs());
|
||||
|
||||
label segmentI = 0;
|
||||
forAll(constructMap, procI)
|
||||
{
|
||||
// what I need to receive is what other processor is sending to me
|
||||
label nRecv = sendSizes[procI][Pstream::myProcNo()];
|
||||
constructMap[procI].setSize(nRecv);
|
||||
|
||||
for (label i = 0; i < nRecv; i++)
|
||||
{
|
||||
constructMap[procI][i] = segmentI++;
|
||||
}
|
||||
}
|
||||
|
||||
autoPtr<mapDistribute> mapPtr
|
||||
(
|
||||
new mapDistribute
|
||||
(
|
||||
segmentI, // size after construction
|
||||
sendMap.xfer(),
|
||||
constructMap.xfer()
|
||||
)
|
||||
);
|
||||
|
||||
return mapPtr;
|
||||
}
|
||||
|
||||
|
||||
void Foam::meshToMesh::distributeCells
|
||||
(
|
||||
const mapDistribute& map,
|
||||
const polyMesh& tgtMesh,
|
||||
const globalIndex& globalI,
|
||||
List<pointField>& points,
|
||||
List<label>& nInternalFaces,
|
||||
List<faceList>& faces,
|
||||
List<labelList>& faceOwner,
|
||||
List<labelList>& faceNeighbour,
|
||||
List<labelList>& cellIDs,
|
||||
List<labelList>& nbrProcIDs,
|
||||
List<labelList>& procLocalFaceIDs
|
||||
) const
|
||||
{
|
||||
PstreamBuffers pBufs(Pstream::nonBlocking);
|
||||
|
||||
points.setSize(Pstream::nProcs());
|
||||
nInternalFaces.setSize(Pstream::nProcs(), 0);
|
||||
faces.setSize(Pstream::nProcs());
|
||||
faceOwner.setSize(Pstream::nProcs());
|
||||
faceNeighbour.setSize(Pstream::nProcs());
|
||||
cellIDs.setSize(Pstream::nProcs());
|
||||
|
||||
nbrProcIDs.setSize(Pstream::nProcs());;
|
||||
procLocalFaceIDs.setSize(Pstream::nProcs());;
|
||||
|
||||
|
||||
for (label domain = 0; domain < Pstream::nProcs(); domain++)
|
||||
{
|
||||
const labelList& sendElems = map.subMap()[domain];
|
||||
|
||||
if (sendElems.size())
|
||||
{
|
||||
// reverse cell map
|
||||
labelList reverseCellMap(tgtMesh.nCells(), -1);
|
||||
forAll(sendElems, subCellI)
|
||||
{
|
||||
reverseCellMap[sendElems[subCellI]] = subCellI;
|
||||
}
|
||||
|
||||
DynamicList<face> subFaces(tgtMesh.nFaces());
|
||||
DynamicList<label> subFaceOwner(tgtMesh.nFaces());
|
||||
DynamicList<label> subFaceNeighbour(tgtMesh.nFaces());
|
||||
|
||||
DynamicList<label> subNbrProcIDs(tgtMesh.nFaces());
|
||||
DynamicList<label> subProcLocalFaceIDs(tgtMesh.nFaces());
|
||||
|
||||
label nInternal = 0;
|
||||
|
||||
// internal faces
|
||||
forAll(tgtMesh.faceNeighbour(), faceI)
|
||||
{
|
||||
label own = tgtMesh.faceOwner()[faceI];
|
||||
label nbr = tgtMesh.faceNeighbour()[faceI];
|
||||
label subOwn = reverseCellMap[own];
|
||||
label subNbr = reverseCellMap[nbr];
|
||||
|
||||
if (subOwn != -1 && subNbr != -1)
|
||||
{
|
||||
nInternal++;
|
||||
|
||||
if (subOwn < subNbr)
|
||||
{
|
||||
subFaces.append(tgtMesh.faces()[faceI]);
|
||||
subFaceOwner.append(subOwn);
|
||||
subFaceNeighbour.append(subNbr);
|
||||
subNbrProcIDs.append(-1);
|
||||
subProcLocalFaceIDs.append(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
subFaces.append(tgtMesh.faces()[faceI].reverseFace());
|
||||
subFaceOwner.append(subNbr);
|
||||
subFaceNeighbour.append(subOwn);
|
||||
subNbrProcIDs.append(-1);
|
||||
subProcLocalFaceIDs.append(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// boundary faces for new region
|
||||
forAll(tgtMesh.faceNeighbour(), faceI)
|
||||
{
|
||||
label own = tgtMesh.faceOwner()[faceI];
|
||||
label nbr = tgtMesh.faceNeighbour()[faceI];
|
||||
label subOwn = reverseCellMap[own];
|
||||
label subNbr = reverseCellMap[nbr];
|
||||
|
||||
if (subOwn != -1 && subNbr == -1)
|
||||
{
|
||||
subFaces.append(tgtMesh.faces()[faceI]);
|
||||
subFaceOwner.append(subOwn);
|
||||
subFaceNeighbour.append(subNbr);
|
||||
subNbrProcIDs.append(-1);
|
||||
subProcLocalFaceIDs.append(-1);
|
||||
}
|
||||
else if (subOwn == -1 && subNbr != -1)
|
||||
{
|
||||
subFaces.append(tgtMesh.faces()[faceI].reverseFace());
|
||||
subFaceOwner.append(subNbr);
|
||||
subFaceNeighbour.append(subOwn);
|
||||
subNbrProcIDs.append(-1);
|
||||
subProcLocalFaceIDs.append(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// boundary faces of existing region
|
||||
forAll(tgtMesh.boundaryMesh(), patchI)
|
||||
{
|
||||
const polyPatch& pp = tgtMesh.boundaryMesh()[patchI];
|
||||
|
||||
label nbrProcI = -1;
|
||||
|
||||
// store info for faces on processor patches
|
||||
if (isA<processorPolyPatch>(pp))
|
||||
{
|
||||
const processorPolyPatch& ppp =
|
||||
dynamic_cast<const processorPolyPatch&>(pp);
|
||||
|
||||
nbrProcI = ppp.neighbProcNo();
|
||||
}
|
||||
|
||||
forAll(pp, i)
|
||||
{
|
||||
label faceI = pp.start() + i;
|
||||
label own = tgtMesh.faceOwner()[faceI];
|
||||
|
||||
if (reverseCellMap[own] != -1)
|
||||
{
|
||||
subFaces.append(tgtMesh.faces()[faceI]);
|
||||
subFaceOwner.append(reverseCellMap[own]);
|
||||
subFaceNeighbour.append(-1);
|
||||
subNbrProcIDs.append(nbrProcI);
|
||||
subProcLocalFaceIDs.append(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reverse point map
|
||||
labelList reversePointMap(tgtMesh.nPoints(), -1);
|
||||
DynamicList<point> subPoints(tgtMesh.nPoints());
|
||||
forAll(subFaces, subFaceI)
|
||||
{
|
||||
face& f = subFaces[subFaceI];
|
||||
forAll(f, fp)
|
||||
{
|
||||
label pointI = f[fp];
|
||||
if (reversePointMap[pointI] == -1)
|
||||
{
|
||||
reversePointMap[pointI] = subPoints.size();
|
||||
subPoints.append(tgtMesh.points()[pointI]);
|
||||
}
|
||||
|
||||
f[fp] = reversePointMap[pointI];
|
||||
}
|
||||
}
|
||||
|
||||
// tgt cells into global numbering
|
||||
labelList globalElems(sendElems.size());
|
||||
forAll(sendElems, i)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "tgtProc:" << Pstream::myProcNo()
|
||||
<< " sending tgt cell " << sendElems[i]
|
||||
<< "[" << globalI.toGlobal(sendElems[i]) << "]"
|
||||
<< " to srcProc " << domain << endl;
|
||||
}
|
||||
|
||||
globalElems[i] = globalI.toGlobal(sendElems[i]);
|
||||
}
|
||||
|
||||
// pass data
|
||||
if (domain == Pstream::myProcNo())
|
||||
{
|
||||
// allocate my own data
|
||||
points[Pstream::myProcNo()] = subPoints;
|
||||
nInternalFaces[Pstream::myProcNo()] = nInternal;
|
||||
faces[Pstream::myProcNo()] = subFaces;
|
||||
faceOwner[Pstream::myProcNo()] = subFaceOwner;
|
||||
faceNeighbour[Pstream::myProcNo()] = subFaceNeighbour;
|
||||
cellIDs[Pstream::myProcNo()] = globalElems;
|
||||
nbrProcIDs[Pstream::myProcNo()] = subNbrProcIDs;
|
||||
procLocalFaceIDs[Pstream::myProcNo()] = subProcLocalFaceIDs;
|
||||
}
|
||||
else
|
||||
{
|
||||
// send data to other processor domains
|
||||
UOPstream toDomain(domain, pBufs);
|
||||
|
||||
toDomain
|
||||
<< subPoints
|
||||
<< nInternal
|
||||
<< subFaces
|
||||
<< subFaceOwner
|
||||
<< subFaceNeighbour
|
||||
<< globalElems
|
||||
<< subNbrProcIDs
|
||||
<< subProcLocalFaceIDs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start receiving
|
||||
pBufs.finishedSends();
|
||||
|
||||
// Consume
|
||||
for (label domain = 0; domain < Pstream::nProcs(); domain++)
|
||||
{
|
||||
const labelList& recvElems = map.constructMap()[domain];
|
||||
|
||||
if (domain != Pstream::myProcNo() && recvElems.size())
|
||||
{
|
||||
UIPstream str(domain, pBufs);
|
||||
|
||||
str >> points[domain]
|
||||
>> nInternalFaces[domain]
|
||||
>> faces[domain]
|
||||
>> faceOwner[domain]
|
||||
>> faceNeighbour[domain]
|
||||
>> cellIDs[domain]
|
||||
>> nbrProcIDs[domain]
|
||||
>> procLocalFaceIDs[domain];
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Target mesh send sizes[" << domain << "]"
|
||||
<< ": points="<< points[domain].size()
|
||||
<< ", faces=" << faces[domain].size()
|
||||
<< ", nInternalFaces=" << nInternalFaces[domain]
|
||||
<< ", faceOwn=" << faceOwner[domain].size()
|
||||
<< ", faceNbr=" << faceNeighbour[domain].size()
|
||||
<< ", cellIDs=" << cellIDs[domain].size() << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::meshToMesh::distributeAndMergeCells
|
||||
(
|
||||
const mapDistribute& map,
|
||||
const polyMesh& tgt,
|
||||
const globalIndex& globalI,
|
||||
pointField& tgtPoints,
|
||||
faceList& tgtFaces,
|
||||
labelList& tgtFaceOwners,
|
||||
labelList& tgtFaceNeighbours,
|
||||
labelList& tgtCellIDs
|
||||
) const
|
||||
{
|
||||
// Exchange per-processor data
|
||||
List<pointField> allPoints;
|
||||
List<label> allNInternalFaces;
|
||||
List<faceList> allFaces;
|
||||
List<labelList> allFaceOwners;
|
||||
List<labelList> allFaceNeighbours;
|
||||
List<labelList> allTgtCellIDs;
|
||||
|
||||
// Per target mesh face the neighbouring proc and index in
|
||||
// processor patch (all -1 for normal boundary face)
|
||||
List<labelList> allNbrProcIDs;
|
||||
List<labelList> allProcLocalFaceIDs;
|
||||
|
||||
distributeCells
|
||||
(
|
||||
map,
|
||||
tgt,
|
||||
globalI,
|
||||
allPoints,
|
||||
allNInternalFaces,
|
||||
allFaces,
|
||||
allFaceOwners,
|
||||
allFaceNeighbours,
|
||||
allTgtCellIDs,
|
||||
allNbrProcIDs,
|
||||
allProcLocalFaceIDs
|
||||
);
|
||||
|
||||
// Convert lists into format that can be used to generate a valid polyMesh
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Points and cells are collected into single flat lists:
|
||||
// - i.e. proc0, proc1 ... procN
|
||||
//
|
||||
// Faces need to be sorted after collection to that internal faces are
|
||||
// contiguous, followed by all boundary faces
|
||||
//
|
||||
// Processor patch faces between included cells on neighbouring processors
|
||||
// are converted into internal faces
|
||||
//
|
||||
// Face list structure:
|
||||
// - Per processor:
|
||||
// - internal faces
|
||||
// - processor faces that have been converted into internal faces
|
||||
// - Followed by all boundary faces
|
||||
// - from 'normal' boundary faces
|
||||
// - from singularly-sided processor patch faces
|
||||
|
||||
|
||||
// Number of internal+coupled faces
|
||||
labelList allNIntCoupledFaces(allNInternalFaces);
|
||||
|
||||
// Starting offset for points
|
||||
label nPoints = 0;
|
||||
labelList pointOffset(Pstream::nProcs(), 0);
|
||||
forAll(allPoints, procI)
|
||||
{
|
||||
pointOffset[procI] = nPoints;
|
||||
nPoints += allPoints[procI].size();
|
||||
}
|
||||
|
||||
// Starting offset for cells
|
||||
label nCells = 0;
|
||||
labelList cellOffset(Pstream::nProcs(), 0);
|
||||
forAll(allTgtCellIDs, procI)
|
||||
{
|
||||
cellOffset[procI] = nCells;
|
||||
nCells += allTgtCellIDs[procI].size();
|
||||
}
|
||||
|
||||
// Count any coupled faces
|
||||
typedef FixedList<label, 3> label3;
|
||||
typedef HashTable<label, label3, label3::Hash<> > procCoupleInfo;
|
||||
procCoupleInfo procFaceToGlobalCell;
|
||||
|
||||
forAll(allNbrProcIDs, procI)
|
||||
{
|
||||
const labelList& nbrProcI = allNbrProcIDs[procI];
|
||||
const labelList& localFaceI = allProcLocalFaceIDs[procI];
|
||||
|
||||
forAll(nbrProcI, i)
|
||||
{
|
||||
if (nbrProcI[i] != -1 && localFaceI[i] != -1)
|
||||
{
|
||||
label3 key;
|
||||
key[0] = min(procI, nbrProcI[i]);
|
||||
key[1] = max(procI, nbrProcI[i]);
|
||||
key[2] = localFaceI[i];
|
||||
|
||||
procCoupleInfo::const_iterator fnd =
|
||||
procFaceToGlobalCell.find(key);
|
||||
|
||||
if (fnd == procFaceToGlobalCell.end())
|
||||
{
|
||||
procFaceToGlobalCell.insert(key, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Additional internal face between procs:"
|
||||
<< key[0] << " and " << key[1]
|
||||
<< " across local face " << key[2] << endl;
|
||||
}
|
||||
|
||||
allNIntCoupledFaces[procI]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Starting offset for internal faces
|
||||
label nIntFaces = 0;
|
||||
label nFacesTotal = 0;
|
||||
labelList internalFaceOffset(Pstream::nProcs(), 0);
|
||||
forAll(allNIntCoupledFaces, procI)
|
||||
{
|
||||
label nCoupledFaces =
|
||||
allNIntCoupledFaces[procI] - allNInternalFaces[procI];
|
||||
|
||||
internalFaceOffset[procI] = nIntFaces;
|
||||
nIntFaces += allNIntCoupledFaces[procI];
|
||||
nFacesTotal += allFaceOwners[procI].size() - nCoupledFaces;
|
||||
}
|
||||
|
||||
tgtPoints.setSize(nPoints);
|
||||
tgtFaces.setSize(nFacesTotal);
|
||||
tgtFaceOwners.setSize(nFacesTotal);
|
||||
tgtFaceNeighbours.setSize(nFacesTotal);
|
||||
tgtCellIDs.setSize(nCells);
|
||||
|
||||
// Insert points
|
||||
forAll(allPoints, procI)
|
||||
{
|
||||
const pointField& pts = allPoints[procI];
|
||||
SubList<point>(tgtPoints, pts.size(), pointOffset[procI]).assign(pts);
|
||||
}
|
||||
|
||||
// Insert cellIDs
|
||||
forAll(allTgtCellIDs, procI)
|
||||
{
|
||||
const labelList& cellIDs = allTgtCellIDs[procI];
|
||||
SubList<label>(tgtCellIDs, cellIDs.size(), cellOffset[procI]).assign
|
||||
(
|
||||
cellIDs
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Insert internal faces (from internal faces)
|
||||
forAll(allFaces, procI)
|
||||
{
|
||||
const faceList& fcs = allFaces[procI];
|
||||
const labelList& faceOs = allFaceOwners[procI];
|
||||
const labelList& faceNs = allFaceNeighbours[procI];
|
||||
|
||||
SubList<face> slice
|
||||
(
|
||||
tgtFaces,
|
||||
allNInternalFaces[procI],
|
||||
internalFaceOffset[procI]
|
||||
);
|
||||
slice.assign(SubList<face>(fcs, allNInternalFaces[procI]));
|
||||
forAll(slice, i)
|
||||
{
|
||||
add(slice[i], pointOffset[procI]);
|
||||
}
|
||||
|
||||
SubField<label> ownSlice
|
||||
(
|
||||
tgtFaceOwners,
|
||||
allNInternalFaces[procI],
|
||||
internalFaceOffset[procI]
|
||||
);
|
||||
ownSlice.assign(SubField<label>(faceOs, allNInternalFaces[procI]));
|
||||
add(ownSlice, cellOffset[procI]);
|
||||
|
||||
SubField<label> nbrSlice
|
||||
(
|
||||
tgtFaceNeighbours,
|
||||
allNInternalFaces[procI],
|
||||
internalFaceOffset[procI]
|
||||
);
|
||||
nbrSlice.assign(SubField<label>(faceNs, allNInternalFaces[procI]));
|
||||
add(nbrSlice, cellOffset[procI]);
|
||||
|
||||
internalFaceOffset[procI] += allNInternalFaces[procI];
|
||||
}
|
||||
|
||||
|
||||
// Insert internal faces (from coupled face-pairs)
|
||||
forAll(allNbrProcIDs, procI)
|
||||
{
|
||||
const labelList& nbrProcI = allNbrProcIDs[procI];
|
||||
const labelList& localFaceI = allProcLocalFaceIDs[procI];
|
||||
const labelList& faceOs = allFaceOwners[procI];
|
||||
const faceList& fcs = allFaces[procI];
|
||||
|
||||
forAll(nbrProcI, i)
|
||||
{
|
||||
if (nbrProcI[i] != -1 && localFaceI[i] != -1)
|
||||
{
|
||||
label3 key;
|
||||
key[0] = min(procI, nbrProcI[i]);
|
||||
key[1] = max(procI, nbrProcI[i]);
|
||||
key[2] = localFaceI[i];
|
||||
|
||||
procCoupleInfo::iterator fnd = procFaceToGlobalCell.find(key);
|
||||
|
||||
if (fnd != procFaceToGlobalCell.end())
|
||||
{
|
||||
label tgtFaceI = fnd();
|
||||
if (tgtFaceI == -1)
|
||||
{
|
||||
// on first visit store the new cell on this side
|
||||
fnd() = cellOffset[procI] + faceOs[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
// get owner and neighbour in new cell numbering
|
||||
label newOwn = cellOffset[procI] + faceOs[i];
|
||||
label newNbr = fnd();
|
||||
label tgtFaceI = internalFaceOffset[procI]++;
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< " proc " << procI
|
||||
<< "\tinserting face:" << tgtFaceI
|
||||
<< " connection between owner " << newOwn
|
||||
<< " and neighbour " << newNbr
|
||||
<< endl;
|
||||
}
|
||||
|
||||
if (newOwn < newNbr)
|
||||
{
|
||||
// we have correct orientation
|
||||
tgtFaces[tgtFaceI] = fcs[i];
|
||||
tgtFaceOwners[tgtFaceI] = newOwn;
|
||||
tgtFaceNeighbours[tgtFaceI] = newNbr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// reverse orientation
|
||||
tgtFaces[tgtFaceI] = fcs[i].reverseFace();
|
||||
tgtFaceOwners[tgtFaceI] = newNbr;
|
||||
tgtFaceNeighbours[tgtFaceI] = newOwn;
|
||||
}
|
||||
|
||||
add(tgtFaces[tgtFaceI], pointOffset[procI]);
|
||||
|
||||
// mark with unique value
|
||||
fnd() = -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
forAll(allNbrProcIDs, procI)
|
||||
{
|
||||
const labelList& nbrProcI = allNbrProcIDs[procI];
|
||||
const labelList& localFaceI = allProcLocalFaceIDs[procI];
|
||||
const labelList& faceOs = allFaceOwners[procI];
|
||||
const labelList& faceNs = allFaceNeighbours[procI];
|
||||
const faceList& fcs = allFaces[procI];
|
||||
|
||||
forAll(nbrProcI, i)
|
||||
{
|
||||
// coupled boundary face
|
||||
if (nbrProcI[i] != -1 && localFaceI[i] != -1)
|
||||
{
|
||||
label3 key;
|
||||
key[0] = min(procI, nbrProcI[i]);
|
||||
key[1] = max(procI, nbrProcI[i]);
|
||||
key[2] = localFaceI[i];
|
||||
|
||||
label tgtFaceI = procFaceToGlobalCell[key];
|
||||
|
||||
if (tgtFaceI == -1)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"void Foam::meshToMesh::"
|
||||
"distributeAndMergeCells"
|
||||
"("
|
||||
"const mapDistribute&, "
|
||||
"const polyMesh&, "
|
||||
"const globalIndex&, "
|
||||
"pointField&, "
|
||||
"faceList&, "
|
||||
"labelList&, "
|
||||
"labelList&, "
|
||||
"labelList&"
|
||||
") const"
|
||||
)
|
||||
<< "Unvisited " << key
|
||||
<< abort(FatalError);
|
||||
}
|
||||
else if (tgtFaceI != -2)
|
||||
{
|
||||
label newOwn = cellOffset[procI] + faceOs[i];
|
||||
label tgtFaceI = nIntFaces++;
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< " proc " << procI
|
||||
<< "\tinserting boundary face:" << tgtFaceI
|
||||
<< " from coupled face " << key
|
||||
<< endl;
|
||||
}
|
||||
|
||||
tgtFaces[tgtFaceI] = fcs[i];
|
||||
add(tgtFaces[tgtFaceI], pointOffset[procI]);
|
||||
|
||||
tgtFaceOwners[tgtFaceI] = newOwn;
|
||||
tgtFaceNeighbours[tgtFaceI] = -1;
|
||||
}
|
||||
}
|
||||
// normal boundary face
|
||||
else
|
||||
{
|
||||
label own = faceOs[i];
|
||||
label nbr = faceNs[i];
|
||||
if ((own != -1) && (nbr == -1))
|
||||
{
|
||||
label newOwn = cellOffset[procI] + faceOs[i];
|
||||
label tgtFaceI = nIntFaces++;
|
||||
|
||||
tgtFaces[tgtFaceI] = fcs[i];
|
||||
add(tgtFaces[tgtFaceI], pointOffset[procI]);
|
||||
|
||||
tgtFaceOwners[tgtFaceI] = newOwn;
|
||||
tgtFaceNeighbours[tgtFaceI] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (debug)
|
||||
{
|
||||
// only merging points in debug mode
|
||||
|
||||
labelList oldToNew;
|
||||
pointField newTgtPoints;
|
||||
bool hasMerged = mergePoints
|
||||
(
|
||||
tgtPoints,
|
||||
SMALL,
|
||||
false,
|
||||
oldToNew,
|
||||
newTgtPoints
|
||||
);
|
||||
|
||||
if (hasMerged)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Merged from " << tgtPoints.size()
|
||||
<< " down to " << newTgtPoints.size() << " points" << endl;
|
||||
}
|
||||
|
||||
tgtPoints.transfer(newTgtPoints);
|
||||
forAll(tgtFaces, i)
|
||||
{
|
||||
inplaceRenumber(oldToNew, tgtFaces[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
711
src/sampling/meshToMesh/meshToMeshTemplates.C
Normal file
711
src/sampling/meshToMesh/meshToMeshTemplates.C
Normal file
@ -0,0 +1,711 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2012-2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "fvMesh.H"
|
||||
#include "volFields.H"
|
||||
#include "directFvPatchFieldMapper.H"
|
||||
#include "calculatedFvPatchField.H"
|
||||
#include "weightedFvPatchFieldMapper.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
//- Helper class for list
|
||||
template<class Type>
|
||||
class ListPlusEqOp
|
||||
{
|
||||
public:
|
||||
void operator()(List<Type>& x, const List<Type> y) const
|
||||
{
|
||||
if (y.size())
|
||||
{
|
||||
if (x.size())
|
||||
{
|
||||
label sz = x.size();
|
||||
x.setSize(sz + y.size());
|
||||
forAll(y, i)
|
||||
{
|
||||
x[sz++] = y[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void Foam::meshToMesh::add
|
||||
(
|
||||
UList<Type>& fld,
|
||||
const label offset
|
||||
) const
|
||||
{
|
||||
forAll(fld, i)
|
||||
{
|
||||
fld[i] += offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class CombineOp>
|
||||
void Foam::meshToMesh::mapSrcToTgt
|
||||
(
|
||||
const UList<Type>& srcField,
|
||||
const CombineOp& cop,
|
||||
List<Type>& result
|
||||
) const
|
||||
{
|
||||
if (result.size() != tgtToSrcCellAddr_.size())
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"void Foam::meshToMesh::mapSrcToTgt"
|
||||
"("
|
||||
"const UList<Type>&, "
|
||||
"const CombineOp&, "
|
||||
"List<Type>&"
|
||||
") const"
|
||||
) << "Supplied field size is not equal to target mesh size" << nl
|
||||
<< " source mesh = " << srcToTgtCellAddr_.size() << nl
|
||||
<< " target mesh = " << tgtToSrcCellAddr_.size() << nl
|
||||
<< " supplied field = " << result.size()
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
multiplyWeightedOp<Type, CombineOp> cbop(cop);
|
||||
|
||||
if (singleMeshProc_ == -1)
|
||||
{
|
||||
const mapDistribute& map = srcMapPtr_();
|
||||
|
||||
List<Type> work(srcField);
|
||||
map.distribute(work);
|
||||
|
||||
forAll(result, cellI)
|
||||
{
|
||||
const labelList& srcAddress = tgtToSrcCellAddr_[cellI];
|
||||
const scalarList& srcWeight = tgtToSrcCellWght_[cellI];
|
||||
|
||||
if (srcAddress.size())
|
||||
{
|
||||
// result[cellI] = pTraits<Type>::zero;
|
||||
result[cellI] *= (1.0 - sum(srcWeight));
|
||||
forAll(srcAddress, i)
|
||||
{
|
||||
label srcI = srcAddress[i];
|
||||
scalar w = srcWeight[i];
|
||||
cbop(result[cellI], cellI, work[srcI], w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forAll(result, cellI)
|
||||
{
|
||||
const labelList& srcAddress = tgtToSrcCellAddr_[cellI];
|
||||
const scalarList& srcWeight = tgtToSrcCellWght_[cellI];
|
||||
|
||||
if (srcAddress.size())
|
||||
{
|
||||
// result[cellI] = pTraits<Type>::zero;
|
||||
result[cellI] *= (1.0 - sum(srcWeight));
|
||||
forAll(srcAddress, i)
|
||||
{
|
||||
label srcI = srcAddress[i];
|
||||
scalar w = srcWeight[i];
|
||||
cbop(result[cellI], cellI, srcField[srcI], w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class CombineOp>
|
||||
Foam::tmp<Foam::Field<Type> > Foam::meshToMesh::mapSrcToTgt
|
||||
(
|
||||
const Field<Type>& srcField,
|
||||
const CombineOp& cop
|
||||
) const
|
||||
{
|
||||
tmp<Field<Type> > tresult
|
||||
(
|
||||
new Field<Type>
|
||||
(
|
||||
tgtToSrcCellAddr_.size(),
|
||||
pTraits<Type>::zero
|
||||
)
|
||||
);
|
||||
|
||||
mapSrcToTgt(srcField, cop, tresult());
|
||||
|
||||
return tresult;
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class CombineOp>
|
||||
Foam::tmp<Foam::Field<Type> > Foam::meshToMesh::mapSrcToTgt
|
||||
(
|
||||
const tmp<Field<Type> >& tsrcField,
|
||||
const CombineOp& cop
|
||||
) const
|
||||
{
|
||||
return mapSrcToTgt(tsrcField(), cop);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type> > Foam::meshToMesh::mapSrcToTgt
|
||||
(
|
||||
const Field<Type>& srcField
|
||||
) const
|
||||
{
|
||||
return mapSrcToTgt(srcField, plusEqOp<Type>());
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type> > Foam::meshToMesh::mapSrcToTgt
|
||||
(
|
||||
const tmp<Field<Type> >& tsrcField
|
||||
) const
|
||||
{
|
||||
return mapSrcToTgt(tsrcField());
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class CombineOp>
|
||||
void Foam::meshToMesh::mapTgtToSrc
|
||||
(
|
||||
const UList<Type>& tgtField,
|
||||
const CombineOp& cop,
|
||||
List<Type>& result
|
||||
) const
|
||||
{
|
||||
if (result.size() != srcToTgtCellAddr_.size())
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"void Foam::meshToMesh::mapTgtToSrc"
|
||||
"("
|
||||
"const UList<Type>&, "
|
||||
"const CombineOp&, "
|
||||
"List<Type>&"
|
||||
") const"
|
||||
) << "Supplied field size is not equal to source mesh size" << nl
|
||||
<< " source mesh = " << srcToTgtCellAddr_.size() << nl
|
||||
<< " target mesh = " << tgtToSrcCellAddr_.size() << nl
|
||||
<< " supplied field = " << result.size()
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
multiplyWeightedOp<Type, CombineOp> cbop(cop);
|
||||
|
||||
if (singleMeshProc_ == -1)
|
||||
{
|
||||
const mapDistribute& map = tgtMapPtr_();
|
||||
|
||||
List<Type> work(tgtField);
|
||||
map.distribute(work);
|
||||
|
||||
forAll(result, cellI)
|
||||
{
|
||||
const labelList& tgtAddress = srcToTgtCellAddr_[cellI];
|
||||
const scalarList& tgtWeight = srcToTgtCellWght_[cellI];
|
||||
|
||||
if (tgtAddress.size())
|
||||
{
|
||||
result[cellI] *= (1.0 - sum(tgtWeight));
|
||||
forAll(tgtAddress, i)
|
||||
{
|
||||
label tgtI = tgtAddress[i];
|
||||
scalar w = tgtWeight[i];
|
||||
cbop(result[cellI], cellI, work[tgtI], w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forAll(result, cellI)
|
||||
{
|
||||
const labelList& tgtAddress = srcToTgtCellAddr_[cellI];
|
||||
const scalarList& tgtWeight = srcToTgtCellWght_[cellI];
|
||||
|
||||
if (tgtAddress.size())
|
||||
{
|
||||
result[cellI] *= (1.0 - sum(tgtWeight));
|
||||
forAll(tgtAddress, i)
|
||||
{
|
||||
label tgtI = tgtAddress[i];
|
||||
scalar w = tgtWeight[i];
|
||||
cbop(result[cellI], cellI, tgtField[tgtI], w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class CombineOp>
|
||||
Foam::tmp<Foam::Field<Type> > Foam::meshToMesh::mapTgtToSrc
|
||||
(
|
||||
const Field<Type>& tgtField,
|
||||
const CombineOp& cop
|
||||
) const
|
||||
{
|
||||
tmp<Field<Type> > tresult
|
||||
(
|
||||
new Field<Type>
|
||||
(
|
||||
srcToTgtCellAddr_.size(),
|
||||
pTraits<Type>::zero
|
||||
)
|
||||
);
|
||||
|
||||
mapTgtToSrc(tgtField, cop, tresult());
|
||||
|
||||
return tresult;
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class CombineOp>
|
||||
Foam::tmp<Foam::Field<Type> > Foam::meshToMesh::mapTgtToSrc
|
||||
(
|
||||
const tmp<Field<Type> >& ttgtField,
|
||||
const CombineOp& cop
|
||||
) const
|
||||
{
|
||||
return mapTgtToSrc(ttgtField(), cop);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type> > Foam::meshToMesh::mapTgtToSrc
|
||||
(
|
||||
const Field<Type>& tgtField
|
||||
) const
|
||||
{
|
||||
return mapTgtToSrc(tgtField, plusEqOp<Type>());
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::Field<Type> > Foam::meshToMesh::mapTgtToSrc
|
||||
(
|
||||
const tmp<Field<Type> >& ttgtField
|
||||
) const
|
||||
{
|
||||
return mapTgtToSrc(ttgtField(), plusEqOp<Type>());
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class CombineOp>
|
||||
void Foam::meshToMesh::mapSrcToTgt
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field,
|
||||
const CombineOp& cop,
|
||||
GeometricField<Type, fvPatchField, volMesh>& result
|
||||
) const
|
||||
{
|
||||
mapSrcToTgt(field, cop, result.internalField());
|
||||
|
||||
const PtrList<AMIPatchToPatchInterpolation>& AMIList = patchAMIs();
|
||||
|
||||
forAll(AMIList, i)
|
||||
{
|
||||
label srcPatchI = srcPatchID_[i];
|
||||
label tgtPatchI = tgtPatchID_[i];
|
||||
|
||||
const fvPatchField<Type>& srcField = field.boundaryField()[srcPatchI];
|
||||
fvPatchField<Type>& tgtField = result.boundaryField()[tgtPatchI];
|
||||
|
||||
// 2.3 does not do distributed mapping yet so only do if
|
||||
// running on single processor
|
||||
if (AMIList[i].singlePatchProc() != -1)
|
||||
{
|
||||
// Clone and map (since rmap does not do general mapping)
|
||||
tmp<fvPatchField<Type> > tnewTgt
|
||||
(
|
||||
fvPatchField<Type>::New
|
||||
(
|
||||
srcField,
|
||||
tgtField.patch(),
|
||||
result.dimensionedInternalField(),
|
||||
weightedFvPatchFieldMapper
|
||||
(
|
||||
AMIList[i].tgtAddress(),
|
||||
AMIList[i].tgtWeights()
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Transfer all mapped quantities (value and e.g. gradient) onto
|
||||
// tgtField. Value will get overwritten below.
|
||||
tgtField.rmap(tnewTgt(), identity(tgtField.size()));
|
||||
}
|
||||
|
||||
tgtField == pTraits<Type>::zero;
|
||||
|
||||
AMIList[i].interpolateToTarget
|
||||
(
|
||||
srcField,
|
||||
multiplyWeightedOp<Type, CombineOp>(cop),
|
||||
tgtField,
|
||||
UList<Type>::null()
|
||||
);
|
||||
}
|
||||
|
||||
forAll(cuttingPatches_, i)
|
||||
{
|
||||
label patchI = cuttingPatches_[i];
|
||||
fvPatchField<Type>& pf = result.boundaryField()[patchI];
|
||||
pf == pf.patchInternalField();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class CombineOp>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
|
||||
Foam::meshToMesh::mapSrcToTgt
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field,
|
||||
const CombineOp& cop
|
||||
) const
|
||||
{
|
||||
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
|
||||
|
||||
const fvMesh& tgtMesh = static_cast<const fvMesh&>(tgtRegion_);
|
||||
|
||||
const fvBoundaryMesh& tgtBm = tgtMesh.boundary();
|
||||
const typename fieldType::GeometricBoundaryField& srcBfld =
|
||||
field.boundaryField();
|
||||
|
||||
PtrList<fvPatchField<Type> > tgtPatchFields(tgtBm.size());
|
||||
|
||||
// constuct tgt boundary patch types as copy of 'field' boundary types
|
||||
// note: this will provide place holders for fields with additional
|
||||
// entries, but these values will need to be reset
|
||||
forAll(tgtPatchID_, i)
|
||||
{
|
||||
label srcPatchI = srcPatchID_[i];
|
||||
label tgtPatchI = tgtPatchID_[i];
|
||||
|
||||
if (!tgtPatchFields.set(tgtPatchI))
|
||||
{
|
||||
tgtPatchFields.set
|
||||
(
|
||||
tgtPatchI,
|
||||
fvPatchField<Type>::New
|
||||
(
|
||||
srcBfld[srcPatchI],
|
||||
tgtMesh.boundary()[tgtPatchI],
|
||||
DimensionedField<Type, volMesh>::null(),
|
||||
directFvPatchFieldMapper
|
||||
(
|
||||
labelList(tgtMesh.boundary()[tgtPatchI].size(), -1)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Any unset tgtPatchFields become calculated
|
||||
forAll(tgtPatchFields, tgtPatchI)
|
||||
{
|
||||
if (!tgtPatchFields.set(tgtPatchI))
|
||||
{
|
||||
// Note: use factory New method instead of direct generation of
|
||||
// calculated so we keep constraints
|
||||
tgtPatchFields.set
|
||||
(
|
||||
tgtPatchI,
|
||||
fvPatchField<Type>::New
|
||||
(
|
||||
calculatedFvPatchField<Type>::typeName,
|
||||
tgtMesh.boundary()[tgtPatchI],
|
||||
DimensionedField<Type, volMesh>::null()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
tmp<fieldType> tresult
|
||||
(
|
||||
new fieldType
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
type() + ":interpolate(" + field.name() + ")",
|
||||
tgtMesh.time().timeName(),
|
||||
tgtMesh,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
tgtMesh,
|
||||
field.dimensions(),
|
||||
Field<Type>(tgtMesh.nCells(), pTraits<Type>::zero),
|
||||
tgtPatchFields
|
||||
)
|
||||
);
|
||||
|
||||
mapSrcToTgt(field, cop, tresult());
|
||||
|
||||
return tresult;
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class CombineOp>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
|
||||
Foam::meshToMesh::mapSrcToTgt
|
||||
(
|
||||
const tmp<GeometricField<Type, fvPatchField, volMesh> >& tfield,
|
||||
const CombineOp& cop
|
||||
) const
|
||||
{
|
||||
return mapSrcToTgt(tfield(), cop);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
|
||||
Foam::meshToMesh::mapSrcToTgt
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field
|
||||
) const
|
||||
{
|
||||
return mapSrcToTgt(field, plusEqOp<Type>());
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
|
||||
Foam::meshToMesh::mapSrcToTgt
|
||||
(
|
||||
const tmp<GeometricField<Type, fvPatchField, volMesh> >& tfield
|
||||
) const
|
||||
{
|
||||
return mapSrcToTgt(tfield(), plusEqOp<Type>());
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class CombineOp>
|
||||
void Foam::meshToMesh::mapTgtToSrc
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field,
|
||||
const CombineOp& cop,
|
||||
GeometricField<Type, fvPatchField, volMesh>& result
|
||||
) const
|
||||
{
|
||||
mapTgtToSrc(field, cop, result.internalField());
|
||||
|
||||
const PtrList<AMIPatchToPatchInterpolation>& AMIList = patchAMIs();
|
||||
|
||||
forAll(AMIList, i)
|
||||
{
|
||||
label srcPatchI = srcPatchID_[i];
|
||||
label tgtPatchI = tgtPatchID_[i];
|
||||
|
||||
fvPatchField<Type>& srcField = result.boundaryField()[srcPatchI];
|
||||
const fvPatchField<Type>& tgtField = field.boundaryField()[tgtPatchI];
|
||||
|
||||
// 2.3 does not do distributed mapping yet so only do if
|
||||
// running on single processor
|
||||
if (AMIList[i].singlePatchProc() != -1)
|
||||
{
|
||||
// Clone and map (since rmap does not do general mapping)
|
||||
tmp<fvPatchField<Type> > tnewSrc
|
||||
(
|
||||
fvPatchField<Type>::New
|
||||
(
|
||||
tgtField,
|
||||
srcField.patch(),
|
||||
result.dimensionedInternalField(),
|
||||
weightedFvPatchFieldMapper
|
||||
(
|
||||
AMIList[i].srcAddress(),
|
||||
AMIList[i].srcWeights()
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Transfer all mapped quantities (value and e.g. gradient) onto
|
||||
// srcField. Value will get overwritten below
|
||||
srcField.rmap(tnewSrc(), identity(srcField.size()));
|
||||
}
|
||||
|
||||
srcField == pTraits<Type>::zero;
|
||||
|
||||
AMIList[i].interpolateToSource
|
||||
(
|
||||
tgtField,
|
||||
multiplyWeightedOp<Type, CombineOp>(cop),
|
||||
srcField
|
||||
);
|
||||
}
|
||||
|
||||
forAll(cuttingPatches_, i)
|
||||
{
|
||||
label patchI = cuttingPatches_[i];
|
||||
fvPatchField<Type>& pf = result.boundaryField()[patchI];
|
||||
pf == pf.patchInternalField();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class CombineOp>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
|
||||
Foam::meshToMesh::mapTgtToSrc
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field,
|
||||
const CombineOp& cop
|
||||
) const
|
||||
{
|
||||
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
|
||||
|
||||
const fvMesh& srcMesh = static_cast<const fvMesh&>(srcRegion_);
|
||||
|
||||
const fvBoundaryMesh& srcBm = srcMesh.boundary();
|
||||
const typename fieldType::GeometricBoundaryField& tgtBfld =
|
||||
field.boundaryField();
|
||||
|
||||
PtrList<fvPatchField<Type> > srcPatchFields(srcBm.size());
|
||||
|
||||
// constuct src boundary patch types as copy of 'field' boundary types
|
||||
// note: this will provide place holders for fields with additional
|
||||
// entries, but these values will need to be reset
|
||||
forAll(srcPatchID_, i)
|
||||
{
|
||||
label srcPatchI = srcPatchID_[i];
|
||||
label tgtPatchI = tgtPatchID_[i];
|
||||
|
||||
if (!srcPatchFields.set(tgtPatchI))
|
||||
{
|
||||
srcPatchFields.set
|
||||
(
|
||||
srcPatchI,
|
||||
fvPatchField<Type>::New
|
||||
(
|
||||
tgtBfld[srcPatchI],
|
||||
srcMesh.boundary()[tgtPatchI],
|
||||
DimensionedField<Type, volMesh>::null(),
|
||||
directFvPatchFieldMapper
|
||||
(
|
||||
labelList(srcMesh.boundary()[srcPatchI].size(), -1)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Any unset srcPatchFields become calculated
|
||||
forAll(srcPatchFields, srcPatchI)
|
||||
{
|
||||
if (!srcPatchFields.set(srcPatchI))
|
||||
{
|
||||
// Note: use factory New method instead of direct generation of
|
||||
// calculated so we keep constraints
|
||||
srcPatchFields.set
|
||||
(
|
||||
srcPatchI,
|
||||
fvPatchField<Type>::New
|
||||
(
|
||||
calculatedFvPatchField<Type>::typeName,
|
||||
srcMesh.boundary()[srcPatchI],
|
||||
DimensionedField<Type, volMesh>::null()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
tmp<fieldType> tresult
|
||||
(
|
||||
new fieldType
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
type() + ":interpolate(" + field.name() + ")",
|
||||
srcMesh.time().timeName(),
|
||||
srcMesh,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
srcMesh,
|
||||
field.dimensions(),
|
||||
Field<Type>(srcMesh.nCells(), pTraits<Type>::zero),
|
||||
srcPatchFields
|
||||
)
|
||||
);
|
||||
|
||||
mapTgtToSrc(field, cop, tresult());
|
||||
|
||||
return tresult;
|
||||
}
|
||||
|
||||
|
||||
template<class Type, class CombineOp>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
|
||||
Foam::meshToMesh::mapTgtToSrc
|
||||
(
|
||||
const tmp<GeometricField<Type, fvPatchField, volMesh> >& tfield,
|
||||
const CombineOp& cop
|
||||
) const
|
||||
{
|
||||
return mapTgtToSrc(tfield(), cop);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
|
||||
Foam::meshToMesh::mapTgtToSrc
|
||||
(
|
||||
const GeometricField<Type, fvPatchField, volMesh>& field
|
||||
) const
|
||||
{
|
||||
return mapTgtToSrc(field, plusEqOp<Type>());
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
|
||||
Foam::meshToMesh::mapTgtToSrc
|
||||
(
|
||||
const tmp<GeometricField<Type, fvPatchField, volMesh> >& tfield
|
||||
) const
|
||||
{
|
||||
return mapTgtToSrc(tfield(), plusEqOp<Type>());
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
122
src/sampling/meshToMesh/weightedFvPatchFieldMapper.H
Normal file
122
src/sampling/meshToMesh/weightedFvPatchFieldMapper.H
Normal file
@ -0,0 +1,122 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
|
||||
\\/ 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::weightedFvPatchFieldMapper
|
||||
|
||||
Description
|
||||
FieldMapper with weighted mapping.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef weightedFvPatchFieldMapper_H
|
||||
#define weightedFvPatchFieldMapper_H
|
||||
|
||||
#include "fvPatchFieldMapper.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class weightedFvPatchFieldMapper Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class weightedFvPatchFieldMapper
|
||||
:
|
||||
public fvPatchFieldMapper
|
||||
{
|
||||
const labelListList& addressing_;
|
||||
|
||||
const scalarListList& weights_;
|
||||
|
||||
bool hasUnmapped_;
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct given addressing
|
||||
weightedFvPatchFieldMapper
|
||||
(
|
||||
const labelListList& addressing,
|
||||
const scalarListList& weights
|
||||
)
|
||||
:
|
||||
addressing_(addressing),
|
||||
weights_(weights),
|
||||
hasUnmapped_(false)
|
||||
{
|
||||
forAll(addressing_, i)
|
||||
{
|
||||
if (addressing_[i].size() == 0)
|
||||
{
|
||||
hasUnmapped_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- Destructor
|
||||
virtual ~weightedFvPatchFieldMapper()
|
||||
{}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual label size() const
|
||||
{
|
||||
return addressing().size();
|
||||
}
|
||||
|
||||
virtual bool direct() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool hasUnmapped() const
|
||||
{
|
||||
return hasUnmapped_;
|
||||
}
|
||||
|
||||
virtual const labelListList& addressing() const
|
||||
{
|
||||
return addressing_;
|
||||
}
|
||||
|
||||
virtual const scalarListList& weights() const
|
||||
{
|
||||
return weights_;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user