ENH: Added map nearest option to mesh-to-mesh interpolation

This commit is contained in:
andy
2013-03-22 18:41:14 +00:00
parent 5baa8f5a6d
commit f4d592c335
6 changed files with 822 additions and 456 deletions

View File

@ -60,6 +60,9 @@ $(meshToMesh)/calculateMeshToMeshAddressing.C
$(meshToMesh)/calculateMeshToMeshWeights.C $(meshToMesh)/calculateMeshToMeshWeights.C
meshToMeshNew = meshToMeshInterpolation/meshToMeshNew meshToMeshNew = meshToMeshInterpolation/meshToMeshNew
$(meshToMeshNew)/calcDirect.C
$(meshToMeshNew)/calcMapNearest.C
$(meshToMeshNew)/calcCellVolumeWeight.C
$(meshToMeshNew)/meshToMeshNew.C $(meshToMeshNew)/meshToMeshNew.C
$(meshToMeshNew)/meshToMeshNewParallelOps.C $(meshToMeshNew)/meshToMeshNewParallelOps.C

View File

@ -0,0 +1,301 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2012-2013 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 "meshToMeshNew.H"
#include "tetOverlapVolume.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::meshToMeshNew::calcCellVolumeWeight
(
const polyMesh& src,
const polyMesh& tgt,
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(src, tgt, 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,
src,
tgt,
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::meshToMeshNew::setNextCells
(
label& startSeedI,
label& srcCellI,
label& tgtCellI,
const polyMesh& src,
const polyMesh& tgt,
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(src, tgt, 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
(
src,
tgt,
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;
}
bool Foam::meshToMeshNew::intersect
(
const polyMesh& src,
const polyMesh& tgt,
const label srcCellI,
const label tgtCellI
) const
{
scalar threshold = tolerance_*src.cellVolumes()[srcCellI];
tetOverlapVolume overlapEngine;
treeBoundBox bbTgtCell
(
pointField
(
tgt.points(),
tgt.cellPoints()[tgtCellI]
)
);
return overlapEngine.cellCellOverlapMinDecomp
(
src,
srcCellI,
tgt,
tgtCellI,
bbTgtCell,
threshold
);
}
Foam::scalar Foam::meshToMeshNew::interVol
(
const polyMesh& src,
const polyMesh& tgt,
const label srcCellI,
const label tgtCellI
) const
{
tetOverlapVolume overlapEngine;
treeBoundBox bbTgtCell
(
pointField
(
tgt.points(),
tgt.cellPoints()[tgtCellI]
)
);
scalar vol = overlapEngine.cellCellOverlapVolumeMinDecomp
(
src,
srcCellI,
tgt,
tgtCellI,
bbTgtCell
);
return vol;
}
// ************************************************************************* //

View File

@ -0,0 +1,159 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2012-2013 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 "meshToMeshNew.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::meshToMeshNew::calcDirect
(
const polyMesh& src,
const polyMesh& tgt,
const label srcSeedI,
const label tgtSeedI
)
{
// store a list of src cells already mapped
boolList srcSeedFlag(src.nCells(), true);
labelList srcTgtSeed(src.nCells(), -1);
List<DynamicList<label> > srcToTgt(src.nCells());
List<DynamicList<label> > tgtToSrc(tgt.nCells());
DynamicList<label> srcSeeds;
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
srcSeedFlag[srcCellI] = false;
// accumulate intersection volume
V_ += srcVc[srcCellI];
// find new source seed cell
appendToDirectSeeds
(
src,
tgt,
srcSeedFlag,
srcTgtSeed,
srcSeeds,
srcCellI,
tgtCellI
);
}
while (srcCellI >= 0);
// transfer addressing into persistent storage
forAll(srcToTgtCellAddr_, i)
{
scalar v = srcVc[i];
srcToTgtCellAddr_[i].transfer(srcToTgt[i]);
srcToTgtCellWght_[i] = scalarList(srcToTgtCellAddr_[i].size(), v);
}
forAll(tgtToSrcCellAddr_, i)
{
scalar v = tgtVc[i];
tgtToSrcCellAddr_[i].transfer(tgtToSrc[i]);
tgtToSrcCellWght_[i] = scalarList(tgtToSrcCellAddr_[i].size(), v);
}
}
void Foam::meshToMeshNew::appendToDirectSeeds
(
const polyMesh& src,
const polyMesh& tgt,
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))
{
// 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;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,242 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2012-2013 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 "meshToMeshNew.H"
#include "ListOps.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::meshToMeshNew::calcMapNearest
(
const polyMesh& src,
const polyMesh& tgt,
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;
boolList tgtMapFlag(tgt.nCells(), true);
do
{
srcToTgt[srcCellI].append(tgtCellI);
// find nearest tgt cell
findNearestCell(src, tgt, srcCellI, tgtCellI);
// store src/tgt cell pair
tgtToSrc[tgtCellI].append(srcCellI);
// mark source cell srcCellI and tgtCellI as matched
mapFlag[srcCellI] = false;
tgtMapFlag[tgtCellI] = false;
// accumulate intersection volume
V_ += srcVc[srcCellI];
// find new source cell
setNextNearestCells
(
startSeedI,
srcCellI,
tgtCellI,
mapFlag,
src,
tgt,
srcCellIDs
);
}
while (srcCellI >= 0);
// If there are more target cells than source cells, some target cells
// will not yet be mapped
forAll(tgtMapFlag, tgtCellI)
{
if (tgtMapFlag[tgtCellI])
{
label srcCellI = findMappedSrcCell(tgt, tgtCellI, tgtToSrc);
findNearestCell(tgt, src, tgtCellI, srcCellI);
tgtToSrc[tgtCellI].append(srcCellI);
}
}
// transfer addressing into persistent storage
// note: always 1 target cell per source cell (srcToTgt)
// can be multiple source cells per target cell (tgtToSrc)
forAll(srcToTgtCellAddr_, i)
{
scalar v = srcVc[i];
srcToTgtCellWght_[i] = scalarList(srcToTgt[i].size(), v);
srcToTgtCellAddr_[i].transfer(srcToTgt[i]);
}
forAll(tgtToSrcCellAddr_, i)
{
scalar v = tgtVc[i];
scalarList w(tgtToSrc[i].size(), v);
forAll(w, j)
{
w[j] /= w.size();
}
tgtToSrcCellWght_[i] = scalarList(w, v);
tgtToSrcCellAddr_[i].transfer(tgtToSrc[i]);
}
}
void Foam::meshToMeshNew::findNearestCell
(
const polyMesh& src,
const polyMesh& tgt,
const label srcCellI,
label& tgtCellI
)
{
const vectorField& srcC = src.cellCentres();
const vectorField& tgtC = tgt.cellCentres();
const vector& srcP = srcC[srcCellI];
DynamicList<label> tgtCells(10);
tgtCells.append(tgtCellI);
DynamicList<label> visitedCells(10);
scalar d = GREAT;
do
{
label tgtI = tgtCells.remove();
visitedCells.append(tgtI);
scalar dTest = magSqr(tgtC[tgtI] - srcP);
if (dTest < d)
{
tgtCellI = tgtI;
d = dTest;
appendNbrCells(tgtCellI, tgt, visitedCells, tgtCells);
}
} while (tgtCells.size() > 0);
}
void Foam::meshToMeshNew::setNextNearestCells
(
label& startSeedI,
label& srcCellI,
label& tgtCellI,
boolList& mapFlag,
const polyMesh& src,
const polyMesh& tgt,
const labelList& srcCellIDs
)
{
const labelList& srcNbr = src.cellCells()[srcCellI];
srcCellI = -1;
forAll(srcNbr, i)
{
label cellI = srcNbr[i];
if (mapFlag[cellI])
{
srcCellI = cellI;
startSeedI = cellI + 1;
return;
}
}
(void)findInitialSeeds
(
src,
tgt,
srcCellIDs,
mapFlag,
startSeedI,
srcCellI,
tgtCellI
);
}
Foam::label Foam::meshToMeshNew::findMappedSrcCell
(
const polyMesh& tgt,
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;
}
// ************************************************************************* //

View File

@ -29,7 +29,6 @@ License
#include "globalIndex.H" #include "globalIndex.H"
#include "mergePoints.H" #include "mergePoints.H"
#include "treeBoundBox.H" #include "treeBoundBox.H"
#include "tetOverlapVolume.H"
#include "indexedOctree.H" #include "indexedOctree.H"
#include "treeDataCell.H" #include "treeDataCell.H"
#include "ListOps.H" #include "ListOps.H"
@ -44,14 +43,15 @@ namespace Foam
const char* Foam::NamedEnum const char* Foam::NamedEnum
< <
Foam::meshToMeshNew::interpolationMethod, Foam::meshToMeshNew::interpolationMethod,
2 3
>::names[] = >::names[] =
{ {
"map", "direct",
"mapNearest",
"cellVolumeWeight" "cellVolumeWeight"
}; };
const NamedEnum<meshToMeshNew::interpolationMethod, 2> const NamedEnum<meshToMeshNew::interpolationMethod, 3>
meshToMeshNew::interpolationMethodNames_; meshToMeshNew::interpolationMethodNames_;
} }
@ -190,132 +190,29 @@ bool Foam::meshToMeshNew::findInitialSeeds
} }
void Foam::meshToMeshNew::appendToDirectSeeds void Foam::meshToMeshNew::appendNbrCells
( (
const polyMesh& src, const label cellI,
const polyMesh& tgt, const polyMesh& mesh,
boolList& mapFlag, const DynamicList<label>& visitedCells,
labelList& srcTgtSeed, DynamicList<label>& nbrCellIDs
DynamicList<label>& srcSeeds,
label& srcSeedI,
label& tgtSeedI
) const ) const
{ {
const labelList& srcNbr = src.cellCells()[srcSeedI]; const labelList& nbrCells = mesh.cellCells()[cellI];
const labelList& tgtNbr = tgt.cellCells()[tgtSeedI];
const vectorField& srcCentre = src.cellCentres(); // filter out cells already visited from cell neighbours
forAll(nbrCells, i)
forAll(srcNbr, i)
{ {
label srcI = srcNbr[i]; label nbrCellI = nbrCells[i];
if (mapFlag[srcI] && (srcTgtSeed[srcI] == -1)) if
{
// 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))
{
// 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;
}
}
void Foam::meshToMeshNew::calcDirect
(
const polyMesh& src,
const polyMesh& tgt,
const label srcSeedI,
const label tgtSeedI
)
{
// store a list of src cells already mapped
boolList srcSeedFlag(src.nCells(), true);
labelList srcTgtSeed(src.nCells(), -1);
List<DynamicList<label> > srcToTgt(src.nCells());
List<DynamicList<label> > tgtToSrc(tgt.nCells());
DynamicList<label> srcSeeds;
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
srcSeedFlag[srcCellI] = false;
// accumulate intersection volume
V_ += srcVc[srcCellI];
// find new source seed cell
appendToDirectSeeds
( (
src, (findIndex(visitedCells, nbrCellI) == -1)
tgt, && (findIndex(nbrCellIDs, nbrCellI) == -1)
srcSeedFlag, )
srcTgtSeed, {
srcSeeds, nbrCellIDs.append(nbrCellI);
srcCellI, }
tgtCellI
);
}
while (srcCellI >= 0);
// transfer addressing into persistent storage
forAll(srcToTgtCellAddr_, i)
{
scalar v = srcVc[i];
srcToTgtCellAddr_[i].transfer(srcToTgt[i]);
srcToTgtCellWght_[i] = scalarList(srcToTgtCellAddr_[i].size(), v);
}
forAll(tgtToSrcCellAddr_, i)
{
scalar v = tgtVc[i];
tgtToSrcCellAddr_[i].transfer(tgtToSrc[i]);
tgtToSrcCellWght_[i] = scalarList(tgtToSrcCellAddr_[i].size(), v);
} }
} }
@ -357,303 +254,6 @@ void Foam::meshToMeshNew::normaliseWeights
} }
void Foam::meshToMeshNew::appendNbrTgtCells
(
const label tgtCellI,
const polyMesh& tgt,
const DynamicList<label>& visitedTgtCells,
DynamicList<label>& nbrTgtCellIDs
) const
{
const labelList& nbrCells = tgt.cellCells()[tgtCellI];
// filter out cells already visited from cell neighbours
forAll(nbrCells, i)
{
label nbrCellI = nbrCells[i];
if
(
(findIndex(visitedTgtCells, nbrCellI) == -1)
&& (findIndex(nbrTgtCellIDs, nbrCellI) == -1)
)
{
nbrTgtCellIDs.append(nbrCellI);
}
}
}
void Foam::meshToMeshNew::setNextCells
(
label& startSeedI,
label& srcCellI,
label& tgtCellI,
const polyMesh& src,
const polyMesh& tgt,
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(src, tgt, 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
(
src,
tgt,
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;
}
bool Foam::meshToMeshNew::intersect
(
const polyMesh& src,
const polyMesh& tgt,
const label srcCellI,
const label tgtCellI
) const
{
scalar threshold = tolerance_*src.cellVolumes()[srcCellI];
tetOverlapVolume overlapEngine;
treeBoundBox bbTgtCell
(
pointField
(
tgt.points(),
tgt.cellPoints()[tgtCellI]
)
);
return overlapEngine.cellCellOverlapMinDecomp
(
src,
srcCellI,
tgt,
tgtCellI,
bbTgtCell,
threshold
);
}
Foam::scalar Foam::meshToMeshNew::interVol
(
const polyMesh& src,
const polyMesh& tgt,
const label srcCellI,
const label tgtCellI
) const
{
tetOverlapVolume overlapEngine;
treeBoundBox bbTgtCell
(
pointField
(
tgt.points(),
tgt.cellPoints()[tgtCellI]
)
);
scalar vol = overlapEngine.cellCellOverlapVolumeMinDecomp
(
src,
srcCellI,
tgt,
tgtCellI,
bbTgtCell
);
return vol;
}
void Foam::meshToMeshNew::calcIndirect
(
const polyMesh& src,
const polyMesh& tgt,
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);
appendNbrTgtCells(tgtCellI, tgt, visitedTgtCells, nbrTgtCells);
do
{
tgtCellI = nbrTgtCells.remove();
visitedTgtCells.append(tgtCellI);
scalar vol = interVol(src, tgt, 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);
appendNbrTgtCells(tgtCellI, tgt, visitedTgtCells, nbrTgtCells);
// accumulate intersection volume
V_ += vol;
}
}
while (!nbrTgtCells.empty());
mapFlag[srcCellI] = false;
// find new source seed cell
setNextCells
(
startSeedI,
srcCellI,
tgtCellI,
src,
tgt,
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::meshToMeshNew::calcAddressing void Foam::meshToMeshNew::calcAddressing
( (
const polyMesh& src, const polyMesh& src,
@ -726,14 +326,28 @@ void Foam::meshToMeshNew::calcAddressing
switch (method_) switch (method_)
{ {
case imMap: case imDirect:
{ {
calcDirect(src, tgt, srcSeedI, tgtSeedI); calcDirect(src, tgt, srcSeedI, tgtSeedI);
break; break;
} }
case imMapNearest:
{
calcMapNearest
(
src,
tgt,
srcSeedI,
tgtSeedI,
srcCellIDs,
mapFlag,
startSeedI
);
break;
}
case imCellVolumeWeight: case imCellVolumeWeight:
{ {
calcIndirect calcCellVolumeWeight
( (
src, src,
tgt, tgt,

View File

@ -28,6 +28,9 @@ Description
Class to calculate the cell-addressing between two overlapping meshes Class to calculate the cell-addressing between two overlapping meshes
SourceFiles SourceFiles
calcDirect.C
calcMapNearest.C
calcCellVolumeWeight.C
meshToMeshNew.C meshToMeshNew.C
meshToMeshNewTemplates.C meshToMeshNewTemplates.C
@ -61,11 +64,12 @@ public:
//- Enumeration specifying required accuracy //- Enumeration specifying required accuracy
enum interpolationMethod enum interpolationMethod
{ {
imMap, imDirect,
imMapNearest,
imCellVolumeWeight imCellVolumeWeight
}; };
static const NamedEnum<interpolationMethod, 2> static const NamedEnum<interpolationMethod, 3>
interpolationMethodNames_; interpolationMethodNames_;
private: private:
@ -149,9 +153,36 @@ private:
label& tgtSeedI label& tgtSeedI
) const; ) const;
//- Append target cell neihgbour cells to cellIDs list
void appendNbrCells
(
const label tgtCellI,
const polyMesh& tgt,
const DynamicList<label>& visitedTgtCells,
DynamicList<label>& nbrTgtCellIDs
) const;
//- Normalise the interpolation weights
void normaliseWeights
(
const word& descriptor,
const scalarField& cellVolumes,
const labelListList& addr,
scalarListList& wght
) const;
// Direct (one-to-one) mapping // Direct (one-to-one) mapping
//- Main driver routine for direct mapping
void calcDirect
(
const polyMesh& src,
const polyMesh& tgt,
const label srcSeedI,
const label tgtSeedI
);
//- Append to list of src mesh seed indices //- Append to list of src mesh seed indices
void appendToDirectSeeds void appendToDirectSeeds
( (
@ -164,36 +195,64 @@ private:
label& tgtSeedI label& tgtSeedI
) const; ) const;
//- Main driver routine for direct mapping // Nearest (non-conformal) mapping
void calcDirect
//- Main driver routine for nearest-mapping routine
void calcMapNearest
( (
const polyMesh& src, const polyMesh& src,
const polyMesh& tgt, const polyMesh& tgt,
const label srcSeedI, const label srcSeedI,
const label tgtSeedI const label tgtSeedI,
const labelList& srcCellIDs,
boolList& mapFlag,
label& startSeedI
); );
//- Find target cell index of cell closest to source cell
// Indirect (non-conformal) mapping void findNearestCell
//- Normalise the interpolation weights
void normaliseWeights
( (
const word& descriptor, const polyMesh& src,
const scalarField& cellVolumes,
const labelListList& addr,
scalarListList& wght
) const;
//- Append target cell neihgbour cells to cellIDs list
void appendNbrTgtCells
(
const label tgtCellI,
const polyMesh& tgt, const polyMesh& tgt,
const DynamicList<label>& visitedTgtCells, const label srcCellI,
DynamicList<label>& nbrTgtCellIDs label& tgtCellI
);
//- Set the next pair of cells
void setNextNearestCells
(
label& startSeedI,
label& srcCellI,
label& tgtCellI,
boolList& mapFlag,
const polyMesh& src,
const polyMesh& tgt,
const labelList& srcCellIDs
);
//- Find source cell for target cell
label findMappedSrcCell
(
const polyMesh& tgt,
const label tgtCellI,
const List<DynamicList<label> >& tgtToSrc
) const; ) const;
// Cell volume weighted (non-conformal) interpolation
//- Main driver routine for cell volume weighted interpolation
void calcCellVolumeWeight
(
const polyMesh& src,
const polyMesh& tgt,
const label srcSeedI,
const label tgtSeedI,
const labelList& srcCellIDs,
boolList& mapFlag,
label& startSeedI
);
//- Set the next cells in the advancing front algorithm //- Set the next cells in the advancing front algorithm
void setNextCells void setNextCells
( (
@ -226,18 +285,6 @@ private:
const label tgtCellI const label tgtCellI
) const; ) const;
//- Main driver routine for indirect mapping
void calcIndirect
(
const polyMesh& src,
const polyMesh& tgt,
const label srcSeedI,
const label tgtSeedI,
const labelList& srcCellIDs,
boolList& mapFlag,
label& startSeedI
);
//- Calculate the addressing between overalping regions of src and tgt //- Calculate the addressing between overalping regions of src and tgt
// meshes // meshes