mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Initial mattijsLib merge
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -x
|
||||
|
||||
( cd $FOAM_SRC/other && ./Allwmake )
|
||||
#( cd $FOAM_SRC/other && ./Allwmake )
|
||||
|
||||
( cd $FOAM_SRC/OpenFOAM && wmakeLnInclude . )
|
||||
|
||||
|
||||
@ -400,7 +400,8 @@ mapPolyMesh = $(polyMesh)/mapPolyMesh
|
||||
$(mapPolyMesh)/mapPolyMesh.C
|
||||
$(mapPolyMesh)/faceMapper/faceMapper.C
|
||||
$(mapPolyMesh)/cellMapper/cellMapper.C
|
||||
$(mapPolyMesh)/mapDistributePolyMesh/mapDistributePolyMesh.C
|
||||
$(mapPolyMesh)/mapDistribute/mapDistribute.C
|
||||
$(mapPolyMesh)/mapDistribute/mapDistributePolyMesh.C
|
||||
$(mapPolyMesh)/mapAddedPolyMesh.C
|
||||
|
||||
PrimitivePatch = $(primitiveMesh)/PrimitivePatch
|
||||
|
||||
@ -527,7 +527,7 @@ void Foam::FaceCellWave<Type>::handleProcPatches()
|
||||
{
|
||||
const polyPatch& patch = mesh_.boundaryMesh()[patchI];
|
||||
|
||||
if (Pstream::parRun() && isA<processorPolyPatch>(patch))
|
||||
if (isA<processorPolyPatch>(patch))
|
||||
{
|
||||
// Allocate buffers
|
||||
label nSendFaces;
|
||||
@ -580,7 +580,7 @@ void Foam::FaceCellWave<Type>::handleProcPatches()
|
||||
{
|
||||
const polyPatch& patch = mesh_.boundaryMesh()[patchI];
|
||||
|
||||
if (Pstream::parRun() && isA<processorPolyPatch>(patch))
|
||||
if (isA<processorPolyPatch>(patch))
|
||||
{
|
||||
const processorPolyPatch& procPatch =
|
||||
refCast<const processorPolyPatch>(patch);
|
||||
@ -812,7 +812,6 @@ Foam::FaceCellWave<Type>::FaceCellWave
|
||||
changedCells_(mesh_.nCells()),
|
||||
nChangedCells_(0),
|
||||
hasCyclicPatches_(hasPatchType(cyclicPolyPatch::typeName)),
|
||||
hasProcPatches_(hasPatchType(processorPolyPatch::typeName)),
|
||||
nEvals_(0),
|
||||
nUnvisitedCells_(mesh_.nCells()),
|
||||
nUnvisitedFaces_(mesh_.nFaces()),
|
||||
@ -843,7 +842,6 @@ Foam::FaceCellWave<Type>::FaceCellWave
|
||||
changedCells_(mesh_.nCells()),
|
||||
nChangedCells_(0),
|
||||
hasCyclicPatches_(hasPatchType(cyclicPolyPatch::typeName)),
|
||||
hasProcPatches_(hasPatchType(processorPolyPatch::typeName)),
|
||||
nEvals_(0),
|
||||
nUnvisitedCells_(mesh_.nCells()),
|
||||
nUnvisitedFaces_(mesh_.nFaces()),
|
||||
@ -1031,7 +1029,7 @@ Foam::label Foam::FaceCellWave<Type>::cellToFace()
|
||||
// Transfer changed faces across cyclic halves
|
||||
handleCyclicPatches();
|
||||
}
|
||||
if (hasProcPatches_)
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
// Transfer changed faces from neighbouring processors.
|
||||
handleProcPatches();
|
||||
@ -1060,7 +1058,7 @@ Foam::label Foam::FaceCellWave<Type>::iterate(const label maxIter)
|
||||
// Transfer changed faces across cyclic halves
|
||||
handleCyclicPatches();
|
||||
}
|
||||
if (hasProcPatches_)
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
// Transfer changed faces from neighbouring processors.
|
||||
handleProcPatches();
|
||||
|
||||
@ -32,8 +32,7 @@ Description
|
||||
|
||||
Handles parallel and cyclics and non-parallel cyclics.
|
||||
|
||||
Note
|
||||
Whether to propagate depends on the return value of Type::update
|
||||
Note: whether to propagate depends on the return value of Type::update
|
||||
which returns true (i.e. propagate) if the value changes by more than a
|
||||
certain tolerance.
|
||||
This tolerance can be very strict for normal face-cell and parallel
|
||||
@ -106,9 +105,6 @@ class FaceCellWave
|
||||
//- Contains cyclics
|
||||
bool hasCyclicPatches_;
|
||||
|
||||
//- Contains processor patches
|
||||
bool hasProcPatches_;
|
||||
|
||||
//- Number of evaluations
|
||||
label nEvals_;
|
||||
|
||||
|
||||
@ -164,9 +164,8 @@ public:
|
||||
//- Get value at index I
|
||||
inline unsigned int get(const label i) const;
|
||||
|
||||
|
||||
//- Set value at index I
|
||||
inline void set(const label i, const unsigned int val);
|
||||
//- Set value at index I. Return true if value changed.
|
||||
inline bool set(const label i, const unsigned int val);
|
||||
|
||||
|
||||
// Member operators
|
||||
|
||||
@ -151,7 +151,7 @@ inline unsigned int PackedList<nBits>::operator[](const label i) const
|
||||
|
||||
// Set value at i
|
||||
template<int nBits>
|
||||
inline void PackedList<nBits>::set(const label i, const unsigned int val)
|
||||
inline bool PackedList<nBits>::set(const label i, const unsigned int val)
|
||||
{
|
||||
# ifdef DEBUGList
|
||||
checkIndex(i);
|
||||
@ -175,7 +175,11 @@ inline void PackedList<nBits>::set(const label i, const unsigned int val)
|
||||
|
||||
unsigned int& elem = List<unsigned int>::operator[](intIndex(i));
|
||||
|
||||
unsigned int oldElem = elem;
|
||||
|
||||
elem = (elem & ~shiftedMask) | shiftedVal;
|
||||
|
||||
return elem != oldElem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -438,6 +438,38 @@ public:
|
||||
template <class T>
|
||||
static void listCombineScatter(List<T>& Value);
|
||||
|
||||
// Combine variants working on whole map at a time. Container needs to
|
||||
// have iterators and find() defined.
|
||||
|
||||
template <class Container, class CombineOp>
|
||||
static void mapCombineGather
|
||||
(
|
||||
const List<commsStruct>& comms,
|
||||
Container& Values,
|
||||
const CombineOp& cop
|
||||
);
|
||||
|
||||
//- Like above but switches between linear/tree communication
|
||||
template <class Container, class CombineOp>
|
||||
static void mapCombineGather
|
||||
(
|
||||
Container& Values,
|
||||
const CombineOp& cop
|
||||
);
|
||||
|
||||
//- Scatter data. Reverse of combineGather
|
||||
template <class Container>
|
||||
static void mapCombineScatter
|
||||
(
|
||||
const List<commsStruct>& comms,
|
||||
Container& Values
|
||||
);
|
||||
|
||||
//- Like above but switches between linear/tree communication
|
||||
template <class Container>
|
||||
static void mapCombineScatter(Container& Values);
|
||||
|
||||
|
||||
|
||||
// Gather/scatter keeping the individual processor data separate.
|
||||
// Values is a List of size Pstream::nProcs() where
|
||||
|
||||
@ -409,6 +409,147 @@ void Pstream::listCombineScatter(List<T>& Values)
|
||||
|
||||
|
||||
|
||||
// Same thing but for sparse list (map)
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
template <class Container, class CombineOp>
|
||||
void Pstream::mapCombineGather
|
||||
(
|
||||
const List<Pstream::commsStruct>& comms,
|
||||
Container& Values,
|
||||
const CombineOp& cop
|
||||
)
|
||||
{
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
// Get my communication order
|
||||
const commsStruct& myComm = comms[Pstream::myProcNo()];
|
||||
|
||||
// Receive from my downstairs neighbours
|
||||
forAll(myComm.below(), belowI)
|
||||
{
|
||||
label belowID = myComm.below()[belowI];
|
||||
|
||||
IPstream fromBelow(Pstream::scheduled, belowID);
|
||||
Container receivedValues(fromBelow);
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< " received from "
|
||||
<< belowID << " data:" << receivedValues << endl;
|
||||
}
|
||||
|
||||
for
|
||||
(
|
||||
typename Container::const_iterator slaveIter =
|
||||
receivedValues.begin();
|
||||
slaveIter != receivedValues.end();
|
||||
++slaveIter
|
||||
)
|
||||
{
|
||||
typename Container::iterator
|
||||
masterIter = Values.find(slaveIter.key());
|
||||
|
||||
if (masterIter != Values.end())
|
||||
{
|
||||
cop(masterIter(), slaveIter());
|
||||
}
|
||||
else
|
||||
{
|
||||
Values.insert(slaveIter.key(), slaveIter());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send up Value
|
||||
if (myComm.above() != -1)
|
||||
{
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< " sending to " << myComm.above()
|
||||
<< " data:" << Values << endl;
|
||||
}
|
||||
|
||||
OPstream toAbove(Pstream::scheduled, myComm.above());
|
||||
toAbove << Values;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class Container, class CombineOp>
|
||||
void Pstream::mapCombineGather(Container& Values, const CombineOp& cop)
|
||||
{
|
||||
if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
|
||||
{
|
||||
mapCombineGather(Pstream::linearCommunication(), Values, cop);
|
||||
}
|
||||
else
|
||||
{
|
||||
mapCombineGather(Pstream::treeCommunication(), Values, cop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class Container>
|
||||
void Pstream::mapCombineScatter
|
||||
(
|
||||
const List<Pstream::commsStruct>& comms,
|
||||
Container& Values
|
||||
)
|
||||
{
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
// Get my communication order
|
||||
const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
|
||||
|
||||
// Reveive from up
|
||||
if (myComm.above() != -1)
|
||||
{
|
||||
IPstream fromAbove(Pstream::scheduled, myComm.above());
|
||||
fromAbove >> Values;
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< " received from "
|
||||
<< myComm.above() << " data:" << Values << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Send to my downstairs neighbours
|
||||
forAll(myComm.below(), belowI)
|
||||
{
|
||||
label belowID = myComm.below()[belowI];
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< " sending to " << belowID << " data:" << Values << endl;
|
||||
}
|
||||
|
||||
OPstream toBelow(Pstream::scheduled, belowID);
|
||||
toBelow << Values;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class Container>
|
||||
void Pstream::mapCombineScatter(Container& Values)
|
||||
{
|
||||
if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
|
||||
{
|
||||
mapCombineScatter(Pstream::linearCommunication(), Values);
|
||||
}
|
||||
else
|
||||
{
|
||||
mapCombineScatter(Pstream::treeCommunication(), Values);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
@ -188,7 +188,7 @@ public:
|
||||
//- Return potential intersection with face with a ray starting
|
||||
// at p, direction n (does not need to be normalized)
|
||||
// Does face-center decomposition and returns triangle intersection
|
||||
// point closest to p.
|
||||
// point closest to p. Face-center is calculated from point average.
|
||||
// For a hit, the distance is signed. Positive number
|
||||
// represents the point in front of triangle
|
||||
// In case of miss the point is the nearest point on the face
|
||||
@ -206,6 +206,19 @@ public:
|
||||
const intersection::direction dir = intersection::VECTOR
|
||||
) const;
|
||||
|
||||
//- Fast intersection with a ray.
|
||||
// For a hit, the pointHit.distance() is the line parameter t :
|
||||
// intersection=p+t*q. Only defined for FULL_RAY or
|
||||
// HALF_RAY.
|
||||
pointHit intersection
|
||||
(
|
||||
const point& p,
|
||||
const vector& q,
|
||||
const point& ctr,
|
||||
const pointField& meshPoints,
|
||||
const intersection::algorithm alg
|
||||
) const;
|
||||
|
||||
//- Return nearest point to face
|
||||
pointHit nearestPoint
|
||||
(
|
||||
|
||||
@ -133,6 +133,52 @@ pointHit face::ray
|
||||
}
|
||||
|
||||
|
||||
pointHit face::intersection
|
||||
(
|
||||
const point& p,
|
||||
const vector& q,
|
||||
const point& ctr,
|
||||
const pointField& meshPoints,
|
||||
const intersection::algorithm alg
|
||||
) const
|
||||
{
|
||||
scalar nearestHitDist = VGREAT;
|
||||
|
||||
// Initialize to miss, distance = GREAT
|
||||
pointHit nearest(p);
|
||||
|
||||
const labelList& f = *this;
|
||||
|
||||
forAll(f, pI)
|
||||
{
|
||||
// Note: for best accuracy, centre point always comes last
|
||||
pointHit curHit = triPointRef
|
||||
(
|
||||
meshPoints[f[pI]],
|
||||
meshPoints[f[fcIndex(pI)]],
|
||||
ctr
|
||||
).intersection(p, q, alg);
|
||||
|
||||
if (curHit.hit())
|
||||
{
|
||||
if (Foam::mag(curHit.distance()) < nearestHitDist)
|
||||
{
|
||||
nearestHitDist = Foam::mag(curHit.distance());
|
||||
nearest.setHit();
|
||||
nearest.setPoint(curHit.hitPoint());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nearest.hit())
|
||||
{
|
||||
nearest.setDistance(nearestHitDist);
|
||||
}
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
||||
|
||||
pointHit face::nearestPoint
|
||||
(
|
||||
const point& p,
|
||||
|
||||
@ -64,9 +64,11 @@ bool Foam::matchPoints
|
||||
startI = 0;
|
||||
}
|
||||
|
||||
label face1I = -1;
|
||||
|
||||
// Go through range of equal mag and find equal vector.
|
||||
// Go through range of equal mag and find nearest vector.
|
||||
scalar minDistSqr = VGREAT;
|
||||
label minFaceI = -1;
|
||||
|
||||
for
|
||||
(
|
||||
label j = startI;
|
||||
@ -78,17 +80,17 @@ bool Foam::matchPoints
|
||||
)
|
||||
{
|
||||
label faceI = pts1MagSqr.indices()[j];
|
||||
|
||||
// Compare actual vectors
|
||||
if (magSqr(pts0[face0I] - pts1[faceI]) <= sqr(matchDist))
|
||||
{
|
||||
face1I = faceI;
|
||||
scalar distSqr = magSqr(pts0[face0I] - pts1[faceI]);
|
||||
|
||||
break;
|
||||
if (distSqr <= sqr(matchDist) && distSqr < minDistSqr)
|
||||
{
|
||||
minDistSqr = distSqr;
|
||||
minFaceI = faceI;
|
||||
}
|
||||
}
|
||||
|
||||
if (face1I == -1)
|
||||
if (minFaceI == -1)
|
||||
{
|
||||
fullMatch = false;
|
||||
|
||||
@ -120,7 +122,7 @@ bool Foam::matchPoints
|
||||
}
|
||||
}
|
||||
|
||||
from0To1[face0I] = face1I;
|
||||
from0To1[face0I] = minFaceI;
|
||||
}
|
||||
|
||||
return fullMatch;
|
||||
|
||||
@ -0,0 +1,197 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "mapDistribute.H"
|
||||
#include "commSchedule.H"
|
||||
#include "HashSet.H"
|
||||
#include "ListOps.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::mapDistribute::calcSchedule() const
|
||||
{
|
||||
// Communications: send and receive processor
|
||||
List<labelPair> allComms;
|
||||
|
||||
{
|
||||
HashSet<labelPair, labelPair::Hash<> > commsSet(Pstream::nProcs());
|
||||
|
||||
// Find what communication is required
|
||||
forAll(subMap_, procI)
|
||||
{
|
||||
if (procI != Pstream::myProcNo())
|
||||
{
|
||||
if (subMap_[procI].size() > 0)
|
||||
{
|
||||
// I need to send to procI
|
||||
commsSet.insert(labelPair(Pstream::myProcNo(), procI));
|
||||
}
|
||||
if (constructMap_[procI].size() > 0)
|
||||
{
|
||||
// I need to receive from procI
|
||||
commsSet.insert(labelPair(procI, Pstream::myProcNo()));
|
||||
}
|
||||
}
|
||||
}
|
||||
allComms = commsSet.toc();
|
||||
}
|
||||
|
||||
|
||||
// Reduce
|
||||
if (Pstream::master())
|
||||
{
|
||||
// Receive and merge
|
||||
for
|
||||
(
|
||||
int slave=Pstream::firstSlave();
|
||||
slave<=Pstream::lastSlave();
|
||||
slave++
|
||||
)
|
||||
{
|
||||
IPstream fromSlave(Pstream::blocking, slave);
|
||||
List<labelPair> nbrData(fromSlave);
|
||||
|
||||
forAll(nbrData, i)
|
||||
{
|
||||
if (findIndex(allComms, nbrData[i]) == -1)
|
||||
{
|
||||
label sz = allComms.size();
|
||||
allComms.setSize(sz+1);
|
||||
allComms[sz] = nbrData[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Send back
|
||||
for
|
||||
(
|
||||
int slave=Pstream::firstSlave();
|
||||
slave<=Pstream::lastSlave();
|
||||
slave++
|
||||
)
|
||||
{
|
||||
OPstream toSlave(Pstream::blocking, slave);
|
||||
toSlave << allComms;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
OPstream toMaster(Pstream::blocking, Pstream::masterNo());
|
||||
toMaster << allComms;
|
||||
}
|
||||
{
|
||||
IPstream fromMaster(Pstream::blocking, Pstream::masterNo());
|
||||
fromMaster >> allComms;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Determine my schedule.
|
||||
labelList mySchedule
|
||||
(
|
||||
commSchedule
|
||||
(
|
||||
Pstream::nProcs(),
|
||||
allComms
|
||||
).procSchedule()[Pstream::myProcNo()]
|
||||
);
|
||||
|
||||
// Processors involved in my schedule
|
||||
schedulePtr_.reset
|
||||
(
|
||||
new List<labelPair>
|
||||
(
|
||||
IndirectList<labelPair>(allComms, mySchedule)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
//if (debug)
|
||||
//{
|
||||
// Pout<< "I need to:" << endl;
|
||||
// const List<labelPair>& comms = schedule();
|
||||
// forAll(comms, i)
|
||||
// {
|
||||
// const labelPair& twoProcs = comms[i];
|
||||
// label sendProc = twoProcs[0];
|
||||
// label recvProc = twoProcs[1];
|
||||
//
|
||||
// if (recvProc == Pstream::myProcNo())
|
||||
// {
|
||||
// Pout<< " receive from " << sendProc << endl;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Pout<< " send to " << recvProc << endl;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
//- Construct from components
|
||||
Foam::mapDistribute::mapDistribute
|
||||
(
|
||||
const label constructSize,
|
||||
const labelListList& subMap,
|
||||
const labelListList& constructMap
|
||||
)
|
||||
:
|
||||
constructSize_(constructSize),
|
||||
subMap_(subMap),
|
||||
constructMap_(constructMap),
|
||||
schedulePtr_()
|
||||
{}
|
||||
|
||||
|
||||
//- (optionally destructively) construct from components
|
||||
Foam::mapDistribute::mapDistribute
|
||||
(
|
||||
const label constructSize,
|
||||
labelListList& subMap,
|
||||
labelListList& constructMap,
|
||||
const bool reUse // clone or reuse
|
||||
)
|
||||
:
|
||||
constructSize_(constructSize),
|
||||
subMap_(subMap, reUse),
|
||||
constructMap_(constructMap, reUse),
|
||||
schedulePtr_()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,203 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::mapDistribute
|
||||
|
||||
Description
|
||||
Class containing processor-to-processor mapping information.
|
||||
|
||||
We store mapping from the bits-to-send to the complete starting list
|
||||
(subXXXMap) and from the received bits to their location in the new
|
||||
list (constructXXXMap).
|
||||
|
||||
Note:
|
||||
Schedule is a list of processor pairs (one send, one receive. One of
|
||||
them will be myself) which forms a scheduled (i.e. non-buffered) exchange.
|
||||
See distribute on how to use it.
|
||||
|
||||
|
||||
SourceFiles
|
||||
mapDistribute.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef mapDistribute_H
|
||||
#define mapDistribute_H
|
||||
|
||||
#include "labelList.H"
|
||||
#include "labelPair.H"
|
||||
#include "Pstream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
class mapPolyMesh;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class mapDistribute Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class mapDistribute
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Size of reconstructed data
|
||||
label constructSize_;
|
||||
|
||||
//- Maps from subsetted data back to original data
|
||||
labelListList subMap_;
|
||||
|
||||
//- Maps from subsetted data to new reconstructed data
|
||||
labelListList constructMap_;
|
||||
|
||||
//- Schedule
|
||||
mutable autoPtr<List<labelPair> > schedulePtr_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
void calcSchedule() const;
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
mapDistribute(const mapDistribute&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const mapDistribute&);
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
mapDistribute
|
||||
(
|
||||
const label constructSize,
|
||||
const labelListList& subMap,
|
||||
const labelListList& constructMap
|
||||
);
|
||||
|
||||
//- (optionally destructively) construct from components
|
||||
mapDistribute
|
||||
(
|
||||
const label constructSize,
|
||||
labelListList& subMap,
|
||||
labelListList& constructMap,
|
||||
const bool reUse // clone or reuse
|
||||
);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Constructed data size
|
||||
label constructSize() const
|
||||
{
|
||||
return constructSize_;
|
||||
}
|
||||
|
||||
//- From subsetted data back to original data
|
||||
const labelListList& subMap() const
|
||||
{
|
||||
return subMap_;
|
||||
}
|
||||
|
||||
//- From subsetted data to new reconstructed data
|
||||
const labelListList& constructMap() const
|
||||
{
|
||||
return constructMap_;
|
||||
}
|
||||
|
||||
//- Return a schedule. Demand driven. See above.
|
||||
const List<labelPair>& schedule() const
|
||||
{
|
||||
if (!schedulePtr_.valid())
|
||||
{
|
||||
calcSchedule();
|
||||
}
|
||||
return schedulePtr_();
|
||||
}
|
||||
|
||||
|
||||
// Other
|
||||
|
||||
//- Distribute data. Note:schedule only used for Pstream::scheduled
|
||||
// for now, all others just use send-to-all, receive-from-all.
|
||||
template<class T>
|
||||
static void distribute
|
||||
(
|
||||
const Pstream::commsTypes commsType,
|
||||
const List<labelPair>& schedule,
|
||||
const label constructSize,
|
||||
const labelListList& subMap,
|
||||
const labelListList& constructMap,
|
||||
List<T>&
|
||||
);
|
||||
|
||||
//- Distribute data using scheduling.
|
||||
template<class T>
|
||||
void distribute(List<T>& fld) const
|
||||
{
|
||||
distribute
|
||||
(
|
||||
Pstream::scheduled,
|
||||
schedule(),
|
||||
constructSize_,
|
||||
subMap_,
|
||||
constructMap_,
|
||||
fld
|
||||
);
|
||||
}
|
||||
|
||||
//- Correct for topo change.
|
||||
void updateMesh(const mapPolyMesh&)
|
||||
{
|
||||
notImplemented
|
||||
(
|
||||
"mapDistribute::updateMesh(const mapPolyMesh&)"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
# include "mapDistributeTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,146 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::mapDistributeLagrangian
|
||||
|
||||
Description
|
||||
Class containing mesh-to-mesh mapping information for particles
|
||||
|
||||
SourceFiles
|
||||
mapDistributeLagrangian.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef mapDistributeLagrangian_H
|
||||
#define mapDistributeLagrangian_H
|
||||
|
||||
#include "mapDistribute.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
class mapPolyMesh;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class mapDistributeLagrangian Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class mapDistributeLagrangian
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Map to distribute particles
|
||||
const mapDistribute particleMap_;
|
||||
|
||||
//- Per element in subsetted mesh the cell label
|
||||
const labelListList constructCellLabels_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
mapDistributeLagrangian
|
||||
(
|
||||
const label nNewParticles,
|
||||
const labelListList& subParticleMap,
|
||||
const labelListList& constructParticleMap,
|
||||
const labelListList& constructCellLabels
|
||||
)
|
||||
:
|
||||
particleMap_(nNewParticles, subParticleMap, constructParticleMap),
|
||||
constructCellLabels_(constructCellLabels)
|
||||
{}
|
||||
|
||||
//- Construct from components and steal storage
|
||||
mapDistributeLagrangian
|
||||
(
|
||||
const label nNewParticles,
|
||||
labelListList& subParticleMap,
|
||||
labelListList& constructParticleMap,
|
||||
labelListList& constructCellLabels,
|
||||
const bool reUse
|
||||
)
|
||||
:
|
||||
particleMap_
|
||||
(
|
||||
nNewParticles,
|
||||
subParticleMap,
|
||||
constructParticleMap,
|
||||
reUse
|
||||
),
|
||||
constructCellLabels_(constructCellLabels, reUse)
|
||||
{}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Distribution map
|
||||
const mapDistribute& particleMap() const
|
||||
{
|
||||
return particleMap_;
|
||||
}
|
||||
|
||||
//- Per received particle the destination cell label
|
||||
const labelListList& constructCellLabels() const
|
||||
{
|
||||
return constructCellLabels_;
|
||||
}
|
||||
|
||||
|
||||
// Edit
|
||||
|
||||
//- distribute list of lagrangian data
|
||||
template<class T>
|
||||
void distributeLagrangianData(List<T>& lst) const
|
||||
{
|
||||
particleMap_.distribute(lst);
|
||||
}
|
||||
|
||||
//- Correct for topo change.
|
||||
void updateMesh(const mapPolyMesh&)
|
||||
{
|
||||
notImplemented
|
||||
(
|
||||
"mapDistributeLagrangian::updateMesh(const mapPolyMesh&)"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,235 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "mapDistributePolyMesh.H"
|
||||
#include "polyMesh.H"
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::mapDistributePolyMesh::calcPatchSizes()
|
||||
{
|
||||
oldPatchSizes_.setSize(oldPatchStarts_.size());
|
||||
|
||||
// Calculate old patch sizes
|
||||
for (label patchI = 0; patchI < oldPatchStarts_.size() - 1; patchI++)
|
||||
{
|
||||
oldPatchSizes_[patchI] =
|
||||
oldPatchStarts_[patchI + 1] - oldPatchStarts_[patchI];
|
||||
}
|
||||
|
||||
// Set the last one by hand
|
||||
const label lastPatchID = oldPatchStarts_.size() - 1;
|
||||
|
||||
oldPatchSizes_[lastPatchID] = nOldFaces_ - oldPatchStarts_[lastPatchID];
|
||||
|
||||
if (min(oldPatchSizes_) < 0)
|
||||
{
|
||||
FatalErrorIn("mapDistributePolyMesh::calcPatchSizes()")
|
||||
<< "Calculated negative old patch size:" << oldPatchSizes_ << nl
|
||||
<< "Error in mapping data" << abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
//- Construct from components
|
||||
Foam::mapDistributePolyMesh::mapDistributePolyMesh
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
|
||||
// mesh before changes
|
||||
const label nOldPoints,
|
||||
const label nOldFaces,
|
||||
const label nOldCells,
|
||||
const labelList& oldPatchStarts,
|
||||
const labelList& oldPatchNMeshPoints,
|
||||
|
||||
// how to subset pieces of mesh to send across
|
||||
const labelListList& subPointMap,
|
||||
const labelListList& subFaceMap,
|
||||
const labelListList& subCellMap,
|
||||
const labelListList& subPatchMap,
|
||||
|
||||
// how to reconstruct received mesh
|
||||
const labelListList& constructPointMap,
|
||||
const labelListList& constructFaceMap,
|
||||
const labelListList& constructCellMap,
|
||||
const labelListList& constructPatchMap
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
nOldPoints_(nOldPoints),
|
||||
nOldFaces_(nOldFaces),
|
||||
nOldCells_(nOldCells),
|
||||
oldPatchSizes_(oldPatchStarts.size()),
|
||||
oldPatchStarts_(oldPatchStarts),
|
||||
oldPatchNMeshPoints_(oldPatchNMeshPoints),
|
||||
pointMap_(mesh.nPoints(), subPointMap, constructPointMap),
|
||||
faceMap_(mesh.nFaces(), subFaceMap, constructFaceMap),
|
||||
cellMap_(mesh.nCells(), subCellMap, constructCellMap),
|
||||
patchMap_(mesh.boundaryMesh().size(), subPatchMap, constructPatchMap)
|
||||
{
|
||||
calcPatchSizes();
|
||||
}
|
||||
|
||||
|
||||
//- (optionally destructively) construct from components
|
||||
Foam::mapDistributePolyMesh::mapDistributePolyMesh
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const label nOldPoints,
|
||||
const label nOldFaces,
|
||||
const label nOldCells,
|
||||
labelList& oldPatchStarts,
|
||||
labelList& oldPatchNMeshPoints,
|
||||
|
||||
labelListList& subPointMap,
|
||||
labelListList& subFaceMap,
|
||||
labelListList& subCellMap,
|
||||
labelListList& subPatchMap,
|
||||
labelListList& constructPointMap,
|
||||
labelListList& constructFaceMap,
|
||||
labelListList& constructCellMap,
|
||||
labelListList& constructPatchMap,
|
||||
const bool reUse // clone or reuse
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
nOldPoints_(nOldPoints),
|
||||
nOldFaces_(nOldFaces),
|
||||
nOldCells_(nOldCells),
|
||||
oldPatchSizes_(oldPatchStarts.size()),
|
||||
oldPatchStarts_(oldPatchStarts, reUse),
|
||||
oldPatchNMeshPoints_(oldPatchNMeshPoints, reUse),
|
||||
|
||||
pointMap_(mesh.nPoints(), subPointMap, constructPointMap, reUse),
|
||||
faceMap_(mesh.nFaces(), subFaceMap, constructFaceMap, reUse),
|
||||
cellMap_(mesh.nCells(), subCellMap, constructCellMap, reUse),
|
||||
patchMap_(mesh.boundaryMesh().size(), subPatchMap, constructPatchMap, reUse)
|
||||
{
|
||||
calcPatchSizes();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::mapDistributePolyMesh::distributePointIndices(labelList& lst) const
|
||||
{
|
||||
// Construct boolList from selected elements
|
||||
boolList isSelected
|
||||
(
|
||||
createWithValues<boolList>
|
||||
(
|
||||
nOldPoints(),
|
||||
false,
|
||||
lst,
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
// Distribute
|
||||
distributePointData(isSelected);
|
||||
|
||||
// Collect selected elements
|
||||
lst = findIndices(isSelected, true);
|
||||
}
|
||||
|
||||
|
||||
void Foam::mapDistributePolyMesh::distributeFaceIndices(labelList& lst) const
|
||||
{
|
||||
// Construct boolList from selected elements
|
||||
boolList isSelected
|
||||
(
|
||||
createWithValues<boolList>
|
||||
(
|
||||
nOldFaces(),
|
||||
false,
|
||||
lst,
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
// Distribute
|
||||
distributeFaceData(isSelected);
|
||||
|
||||
// Collect selected elements
|
||||
lst = findIndices(isSelected, true);
|
||||
}
|
||||
|
||||
|
||||
void Foam::mapDistributePolyMesh::distributeCellIndices(labelList& lst) const
|
||||
{
|
||||
// Construct boolList from selected elements
|
||||
boolList isSelected
|
||||
(
|
||||
createWithValues<boolList>
|
||||
(
|
||||
nOldCells(),
|
||||
false,
|
||||
lst,
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
// Distribute
|
||||
distributeCellData(isSelected);
|
||||
|
||||
// Collect selected elements
|
||||
lst = findIndices(isSelected, true);
|
||||
}
|
||||
|
||||
|
||||
void Foam::mapDistributePolyMesh::distributePatchIndices(labelList& lst) const
|
||||
{
|
||||
// Construct boolList from selected elements
|
||||
boolList isSelected
|
||||
(
|
||||
createWithValues<boolList>
|
||||
(
|
||||
oldPatchStarts().size(), // nOldPatches
|
||||
false,
|
||||
lst,
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
// Distribute
|
||||
distributePatchData(isSelected);
|
||||
|
||||
// Collect selected elements
|
||||
lst = findIndices(isSelected, true);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,291 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::mapDistributePolyMesh
|
||||
|
||||
Description
|
||||
Class containing mesh-to-mesh mapping information after a mesh distribution
|
||||
where we send parts of meshes (using subsetting) to other processors
|
||||
and receive and reconstruct mesh.
|
||||
|
||||
We store mapping from the bits-to-send to the complete starting mesh
|
||||
(subXXXMap) and from the received bits to their location in the new
|
||||
mesh (constructXXXMap).
|
||||
|
||||
SourceFiles
|
||||
mapDistributePolyMesh.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef mapDistributePolyMesh_H
|
||||
#define mapDistributePolyMesh_H
|
||||
|
||||
#include "mapDistribute.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
class mapPolyMesh;
|
||||
class polyMesh;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class mapDistributePolyMesh Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class mapDistributePolyMesh
|
||||
{
|
||||
// Private data
|
||||
|
||||
const polyMesh& mesh_;
|
||||
|
||||
//- Number of old live points
|
||||
const label nOldPoints_;
|
||||
|
||||
//- Number of old live faces
|
||||
const label nOldFaces_;
|
||||
|
||||
//- Number of old live cells
|
||||
const label nOldCells_;
|
||||
|
||||
//- List of the old patch sizes
|
||||
labelList oldPatchSizes_;
|
||||
|
||||
//- List of the old patch start labels
|
||||
const labelList oldPatchStarts_;
|
||||
|
||||
//- List of numbers of mesh points per old patch
|
||||
const labelList oldPatchNMeshPoints_;
|
||||
|
||||
|
||||
//- Point distribute map
|
||||
const mapDistribute pointMap_;
|
||||
|
||||
//- Face distribute map
|
||||
const mapDistribute faceMap_;
|
||||
|
||||
//- Cell distribute map
|
||||
const mapDistribute cellMap_;
|
||||
|
||||
//- Patch distribute map
|
||||
const mapDistribute patchMap_;
|
||||
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
void calcPatchSizes();
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
mapDistributePolyMesh(const mapDistributePolyMesh&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const mapDistributePolyMesh&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components. Note that mesh has to be changed already
|
||||
// since uses mesh.nPoints etc as the new size.
|
||||
mapDistributePolyMesh
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
|
||||
// mesh before changes
|
||||
const label nOldPoints,
|
||||
const label nOldFaces,
|
||||
const label nOldCells,
|
||||
const labelList& oldPatchStarts,
|
||||
const labelList& oldPatchNMeshPoints,
|
||||
|
||||
// how to subset pieces of mesh to send across
|
||||
const labelListList& subPointMap,
|
||||
const labelListList& subFaceMap,
|
||||
const labelListList& subCellMap,
|
||||
const labelListList& subPatchMap,
|
||||
|
||||
// how to reconstruct received mesh
|
||||
const labelListList& constructPointMap,
|
||||
const labelListList& constructFaceMap,
|
||||
const labelListList& constructCellMap,
|
||||
const labelListList& constructPatchMap
|
||||
);
|
||||
|
||||
//- (optionally destructively) construct from components
|
||||
// Note that mesh has to be changed already!
|
||||
mapDistributePolyMesh
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const label nOldPoints,
|
||||
const label nOldFaces,
|
||||
const label nOldCells,
|
||||
labelList& oldPatchStarts,
|
||||
labelList& oldPatchNMeshPoints,
|
||||
|
||||
labelListList& subPointMap,
|
||||
labelListList& subFaceMap,
|
||||
labelListList& subCellMap,
|
||||
labelListList& subPatchMap,
|
||||
labelListList& constructPointMap,
|
||||
labelListList& constructFaceMap,
|
||||
labelListList& constructCellMap,
|
||||
labelListList& constructPatchMap,
|
||||
const bool reUse // clone or reuse
|
||||
);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
const polyMesh& mesh() const
|
||||
{
|
||||
return mesh_;
|
||||
}
|
||||
|
||||
//- Number of points in mesh before distribution
|
||||
label nOldPoints() const
|
||||
{
|
||||
return nOldPoints_;
|
||||
}
|
||||
|
||||
//- Number of faces in mesh before distribution
|
||||
label nOldFaces() const
|
||||
{
|
||||
return nOldFaces_;
|
||||
}
|
||||
|
||||
//- Number of cells in mesh before distribution
|
||||
label nOldCells() const
|
||||
{
|
||||
return nOldCells_;
|
||||
}
|
||||
|
||||
//- List of the old patch sizes
|
||||
const labelList& oldPatchSizes() const
|
||||
{
|
||||
return oldPatchSizes_;
|
||||
}
|
||||
|
||||
//- List of the old patch start labels
|
||||
const labelList& oldPatchStarts() const
|
||||
{
|
||||
return oldPatchStarts_;
|
||||
}
|
||||
|
||||
//- List of numbers of mesh points per old patch
|
||||
const labelList& oldPatchNMeshPoints() const
|
||||
{
|
||||
return oldPatchNMeshPoints_;
|
||||
}
|
||||
|
||||
//- Point distribute map
|
||||
const mapDistribute& pointMap() const
|
||||
{
|
||||
return pointMap_;
|
||||
}
|
||||
|
||||
//- Face distribute map
|
||||
const mapDistribute& faceMap() const
|
||||
{
|
||||
return faceMap_;
|
||||
}
|
||||
|
||||
//- Cell distribute map
|
||||
const mapDistribute& cellMap() const
|
||||
{
|
||||
return cellMap_;
|
||||
}
|
||||
|
||||
//- Patch distribute map
|
||||
const mapDistribute& patchMap() const
|
||||
{
|
||||
return patchMap_;
|
||||
}
|
||||
|
||||
|
||||
// Edit
|
||||
|
||||
//- distribute list of point data
|
||||
template<class T>
|
||||
void distributePointData(List<T>& lst) const
|
||||
{
|
||||
pointMap_.distribute(lst);
|
||||
}
|
||||
|
||||
//- distribute list of face data
|
||||
template<class T>
|
||||
void distributeFaceData(List<T>& lst) const
|
||||
{
|
||||
faceMap_.distribute(lst);
|
||||
}
|
||||
|
||||
//- distribute list of cell data
|
||||
template<class T>
|
||||
void distributeCellData(List<T>& lst) const
|
||||
{
|
||||
cellMap_.distribute(lst);
|
||||
}
|
||||
|
||||
//- distribute list of patch data
|
||||
template<class T>
|
||||
void distributePatchData(List<T>& lst) const
|
||||
{
|
||||
patchMap_.distribute(lst);
|
||||
}
|
||||
|
||||
|
||||
//- distribute list of point/face/cell/patch indices.
|
||||
// (Converts to boolList, distributes boolList and reconstructs)
|
||||
void distributePointIndices(labelList& pointIDs) const;
|
||||
|
||||
void distributeFaceIndices(labelList& faceIDs) const;
|
||||
void distributeCellIndices(labelList& cellIDs) const;
|
||||
void distributePatchIndices(labelList& patchIDs) const;
|
||||
|
||||
|
||||
//- Correct for topo change.
|
||||
void updateMesh(const mapPolyMesh&)
|
||||
{
|
||||
notImplemented
|
||||
(
|
||||
"mapDistributePolyMesh::updateMesh(const mapPolyMesh&)"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,190 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "Pstream.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
// Distribute list.
|
||||
template<class T>
|
||||
void Foam::mapDistribute::distribute
|
||||
(
|
||||
const Pstream::commsTypes commsType,
|
||||
const List<labelPair>& schedule,
|
||||
const label constructSize,
|
||||
const labelListList& subMap,
|
||||
const labelListList& constructMap,
|
||||
List<T>& field
|
||||
)
|
||||
{
|
||||
if (commsType == Pstream::blocking)
|
||||
{
|
||||
// Since buffered sending can reuse the field to collect the
|
||||
// received data.
|
||||
|
||||
// Send sub field to neighbour
|
||||
for (label domain = 0; domain < Pstream::nProcs(); domain++)
|
||||
{
|
||||
if (domain != Pstream::myProcNo())
|
||||
{
|
||||
OPstream toNbr(Pstream::blocking, domain);
|
||||
toNbr << IndirectList<T>(field, subMap[domain])();
|
||||
}
|
||||
}
|
||||
|
||||
// Subset myself
|
||||
List<T> subField(IndirectList<T>(field, subMap[Pstream::myProcNo()]));
|
||||
|
||||
// Receive sub field from myself (subField)
|
||||
const labelList& map = constructMap[Pstream::myProcNo()];
|
||||
|
||||
field.setSize(constructSize);
|
||||
|
||||
forAll(map, i)
|
||||
{
|
||||
field[map[i]] = subField[i];
|
||||
}
|
||||
|
||||
// Receive sub field from neighbour
|
||||
for (label domain = 0; domain < Pstream::nProcs(); domain++)
|
||||
{
|
||||
if (domain != Pstream::myProcNo())
|
||||
{
|
||||
IPstream fromNbr(Pstream::blocking, domain);
|
||||
List<T> subField(fromNbr);
|
||||
|
||||
const labelList& map = constructMap[domain];
|
||||
|
||||
forAll(map, i)
|
||||
{
|
||||
field[map[i]] = subField[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (commsType == Pstream::scheduled)
|
||||
{
|
||||
// Need to make sure I don't overwrite field with received data
|
||||
// since the data might need to be sent to another processor. So
|
||||
// allocate a new field for the results.
|
||||
List<T> newField(constructSize);
|
||||
|
||||
// Subset myself
|
||||
List<T> subField(IndirectList<T>(field, subMap[Pstream::myProcNo()]));
|
||||
|
||||
// Receive sub field from myself (subField)
|
||||
const labelList& map = constructMap[Pstream::myProcNo()];
|
||||
|
||||
forAll(map, i)
|
||||
{
|
||||
newField[map[i]] = subField[i];
|
||||
}
|
||||
|
||||
forAll(schedule, i)
|
||||
{
|
||||
const labelPair& twoProcs = schedule[i];
|
||||
label sendProc = twoProcs[0];
|
||||
label recvProc = twoProcs[1];
|
||||
|
||||
if (Pstream::myProcNo() == sendProc)
|
||||
{
|
||||
// I am sender. Send to recvProc.
|
||||
OPstream toNbr(Pstream::scheduled, recvProc);
|
||||
toNbr << IndirectList<T>(field, subMap[recvProc])();
|
||||
}
|
||||
else
|
||||
{
|
||||
// I am receiver. Receive from sendProc.
|
||||
IPstream fromNbr(Pstream::scheduled, sendProc);
|
||||
List<T> subField(fromNbr);
|
||||
|
||||
const labelList& map = constructMap[sendProc];
|
||||
|
||||
forAll(map, i)
|
||||
{
|
||||
newField[map[i]] = subField[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
field.transfer(newField);
|
||||
}
|
||||
else if (commsType == Pstream::nonBlocking)
|
||||
{
|
||||
List<T> newField(constructSize);
|
||||
|
||||
// Subset myself
|
||||
List<T> subField(IndirectList<T>(field, subMap[Pstream::myProcNo()]));
|
||||
|
||||
// Receive sub field from myself (subField)
|
||||
const labelList& map = constructMap[Pstream::myProcNo()];
|
||||
|
||||
forAll(map, i)
|
||||
{
|
||||
newField[map[i]] = subField[i];
|
||||
}
|
||||
|
||||
// Send sub field to neighbour
|
||||
for (label domain = 0; domain < Pstream::nProcs(); domain++)
|
||||
{
|
||||
if (domain != Pstream::myProcNo())
|
||||
{
|
||||
OPstream toNbr(Pstream::nonBlocking, domain);
|
||||
toNbr << IndirectList<T>(field, subMap[domain])();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Receive sub field from neighbour
|
||||
for (label domain = 0; domain < Pstream::nProcs(); domain++)
|
||||
{
|
||||
if (domain != Pstream::myProcNo())
|
||||
{
|
||||
IPstream fromNbr(Pstream::nonBlocking, domain);
|
||||
List<T> subField(fromNbr);
|
||||
|
||||
const labelList& map = constructMap[domain];
|
||||
|
||||
forAll(map, i)
|
||||
{
|
||||
newField[map[i]] = subField[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
OPstream::waitRequests();
|
||||
IPstream::waitRequests();
|
||||
|
||||
field.transfer(newField);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorIn("mapDistribute::distribute(..)")
|
||||
<< "Unknown communication schedule " << commsType
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -37,7 +37,7 @@ namespace Foam
|
||||
defineTypeNameAndDebug(coupledPolyPatch, 0);
|
||||
}
|
||||
|
||||
Foam::scalar Foam::coupledPolyPatch::matchTol_ = 1E-3;
|
||||
Foam::scalar Foam::coupledPolyPatch::matchTol = 1E-3;
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
||||
@ -83,7 +83,7 @@ void Foam::coupledPolyPatch::writeOBJ
|
||||
void Foam::coupledPolyPatch::writeOBJ
|
||||
(
|
||||
const fileName& fName,
|
||||
const faceList& faces,
|
||||
const UList<face>& faces,
|
||||
const pointField& points
|
||||
)
|
||||
{
|
||||
@ -118,7 +118,7 @@ void Foam::coupledPolyPatch::writeOBJ
|
||||
|
||||
Foam::pointField Foam::coupledPolyPatch::calcFaceCentres
|
||||
(
|
||||
const faceList& faces,
|
||||
const UList<face>& faces,
|
||||
const pointField& points
|
||||
)
|
||||
{
|
||||
@ -135,7 +135,7 @@ Foam::pointField Foam::coupledPolyPatch::calcFaceCentres
|
||||
|
||||
Foam::pointField Foam::coupledPolyPatch::getAnchorPoints
|
||||
(
|
||||
const faceList& faces,
|
||||
const UList<face>& faces,
|
||||
const pointField& points
|
||||
)
|
||||
{
|
||||
@ -189,7 +189,7 @@ Foam::label Foam::coupledPolyPatch::whichPatch
|
||||
|
||||
Foam::scalarField Foam::coupledPolyPatch::calcFaceTol
|
||||
(
|
||||
const faceList& faces,
|
||||
const UList<face>& faces,
|
||||
const pointField& points,
|
||||
const pointField& faceCentres
|
||||
)
|
||||
@ -203,13 +203,13 @@ Foam::scalarField Foam::coupledPolyPatch::calcFaceTol
|
||||
|
||||
const face& f = faces[faceI];
|
||||
|
||||
scalar maxLen = -GREAT;
|
||||
scalar maxLenSqr = -GREAT;
|
||||
|
||||
forAll(f, fp)
|
||||
{
|
||||
maxLen = max(maxLen, mag(points[f[fp]] - cc));
|
||||
maxLenSqr = max(maxLenSqr, magSqr(points[f[fp]] - cc));
|
||||
}
|
||||
tols[faceI] = matchTol_ * maxLen;
|
||||
tols[faceI] = matchTol * Foam::sqrt(maxLenSqr);
|
||||
}
|
||||
return tols;
|
||||
}
|
||||
@ -249,71 +249,32 @@ Foam::label Foam::coupledPolyPatch::getRotation
|
||||
}
|
||||
|
||||
|
||||
void Foam::coupledPolyPatch::calcTransformTensors
|
||||
(
|
||||
const vector& Cf,
|
||||
const vector& Cr,
|
||||
const vector& nf,
|
||||
const vector& nr
|
||||
) const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "coupledPolyPatch::calcTransformTensors : " << name() << endl
|
||||
<< " nf:" << nf << nl
|
||||
<< " nr:" << nr << nl
|
||||
<< " mag(nf&nr):" << mag(nf & nr) << nl
|
||||
<< " Cf:" << Cf << nl
|
||||
<< " Cr:" << Cr << endl;
|
||||
}
|
||||
|
||||
if (mag(nf & nr) < 1 - SMALL)
|
||||
{
|
||||
separation_.setSize(0);
|
||||
|
||||
forwardT_ = tensorField(1, rotationTensor(-nr, nf));
|
||||
reverseT_ = tensorField(1, rotationTensor(nf, -nr));
|
||||
}
|
||||
else
|
||||
{
|
||||
forwardT_.setSize(0);
|
||||
reverseT_.setSize(0);
|
||||
|
||||
vector separation = (nf & (Cr - Cf))*nf;
|
||||
|
||||
if (mag(separation) > SMALL)
|
||||
{
|
||||
separation_ = vectorField(1, separation);
|
||||
}
|
||||
else
|
||||
{
|
||||
separation_.setSize(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< " separation_:" << separation_ << nl
|
||||
<< " forwardT size:" << forwardT_.size() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::coupledPolyPatch::calcTransformTensors
|
||||
(
|
||||
const vectorField& Cf,
|
||||
const vectorField& Cr,
|
||||
const vectorField& nf,
|
||||
const vectorField& nr
|
||||
const vectorField& nr,
|
||||
const scalarField& smallDist,
|
||||
const scalar absTol
|
||||
) const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "coupledPolyPatch::calcTransformTensors : " << name() << endl
|
||||
<< " size:" << size() << nl
|
||||
<< " (half)size:" << Cf.size() << nl
|
||||
<< " absTol:" << absTol << nl
|
||||
<< " sum(mag(nf & nr)):" << sum(mag(nf & nr)) << endl;
|
||||
}
|
||||
|
||||
// Tolerance calculation.
|
||||
// - normal calculation: assume absTol is the absolute error in a
|
||||
// single normal/transformation calculation. Consists both of numerical
|
||||
// precision (on the order of SMALL and of writing precision
|
||||
// (from e.g. decomposition)
|
||||
// Then the overall error of summing the normals is sqrt(size())*absTol
|
||||
// - separation calculation: pass in from the outside an allowable error.
|
||||
|
||||
if (size() == 0)
|
||||
{
|
||||
// Dummy geometry.
|
||||
@ -321,39 +282,104 @@ void Foam::coupledPolyPatch::calcTransformTensors
|
||||
forwardT_ = I;
|
||||
reverseT_ = I;
|
||||
}
|
||||
else if (sum(mag(nf & nr)) < size() - 1E-12)
|
||||
{
|
||||
separation_.setSize(0);
|
||||
|
||||
forwardT_.setSize(size());
|
||||
reverseT_.setSize(size());
|
||||
|
||||
forAll (forwardT_, facei)
|
||||
{
|
||||
forwardT_[facei] = rotationTensor(-nr[facei], nf[facei]);
|
||||
reverseT_[facei] = rotationTensor(nf[facei], -nr[facei]);
|
||||
}
|
||||
|
||||
if (sum(mag(forwardT_ - forwardT_[0])) < 1E-12)
|
||||
{
|
||||
forwardT_.setSize(1);
|
||||
reverseT_.setSize(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forwardT_.setSize(0);
|
||||
reverseT_.setSize(0);
|
||||
scalar error = absTol*Foam::sqrt(1.0*Cf.size());
|
||||
|
||||
separation_ = (nf&(Cr - Cf))*nf;
|
||||
|
||||
if (sum(mag(separation_))/size() < 1E-12)
|
||||
if (debug)
|
||||
{
|
||||
separation_.setSize(0);
|
||||
Pout<< " error:" << error << endl;
|
||||
}
|
||||
else if (sum(mag(separation_ - separation_[0]))/size() < 1E-12)
|
||||
|
||||
if (sum(mag(nf & nr)) < Cf.size()-error)
|
||||
{
|
||||
separation_.setSize(1);
|
||||
// Rotation, no separation
|
||||
|
||||
separation_.setSize(0);
|
||||
|
||||
forwardT_.setSize(Cf.size());
|
||||
reverseT_.setSize(Cf.size());
|
||||
|
||||
forAll (forwardT_, facei)
|
||||
{
|
||||
forwardT_[facei] = rotationTensor(-nr[facei], nf[facei]);
|
||||
reverseT_[facei] = rotationTensor(nf[facei], -nr[facei]);
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< " sum(mag(forwardT_ - forwardT_[0])):"
|
||||
<< sum(mag(forwardT_ - forwardT_[0]))
|
||||
<< endl;
|
||||
}
|
||||
|
||||
if (sum(mag(forwardT_ - forwardT_[0])) < error)
|
||||
{
|
||||
forwardT_.setSize(1);
|
||||
reverseT_.setSize(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forwardT_.setSize(0);
|
||||
reverseT_.setSize(0);
|
||||
|
||||
separation_ = (nf&(Cr - Cf))*nf;
|
||||
|
||||
// Three situations:
|
||||
// - separation is zero. No separation.
|
||||
// - separation is same. Single separation vector.
|
||||
// - separation differs per face. Separation vectorField.
|
||||
|
||||
// Check for different separation per face
|
||||
bool sameSeparation = true;
|
||||
|
||||
forAll(separation_, facei)
|
||||
{
|
||||
scalar smallSqr = sqr(smallDist[facei]);
|
||||
|
||||
if (magSqr(separation_[facei] - separation_[0]) > smallSqr)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< " separation " << separation_[facei]
|
||||
<< " at " << facei
|
||||
<< " differs from separation[0] " << separation_[0]
|
||||
<< " by more than local tolerance "
|
||||
<< smallDist[facei]
|
||||
<< ". Assuming non-uniform separation." << endl;
|
||||
}
|
||||
sameSeparation = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sameSeparation)
|
||||
{
|
||||
// Check for zero separation (at 0 so everywhere)
|
||||
if (magSqr(separation_[0]) < sqr(smallDist[0]))
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< " separation " << mag(separation_[0])
|
||||
<< " less than local tolerance " << smallDist[0]
|
||||
<< ". Assuming zero separation." << endl;
|
||||
}
|
||||
|
||||
separation_.setSize(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< " separation " << mag(separation_[0])
|
||||
<< " more than local tolerance " << smallDist[0]
|
||||
<< ". Assuming uniform separation." << endl;
|
||||
}
|
||||
|
||||
separation_.setSize(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ License
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::coupledPolyPatch
|
||||
coupledPolyPatch
|
||||
|
||||
Description
|
||||
coupledPolyPatch is an abstract base class for patches that couple regions
|
||||
@ -64,34 +64,29 @@ class coupledPolyPatch
|
||||
//- Neighbour-cell transformation tensor
|
||||
mutable tensorField reverseT_;
|
||||
|
||||
public:
|
||||
|
||||
// Private static data
|
||||
// Static data members
|
||||
|
||||
//- Relative tolerance (for geometric matching). Is factor of
|
||||
// maximum edge length per face.
|
||||
static scalar matchTol_;
|
||||
//- Relative tolerance (for geometric matching).
|
||||
static scalar matchTol;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Calculate the uniform transformation tensors
|
||||
void calcTransformTensors
|
||||
(
|
||||
const vector& Cf,
|
||||
const vector& Cr,
|
||||
const vector& nf,
|
||||
const vector& nr
|
||||
) const;
|
||||
|
||||
//- Calculate the transformation tensors
|
||||
// smallDist : matching distance per face
|
||||
// absTol : absolute error in normal
|
||||
void calcTransformTensors
|
||||
(
|
||||
const vectorField& Cf,
|
||||
const vectorField& Cr,
|
||||
const vectorField& nf,
|
||||
const vectorField& nr
|
||||
const vectorField& nr,
|
||||
const scalarField& smallDist,
|
||||
const scalar absTol = matchTol
|
||||
) const;
|
||||
|
||||
//- Initialise the calculation of the patch geometry
|
||||
@ -123,7 +118,7 @@ protected:
|
||||
static void writeOBJ
|
||||
(
|
||||
const fileName&,
|
||||
const faceList&,
|
||||
const UList<face>&,
|
||||
const pointField&
|
||||
);
|
||||
|
||||
@ -137,10 +132,18 @@ protected:
|
||||
);
|
||||
|
||||
//- Calculate face centres
|
||||
static pointField calcFaceCentres(const faceList&, const pointField&);
|
||||
static pointField calcFaceCentres
|
||||
(
|
||||
const UList<face>&,
|
||||
const pointField&
|
||||
);
|
||||
|
||||
//- Get f[0] for all faces
|
||||
static pointField getAnchorPoints(const faceList&, const pointField&);
|
||||
static pointField getAnchorPoints
|
||||
(
|
||||
const UList<face>&,
|
||||
const pointField&
|
||||
);
|
||||
|
||||
//- Is face (in old face labels) in current patch?
|
||||
bool inPatch
|
||||
@ -161,7 +164,7 @@ protected:
|
||||
// from face centre to any of the face vertices.
|
||||
static scalarField calcFaceTol
|
||||
(
|
||||
const faceList& faces,
|
||||
const UList<face>& faces,
|
||||
const pointField& points,
|
||||
const pointField& faceCentres
|
||||
);
|
||||
|
||||
@ -33,6 +33,7 @@ License
|
||||
#include "patchZones.H"
|
||||
#include "matchPoints.H"
|
||||
#include "EdgeMap.H"
|
||||
#include "Time.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
@ -51,23 +52,108 @@ void Foam::cyclicPolyPatch::calcTransforms()
|
||||
{
|
||||
if (size() > 0)
|
||||
{
|
||||
const pointField& points = this->points();
|
||||
primitivePatch half0
|
||||
(
|
||||
SubList<face>
|
||||
(
|
||||
*this,
|
||||
size()/2
|
||||
),
|
||||
points()
|
||||
);
|
||||
pointField half0Ctrs(calcFaceCentres(half0, half0.points()));
|
||||
scalarField half0Tols(calcFaceTol(half0, half0.points(), half0Ctrs));
|
||||
|
||||
const face& f0 = static_cast<const faceList&>(*this)[0];
|
||||
const face& fn2 = static_cast<const faceList&>(*this)[size()/2];
|
||||
primitivePatch half1
|
||||
(
|
||||
SubList<face>
|
||||
(
|
||||
*this,
|
||||
size()/2,
|
||||
size()/2
|
||||
),
|
||||
points()
|
||||
);
|
||||
pointField half1Ctrs(calcFaceCentres(half1, half1.points()));
|
||||
|
||||
vector nf0 = f0.normal(points);
|
||||
nf0 /= mag(nf0);
|
||||
// Dump halves
|
||||
if (debug)
|
||||
{
|
||||
fileName casePath(boundaryMesh().mesh().time().path());
|
||||
|
||||
vector nfn2 = fn2.normal(points);
|
||||
nfn2 /= mag(nfn2);
|
||||
fileName nm0(casePath/name()+"_half0_faces.obj");
|
||||
Pout<< "cyclicPolyPatch::calcTransforms : Writing half0"
|
||||
<< " faces to OBJ file " << nm0 << endl;
|
||||
writeOBJ(nm0, half0, half0.points());
|
||||
|
||||
fileName nm1(casePath/name()+"_half1_faces.obj");
|
||||
Pout<< "cyclicPolyPatch::calcTransforms : Writing half1"
|
||||
<< " faces to OBJ file " << nm1 << endl;
|
||||
writeOBJ(nm1, half1, half1.points());
|
||||
}
|
||||
|
||||
vectorField half0Normals(half0.size());
|
||||
vectorField half1Normals(half1.size());
|
||||
|
||||
for (label facei = 0; facei < size()/2; facei++)
|
||||
{
|
||||
half0Normals[facei] = operator[](facei).normal(points());
|
||||
label nbrFacei = facei+size()/2;
|
||||
half1Normals[facei] = operator[](nbrFacei).normal(points());
|
||||
|
||||
scalar magSf = mag(half0Normals[facei]);
|
||||
scalar nbrMagSf = mag(half1Normals[facei]);
|
||||
scalar avSf = (magSf + nbrMagSf)/2.0;
|
||||
|
||||
if (magSf < ROOTVSMALL && nbrMagSf < ROOTVSMALL)
|
||||
{
|
||||
// Undetermined normal. Use dummy normal to force separation
|
||||
// check. (note use of sqrt(VSMALL) since that is how mag
|
||||
// scales)
|
||||
half0Normals[facei] = point(1, 0, 0);
|
||||
half1Normals[facei] = half0Normals[facei];
|
||||
}
|
||||
else if (mag(magSf - nbrMagSf)/avSf > coupledPolyPatch::matchTol)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"cyclicPolyPatch::calcTransforms()"
|
||||
) << "face " << facei << " area does not match neighbour "
|
||||
<< nbrFacei << " by "
|
||||
<< 100*mag(magSf - nbrMagSf)/avSf
|
||||
<< "% -- possible face ordering problem." << endl
|
||||
<< "patch:" << name()
|
||||
<< " my area:" << magSf
|
||||
<< " neighbour area:" << nbrMagSf
|
||||
<< " matching tolerance:" << coupledPolyPatch::matchTol
|
||||
<< endl
|
||||
<< "Mesh face:" << start()+facei
|
||||
<< " vertices:"
|
||||
<< IndirectList<point>(points(), operator[](facei))()
|
||||
<< endl
|
||||
<< "Neighbour face:" << start()+nbrFacei
|
||||
<< " vertices:"
|
||||
<< IndirectList<point>(points(), operator[](nbrFacei))()
|
||||
<< endl
|
||||
<< "Rerun with cyclic debug flag set"
|
||||
<< " for more information." << exit(FatalError);
|
||||
}
|
||||
else
|
||||
{
|
||||
half0Normals[facei] /= magSf;
|
||||
half1Normals[facei] /= nbrMagSf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Calculate transformation tensors
|
||||
calcTransformTensors
|
||||
(
|
||||
f0.centre(points),
|
||||
fn2.centre(points),
|
||||
nf0,
|
||||
nfn2
|
||||
half0Ctrs,
|
||||
half1Ctrs,
|
||||
half0Normals,
|
||||
half1Normals,
|
||||
half0Tols
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -86,14 +172,7 @@ bool Foam::cyclicPolyPatch::getGeometricHalves
|
||||
) const
|
||||
{
|
||||
// Calculate normals
|
||||
vectorField normals(pp.size());
|
||||
|
||||
forAll(pp, faceI)
|
||||
{
|
||||
normals[faceI] = pp[faceI].normal(pp.points());
|
||||
}
|
||||
normals /= mag(normals) + VSMALL;
|
||||
|
||||
const vectorField& faceNormals = pp.faceNormals();
|
||||
|
||||
// Find edges with sharp angles.
|
||||
boolList regionEdge(pp.nEdges(), false);
|
||||
@ -106,9 +185,11 @@ bool Foam::cyclicPolyPatch::getGeometricHalves
|
||||
{
|
||||
const labelList& eFaces = edgeFaces[edgeI];
|
||||
|
||||
// Check manifold edges for sharp angle.
|
||||
// (Non-manifold already handled by patchZones)
|
||||
if (eFaces.size() == 2)
|
||||
{
|
||||
if ((normals[eFaces[0]] & normals[eFaces[1]])< featureCos_)
|
||||
if ((faceNormals[eFaces[0]] & faceNormals[eFaces[1]])< featureCos_)
|
||||
{
|
||||
regionEdge[edgeI] = true;
|
||||
|
||||
@ -138,7 +219,11 @@ bool Foam::cyclicPolyPatch::getGeometricHalves
|
||||
|
||||
for (label zoneI = 0; zoneI < ppZones.nZones(); zoneI++)
|
||||
{
|
||||
OFstream stream(name()+"_zone_"+Foam::name(zoneI)+".obj");
|
||||
OFstream stream
|
||||
(
|
||||
boundaryMesh().mesh().time().path()
|
||||
/name()+"_zone_"+Foam::name(zoneI)+".obj"
|
||||
);
|
||||
Pout<< "cyclicPolyPatch::getGeometricHalves : Writing zone "
|
||||
<< zoneI << " face centres to OBJ file " << stream.name()
|
||||
<< endl;
|
||||
@ -152,9 +237,6 @@ bool Foam::cyclicPolyPatch::getGeometricHalves
|
||||
|
||||
nZoneFaces[zoneI] = zoneFaces.size();
|
||||
}
|
||||
|
||||
Pout<< "cyclicPolyPatch::getGeometricHalves : Number of faces per zone:"
|
||||
<< nZoneFaces << endl;
|
||||
}
|
||||
|
||||
|
||||
@ -168,7 +250,7 @@ bool Foam::cyclicPolyPatch::getGeometricHalves
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "cyclicPolyPatch::getGeometricHalves :"
|
||||
<< " falling back to normal comparison" << endl;
|
||||
<< " falling back to face-normal comparison" << endl;
|
||||
}
|
||||
label n0Faces = 0;
|
||||
half0ToPatch.setSize(pp.size());
|
||||
@ -177,9 +259,9 @@ bool Foam::cyclicPolyPatch::getGeometricHalves
|
||||
half1ToPatch.setSize(pp.size());
|
||||
|
||||
// Compare to face 0 normal.
|
||||
forAll(normals, faceI)
|
||||
forAll(faceNormals, faceI)
|
||||
{
|
||||
if ((normals[faceI] & normals[0]) > 0)
|
||||
if ((faceNormals[faceI] & faceNormals[0]) > 0)
|
||||
{
|
||||
half0ToPatch[n0Faces++] = faceI;
|
||||
}
|
||||
@ -191,21 +273,26 @@ bool Foam::cyclicPolyPatch::getGeometricHalves
|
||||
half0ToPatch.setSize(n0Faces);
|
||||
half1ToPatch.setSize(n1Faces);
|
||||
|
||||
Pout<< "cyclicPolyPatch::getGeometricHalves :"
|
||||
<< " Number of faces per zone:("
|
||||
<< n0Faces << ' ' << n1Faces << ')' << endl;
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "cyclicPolyPatch::getGeometricHalves :"
|
||||
<< " Number of faces per zone:("
|
||||
<< n0Faces << ' ' << n1Faces << ')' << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (half0ToPatch.size() != half1ToPatch.size())
|
||||
{
|
||||
fileName casePath(boundaryMesh().mesh().time().path());
|
||||
|
||||
// Dump halves
|
||||
{
|
||||
fileName nm0(name()+"_half0_faces.obj");
|
||||
fileName nm0(casePath/name()+"_half0_faces.obj");
|
||||
Pout<< "cyclicPolyPatch::getGeometricHalves : Writing half0"
|
||||
<< " faces to OBJ file " << nm0 << endl;
|
||||
writeOBJ(nm0, IndirectList<face>(pp, half0ToPatch)(), pp.points());
|
||||
|
||||
fileName nm1(name()+"_half1_faces.obj");
|
||||
fileName nm1(casePath/name()+"_half1_faces.obj");
|
||||
Pout<< "cyclicPolyPatch::getGeometricHalves : Writing half1"
|
||||
<< " faces to OBJ file " << nm1 << endl;
|
||||
writeOBJ(nm1, IndirectList<face>(pp, half1ToPatch)(), pp.points());
|
||||
@ -213,7 +300,7 @@ bool Foam::cyclicPolyPatch::getGeometricHalves
|
||||
|
||||
// Dump face centres
|
||||
{
|
||||
OFstream str0(name()+"_half0.obj");
|
||||
OFstream str0(casePath/name()+"_half0.obj");
|
||||
Pout<< "cyclicPolyPatch::getGeometricHalves : Writing half0"
|
||||
<< " face centres to OBJ file " << str0.name() << endl;
|
||||
|
||||
@ -222,7 +309,7 @@ bool Foam::cyclicPolyPatch::getGeometricHalves
|
||||
writeOBJ(str0, pp[half0ToPatch[i]].centre(pp.points()));
|
||||
}
|
||||
|
||||
OFstream str1(name()+"_half1.obj");
|
||||
OFstream str1(casePath/name()+"_half1.obj");
|
||||
Pout<< "cyclicPolyPatch::getGeometricHalves : Writing half1"
|
||||
<< " face centres to OBJ file " << str1.name() << endl;
|
||||
forAll(half1ToPatch, i)
|
||||
@ -235,15 +322,13 @@ bool Foam::cyclicPolyPatch::getGeometricHalves
|
||||
(
|
||||
"cyclicPolyPatch::getGeometricHalves"
|
||||
"(const primitivePatch&, labelList&, labelList&) const"
|
||||
) << " patch:" << name() << " : "
|
||||
<< "Patch " << name() << " gets decomposed in two zones of"
|
||||
) << "Patch " << name() << " gets decomposed in two zones of"
|
||||
<< "inequal size: " << half0ToPatch.size()
|
||||
<< " and " << half1ToPatch.size() << endl
|
||||
<< "This means that the patch is either not two separate regions"
|
||||
<< " or one region where the angle between the different regions"
|
||||
<< " is not sufficiently sharp." << endl
|
||||
<< "Please use topological matching or adapt the featureCos"
|
||||
<< " setting" << endl
|
||||
<< "Please adapt the featureCos setting." << endl
|
||||
<< "Continuing with incorrect face ordering from now on!" << endl;
|
||||
|
||||
return false;
|
||||
@ -278,7 +363,7 @@ void Foam::cyclicPolyPatch::getCentresAndAnchors
|
||||
anchors0 = getAnchorPoints(half0Faces, pp.points());
|
||||
half1Ctrs = calcFaceCentres(half1Faces, pp.points());
|
||||
|
||||
if (mag(n0 & n1) < 1-SMALL)
|
||||
if (mag(n0 & n1) < 1-coupledPolyPatch::matchTol)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
@ -288,6 +373,7 @@ void Foam::cyclicPolyPatch::getCentresAndAnchors
|
||||
|
||||
// Rotation (around origin)
|
||||
const tensor reverseT(rotationTensor(n0, -n1));
|
||||
const tensor forwardT(rotationTensor(-n1, n0));
|
||||
|
||||
// Rotation
|
||||
forAll(half0Ctrs, faceI)
|
||||
@ -393,7 +479,7 @@ bool Foam::cyclicPolyPatch::matchAnchors
|
||||
SeriousErrorIn
|
||||
(
|
||||
"cyclicPolyPatch::matchAnchors(..)"
|
||||
) << " patch:" << name() << " : "
|
||||
) << "Patch:" << name() << " : "
|
||||
<< "Cannot find point on face " << f
|
||||
<< " with vertices:"
|
||||
<< IndirectList<point>(pp.points(), f)()
|
||||
@ -583,16 +669,20 @@ const Foam::edgeList& Foam::cyclicPolyPatch::coupledPoints() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Writing file coupledPoints.obj with coordinates of "
|
||||
<< "coupled points" << endl;
|
||||
|
||||
OFstream str("coupledPoints.obj");
|
||||
OFstream str
|
||||
(
|
||||
boundaryMesh().mesh().time().path()
|
||||
/"coupledPoints.obj"
|
||||
);
|
||||
label vertI = 0;
|
||||
|
||||
Pout<< "Writing file " << str.name() << " with coordinates of "
|
||||
<< "coupled points" << endl;
|
||||
|
||||
forAll(connected, i)
|
||||
{
|
||||
const point& a = localPoints()[connected[i][0]];
|
||||
const point& b = localPoints()[connected[i][1]];
|
||||
const point& a = points()[meshPoints()[connected[i][0]]];
|
||||
const point& b = points()[meshPoints()[connected[i][1]]];
|
||||
|
||||
str<< "v " << a.x() << ' ' << a.y() << ' ' << a.z() << nl;
|
||||
str<< "v " << b.x() << ' ' << b.y() << ' ' << b.z() << nl;
|
||||
@ -601,6 +691,10 @@ const Foam::edgeList& Foam::cyclicPolyPatch::coupledPoints() const
|
||||
str<< "l " << vertI-1 << ' ' << vertI << nl;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any addressing calculated for the coupled edges calculation
|
||||
const_cast<primitivePatch&>(static_cast<const primitivePatch&>(*this))
|
||||
.clearOut();
|
||||
}
|
||||
return *coupledPointsPtr_;
|
||||
}
|
||||
@ -637,7 +731,15 @@ const Foam::edgeList& Foam::cyclicPolyPatch::coupledEdges() const
|
||||
|
||||
// Convert edge end points to corresponding points on halfB
|
||||
// side.
|
||||
edgeMap.insert(edge(aToB[e[0]], aToB[e[1]]), edgeI);
|
||||
Map<label>::const_iterator fnd0 = aToB.find(e[0]);
|
||||
if (fnd0 != aToB.end())
|
||||
{
|
||||
Map<label>::const_iterator fnd1 = aToB.find(e[1]);
|
||||
if (fnd1 != aToB.end())
|
||||
{
|
||||
edgeMap.insert(edge(fnd0(), fnd1()), edgeI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -693,12 +795,16 @@ const Foam::edgeList& Foam::cyclicPolyPatch::coupledEdges() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Writing file coupledEdges.obj with centres of "
|
||||
<< "coupled edges" << endl;
|
||||
|
||||
OFstream str("coupledEdges.obj");
|
||||
OFstream str
|
||||
(
|
||||
boundaryMesh().mesh().time().path()
|
||||
/"coupledEdges.obj"
|
||||
);
|
||||
label vertI = 0;
|
||||
|
||||
Pout<< "Writing file " << str.name() << " with centres of "
|
||||
<< "coupled edges" << endl;
|
||||
|
||||
forAll(coupledEdges, i)
|
||||
{
|
||||
const edge& e = coupledEdges[i];
|
||||
@ -713,6 +819,10 @@ const Foam::edgeList& Foam::cyclicPolyPatch::coupledEdges() const
|
||||
str<< "l " << vertI-1 << ' ' << vertI << nl;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any addressing calculated for the coupled edges calculation
|
||||
const_cast<primitivePatch&>(static_cast<const primitivePatch&>(*this))
|
||||
.clearOut();
|
||||
}
|
||||
return *coupledEdgesPtr_;
|
||||
}
|
||||
@ -848,7 +958,85 @@ bool Foam::cyclicPolyPatch::order
|
||||
}
|
||||
|
||||
|
||||
// 3. Automatic geometric ordering
|
||||
// 3. Baffles(coincident faces) converted into cyclics (e.g. jump)
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
if (!matchedAll)
|
||||
{
|
||||
label baffleI = 0;
|
||||
|
||||
forAll(*this, faceI)
|
||||
{
|
||||
const face& f = pp.localFaces()[faceI];
|
||||
const labelList& pFaces = pp.pointFaces()[f[0]];
|
||||
|
||||
label matchedFaceI = -1;
|
||||
|
||||
forAll(pFaces, i)
|
||||
{
|
||||
label otherFaceI = pFaces[i];
|
||||
|
||||
if (otherFaceI > faceI)
|
||||
{
|
||||
const face& otherF = pp.localFaces()[otherFaceI];
|
||||
|
||||
// Note: might pick up two similar oriented faces
|
||||
// (but that is illegal anyway)
|
||||
if (f == otherF)
|
||||
{
|
||||
matchedFaceI = otherFaceI;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchedFaceI != -1)
|
||||
{
|
||||
half0ToPatch[baffleI] = faceI;
|
||||
half1ToPatch[baffleI] = matchedFaceI;
|
||||
baffleI++;
|
||||
}
|
||||
}
|
||||
|
||||
if (baffleI == halfSize)
|
||||
{
|
||||
// And redo all matching
|
||||
half0Faces = IndirectList<face>(pp, half0ToPatch);
|
||||
half1Faces = IndirectList<face>(pp, half1ToPatch);
|
||||
|
||||
getCentresAndAnchors
|
||||
(
|
||||
pp,
|
||||
half0Faces,
|
||||
half1Faces,
|
||||
|
||||
half0Ctrs,
|
||||
half1Ctrs,
|
||||
anchors0,
|
||||
tols
|
||||
);
|
||||
|
||||
// Geometric match of face centre vectors
|
||||
matchedAll = matchPoints
|
||||
(
|
||||
half1Ctrs,
|
||||
half0Ctrs,
|
||||
tols,
|
||||
false,
|
||||
from1To0
|
||||
);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "cyclicPolyPatch::order : test if baffles:"
|
||||
<< matchedAll << endl;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 4. Automatic geometric ordering
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
if (!matchedAll)
|
||||
@ -896,7 +1084,7 @@ bool Foam::cyclicPolyPatch::order
|
||||
}
|
||||
|
||||
|
||||
if (debug)
|
||||
if (!matchedAll || debug)
|
||||
{
|
||||
// Dump halves
|
||||
fileName nm0(name()+"_half0_faces.obj");
|
||||
@ -909,12 +1097,18 @@ bool Foam::cyclicPolyPatch::order
|
||||
<< " faces to OBJ file " << nm1 << endl;
|
||||
writeOBJ(nm1, half1Faces, pp.points());
|
||||
|
||||
OFstream ccStr(name() + "_faceCentres.obj");
|
||||
OFstream ccStr
|
||||
(
|
||||
boundaryMesh().mesh().time().path()
|
||||
/name() + "_faceCentres.obj"
|
||||
);
|
||||
Pout<< "cyclicPolyPatch::order : "
|
||||
<< "Dumping newly found cyclic match as lines between"
|
||||
<< "Dumping currently found cyclic match as lines between"
|
||||
<< " corresponding face centres to file " << ccStr.name()
|
||||
<< endl;
|
||||
|
||||
// Recalculate untransformed face centres
|
||||
//pointField rawHalf0Ctrs = calcFaceCentres(half0Faces, pp.points());
|
||||
label vertI = 0;
|
||||
|
||||
forAll(half1Ctrs, i)
|
||||
@ -922,6 +1116,7 @@ bool Foam::cyclicPolyPatch::order
|
||||
if (from1To0[i] != -1)
|
||||
{
|
||||
// Write edge between c1 and c0
|
||||
//const point& c0 = rawHalf0Ctrs[from1To0[i]];
|
||||
const point& c0 = half0Ctrs[from1To0[i]];
|
||||
const point& c1 = half1Ctrs[i];
|
||||
writeOBJ(ccStr, c0, c1, vertI);
|
||||
@ -936,13 +1131,12 @@ bool Foam::cyclicPolyPatch::order
|
||||
(
|
||||
"cyclicPolyPatch::order"
|
||||
"(const primitivePatch&, labelList&, labelList&) const"
|
||||
) << " patch:" << name() << " : "
|
||||
) << "Patch:" << name() << " : "
|
||||
<< "Cannot match vectors to faces on both sides of patch" << endl
|
||||
<< "half0Ctrs[0]:" << half0Ctrs[0] << endl
|
||||
<< "half1Ctrs[0]:" << half1Ctrs[0] << endl
|
||||
<< "Please use topological matching or adapt the featureCos"
|
||||
<< " setting" << endl
|
||||
<< "Continuing with incorrect face ordering from now on!" << endl;
|
||||
<< " Perhaps your faces do not match?"
|
||||
<< " The obj files written contain the current match." << endl
|
||||
<< " Continuing with incorrect face ordering from now on!"
|
||||
<< endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -224,10 +224,12 @@ public:
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return connected points (in patch local point indexing)
|
||||
//- Return connected points (in patch local point indexing). Demand
|
||||
// driven calculation. Does primitivePatch::clearOut after calculation!
|
||||
const edgeList& coupledPoints() const;
|
||||
|
||||
//- Return connected edges (in patch local edge indexing)
|
||||
//- Return connected edges (in patch local edge indexing). Demand
|
||||
// driven calculation. Does primitivePatch::clearOut after calculation!
|
||||
const edgeList& coupledEdges() const;
|
||||
|
||||
|
||||
|
||||
@ -25,13 +25,15 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "processorPolyPatch.H"
|
||||
#include "polyBoundaryMesh.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "dictionary.H"
|
||||
#include "SubField.H"
|
||||
#include "demandDrivenData.H"
|
||||
#include "matchPoints.H"
|
||||
#include "OFstream.H"
|
||||
#include "polyMesh.H"
|
||||
#include "Time.H"
|
||||
#include "transformList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -169,26 +171,51 @@ void Foam::processorPolyPatch::calcGeometry()
|
||||
>> neighbFaceCellCentres_;
|
||||
}
|
||||
|
||||
scalarField magSf = mag(faceAreas());
|
||||
// My normals
|
||||
vectorField faceNormals(size());
|
||||
|
||||
forAll(magSf, facei)
|
||||
// Neighbour normals
|
||||
vectorField nbrFaceNormals(neighbFaceAreas_.size());
|
||||
|
||||
// Calculate normals from areas and check
|
||||
forAll(faceNormals, facei)
|
||||
{
|
||||
scalar nmagSf = mag(neighbFaceAreas_[facei]);
|
||||
scalar avSf = (magSf[facei] + nmagSf)/2.0;
|
||||
scalar magSf = mag(faceAreas()[facei]);
|
||||
scalar nbrMagSf = mag(neighbFaceAreas_[facei]);
|
||||
scalar avSf = (magSf + nbrMagSf)/2.0;
|
||||
|
||||
if (avSf > VSMALL && mag(magSf[facei] - nmagSf)/avSf > 1e-4)
|
||||
if (magSf < ROOTVSMALL && nbrMagSf < ROOTVSMALL)
|
||||
{
|
||||
// Undetermined normal. Use dummy normal to force separation
|
||||
// check. (note use of sqrt(VSMALL) since that is how mag
|
||||
// scales)
|
||||
faceNormals[facei] = point(1, 0, 0);
|
||||
nbrFaceNormals[facei] = faceNormals[facei];
|
||||
}
|
||||
else if (mag(magSf - nbrMagSf)/avSf > coupledPolyPatch::matchTol)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"processorPolyPatch::calcGeometry()"
|
||||
) << "face " << facei << " area does not match neighbour by "
|
||||
<< 100*mag(magSf[facei] - nmagSf)/avSf
|
||||
<< 100*mag(magSf - nbrMagSf)/avSf
|
||||
<< "% -- possible face ordering problem." << endl
|
||||
<< "patch:" << name() << " mesh face:" << start()+facei
|
||||
<< " face centre:" << faceCentres()[facei]
|
||||
<< " my area:" << magSf[facei]
|
||||
<< " neighbour area:" << nmagSf
|
||||
<< exit(FatalError);
|
||||
<< "patch:" << name()
|
||||
<< " my area:" << magSf
|
||||
<< " neighbour area:" << nbrMagSf
|
||||
<< " matching tolerance:" << coupledPolyPatch::matchTol
|
||||
<< endl
|
||||
<< "Mesh face:" << start()+facei
|
||||
<< " vertices:"
|
||||
<< IndirectList<point>(points(), operator[](facei))()
|
||||
<< endl
|
||||
<< "Rerun with processor debug flag set for"
|
||||
<< " more information." << exit(FatalError);
|
||||
}
|
||||
else
|
||||
{
|
||||
faceNormals[facei] = faceAreas()[facei]/magSf;
|
||||
nbrFaceNormals[facei] = neighbFaceAreas_[facei]/nbrMagSf;
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,8 +223,9 @@ void Foam::processorPolyPatch::calcGeometry()
|
||||
(
|
||||
faceCentres(),
|
||||
neighbFaceCentres_,
|
||||
faceNormals(),
|
||||
neighbFaceAreas_/(mag(neighbFaceAreas_)+VSMALL)
|
||||
faceNormals,
|
||||
nbrFaceNormals,
|
||||
calcFaceTol(*this, points(), faceCentres())
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -226,33 +254,49 @@ void Foam::processorPolyPatch::initUpdateMesh()
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
// Express all points as patch face and index in face.
|
||||
labelList patchFace(nPoints());
|
||||
labelList indexInFace(nPoints());
|
||||
labelList pointFace(nPoints());
|
||||
labelList pointIndex(nPoints());
|
||||
|
||||
for (label patchPointI = 0; patchPointI < nPoints(); patchPointI++)
|
||||
{
|
||||
label faceI = pointFaces()[patchPointI][0];
|
||||
|
||||
patchFace[patchPointI] = faceI;
|
||||
pointFace[patchPointI] = faceI;
|
||||
|
||||
const face& f = localFaces()[faceI];
|
||||
|
||||
indexInFace[patchPointI] = findIndex(f, patchPointI);
|
||||
pointIndex[patchPointI] = findIndex(f, patchPointI);
|
||||
}
|
||||
|
||||
// Express all edges as patch face and index in face.
|
||||
labelList edgeFace(nEdges());
|
||||
labelList edgeIndex(nEdges());
|
||||
|
||||
for (label patchEdgeI = 0; patchEdgeI < nEdges(); patchEdgeI++)
|
||||
{
|
||||
label faceI = edgeFaces()[patchEdgeI][0];
|
||||
|
||||
edgeFace[patchEdgeI] = faceI;
|
||||
|
||||
const labelList& fEdges = faceEdges()[faceI];
|
||||
|
||||
edgeIndex[patchEdgeI] = findIndex(fEdges, patchEdgeI);
|
||||
}
|
||||
|
||||
OPstream toNeighbProc
|
||||
(
|
||||
Pstream::blocking,
|
||||
neighbProcNo(),
|
||||
3*sizeof(label)
|
||||
+ 2*nPoints()*sizeof(label)
|
||||
+ nEdges()*sizeof(edge)
|
||||
8*sizeof(label) // four headers of labelList
|
||||
+ 2*nPoints()*sizeof(label) // two point-based labellists
|
||||
+ 2*nEdges()*sizeof(label) // two edge-based labelLists
|
||||
);
|
||||
|
||||
toNeighbProc
|
||||
<< patchFace
|
||||
<< indexInFace
|
||||
<< edges();
|
||||
<< pointFace
|
||||
<< pointIndex
|
||||
<< edgeFace
|
||||
<< edgeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,118 +308,96 @@ void Foam::processorPolyPatch::updateMesh()
|
||||
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
labelList nbrPatchFace(nPoints());
|
||||
labelList nbrIndexInFace(nPoints());
|
||||
edgeList nbrEdges(nEdges());
|
||||
labelList nbrPointFace;
|
||||
labelList nbrPointIndex;
|
||||
labelList nbrEdgeFace;
|
||||
labelList nbrEdgeIndex;
|
||||
|
||||
{
|
||||
// Note cannot predict exact size since edgeList not (yet) sent as
|
||||
// binary entity but as List of edges.
|
||||
// Note cannot predict exact size since opposite nPoints might
|
||||
// be different from one over here.
|
||||
IPstream fromNeighbProc(Pstream::blocking, neighbProcNo());
|
||||
|
||||
fromNeighbProc
|
||||
>> nbrPatchFace
|
||||
>> nbrIndexInFace
|
||||
>> nbrEdges;
|
||||
>> nbrPointFace
|
||||
>> nbrPointIndex
|
||||
>> nbrEdgeFace
|
||||
>> nbrEdgeIndex;
|
||||
}
|
||||
|
||||
if (nbrPatchFace.size() == nPoints() && nbrEdges.size() == nEdges())
|
||||
// Convert neighbour faces and indices into face back into
|
||||
// my edges and points.
|
||||
|
||||
// Convert points.
|
||||
// ~~~~~~~~~~~~~~~
|
||||
|
||||
neighbPointsPtr_ = new labelList(nPoints(), -1);
|
||||
labelList& neighbPoints = *neighbPointsPtr_;
|
||||
|
||||
forAll(nbrPointFace, nbrPointI)
|
||||
{
|
||||
// Convert neighbour edges and indices into face back into
|
||||
// my edges and points.
|
||||
neighbPointsPtr_ = new labelList(nPoints());
|
||||
labelList& neighbPoints = *neighbPointsPtr_;
|
||||
// Find face and index in face on this side.
|
||||
const face& f = localFaces()[nbrPointFace[nbrPointI]];
|
||||
label index = (f.size() - nbrPointIndex[nbrPointI]) % f.size();
|
||||
label patchPointI = f[index];
|
||||
|
||||
// Inverse of neighbPoints so from neighbour point to current point.
|
||||
labelList nbrToThis(nPoints(), -1);
|
||||
|
||||
forAll(nbrPatchFace, nbrPointI)
|
||||
if (neighbPoints[patchPointI] == -1)
|
||||
{
|
||||
// Find face and index in face on this side.
|
||||
const face& f = localFaces()[nbrPatchFace[nbrPointI]];
|
||||
label index = (f.size() - nbrIndexInFace[nbrPointI]) % f.size();
|
||||
label patchPointI = f[index];
|
||||
|
||||
// First reference of point
|
||||
neighbPoints[patchPointI] = nbrPointI;
|
||||
nbrToThis[nbrPointI] = patchPointI;
|
||||
}
|
||||
|
||||
// Convert edges.
|
||||
neighbEdgesPtr_ = new labelList(nEdges());
|
||||
labelList& neighbEdges = *neighbEdgesPtr_;
|
||||
|
||||
forAll(nbrEdges, nbrEdgeI)
|
||||
else if (neighbPoints[patchPointI] >= 0)
|
||||
{
|
||||
const edge& nbrEdge = nbrEdges[nbrEdgeI];
|
||||
|
||||
// Get edge in local point numbering
|
||||
edge e(nbrToThis[nbrEdge[0]], nbrToThis[nbrEdge[1]]);
|
||||
|
||||
// Find the edge.
|
||||
const labelList& pEdges = pointEdges()[e[0]];
|
||||
|
||||
label edgeI = -1;
|
||||
|
||||
forAll(pEdges, i)
|
||||
{
|
||||
if (edges()[pEdges[i]] == e)
|
||||
{
|
||||
edgeI = pEdges[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (edgeI == -1)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
WarningIn("processorPolyPatch::updateMesh()")
|
||||
<< "Patch:" << name()
|
||||
<< "Cannot find patch edge with vertices " << e
|
||||
<< " coords:"
|
||||
<< localPoints()[e[0]]<< localPoints()[e[1]]
|
||||
<< " on patch " << name() << nl
|
||||
<< "Can only find edges "
|
||||
<< IndirectList<edge>(edges(), pEdges)()
|
||||
<< " connected to first vertex" << nl
|
||||
<< "Either your mesh is incorrect or this patch"
|
||||
<< " was constructed from part of a cyclic patch."
|
||||
<< nl
|
||||
<< "Not calculating edge neighbour addressing."
|
||||
<< endl;
|
||||
}
|
||||
deleteDemandDrivenData(neighbEdgesPtr_);
|
||||
break;
|
||||
}
|
||||
|
||||
neighbEdges[edgeI] = nbrEdgeI;
|
||||
// Point already visited. Mark as duplicate.
|
||||
neighbPoints[patchPointI] = -2;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// Reset all duplicate entries to -1.
|
||||
forAll(neighbPoints, patchPointI)
|
||||
{
|
||||
// Differing number of points or edges. Probably patch includes
|
||||
// part of a cyclic.
|
||||
neighbPointsPtr_ = NULL;
|
||||
neighbEdgesPtr_ = NULL;
|
||||
|
||||
if (debug)
|
||||
if (neighbPoints[patchPointI] == -2)
|
||||
{
|
||||
{
|
||||
fileName nm(name()+"_faces.obj");
|
||||
Pout<< "processorPolyPatch::order : Writing my " << size()
|
||||
<< " faces to OBJ file " << nm << endl;
|
||||
writeOBJ(nm, *this, points());
|
||||
}
|
||||
|
||||
WarningIn("processorPolyPatch::updateMesh()")
|
||||
<< "Patch:" << name()
|
||||
<< "my nPoints:" << nPoints()
|
||||
<< " edges:" << nEdges()
|
||||
<< " nbrPatchFace:" << nbrPatchFace.size()
|
||||
<< " nbrEdges:" << nbrEdges.size()
|
||||
<< endl;
|
||||
neighbPoints[patchPointI] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert edges.
|
||||
// ~~~~~~~~~~~~~~
|
||||
|
||||
neighbEdgesPtr_ = new labelList(nEdges(), -1);
|
||||
labelList& neighbEdges = *neighbEdgesPtr_;
|
||||
|
||||
forAll(nbrEdgeFace, nbrEdgeI)
|
||||
{
|
||||
// Find face and index in face on this side.
|
||||
const labelList& f = faceEdges()[nbrEdgeFace[nbrEdgeI]];
|
||||
label index = (f.size() - nbrEdgeIndex[nbrEdgeI] - 1) % f.size();
|
||||
label patchEdgeI = f[index];
|
||||
|
||||
if (neighbEdges[patchEdgeI] == -1)
|
||||
{
|
||||
// First reference of edge
|
||||
neighbEdges[patchEdgeI] = nbrEdgeI;
|
||||
}
|
||||
else if (neighbEdges[patchEdgeI] >= 0)
|
||||
{
|
||||
// Edge already visited. Mark as duplicate.
|
||||
neighbEdges[patchEdgeI] = -2;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset all duplicate entries to -1.
|
||||
forAll(neighbEdges, patchEdgeI)
|
||||
{
|
||||
if (neighbEdges[patchEdgeI] == -2)
|
||||
{
|
||||
neighbEdges[patchEdgeI] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any addressing used for shared points/edges calculation
|
||||
primitivePatch::clearOut();
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,18 +406,8 @@ const Foam::labelList& Foam::processorPolyPatch::neighbPoints() const
|
||||
{
|
||||
if (!neighbPointsPtr_)
|
||||
{
|
||||
// Was probably created from cyclic patch and hence the
|
||||
// number of edges or points might differ on both
|
||||
// sides of the processor patch since one side might have
|
||||
// it merged with another bit of geometry
|
||||
|
||||
FatalErrorIn("processorPolyPatch::neighbPoints() const")
|
||||
<< "No extended addressing calculated for patch " << name()
|
||||
<< nl
|
||||
<< "This can happen if the number of points or edges on both"
|
||||
<< " sides of the two coupled patches differ." << nl
|
||||
<< "This happens if the processorPatch was constructed from"
|
||||
<< " part of a cyclic patch."
|
||||
<< abort(FatalError);
|
||||
}
|
||||
return *neighbPointsPtr_;
|
||||
@ -406,18 +418,8 @@ const Foam::labelList& Foam::processorPolyPatch::neighbEdges() const
|
||||
{
|
||||
if (!neighbEdgesPtr_)
|
||||
{
|
||||
// Was probably created from cyclic patch and hence the
|
||||
// number of edges or points might differ on both
|
||||
// sides of the processor patch since one side might have
|
||||
// it merged with another bit of geometry
|
||||
|
||||
FatalErrorIn("processorPolyPatch::neighbEdges() const")
|
||||
<< "No extended addressing calculated for patch " << name()
|
||||
<< nl
|
||||
<< "This can happen if the number of points or edges on both"
|
||||
<< " sides of the two coupled patches differ." << nl
|
||||
<< "This happens if the processorPatch was constructed from"
|
||||
<< " part of a cyclic patch."
|
||||
<< abort(FatalError);
|
||||
}
|
||||
return *neighbEdgesPtr_;
|
||||
@ -433,7 +435,11 @@ void Foam::processorPolyPatch::initOrder(const primitivePatch& pp) const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
fileName nm(name()+"_faces.obj");
|
||||
fileName nm
|
||||
(
|
||||
boundaryMesh().mesh().time().path()
|
||||
/name()+"_faces.obj"
|
||||
);
|
||||
Pout<< "processorPolyPatch::order : Writing my " << pp.size()
|
||||
<< " faces to OBJ file " << nm << endl;
|
||||
writeOBJ(nm, pp, pp.points());
|
||||
@ -441,7 +447,11 @@ void Foam::processorPolyPatch::initOrder(const primitivePatch& pp) const
|
||||
// Calculate my face centres
|
||||
pointField ctrs(calcFaceCentres(pp, pp.points()));
|
||||
|
||||
OFstream localStr(name() + "_localFaceCentres.obj");
|
||||
OFstream localStr
|
||||
(
|
||||
boundaryMesh().mesh().time().path()
|
||||
/name() + "_localFaceCentres.obj"
|
||||
);
|
||||
Pout<< "processorPolyPatch::order : "
|
||||
<< "Dumping " << ctrs.size()
|
||||
<< " local faceCentres to " << localStr.name() << endl;
|
||||
@ -454,28 +464,15 @@ void Foam::processorPolyPatch::initOrder(const primitivePatch& pp) const
|
||||
|
||||
const bool isMaster = Pstream::myProcNo() < neighbProcNo();
|
||||
|
||||
// Check (on old patch!) for weirdness.
|
||||
if (separated() || !parallel())
|
||||
{
|
||||
WarningIn
|
||||
(
|
||||
"processorPolyPatch::initOrder(const primitivePatch&) const"
|
||||
) << "in patch:" << name() << " : "
|
||||
<< "using geometric matching on this processor patch might fail"
|
||||
<< " since it has 'separated' faces or is not 'parallel'"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
if (isMaster)
|
||||
{
|
||||
pointField ctrs(calcFaceCentres(pp, pp.points()));
|
||||
|
||||
pointField anchorPoints(getAnchorPoints(pp, pp.points()));
|
||||
pointField anchors(getAnchorPoints(pp, pp.points()));
|
||||
|
||||
// Now send all info over to the neighbour
|
||||
OPstream toNeighbour(Pstream::blocking, neighbProcNo());
|
||||
toNeighbour << ctrs << anchorPoints;
|
||||
toNeighbour << ctrs << anchors;
|
||||
}
|
||||
}
|
||||
|
||||
@ -518,12 +515,12 @@ bool Foam::processorPolyPatch::order
|
||||
else
|
||||
{
|
||||
vectorField masterCtrs;
|
||||
vectorField masterAnchorPoints;
|
||||
vectorField masterAnchors;
|
||||
|
||||
// Receive data from neighbour
|
||||
{
|
||||
IPstream fromNeighbour(Pstream::blocking, neighbProcNo());
|
||||
fromNeighbour >> masterCtrs >> masterAnchorPoints;
|
||||
fromNeighbour >> masterCtrs >> masterAnchors;
|
||||
}
|
||||
|
||||
// Calculate my face centres
|
||||
@ -535,7 +532,11 @@ bool Foam::processorPolyPatch::order
|
||||
if (debug || masterCtrs.size() != pp.size())
|
||||
{
|
||||
{
|
||||
OFstream nbrStr(name() + "_nbrFaceCentres.obj");
|
||||
OFstream nbrStr
|
||||
(
|
||||
boundaryMesh().mesh().time().path()
|
||||
/name() + "_nbrFaceCentres.obj"
|
||||
);
|
||||
Pout<< "processorPolyPatch::order : "
|
||||
<< "Dumping neighbour faceCentres to " << nbrStr.name()
|
||||
<< endl;
|
||||
@ -561,14 +562,108 @@ bool Foam::processorPolyPatch::order
|
||||
}
|
||||
|
||||
// Geometric match of face centre vectors
|
||||
bool matchedAll = matchPoints(ctrs, masterCtrs, tols, true, faceMap);
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
if (debug)
|
||||
// 1. Try existing ordering and transformation
|
||||
bool matchedAll = false;
|
||||
|
||||
if
|
||||
(
|
||||
separated()
|
||||
&& (separation().size() == 1 || separation().size() == pp.size())
|
||||
)
|
||||
{
|
||||
OFstream ccStr(name() + "_faceCentresConnections.obj");
|
||||
vectorField transformedCtrs;
|
||||
|
||||
Pout<< "processorPolyPatch::order : "
|
||||
<< "Dumping newly found match as lines between"
|
||||
const vectorField& v = separation();
|
||||
|
||||
if (v.size() == 1)
|
||||
{
|
||||
transformedCtrs = masterCtrs-v[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
transformedCtrs = masterCtrs-v;
|
||||
}
|
||||
matchedAll = matchPoints
|
||||
(
|
||||
ctrs,
|
||||
transformedCtrs,
|
||||
tols,
|
||||
true,
|
||||
faceMap
|
||||
);
|
||||
|
||||
if (matchedAll)
|
||||
{
|
||||
// Use transformed centers from now on
|
||||
masterCtrs = transformedCtrs;
|
||||
|
||||
// Transform anchors
|
||||
if (v.size() == 1)
|
||||
{
|
||||
masterAnchors -= v[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
masterAnchors -= v;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if
|
||||
(
|
||||
!parallel()
|
||||
&& (forwardT().size() == 1 || forwardT().size() == pp.size())
|
||||
)
|
||||
{
|
||||
vectorField transformedCtrs = masterCtrs;
|
||||
transformList(forwardT(), transformedCtrs);
|
||||
matchedAll = matchPoints
|
||||
(
|
||||
ctrs,
|
||||
transformedCtrs,
|
||||
tols,
|
||||
true,
|
||||
faceMap
|
||||
);
|
||||
|
||||
if (matchedAll)
|
||||
{
|
||||
// Use transformed centers from now on
|
||||
masterCtrs = transformedCtrs;
|
||||
|
||||
// Transform anchors
|
||||
transformList(forwardT(), masterAnchors);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 2. Try zero separation automatic matching
|
||||
if (!matchedAll)
|
||||
{
|
||||
matchedAll = matchPoints(ctrs, masterCtrs, tols, true, faceMap);
|
||||
}
|
||||
|
||||
if (!matchedAll || debug)
|
||||
{
|
||||
// Dump faces
|
||||
fileName str
|
||||
(
|
||||
boundaryMesh().mesh().time().path()
|
||||
/name()/name()+"_faces.obj"
|
||||
);
|
||||
Pout<< "processorPolyPatch::order :"
|
||||
<< " Writing faces to OBJ file " << str.name() << endl;
|
||||
writeOBJ(str, pp, pp.points());
|
||||
|
||||
OFstream ccStr
|
||||
(
|
||||
boundaryMesh().mesh().time().path()
|
||||
/name() + "_faceCentresConnections.obj"
|
||||
);
|
||||
|
||||
Pout<< "processorPolyPatch::order :"
|
||||
<< " Dumping newly found match as lines between"
|
||||
<< " corresponding face centres to OBJ file " << ccStr.name()
|
||||
<< endl;
|
||||
|
||||
@ -596,12 +691,12 @@ bool Foam::processorPolyPatch::order
|
||||
) << "in patch:" << name() << " : "
|
||||
<< "Cannot match vectors to faces on both sides of patch"
|
||||
<< endl
|
||||
<< "masterCtrs[0]:" << masterCtrs[0] << endl
|
||||
<< "ctrs[0]:" << ctrs[0] << endl
|
||||
<< "Please check your topology changes or maybe you have"
|
||||
<< " masterCtrs[0]:" << masterCtrs[0] << endl
|
||||
<< " ctrs[0]:" << ctrs[0] << endl
|
||||
<< " Please check your topology changes or maybe you have"
|
||||
<< " multiple separated (from cyclics) processor patches"
|
||||
<< endl
|
||||
<< "Continuing with incorrect face ordering from now on!"
|
||||
<< " Continuing with incorrect face ordering from now on!"
|
||||
<< endl;
|
||||
|
||||
return false;
|
||||
@ -616,7 +711,7 @@ bool Foam::processorPolyPatch::order
|
||||
|
||||
label newFaceI = faceMap[oldFaceI];
|
||||
|
||||
const point& wantedAnchor = masterAnchorPoints[newFaceI];
|
||||
const point& wantedAnchor = masterAnchors[newFaceI];
|
||||
|
||||
rotation[newFaceI] = getRotation
|
||||
(
|
||||
@ -632,10 +727,10 @@ bool Foam::processorPolyPatch::order
|
||||
(
|
||||
"processorPolyPatch::order(const primitivePatch&"
|
||||
", labelList&, labelList&) const"
|
||||
) << "in patch:" << name()
|
||||
) << "in patch " << name()
|
||||
<< " : "
|
||||
<< "Cannot find point on face " << pp[oldFaceI]
|
||||
<< " with vertices:"
|
||||
<< " with vertices "
|
||||
<< IndirectList<point>(pp.points(), pp[oldFaceI])()
|
||||
<< " that matches point " << wantedAnchor
|
||||
<< " when matching the halves of processor patch " << name()
|
||||
|
||||
@ -219,18 +219,6 @@ public:
|
||||
return !owner();
|
||||
}
|
||||
|
||||
//- Force calculation of transformation tensors
|
||||
void calcTransformTensors
|
||||
(
|
||||
const vectorField& Cf,
|
||||
const vectorField& Cr,
|
||||
const vectorField& nf,
|
||||
const vectorField& nr
|
||||
) const
|
||||
{
|
||||
coupledPolyPatch::calcTransformTensors(Cf, Cr, nf, nr);
|
||||
}
|
||||
|
||||
//- Return processor-neighbbour patch face centres
|
||||
const vectorField& neighbFaceCentres() const
|
||||
{
|
||||
@ -249,12 +237,14 @@ public:
|
||||
return neighbFaceCellCentres_;
|
||||
}
|
||||
|
||||
//- Return neighbour point labels. This is for my local point the
|
||||
// corresponding local point on the other side.
|
||||
//- Return neighbour point labels. This is for my local point (-1 or)
|
||||
// the corresponding local point on the other side. It is -1 if
|
||||
// there are multiple corresponding points on this or the other side
|
||||
// (can happen for cyclics being converted into proc patches)
|
||||
const labelList& neighbPoints() const;
|
||||
|
||||
//- Return neighbour edge labels. This is for my local edge the
|
||||
// corresponding local edge on the other side.
|
||||
//- Return neighbour edge labels. This is for my local edge (-1 or) the
|
||||
// corresponding local edge on the other side. See above for -1 cause.
|
||||
const labelList& neighbEdges() const;
|
||||
|
||||
|
||||
|
||||
@ -157,7 +157,10 @@ void Foam::syncTools::syncPointMap
|
||||
|
||||
if (iter != pointValues.end())
|
||||
{
|
||||
patchInfo.insert(nbrPts[i], iter());
|
||||
if (nbrPts[i] >= 0)
|
||||
{
|
||||
patchInfo.insert(nbrPts[i], iter());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,7 +190,7 @@ void Foam::syncTools::syncPointMap
|
||||
if (!procPatch.parallel())
|
||||
{
|
||||
hasTransformation = true;
|
||||
transformList(procPatch.reverseT(), nbrPatchInfo);
|
||||
transformList(procPatch.forwardT(), nbrPatchInfo);
|
||||
}
|
||||
else if (applySeparation && procPatch.separated())
|
||||
{
|
||||
@ -227,8 +230,8 @@ void Foam::syncTools::syncPointMap
|
||||
refCast<const cyclicPolyPatch>(patches[patchI]);
|
||||
checkTransform(cycPatch, applySeparation);
|
||||
|
||||
const labelList& meshPts = cycPatch.meshPoints();
|
||||
const edgeList& coupledPoints = cycPatch.coupledPoints();
|
||||
const labelList& meshPts = cycPatch.meshPoints();
|
||||
|
||||
// Extract local values. Create map from nbrPoint to value.
|
||||
Map<T> half0Values(meshPts.size() / 20);
|
||||
@ -258,7 +261,8 @@ void Foam::syncTools::syncPointMap
|
||||
if (!cycPatch.parallel())
|
||||
{
|
||||
hasTransformation = true;
|
||||
transformList(cycPatch.forwardT(), half0Values);
|
||||
transformList(cycPatch.reverseT(), half0Values);
|
||||
transformList(cycPatch.forwardT(), half1Values);
|
||||
}
|
||||
else if (applySeparation && cycPatch.separated())
|
||||
{
|
||||
@ -315,138 +319,135 @@ void Foam::syncTools::syncPointMap
|
||||
{
|
||||
WarningIn
|
||||
(
|
||||
"syncTools<class T, class CombineOp>::syncPointList"
|
||||
"(const polyMesh&, UList<T>&, const CombineOp&, const T&"
|
||||
"syncTools<class T, class CombineOp>::syncPointMap"
|
||||
"(const polyMesh&, Map<T>&, const CombineOp&"
|
||||
", const bool)"
|
||||
) << "There are decomposed cyclics in this mesh with"
|
||||
<< " transformations." << endl
|
||||
<< "This is not supported. The result will be incorrect"
|
||||
<< endl;
|
||||
}
|
||||
else
|
||||
// meshPoint per local index
|
||||
const labelList& sharedPtLabels = pd.sharedPointLabels();
|
||||
// global shared index per local index
|
||||
const labelList& sharedPtAddr = pd.sharedPointAddr();
|
||||
|
||||
// Values on shared points. Keyed on global shared index.
|
||||
Map<T> sharedPointValues(sharedPtAddr.size());
|
||||
|
||||
|
||||
// Fill my entries in the shared points
|
||||
forAll(sharedPtLabels, i)
|
||||
{
|
||||
// meshPoint per local index
|
||||
const labelList& sharedPtLabels = pd.sharedPointLabels();
|
||||
// global shared index per local index
|
||||
const labelList& sharedPtAddr = pd.sharedPointAddr();
|
||||
label meshPointI = sharedPtLabels[i];
|
||||
|
||||
// Values on shared points. Keyed on global shared index.
|
||||
Map<T> sharedPointValues(sharedPtAddr.size());
|
||||
typename Map<T>::const_iterator fnd =
|
||||
pointValues.find(meshPointI);
|
||||
|
||||
|
||||
// Fill my entries in the shared points
|
||||
forAll(sharedPtLabels, i)
|
||||
if (fnd != pointValues.end())
|
||||
{
|
||||
label meshPointI = sharedPtLabels[i];
|
||||
|
||||
typename Map<T>::const_iterator fnd =
|
||||
pointValues.find(meshPointI);
|
||||
|
||||
if (fnd != pointValues.end())
|
||||
{
|
||||
combine
|
||||
(
|
||||
sharedPointValues,
|
||||
cop,
|
||||
sharedPtAddr[i], // index
|
||||
fnd() // value
|
||||
);
|
||||
}
|
||||
combine
|
||||
(
|
||||
sharedPointValues,
|
||||
cop,
|
||||
sharedPtAddr[i], // index
|
||||
fnd() // value
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Reduce on master.
|
||||
// Reduce on master.
|
||||
|
||||
if (Pstream::parRun())
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
if (Pstream::master())
|
||||
// Receive the edges using shared points from the slave.
|
||||
for
|
||||
(
|
||||
int slave=Pstream::firstSlave();
|
||||
slave<=Pstream::lastSlave();
|
||||
slave++
|
||||
)
|
||||
{
|
||||
// Receive the edges using shared points from the slave.
|
||||
for
|
||||
(
|
||||
int slave=Pstream::firstSlave();
|
||||
slave<=Pstream::lastSlave();
|
||||
slave++
|
||||
)
|
||||
{
|
||||
IPstream fromSlave(Pstream::blocking, slave);
|
||||
Map<T> nbrValues(fromSlave);
|
||||
IPstream fromSlave(Pstream::blocking, slave);
|
||||
Map<T> nbrValues(fromSlave);
|
||||
|
||||
// Merge neighbouring values with my values
|
||||
forAllConstIter(typename Map<T>, nbrValues, iter)
|
||||
{
|
||||
combine
|
||||
(
|
||||
sharedPointValues,
|
||||
cop,
|
||||
iter.key(), // edge
|
||||
iter() // value
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Send back
|
||||
for
|
||||
(
|
||||
int slave=Pstream::firstSlave();
|
||||
slave<=Pstream::lastSlave();
|
||||
slave++
|
||||
)
|
||||
// Merge neighbouring values with my values
|
||||
forAllConstIter(typename Map<T>, nbrValues, iter)
|
||||
{
|
||||
OPstream toSlave(Pstream::blocking, slave);
|
||||
toSlave << sharedPointValues;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send to master
|
||||
{
|
||||
OPstream toMaster
|
||||
combine
|
||||
(
|
||||
Pstream::blocking,
|
||||
Pstream::masterNo()
|
||||
sharedPointValues,
|
||||
cop,
|
||||
iter.key(), // edge
|
||||
iter() // value
|
||||
);
|
||||
toMaster << sharedPointValues;
|
||||
}
|
||||
// Receive merged values
|
||||
{
|
||||
IPstream fromMaster
|
||||
(
|
||||
Pstream::blocking,
|
||||
Pstream::masterNo()
|
||||
);
|
||||
fromMaster >> sharedPointValues;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Merge sharedPointValues (keyed on sharedPointAddr) into
|
||||
// pointValues (keyed on mesh points).
|
||||
|
||||
// Map from global shared index to meshpoint
|
||||
Map<label> sharedToMeshPoint(2*sharedPtAddr.size());
|
||||
forAll(sharedPtAddr, i)
|
||||
{
|
||||
sharedToMeshPoint.insert(sharedPtAddr[i], sharedPtLabels[i]);
|
||||
}
|
||||
|
||||
forAllConstIter(Map<label>, sharedToMeshPoint, iter)
|
||||
{
|
||||
// Do I have a value for my shared point
|
||||
typename Map<T>::const_iterator sharedFnd =
|
||||
sharedPointValues.find(iter.key());
|
||||
|
||||
if (sharedFnd != sharedPointValues.end())
|
||||
// Send back
|
||||
for
|
||||
(
|
||||
int slave=Pstream::firstSlave();
|
||||
slave<=Pstream::lastSlave();
|
||||
slave++
|
||||
)
|
||||
{
|
||||
combine
|
||||
(
|
||||
pointValues,
|
||||
cop,
|
||||
iter(), // index
|
||||
sharedFnd() // value
|
||||
);
|
||||
OPstream toSlave(Pstream::blocking, slave);
|
||||
toSlave << sharedPointValues;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send to master
|
||||
{
|
||||
OPstream toMaster
|
||||
(
|
||||
Pstream::blocking,
|
||||
Pstream::masterNo()
|
||||
);
|
||||
toMaster << sharedPointValues;
|
||||
}
|
||||
// Receive merged values
|
||||
{
|
||||
IPstream fromMaster
|
||||
(
|
||||
Pstream::blocking,
|
||||
Pstream::masterNo()
|
||||
);
|
||||
fromMaster >> sharedPointValues;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Merge sharedPointValues (keyed on sharedPointAddr) into
|
||||
// pointValues (keyed on mesh points).
|
||||
|
||||
// Map from global shared index to meshpoint
|
||||
Map<label> sharedToMeshPoint(2*sharedPtAddr.size());
|
||||
forAll(sharedPtAddr, i)
|
||||
{
|
||||
sharedToMeshPoint.insert(sharedPtAddr[i], sharedPtLabels[i]);
|
||||
}
|
||||
|
||||
forAllConstIter(Map<label>, sharedToMeshPoint, iter)
|
||||
{
|
||||
// Do I have a value for my shared point
|
||||
typename Map<T>::const_iterator sharedFnd =
|
||||
sharedPointValues.find(iter.key());
|
||||
|
||||
if (sharedFnd != sharedPointValues.end())
|
||||
{
|
||||
combine
|
||||
(
|
||||
pointValues,
|
||||
cop,
|
||||
iter(), // index
|
||||
sharedFnd() // value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -510,7 +511,11 @@ void Foam::syncTools::syncEdgeMap
|
||||
if (iter != edgeValues.end())
|
||||
{
|
||||
const edge nbrEdge(nbrPts[e[0]], nbrPts[e[1]]);
|
||||
patchInfo.insert(nbrEdge, iter());
|
||||
|
||||
if (nbrEdge[0] >= 0 && nbrEdge[1] >= 0)
|
||||
{
|
||||
patchInfo.insert(nbrEdge, iter());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -541,7 +546,7 @@ void Foam::syncTools::syncEdgeMap
|
||||
|
||||
if (!procPatch.parallel())
|
||||
{
|
||||
transformList(procPatch.reverseT(), nbrPatchInfo);
|
||||
transformList(procPatch.forwardT(), nbrPatchInfo);
|
||||
}
|
||||
else if (applySeparation && procPatch.separated())
|
||||
{
|
||||
@ -584,8 +589,8 @@ void Foam::syncTools::syncEdgeMap
|
||||
refCast<const cyclicPolyPatch>(patches[patchI]);
|
||||
checkTransform(cycPatch, applySeparation);
|
||||
|
||||
const labelList& meshPts = cycPatch.meshPoints();
|
||||
const edgeList& coupledEdges = cycPatch.coupledEdges();
|
||||
const labelList& meshPts = cycPatch.meshPoints();
|
||||
const edgeList& edges = cycPatch.edges();
|
||||
|
||||
// Extract local values. Create map from nbrPoint to value.
|
||||
@ -627,7 +632,8 @@ void Foam::syncTools::syncEdgeMap
|
||||
|
||||
if (!cycPatch.parallel())
|
||||
{
|
||||
transformList(cycPatch.forwardT(), half0Values);
|
||||
transformList(cycPatch.reverseT(), half0Values);
|
||||
transformList(cycPatch.forwardT(), half1Values);
|
||||
}
|
||||
else if (applySeparation && cycPatch.separated())
|
||||
{
|
||||
@ -888,31 +894,22 @@ void Foam::syncTools::syncPointList
|
||||
refCast<const processorPolyPatch>(patches[patchI]);
|
||||
|
||||
// Get data per patchPoint in neighbouring point numbers.
|
||||
List<T> patchInfo(procPatch.nPoints());
|
||||
List<T> patchInfo(procPatch.nPoints(), nullValue);
|
||||
|
||||
const labelList& meshPts = procPatch.meshPoints();
|
||||
const labelList& nbrPts = procPatch.neighbPoints();
|
||||
|
||||
forAll(meshPts, pointI)
|
||||
forAll(nbrPts, pointI)
|
||||
{
|
||||
patchInfo[nbrPts[pointI]] = pointValues[meshPts[pointI]];
|
||||
label nbrPointI = nbrPts[pointI];
|
||||
if (nbrPointI >= 0 && nbrPointI < patchInfo.size())
|
||||
{
|
||||
patchInfo[nbrPointI] = pointValues[meshPts[pointI]];
|
||||
}
|
||||
}
|
||||
|
||||
if (contiguous<T>())
|
||||
{
|
||||
OPstream::write
|
||||
(
|
||||
Pstream::blocking,
|
||||
procPatch.neighbProcNo(),
|
||||
reinterpret_cast<const char*>(patchInfo.begin()),
|
||||
patchInfo.byteSize()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
|
||||
toNbr << patchInfo;
|
||||
}
|
||||
OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
|
||||
toNbr << patchInfo;
|
||||
}
|
||||
}
|
||||
|
||||
@ -932,19 +929,9 @@ void Foam::syncTools::syncPointList
|
||||
checkTransform(procPatch, applySeparation);
|
||||
|
||||
List<T> nbrPatchInfo(procPatch.nPoints());
|
||||
|
||||
if (contiguous<T>())
|
||||
{
|
||||
IPstream::read
|
||||
(
|
||||
Pstream::blocking,
|
||||
procPatch.neighbProcNo(),
|
||||
reinterpret_cast<char*>(nbrPatchInfo.begin()),
|
||||
nbrPatchInfo.byteSize()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We do not know the number of points on the other side
|
||||
// so cannot use Pstream::read.
|
||||
IPstream fromNbr
|
||||
(
|
||||
Pstream::blocking,
|
||||
@ -952,11 +939,23 @@ void Foam::syncTools::syncPointList
|
||||
);
|
||||
fromNbr >> nbrPatchInfo;
|
||||
}
|
||||
// Null any value which is not on neighbouring processor
|
||||
label nbrSize = nbrPatchInfo.size();
|
||||
nbrPatchInfo.setSize(procPatch.nPoints());
|
||||
for
|
||||
(
|
||||
label i = nbrSize;
|
||||
i < procPatch.nPoints();
|
||||
i++
|
||||
)
|
||||
{
|
||||
nbrPatchInfo[i] = nullValue;
|
||||
}
|
||||
|
||||
if (!procPatch.parallel())
|
||||
{
|
||||
hasTransformation = true;
|
||||
transformList(procPatch.reverseT(), nbrPatchInfo);
|
||||
transformList(procPatch.forwardT(), nbrPatchInfo);
|
||||
}
|
||||
else if (applySeparation && procPatch.separated())
|
||||
{
|
||||
@ -985,8 +984,8 @@ void Foam::syncTools::syncPointList
|
||||
|
||||
checkTransform(cycPatch, applySeparation);
|
||||
|
||||
const labelList& meshPts = cycPatch.meshPoints();
|
||||
const edgeList& coupledPoints = cycPatch.coupledPoints();
|
||||
const labelList& meshPts = cycPatch.meshPoints();
|
||||
|
||||
List<T> half0Values(coupledPoints.size());
|
||||
List<T> half1Values(coupledPoints.size());
|
||||
@ -1005,12 +1004,12 @@ void Foam::syncTools::syncPointList
|
||||
if (!cycPatch.parallel())
|
||||
{
|
||||
hasTransformation = true;
|
||||
transformList(cycPatch.forwardT(), half0Values);
|
||||
transformList(cycPatch.reverseT(), half0Values);
|
||||
transformList(cycPatch.forwardT(), half1Values);
|
||||
}
|
||||
else if (applySeparation && cycPatch.separated())
|
||||
{
|
||||
hasTransformation = true;
|
||||
|
||||
const vectorField& v = cycPatch.coupledPolyPatch::separation();
|
||||
separateList(v, half0Values);
|
||||
separateList(-v, half1Values);
|
||||
@ -1050,30 +1049,28 @@ void Foam::syncTools::syncPointList
|
||||
<< "This is not supported. The result will be incorrect"
|
||||
<< endl;
|
||||
}
|
||||
else
|
||||
|
||||
|
||||
// Values on shared points.
|
||||
List<T> sharedPts(pd.nGlobalPoints(), nullValue);
|
||||
|
||||
forAll(pd.sharedPointLabels(), i)
|
||||
{
|
||||
// Values on shared points.
|
||||
List<T> sharedPts(pd.nGlobalPoints(), nullValue);
|
||||
label meshPointI = pd.sharedPointLabels()[i];
|
||||
// Fill my entries in the shared points
|
||||
sharedPts[pd.sharedPointAddr()[i]] = pointValues[meshPointI];
|
||||
}
|
||||
|
||||
forAll(pd.sharedPointLabels(), i)
|
||||
{
|
||||
label meshPointI = pd.sharedPointLabels()[i];
|
||||
// Combine on master.
|
||||
Pstream::listCombineGather(sharedPts, cop);
|
||||
Pstream::listCombineScatter(sharedPts);
|
||||
|
||||
// Fill my entries in the shared points
|
||||
sharedPts[pd.sharedPointAddr()[i]] = pointValues[meshPointI];
|
||||
}
|
||||
|
||||
// Combine on master.
|
||||
Pstream::listCombineGather(sharedPts, cop);
|
||||
Pstream::listCombineScatter(sharedPts);
|
||||
|
||||
// Now we will all have the same information. Merge it back with
|
||||
// my local information.
|
||||
forAll(pd.sharedPointLabels(), i)
|
||||
{
|
||||
label meshPointI = pd.sharedPointLabels()[i];
|
||||
pointValues[meshPointI] = sharedPts[pd.sharedPointAddr()[i]];
|
||||
}
|
||||
// Now we will all have the same information. Merge it back with
|
||||
// my local information.
|
||||
forAll(pd.sharedPointLabels(), i)
|
||||
{
|
||||
label meshPointI = pd.sharedPointLabels()[i];
|
||||
pointValues[meshPointI] = sharedPts[pd.sharedPointAddr()[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1177,33 +1174,24 @@ void Foam::syncTools::syncEdgeList
|
||||
const processorPolyPatch& procPatch =
|
||||
refCast<const processorPolyPatch>(patches[patchI]);
|
||||
|
||||
// Get region per patch edge in neighbouring edge numbers.
|
||||
List<T> patchInfo(procPatch.nEdges());
|
||||
|
||||
const labelList& meshEdges = procPatch.meshEdges();
|
||||
const labelList& neighbEdges = procPatch.neighbEdges();
|
||||
|
||||
forAll(meshEdges, edgeI)
|
||||
// Get region per patch edge in neighbouring edge numbers.
|
||||
List<T> patchInfo(procPatch.nEdges(), nullValue);
|
||||
|
||||
forAll(neighbEdges, edgeI)
|
||||
{
|
||||
patchInfo[neighbEdges[edgeI]] =
|
||||
edgeValues[meshEdges[edgeI]];
|
||||
label nbrEdgeI = neighbEdges[edgeI];
|
||||
|
||||
if (nbrEdgeI >= 0 && nbrEdgeI < patchInfo.size())
|
||||
{
|
||||
patchInfo[nbrEdgeI] = edgeValues[meshEdges[edgeI]];
|
||||
}
|
||||
}
|
||||
|
||||
if (contiguous<T>())
|
||||
{
|
||||
OPstream::write
|
||||
(
|
||||
Pstream::blocking,
|
||||
procPatch.neighbProcNo(),
|
||||
reinterpret_cast<const char*>(patchInfo.begin()),
|
||||
patchInfo.byteSize()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
|
||||
toNbr << patchInfo;
|
||||
}
|
||||
OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
|
||||
toNbr << patchInfo;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1228,17 +1216,6 @@ void Foam::syncTools::syncEdgeList
|
||||
// neighbouring patch edge.
|
||||
List<T> nbrPatchInfo(procPatch.nEdges());
|
||||
|
||||
if (contiguous<T>())
|
||||
{
|
||||
IPstream::read
|
||||
(
|
||||
Pstream::blocking,
|
||||
procPatch.neighbProcNo(),
|
||||
reinterpret_cast<char*>(nbrPatchInfo.begin()),
|
||||
nbrPatchInfo.byteSize()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
IPstream fromNeighb
|
||||
(
|
||||
@ -1247,11 +1224,24 @@ void Foam::syncTools::syncEdgeList
|
||||
);
|
||||
fromNeighb >> nbrPatchInfo;
|
||||
}
|
||||
// Null any value which is not on neighbouring processor
|
||||
label nbrSize = nbrPatchInfo.size();
|
||||
nbrPatchInfo.setSize(procPatch.nEdges());
|
||||
for
|
||||
(
|
||||
label i = nbrSize;
|
||||
i < procPatch.nEdges();
|
||||
i++
|
||||
)
|
||||
{
|
||||
nbrPatchInfo[i] = nullValue;
|
||||
}
|
||||
|
||||
|
||||
if (!procPatch.parallel())
|
||||
{
|
||||
hasTransformation = true;
|
||||
transformList(procPatch.reverseT(), nbrPatchInfo);
|
||||
transformList(procPatch.forwardT(), nbrPatchInfo);
|
||||
}
|
||||
else if (applySeparation && procPatch.separated())
|
||||
{
|
||||
@ -1299,7 +1289,8 @@ void Foam::syncTools::syncEdgeList
|
||||
if (!cycPatch.parallel())
|
||||
{
|
||||
hasTransformation = true;
|
||||
transformList(cycPatch.forwardT(), half0Values);
|
||||
transformList(cycPatch.reverseT(), half0Values);
|
||||
transformList(cycPatch.forwardT(), half1Values);
|
||||
}
|
||||
else if (applySeparation && cycPatch.separated())
|
||||
{
|
||||
@ -1344,30 +1335,28 @@ void Foam::syncTools::syncEdgeList
|
||||
<< "This is not supported. The result will be incorrect"
|
||||
<< endl;
|
||||
}
|
||||
else
|
||||
|
||||
// Values on shared edges.
|
||||
List<T> sharedPts(pd.nGlobalEdges(), nullValue);
|
||||
|
||||
forAll(pd.sharedEdgeLabels(), i)
|
||||
{
|
||||
// Values on shared edges.
|
||||
List<T> sharedPts(pd.nGlobalEdges(), nullValue);
|
||||
label meshEdgeI = pd.sharedEdgeLabels()[i];
|
||||
|
||||
forAll(pd.sharedEdgeLabels(), i)
|
||||
{
|
||||
label meshEdgeI = pd.sharedEdgeLabels()[i];
|
||||
// Fill my entries in the shared edges
|
||||
sharedPts[pd.sharedEdgeAddr()[i]] = edgeValues[meshEdgeI];
|
||||
}
|
||||
|
||||
// Fill my entries in the shared edges
|
||||
sharedPts[pd.sharedEdgeAddr()[i]] = edgeValues[meshEdgeI];
|
||||
}
|
||||
// Combine on master.
|
||||
Pstream::listCombineGather(sharedPts, cop);
|
||||
Pstream::listCombineScatter(sharedPts);
|
||||
|
||||
// Combine on master.
|
||||
Pstream::listCombineGather(sharedPts, cop);
|
||||
Pstream::listCombineScatter(sharedPts);
|
||||
|
||||
// Now we will all have the same information. Merge it back with
|
||||
// my local information.
|
||||
forAll(pd.sharedEdgeLabels(), i)
|
||||
{
|
||||
label meshEdgeI = pd.sharedEdgeLabels()[i];
|
||||
edgeValues[meshEdgeI] = sharedPts[pd.sharedEdgeAddr()[i]];
|
||||
}
|
||||
// Now we will all have the same information. Merge it back with
|
||||
// my local information.
|
||||
forAll(pd.sharedEdgeLabels(), i)
|
||||
{
|
||||
label meshEdgeI = pd.sharedEdgeLabels()[i];
|
||||
edgeValues[meshEdgeI] = sharedPts[pd.sharedEdgeAddr()[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1478,11 +1467,11 @@ void Foam::syncTools::syncBoundaryFaceList
|
||||
|
||||
if (!procPatch.parallel())
|
||||
{
|
||||
transformList(procPatch.reverseT(), nbrPatchInfo);
|
||||
transformList(procPatch.forwardT(), nbrPatchInfo);
|
||||
}
|
||||
else if (applySeparation && procPatch.separated())
|
||||
{
|
||||
separateList(procPatch.separation(), nbrPatchInfo);
|
||||
separateList(-procPatch.separation(), nbrPatchInfo);
|
||||
}
|
||||
|
||||
|
||||
@ -1514,8 +1503,8 @@ void Foam::syncTools::syncBoundaryFaceList
|
||||
|
||||
if (!cycPatch.parallel())
|
||||
{
|
||||
transformList(cycPatch.reverseT(), half1Values);
|
||||
transformList(cycPatch.forwardT(), half0Values);
|
||||
transformList(cycPatch.reverseT(), half0Values);
|
||||
transformList(cycPatch.forwardT(), half1Values);
|
||||
}
|
||||
else if (applySeparation && cycPatch.separated())
|
||||
{
|
||||
|
||||
@ -24,7 +24,6 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//#include "PrimitivePatch.H"
|
||||
#include "Map.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
@ -35,11 +34,17 @@ namespace Foam
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct from components
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
PrimitivePatch<Face, FaceList, PointField>::PrimitivePatch
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::PrimitivePatch
|
||||
(
|
||||
const FaceList<Face>& faces,
|
||||
const pointField& points
|
||||
const Field<PointType>& points
|
||||
)
|
||||
:
|
||||
FaceList<Face>(faces),
|
||||
@ -64,10 +69,16 @@ PrimitivePatch<Face, FaceList, PointField>::PrimitivePatch
|
||||
|
||||
|
||||
// Construct as copy
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
PrimitivePatch<Face, FaceList, PointField>::PrimitivePatch
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::PrimitivePatch
|
||||
(
|
||||
const PrimitivePatch<Face, FaceList, PointField>& pp
|
||||
const PrimitivePatch<Face, FaceList, PointField, PointType>& pp
|
||||
)
|
||||
:
|
||||
PrimitivePatchName(),
|
||||
@ -94,8 +105,14 @@ PrimitivePatch<Face, FaceList, PointField>::PrimitivePatch
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
PrimitivePatch<Face, FaceList, PointField>::~PrimitivePatch()
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::~PrimitivePatch()
|
||||
{
|
||||
clearOut();
|
||||
}
|
||||
@ -104,12 +121,22 @@ PrimitivePatch<Face, FaceList, PointField>::~PrimitivePatch()
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
// Correct patch after moving points
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::movePoints(const pointField&)
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::movePoints
|
||||
(
|
||||
const Field<PointType>&
|
||||
)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::movePoints() : "
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "movePoints() : "
|
||||
<< "recalculating PrimitivePatch geometry following mesh motion"
|
||||
<< endl;
|
||||
}
|
||||
@ -118,9 +145,15 @@ void PrimitivePatch<Face, FaceList, PointField>::movePoints(const pointField&)
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const edgeList&
|
||||
PrimitivePatch<Face, FaceList, PointField>::edges() const
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::edges() const
|
||||
{
|
||||
if (!edgesPtr_)
|
||||
{
|
||||
@ -131,8 +164,15 @@ PrimitivePatch<Face, FaceList, PointField>::edges() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
label PrimitivePatch<Face, FaceList, PointField>::nInternalEdges() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
label PrimitivePatch<Face, FaceList, PointField, PointType>::nInternalEdges()
|
||||
const
|
||||
{
|
||||
if (!edgesPtr_)
|
||||
{
|
||||
@ -143,9 +183,15 @@ label PrimitivePatch<Face, FaceList, PointField>::nInternalEdges() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const labelList&
|
||||
PrimitivePatch<Face, FaceList, PointField>::boundaryPoints() const
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::boundaryPoints() const
|
||||
{
|
||||
if (!boundaryPointsPtr_)
|
||||
{
|
||||
@ -156,9 +202,15 @@ PrimitivePatch<Face, FaceList, PointField>::boundaryPoints() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const labelListList&
|
||||
PrimitivePatch<Face, FaceList, PointField>::faceFaces() const
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::faceFaces() const
|
||||
{
|
||||
if (!faceFacesPtr_)
|
||||
{
|
||||
@ -169,9 +221,15 @@ PrimitivePatch<Face, FaceList, PointField>::faceFaces() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const labelListList&
|
||||
PrimitivePatch<Face, FaceList, PointField>::edgeFaces() const
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::edgeFaces() const
|
||||
{
|
||||
if (!edgeFacesPtr_)
|
||||
{
|
||||
@ -182,9 +240,15 @@ PrimitivePatch<Face, FaceList, PointField>::edgeFaces() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const labelListList&
|
||||
PrimitivePatch<Face, FaceList, PointField>::faceEdges() const
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::faceEdges() const
|
||||
{
|
||||
if (!faceEdgesPtr_)
|
||||
{
|
||||
@ -195,9 +259,15 @@ PrimitivePatch<Face, FaceList, PointField>::faceEdges() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const labelListList&
|
||||
PrimitivePatch<Face, FaceList, PointField>::pointEdges() const
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::pointEdges() const
|
||||
{
|
||||
if (!pointEdgesPtr_)
|
||||
{
|
||||
@ -208,9 +278,15 @@ PrimitivePatch<Face, FaceList, PointField>::pointEdges() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const labelListList&
|
||||
PrimitivePatch<Face, FaceList, PointField>::pointFaces() const
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::pointFaces() const
|
||||
{
|
||||
if (!pointFacesPtr_)
|
||||
{
|
||||
@ -221,9 +297,15 @@ PrimitivePatch<Face, FaceList, PointField>::pointFaces() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const List<Face>&
|
||||
PrimitivePatch<Face, FaceList, PointField>::localFaces() const
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::localFaces() const
|
||||
{
|
||||
if (!localFacesPtr_)
|
||||
{
|
||||
@ -234,9 +316,15 @@ PrimitivePatch<Face, FaceList, PointField>::localFaces() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const labelList&
|
||||
PrimitivePatch<Face, FaceList, PointField>::meshPoints() const
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::meshPoints() const
|
||||
{
|
||||
if (!meshPointsPtr_)
|
||||
{
|
||||
@ -247,9 +335,15 @@ PrimitivePatch<Face, FaceList, PointField>::meshPoints() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const Map<label>&
|
||||
PrimitivePatch<Face, FaceList, PointField>::meshPointMap() const
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::meshPointMap() const
|
||||
{
|
||||
if (!meshPointMapPtr_)
|
||||
{
|
||||
@ -260,9 +354,15 @@ PrimitivePatch<Face, FaceList, PointField>::meshPointMap() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
const pointField&
|
||||
PrimitivePatch<Face, FaceList, PointField>::localPoints() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const Field<PointType>&
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::localPoints() const
|
||||
{
|
||||
if (!localPointsPtr_)
|
||||
{
|
||||
@ -273,9 +373,15 @@ PrimitivePatch<Face, FaceList, PointField>::localPoints() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const labelList&
|
||||
PrimitivePatch<Face, FaceList, PointField>::localPointOrder() const
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::localPointOrder() const
|
||||
{
|
||||
if (!localPointOrderPtr_)
|
||||
{
|
||||
@ -286,8 +392,14 @@ PrimitivePatch<Face, FaceList, PointField>::localPointOrder() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
label PrimitivePatch<Face, FaceList, PointField>::whichPoint
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
label PrimitivePatch<Face, FaceList, PointField, PointType>::whichPoint
|
||||
(
|
||||
const label gp
|
||||
) const
|
||||
@ -306,9 +418,15 @@ label PrimitivePatch<Face, FaceList, PointField>::whichPoint
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
const vectorField&
|
||||
PrimitivePatch<Face, FaceList, PointField>::faceNormals() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const Field<PointType>&
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::faceNormals() const
|
||||
{
|
||||
if (!faceNormalsPtr_)
|
||||
{
|
||||
@ -319,9 +437,15 @@ PrimitivePatch<Face, FaceList, PointField>::faceNormals() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
const vectorField&
|
||||
PrimitivePatch<Face, FaceList, PointField>::pointNormals() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const Field<PointType>&
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::pointNormals() const
|
||||
{
|
||||
if (!pointNormalsPtr_)
|
||||
{
|
||||
@ -334,10 +458,16 @@ PrimitivePatch<Face, FaceList, PointField>::pointNormals() const
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::operator=
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::operator=
|
||||
(
|
||||
const PrimitivePatch<Face, FaceList, PointField>& pp
|
||||
const PrimitivePatch<Face, FaceList, PointField, PointType>& pp
|
||||
)
|
||||
{
|
||||
clearOut();
|
||||
|
||||
@ -34,17 +34,18 @@ Description
|
||||
storage using List and pointField.
|
||||
|
||||
SourceFiles
|
||||
PrimitivePatch.C
|
||||
PrimitivePatchAddressing.C
|
||||
PrimitivePatchFaceCells.C
|
||||
PrimitivePatchBdryPoints.C
|
||||
PrimitivePatchMeshData.C
|
||||
PrimitivePatchPointAddressing.C
|
||||
PrimitivePatchLocalPointOrder.C
|
||||
PrimitivePatchEdgeLoops.C
|
||||
PrimitivePatchMeshEdges.C
|
||||
PrimitivePatchProjectPoints.C
|
||||
PrimitivePatch.C
|
||||
PrimitivePatchCheck.C
|
||||
PrimitivePatchClear.C
|
||||
PrimitivePatchEdgeLoops.C
|
||||
PrimitivePatchLocalPointOrder.C
|
||||
PrimitivePatchMeshData.C
|
||||
PrimitivePatchMeshEdges.C
|
||||
PrimitivePatchName.C
|
||||
PrimitivePatchPointAddressing.C
|
||||
PrimitivePatchProjectPoints.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -54,8 +55,7 @@ SourceFiles
|
||||
#include "boolList.H"
|
||||
#include "labelList.H"
|
||||
#include "edgeList.H"
|
||||
#include "pointField.H"
|
||||
#include "vectorField.H"
|
||||
#include "point.H"
|
||||
#include "intersection.H"
|
||||
#include "labelHashSet.H"
|
||||
|
||||
@ -79,7 +79,13 @@ TemplateName(PrimitivePatch);
|
||||
Class PrimitivePatch Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType=point
|
||||
>
|
||||
class PrimitivePatch
|
||||
:
|
||||
public PrimitivePatchName,
|
||||
@ -92,6 +98,7 @@ public:
|
||||
|
||||
typedef Face FaceType;
|
||||
typedef FaceList<Face> FaceListType;
|
||||
typedef PointField PointFieldType;
|
||||
|
||||
|
||||
// Public data types
|
||||
@ -154,16 +161,16 @@ private:
|
||||
mutable labelListList* edgeLoopsPtr_;
|
||||
|
||||
//- Points local to patch
|
||||
mutable pointField* localPointsPtr_;
|
||||
mutable Field<PointType>* localPointsPtr_;
|
||||
|
||||
//- Local point order for most efficient search
|
||||
mutable labelList* localPointOrderPtr_;
|
||||
|
||||
//- Face unit normals
|
||||
mutable vectorField* faceNormalsPtr_;
|
||||
mutable Field<PointType>* faceNormalsPtr_;
|
||||
|
||||
//- Point unit normals
|
||||
mutable vectorField* pointNormalsPtr_;
|
||||
mutable Field<PointType>* pointNormalsPtr_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
@ -225,11 +232,14 @@ public:
|
||||
PrimitivePatch
|
||||
(
|
||||
const FaceList<Face>& faces,
|
||||
const pointField& points
|
||||
const Field<PointType>& points
|
||||
);
|
||||
|
||||
//- Construct as copy
|
||||
PrimitivePatch(const PrimitivePatch<Face, FaceList, PointField>&);
|
||||
PrimitivePatch
|
||||
(
|
||||
const PrimitivePatch<Face, FaceList, PointField, PointType>&
|
||||
);
|
||||
|
||||
|
||||
// Destructor
|
||||
@ -250,7 +260,7 @@ public:
|
||||
// Access
|
||||
|
||||
//- Return reference to global points
|
||||
const pointField& points() const
|
||||
const Field<PointType>& points() const
|
||||
{
|
||||
return points_;
|
||||
}
|
||||
@ -317,7 +327,7 @@ public:
|
||||
const Map<label>& meshPointMap() const;
|
||||
|
||||
//- Return pointField of points in patch
|
||||
const pointField& localPoints() const;
|
||||
const Field<PointType>& localPoints() const;
|
||||
|
||||
//- Return orders the local points for most efficient search
|
||||
const labelList& localPointOrder() const;
|
||||
@ -339,10 +349,10 @@ public:
|
||||
) const;
|
||||
|
||||
//- Return face normals for patch
|
||||
const vectorField& faceNormals() const;
|
||||
const Field<PointType>& faceNormals() const;
|
||||
|
||||
//- Return point normals for patch
|
||||
const vectorField& pointNormals() const;
|
||||
const Field<PointType>& pointNormals() const;
|
||||
|
||||
|
||||
// Other patch operations
|
||||
@ -352,7 +362,7 @@ public:
|
||||
List<objectHit> projectPoints
|
||||
(
|
||||
const ToPatch& targetPatch,
|
||||
const vectorField& projectionDirection,
|
||||
const Field<PointType>& projectionDirection,
|
||||
const intersection::algorithm alg = intersection::FULL_RAY,
|
||||
const intersection::direction dir = intersection::VECTOR
|
||||
) const;
|
||||
@ -362,7 +372,7 @@ public:
|
||||
List<objectHit> projectFaceCentres
|
||||
(
|
||||
const ToPatch& targetPatch,
|
||||
const vectorField& projectionDirection,
|
||||
const Field<PointType>& projectionDirection,
|
||||
const intersection::algorithm alg = intersection::FULL_RAY,
|
||||
const intersection::direction dir = intersection::VECTOR
|
||||
) const;
|
||||
@ -406,13 +416,16 @@ public:
|
||||
// Edit
|
||||
|
||||
//- Correct patch after moving points
|
||||
virtual void movePoints(const pointField&);
|
||||
virtual void movePoints(const Field<PointType>&);
|
||||
|
||||
|
||||
// Member operators
|
||||
|
||||
//- Assignment
|
||||
void operator=(const PrimitivePatch<Face, FaceList, PointField>&);
|
||||
void operator=
|
||||
(
|
||||
const PrimitivePatch<Face, FaceList, PointField, PointType>&
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -46,13 +46,20 @@ namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::calcAddressing() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::calcAddressing()
|
||||
const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::calcAddressing() : "
|
||||
<< "calculating patch addressing"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "calcAddressing() : calculating patch addressing"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
@ -62,7 +69,8 @@ void PrimitivePatch<Face, FaceList, PointField>::calcAddressing() const
|
||||
// if already allocated
|
||||
FatalErrorIn
|
||||
(
|
||||
"PrimitivePatch<Face, FaceList, PointField>::calcAddressing()"
|
||||
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcAddressing()"
|
||||
) << "addressing already calculated"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
@ -244,7 +252,7 @@ void PrimitivePatch<Face, FaceList, PointField>::calcAddressing() const
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"PrimitivePatch<Face, FaceList, PointField>::"
|
||||
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcAddressing()"
|
||||
) << "Error in internal edge insertion"
|
||||
<< abort(FatalError);
|
||||
@ -296,8 +304,8 @@ void PrimitivePatch<Face, FaceList, PointField>::calcAddressing() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::calcAddressing() : "
|
||||
<< "finished calculating patch addressing"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "calcAddressing() : finished calculating patch addressing"
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,12 +36,19 @@ namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::calcBdryPoints() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::calcBdryPoints()
|
||||
const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "calcBdryPoints() : "
|
||||
<< "calculating boundary points"
|
||||
<< endl;
|
||||
@ -53,7 +60,8 @@ void PrimitivePatch<Face, FaceList, PointField>::calcBdryPoints() const
|
||||
// if already allocated
|
||||
FatalErrorIn
|
||||
(
|
||||
"PrimitivePatch<Face, FaceList, PointField>::calcBdryPoints()"
|
||||
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcBdryPoints()"
|
||||
) << "edge types already calculated"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
@ -75,7 +83,7 @@ void PrimitivePatch<Face, FaceList, PointField>::calcBdryPoints() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "calcBdryPoints() : "
|
||||
<< "finished calculating boundary points"
|
||||
<< endl;
|
||||
|
||||
@ -38,8 +38,14 @@ namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::visitPointRegion
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::visitPointRegion
|
||||
(
|
||||
const label pointI,
|
||||
const labelList& pFaces,
|
||||
@ -78,7 +84,8 @@ void PrimitivePatch<Face, FaceList, PointField>::visitPointRegion
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"PrimitivePatch<Face, FaceList, PointField>::visitPointRegion"
|
||||
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"visitPointRegion"
|
||||
) << "Problem: cannot find edge out of " << fEdges
|
||||
<< "on face " << startFaceI << " that uses point " << pointI
|
||||
<< " and is not edge " << startEdgeI << abort(FatalError);
|
||||
@ -107,13 +114,19 @@ void PrimitivePatch<Face, FaceList, PointField>::visitPointRegion
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
typename PrimitivePatch<Face, FaceList, PointField>::surfaceTopo
|
||||
PrimitivePatch<Face, FaceList, PointField>::surfaceType() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
typename PrimitivePatch<Face, FaceList, PointField, PointType>::surfaceTopo
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::surfaceType() const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"surfaceType() : "
|
||||
"calculating patch topology"
|
||||
<< endl;
|
||||
@ -143,7 +156,7 @@ PrimitivePatch<Face, FaceList, PointField>::surfaceType() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"surfaceType() : "
|
||||
"finished calculating patch topology"
|
||||
<< endl;
|
||||
@ -153,8 +166,14 @@ PrimitivePatch<Face, FaceList, PointField>::surfaceType() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
bool PrimitivePatch<Face, FaceList, PointField>::checkTopology
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
bool PrimitivePatch<Face, FaceList, PointField, PointType>::checkTopology
|
||||
(
|
||||
const bool report,
|
||||
labelHashSet* setPtr
|
||||
@ -162,7 +181,7 @@ bool PrimitivePatch<Face, FaceList, PointField>::checkTopology
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"checkTopology(const bool, labelHashSet&) : "
|
||||
"checking patch topology"
|
||||
<< endl;
|
||||
@ -205,7 +224,7 @@ bool PrimitivePatch<Face, FaceList, PointField>::checkTopology
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"checkTopology(const bool, labelHashSet&) : "
|
||||
"finished checking patch topology"
|
||||
<< endl;
|
||||
@ -215,9 +234,15 @@ bool PrimitivePatch<Face, FaceList, PointField>::checkTopology
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
bool
|
||||
PrimitivePatch<Face, FaceList, PointField>::checkPointManifold
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::checkPointManifold
|
||||
(
|
||||
const bool report,
|
||||
labelHashSet* setPtr
|
||||
|
||||
@ -36,13 +36,19 @@ namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::clearGeom()
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::clearGeom()
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::clearGeom() : "
|
||||
<< "clearing geometric data"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "clearGeom() : clearing geometric data"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
@ -52,13 +58,19 @@ void PrimitivePatch<Face, FaceList, PointField>::clearGeom()
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::clearTopology()
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::clearTopology()
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::clearTopology() : "
|
||||
<< "clearing patch addressing"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "clearTopology() : clearing patch addressing"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
@ -87,12 +99,18 @@ void PrimitivePatch<Face, FaceList, PointField>::clearTopology()
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::clearPatchMeshAddr()
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::clearPatchMeshAddr()
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "clearPatchMeshAddr() : "
|
||||
<< "clearing patch-mesh addressing"
|
||||
<< endl;
|
||||
@ -104,8 +122,14 @@ void PrimitivePatch<Face, FaceList, PointField>::clearPatchMeshAddr()
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::clearOut()
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::clearOut()
|
||||
{
|
||||
clearGeom();
|
||||
clearTopology();
|
||||
|
||||
@ -37,12 +37,19 @@ namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::calcEdgeLoops() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::calcEdgeLoops()
|
||||
const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "calcEdgeLoops() : "
|
||||
<< "calculating boundary edge loops"
|
||||
<< endl;
|
||||
@ -54,7 +61,8 @@ void PrimitivePatch<Face, FaceList, PointField>::calcEdgeLoops() const
|
||||
// if already allocated
|
||||
FatalErrorIn
|
||||
(
|
||||
"PrimitivePatch<Face, FaceList, PointField>::calcIntBdryEdges()"
|
||||
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcIntBdryEdges()"
|
||||
) << "edge loops already calculated"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
@ -154,7 +162,7 @@ void PrimitivePatch<Face, FaceList, PointField>::calcEdgeLoops() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "calcEdgeLoops() : "
|
||||
<< "finished calculating boundary edge loops"
|
||||
<< endl;
|
||||
@ -162,9 +170,15 @@ void PrimitivePatch<Face, FaceList, PointField>::calcEdgeLoops() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
const labelListList&
|
||||
PrimitivePatch<Face, FaceList, PointField>::edgeLoops() const
|
||||
PrimitivePatch<Face, FaceList, PointField, PointType>::edgeLoops() const
|
||||
{
|
||||
if (!edgeLoopsPtr_)
|
||||
{
|
||||
|
||||
@ -27,7 +27,6 @@ Description
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//#include "PrimitivePatch.H"
|
||||
#include "SLList.H"
|
||||
#include "boolList.H"
|
||||
|
||||
@ -38,8 +37,15 @@ namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::calcLocalPointOrder() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::
|
||||
calcLocalPointOrder() const
|
||||
{
|
||||
// Note: Cannot use bandCompressing as point-point addressing does
|
||||
// not exist and is not considered generally useful.
|
||||
@ -47,7 +53,7 @@ void PrimitivePatch<Face, FaceList, PointField>::calcLocalPointOrder() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "calcLocalPointOrder() : "
|
||||
<< "calculating local point order"
|
||||
<< endl;
|
||||
@ -59,7 +65,8 @@ void PrimitivePatch<Face, FaceList, PointField>::calcLocalPointOrder() const
|
||||
// if already allocated
|
||||
FatalErrorIn
|
||||
(
|
||||
"PrimitivePatch<Face, FaceList, PointField>::calcLocalPointOrder()"
|
||||
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcLocalPointOrder()"
|
||||
) << "local point order already calculated"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
@ -126,7 +133,7 @@ void PrimitivePatch<Face, FaceList, PointField>::calcLocalPointOrder() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "calcLocalPointOrder() "
|
||||
<< "finished calculating local point order"
|
||||
<< endl;
|
||||
|
||||
@ -34,12 +34,19 @@ namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::calcMeshData() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::calcMeshData() const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcMeshData() : "
|
||||
"calculating mesh data in PrimitivePatch"
|
||||
<< endl;
|
||||
@ -51,7 +58,7 @@ void PrimitivePatch<Face, FaceList, PointField>::calcMeshData() const
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"PrimitivePatch<Face, FaceList, PointField>::"
|
||||
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcMeshData()"
|
||||
) << "meshPointsPtr_ or localFacesPtr_already allocated"
|
||||
<< abort(FatalError);
|
||||
@ -105,7 +112,7 @@ void PrimitivePatch<Face, FaceList, PointField>::calcMeshData() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcMeshData() : "
|
||||
"finished calculating mesh data in PrimitivePatch"
|
||||
<< endl;
|
||||
@ -113,12 +120,20 @@ void PrimitivePatch<Face, FaceList, PointField>::calcMeshData() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::calcMeshPointMap() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::calcMeshPointMap()
|
||||
const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcMeshPointMap() : "
|
||||
"calculating mesh point map in PrimitivePatch"
|
||||
<< endl;
|
||||
@ -130,7 +145,7 @@ void PrimitivePatch<Face, FaceList, PointField>::calcMeshPointMap() const
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"PrimitivePatch<Face, FaceList, PointField>::"
|
||||
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcMeshPointMap()"
|
||||
) << "meshPointMapPtr_ already allocated"
|
||||
<< abort(FatalError);
|
||||
@ -148,7 +163,7 @@ void PrimitivePatch<Face, FaceList, PointField>::calcMeshPointMap() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcMeshPointMap() : "
|
||||
"finished calculating mesh point map in PrimitivePatch"
|
||||
<< endl;
|
||||
@ -156,12 +171,20 @@ void PrimitivePatch<Face, FaceList, PointField>::calcMeshPointMap() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::calcLocalPoints() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::calcLocalPoints()
|
||||
const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcLocalPoints() : "
|
||||
"calculating localPoints in PrimitivePatch"
|
||||
<< endl;
|
||||
@ -173,16 +196,17 @@ void PrimitivePatch<Face, FaceList, PointField>::calcLocalPoints() const
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"PrimitivePatch<Face, FaceList, PointField>::calcLocalPoints()"
|
||||
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcLocalPoints()"
|
||||
) << "localPointsPtr_already allocated"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
const labelList& meshPts = meshPoints();
|
||||
|
||||
localPointsPtr_ = new pointField(meshPts.size());
|
||||
localPointsPtr_ = new Field<PointType>(meshPts.size());
|
||||
|
||||
pointField& locPts = *localPointsPtr_;
|
||||
Field<PointType>& locPts = *localPointsPtr_;
|
||||
|
||||
forAll (meshPts, pointI)
|
||||
{
|
||||
@ -191,7 +215,7 @@ void PrimitivePatch<Face, FaceList, PointField>::calcLocalPoints() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "calcLocalPoints() : "
|
||||
<< "finished calculating localPoints in PrimitivePatch"
|
||||
<< endl;
|
||||
@ -199,12 +223,20 @@ void PrimitivePatch<Face, FaceList, PointField>::calcLocalPoints() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::calcPointNormals() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::calcPointNormals()
|
||||
const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcPointNormals() : "
|
||||
"calculating pointNormals in PrimitivePatch"
|
||||
<< endl;
|
||||
@ -216,22 +248,27 @@ void PrimitivePatch<Face, FaceList, PointField>::calcPointNormals() const
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"PrimitivePatch<Face, FaceList, PointField>::calcPointNormals()"
|
||||
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcPointNormals()"
|
||||
) << "pointNormalsPtr_already allocated"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
const vectorField& faceUnitNormals = faceNormals();
|
||||
const Field<PointType>& faceUnitNormals = faceNormals();
|
||||
|
||||
const labelListList& pf = pointFaces();
|
||||
|
||||
pointNormalsPtr_ = new vectorField(meshPoints().size(), vector(0, 0, 0));
|
||||
pointNormalsPtr_ = new Field<PointType>
|
||||
(
|
||||
meshPoints().size(),
|
||||
PointType::zero
|
||||
);
|
||||
|
||||
vectorField& n = *pointNormalsPtr_;
|
||||
Field<PointType>& n = *pointNormalsPtr_;
|
||||
|
||||
forAll (pf, pointI)
|
||||
{
|
||||
vector& curNormal = n[pointI];
|
||||
PointType& curNormal = n[pointI];
|
||||
|
||||
const labelList& curFaces = pf[pointI];
|
||||
|
||||
@ -245,7 +282,7 @@ void PrimitivePatch<Face, FaceList, PointField>::calcPointNormals() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcPointNormals() : "
|
||||
"finished calculating pointNormals in PrimitivePatch"
|
||||
<< endl;
|
||||
@ -253,12 +290,20 @@ void PrimitivePatch<Face, FaceList, PointField>::calcPointNormals() const
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::calcFaceNormals() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::calcFaceNormals()
|
||||
const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcFaceNormals() : "
|
||||
"calculating faceNormals in PrimitivePatch"
|
||||
<< endl;
|
||||
@ -270,14 +315,15 @@ void PrimitivePatch<Face, FaceList, PointField>::calcFaceNormals() const
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"PrimitivePatch<Face, FaceList, PointField>::calcFaceNormals()"
|
||||
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcFaceNormals()"
|
||||
) << "faceNormalsPtr_already allocated"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
faceNormalsPtr_ = new vectorField(this->size());
|
||||
faceNormalsPtr_ = new Field<PointType>(this->size());
|
||||
|
||||
vectorField& n = *faceNormalsPtr_;
|
||||
Field<PointType>& n = *faceNormalsPtr_;
|
||||
|
||||
forAll (n, faceI)
|
||||
{
|
||||
@ -287,7 +333,7 @@ void PrimitivePatch<Face, FaceList, PointField>::calcFaceNormals() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::"
|
||||
Pout<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcFaceNormals() : "
|
||||
"finished calculating faceNormals in PrimitivePatch"
|
||||
<< endl;
|
||||
|
||||
@ -35,8 +35,15 @@ namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
labelList PrimitivePatch<Face, FaceList, PointField>::meshEdges
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
|
||||
labelList PrimitivePatch<Face, FaceList, PointField, PointType>::meshEdges
|
||||
(
|
||||
const edgeList& allEdges,
|
||||
const labelListList& cellEdges,
|
||||
@ -45,7 +52,7 @@ labelList PrimitivePatch<Face, FaceList, PointField>::meshEdges
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "labelList PrimitivePatch<Face, FaceList, PointField>"
|
||||
Info<< "labelList PrimitivePatch<Face, FaceList, PointField, PointType>"
|
||||
<< "::meshEdges() : "
|
||||
<< "calculating labels of patch edges in mesh edge list"
|
||||
<< endl;
|
||||
@ -106,8 +113,15 @@ labelList PrimitivePatch<Face, FaceList, PointField>::meshEdges
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
label PrimitivePatch<Face, FaceList, PointField>::whichEdge
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
|
||||
label PrimitivePatch<Face, FaceList, PointField, PointType>::whichEdge
|
||||
(
|
||||
const edge& e
|
||||
) const
|
||||
|
||||
@ -37,13 +37,21 @@ namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::calcPointEdges() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::calcPointEdges()
|
||||
const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::calcPointEdges() : "
|
||||
<< "calculating pointEdges"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "calcPointEdges() : calculating pointEdges"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
@ -51,8 +59,11 @@ void PrimitivePatch<Face, FaceList, PointField>::calcPointEdges() const
|
||||
{
|
||||
// it is considered an error to attempt to recalculate
|
||||
// if already allocated
|
||||
FatalErrorIn("PrimitivePatch<Face, FaceList, PointField>::calcPointEdges()")
|
||||
<< "pointEdges already calculated"
|
||||
FatalErrorIn
|
||||
(
|
||||
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcPointEdges()"
|
||||
) << "pointEdges already calculated"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
@ -90,20 +101,28 @@ void PrimitivePatch<Face, FaceList, PointField>::calcPointEdges() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::calcPointEdges() "
|
||||
<< "finished calculating pointEdges"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "calcPointEdges() finished calculating pointEdges"
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
void PrimitivePatch<Face, FaceList, PointField>::calcPointFaces() const
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
|
||||
void PrimitivePatch<Face, FaceList, PointField, PointType>::calcPointFaces()
|
||||
const
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::calcPointFaces() : "
|
||||
<< "calculating pointFaces"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "calcPointFaces() : calculating pointFaces"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
@ -111,8 +130,11 @@ void PrimitivePatch<Face, FaceList, PointField>::calcPointFaces() const
|
||||
{
|
||||
// it is considered an error to attempt to recalculate
|
||||
// if already allocated
|
||||
FatalErrorIn("PrimitivePatch<Face, FaceList, PointField>::calcPointFaces()")
|
||||
<< "pointFaces already calculated"
|
||||
FatalErrorIn
|
||||
(
|
||||
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"calcPointFaces()"
|
||||
) << "pointFaces already calculated"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
@ -154,8 +176,8 @@ void PrimitivePatch<Face, FaceList, PointField>::calcPointFaces() const
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField>::calcPointFaces() "
|
||||
<< "finished calculating pointFaces"
|
||||
Info<< "PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
<< "calcPointFaces() finished calculating pointFaces"
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ Description
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "boolList.H"
|
||||
#include "pointHit.H"
|
||||
#include "PointHit.H"
|
||||
#include "objectHit.H"
|
||||
#include "bandCompression.H"
|
||||
|
||||
@ -40,12 +40,20 @@ namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
|
||||
template <class ToPatch>
|
||||
List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectPoints
|
||||
List<objectHit> PrimitivePatch<Face, FaceList, PointField, PointType>::
|
||||
projectPoints
|
||||
(
|
||||
const ToPatch& targetPatch,
|
||||
const vectorField& projectionDirection,
|
||||
const Field<PointType>& projectionDirection,
|
||||
const intersection::algorithm alg,
|
||||
const intersection::direction dir
|
||||
) const
|
||||
@ -57,9 +65,9 @@ List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectPoints
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"List<objectHit> PrimitivePatch<Face, FaceList, PointField>::"
|
||||
"PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"projectPoints(const PrimitivePatch& "
|
||||
"targetPatch, const vectorField& projectionDirection) const"
|
||||
", const Field<PointType>&) const"
|
||||
) << "Projection direction field does not correspond to "
|
||||
<< "patch points." << endl
|
||||
<< "Size: " << projectionDirection.size()
|
||||
@ -78,10 +86,10 @@ List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectPoints
|
||||
|
||||
const ToPatch& masterFaces = targetPatch;
|
||||
|
||||
const pointField& masterPoints = targetPatch.points();
|
||||
const typename ToPatch::PointFieldType& masterPoints = targetPatch.points();
|
||||
|
||||
// Estimate face centre of target side
|
||||
vectorField masterFaceCentres(targetPatch.size());
|
||||
Field<PointType> masterFaceCentres(targetPatch.size());
|
||||
|
||||
forAll (masterFaceCentres, faceI)
|
||||
{
|
||||
@ -105,9 +113,10 @@ List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectPoints
|
||||
// Pick up slave point and direction
|
||||
const label curLocalPointLabel = slavePointOrder[pointI];
|
||||
|
||||
const point& curPoint = points_[slaveMeshPoints[curLocalPointLabel]];
|
||||
const PointType& curPoint =
|
||||
points_[slaveMeshPoints[curLocalPointLabel]];
|
||||
|
||||
const vector& curProjectionDir =
|
||||
const PointType& curProjectionDir =
|
||||
projectionDirection[curLocalPointLabel];
|
||||
|
||||
bool closer;
|
||||
@ -133,7 +142,7 @@ List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectPoints
|
||||
doNSquaredSearch = false;
|
||||
|
||||
// Calculate intersection with curFace
|
||||
pointHit curHit =
|
||||
PointHit<PointType> curHit =
|
||||
masterFaces[curFace].ray
|
||||
(
|
||||
curPoint,
|
||||
@ -169,7 +178,7 @@ List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectPoints
|
||||
// face. This is cooked (illogical!) for fastest
|
||||
// surface walk.
|
||||
//
|
||||
point missPlanePoint =
|
||||
PointType missPlanePoint =
|
||||
curPoint + curProjectionDir*curHit.distance();
|
||||
|
||||
const labelList& masterNbrs = masterFaceFaces[curFace];
|
||||
@ -224,7 +233,7 @@ List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectPoints
|
||||
|
||||
forAll (masterFaces, faceI)
|
||||
{
|
||||
pointHit curHit =
|
||||
PointHit<PointType> curHit =
|
||||
masterFaces[faceI].ray
|
||||
(
|
||||
curPoint,
|
||||
@ -279,12 +288,20 @@ List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectPoints
|
||||
}
|
||||
|
||||
|
||||
template<class Face, template<class> class FaceList, class PointField>
|
||||
template
|
||||
<
|
||||
class Face,
|
||||
template<class> class FaceList,
|
||||
class PointField,
|
||||
class PointType
|
||||
>
|
||||
|
||||
template <class ToPatch>
|
||||
List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectFaceCentres
|
||||
List<objectHit> PrimitivePatch<Face, FaceList, PointField, PointType>::
|
||||
projectFaceCentres
|
||||
(
|
||||
const ToPatch& targetPatch,
|
||||
const vectorField& projectionDirection,
|
||||
const Field<PointType>& projectionDirection,
|
||||
const intersection::algorithm alg,
|
||||
const intersection::direction dir
|
||||
) const
|
||||
@ -296,9 +313,9 @@ List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectFaceCentres
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"labelList PrimitivePatch<Face, FaceList, PointField>::"
|
||||
"labelList PrimitivePatch<Face, FaceList, PointField, PointType>::"
|
||||
"projectFaceCentres(const PrimitivePatch& "
|
||||
"targetPatch, const vectorField& projectionDirection) const"
|
||||
", const Field<PointType>&) const"
|
||||
) << "Projection direction field does not correspond to patch faces."
|
||||
<< endl << "Size: " << projectionDirection.size()
|
||||
<< " Number of points: " << this->size()
|
||||
@ -308,13 +325,13 @@ List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectFaceCentres
|
||||
labelList slaveFaceOrder = bandCompression(faceFaces());
|
||||
|
||||
// calculate master face centres
|
||||
vectorField masterFaceCentres(targetPatch.size());
|
||||
Field<PointType> masterFaceCentres(targetPatch.size());
|
||||
|
||||
const labelListList& masterFaceFaces = targetPatch.faceFaces();
|
||||
|
||||
const ToPatch& masterFaces = targetPatch;
|
||||
|
||||
const pointField& masterPoints = targetPatch.points();
|
||||
const typename ToPatch::PointFieldType& masterPoints = targetPatch.points();
|
||||
|
||||
forAll (masterFaceCentres, faceI)
|
||||
{
|
||||
@ -325,8 +342,8 @@ List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectFaceCentres
|
||||
// Result
|
||||
List<objectHit> result(this->size());
|
||||
|
||||
const PrimitivePatch<Face, FaceList, PointField>& slaveFaces = *this;
|
||||
const vectorField& slaveGlobalPoints = points();
|
||||
const PrimitivePatch<Face, FaceList, PointField, PointType>& slaveFaces = *this;
|
||||
const PointField& slaveGlobalPoints = points();
|
||||
|
||||
// Algorithm:
|
||||
// Loop through all points of the slave side. For every point find the
|
||||
@ -373,7 +390,7 @@ List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectFaceCentres
|
||||
doNSquaredSearch = false;
|
||||
|
||||
// Calculate intersection with curFace
|
||||
pointHit curHit =
|
||||
PointHit<PointType> curHit =
|
||||
masterFaces[curFace].ray
|
||||
(
|
||||
curFaceCentre,
|
||||
@ -408,7 +425,7 @@ List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectFaceCentres
|
||||
// Calculate the miss point. This is
|
||||
// cooked (illogical!) for fastest surface walk.
|
||||
//
|
||||
point missPlanePoint =
|
||||
PointType missPlanePoint =
|
||||
curFaceCentre + curProjectionDir*curHit.distance();
|
||||
|
||||
sqrDistance =
|
||||
@ -460,7 +477,7 @@ List<objectHit> PrimitivePatch<Face, FaceList, PointField>::projectFaceCentres
|
||||
|
||||
forAll (masterFaces, faceI)
|
||||
{
|
||||
pointHit curHit =
|
||||
PointHit<PointType> curHit =
|
||||
masterFaces[faceI].ray
|
||||
(
|
||||
curFaceCentre,
|
||||
|
||||
@ -36,11 +36,11 @@ SourceFiles
|
||||
#ifndef triangle_H
|
||||
#define triangle_H
|
||||
|
||||
#include "point.H"
|
||||
#include "intersection.H"
|
||||
#include "vector.H"
|
||||
#include "pointHit.H"
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
@ -81,23 +81,6 @@ class triangle
|
||||
|
||||
// Private member functions
|
||||
|
||||
//- Find intersection of triangle (origin V0, spanning edges
|
||||
// E0, E1) with infinite ray (origin P, direction dir) Based
|
||||
// on Graphics Gems - Fast Ray Triangle intersection. Since
|
||||
// direction is coordinate axis there is no need to do
|
||||
// projection, we can directly check u,v components for
|
||||
// inclusion in triangle.
|
||||
static bool intersection
|
||||
(
|
||||
const Point& baseVertex,
|
||||
const vector& E0,
|
||||
const vector& E1,
|
||||
const vector& n,
|
||||
const point& P,
|
||||
const vector& dir,
|
||||
point& pInter
|
||||
);
|
||||
|
||||
//- Fast distance to triangle calculation. From
|
||||
// "Distance Between Point and Trangle in 3D"
|
||||
// David Eberly, Magic Software Inc. Aug. 2002.
|
||||
@ -183,6 +166,17 @@ public:
|
||||
const intersection::direction dir = intersection::VECTOR
|
||||
) const;
|
||||
|
||||
//- Fast intersection with a ray.
|
||||
// For a hit, the pointHit.distance() is the line parameter t :
|
||||
// intersection=p+t*q. Only defined for VISIBLE, FULL_RAY or
|
||||
// HALF_RAY.
|
||||
inline pointHit intersection
|
||||
(
|
||||
const point& p,
|
||||
const vector& q,
|
||||
const intersection::algorithm alg
|
||||
) const;
|
||||
|
||||
//- Return nearest point to p on triangle
|
||||
inline pointHit nearestPoint
|
||||
(
|
||||
|
||||
@ -35,90 +35,6 @@ namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Point, class PointRef>
|
||||
bool triangle<Point, PointRef>::intersection
|
||||
(
|
||||
const Point& baseVertex,
|
||||
const vector& E0,
|
||||
const vector& E1,
|
||||
const vector& n,
|
||||
const point& P,
|
||||
const vector& dir,
|
||||
point& pInter
|
||||
)
|
||||
{
|
||||
// Calculate intersection of ray with triangle plane
|
||||
scalar denom = n & dir;
|
||||
|
||||
if (Foam::mag(denom) < SMALL)
|
||||
{
|
||||
// Parallel
|
||||
pInter = P;
|
||||
return false;
|
||||
}
|
||||
pInter = P + dir*(n & (baseVertex - P))/denom;
|
||||
|
||||
// Get largest component of normal
|
||||
scalar magX = Foam::mag(n.x());
|
||||
scalar magY = Foam::mag(n.y());
|
||||
scalar magZ = Foam::mag(n.z());
|
||||
|
||||
label i0 = -1;
|
||||
if ((magX >= magY) && (magX >= magZ))
|
||||
{
|
||||
i0 = 0;
|
||||
}
|
||||
else if ((magY >= magX) && (magY >= magZ))
|
||||
{
|
||||
i0 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
i0 = 2;
|
||||
}
|
||||
|
||||
// Get other components
|
||||
label i1 = (i0 + 1) % 3;
|
||||
label i2 = (i1 + 1) % 3;
|
||||
|
||||
scalar u1 = E0[i1];
|
||||
scalar v1 = E0[i2];
|
||||
|
||||
scalar u2 = E1[i1];
|
||||
scalar v2 = E1[i2];
|
||||
|
||||
scalar det = v2*u1 - u2*v1;
|
||||
|
||||
scalar u0 = pInter[i1] - baseVertex[i1];
|
||||
scalar v0 = pInter[i2] - baseVertex[i2];
|
||||
|
||||
scalar alpha = 0;
|
||||
scalar beta = 0;
|
||||
bool hit = false;
|
||||
|
||||
if (Foam::mag(u1) < SMALL)
|
||||
{
|
||||
beta = u0/u2;
|
||||
if ((beta >= 0) && (beta <= 1))
|
||||
{
|
||||
alpha = (v0 - beta*v2)/v1;
|
||||
hit = ((alpha >= 0) && ((alpha + beta) <= 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
beta = (v0*u1 - u0*v1)/det;
|
||||
if ((beta >= 0) && (beta <= 1))
|
||||
{
|
||||
alpha = (u0 - beta*u2)/u1;
|
||||
hit = ((alpha >= 0) && ((alpha + beta) <= 1));
|
||||
}
|
||||
}
|
||||
|
||||
return hit;
|
||||
}
|
||||
|
||||
|
||||
template<class Point, class PointRef>
|
||||
pointHit triangle<Point, PointRef>::nearestPoint
|
||||
(
|
||||
@ -447,19 +363,24 @@ inline pointHit triangle<Point, PointRef>::ray
|
||||
return inter;
|
||||
}
|
||||
|
||||
n /= area;
|
||||
|
||||
vector q1 = q/Foam::mag(q);
|
||||
|
||||
if (dir == intersection::CONTACT_SPHERE)
|
||||
{
|
||||
n /= area;
|
||||
|
||||
return ray(p, q1 - n, alg, intersection::VECTOR);
|
||||
}
|
||||
|
||||
point pInter;
|
||||
|
||||
// Calculate planar hit tolerance as percentage of shortest edge length
|
||||
bool hit = intersection(a_, E0, E1, n, p, q1, pInter);
|
||||
bool hit;
|
||||
{
|
||||
// Reuse the fast ray intersection routine below in FULL_RAY
|
||||
// mode since the original intersection routine has rounding problems.
|
||||
pointHit fastInter = intersection(p, q1, intersection::FULL_RAY);
|
||||
pInter = fastInter.rawPoint();
|
||||
hit = fastInter.hit();
|
||||
}
|
||||
|
||||
scalar dist = q1 & (pInter - p);
|
||||
|
||||
@ -502,10 +423,132 @@ inline pointHit triangle<Point, PointRef>::ray
|
||||
inter.setDistance(Foam::mag(pInter - p));
|
||||
}
|
||||
|
||||
|
||||
return inter;
|
||||
}
|
||||
|
||||
|
||||
// From "Fast, Minimum Storage Ray/Triangle Intersection"
|
||||
// Moeller/Trumbore.
|
||||
template<class Point, class PointRef>
|
||||
inline pointHit triangle<Point, PointRef>::intersection
|
||||
(
|
||||
const point& orig,
|
||||
const vector& dir,
|
||||
const intersection::algorithm alg
|
||||
) const
|
||||
{
|
||||
const vector edge1 = b_ - a_;
|
||||
const vector edge2 = c_ - a_;
|
||||
|
||||
// begin calculating determinant - also used to calculate U parameter
|
||||
const vector pVec = dir ^ edge2;
|
||||
|
||||
// if determinant is near zero, ray lies in plane of triangle
|
||||
const scalar det = edge1 & pVec;
|
||||
|
||||
// Initialise to miss
|
||||
pointHit intersection(false, vector::zero, GREAT, false);
|
||||
|
||||
if (alg == intersection::VISIBLE)
|
||||
{
|
||||
// Culling branch
|
||||
if (det < SMALL)
|
||||
{
|
||||
// return miss
|
||||
return intersection;
|
||||
}
|
||||
/* calculate distance from a_ to ray origin */
|
||||
const vector tVec = orig-a_;
|
||||
|
||||
/* calculate U parameter and test bounds */
|
||||
scalar u = tVec & pVec;
|
||||
|
||||
if (u < 0.0 || u > det)
|
||||
{
|
||||
// return miss
|
||||
return intersection;
|
||||
}
|
||||
|
||||
/* prepare to test V parameter */
|
||||
const vector qVec = tVec ^ edge1;
|
||||
|
||||
/* calculate V parameter and test bounds */
|
||||
scalar v = dir & qVec;
|
||||
|
||||
if (v < 0.0 || u + v > det)
|
||||
{
|
||||
// return miss
|
||||
return intersection;
|
||||
}
|
||||
|
||||
/* calculate t, scale parameters, ray intersects triangle */
|
||||
scalar t = edge2 & qVec;
|
||||
scalar inv_det = 1.0 / det;
|
||||
t *= inv_det;
|
||||
u *= inv_det;
|
||||
v *= inv_det;
|
||||
|
||||
intersection.setHit();
|
||||
intersection.setPoint(a_ + u*edge1 + v*edge2);
|
||||
intersection.setDistance(t);
|
||||
}
|
||||
else if (alg == intersection::HALF_RAY || alg == intersection::FULL_RAY)
|
||||
{
|
||||
// Non-culling branch
|
||||
if (det > -SMALL && det < SMALL)
|
||||
{
|
||||
// return miss
|
||||
return intersection;
|
||||
}
|
||||
const scalar inv_det = 1.0 / det;
|
||||
|
||||
/* calculate distance from a_ to ray origin */
|
||||
const vector tVec = orig - a_;
|
||||
/* calculate U parameter and test bounds */
|
||||
const scalar u = (tVec & pVec)*inv_det;
|
||||
|
||||
if (u < 0.0 || u > 1.0)
|
||||
{
|
||||
// return miss
|
||||
return intersection;
|
||||
}
|
||||
/* prepare to test V parameter */
|
||||
const vector qVec = tVec ^ edge1;
|
||||
/* calculate V parameter and test bounds */
|
||||
const scalar v = (dir & qVec) * inv_det;
|
||||
|
||||
if (v < 0.0 || u + v > 1.0)
|
||||
{
|
||||
// return miss
|
||||
return intersection;
|
||||
}
|
||||
/* calculate t, ray intersects triangle */
|
||||
const scalar t = (edge2 & qVec) * inv_det;
|
||||
|
||||
if (alg == intersection::HALF_RAY && t < 0)
|
||||
{
|
||||
// return miss
|
||||
return intersection;
|
||||
}
|
||||
|
||||
intersection.setHit();
|
||||
intersection.setPoint(a_ + u*edge1 + v*edge2);
|
||||
intersection.setDistance(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"triangle<Point, PointRef>::intersection(const point&"
|
||||
", const vector&, const intersection::algorithm)"
|
||||
) << "intersection only defined for VISIBLE, FULL_RAY or HALF_RAY"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
return intersection;
|
||||
}
|
||||
|
||||
|
||||
template<class Point, class PointRef>
|
||||
inline pointHit triangle<Point, PointRef>::nearestPoint
|
||||
|
||||
@ -99,10 +99,14 @@ Foam::autoPtr<Foam::mapAddedPolyMesh> Foam::fvMeshAdder::add
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
fvMeshAdder::MapVolFields<scalar>(mapPtr, mesh0, mesh1);
|
||||
fvMeshAdder::MapVolFields<vector>(mapPtr, mesh0, mesh1);
|
||||
fvMeshAdder::MapVolFields<sphericalTensor>(mapPtr, mesh0, mesh1);
|
||||
fvMeshAdder::MapVolFields<symmTensor>(mapPtr, mesh0, mesh1);
|
||||
fvMeshAdder::MapVolFields<tensor>(mapPtr, mesh0, mesh1);
|
||||
|
||||
fvMeshAdder::MapSurfaceFields<scalar>(mapPtr, mesh0, mesh1);
|
||||
fvMeshAdder::MapSurfaceFields<vector>(mapPtr, mesh0, mesh1);
|
||||
fvMeshAdder::MapSurfaceFields<sphericalTensor>(mapPtr, mesh0, mesh1);
|
||||
fvMeshAdder::MapSurfaceFields<symmTensor>(mapPtr, mesh0, mesh1);
|
||||
fvMeshAdder::MapSurfaceFields<tensor>(mapPtr, mesh0, mesh1);
|
||||
|
||||
return mapPtr;
|
||||
|
||||
@ -196,29 +196,38 @@ void Foam::fvMeshDistribute::printMeshInfo(const fvMesh& mesh)
|
||||
<< endl;
|
||||
}
|
||||
|
||||
Pout<< "PointZones:" << endl;
|
||||
forAll(mesh.pointZones(), zoneI)
|
||||
if (mesh.pointZones().size() > 0)
|
||||
{
|
||||
const pointZone& pz = mesh.pointZones()[zoneI];
|
||||
Pout<< " " << zoneI << " name:" << pz.name()
|
||||
<< " size:" << pz.size()
|
||||
<< endl;
|
||||
Pout<< "PointZones:" << endl;
|
||||
forAll(mesh.pointZones(), zoneI)
|
||||
{
|
||||
const pointZone& pz = mesh.pointZones()[zoneI];
|
||||
Pout<< " " << zoneI << " name:" << pz.name()
|
||||
<< " size:" << pz.size()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
Pout<< "FaceZones:" << endl;
|
||||
forAll(mesh.faceZones(), zoneI)
|
||||
if (mesh.faceZones().size() > 0)
|
||||
{
|
||||
const faceZone& fz = mesh.faceZones()[zoneI];
|
||||
Pout<< " " << zoneI << " name:" << fz.name()
|
||||
<< " size:" << fz.size()
|
||||
<< endl;
|
||||
Pout<< "FaceZones:" << endl;
|
||||
forAll(mesh.faceZones(), zoneI)
|
||||
{
|
||||
const faceZone& fz = mesh.faceZones()[zoneI];
|
||||
Pout<< " " << zoneI << " name:" << fz.name()
|
||||
<< " size:" << fz.size()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
Pout<< "CellZones:" << endl;
|
||||
forAll(mesh.cellZones(), zoneI)
|
||||
if (mesh.cellZones().size() > 0)
|
||||
{
|
||||
const cellZone& cz = mesh.cellZones()[zoneI];
|
||||
Pout<< " " << zoneI << " name:" << cz.name()
|
||||
<< " size:" << cz.size()
|
||||
<< endl;
|
||||
Pout<< "CellZones:" << endl;
|
||||
forAll(mesh.cellZones(), zoneI)
|
||||
{
|
||||
const cellZone& cz = mesh.cellZones()[zoneI];
|
||||
Pout<< " " << zoneI << " name:" << cz.name()
|
||||
<< " size:" << cz.size()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,7 +278,7 @@ Foam::label Foam::fvMeshDistribute::findNonEmptyPatch() const
|
||||
|
||||
if (nonEmptyPatchI == -1)
|
||||
{
|
||||
FatalErrorIn("findNonEmptyPatch() const")
|
||||
FatalErrorIn("fvMeshDistribute::findNonEmptyPatch() const")
|
||||
<< "Cannot find a patch which is neither of type empty nor"
|
||||
<< " coupled in patches " << patches.names() << endl
|
||||
<< "There has to be at least one such patch for"
|
||||
@ -297,7 +306,7 @@ Foam::label Foam::fvMeshDistribute::findNonEmptyPatch() const
|
||||
}
|
||||
else if (procPatchI != -1)
|
||||
{
|
||||
FatalErrorIn("findNonEmptyPatch() const")
|
||||
FatalErrorIn("fvMeshDistribute::findNonEmptyPatch() const")
|
||||
<< "Processor patches should be at end of patch list."
|
||||
<< endl
|
||||
<< "Have processor patch " << procPatchI
|
||||
@ -328,7 +337,7 @@ Foam::label Foam::fvMeshDistribute::addProcPatch
|
||||
|
||||
if (polyPatches.findPatchID(patchName) != -1)
|
||||
{
|
||||
FatalErrorIn("addProcPatch(const word&, const label)")
|
||||
FatalErrorIn("fvMeshDistribute::addProcPatch(const word&, const label)")
|
||||
<< "Cannot create patch " << patchName << " since already exists."
|
||||
<< nl
|
||||
<< "Current patch names:" << polyPatches.names()
|
||||
@ -385,7 +394,7 @@ void Foam::fvMeshDistribute::deleteTrailingPatch()
|
||||
|
||||
if (polyPatches.size() == 0)
|
||||
{
|
||||
FatalErrorIn("deleteTrailingPatch(fvMesh&)")
|
||||
FatalErrorIn("fvMeshDistribute::deleteTrailingPatch(fvMesh&)")
|
||||
<< "No patches in mesh"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
@ -403,7 +412,7 @@ void Foam::fvMeshDistribute::deleteTrailingPatch()
|
||||
|
||||
if (nFaces != 0)
|
||||
{
|
||||
FatalErrorIn("deleteTrailingPatch()")
|
||||
FatalErrorIn("fvMeshDistribute::deleteTrailingPatch()")
|
||||
<< "There are still " << nFaces << " faces in patch to be deleted "
|
||||
<< sz-1 << ' ' << polyPatches[sz-1].name()
|
||||
<< abort(FatalError);
|
||||
@ -563,10 +572,6 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::repatch
|
||||
{
|
||||
mesh_.movePoints(map().preMotionPoints());
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh_.clearOut();
|
||||
}
|
||||
|
||||
// Adapt constructMaps.
|
||||
|
||||
@ -639,10 +644,6 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::mergeSharedPoints
|
||||
{
|
||||
mesh_.movePoints(map().preMotionPoints());
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh_.clearOut();
|
||||
}
|
||||
|
||||
// Adapt constructMaps for merged points.
|
||||
// 1.4.1: use reversePointMap < -1 feature.
|
||||
@ -975,10 +976,6 @@ Foam::autoPtr<Foam::mapPolyMesh> Foam::fvMeshDistribute::doRemoveCells
|
||||
{
|
||||
mesh_.movePoints(map().preMotionPoints());
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh_.clearOut();
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
@ -1468,6 +1465,7 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
|
||||
// during topo changes and we have to guarantee that all the fields
|
||||
// can be sent.
|
||||
mesh_.clearOut();
|
||||
mesh_.resetMotion();
|
||||
|
||||
const wordList volScalars(mesh_.names(volScalarField::typeName));
|
||||
checkEqualWordList(volScalars);
|
||||
|
||||
@ -36,6 +36,54 @@ License
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
//- Calculate the offset to the next layer
|
||||
Foam::tmp<Foam::vectorField> Foam::layerAdditionRemoval::extrusionDir() const
|
||||
{
|
||||
const polyMesh& mesh = topoChanger().mesh();
|
||||
const primitiveFacePatch& masterFaceLayer =
|
||||
mesh.faceZones()[faceZoneID_.index()]();
|
||||
|
||||
const pointField& points = mesh.points();
|
||||
const labelList& mp = masterFaceLayer.meshPoints();
|
||||
|
||||
tmp<vectorField> textrusionDir(new vectorField(mp.size()));
|
||||
vectorField& extrusionDir = textrusionDir();
|
||||
|
||||
if (setLayerPairing())
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "void layerAdditionRemoval::extrusionDir() const "
|
||||
<< " for object " << name() << " : "
|
||||
<< "Using edges for point insertion" << endl;
|
||||
}
|
||||
|
||||
// Detected a valid layer. Grab the point and face collapse mapping
|
||||
const labelList& ptc = pointsPairing();
|
||||
|
||||
forAll (extrusionDir, mpI)
|
||||
{
|
||||
extrusionDir[mpI] = points[ptc[mpI]] - points[mp[mpI]];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "void layerAdditionRemoval::extrusionDir() const "
|
||||
<< " for object " << name() << " : "
|
||||
<< "A valid layer could not be found in front of "
|
||||
<< "the addition face layer. Using face-based "
|
||||
<< "point normals for point addition"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
extrusionDir = minLayerThickness_*masterFaceLayer.pointNormals();
|
||||
}
|
||||
return textrusionDir;
|
||||
}
|
||||
|
||||
|
||||
void Foam::layerAdditionRemoval::addCellLayer
|
||||
(
|
||||
polyTopoChange& ref
|
||||
@ -71,43 +119,9 @@ void Foam::layerAdditionRemoval::addCellLayer
|
||||
const pointField& points = mesh.points();
|
||||
const labelList& mp = masterFaceLayer.meshPoints();
|
||||
|
||||
// Calculation of point normals, using point pairing
|
||||
// Get the extrusion direction for the added points
|
||||
|
||||
vectorField extrusionDir(mp.size());
|
||||
|
||||
if (setLayerPairing())
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "void layerAdditionRemoval::addCellLayer("
|
||||
<< "polyTopoChange& ref) const "
|
||||
<< " for object " << name() << " : "
|
||||
<< "Using edges for point insertion" << endl;
|
||||
}
|
||||
|
||||
// Detected a valid layer. Grab the point and face collapse mapping
|
||||
const labelList& ptc = pointsPairing();
|
||||
|
||||
forAll (extrusionDir, mpI)
|
||||
{
|
||||
extrusionDir[mpI] = points[ptc[mpI]] - points[mp[mpI]];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "void layerAdditionRemoval::addCellLayer("
|
||||
<< "polyTopoChange& ref) const "
|
||||
<< " for object " << name() << " : "
|
||||
<< "A valid layer could not be found in front of "
|
||||
<< "the addition face layer. Using face-based "
|
||||
<< "point normals for point addition"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
extrusionDir = minLayerThickness_*masterFaceLayer.pointNormals();
|
||||
}
|
||||
tmp<vectorField> tpointOffsets = extrusionDir();
|
||||
|
||||
// Add the new points
|
||||
labelList addedPoints(mp.size());
|
||||
@ -122,8 +136,7 @@ void Foam::layerAdditionRemoval::addCellLayer
|
||||
polyAddPoint
|
||||
(
|
||||
points[mp[pointI]] // point
|
||||
// + addDelta_*maxLayerThickness_*extrusionDir[pointI],
|
||||
+ addDelta_*extrusionDir[pointI],
|
||||
+ addDelta_*tpointOffsets()[pointI],
|
||||
mp[pointI], // master point
|
||||
-1, // zone for point
|
||||
true // supports a cell
|
||||
|
||||
@ -197,11 +197,8 @@ bool Foam::layerAdditionRemoval::changeTopology() const
|
||||
// Layer removal:
|
||||
// When the min thickness falls below the threshold, trigger removal.
|
||||
|
||||
const labelList& mc =
|
||||
topoChanger().mesh().faceZones()[faceZoneID_.index()].masterCells();
|
||||
|
||||
const labelList& mf = topoChanger().mesh().faceZones()[faceZoneID_.index()];
|
||||
|
||||
const faceZone& fz = topoChanger().mesh().faceZones()[faceZoneID_.index()];
|
||||
const labelList& mc = fz.masterCells();
|
||||
|
||||
const scalarField& V = topoChanger().mesh().cellVolumes();
|
||||
const vectorField& S = topoChanger().mesh().faceAreas();
|
||||
@ -218,17 +215,62 @@ bool Foam::layerAdditionRemoval::changeTopology() const
|
||||
scalar minDelta = GREAT;
|
||||
scalar maxDelta = 0;
|
||||
|
||||
scalar curDelta;
|
||||
|
||||
forAll (mf, faceI)
|
||||
forAll (fz, faceI)
|
||||
{
|
||||
curDelta = V[mc[faceI]]/mag(S[mf[faceI]]);
|
||||
scalar curDelta = V[mc[faceI]]/mag(S[fz[faceI]]);
|
||||
avgDelta += curDelta;
|
||||
minDelta = min(minDelta, curDelta);
|
||||
maxDelta = max(maxDelta, curDelta);
|
||||
}
|
||||
|
||||
avgDelta /= mf.size();
|
||||
avgDelta /= fz.size();
|
||||
|
||||
////MJ Alternative thickness determination
|
||||
//{
|
||||
// // Edges on layer.
|
||||
// const Map<label>& zoneMeshPointMap = fz().meshPointMap();
|
||||
//
|
||||
// label nDelta = 0;
|
||||
//
|
||||
// // Edges with only one point on zone
|
||||
// const polyMesh& mesh = topoChanger().mesh();
|
||||
//
|
||||
// forAll(mc, faceI)
|
||||
// {
|
||||
// const cell& cFaces = mesh.cells()[mc[faceI]];
|
||||
// const edgeList cellEdges(cFaces.edges(mesh.faces()));
|
||||
//
|
||||
// forAll(cellEdges, i)
|
||||
// {
|
||||
// const edge& e = cellEdges[i];
|
||||
//
|
||||
// if (zoneMeshPointMap.found(e[0]))
|
||||
// {
|
||||
// if (!zoneMeshPointMap.found(e[1]))
|
||||
// {
|
||||
// scalar curDelta = e.mag(mesh.points());
|
||||
// avgDelta += curDelta;
|
||||
// nDelta++;
|
||||
// minDelta = min(minDelta, curDelta);
|
||||
// maxDelta = max(maxDelta, curDelta);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (zoneMeshPointMap.found(e[1]))
|
||||
// {
|
||||
// scalar curDelta = e.mag(mesh.points());
|
||||
// avgDelta += curDelta;
|
||||
// nDelta++;
|
||||
// minDelta = min(minDelta, curDelta);
|
||||
// maxDelta = max(maxDelta, curDelta);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// avgDelta /= nDelta;
|
||||
//}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
|
||||
@ -109,6 +109,9 @@ class layerAdditionRemoval
|
||||
//- Return faces pairing in a layer (not automatic!)
|
||||
const labelList& facesPairing() const;
|
||||
|
||||
//- Calculate the offset to the next layer
|
||||
tmp<vectorField> extrusionDir() const;
|
||||
|
||||
//- Add a layer of cells
|
||||
void addCellLayer(polyTopoChange&) const;
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ bool Foam::layerAdditionRemoval::validCollapse() const
|
||||
<< nBoundaryHits << endl;
|
||||
}
|
||||
|
||||
if (nBoundaryHits > 0)
|
||||
if (returnReduce(nBoundaryHits, sumOp<label>()) > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -157,6 +157,9 @@ bool Foam::layerAdditionRemoval::setLayerPairing() const
|
||||
// Pout << "ptc: " << ptc << endl;
|
||||
}
|
||||
|
||||
reduce(nPointErrors, sumOp<label>());
|
||||
reduce(nFaceErrors, sumOp<label>());
|
||||
|
||||
if (nPointErrors > 0 || nFaceErrors > 0)
|
||||
{
|
||||
clearAddressing();
|
||||
|
||||
@ -566,7 +566,8 @@ void Foam::motionSmoother::setDisplacement(pointField& patchDisp)
|
||||
displacement_[ppMeshPoints[patchPointI]] = patchDisp[patchPointI];
|
||||
}
|
||||
|
||||
// Copy internal point data to boundaryField for all affected patches
|
||||
// Adapt the fixedValue bc's (i.e. copy internal point data to
|
||||
// boundaryField for all affected patches)
|
||||
forAll(adaptPatchIDs_, i)
|
||||
{
|
||||
label patchI = adaptPatchIDs_[i];
|
||||
@ -615,6 +616,17 @@ void Foam::motionSmoother::setDisplacement(pointField& patchDisp)
|
||||
false // no separation
|
||||
);
|
||||
|
||||
// Adapt the fixedValue bc's (i.e. copy internal point data to
|
||||
// boundaryField for all affected patches) to take the changes caused
|
||||
// by multi-corner constraints into account.
|
||||
forAll(adaptPatchIDs_, i)
|
||||
{
|
||||
label patchI = adaptPatchIDs_[i];
|
||||
|
||||
displacement_.boundaryField()[patchI] ==
|
||||
displacement_.boundaryField()[patchI].patchInternalField();
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
OFstream str(mesh_.db().path()/"changedPoints.obj");
|
||||
@ -797,6 +809,25 @@ bool Foam::motionSmoother::scaleMesh
|
||||
const bool smoothMesh,
|
||||
const label nAllowableErrors
|
||||
)
|
||||
{
|
||||
List<labelPair> emptyBaffles;
|
||||
return scaleMesh
|
||||
(
|
||||
checkFaces,
|
||||
emptyBaffles,
|
||||
smoothMesh,
|
||||
nAllowableErrors
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::motionSmoother::scaleMesh
|
||||
(
|
||||
labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
const bool smoothMesh,
|
||||
const label nAllowableErrors
|
||||
)
|
||||
{
|
||||
if (!smoothMesh && adaptPatchIDs_.size() == 0)
|
||||
{
|
||||
@ -832,7 +863,7 @@ bool Foam::motionSmoother::scaleMesh
|
||||
|
||||
const scalar errorReduction =
|
||||
readScalar(paramDict_.lookup("errorReduction"));
|
||||
const scalar nSmoothScale =
|
||||
const label nSmoothScale =
|
||||
readLabel(paramDict_.lookup("nSmoothScale"));
|
||||
|
||||
|
||||
@ -893,7 +924,7 @@ bool Foam::motionSmoother::scaleMesh
|
||||
|
||||
// Check. Returns parallel number of incorrect faces.
|
||||
faceSet wrongFaces(mesh_, "wrongFaces", mesh_.nFaces()/100+100);
|
||||
checkMesh(false, mesh_, paramDict_, checkFaces, wrongFaces);
|
||||
checkMesh(false, mesh_, paramDict_, checkFaces, baffles, wrongFaces);
|
||||
|
||||
if (returnReduce(wrongFaces.size(), sumOp<label>()) <= nAllowableErrors)
|
||||
{
|
||||
|
||||
@ -27,11 +27,11 @@ Class
|
||||
|
||||
Description
|
||||
Given a displacement moves the mesh by scaling the displacement back
|
||||
until there are no more mesh errors.
|
||||
until there are no more mesh errors. Holds displacement field
|
||||
(read upon construction since need boundary conditions) and scaling factor
|
||||
and optional patch number on which to scale back displacement.
|
||||
|
||||
Holds displacement field (read upon construction since need boundary
|
||||
conditions) and scaling factor and optional patch number on which to
|
||||
scale back displacement.
|
||||
E.g.
|
||||
|
||||
E.g.
|
||||
@verbatim
|
||||
@ -60,6 +60,10 @@ Description
|
||||
by resetting the internal displacement to zero before doing anything else.
|
||||
The combine operator used will give preference to non-zero values.
|
||||
|
||||
Note: various routines take baffles. These are sets of boundary faces
|
||||
that are treated as a single internal face. This is a hack used to apply
|
||||
movement to internal faces.
|
||||
|
||||
SourceFiles
|
||||
motionSmoother.C
|
||||
motionSmootherTemplates.C
|
||||
@ -402,6 +406,15 @@ public:
|
||||
const label nAllow = 0
|
||||
);
|
||||
|
||||
//- Move mesh (with baffles) with given scale.
|
||||
bool scaleMesh
|
||||
(
|
||||
labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
const bool smoothMesh = true,
|
||||
const label nAllow = 0
|
||||
);
|
||||
|
||||
//- Update topology
|
||||
void updateMesh();
|
||||
|
||||
@ -428,6 +441,19 @@ public:
|
||||
labelHashSet& wrongFaces
|
||||
);
|
||||
|
||||
//- Check (subset of mesh including baffles) with mesh settings
|
||||
// in dict. Collects incorrect faces in set. Returns true if one
|
||||
// or more faces in error. Parallel ok.
|
||||
static bool checkMesh
|
||||
(
|
||||
const bool report,
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet& wrongFaces
|
||||
);
|
||||
|
||||
//- Check part of mesh with mesh settings in dict.
|
||||
// Collects incorrect faces in set. Returns true if one or
|
||||
// more faces in error. Parallel ok.
|
||||
@ -440,6 +466,19 @@ public:
|
||||
labelHashSet& wrongFaces
|
||||
);
|
||||
|
||||
//- Check part of mesh including baffles with mesh settings in dict.
|
||||
// Collects incorrect faces in set. Returns true if one or
|
||||
// more faces in error. Parallel ok.
|
||||
static bool checkMesh
|
||||
(
|
||||
const bool report,
|
||||
const dictionary& dict,
|
||||
const polyMeshGeometry&,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet& wrongFaces
|
||||
);
|
||||
|
||||
// Helper functions to manipulate displacement vector.
|
||||
|
||||
////- Point-jacobi smoothing of internal points
|
||||
|
||||
@ -51,6 +51,28 @@ bool Foam::motionSmoother::checkMesh
|
||||
const labelList& checkFaces,
|
||||
labelHashSet& wrongFaces
|
||||
)
|
||||
{
|
||||
List<labelPair> emptyBaffles;
|
||||
return checkMesh
|
||||
(
|
||||
report,
|
||||
mesh,
|
||||
dict,
|
||||
checkFaces,
|
||||
emptyBaffles,
|
||||
wrongFaces
|
||||
);
|
||||
}
|
||||
|
||||
bool Foam::motionSmoother::checkMesh
|
||||
(
|
||||
const bool report,
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet& wrongFaces
|
||||
)
|
||||
{
|
||||
const scalar maxNonOrtho(readScalar(dict.lookup("maxNonOrtho")));
|
||||
const scalar minVol(readScalar(dict.lookup("minVol")));
|
||||
@ -79,6 +101,7 @@ bool Foam::motionSmoother::checkMesh
|
||||
mesh.cellCentres(),
|
||||
mesh.faceAreas(),
|
||||
checkFaces,
|
||||
baffles,
|
||||
&wrongFaces
|
||||
);
|
||||
|
||||
@ -102,6 +125,7 @@ bool Foam::motionSmoother::checkMesh
|
||||
mesh.cellCentres(),
|
||||
mesh.points(),
|
||||
checkFaces,
|
||||
baffles,
|
||||
&wrongFaces
|
||||
);
|
||||
|
||||
@ -171,6 +195,7 @@ bool Foam::motionSmoother::checkMesh
|
||||
mesh.faceCentres(),
|
||||
mesh.faceAreas(),
|
||||
checkFaces,
|
||||
baffles,
|
||||
&wrongFaces
|
||||
);
|
||||
|
||||
@ -195,6 +220,7 @@ bool Foam::motionSmoother::checkMesh
|
||||
mesh.faceCentres(),
|
||||
mesh.faceAreas(),
|
||||
checkFaces,
|
||||
baffles,
|
||||
&wrongFaces
|
||||
);
|
||||
|
||||
@ -217,6 +243,7 @@ bool Foam::motionSmoother::checkMesh
|
||||
mesh,
|
||||
mesh.cellVolumes(),
|
||||
checkFaces,
|
||||
baffles,
|
||||
&wrongFaces
|
||||
);
|
||||
|
||||
@ -329,6 +356,28 @@ bool Foam::motionSmoother::checkMesh
|
||||
);
|
||||
}
|
||||
|
||||
bool Foam::motionSmoother::checkMesh
|
||||
(
|
||||
const bool report,
|
||||
const dictionary& dict,
|
||||
const polyMeshGeometry& meshGeom,
|
||||
const labelList& checkFaces,
|
||||
labelHashSet& wrongFaces
|
||||
)
|
||||
{
|
||||
List<labelPair> emptyBaffles;
|
||||
|
||||
return checkMesh
|
||||
(
|
||||
report,
|
||||
dict,
|
||||
meshGeom,
|
||||
checkFaces,
|
||||
emptyBaffles,
|
||||
wrongFaces
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::motionSmoother::checkMesh
|
||||
(
|
||||
@ -336,6 +385,7 @@ bool Foam::motionSmoother::checkMesh
|
||||
const dictionary& dict,
|
||||
const polyMeshGeometry& meshGeom,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet& wrongFaces
|
||||
)
|
||||
{
|
||||
@ -363,6 +413,7 @@ bool Foam::motionSmoother::checkMesh
|
||||
report,
|
||||
maxNonOrtho,
|
||||
checkFaces,
|
||||
baffles,
|
||||
&wrongFaces
|
||||
);
|
||||
|
||||
@ -384,6 +435,7 @@ bool Foam::motionSmoother::checkMesh
|
||||
minVol,
|
||||
meshGeom.mesh().points(),
|
||||
checkFaces,
|
||||
baffles,
|
||||
&wrongFaces
|
||||
);
|
||||
|
||||
@ -439,6 +491,7 @@ bool Foam::motionSmoother::checkMesh
|
||||
maxIntSkew,
|
||||
maxBounSkew,
|
||||
checkFaces,
|
||||
baffles,
|
||||
&wrongFaces
|
||||
);
|
||||
|
||||
@ -459,6 +512,7 @@ bool Foam::motionSmoother::checkMesh
|
||||
report,
|
||||
minWeight,
|
||||
checkFaces,
|
||||
baffles,
|
||||
&wrongFaces
|
||||
);
|
||||
|
||||
@ -479,6 +533,7 @@ bool Foam::motionSmoother::checkMesh
|
||||
report,
|
||||
minVolRatio,
|
||||
checkFaces,
|
||||
baffles,
|
||||
&wrongFaces
|
||||
);
|
||||
|
||||
|
||||
@ -209,7 +209,7 @@ Foam::tmp<Foam::GeometricField<Type, Foam::pointPatchField, Foam::pointMesh> >
|
||||
|
||||
forAll(patches, patchI)
|
||||
{
|
||||
if (isA<processorPolyPatch>(patches[patchI]))
|
||||
if (Pstream::parRun() && isA<processorPolyPatch>(patches[patchI]))
|
||||
{
|
||||
const processorPolyPatch& pp =
|
||||
refCast<const processorPolyPatch>(patches[patchI]);
|
||||
|
||||
@ -310,10 +310,7 @@ Foam::scalar Foam::polyMeshGeometry::calcSkewness
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct from components
|
||||
Foam::polyMeshGeometry::polyMeshGeometry
|
||||
(
|
||||
const polyMesh& mesh
|
||||
)
|
||||
Foam::polyMeshGeometry::polyMeshGeometry(const polyMesh& mesh)
|
||||
:
|
||||
mesh_(mesh)
|
||||
{
|
||||
@ -358,6 +355,7 @@ bool Foam::polyMeshGeometry::checkFaceDotProduct
|
||||
const vectorField& cellCentres,
|
||||
const vectorField& faceAreas,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
)
|
||||
{
|
||||
@ -453,6 +451,36 @@ bool Foam::polyMeshGeometry::checkFaceDotProduct
|
||||
}
|
||||
}
|
||||
|
||||
forAll(baffles, i)
|
||||
{
|
||||
label face0 = baffles[i].first();
|
||||
label face1 = baffles[i].second();
|
||||
|
||||
const point& ownCc = cellCentres[own[face0]];
|
||||
|
||||
scalar dDotS = checkNonOrtho
|
||||
(
|
||||
mesh,
|
||||
report,
|
||||
severeNonorthogonalityThreshold,
|
||||
face0,
|
||||
faceAreas[face0],
|
||||
cellCentres[own[face1]] - ownCc,
|
||||
|
||||
severeNonOrth,
|
||||
errorNonOrth,
|
||||
setPtr
|
||||
);
|
||||
|
||||
if (dDotS < minDDotS)
|
||||
{
|
||||
minDDotS = dDotS;
|
||||
}
|
||||
|
||||
sumDDotS += dDotS;
|
||||
nDDotS++;
|
||||
}
|
||||
|
||||
reduce(minDDotS, minOp<scalar>());
|
||||
reduce(sumDDotS, sumOp<scalar>());
|
||||
reduce(nDDotS, sumOp<label>());
|
||||
@ -515,6 +543,7 @@ bool Foam::polyMeshGeometry::checkFacePyramids
|
||||
const vectorField& cellCentres,
|
||||
const pointField& p,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
)
|
||||
{
|
||||
@ -594,6 +623,74 @@ bool Foam::polyMeshGeometry::checkFacePyramids
|
||||
}
|
||||
}
|
||||
|
||||
forAll(baffles, i)
|
||||
{
|
||||
label face0 = baffles[i].first();
|
||||
label face1 = baffles[i].second();
|
||||
|
||||
const point& ownCc = cellCentres[own[face0]];
|
||||
|
||||
// Create the owner pyramid - it will have negative volume
|
||||
scalar pyrVolOwn = pyramidPointFaceRef
|
||||
(
|
||||
f[face0],
|
||||
ownCc
|
||||
).mag(p);
|
||||
|
||||
if (pyrVolOwn > -minPyrVol)
|
||||
{
|
||||
if (report)
|
||||
{
|
||||
Pout<< "bool polyMeshGeometry::checkFacePyramids("
|
||||
<< "const bool, const scalar, const pointField&"
|
||||
<< ", const labelList&, labelHashSet*): "
|
||||
<< "face " << face0 << " points the wrong way. " << endl
|
||||
<< "Pyramid volume: " << -pyrVolOwn
|
||||
<< " Face " << f[face0] << " area: " << f[face0].mag(p)
|
||||
<< " Owner cell: " << own[face0] << endl
|
||||
<< "Owner cell vertex labels: "
|
||||
<< mesh.cells()[own[face0]].labels(f)
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
if (setPtr)
|
||||
{
|
||||
setPtr->insert(face0);
|
||||
}
|
||||
|
||||
nErrorPyrs++;
|
||||
}
|
||||
|
||||
// Create the neighbour pyramid - it will have positive volume
|
||||
scalar pyrVolNbr =
|
||||
pyramidPointFaceRef(f[face0], cellCentres[own[face1]]).mag(p);
|
||||
|
||||
if (pyrVolNbr < minPyrVol)
|
||||
{
|
||||
if (report)
|
||||
{
|
||||
Pout<< "bool polyMeshGeometry::checkFacePyramids("
|
||||
<< "const bool, const scalar, const pointField&"
|
||||
<< ", const labelList&, labelHashSet*): "
|
||||
<< "face " << face0 << " points the wrong way. " << endl
|
||||
<< "Pyramid volume: " << -pyrVolNbr
|
||||
<< " Face " << f[face0] << " area: " << f[face0].mag(p)
|
||||
<< " Neighbour cell: " << own[face1] << endl
|
||||
<< "Neighbour cell vertex labels: "
|
||||
<< mesh.cells()[own[face1]].labels(f)
|
||||
<< endl;
|
||||
}
|
||||
|
||||
if (setPtr)
|
||||
{
|
||||
setPtr->insert(face0);
|
||||
}
|
||||
|
||||
nErrorPyrs++;
|
||||
}
|
||||
}
|
||||
|
||||
reduce(nErrorPyrs, sumOp<label>());
|
||||
|
||||
if (nErrorPyrs > 0)
|
||||
@ -633,6 +730,7 @@ bool Foam::polyMeshGeometry::checkFaceSkewness
|
||||
const vectorField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
)
|
||||
{
|
||||
@ -762,6 +860,43 @@ bool Foam::polyMeshGeometry::checkFaceSkewness
|
||||
}
|
||||
}
|
||||
|
||||
forAll(baffles, i)
|
||||
{
|
||||
label face0 = baffles[i].first();
|
||||
label face1 = baffles[i].second();
|
||||
|
||||
const point& ownCc = cellCentres[own[face0]];
|
||||
|
||||
scalar skewness = calcSkewness
|
||||
(
|
||||
ownCc,
|
||||
cellCentres[own[face1]],
|
||||
faceCentres[face0]
|
||||
);
|
||||
|
||||
// Check if the skewness vector is greater than the PN vector.
|
||||
// This does not cause trouble but is a good indication of a poor
|
||||
// mesh.
|
||||
if (skewness > internalSkew)
|
||||
{
|
||||
if (report)
|
||||
{
|
||||
Pout<< "Severe skewness for face " << face0
|
||||
<< " skewness = " << skewness << endl;
|
||||
}
|
||||
|
||||
if (setPtr)
|
||||
{
|
||||
setPtr->insert(face0);
|
||||
}
|
||||
|
||||
nWarnSkew++;
|
||||
}
|
||||
|
||||
maxSkew = max(maxSkew, skewness);
|
||||
}
|
||||
|
||||
|
||||
reduce(maxSkew, maxOp<scalar>());
|
||||
reduce(nWarnSkew, sumOp<label>());
|
||||
|
||||
@ -804,6 +939,7 @@ bool Foam::polyMeshGeometry::checkFaceWeights
|
||||
const vectorField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
)
|
||||
{
|
||||
@ -889,6 +1025,38 @@ bool Foam::polyMeshGeometry::checkFaceWeights
|
||||
}
|
||||
}
|
||||
|
||||
forAll(baffles, i)
|
||||
{
|
||||
label face0 = baffles[i].first();
|
||||
label face1 = baffles[i].second();
|
||||
|
||||
const point& ownCc = cellCentres[own[face0]];
|
||||
const point& fc = faceCentres[face0];
|
||||
const vector& fa = faceAreas[face0];
|
||||
|
||||
scalar dOwn = mag(fa & (fc-ownCc));
|
||||
scalar dNei = mag(fa & (cellCentres[own[face1]]-fc));
|
||||
scalar weight = min(dNei,dOwn)/(dNei+dOwn+VSMALL);
|
||||
|
||||
if (weight < warnWeight)
|
||||
{
|
||||
if (report)
|
||||
{
|
||||
Pout<< "Small weighting factor for face " << face0
|
||||
<< " weight = " << weight << endl;
|
||||
}
|
||||
|
||||
if (setPtr)
|
||||
{
|
||||
setPtr->insert(face0);
|
||||
}
|
||||
|
||||
nWarnWeight++;
|
||||
}
|
||||
|
||||
minWeight = min(minWeight, weight);
|
||||
}
|
||||
|
||||
reduce(minWeight, minOp<scalar>());
|
||||
reduce(nWarnWeight, sumOp<label>());
|
||||
|
||||
@ -928,6 +1096,7 @@ bool Foam::polyMeshGeometry::checkVolRatio
|
||||
const polyMesh& mesh,
|
||||
const scalarField& cellVolumes,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
)
|
||||
{
|
||||
@ -997,6 +1166,39 @@ bool Foam::polyMeshGeometry::checkVolRatio
|
||||
}
|
||||
}
|
||||
|
||||
forAll(baffles, i)
|
||||
{
|
||||
label face0 = baffles[i].first();
|
||||
label face1 = baffles[i].second();
|
||||
|
||||
scalar ownVol = mag(cellVolumes[own[face0]]);
|
||||
|
||||
scalar neiVol = mag(cellVolumes[own[face1]]);
|
||||
|
||||
if (neiVol >= 0)
|
||||
{
|
||||
scalar ratio = min(ownVol, neiVol) / (max(ownVol, neiVol) + VSMALL);
|
||||
|
||||
if (ratio < warnRatio)
|
||||
{
|
||||
if (report)
|
||||
{
|
||||
Pout<< "Small ratio for face " << face0
|
||||
<< " ratio = " << ratio << endl;
|
||||
}
|
||||
|
||||
if (setPtr)
|
||||
{
|
||||
setPtr->insert(face0);
|
||||
}
|
||||
|
||||
nWarnRatio++;
|
||||
}
|
||||
|
||||
minRatio = min(minRatio, ratio);
|
||||
}
|
||||
}
|
||||
|
||||
reduce(minRatio, minOp<scalar>());
|
||||
reduce(nWarnRatio, sumOp<label>());
|
||||
|
||||
@ -1704,6 +1906,7 @@ bool Foam::polyMeshGeometry::checkFaceDotProduct
|
||||
const bool report,
|
||||
const scalar orthWarn,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
) const
|
||||
{
|
||||
@ -1715,6 +1918,7 @@ bool Foam::polyMeshGeometry::checkFaceDotProduct
|
||||
cellCentres_,
|
||||
faceAreas_,
|
||||
checkFaces,
|
||||
baffles,
|
||||
setPtr
|
||||
);
|
||||
}
|
||||
@ -1726,6 +1930,7 @@ bool Foam::polyMeshGeometry::checkFacePyramids
|
||||
const scalar minPyrVol,
|
||||
const pointField& p,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
) const
|
||||
{
|
||||
@ -1737,6 +1942,7 @@ bool Foam::polyMeshGeometry::checkFacePyramids
|
||||
cellCentres_,
|
||||
p,
|
||||
checkFaces,
|
||||
baffles,
|
||||
setPtr
|
||||
);
|
||||
}
|
||||
@ -1748,6 +1954,7 @@ bool Foam::polyMeshGeometry::checkFaceSkewness
|
||||
const scalar internalSkew,
|
||||
const scalar boundarySkew,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
) const
|
||||
{
|
||||
@ -1761,6 +1968,7 @@ bool Foam::polyMeshGeometry::checkFaceSkewness
|
||||
faceCentres_,
|
||||
faceAreas_,
|
||||
checkFaces,
|
||||
baffles,
|
||||
setPtr
|
||||
);
|
||||
}
|
||||
@ -1771,6 +1979,7 @@ bool Foam::polyMeshGeometry::checkFaceWeights
|
||||
const bool report,
|
||||
const scalar warnWeight,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
) const
|
||||
{
|
||||
@ -1783,6 +1992,7 @@ bool Foam::polyMeshGeometry::checkFaceWeights
|
||||
faceCentres_,
|
||||
faceAreas_,
|
||||
checkFaces,
|
||||
baffles,
|
||||
setPtr
|
||||
);
|
||||
}
|
||||
@ -1793,6 +2003,7 @@ bool Foam::polyMeshGeometry::checkVolRatio
|
||||
const bool report,
|
||||
const scalar warnRatio,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
) const
|
||||
{
|
||||
@ -1803,6 +2014,7 @@ bool Foam::polyMeshGeometry::checkVolRatio
|
||||
mesh_,
|
||||
cellVolumes_,
|
||||
checkFaces,
|
||||
baffles,
|
||||
setPtr
|
||||
);
|
||||
}
|
||||
|
||||
@ -178,6 +178,7 @@ public:
|
||||
const vectorField& cellCentres,
|
||||
const vectorField& faceAreas,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
);
|
||||
|
||||
@ -190,6 +191,7 @@ public:
|
||||
const vectorField& cellCentres,
|
||||
const pointField& p,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet*
|
||||
);
|
||||
|
||||
@ -204,6 +206,7 @@ public:
|
||||
const vectorField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
);
|
||||
|
||||
@ -217,6 +220,7 @@ public:
|
||||
const vectorField& faceCentres,
|
||||
const vectorField& faceAreas,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
);
|
||||
|
||||
@ -228,6 +232,7 @@ public:
|
||||
const polyMesh& mesh,
|
||||
const scalarField& cellVolumes,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
);
|
||||
|
||||
@ -302,6 +307,7 @@ public:
|
||||
const bool report,
|
||||
const scalar orthWarn,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
) const;
|
||||
|
||||
@ -311,6 +317,7 @@ public:
|
||||
const scalar minPyrVol,
|
||||
const pointField& p,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
) const;
|
||||
|
||||
@ -320,6 +327,7 @@ public:
|
||||
const scalar internalSkew,
|
||||
const scalar boundarySkew,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
) const;
|
||||
|
||||
@ -328,6 +336,7 @@ public:
|
||||
const bool report,
|
||||
const scalar warnWeight,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
) const;
|
||||
|
||||
@ -336,6 +345,7 @@ public:
|
||||
const bool report,
|
||||
const scalar warnRatio,
|
||||
const labelList& checkFaces,
|
||||
const List<labelPair>& baffles,
|
||||
labelHashSet* setPtr
|
||||
) const;
|
||||
|
||||
|
||||
@ -136,7 +136,7 @@ void Foam::motionSolver::twoDCorrectPoints(pointField& p) const
|
||||
}
|
||||
|
||||
|
||||
void Foam::motionSolver::updateMesh()
|
||||
void Foam::motionSolver::updateMesh(const mapPolyMesh& mpm)
|
||||
{
|
||||
twoDPointCorrector_.updateMesh();
|
||||
}
|
||||
|
||||
@ -47,6 +47,7 @@ namespace Foam
|
||||
|
||||
// Forward class declarations
|
||||
class polyMesh;
|
||||
class mapPolyMesh;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class motionSolver Declaration
|
||||
@ -122,7 +123,7 @@ public:
|
||||
virtual void solve() = 0;
|
||||
|
||||
//- Update topology
|
||||
virtual void updateMesh();
|
||||
virtual void updateMesh(const mapPolyMesh&) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -1699,6 +1699,7 @@ Foam::autoPtr<Foam::mapAddedPolyMesh> Foam::polyMeshAdder::add
|
||||
labelList patchSizes(getPatchSizes(allPatches));
|
||||
labelList patchStarts(getPatchStarts(allPatches));
|
||||
|
||||
mesh0.resetMotion(); // delete any oldPoints.
|
||||
mesh0.resetPrimitives
|
||||
(
|
||||
allFaces.size(),
|
||||
|
||||
@ -35,6 +35,7 @@ License
|
||||
#include "polyModifyFace.H"
|
||||
#include "polyAddCell.H"
|
||||
#include "wallPoint.H"
|
||||
#include "globalIndex.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
@ -43,18 +44,88 @@ defineTypeNameAndDebug(Foam::addPatchCellLayer, 0);
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::label Foam::addPatchCellLayer::nbrFace
|
||||
// Calculate global faces per pp edge.
|
||||
Foam::labelListList Foam::addPatchCellLayer::calcGlobalEdgeFaces
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const globalIndex& globalFaces,
|
||||
const indirectPrimitivePatch& pp,
|
||||
const label patchEdgeI,
|
||||
const label patchFaceI
|
||||
const labelList& meshEdges
|
||||
)
|
||||
{
|
||||
const labelList& eFaces = pp.edgeFaces()[patchEdgeI];
|
||||
//// Determine coupled edges just so we don't have to have storage
|
||||
//// for all non-coupled edges.
|
||||
//
|
||||
//PackedList<1> isCoupledEdge(mesh.nEdges(), 0);
|
||||
//
|
||||
//const polyBoundaryMesh& patches = mesh.boundaryMesh();
|
||||
//
|
||||
//forAll(patches, patchI)
|
||||
//{
|
||||
// const polyPatch& pp = patches[patchI];
|
||||
//
|
||||
// if (pp.coupled())
|
||||
// {
|
||||
// const labelList& meshEdges = pp.meshEdges();
|
||||
//
|
||||
// forAll(meshEdges, i)
|
||||
// {
|
||||
// isCoupledEdge.set(meshEdges[i], 1);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
// From mesh edge to global face labels. Sized only for pp edges.
|
||||
labelListList globalEdgeFaces(mesh.nEdges());
|
||||
|
||||
const labelListList& edgeFaces = pp.edgeFaces();
|
||||
|
||||
forAll(edgeFaces, edgeI)
|
||||
{
|
||||
label meshEdgeI = meshEdges[edgeI];
|
||||
|
||||
//if (isCoupledEdge.get(meshEdgeI) == 1)
|
||||
{
|
||||
const labelList& eFaces = edgeFaces[edgeI];
|
||||
|
||||
// Store face and processor as unique tag.
|
||||
labelList& globalEFaces = globalEdgeFaces[meshEdgeI];
|
||||
globalEFaces.setSize(eFaces.size());
|
||||
forAll(eFaces, i)
|
||||
{
|
||||
globalEFaces[i] =
|
||||
globalFaces.toGlobal(pp.addressing()[eFaces[i]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Synchronise across coupled edges.
|
||||
syncTools::syncEdgeList
|
||||
(
|
||||
mesh,
|
||||
globalEdgeFaces,
|
||||
uniqueEqOp(),
|
||||
labelList(), // null value
|
||||
false // no separation
|
||||
);
|
||||
|
||||
// Extract pp part
|
||||
return IndirectList<labelList>(globalEdgeFaces, meshEdges)();
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::addPatchCellLayer::nbrFace
|
||||
(
|
||||
const labelListList& edgeFaces,
|
||||
const label edgeI,
|
||||
const label faceI
|
||||
)
|
||||
{
|
||||
const labelList& eFaces = edgeFaces[edgeI];
|
||||
|
||||
if (eFaces.size() == 2)
|
||||
{
|
||||
return (eFaces[0] != patchFaceI ? eFaces[0] : eFaces[1]);
|
||||
return (eFaces[0] != faceI ? eFaces[0] : eFaces[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -95,8 +166,11 @@ void Foam::addPatchCellLayer::addVertex
|
||||
if (n == 2)
|
||||
{
|
||||
f.setSize(fp);
|
||||
FatalErrorIn("addPatchCellLayer::addVertex")
|
||||
<< "Point " << pointI << " already present in face "
|
||||
FatalErrorIn
|
||||
(
|
||||
"addPatchCellLayer::addVertex(const label, face&"
|
||||
", label&)"
|
||||
) << "Point " << pointI << " already present in face "
|
||||
<< f << abort(FatalError);
|
||||
}
|
||||
}
|
||||
@ -110,9 +184,10 @@ void Foam::addPatchCellLayer::addVertex
|
||||
bool Foam::addPatchCellLayer::sameEdgeNeighbour
|
||||
(
|
||||
const indirectPrimitivePatch& pp,
|
||||
const labelListList& globalEdgeFaces,
|
||||
const boolList& doneEdge,
|
||||
const label thisFaceI,
|
||||
const label nbrFaceI,
|
||||
const label thisGlobalFaceI,
|
||||
const label nbrGlobalFaceI,
|
||||
const label edgeI
|
||||
) const
|
||||
{
|
||||
@ -124,24 +199,29 @@ bool Foam::addPatchCellLayer::sameEdgeNeighbour
|
||||
addedPoints_[e[0]].size() != 0 // is extruded
|
||||
|| addedPoints_[e[1]].size() != 0
|
||||
)
|
||||
&& nbrFace(pp, edgeI, thisFaceI) == nbrFaceI; // is to same neighbour
|
||||
&& (
|
||||
nbrFace(globalEdgeFaces, edgeI, thisGlobalFaceI)
|
||||
== nbrGlobalFaceI // is to same neighbour
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Get index on face that hasn't been handled yet.
|
||||
void Foam::addPatchCellLayer::getStartEdge
|
||||
// Collect consecutive string of edges that connects the same two
|
||||
// (possibly coupled) faces. Returns -1 if no unvisited edge can be found.
|
||||
// Otherwise returns start and end index in face.
|
||||
Foam::labelPair Foam::addPatchCellLayer::getEdgeString
|
||||
(
|
||||
const indirectPrimitivePatch& pp,
|
||||
const labelListList& globalEdgeFaces,
|
||||
const boolList& doneEdge,
|
||||
const label patchFaceI,
|
||||
label& startFp,
|
||||
label& nbrFaceI
|
||||
const label globalFaceI
|
||||
) const
|
||||
{
|
||||
const labelList& fEdges = pp.faceEdges()[patchFaceI];
|
||||
|
||||
startFp = -1;
|
||||
nbrFaceI = -1;
|
||||
label startFp = -1;
|
||||
label endFp = -1;
|
||||
|
||||
// Get edge that hasn't been done yet but needs extrusion
|
||||
forAll(fEdges, fp)
|
||||
@ -165,9 +245,21 @@ void Foam::addPatchCellLayer::getStartEdge
|
||||
|
||||
if (startFp != -1)
|
||||
{
|
||||
nbrFaceI = nbrFace(pp, fEdges[startFp], patchFaceI);
|
||||
// We found an edge that needs extruding but hasn't been done yet.
|
||||
// Now find the face on the other side
|
||||
label nbrGlobalFaceI = nbrFace
|
||||
(
|
||||
globalEdgeFaces,
|
||||
fEdges[startFp],
|
||||
globalFaceI
|
||||
);
|
||||
|
||||
if (nbrFaceI != -1)
|
||||
if (nbrGlobalFaceI == -1)
|
||||
{
|
||||
// Proper boundary edge. Only extrude single edge.
|
||||
endFp = startFp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search back for edge
|
||||
// - which hasn't been handled yet
|
||||
@ -182,9 +274,10 @@ void Foam::addPatchCellLayer::getStartEdge
|
||||
!sameEdgeNeighbour
|
||||
(
|
||||
pp,
|
||||
globalEdgeFaces,
|
||||
doneEdge,
|
||||
patchFaceI,
|
||||
nbrFaceI,
|
||||
globalFaceI,
|
||||
nbrGlobalFaceI,
|
||||
fEdges[prevFp]
|
||||
)
|
||||
)
|
||||
@ -193,8 +286,34 @@ void Foam::addPatchCellLayer::getStartEdge
|
||||
}
|
||||
startFp = prevFp;
|
||||
}
|
||||
|
||||
// Search forward for end of string
|
||||
endFp = startFp;
|
||||
while(true)
|
||||
{
|
||||
label nextFp = fEdges.fcIndex(endFp);
|
||||
|
||||
if
|
||||
(
|
||||
!sameEdgeNeighbour
|
||||
(
|
||||
pp,
|
||||
globalEdgeFaces,
|
||||
doneEdge,
|
||||
globalFaceI,
|
||||
nbrGlobalFaceI,
|
||||
fEdges[nextFp]
|
||||
)
|
||||
)
|
||||
{
|
||||
break;
|
||||
}
|
||||
endFp = nextFp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return labelPair(startFp, endFp);
|
||||
}
|
||||
|
||||
|
||||
@ -502,23 +621,7 @@ void Foam::addPatchCellLayer::setRefinement
|
||||
const labelList& meshPoints = pp.meshPoints();
|
||||
|
||||
// Precalculate mesh edges for pp.edges.
|
||||
labelList meshEdges(pp.nEdges());
|
||||
|
||||
forAll(meshEdges, patchEdgeI)
|
||||
{
|
||||
const edge& e = pp.edges()[patchEdgeI];
|
||||
|
||||
label v0 = pp.meshPoints()[e[0]];
|
||||
label v1 = pp.meshPoints()[e[1]];
|
||||
meshEdges[patchEdgeI] = meshTools::findEdge
|
||||
(
|
||||
mesh_.edges(),
|
||||
mesh_.pointEdges()[v0],
|
||||
v0,
|
||||
v1
|
||||
);
|
||||
}
|
||||
|
||||
labelList meshEdges(calcMeshEdges(mesh_, pp));
|
||||
|
||||
if (debug)
|
||||
{
|
||||
@ -809,14 +912,16 @@ void Foam::addPatchCellLayer::setRefinement
|
||||
|
||||
for (label i = 0; i < nFaceLayers[patchFaceI]; i++)
|
||||
{
|
||||
// Note: add from cell (owner of patch face) or from face?
|
||||
// for now add from cell so we can map easily.
|
||||
addedCells[patchFaceI][i] = meshMod.setAction
|
||||
(
|
||||
polyAddCell
|
||||
(
|
||||
-1, // master point
|
||||
-1, // master edge
|
||||
meshFaceI, // master face
|
||||
-1, // master cell id
|
||||
-1, // master face
|
||||
mesh_.faceOwner()[meshFaceI], // master cell id
|
||||
ownZoneI // zone for cell
|
||||
)
|
||||
);
|
||||
@ -879,7 +984,7 @@ void Foam::addPatchCellLayer::setRefinement
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get new outside point
|
||||
// Get new outside point
|
||||
label offset =
|
||||
addedPoints_[f[fp]].size()
|
||||
- addedCells[patchFaceI].size();
|
||||
@ -1002,7 +1107,7 @@ void Foam::addPatchCellLayer::setRefinement
|
||||
(
|
||||
nFaceLayers[eFaces[i]],
|
||||
meshEdgeLayers[meshEdgeI]
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1019,85 +1124,88 @@ void Foam::addPatchCellLayer::setRefinement
|
||||
forAll(meshEdges, edgeI)
|
||||
{
|
||||
edgeLayers[edgeI] = meshEdgeLayers[meshEdges[edgeI]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Global indices engine
|
||||
const globalIndex globalFaces(mesh_.nFaces());
|
||||
|
||||
// Get for all pp edgeFaces a unique faceID
|
||||
labelListList globalEdgeFaces
|
||||
(
|
||||
calcGlobalEdgeFaces
|
||||
(
|
||||
mesh_,
|
||||
globalFaces,
|
||||
pp,
|
||||
meshEdges
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// Mark off which edges have been extruded
|
||||
boolList doneEdge(pp.nEdges(), false);
|
||||
|
||||
|
||||
// Create faces. Per face walk connected edges and find string of edges
|
||||
// between the same two faces and extrude string into a single face.
|
||||
forAll(pp, patchFaceI)
|
||||
{
|
||||
const labelList& fEdges = faceEdges[patchFaceI];
|
||||
|
||||
forAll(fEdges, fp)
|
||||
{
|
||||
// Get starting edge that hasn't been done yet.
|
||||
label startFp;
|
||||
label nbrFaceI;
|
||||
getStartEdge
|
||||
// Get string of edges that needs to be extruded as a single face.
|
||||
// Returned as indices in fEdges.
|
||||
labelPair indexPair
|
||||
(
|
||||
pp,
|
||||
doneEdge,
|
||||
patchFaceI,
|
||||
startFp,
|
||||
nbrFaceI
|
||||
getEdgeString
|
||||
(
|
||||
pp,
|
||||
globalEdgeFaces,
|
||||
doneEdge,
|
||||
patchFaceI,
|
||||
globalFaces.toGlobal(pp.addressing()[patchFaceI])
|
||||
)
|
||||
);
|
||||
|
||||
//Pout<< "Found unextruded edges in edges:" << fEdges
|
||||
// << " start:" << indexPair[0]
|
||||
// << " end:" << indexPair[1]
|
||||
// << endl;
|
||||
|
||||
const label startFp = indexPair[0];
|
||||
const label endFp = indexPair[1];
|
||||
|
||||
if (startFp != -1)
|
||||
{
|
||||
label startEdgeI = fEdges[startFp];
|
||||
|
||||
// Extrude edges from indexPair[0] up to indexPair[1]
|
||||
// (note indexPair = indices of edges. There is one more vertex
|
||||
// than edges)
|
||||
const face& f = localFaces[patchFaceI];
|
||||
|
||||
DynamicList<label> stringedVerts(fEdges.size());
|
||||
|
||||
if (nbrFaceI != -1)
|
||||
labelList stringedVerts;
|
||||
if (endFp >= startFp)
|
||||
{
|
||||
// Start walking edge from f[startFp] to f[startFp+1],
|
||||
// crossing to connected edges that have the same neighbour
|
||||
stringedVerts.append(f[startFp]);
|
||||
|
||||
for (label i = 0; i < f.size()-1; i++)
|
||||
{
|
||||
doneEdge[fEdges[startFp]] = true;
|
||||
|
||||
startFp = f.fcIndex(startFp);
|
||||
stringedVerts.append(f[startFp]);
|
||||
|
||||
if
|
||||
(
|
||||
!sameEdgeNeighbour
|
||||
(
|
||||
pp,
|
||||
doneEdge,
|
||||
patchFaceI,
|
||||
nbrFaceI,
|
||||
fEdges[startFp]
|
||||
)
|
||||
)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Pout<< "Betweeen face:" << patchFaceI
|
||||
// << " verts:" << localFaces[patchFaceI]
|
||||
// << " and face:" << nbrFaceI
|
||||
// << " verts:" << localFaces[nbrFaceI]
|
||||
// << " found vertices:" << stringedVerts << endl;
|
||||
stringedVerts.setSize(endFp-startFp+2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// External edge.
|
||||
doneEdge[fEdges[startFp]] = true;
|
||||
stringedVerts.append(f[startFp]);
|
||||
stringedVerts.append(f.nextLabel(startFp));
|
||||
|
||||
//Pout<< "At external edge " << edges[fEdges[startFp]]
|
||||
// << " on face:" << patchFaceI
|
||||
// << " verts:" << localFaces[patchFaceI]
|
||||
// << " found vertices:" << stringedVerts << endl;
|
||||
stringedVerts.setSize(endFp+f.size()-startFp+2);
|
||||
}
|
||||
|
||||
label fp = startFp;
|
||||
|
||||
for (label i = 0; i < stringedVerts.size()-1; i++)
|
||||
{
|
||||
stringedVerts[i] = f[fp];
|
||||
doneEdge[fEdges[fp]] = true;
|
||||
fp = f.fcIndex(fp);
|
||||
}
|
||||
stringedVerts[stringedVerts.size()-1] = f[fp];
|
||||
|
||||
|
||||
// Now stringedVerts contains the vertices in order of face f.
|
||||
// This is consistent with the order if f becomes the owner cell
|
||||
// and nbrFaceI the neighbour cell. Note that the cells get
|
||||
@ -1105,19 +1213,24 @@ void Foam::addPatchCellLayer::setRefinement
|
||||
// because we loop in incrementing order as well we will
|
||||
// always have nbrFaceI > patchFaceI.
|
||||
|
||||
label startEdgeI = fEdges[startFp];
|
||||
|
||||
label meshEdgeI = meshEdges[startEdgeI];
|
||||
|
||||
label numEdgeSideFaces = edgeLayers[startEdgeI];
|
||||
|
||||
for (label i = 0; i < numEdgeSideFaces; i++)
|
||||
{
|
||||
label vEnd = stringedVerts[stringedVerts.size()-1];
|
||||
label vStart = stringedVerts[0];
|
||||
label vEnd = stringedVerts[stringedVerts.size()-1];
|
||||
label vStart = stringedVerts[0];
|
||||
|
||||
// calculate number of points making up a face
|
||||
label newFp = 0;
|
||||
label newFp = 2*stringedVerts.size();
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
// layer 0 gets all the truncation of neighbouring
|
||||
// faces with more layers.
|
||||
if (addedPoints_[vEnd].size() != 0)
|
||||
{
|
||||
newFp +=
|
||||
@ -1128,11 +1241,6 @@ void Foam::addPatchCellLayer::setRefinement
|
||||
newFp +=
|
||||
addedPoints_[vStart].size() - numEdgeSideFaces;
|
||||
}
|
||||
newFp += 2*stringedVerts.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
newFp += 2*stringedVerts.size();
|
||||
}
|
||||
|
||||
face newFace(newFp);
|
||||
@ -1171,9 +1279,9 @@ void Foam::addPatchCellLayer::setRefinement
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// add points between stringed vertices (end)
|
||||
if (numEdgeSideFaces < addedPoints_[vEnd].size())
|
||||
if (numEdgeSideFaces < addedPoints_[vEnd].size())
|
||||
{
|
||||
if (i == 0 && addedPoints_[vEnd].size() != 0)
|
||||
{
|
||||
@ -1189,8 +1297,8 @@ void Foam::addPatchCellLayer::setRefinement
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
forAllReverse(stringedVerts, stringedI)
|
||||
{
|
||||
label v = stringedVerts[stringedI];
|
||||
@ -1213,7 +1321,7 @@ void Foam::addPatchCellLayer::setRefinement
|
||||
|
||||
|
||||
// add points between stringed vertices (start)
|
||||
if (numEdgeSideFaces < addedPoints_[vStart].size())
|
||||
if (numEdgeSideFaces < addedPoints_[vStart].size())
|
||||
{
|
||||
if (i == 0 && addedPoints_[vStart].size() != 0)
|
||||
{
|
||||
@ -1229,21 +1337,21 @@ void Foam::addPatchCellLayer::setRefinement
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newFace.setSize(newFp);
|
||||
//Pout<< "Betweeen face:" << patchFaceI
|
||||
// << " verts:" << pp[patchFaceI]
|
||||
// << " and face:" << nbrFaceI
|
||||
// << " layer:" << i
|
||||
// << " stringedVerts:" << stringedVerts
|
||||
// << " adding face:" << newFace << endl;
|
||||
}
|
||||
|
||||
if (newFp >= 3)
|
||||
{
|
||||
// Add face inbetween faces patchFaceI and nbrFaceI
|
||||
// (possibly -1 for external edges)
|
||||
|
||||
newFace.setSize(newFp);
|
||||
|
||||
// Add face inbetween faces
|
||||
label nbrFaceI = nbrFace
|
||||
(
|
||||
pp.edgeFaces(),
|
||||
startEdgeI,
|
||||
patchFaceI
|
||||
);
|
||||
|
||||
addSideFace
|
||||
(
|
||||
@ -1330,4 +1438,30 @@ void Foam::addPatchCellLayer::updateMesh
|
||||
}
|
||||
|
||||
|
||||
Foam::labelList Foam::addPatchCellLayer::calcMeshEdges
|
||||
(
|
||||
const primitiveMesh& mesh,
|
||||
const indirectPrimitivePatch& pp
|
||||
)
|
||||
{
|
||||
labelList meshEdges(pp.nEdges());
|
||||
|
||||
forAll(meshEdges, patchEdgeI)
|
||||
{
|
||||
const edge& e = pp.edges()[patchEdgeI];
|
||||
|
||||
label v0 = pp.meshPoints()[e[0]];
|
||||
label v1 = pp.meshPoints()[e[1]];
|
||||
meshEdges[patchEdgeI] = meshTools::findEdge
|
||||
(
|
||||
mesh.edges(),
|
||||
mesh.pointEdges()[v0],
|
||||
v0,
|
||||
v1
|
||||
);
|
||||
}
|
||||
return meshEdges;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -23,30 +23,27 @@ License
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::addPatchCellLayer
|
||||
addPatchCellLayer
|
||||
|
||||
Description
|
||||
Adds layers of cells to outside of polyPatch.
|
||||
|
||||
Call setRefinement with offset vector for every patch point and number
|
||||
of layers per patch face and number of layers per patch point.
|
||||
|
||||
Adds layers of cells to outside of polyPatch. Call setRefinement with
|
||||
offset vector for every patch point and number of layers per patch face
|
||||
and number of layers per patch point.
|
||||
- offset vector should be zero for any non-manifold point and synchronised
|
||||
on coupled points before calling this.
|
||||
on coupled points before calling this.
|
||||
- offset vector of zero will not add any points.
|
||||
- gets supplied the number of extruded layers both per face and per
|
||||
point. Usually the point nlayers is the max of surrounding face nlayers.
|
||||
|
||||
point nlayers:
|
||||
- (0) : no extrusion. Any surrounding face being extruded becomes 'prism'
|
||||
- (>0) : should be max of surrounding face nlayers.
|
||||
0 : no extrusion. Any surrounding face being extruded becomes 'prism'
|
||||
>0 : should be max of surrounding face nlayers.
|
||||
|
||||
- differing face nlayers: 'termination' : (e.g. from 2 to 4 layers) match
|
||||
at original patch face side.
|
||||
|
||||
E.g. 2 boundary faces on patches a,b. 2 layers for a, 3 for b.
|
||||
|
||||
@verbatim
|
||||
Was:
|
||||
|
||||
a b <- patch of boundary face
|
||||
@ -54,6 +51,7 @@ Description
|
||||
| | | <- original cells
|
||||
+------+------+
|
||||
|
||||
|
||||
Becomes:
|
||||
|
||||
a b <- patch of boundary face
|
||||
@ -63,16 +61,15 @@ Description
|
||||
+------+------+
|
||||
| | | <- original cells
|
||||
+------+------+
|
||||
@endverbatim
|
||||
|
||||
|
||||
- added faces get same patchID as face they are extruded from
|
||||
- 'side' faces (i.e. on the edge of pp) get the patchID of the
|
||||
other patch they are connected to.
|
||||
other patch they are connected to.
|
||||
|
||||
|
||||
E.g. 3 boundary faces on patches a,b. b gets extruded, a doesn't.
|
||||
|
||||
@verbatim
|
||||
a b b <- patch of boundary face
|
||||
+------+------+------+
|
||||
| | | | <- cells
|
||||
@ -91,7 +88,6 @@ Description
|
||||
+------+------+------+ 2. side-face gets patch a, not b.
|
||||
| | | |
|
||||
+------+------+------+
|
||||
@endverbatim
|
||||
|
||||
|
||||
SourceFiles
|
||||
@ -104,7 +100,7 @@ SourceFiles
|
||||
|
||||
#include "labelList.H"
|
||||
#include "typeInfo.H"
|
||||
#include "pointField.H"
|
||||
#include "labelPair.H"
|
||||
#include "indirectPrimitivePatch.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
@ -116,6 +112,8 @@ namespace Foam
|
||||
class polyMesh;
|
||||
class polyTopoChange;
|
||||
class mapPolyMesh;
|
||||
class primitiveMesh;
|
||||
class globalIndex;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class addPatchCellLayer Declaration
|
||||
@ -123,6 +121,40 @@ class mapPolyMesh;
|
||||
|
||||
class addPatchCellLayer
|
||||
{
|
||||
// Private classes
|
||||
|
||||
// To combineReduce a labelList. Filters out duplicates.
|
||||
class uniqueEqOp
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
void operator()(labelList& x, const labelList& y) const
|
||||
{
|
||||
if (x.size() == 0)
|
||||
{
|
||||
if (y.size() > 0)
|
||||
{
|
||||
x = y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forAll(y, yi)
|
||||
{
|
||||
if (findIndex(x, y[yi]) == -1)
|
||||
{
|
||||
label sz = x.size();
|
||||
x.setSize(sz+1);
|
||||
x[sz] = y[yi];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Private data
|
||||
|
||||
//- Reference to mesh
|
||||
@ -142,12 +174,22 @@ class addPatchCellLayer
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Per patch edge the pp faces (in global indices) using it. Uses
|
||||
// uniqueEqOp() to remove duplicates.
|
||||
labelListList calcGlobalEdgeFaces
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const globalIndex& globalFaces,
|
||||
const indirectPrimitivePatch& pp,
|
||||
const labelList& meshEdges
|
||||
);
|
||||
|
||||
//- Get the face on the other side of the edge.
|
||||
static label nbrFace
|
||||
(
|
||||
const indirectPrimitivePatch&,
|
||||
const label patchEdgeI,
|
||||
const label patchFaceI
|
||||
const labelListList& edgeFaces,
|
||||
const label edgeI,
|
||||
const label faceI
|
||||
);
|
||||
|
||||
//- Add vertex to face if unique.
|
||||
@ -156,22 +198,23 @@ class addPatchCellLayer
|
||||
bool sameEdgeNeighbour
|
||||
(
|
||||
const indirectPrimitivePatch& pp,
|
||||
const labelListList& globalEdgeFaces,
|
||||
const boolList& doneEdge,
|
||||
const label thisFaceI,
|
||||
const label nbrFaceI,
|
||||
const label thisGlobalFaceI,
|
||||
const label nbrGlobalFaceI,
|
||||
const label edgeI
|
||||
) const;
|
||||
|
||||
//- Get index on face that hasn't been handled yet.
|
||||
void getStartEdge
|
||||
labelPair getEdgeString
|
||||
(
|
||||
const indirectPrimitivePatch& pp,
|
||||
const labelListList& globalEdgeFaces,
|
||||
const boolList& doneEdge,
|
||||
const label patchFaceI,
|
||||
label& startFp,
|
||||
label& nbrFaceI
|
||||
const label globalFaceI
|
||||
) const;
|
||||
|
||||
|
||||
//- Add face between layer-1 and layer.
|
||||
label addSideFace
|
||||
(
|
||||
@ -254,6 +297,8 @@ public:
|
||||
// Note: firstDisplacement has to be parallel synchronised before
|
||||
// calling this routine. Only if all procs sharing a point
|
||||
// get a cell should firstDisplacement be <> 0
|
||||
// Note: cells get added from owner cells of patch faces
|
||||
// (instead of e.g. from patch faces)
|
||||
void setRefinement
|
||||
(
|
||||
const scalar expansionRatio,
|
||||
@ -278,8 +323,8 @@ public:
|
||||
(
|
||||
1.0, // expansion ration
|
||||
pp,
|
||||
labelList(pp.nPoints(), nLayers),
|
||||
labelList(pp.size(), nLayers),
|
||||
labelList(pp.nPoints(), nLayers),
|
||||
overallDisplacement / nLayers,
|
||||
meshMod
|
||||
);
|
||||
@ -295,6 +340,15 @@ public:
|
||||
const labelList& faceMap, // new to old patch faces
|
||||
const labelList& pointMap // new to old patch points
|
||||
);
|
||||
|
||||
// Helper
|
||||
|
||||
//- Per patch edge the corresponding mesh edge
|
||||
static labelList calcMeshEdges
|
||||
(
|
||||
const primitiveMesh& mesh,
|
||||
const indirectPrimitivePatch&
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -280,7 +280,11 @@ Foam::combineFaces::combineFaces
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
undoable_(undoable)
|
||||
undoable_(undoable),
|
||||
masterFace_(0),
|
||||
faceSetsVertices_(0),
|
||||
savedPointLabels_(0),
|
||||
savedPoints_(0)
|
||||
{}
|
||||
|
||||
|
||||
@ -697,47 +701,66 @@ void Foam::combineFaces::setRefinement
|
||||
false // no separation
|
||||
);
|
||||
|
||||
label n = 0;
|
||||
forAll(nPointFaces, pointI)
|
||||
// Remove all unused points. Store position if undoable.
|
||||
if (!undoable_)
|
||||
{
|
||||
if (nPointFaces[pointI] > 0)
|
||||
forAll(nPointFaces, pointI)
|
||||
{
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
savedPoints_.setSize(n);
|
||||
Map<label> meshToSaved(2*n);
|
||||
|
||||
n = 0;
|
||||
forAll(nPointFaces, pointI)
|
||||
{
|
||||
if (nPointFaces[pointI] == 0)
|
||||
{
|
||||
meshMod.setAction(polyRemovePoint(pointI));
|
||||
|
||||
savedPoints_[n] = mesh_.points()[pointI];
|
||||
meshToSaved.insert(pointI, n);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
// Update stored vertex labels. Negative indices index into local points
|
||||
forAll(faceSetsVertices_, setI)
|
||||
{
|
||||
faceList& setFaces = faceSetsVertices_[setI];
|
||||
|
||||
forAll(setFaces, i)
|
||||
{
|
||||
face& f = setFaces[i];
|
||||
|
||||
forAll(f, fp)
|
||||
if (nPointFaces[pointI] == 0)
|
||||
{
|
||||
label pointI = f[fp];
|
||||
meshMod.setAction(polyRemovePoint(pointI));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Count removed points
|
||||
label n = 0;
|
||||
forAll(nPointFaces, pointI)
|
||||
{
|
||||
if (nPointFaces[pointI] == 0)
|
||||
{
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nPointFaces[pointI] == 0)
|
||||
savedPointLabels_.setSize(n);
|
||||
savedPoints_.setSize(n);
|
||||
Map<label> meshToSaved(2*n);
|
||||
|
||||
// Remove points and store position
|
||||
n = 0;
|
||||
forAll(nPointFaces, pointI)
|
||||
{
|
||||
if (nPointFaces[pointI] == 0)
|
||||
{
|
||||
meshMod.setAction(polyRemovePoint(pointI));
|
||||
|
||||
savedPointLabels_[n] = pointI;
|
||||
savedPoints_[n] = mesh_.points()[pointI];
|
||||
|
||||
meshToSaved.insert(pointI, n);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
// Update stored vertex labels. Negative indices index into local points
|
||||
forAll(faceSetsVertices_, setI)
|
||||
{
|
||||
faceList& setFaces = faceSetsVertices_[setI];
|
||||
|
||||
forAll(setFaces, i)
|
||||
{
|
||||
face& f = setFaces[i];
|
||||
|
||||
forAll(f, fp)
|
||||
{
|
||||
f[fp] = -meshToSaved[pointI]-1;
|
||||
label pointI = f[fp];
|
||||
|
||||
if (nPointFaces[pointI] == 0)
|
||||
{
|
||||
f[fp] = -meshToSaved[pointI]-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -749,8 +772,11 @@ void Foam::combineFaces::updateMesh(const mapPolyMesh& map)
|
||||
{
|
||||
if (undoable_)
|
||||
{
|
||||
// Master face just renumbering of point labels
|
||||
inplaceRenumber(map.reverseFaceMap(), masterFace_);
|
||||
|
||||
// Stored faces refer to backed-up vertices (not changed)
|
||||
// and normal vertices (need to be renumbered)
|
||||
forAll(faceSetsVertices_, setI)
|
||||
{
|
||||
faceList& faces = faceSetsVertices_[setI];
|
||||
@ -768,7 +794,7 @@ void Foam::combineFaces::updateMesh(const mapPolyMesh& map)
|
||||
{
|
||||
f[fp] = map.reversePointMap()[pointI];
|
||||
|
||||
if (f[fp] == -1)
|
||||
if (f[fp] < 0)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
@ -796,7 +822,10 @@ void Foam::combineFaces::updateMesh(const mapPolyMesh& map)
|
||||
void Foam::combineFaces::setUnrefinement
|
||||
(
|
||||
const labelList& masterFaces,
|
||||
polyTopoChange& meshMod
|
||||
polyTopoChange& meshMod,
|
||||
Map<label>& restoredPoints,
|
||||
Map<label>& restoredFaces,
|
||||
Map<label>& restoredCells
|
||||
)
|
||||
{
|
||||
if (!undoable_)
|
||||
@ -804,7 +833,8 @@ void Foam::combineFaces::setUnrefinement
|
||||
FatalErrorIn
|
||||
(
|
||||
"combineFaces::setUnrefinement"
|
||||
"(const labelList&, polyTopoChange&)"
|
||||
"(const labelList&, polyTopoChange&"
|
||||
", Map<label>&, Map<label>&, Map<label>&)"
|
||||
) << "Can only call setUnrefinement if constructed with"
|
||||
<< " unrefinement capability." << exit(FatalError);
|
||||
}
|
||||
@ -835,7 +865,8 @@ void Foam::combineFaces::setUnrefinement
|
||||
FatalErrorIn
|
||||
(
|
||||
"combineFaces::setUnrefinement"
|
||||
"(const labelList&, polyTopoChange&)"
|
||||
"(const labelList&, polyTopoChange&"
|
||||
", Map<label>&, Map<label>&, Map<label>&)"
|
||||
) << "Master face " << masterFaceI
|
||||
<< " is not the master of one of the merge sets"
|
||||
<< " or has already been merged"
|
||||
@ -855,7 +886,8 @@ void Foam::combineFaces::setUnrefinement
|
||||
FatalErrorIn
|
||||
(
|
||||
"combineFaces::setUnrefinement"
|
||||
"(const labelList&, polyTopoChange&)"
|
||||
"(const labelList&, polyTopoChange&"
|
||||
", Map<label>&, Map<label>&, Map<label>&)"
|
||||
) << "Set " << setI << " with master face " << masterFaceI
|
||||
<< " has already been merged." << abort(FatalError);
|
||||
}
|
||||
@ -885,6 +917,12 @@ void Foam::combineFaces::setUnrefinement
|
||||
true // supports a cell
|
||||
)
|
||||
);
|
||||
restoredPoints.insert
|
||||
(
|
||||
addedPoints[localI], // current point label
|
||||
savedPointLabels_[localI] // point label when it
|
||||
// was stored
|
||||
);
|
||||
}
|
||||
f[fp] = addedPoints[localI];
|
||||
}
|
||||
@ -910,7 +948,8 @@ void Foam::combineFaces::setUnrefinement
|
||||
FatalErrorIn
|
||||
(
|
||||
"combineFaces::setUnrefinement"
|
||||
"(const labelList&, polyTopoChange&)"
|
||||
"(const labelList&, polyTopoChange&"
|
||||
", Map<label>&, Map<label>&, Map<label>&)"
|
||||
) << "Master face " << masterFaceI << " is on coupled patch "
|
||||
<< mesh_.boundaryMesh()[patchI].name()
|
||||
<< abort(FatalError);
|
||||
|
||||
@ -23,7 +23,7 @@ License
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::combineFaces
|
||||
combineFaces
|
||||
|
||||
Description
|
||||
Combines boundary faces into single face. The faces get the patch
|
||||
@ -70,10 +70,14 @@ class combineFaces
|
||||
//- If undoable: per set the vertices of all the faces in the set.
|
||||
List<faceList> faceSetsVertices_;
|
||||
|
||||
//- If undoable: saved coordinates.
|
||||
//- If undoable: saved point labels.
|
||||
labelList savedPointLabels_;
|
||||
|
||||
//- If undoable: saved coordinates of above points.
|
||||
pointField savedPoints_;
|
||||
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Test if face is convex. Allow slight concavity through
|
||||
@ -109,6 +113,8 @@ class combineFaces
|
||||
const Map<label>& faceRegion
|
||||
) const;
|
||||
|
||||
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
combineFaces(const combineFaces&);
|
||||
|
||||
@ -137,6 +143,12 @@ public:
|
||||
return masterFace_;
|
||||
}
|
||||
|
||||
//- If undoable: set of original point labels of stored points
|
||||
const labelList& savedPointLabels() const
|
||||
{
|
||||
return savedPointLabels_;
|
||||
}
|
||||
|
||||
|
||||
// Helper functions
|
||||
|
||||
@ -168,14 +180,21 @@ public:
|
||||
|
||||
//- Play commands into polyTopoChange to reinsert original faces.
|
||||
// No other topo changes can be done inbetween setRefinement and
|
||||
// setUnrefinement. Gets the master face labels whose sets need
|
||||
// to be restored.
|
||||
// setUnrefinement. Can be called multiple times to undo parts
|
||||
// of the last setRefinement call.
|
||||
// Gets the master face labels whose sets need to be restored.
|
||||
// Returns maps from added restored point to
|
||||
// original point label (i.e. content of savedPointLabels_).
|
||||
// (only restoredPoints are actually set; rest are just for
|
||||
// generalness)
|
||||
void setUnrefinement
|
||||
(
|
||||
const labelList& masterFaces,
|
||||
polyTopoChange& meshMod
|
||||
polyTopoChange& meshMod,
|
||||
Map<label>& restoredPoints,
|
||||
Map<label>& restoredFaces,
|
||||
Map<label>& restoredCells
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -49,6 +49,17 @@ License
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(hexRef8, 0);
|
||||
|
||||
// Reduction class. If x and y are not equal assign value.
|
||||
template< int value >
|
||||
class ifEqEqOp
|
||||
{
|
||||
public:
|
||||
void operator()( label& x, const label& y ) const
|
||||
{
|
||||
x = (x==y) ? x:value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
@ -173,7 +184,7 @@ Foam::label Foam::hexRef8::addFace
|
||||
// Adds an internal face from an edge. Assumes orientation correct.
|
||||
// Problem is that the face is between four new vertices. So what do we provide
|
||||
// as master? The only existing mesh item we have is the edge we have split.
|
||||
// Have to be careful in only using it if it has internal faces since otherwise
|
||||
// Have to be careful in only using it if it has internal faces since otherwise
|
||||
// polyMeshMorph will complain (because it cannot generate a sensible mapping
|
||||
// for the face)
|
||||
Foam::label Foam::hexRef8::addInternalFace
|
||||
@ -267,7 +278,7 @@ Foam::label Foam::hexRef8::addInternalFace
|
||||
// false // face zone flip
|
||||
// )
|
||||
//);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -381,6 +392,18 @@ Foam::scalar Foam::hexRef8::getLevel0EdgeLength() const
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that edges with different levels on different processors
|
||||
// are also marked. Do the same test (edgeLevel != cLevel) on coupled
|
||||
// edges.
|
||||
syncTools::syncEdgeList
|
||||
(
|
||||
mesh_,
|
||||
edgeLevel,
|
||||
ifEqEqOp<labelMax>(),
|
||||
labelMin,
|
||||
false // no separation
|
||||
);
|
||||
|
||||
// Now use the edgeLevel with a valid value to determine the
|
||||
// length per level.
|
||||
forAll(edgeLevel, edgeI)
|
||||
@ -610,7 +633,7 @@ Foam::label Foam::hexRef8::findMinLevel(const labelList& f) const
|
||||
{
|
||||
label minLevel = labelMax;
|
||||
label minFp = -1;
|
||||
|
||||
|
||||
forAll(f, fp)
|
||||
{
|
||||
label level = pointLevel_[f[fp]];
|
||||
@ -631,7 +654,7 @@ Foam::label Foam::hexRef8::findMaxLevel(const labelList& f) const
|
||||
{
|
||||
label maxLevel = labelMin;
|
||||
label maxFp = -1;
|
||||
|
||||
|
||||
forAll(f, fp)
|
||||
{
|
||||
label level = pointLevel_[f[fp]];
|
||||
@ -1690,7 +1713,9 @@ Foam::hexRef8::hexRef8(const polyMesh& mesh)
|
||||
),
|
||||
mesh_.nCells() // All cells visible if could not be read
|
||||
),
|
||||
faceRemover_(mesh_, GREAT) // merge boundary faces wherever possible
|
||||
faceRemover_(mesh_, GREAT), // merge boundary faces wherever possible
|
||||
savedPointLevel_(0),
|
||||
savedCellLevel_(0)
|
||||
{
|
||||
if (history_.active() && history_.visibleCells().size() != mesh_.nCells())
|
||||
{
|
||||
@ -1767,7 +1792,9 @@ Foam::hexRef8::hexRef8
|
||||
),
|
||||
history
|
||||
),
|
||||
faceRemover_(mesh_, GREAT) // merge boundary faces wherever possible
|
||||
faceRemover_(mesh_, GREAT), // merge boundary faces wherever possible
|
||||
savedPointLevel_(0),
|
||||
savedCellLevel_(0)
|
||||
{
|
||||
if (history_.active() && history_.visibleCells().size() != mesh_.nCells())
|
||||
{
|
||||
@ -1845,7 +1872,9 @@ Foam::hexRef8::hexRef8
|
||||
List<refinementHistory::splitCell8>(0),
|
||||
labelList(0)
|
||||
),
|
||||
faceRemover_(mesh_, GREAT) // merge boundary faces wherever possible
|
||||
faceRemover_(mesh_, GREAT), // merge boundary faces wherever possible
|
||||
savedPointLevel_(0),
|
||||
savedCellLevel_(0)
|
||||
{
|
||||
// Check refinement levels for consistency
|
||||
checkRefinementLevels(-1, labelList(0));
|
||||
@ -2188,7 +2217,7 @@ Foam::labelList Foam::hexRef8::consistentSlowRefinement
|
||||
seedFacesInfo.clear();
|
||||
|
||||
// Iterate until no change. Now 2:1 face difference should be satisfied
|
||||
levelCalc.iterate(mesh_.nFaces());
|
||||
levelCalc.iterate(mesh_.globalData().nTotalFaces());
|
||||
|
||||
|
||||
// Now check point-connected cells (face-connected cells already ok):
|
||||
@ -2688,7 +2717,7 @@ Foam::labelList Foam::hexRef8::consistentSlowRefinement2
|
||||
seedFacesInfo,
|
||||
allFaceInfo,
|
||||
allCellInfo,
|
||||
mesh_.nCells()
|
||||
mesh_.globalData().nTotalCells()
|
||||
);
|
||||
|
||||
|
||||
@ -2721,27 +2750,129 @@ Foam::labelList Foam::hexRef8::consistentSlowRefinement2
|
||||
|
||||
|
||||
// Convert back to labelList of cells to refine.
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
DynamicList<label> newCellsToRefine(cellsToRefine.size());
|
||||
// 1. Force original refinement cells to be picked up by setting the
|
||||
// originLevel of input cells to be a very large level (but within range
|
||||
// of 1<< shift inside refinementDistanceData::wantedLevel)
|
||||
forAll(cellsToRefine, i)
|
||||
{
|
||||
label cellI = cellsToRefine[i];
|
||||
|
||||
allCellInfo[cellI].originLevel() = sizeof(label)*8-2;
|
||||
allCellInfo[cellI].origin() = cc[cellI];
|
||||
}
|
||||
|
||||
// 2. Extend to 2:1. I don't understand yet why this is not done
|
||||
PackedList<1> refineCell(mesh_.nCells(), 0);
|
||||
forAll(allCellInfo, cellI)
|
||||
{
|
||||
label wanted =
|
||||
allCellInfo[cellI].wantedLevel(cc[cellI]);
|
||||
label wanted = allCellInfo[cellI].wantedLevel(cc[cellI]);
|
||||
|
||||
if (wanted > cellLevel_[cellI]+1)
|
||||
{
|
||||
newCellsToRefine.append(cellI);
|
||||
refineCell.set(cellI, 1);
|
||||
}
|
||||
}
|
||||
faceConsistentRefinement(true, refineCell);
|
||||
|
||||
// 3. Convert back to labelList.
|
||||
label nRefined = 0;
|
||||
|
||||
forAll(refineCell, cellI)
|
||||
{
|
||||
if (refineCell.get(cellI) == 1)
|
||||
{
|
||||
nRefined++;
|
||||
}
|
||||
}
|
||||
|
||||
newCellsToRefine.shrink();
|
||||
labelList newCellsToRefine(nRefined);
|
||||
nRefined = 0;
|
||||
|
||||
forAll(refineCell, cellI)
|
||||
{
|
||||
if (refineCell.get(cellI) == 1)
|
||||
{
|
||||
newCellsToRefine[nRefined++] = cellI;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "hexRef8::consistentSlowRefinement2 : From "
|
||||
<< cellsToRefine.size() << " to " << newCellsToRefine.size()
|
||||
<< " cells to refine." << endl;
|
||||
|
||||
//XXXX
|
||||
// Check that newCellsToRefine obeys at least 2:1.
|
||||
|
||||
{
|
||||
cellSet cellsIn(mesh_, "cellsToRefineIn", cellsToRefine);
|
||||
Pout<< "hexRef8::consistentSlowRefinement2 : writing "
|
||||
<< cellsIn.size() << " to cellSet "
|
||||
<< cellsIn.objectPath() << endl;
|
||||
cellsIn.write();
|
||||
}
|
||||
{
|
||||
cellSet cellsOut(mesh_, "cellsToRefineOut", newCellsToRefine);
|
||||
Pout<< "hexRef8::consistentSlowRefinement2 : writing "
|
||||
<< cellsOut.size() << " to cellSet "
|
||||
<< cellsOut.objectPath() << endl;
|
||||
cellsOut.write();
|
||||
}
|
||||
|
||||
// Extend to 2:1
|
||||
PackedList<1> refineCell(mesh_.nCells(), 0);
|
||||
forAll(newCellsToRefine, i)
|
||||
{
|
||||
refineCell.set(newCellsToRefine[i], 1);
|
||||
}
|
||||
const PackedList<1> savedRefineCell(refineCell);
|
||||
|
||||
label nChanged = faceConsistentRefinement(true, refineCell);
|
||||
|
||||
{
|
||||
cellSet cellsOut2
|
||||
(
|
||||
mesh_, "cellsToRefineOut2", newCellsToRefine.size()
|
||||
);
|
||||
forAll(refineCell, cellI)
|
||||
{
|
||||
if (refineCell.get(cellI) == 1)
|
||||
{
|
||||
cellsOut2.insert(cellI);
|
||||
}
|
||||
}
|
||||
Pout<< "hexRef8::consistentSlowRefinement2 : writing "
|
||||
<< cellsOut2.size() << " to cellSet "
|
||||
<< cellsOut2.objectPath() << endl;
|
||||
cellsOut2.write();
|
||||
}
|
||||
|
||||
if (nChanged > 0)
|
||||
{
|
||||
forAll(refineCell, cellI)
|
||||
{
|
||||
if
|
||||
(
|
||||
refineCell.get(cellI) == 1
|
||||
&& savedRefineCell.get(cellI) == 0
|
||||
)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"hexRef8::consistentSlowRefinement2"
|
||||
"(const label, const labelList&, const labelList&)"
|
||||
) << "Cell:" << cellI << " cc:"
|
||||
<< mesh_.cellCentres()[cellI]
|
||||
<< " was not marked for refinement but does not obey"
|
||||
<< " 2:1 constraints."
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
//XXXX
|
||||
}
|
||||
|
||||
return newCellsToRefine;
|
||||
@ -2764,6 +2895,10 @@ Foam::labelListList Foam::hexRef8::setRefinement
|
||||
checkRefinementLevels(-1, labelList(0));
|
||||
}
|
||||
|
||||
// Clear any saved point/cell data.
|
||||
savedPointLevel_.clear();
|
||||
savedCellLevel_.clear();
|
||||
|
||||
|
||||
// New point/cell level. Copy of pointLevel for existing points.
|
||||
DynamicList<label> newCellLevel(cellLevel_.size());
|
||||
@ -2849,7 +2984,7 @@ Foam::labelListList Foam::hexRef8::setRefinement
|
||||
// -1 : no need to split edge
|
||||
// >=0 : label of introduced mid point
|
||||
labelList edgeMidPoint(mesh_.nEdges(), -1);
|
||||
|
||||
|
||||
// Note: Loop over cells to be refined or edges?
|
||||
forAll(cellMidPoint, cellI)
|
||||
{
|
||||
@ -3102,7 +3237,7 @@ Foam::labelListList Foam::hexRef8::setRefinement
|
||||
maxEqOp<vector>(),
|
||||
true // apply separation
|
||||
);
|
||||
|
||||
|
||||
forAll(faceMidPoint, faceI)
|
||||
{
|
||||
if (faceMidPoint[faceI] >= 0)
|
||||
@ -3468,7 +3603,7 @@ Foam::labelListList Foam::hexRef8::setRefinement
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!modifiedFace)
|
||||
{
|
||||
@ -3767,10 +3902,50 @@ Foam::labelListList Foam::hexRef8::setRefinement
|
||||
}
|
||||
|
||||
|
||||
void Foam::hexRef8::storeData
|
||||
(
|
||||
const labelList& pointsToStore,
|
||||
const labelList& facesToStore,
|
||||
const labelList& cellsToStore
|
||||
)
|
||||
{
|
||||
savedPointLevel_.resize(2*pointsToStore.size());
|
||||
forAll(pointsToStore, i)
|
||||
{
|
||||
label pointI = pointsToStore[i];
|
||||
savedPointLevel_.insert(pointI, pointLevel_[pointI]);
|
||||
}
|
||||
|
||||
savedCellLevel_.resize(2*cellsToStore.size());
|
||||
forAll(cellsToStore, i)
|
||||
{
|
||||
label cellI = cellsToStore[i];
|
||||
savedCellLevel_.insert(cellI, cellLevel_[cellI]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Gets called after the mesh change. setRefinement will already have made
|
||||
// sure the pointLevel_ and cellLevel_ are the size of the new mesh so we
|
||||
// only need to account for reordering.
|
||||
void Foam::hexRef8::updateMesh(const mapPolyMesh& map)
|
||||
{
|
||||
Map<label> dummyMap(0);
|
||||
|
||||
updateMesh(map, dummyMap, dummyMap, dummyMap);
|
||||
}
|
||||
|
||||
|
||||
// Gets called after the mesh change. setRefinement will already have made
|
||||
// sure the pointLevel_ and cellLevel_ are the size of the new mesh so we
|
||||
// only need to account for reordering.
|
||||
void Foam::hexRef8::updateMesh
|
||||
(
|
||||
const mapPolyMesh& map,
|
||||
const Map<label>& pointsToRestore,
|
||||
const Map<label>& facesToRestore,
|
||||
const Map<label>& cellsToRestore
|
||||
)
|
||||
{
|
||||
// Update celllevel
|
||||
if (debug)
|
||||
@ -3783,26 +3958,90 @@ void Foam::hexRef8::updateMesh(const mapPolyMesh& map)
|
||||
{
|
||||
const labelList& reverseCellMap = map.reverseCellMap();
|
||||
|
||||
// Do not allow anyone outside us adding/removing cells for now.
|
||||
if (reverseCellMap.size() != cellLevel_.size())
|
||||
if (debug)
|
||||
{
|
||||
FatalErrorIn("hexRef8::updateMesh")
|
||||
<< "Problem : size of reverseCellMap " << reverseCellMap.size()
|
||||
<< " does not equal cellLevel " << cellLevel_.size() << nl
|
||||
<< "This means that someone else is modifying the mesh"
|
||||
<< abort(FatalError);
|
||||
Pout<< "hexRef8::updateMesh :"
|
||||
<< " reverseCellMap:" << map.reverseCellMap().size()
|
||||
<< " cellMap:" << map.cellMap().size()
|
||||
<< " nCells:" << mesh_.nCells()
|
||||
<< " nOldCells:" << map.nOldCells()
|
||||
<< " cellLevel_:" << cellLevel_.size()
|
||||
<< " reversePointMap:" << map.reversePointMap().size()
|
||||
<< " pointMap:" << map.pointMap().size()
|
||||
<< " nPoints:" << mesh_.nPoints()
|
||||
<< " nOldPoints:" << map.nOldPoints()
|
||||
<< " pointLevel_:" << pointLevel_.size()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
reorder(reverseCellMap, mesh_.nCells(), -1, cellLevel_);
|
||||
|
||||
if (findIndex(cellLevel_, -1) != -1)
|
||||
if (reverseCellMap.size() == cellLevel_.size())
|
||||
{
|
||||
FatalErrorIn("hexRef8::updateMesh")
|
||||
<< "Problem : "
|
||||
<< "cellLevel_ contains illegal value -1 after mapping:"
|
||||
<< cellLevel_
|
||||
<< abort(FatalError);
|
||||
// Assume it is after hexRef8 that this routine is called.
|
||||
// Just account for reordering. We cannot use cellMap since
|
||||
// then cells created from cells would get cellLevel_ of
|
||||
// cell they were created from.
|
||||
reorder(reverseCellMap, mesh_.nCells(), -1, cellLevel_);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Map data
|
||||
const labelList& cellMap = map.cellMap();
|
||||
|
||||
labelList newCellLevel(cellMap.size());
|
||||
forAll(cellMap, newCellI)
|
||||
{
|
||||
label oldCellI = cellMap[newCellI];
|
||||
|
||||
if (oldCellI == -1)
|
||||
{
|
||||
//FatalErrorIn("hexRef8::updateMesh(const mapPolyMesh&)")
|
||||
// << "Problem : cell " << newCellI
|
||||
// << " at " << mesh_.cellCentres()[newCellI]
|
||||
// << " does not originate from another cell"
|
||||
// << " (i.e. is inflated)." << nl
|
||||
// << "Hence we cannot determine the new cellLevel"
|
||||
// << " for it." << abort(FatalError);
|
||||
newCellLevel[newCellI] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
newCellLevel[newCellI] = cellLevel_[oldCellI];
|
||||
}
|
||||
}
|
||||
cellLevel_.transfer(newCellLevel);
|
||||
}
|
||||
|
||||
// See if any cells to restore. This will be for some new cells
|
||||
// the corresponding old cell.
|
||||
forAllConstIter(Map<label>, cellsToRestore, iter)
|
||||
{
|
||||
label newCellI = iter.key();
|
||||
label storedCellI = iter();
|
||||
|
||||
Map<label>::iterator fnd = savedCellLevel_.find(storedCellI);
|
||||
|
||||
if (fnd == savedCellLevel_.end())
|
||||
{
|
||||
FatalErrorIn("hexRef8::updateMesh(const mapPolyMesh&)")
|
||||
<< "Problem : trying to restore old value for new cell "
|
||||
<< newCellI << " but cannot find old cell " << storedCellI
|
||||
<< " in map of stored values " << savedCellLevel_
|
||||
<< abort(FatalError);
|
||||
}
|
||||
cellLevel_[newCellI] = fnd();
|
||||
}
|
||||
|
||||
//if (findIndex(cellLevel_, -1) != -1)
|
||||
//{
|
||||
// WarningIn("hexRef8::updateMesh(const mapPolyMesh&)")
|
||||
// << "Problem : "
|
||||
// << "cellLevel_ contains illegal value -1 after mapping at cell "
|
||||
// << findIndex(cellLevel_, -1) << endl
|
||||
// << "This means that another program has inflated cells"
|
||||
// << " (created cells out-of-nothing) and hence we don't know"
|
||||
// << " their cell level. Continuing with illegal value."
|
||||
// << abort(FatalError);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
@ -3810,13 +4049,6 @@ void Foam::hexRef8::updateMesh(const mapPolyMesh& map)
|
||||
{
|
||||
const labelList& reversePointMap = map.reversePointMap();
|
||||
|
||||
// This is a bit tricky. If this routine gets called from us the
|
||||
// pointLevel_ is already the correct size and the correct setting
|
||||
// for the added points and we only need to account
|
||||
// for reordering. However if this routine gets called from outside
|
||||
// because someone else has modified the mesh (e.g. splitting baffles)
|
||||
// we have to pull the data across.
|
||||
|
||||
if (reversePointMap.size() == pointLevel_.size())
|
||||
{
|
||||
// Assume it is after hexRef8 that this routine is called.
|
||||
@ -3827,23 +4059,63 @@ void Foam::hexRef8::updateMesh(const mapPolyMesh& map)
|
||||
// Map data
|
||||
const labelList& pointMap = map.pointMap();
|
||||
|
||||
labelList newPointLevel(pointMap.size(), -1);
|
||||
labelList newPointLevel(pointMap.size());
|
||||
|
||||
forAll(pointMap, newPointI)
|
||||
{
|
||||
newPointLevel[newPointI] = pointLevel_[pointMap[newPointI]];
|
||||
label oldPointI = pointMap[newPointI];
|
||||
|
||||
if (oldPointI == -1)
|
||||
{
|
||||
//FatalErrorIn("hexRef8::updateMesh(const mapPolyMesh&)")
|
||||
// << "Problem : point " << newPointI
|
||||
// << " at " << mesh_.points()[newPointI]
|
||||
// << " does not originate from another point"
|
||||
// << " (i.e. is inflated)." << nl
|
||||
// << "Hence we cannot determine the new pointLevel"
|
||||
// << " for it." << abort(FatalError);
|
||||
newPointLevel[newPointI] = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
newPointLevel[newPointI] = pointLevel_[oldPointI];
|
||||
}
|
||||
}
|
||||
pointLevel_.transfer(newPointLevel);
|
||||
}
|
||||
|
||||
if (findIndex(pointLevel_, -1) != -1)
|
||||
// See if any points to restore. This will be for some new points
|
||||
// the corresponding old point (the one from the call to storeData)
|
||||
forAllConstIter(Map<label>, pointsToRestore, iter)
|
||||
{
|
||||
FatalErrorIn("hexRef8::updateMesh")
|
||||
<< "Problem : "
|
||||
<< "pointLevel_ contains illegal value -1 after mapping:"
|
||||
<< pointLevel_
|
||||
<< abort(FatalError);
|
||||
label newPointI = iter.key();
|
||||
label storedPointI = iter();
|
||||
|
||||
Map<label>::iterator fnd = savedPointLevel_.find(storedPointI);
|
||||
|
||||
if (fnd == savedPointLevel_.end())
|
||||
{
|
||||
FatalErrorIn("hexRef8::updateMesh(const mapPolyMesh&)")
|
||||
<< "Problem : trying to restore old value for new point "
|
||||
<< newPointI << " but cannot find old point "
|
||||
<< storedPointI
|
||||
<< " in map of stored values " << savedPointLevel_
|
||||
<< abort(FatalError);
|
||||
}
|
||||
pointLevel_[newPointI] = fnd();
|
||||
}
|
||||
|
||||
//if (findIndex(pointLevel_, -1) != -1)
|
||||
//{
|
||||
// WarningIn("hexRef8::updateMesh(const mapPolyMesh&)")
|
||||
// << "Problem : "
|
||||
// << "pointLevel_ contains illegal value -1 after mapping"
|
||||
// << " at point" << findIndex(pointLevel_, -1) << endl
|
||||
// << "This means that another program has inflated points"
|
||||
// << " (created points out-of-nothing) and hence we don't know"
|
||||
// << " their point level. Continuing with illegal value."
|
||||
// //<< abort(FatalError);
|
||||
//}
|
||||
}
|
||||
|
||||
// Update refinement tree
|
||||
@ -3906,7 +4178,7 @@ void Foam::hexRef8::subset
|
||||
<< "cellLevel_ contains illegal value -1 after mapping:"
|
||||
<< cellLevel_
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update pointlevel
|
||||
@ -3927,7 +4199,7 @@ void Foam::hexRef8::subset
|
||||
<< "pointLevel_ contains illegal value -1 after mapping:"
|
||||
<< pointLevel_
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update refinement tree
|
||||
@ -3973,7 +4245,7 @@ void Foam::hexRef8::distribute(const mapDistributePolyMesh& map)
|
||||
void Foam::hexRef8::checkMesh() const
|
||||
{
|
||||
const boundBox& meshBb = mesh_.globalData().bb();
|
||||
const scalar smallDim = 1E-9*mag(meshBb.max() - meshBb.min());
|
||||
const scalar smallDim = 1E-6*mag(meshBb.max() - meshBb.min());
|
||||
|
||||
if (debug)
|
||||
{
|
||||
@ -4535,12 +4807,12 @@ Foam::labelList Foam::hexRef8::getSplitPoints() const
|
||||
//
|
||||
// if (split.parent_ >= 0)
|
||||
// {
|
||||
// markIndex(maxLevel, level+1, split.parent_, markValue, indexValues);
|
||||
//
|
||||
//
|
||||
// markIndex
|
||||
// (
|
||||
// maxLevel, level+1, split.parent_, markValue, indexValues);
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
//
|
||||
//
|
||||
@ -4781,7 +5053,7 @@ Foam::labelList Foam::hexRef8::consistentUnrefinement
|
||||
|
||||
// Convert back to labelList.
|
||||
label nSet = 0;
|
||||
|
||||
|
||||
forAll(unrefinePoint, pointI)
|
||||
{
|
||||
if (unrefinePoint.get(pointI) == 1)
|
||||
|
||||
@ -74,7 +74,7 @@ class hexRef8
|
||||
//- Per point the refinement level
|
||||
labelIOList pointLevel_;
|
||||
|
||||
//- typcial edge length between unrefined points
|
||||
//- Typical edge length between unrefined points
|
||||
const scalar level0Edge_;
|
||||
|
||||
//- Refinement history
|
||||
@ -83,6 +83,12 @@ class hexRef8
|
||||
//- Face remover engine
|
||||
removeFaces faceRemover_;
|
||||
|
||||
//- Level of saved points
|
||||
Map<label> savedPointLevel_;
|
||||
|
||||
//- Level of saved cells
|
||||
Map<label> savedCellLevel_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
@ -353,6 +359,11 @@ public:
|
||||
return history_;
|
||||
}
|
||||
|
||||
//- Typical edge length between unrefined points
|
||||
scalar level0EdgeLength() const
|
||||
{
|
||||
return level0Edge_;
|
||||
}
|
||||
|
||||
// Refinement
|
||||
|
||||
@ -417,13 +428,39 @@ public:
|
||||
// -midpoints added: added from cellPoints[0].
|
||||
labelListList setRefinement
|
||||
(
|
||||
const labelList& cells,
|
||||
const labelList& cells,
|
||||
polyTopoChange&
|
||||
);
|
||||
|
||||
//- Update local numbering for changed mesh.
|
||||
void updateMesh(const mapPolyMesh&);
|
||||
|
||||
|
||||
// Restoring : is where other processes delete and reinsert data.
|
||||
// These callbacks allow this to restore the cellLevel
|
||||
// and pointLevel for reintroduced points.
|
||||
// Is not related to undoing my refinement
|
||||
|
||||
//- Signal points/face/cells for which to store data
|
||||
void storeData
|
||||
(
|
||||
const labelList& pointsToStore,
|
||||
const labelList& facesToStore,
|
||||
const labelList& cellsToStore
|
||||
);
|
||||
|
||||
//- Update local numbering + undo
|
||||
// Data to restore given as new pointlabel + stored pointlabel
|
||||
// (i.e. what was in pointsToStore)
|
||||
void updateMesh
|
||||
(
|
||||
const mapPolyMesh&,
|
||||
const Map<label>& pointsToRestore,
|
||||
const Map<label>& facesToRestore,
|
||||
const Map<label>& cellsToRestore
|
||||
);
|
||||
|
||||
|
||||
//- Update local numbering for subsetted mesh.
|
||||
// Gets new-to-old maps. Not compatible with unrefinement.
|
||||
void subset
|
||||
|
||||
@ -21,6 +21,8 @@ coordinateSystems/coordinateRotation/coordinateRotation.C
|
||||
coordinateSystems/coordinateRotation/EulerCoordinateRotation.C
|
||||
coordinateSystems/coordinateRotation/STARCDCoordinateRotation.C
|
||||
|
||||
edgeFaceCirculator/edgeFaceCirculator.C
|
||||
|
||||
polyMeshZipUpCells/polyMeshZipUpCells.C
|
||||
primitiveMeshGeometry/primitiveMeshGeometry.C
|
||||
|
||||
@ -116,6 +118,10 @@ triSurface/octreeData/octreeDataTriSurfaceTreeLeaf.C
|
||||
|
||||
triSurface/triangleFuncs/triangleFuncs.C
|
||||
|
||||
triSurface/searchableSurface/searchableSurface.C
|
||||
triSurface/searchableSurface/triSurfaceMesh.C
|
||||
triSurface/searchableSurface/searchableBox.C
|
||||
|
||||
triSurface/surfaceFeatures/surfaceFeatures.C
|
||||
|
||||
triSurface/triSurfaceMeshes/triSurfaceMeshes.C
|
||||
|
||||
@ -433,149 +433,146 @@ void Foam::PointEdgeWave<Type>::updateFromPatchInfo
|
||||
template <class Type>
|
||||
void Foam::PointEdgeWave<Type>::handleProcPatches()
|
||||
{
|
||||
if (Pstream::parRun())
|
||||
const polyMesh& mesh = pMesh_();
|
||||
|
||||
|
||||
// 1. Send all point info on processor patches. Send as
|
||||
// face label + offset in face.
|
||||
|
||||
forAll(mesh.boundaryMesh(), patchI)
|
||||
{
|
||||
const polyMesh& mesh = pMesh_();
|
||||
const polyPatch& patch = mesh.boundaryMesh()[patchI];
|
||||
|
||||
|
||||
// 1. Send all point info on processor patches. Send as
|
||||
// face label + offset in face.
|
||||
|
||||
forAll(mesh.boundaryMesh(), patchI)
|
||||
if (isA<processorPolyPatch>(patch))
|
||||
{
|
||||
const polyPatch& patch = mesh.boundaryMesh()[patchI];
|
||||
// Get all changed points in relative addressing
|
||||
|
||||
if (isA<processorPolyPatch>(patch))
|
||||
{
|
||||
// Get all changed points in relative addressing
|
||||
DynamicList<Type> patchInfo(patch.nPoints());
|
||||
DynamicList<label> patchPoints(patch.nPoints());
|
||||
DynamicList<label> owner(patch.nPoints());
|
||||
DynamicList<label> ownerIndex(patch.nPoints());
|
||||
|
||||
DynamicList<Type> patchInfo(patch.nPoints());
|
||||
DynamicList<label> patchPoints(patch.nPoints());
|
||||
DynamicList<label> owner(patch.nPoints());
|
||||
DynamicList<label> ownerIndex(patch.nPoints());
|
||||
|
||||
getChangedPatchPoints
|
||||
(
|
||||
patch,
|
||||
patchInfo,
|
||||
patchPoints,
|
||||
owner,
|
||||
ownerIndex
|
||||
);
|
||||
|
||||
// Adapt for leaving domain
|
||||
leaveDomain(patch, patch, patchPoints, patchInfo);
|
||||
|
||||
const processorPolyPatch& procPatch =
|
||||
refCast<const processorPolyPatch>(patch);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Processor patch " << patchI << ' ' << patch.name()
|
||||
<< " communicating with " << procPatch.neighbProcNo()
|
||||
<< " Sending:" << patchInfo.size() << endl;
|
||||
}
|
||||
|
||||
{
|
||||
OPstream toNeighbour
|
||||
(
|
||||
Pstream::blocking,
|
||||
procPatch.neighbProcNo()
|
||||
);
|
||||
|
||||
toNeighbour << owner << ownerIndex << patchInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 2. Receive all point info on processor patches.
|
||||
//
|
||||
|
||||
forAll(mesh.boundaryMesh(), patchI)
|
||||
{
|
||||
const polyPatch& patch = mesh.boundaryMesh()[patchI];
|
||||
|
||||
if (isA<processorPolyPatch>(patch))
|
||||
{
|
||||
const processorPolyPatch& procPatch =
|
||||
refCast<const processorPolyPatch>(patch);
|
||||
|
||||
List<Type> patchInfo;
|
||||
labelList owner;
|
||||
labelList ownerIndex;
|
||||
{
|
||||
IPstream fromNeighbour
|
||||
(
|
||||
Pstream::blocking,
|
||||
procPatch.neighbProcNo()
|
||||
);
|
||||
|
||||
fromNeighbour >> owner >> ownerIndex >> patchInfo;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Processor patch " << patchI << ' ' << patch.name()
|
||||
<< " communicating with " << procPatch.neighbProcNo()
|
||||
<< " Received:" << patchInfo.size() << endl;
|
||||
}
|
||||
|
||||
// Apply transform to received data for non-parallel planes
|
||||
if (!procPatch.parallel())
|
||||
{
|
||||
transform(procPatch.reverseT(), patchInfo);
|
||||
}
|
||||
|
||||
updateFromPatchInfo
|
||||
(
|
||||
patch,
|
||||
patch,
|
||||
owner,
|
||||
ownerIndex,
|
||||
patchInfo
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// 3. Handle all shared points
|
||||
// (Note:irrespective if changed or not for now)
|
||||
//
|
||||
|
||||
const globalMeshData& pd = mesh.globalData();
|
||||
|
||||
List<Type> sharedData(pd.nGlobalPoints());
|
||||
|
||||
forAll(pd.sharedPointLabels(), i)
|
||||
{
|
||||
label meshPointI = pd.sharedPointLabels()[i];
|
||||
|
||||
// Fill my entries in the shared points
|
||||
sharedData[pd.sharedPointAddr()[i]] = allPointInfo_[meshPointI];
|
||||
}
|
||||
|
||||
// Combine on master. Reduce operator has to handle a list and call
|
||||
// Type.updatePoint for all elements
|
||||
combineReduce(sharedData, listUpdateOp<Type>());
|
||||
|
||||
forAll(pd.sharedPointLabels(), i)
|
||||
{
|
||||
label meshPointI = pd.sharedPointLabels()[i];
|
||||
|
||||
// Retrieve my entries from the shared points
|
||||
updatePoint
|
||||
getChangedPatchPoints
|
||||
(
|
||||
meshPointI,
|
||||
sharedData[pd.sharedPointAddr()[i]],
|
||||
propagationTol_,
|
||||
allPointInfo_[meshPointI]
|
||||
patch,
|
||||
patchInfo,
|
||||
patchPoints,
|
||||
owner,
|
||||
ownerIndex
|
||||
);
|
||||
|
||||
// Adapt for leaving domain
|
||||
leaveDomain(patch, patch, patchPoints, patchInfo);
|
||||
|
||||
const processorPolyPatch& procPatch =
|
||||
refCast<const processorPolyPatch>(patch);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Processor patch " << patchI << ' ' << patch.name()
|
||||
<< " communicating with " << procPatch.neighbProcNo()
|
||||
<< " Sending:" << patchInfo.size() << endl;
|
||||
}
|
||||
|
||||
{
|
||||
OPstream toNeighbour
|
||||
(
|
||||
Pstream::blocking,
|
||||
procPatch.neighbProcNo()
|
||||
);
|
||||
|
||||
toNeighbour << owner << ownerIndex << patchInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 2. Receive all point info on processor patches.
|
||||
//
|
||||
|
||||
forAll(mesh.boundaryMesh(), patchI)
|
||||
{
|
||||
const polyPatch& patch = mesh.boundaryMesh()[patchI];
|
||||
|
||||
if (isA<processorPolyPatch>(patch))
|
||||
{
|
||||
const processorPolyPatch& procPatch =
|
||||
refCast<const processorPolyPatch>(patch);
|
||||
|
||||
List<Type> patchInfo;
|
||||
labelList owner;
|
||||
labelList ownerIndex;
|
||||
{
|
||||
IPstream fromNeighbour
|
||||
(
|
||||
Pstream::blocking,
|
||||
procPatch.neighbProcNo()
|
||||
);
|
||||
|
||||
fromNeighbour >> owner >> ownerIndex >> patchInfo;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Processor patch " << patchI << ' ' << patch.name()
|
||||
<< " communicating with " << procPatch.neighbProcNo()
|
||||
<< " Received:" << patchInfo.size() << endl;
|
||||
}
|
||||
|
||||
// Apply transform to received data for non-parallel planes
|
||||
if (!procPatch.parallel())
|
||||
{
|
||||
transform(procPatch.reverseT(), patchInfo);
|
||||
}
|
||||
|
||||
updateFromPatchInfo
|
||||
(
|
||||
patch,
|
||||
patch,
|
||||
owner,
|
||||
ownerIndex,
|
||||
patchInfo
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// 3. Handle all shared points
|
||||
// (Note:irrespective if changed or not for now)
|
||||
//
|
||||
|
||||
const globalMeshData& pd = mesh.globalData();
|
||||
|
||||
List<Type> sharedData(pd.nGlobalPoints());
|
||||
|
||||
forAll(pd.sharedPointLabels(), i)
|
||||
{
|
||||
label meshPointI = pd.sharedPointLabels()[i];
|
||||
|
||||
// Fill my entries in the shared points
|
||||
sharedData[pd.sharedPointAddr()[i]] = allPointInfo_[meshPointI];
|
||||
}
|
||||
|
||||
// Combine on master. Reduce operator has to handle a list and call
|
||||
// Type.updatePoint for all elements
|
||||
combineReduce(sharedData, listUpdateOp<Type>());
|
||||
|
||||
forAll(pd.sharedPointLabels(), i)
|
||||
{
|
||||
label meshPointI = pd.sharedPointLabels()[i];
|
||||
|
||||
// Retrieve my entries from the shared points
|
||||
updatePoint
|
||||
(
|
||||
meshPointI,
|
||||
sharedData[pd.sharedPointAddr()[i]],
|
||||
propagationTol_,
|
||||
allPointInfo_[meshPointI]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -716,7 +713,6 @@ Foam::PointEdgeWave<Type>::PointEdgeWave
|
||||
nChangedEdges_(0),
|
||||
nCyclicPatches_(countPatchType<cyclicPolyPatch>()),
|
||||
cycHalves_(2*nCyclicPatches_),
|
||||
hasProcPatches_(countPatchType<processorPolyPatch>() > 0),
|
||||
nEvals_(0),
|
||||
nUnvisitedPoints_(pMesh_().nPoints()),
|
||||
nUnvisitedEdges_(pMesh_().nEdges())
|
||||
@ -898,7 +894,7 @@ Foam::label Foam::PointEdgeWave<Type>::edgeToPoint()
|
||||
// Transfer changed points across cyclic halves
|
||||
handleCyclicPatches();
|
||||
}
|
||||
if (hasProcPatches_)
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
// Transfer changed points from neighbouring processors.
|
||||
handleProcPatches();
|
||||
@ -996,7 +992,7 @@ Foam::label Foam::PointEdgeWave<Type>::iterate(const label maxIter)
|
||||
// Transfer changed points across cyclic halves
|
||||
handleCyclicPatches();
|
||||
}
|
||||
if (hasProcPatches_)
|
||||
if (Pstream::parRun())
|
||||
{
|
||||
// Transfer changed points from neighbouring processors.
|
||||
handleProcPatches();
|
||||
|
||||
@ -27,7 +27,8 @@ Class
|
||||
|
||||
Description
|
||||
Wave propagation of information through grid. Every iteration
|
||||
information goes through one layer of edges.
|
||||
information goes through one layer of edges. Templated on information
|
||||
that is transferred.
|
||||
|
||||
Templated on information that is transferred.
|
||||
Handles parallel and cyclics. Only parallel reasonably tested. Cyclics
|
||||
@ -131,9 +132,6 @@ class PointEdgeWave
|
||||
//- For every cyclic patch two primitivePatches
|
||||
PtrList<primitivePatch> cycHalves_;
|
||||
|
||||
//- Contains processor patches
|
||||
bool hasProcPatches_;
|
||||
|
||||
//- Number of evaluations
|
||||
label nEvals_;
|
||||
|
||||
@ -354,7 +352,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
|
||||
42
src/meshTools/edgeFaceCirculator/edgeFaceCirculator.C
Normal file
42
src/meshTools/edgeFaceCirculator/edgeFaceCirculator.C
Normal file
@ -0,0 +1,42 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "edgeFaceCirculator.H"
|
||||
#include "primitiveMesh.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
const Foam::edgeFaceCirculator Foam::edgeFaceCirculator::endConstIter
|
||||
(
|
||||
*reinterpret_cast<primitiveMesh*>(NULL), // primitiveMesh
|
||||
-1, // faceLabel
|
||||
false, // ownerSide
|
||||
-1, // index
|
||||
false // isBoundaryEdge
|
||||
);
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
211
src/meshTools/edgeFaceCirculator/edgeFaceCirculator.H
Normal file
211
src/meshTools/edgeFaceCirculator/edgeFaceCirculator.H
Normal file
@ -0,0 +1,211 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::edgeFaceCirculator
|
||||
|
||||
Description
|
||||
Walks from starting face around edge. Implicit
|
||||
description of edge:
|
||||
- face
|
||||
- index in face. edge is always between f[index] and f[index+1]
|
||||
- direction (cell to walk into)
|
||||
|
||||
Use as:
|
||||
|
||||
1) in-place:
|
||||
edgeFaceCirculator circ(..);
|
||||
// Optionally rotate to beginning: circ.setCanonical();
|
||||
|
||||
// Walk
|
||||
do
|
||||
{
|
||||
Info<< "face:" << circ.face() << endl;
|
||||
++circ;
|
||||
}
|
||||
while (circ != circ.end());
|
||||
|
||||
2) like STL iterator:
|
||||
|
||||
edgeFaceCirculator circ(..);
|
||||
for
|
||||
(
|
||||
edgeFaceCirculator iter = circ.begin();
|
||||
iter != circ.end();
|
||||
++iter
|
||||
)
|
||||
{
|
||||
Info<< "face:" << iter.face() << endl;
|
||||
}
|
||||
|
||||
|
||||
SourceFiles
|
||||
edgeFaceCirculator.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef edgeFaceCirculator_H
|
||||
#define edgeFaceCirculator_H
|
||||
|
||||
#include "face.H"
|
||||
#include "ListOps.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
class primitiveMesh;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class edgeFaceCirculator Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class edgeFaceCirculator
|
||||
{
|
||||
// Static data members
|
||||
|
||||
//- end iterator
|
||||
static const edgeFaceCirculator endConstIter;
|
||||
|
||||
|
||||
// Private data
|
||||
|
||||
//- Mesh
|
||||
const primitiveMesh& mesh_;
|
||||
|
||||
//- Current face
|
||||
label faceLabel_;
|
||||
|
||||
//- Current side of face
|
||||
bool ownerSide_;
|
||||
|
||||
//- Edge (between index and index+1 on faces[faceLabel_]
|
||||
label index_;
|
||||
|
||||
//- Is boundary edge?
|
||||
bool isBoundaryEdge_;
|
||||
|
||||
//- Starting face so we know when to stop. Used when circulating over
|
||||
// internal edges.
|
||||
label startFaceLabel_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Set to end() iterator
|
||||
inline void setEnd();
|
||||
|
||||
//- Check and set faceLabel_ and ownerSide_
|
||||
inline void setFace(const label faceI, const label cellI);
|
||||
|
||||
//- Set faceLabel_ to be the other face on the cell that uses the
|
||||
// edge.
|
||||
inline void otherFace(const label cellI);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
inline edgeFaceCirculator
|
||||
(
|
||||
const primitiveMesh& mesh,
|
||||
const label faceLabel,
|
||||
const bool ownerSide,
|
||||
const label index,
|
||||
const bool isBoundaryEdge
|
||||
);
|
||||
|
||||
//- Construct as copy
|
||||
inline edgeFaceCirculator(const edgeFaceCirculator&);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Helper: find index in face of edge or -1. Index is such that edge is
|
||||
// between f[index] and f[index+1]
|
||||
inline static label getMinIndex
|
||||
(
|
||||
const face& f,
|
||||
const label v0,
|
||||
const label v1
|
||||
);
|
||||
|
||||
inline label faceLabel() const;
|
||||
|
||||
inline bool ownerSide() const;
|
||||
|
||||
inline label index() const;
|
||||
|
||||
//- Helper: get the neighbouring cell according to the ownerSide.
|
||||
// Returns -1 if on neighbourside of boundary face.
|
||||
inline label cellLabel() const;
|
||||
|
||||
//- Helper: return true if normal of generated face points along
|
||||
// edge from v0 to v1. (v0 and v1 have to be on edge)
|
||||
inline bool sameOrder(const label v0, const label v1) const;
|
||||
|
||||
//- Set edge to a unique state so different ones can be compared.
|
||||
// Internal edge: minimum face index.
|
||||
// Boundary edge: walk back until boundary face.
|
||||
inline void setCanonical();
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
inline void operator=(const edgeFaceCirculator& iter);
|
||||
|
||||
inline bool operator==(const edgeFaceCirculator& iter) const;
|
||||
|
||||
inline bool operator!=(const edgeFaceCirculator& iter) const;
|
||||
|
||||
//- Step to next face. Uses no edge addressing!
|
||||
inline edgeFaceCirculator& operator++();
|
||||
|
||||
//- iterator set to the beginning face. For internal edges this is
|
||||
// the current face. For boundary edges this is the first boundary face
|
||||
// reached from walking back (i.e. in opposite direction to ++)
|
||||
inline edgeFaceCirculator begin() const;
|
||||
|
||||
//- iterator set to beyond the end of the walk.
|
||||
inline const edgeFaceCirculator& end() const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "edgeFaceCirculatorI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
428
src/meshTools/edgeFaceCirculator/edgeFaceCirculatorI.H
Normal file
428
src/meshTools/edgeFaceCirculator/edgeFaceCirculatorI.H
Normal file
@ -0,0 +1,428 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "primitiveMesh.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::edgeFaceCirculator::setEnd()
|
||||
{
|
||||
faceLabel_ = -1;
|
||||
index_ = -1;
|
||||
}
|
||||
|
||||
|
||||
void Foam::edgeFaceCirculator::setFace
|
||||
(
|
||||
const label faceI,
|
||||
const label cellI
|
||||
)
|
||||
{
|
||||
faceLabel_ = faceI;
|
||||
|
||||
if (!isBoundaryEdge_ && !mesh_.isInternalFace(faceI))
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"edgeFaceCirculator::setFace(const label, const label)"
|
||||
) << "Edge is not defined as boundary edge but still walked to"
|
||||
<< " boundary face:" << faceI << " on cell:" << cellI
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::edgeFaceCirculator::otherFace(const label cellI)
|
||||
{
|
||||
const face& f = mesh_.faces()[faceLabel_];
|
||||
label v0 = f[index_];
|
||||
label v1 = f.nextLabel(index_);
|
||||
|
||||
const cell& cFaces = mesh_.cells()[cellI];
|
||||
|
||||
forAll(cFaces, i)
|
||||
{
|
||||
label faceB = cFaces[i];
|
||||
|
||||
if (faceB != faceLabel_)
|
||||
{
|
||||
label fp = getMinIndex(mesh_.faces()[faceB], v0, v1);
|
||||
|
||||
if (fp >= 0)
|
||||
{
|
||||
index_ = fp;
|
||||
setFace(faceB, cellI);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FatalErrorIn("edgeFaceCirculator::otherFace(const label)")
|
||||
<< "Could not find next face stepping"
|
||||
<< " through cell along edge." << endl
|
||||
<< "face:" << faceLabel_ << " index in face:" << index_
|
||||
<< " edge:" << mesh_.points()[v0] << mesh_.points()[v1]
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
//- Construct from components
|
||||
Foam::edgeFaceCirculator::edgeFaceCirculator
|
||||
(
|
||||
const primitiveMesh& mesh,
|
||||
const label faceLabel,
|
||||
const bool ownerSide,
|
||||
const label index,
|
||||
const bool isBoundaryEdge
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
faceLabel_(faceLabel),
|
||||
ownerSide_(ownerSide),
|
||||
index_(index),
|
||||
isBoundaryEdge_(isBoundaryEdge),
|
||||
startFaceLabel_(faceLabel_)
|
||||
{}
|
||||
|
||||
|
||||
//- Construct copy
|
||||
Foam::edgeFaceCirculator::edgeFaceCirculator(const edgeFaceCirculator& circ)
|
||||
:
|
||||
mesh_(circ.mesh_),
|
||||
faceLabel_(circ.faceLabel_),
|
||||
ownerSide_(circ.ownerSide_),
|
||||
index_(circ.index_),
|
||||
isBoundaryEdge_(circ.isBoundaryEdge_),
|
||||
startFaceLabel_(circ.startFaceLabel_)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::label Foam::edgeFaceCirculator::getMinIndex
|
||||
(
|
||||
const face& f,
|
||||
const label v0,
|
||||
const label v1
|
||||
)
|
||||
{
|
||||
label fp = findIndex(f, v0);
|
||||
|
||||
if (fp != -1)
|
||||
{
|
||||
label fpMin1 = f.rcIndex(fp);
|
||||
|
||||
if (f[fpMin1] == v1)
|
||||
{
|
||||
fp = fpMin1;
|
||||
}
|
||||
else
|
||||
{
|
||||
label fpPlus1 = f.fcIndex(fp);
|
||||
|
||||
if (f[fpPlus1] != v1)
|
||||
{
|
||||
fp = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::edgeFaceCirculator::faceLabel() const
|
||||
{
|
||||
return faceLabel_;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::edgeFaceCirculator::ownerSide() const
|
||||
{
|
||||
return ownerSide_;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::edgeFaceCirculator::index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::edgeFaceCirculator::cellLabel() const
|
||||
{
|
||||
if (ownerSide_)
|
||||
{
|
||||
return mesh_.faceOwner()[faceLabel_];
|
||||
}
|
||||
else if (mesh_.isInternalFace(faceLabel_))
|
||||
{
|
||||
return mesh_.faceNeighbour()[faceLabel_];
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::edgeFaceCirculator::sameOrder(const label v0, const label v1) const
|
||||
{
|
||||
const face& f = mesh_.faces()[faceLabel_];
|
||||
|
||||
label fp = getMinIndex(f, v0, v1);
|
||||
|
||||
if (fp != index_)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"edgeFaceCirculator::sameOrder(const label, const label) const"
|
||||
) << "v0:" << v1 << " and v1:" << v1
|
||||
<< " not on position:" << index_ << " on face:" << faceLabel_
|
||||
<< " verts:" << f << " or not consecutive." << abort(FatalError);
|
||||
}
|
||||
|
||||
// If we are neighbour the face would point into us so the min index would
|
||||
// be v0.
|
||||
return ownerSide_ != (f[index_] == v0);
|
||||
}
|
||||
|
||||
|
||||
void Foam::edgeFaceCirculator::setCanonical()
|
||||
{
|
||||
if (isBoundaryEdge_)
|
||||
{
|
||||
// Boundary edge. Step until we're on boundary face and ownerSide
|
||||
label i = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (mesh_.isInternalFace(faceLabel_))
|
||||
{
|
||||
if (ownerSide_)
|
||||
{
|
||||
label cellI = mesh_.faceNeighbour()[faceLabel_];
|
||||
otherFace(cellI);
|
||||
// Maintain reverse direction of walking
|
||||
ownerSide_ = (mesh_.faceOwner()[faceLabel_] == cellI);
|
||||
}
|
||||
else
|
||||
{
|
||||
label cellI = mesh_.faceOwner()[faceLabel_];
|
||||
otherFace(cellI);
|
||||
// Maintain reverse direction of walking
|
||||
ownerSide_ = (mesh_.faceOwner()[faceLabel_] == cellI);
|
||||
}
|
||||
}
|
||||
else if (ownerSide_)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
label cellI = mesh_.faceOwner()[faceLabel_];
|
||||
otherFace(cellI);
|
||||
// Maintain reverse direction of walking
|
||||
ownerSide_ = (mesh_.faceOwner()[faceLabel_] == cellI);
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (i >= 1000)
|
||||
{
|
||||
const face& f = mesh_.faces()[faceLabel_];
|
||||
|
||||
FatalErrorIn("Foam::edgeFaceCirculator::setCanonical()")
|
||||
<< "Walked " << i << " cells around edge "
|
||||
<< mesh_.points()[f[index_]]
|
||||
<< mesh_.points()[f.nextLabel(index_)]
|
||||
<< " without reaching a boundary face."
|
||||
<< " Are you sure this is a boundary edge?"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
// Set up for correct walking
|
||||
ownerSide_ = true;
|
||||
startFaceLabel_ = faceLabel_;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Internal edge. Walk until we hit minimum face label.
|
||||
label minFaceI = faceLabel_;
|
||||
bool minOwnerSide = ownerSide_;
|
||||
label minIndex = index_;
|
||||
|
||||
while (true)
|
||||
{
|
||||
operator++();
|
||||
|
||||
if (operator==(end()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!mesh_.isInternalFace(faceLabel_))
|
||||
{
|
||||
const face& f = mesh_.faces()[faceLabel_];
|
||||
|
||||
FatalErrorIn("Foam::edgeFaceCirculator::setCanonical()")
|
||||
<< "Reached boundary face " << faceLabel_
|
||||
<< " when walking around internal edge "
|
||||
<< mesh_.points()[f[index_]]
|
||||
<< mesh_.points()[f.nextLabel(index_)]
|
||||
<< "." << endl
|
||||
<< "Are you sure this is an internal edge?"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
if (faceLabel_ < minFaceI)
|
||||
{
|
||||
minFaceI = faceLabel_;
|
||||
minOwnerSide = ownerSide_;
|
||||
minIndex = index_;
|
||||
}
|
||||
}
|
||||
|
||||
faceLabel_ = minFaceI;
|
||||
ownerSide_ = minOwnerSide;
|
||||
index_ = minIndex;
|
||||
startFaceLabel_ = faceLabel_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::edgeFaceCirculator::operator=(const edgeFaceCirculator& circ)
|
||||
{
|
||||
faceLabel_ = circ.faceLabel_;
|
||||
ownerSide_ = circ.ownerSide_;
|
||||
index_ = circ.index_;
|
||||
isBoundaryEdge_ = circ.isBoundaryEdge_;
|
||||
startFaceLabel_ = circ.startFaceLabel_;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::edgeFaceCirculator::operator==(const edgeFaceCirculator& circ) const
|
||||
{
|
||||
return faceLabel_ == circ.faceLabel_ && index_ == circ.index_;
|
||||
|
||||
////- Note: do I need full comparison? If not we now have that circulators
|
||||
//// around same edge but in different direction are considered not equal
|
||||
//if (faceLabel_ == -1 && circ.faceLabel_ == -1)
|
||||
//{
|
||||
// // both endConstIter
|
||||
// return true;
|
||||
//}
|
||||
//
|
||||
//return
|
||||
// faceLabel_ == circ.faceLabel_
|
||||
// && ownerSide_ == circ.ownerSide_
|
||||
// && index_ == circ.index_;
|
||||
// && startFaceLabel_ == circ.startFaceLabel_;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::edgeFaceCirculator::operator!=(const edgeFaceCirculator& circ) const
|
||||
{
|
||||
return !(*this == circ);
|
||||
}
|
||||
|
||||
|
||||
//- Step to next face.
|
||||
Foam::edgeFaceCirculator::edgeFaceCirculator&
|
||||
Foam::edgeFaceCirculator::operator++()
|
||||
{
|
||||
if (faceLabel_ == -1)
|
||||
{
|
||||
FatalErrorIn("edgeFaceCirculator::operator++()")
|
||||
<< "Already reached end(). Cannot walk any further."
|
||||
<< abort(FatalError);
|
||||
}
|
||||
else if (ownerSide_)
|
||||
{
|
||||
// Step to owner
|
||||
label cellI = mesh_.faceOwner()[faceLabel_];
|
||||
otherFace(cellI);
|
||||
// Maintain direction of walking
|
||||
ownerSide_ = (mesh_.faceOwner()[faceLabel_] != cellI);
|
||||
|
||||
// Check for internal edge : ends on starting face.
|
||||
if (!isBoundaryEdge_ && faceLabel_ == startFaceLabel_)
|
||||
{
|
||||
setEnd();
|
||||
}
|
||||
}
|
||||
else if (mesh_.isInternalFace(faceLabel_))
|
||||
{
|
||||
// Step to neighbour
|
||||
label cellI = mesh_.faceNeighbour()[faceLabel_];
|
||||
otherFace(cellI);
|
||||
// Maintain direction of walking
|
||||
ownerSide_ = (mesh_.faceOwner()[faceLabel_] != cellI);
|
||||
|
||||
// Check for internal edge : ends on starting face.
|
||||
if (!isBoundaryEdge_ && faceLabel_ == startFaceLabel_)
|
||||
{
|
||||
setEnd();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// neighbour side of boundary face reached. Mark as endConstIter.
|
||||
setEnd();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Foam::edgeFaceCirculator Foam::edgeFaceCirculator::begin() const
|
||||
{
|
||||
edgeFaceCirculator iter
|
||||
(
|
||||
mesh_,
|
||||
faceLabel_,
|
||||
ownerSide_,
|
||||
index_,
|
||||
isBoundaryEdge_
|
||||
);
|
||||
|
||||
if (isBoundaryEdge_)
|
||||
{
|
||||
iter.setCanonical();
|
||||
}
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
||||
const Foam::edgeFaceCirculator& Foam::edgeFaceCirculator::end() const
|
||||
{
|
||||
return endConstIter;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -292,7 +292,7 @@ void indexedOctree<Type>::splitNodes
|
||||
{
|
||||
label contentI = getContent(index);
|
||||
|
||||
if (contents[contentI].size() > minSize)
|
||||
if (contents[contentI].size() > minSize)
|
||||
{
|
||||
// Create node for content.
|
||||
|
||||
@ -496,7 +496,7 @@ typename indexedOctree<Type>::volumeType indexedOctree<Type>::getVolumeType
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
@ -550,35 +550,21 @@ void indexedOctree<Type>::findNearest
|
||||
{
|
||||
const node& nod = nodes_[nodeI];
|
||||
|
||||
// Find the octant containing the sample
|
||||
direction sampleOctant = nod.bb_.subOctant(sample);
|
||||
// Determine order to walk through octants
|
||||
FixedList<direction, 8> octantOrder;
|
||||
nod.bb_.searchOrder(sample, octantOrder);
|
||||
|
||||
// Go into all suboctants (one containing sample first) and update nearest.
|
||||
// Order of visiting is if e.g. sampleOctant = 5:
|
||||
// 5 1 2 3 4 0 6 7
|
||||
for (direction i = 0; i < 8; i++)
|
||||
{
|
||||
direction octant;
|
||||
if (i == 0)
|
||||
{
|
||||
// Use sampleOctant first
|
||||
octant = sampleOctant;
|
||||
}
|
||||
else if (i == sampleOctant)
|
||||
{
|
||||
octant = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
octant = i;
|
||||
}
|
||||
direction octant = octantOrder[i];
|
||||
|
||||
labelBits index = nod.subNodes_[octant];
|
||||
|
||||
if (isNode(index))
|
||||
{
|
||||
label subNodeI = getNode(index);
|
||||
|
||||
|
||||
const treeBoundBox& subBb = nodes_[subNodeI].bb_;
|
||||
|
||||
if (intersects(subBb.min(), subBb.max(), nearestDistSqr, sample))
|
||||
@ -638,28 +624,14 @@ void indexedOctree<Type>::findNearest
|
||||
const node& nod = nodes_[nodeI];
|
||||
const treeBoundBox& nodeBb = nod.bb_;
|
||||
|
||||
// Estimate for where best to start searching
|
||||
direction sampleOctant = treeBoundBox::subOctant(ln.centre());
|
||||
// Determine order to walk through octants
|
||||
FixedList<direction, 8> octantOrder;
|
||||
nod.bb_.searchOrder(ln.centre(), octantOrder);
|
||||
|
||||
// Go into all suboctants (one containing sample first) and update tightest.
|
||||
// Order of visiting is if e.g. sampleOctant = 5:
|
||||
// 5 1 2 3 4 0 6 7
|
||||
// Go into all suboctants (one containing sample first) and update nearest.
|
||||
for (direction i = 0; i < 8; i++)
|
||||
{
|
||||
direction octant;
|
||||
if (i == 0)
|
||||
{
|
||||
// Use sampleOctant first
|
||||
octant = sampleOctant;
|
||||
}
|
||||
else if (i == sampleOctant)
|
||||
{
|
||||
octant = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
octant = i;
|
||||
}
|
||||
direction octant = octantOrder[i];
|
||||
|
||||
labelBits index = nod.subNodes_[octant];
|
||||
|
||||
@ -706,7 +678,7 @@ void indexedOctree<Type>::findNearest
|
||||
// Walk tree to neighbouring node. Gets current position as
|
||||
// node and octant in this node and walks in the direction given by
|
||||
// the faceID (one of treeBoundBox::LEFTBIT, RIGHTBIT etc.)
|
||||
// Returns false if edge of tree hit.
|
||||
// Returns false if edge of tree hit.
|
||||
template <class Type>
|
||||
bool indexedOctree<Type>::walkToNeighbour
|
||||
(
|
||||
@ -734,22 +706,22 @@ bool indexedOctree<Type>::walkToNeighbour
|
||||
octantMask |= treeBoundBox::RIGHTHALF; // valueMask already 0
|
||||
}
|
||||
|
||||
if ((faceID & treeBoundBox::BELOWBIT) != 0)
|
||||
if ((faceID & treeBoundBox::BOTTOMBIT) != 0)
|
||||
{
|
||||
octantMask |= treeBoundBox::TOPHALF;
|
||||
valueMask |= treeBoundBox::TOPHALF;
|
||||
}
|
||||
else if ((faceID & treeBoundBox::ABOVEBIT) != 0)
|
||||
else if ((faceID & treeBoundBox::TOPBIT) != 0)
|
||||
{
|
||||
octantMask |= treeBoundBox::TOPHALF;
|
||||
}
|
||||
|
||||
if ((faceID & treeBoundBox::BEHINDBIT) != 0)
|
||||
if ((faceID & treeBoundBox::BACKBIT) != 0)
|
||||
{
|
||||
octantMask |= treeBoundBox::FRONTHALF;
|
||||
valueMask |= treeBoundBox::FRONTHALF;
|
||||
}
|
||||
else if ((faceID & treeBoundBox::INFRONTBIT) != 0)
|
||||
else if ((faceID & treeBoundBox::FRONTBIT) != 0)
|
||||
{
|
||||
octantMask |= treeBoundBox::FRONTHALF;
|
||||
}
|
||||
@ -830,20 +802,20 @@ direction indexedOctree<Type>::getFace(const treeBoundBox& bb, const point& pt)
|
||||
|
||||
if (pt.y() <= bb.min().y())
|
||||
{
|
||||
faceID |= treeBoundBox::BELOWBIT;
|
||||
faceID |= treeBoundBox::BOTTOMBIT;
|
||||
}
|
||||
if (pt.y() >= bb.max().y())
|
||||
{
|
||||
faceID |= treeBoundBox::ABOVEBIT;
|
||||
faceID |= treeBoundBox::TOPBIT;
|
||||
}
|
||||
|
||||
if (pt.z() <= bb.min().z())
|
||||
{
|
||||
faceID |= treeBoundBox::BEHINDBIT;
|
||||
faceID |= treeBoundBox::BACKBIT;
|
||||
}
|
||||
if (pt.z() >= bb.max().z())
|
||||
{
|
||||
faceID |= treeBoundBox::INFRONTBIT;
|
||||
faceID |= treeBoundBox::FRONTBIT;
|
||||
}
|
||||
return faceID;
|
||||
}
|
||||
@ -943,9 +915,14 @@ void indexedOctree<Type>::traverseNode
|
||||
{
|
||||
faceID = 0;
|
||||
|
||||
//WarningIn("indexedOctree<Type>::traverseNode")
|
||||
FatalErrorIn("indexedOctree<Type>::traverseNode")
|
||||
<< "Did not hit side of node box " << subBb
|
||||
WarningIn("indexedOctree<Type>::traverseNode")
|
||||
<< "Did not hit side of box " << subBb
|
||||
<< " with ray from " << start << " to " << end
|
||||
//<< endl;
|
||||
<< abort(FatalError);
|
||||
<< endl;
|
||||
}
|
||||
else
|
||||
@ -961,9 +938,14 @@ void indexedOctree<Type>::traverseNode
|
||||
{
|
||||
faceID = 0;
|
||||
|
||||
//WarningIn("indexedOctree<Type>::traverseNode")
|
||||
FatalErrorIn("indexedOctree<Type>::traverseNode")
|
||||
<< "Did not hit side of content box " << subBb
|
||||
WarningIn("indexedOctree<Type>::traverseNode")
|
||||
<< "Did not hit side of box " << subBb
|
||||
<< " with ray from " << start << " to " << end
|
||||
//<< endl;
|
||||
<< abort(FatalError);
|
||||
<< endl;
|
||||
}
|
||||
else
|
||||
@ -1074,53 +1056,58 @@ pointIndexHit indexedOctree<Type>::findLine
|
||||
const point& end
|
||||
) const
|
||||
{
|
||||
const treeBoundBox& treeBb = nodes_[0].bb_;
|
||||
pointIndexHit hitInfo;
|
||||
|
||||
direction startBit = treeBb.posBits(start);
|
||||
direction endBit = treeBb.posBits(end);
|
||||
|
||||
if (startBit&endBit != 0)
|
||||
if (nodes_.size() > 0)
|
||||
{
|
||||
// Both start and end outside domain and in same block.
|
||||
return pointIndexHit(false, vector::zero, -1);
|
||||
}
|
||||
const treeBoundBox& treeBb = nodes_[0].bb_;
|
||||
|
||||
point trackStart(start);
|
||||
point trackEnd(end);
|
||||
direction startBit = treeBb.posBits(start);
|
||||
direction endBit = treeBb.posBits(end);
|
||||
|
||||
if (startBit != 0)
|
||||
{
|
||||
// Track start to inside domain.
|
||||
if (!treeBb.intersects(start, end, trackStart))
|
||||
if (startBit&endBit != 0)
|
||||
{
|
||||
// Both start and end outside domain and in same block.
|
||||
return pointIndexHit(false, vector::zero, -1);
|
||||
}
|
||||
}
|
||||
|
||||
if (endBit != 0)
|
||||
{
|
||||
// Track end to inside domain.
|
||||
if (!treeBb.intersects(end, trackStart, trackEnd))
|
||||
point trackStart(start);
|
||||
point trackEnd(end);
|
||||
|
||||
if (startBit != 0)
|
||||
{
|
||||
return pointIndexHit(false, vector::zero, -1);
|
||||
// Track start to inside domain.
|
||||
if (!treeBb.intersects(start, end, trackStart))
|
||||
{
|
||||
return pointIndexHit(false, vector::zero, -1);
|
||||
}
|
||||
}
|
||||
|
||||
if (endBit != 0)
|
||||
{
|
||||
// Track end to inside domain.
|
||||
if (!treeBb.intersects(end, trackStart, trackEnd))
|
||||
{
|
||||
return pointIndexHit(false, vector::zero, -1);
|
||||
}
|
||||
}
|
||||
|
||||
// Find lowest level tree node that start is in.
|
||||
labelBits index = findNode(0, trackStart);
|
||||
|
||||
label parentNodeI = getNode(index);
|
||||
direction octant = getOctant(index);
|
||||
|
||||
hitInfo = findLine
|
||||
(
|
||||
findAny,
|
||||
trackStart,
|
||||
trackEnd,
|
||||
parentNodeI,
|
||||
octant
|
||||
);
|
||||
}
|
||||
|
||||
// Find lowest level tree node that start is in.
|
||||
labelBits index = findNode(0, trackStart);
|
||||
|
||||
label parentNodeI = getNode(index);
|
||||
direction octant = getOctant(index);
|
||||
|
||||
pointIndexHit hitInfo = findLine
|
||||
(
|
||||
findAny,
|
||||
trackStart,
|
||||
trackEnd,
|
||||
parentNodeI,
|
||||
octant
|
||||
);
|
||||
|
||||
return hitInfo;
|
||||
}
|
||||
|
||||
@ -1234,7 +1221,6 @@ void indexedOctree<Type>::writeOBJ
|
||||
label vertI = 0;
|
||||
|
||||
// Dump bounding box
|
||||
edgeList bbEdges(subBb.edges());
|
||||
pointField bbPoints(subBb.points());
|
||||
|
||||
label pointVertI = vertI;
|
||||
@ -1244,38 +1230,38 @@ void indexedOctree<Type>::writeOBJ
|
||||
vertI++;
|
||||
}
|
||||
|
||||
forAll(bbEdges, i)
|
||||
forAll(treeBoundBox::edges, i)
|
||||
{
|
||||
const edge& e = bbEdges[i];
|
||||
const edge& e = treeBoundBox::edges[i];
|
||||
|
||||
str<< "l " << e[0]+pointVertI+1 << ' ' << e[1]+pointVertI+1 << nl;
|
||||
}
|
||||
|
||||
|
||||
// Dump triangles
|
||||
if (isContent(index))
|
||||
{
|
||||
const labelList& indices = contents_[getContent(index)];
|
||||
const triSurface& surf = shapes_.surface();
|
||||
const pointField& points = surf.points();
|
||||
|
||||
forAll(indices, i)
|
||||
{
|
||||
label shapeI = indices[i];
|
||||
|
||||
const labelledTri& f = surf[shapeI];
|
||||
|
||||
meshTools::writeOBJ(str, points[f[0]]);
|
||||
vertI++;
|
||||
meshTools::writeOBJ(str, points[f[1]]);
|
||||
vertI++;
|
||||
meshTools::writeOBJ(str, points[f[2]]);
|
||||
vertI++;
|
||||
|
||||
str<< "l " << vertI-2 << ' ' << vertI-1 << ' ' << vertI << ' '
|
||||
<< vertI-2 << nl;
|
||||
}
|
||||
}
|
||||
//// Dump triangles
|
||||
//if (isContent(index))
|
||||
//{
|
||||
// const labelList& indices = contents_[getContent(index)];
|
||||
// const triSurface& surf = shapes_.surface();
|
||||
// const pointField& points = surf.points();
|
||||
//
|
||||
// forAll(indices, i)
|
||||
// {
|
||||
// label shapeI = indices[i];
|
||||
//
|
||||
// const labelledTri& f = surf[shapeI];
|
||||
//
|
||||
// meshTools::writeOBJ(str, points[f[0]]);
|
||||
// vertI++;
|
||||
// meshTools::writeOBJ(str, points[f[1]]);
|
||||
// vertI++;
|
||||
// meshTools::writeOBJ(str, points[f[2]]);
|
||||
// vertI++;
|
||||
//
|
||||
// str<< "l " << vertI-2 << ' ' << vertI-1 << ' ' << vertI << ' '
|
||||
// << vertI-2 << nl;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
@ -1321,6 +1307,11 @@ indexedOctree<Type>::indexedOctree
|
||||
contents_(0),
|
||||
nodeTypes_(0)
|
||||
{
|
||||
if (shapes.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Start off with one node with all shapes in it.
|
||||
DynamicList<node> nodes(label(shapes.size() / maxLeafRatio));
|
||||
DynamicList<labelList> contents(label(shapes.size() / maxLeafRatio));
|
||||
@ -1380,7 +1371,7 @@ indexedOctree<Type>::indexedOctree
|
||||
if (nOldNodes == nodes.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shrink
|
||||
@ -1411,6 +1402,7 @@ indexedOctree<Type>::indexedOctree
|
||||
|
||||
if (compactI == contents_.size())
|
||||
{
|
||||
// Transferred all contents to contents_ (in order breadth first)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1468,15 +1460,22 @@ pointIndexHit indexedOctree<Type>::findNearest
|
||||
label nearestShapeI = -1;
|
||||
point nearestPoint;
|
||||
|
||||
findNearest
|
||||
(
|
||||
0,
|
||||
sample,
|
||||
if (nodes_.size() == 0)
|
||||
{
|
||||
nearestPoint = vector::zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
findNearest
|
||||
(
|
||||
0,
|
||||
sample,
|
||||
|
||||
nearestDistSqr,
|
||||
nearestShapeI,
|
||||
nearestPoint
|
||||
);
|
||||
nearestDistSqr,
|
||||
nearestShapeI,
|
||||
nearestPoint
|
||||
);
|
||||
}
|
||||
|
||||
return pointIndexHit(nearestShapeI != -1, nearestPoint, nearestShapeI);
|
||||
}
|
||||
@ -1493,16 +1492,23 @@ pointIndexHit indexedOctree<Type>::findNearest
|
||||
label nearestShapeI = -1;
|
||||
point nearestPoint;
|
||||
|
||||
findNearest
|
||||
(
|
||||
0,
|
||||
ln,
|
||||
if (nodes_.size() == 0)
|
||||
{
|
||||
nearestPoint = vector::zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
findNearest
|
||||
(
|
||||
0,
|
||||
ln,
|
||||
|
||||
tightest,
|
||||
nearestShapeI,
|
||||
linePoint,
|
||||
nearestPoint
|
||||
);
|
||||
tightest,
|
||||
nearestShapeI,
|
||||
linePoint,
|
||||
nearestPoint
|
||||
);
|
||||
}
|
||||
|
||||
return pointIndexHit(nearestShapeI != -1, nearestPoint, nearestShapeI);
|
||||
}
|
||||
@ -1538,7 +1544,10 @@ labelList indexedOctree<Type>::findBox(const boundBox& searchBox) const
|
||||
// Storage for labels of shapes inside bb. Size estimate.
|
||||
labelHashSet elements(shapes_.size() / 100);
|
||||
|
||||
findBox(0, searchBox, elements);
|
||||
if (nodes_.size() > 0)
|
||||
{
|
||||
findBox(0, searchBox, elements);
|
||||
}
|
||||
|
||||
return elements.toc();
|
||||
}
|
||||
@ -1552,6 +1561,12 @@ labelBits indexedOctree<Type>::findNode
|
||||
const point& sample
|
||||
) const
|
||||
{
|
||||
if (nodes_.size() == 0)
|
||||
{
|
||||
// Empty tree. Return what?
|
||||
return nodePlusOctant(nodeI, 0);
|
||||
}
|
||||
|
||||
const node& nod = nodes_[nodeI];
|
||||
|
||||
direction octant = nod.bb_.subOctant(sample);
|
||||
@ -1583,6 +1598,11 @@ typename indexedOctree<Type>::volumeType indexedOctree<Type>::getVolumeType
|
||||
const point& sample
|
||||
) const
|
||||
{
|
||||
if (nodes_.size() == 0)
|
||||
{
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
if (nodeTypes_.size() != 8*nodes_.size())
|
||||
{
|
||||
// Calculate type for every octant of node.
|
||||
|
||||
@ -26,7 +26,7 @@ Class
|
||||
Foam::indexedOctree
|
||||
|
||||
Description
|
||||
An indexedOctree is ...
|
||||
Non-pointer based hierarchical recursive searching
|
||||
|
||||
SourceFiles
|
||||
indexedOctree.C
|
||||
@ -299,7 +299,7 @@ private:
|
||||
return labelBits(i + 1, octant);
|
||||
}
|
||||
|
||||
//- Fempty to subNodes_ entry
|
||||
//- From empty to subNodes_ entry
|
||||
static labelBits emptyPlusOctant
|
||||
(
|
||||
const direction octant
|
||||
|
||||
250
src/meshTools/indexedOctree/treeDataCell.C
Normal file
250
src/meshTools/indexedOctree/treeDataCell.C
Normal file
@ -0,0 +1,250 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "treeDataCell.H"
|
||||
#include "indexedOctree.H"
|
||||
#include "polyMesh.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
defineTypeNameAndDebug(Foam::treeDataCell, 0);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::treeBoundBox Foam::treeDataCell::calcCellBb(const label cellI) const
|
||||
{
|
||||
const cellList& cells = mesh_.cells();
|
||||
const faceList& faces = mesh_.faces();
|
||||
const pointField& points = mesh_.points();
|
||||
|
||||
treeBoundBox cellBb
|
||||
(
|
||||
vector(GREAT, GREAT, GREAT),
|
||||
vector(-GREAT, -GREAT, -GREAT)
|
||||
);
|
||||
|
||||
const cell& cFaces = cells[cellI];
|
||||
|
||||
forAll(cFaces, cFaceI)
|
||||
{
|
||||
const face& f = faces[cFaces[cFaceI]];
|
||||
|
||||
forAll(f, fp)
|
||||
{
|
||||
const point& p = points[f[fp]];
|
||||
|
||||
cellBb.min() = min(cellBb.min(), p);
|
||||
cellBb.max() = max(cellBb.max(), p);
|
||||
}
|
||||
}
|
||||
return cellBb;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct from components
|
||||
Foam::treeDataCell::treeDataCell
|
||||
(
|
||||
const bool cacheBb,
|
||||
const polyMesh& mesh,
|
||||
const labelList& cellLabels
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
cellLabels_(cellLabels),
|
||||
cacheBb_(cacheBb)
|
||||
{
|
||||
if (cacheBb_)
|
||||
{
|
||||
bbs_.setSize(cellLabels_.size());
|
||||
|
||||
forAll(cellLabels_, i)
|
||||
{
|
||||
bbs_[i] = calcCellBb(cellLabels_[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::treeDataCell::treeDataCell
|
||||
(
|
||||
const bool cacheBb,
|
||||
const polyMesh& mesh
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
cellLabels_(identity(mesh_.nCells())),
|
||||
cacheBb_(cacheBb)
|
||||
{
|
||||
if (cacheBb_)
|
||||
{
|
||||
bbs_.setSize(cellLabels_.size());
|
||||
|
||||
forAll(cellLabels_, i)
|
||||
{
|
||||
bbs_[i] = calcCellBb(cellLabels_[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointField Foam::treeDataCell::points() const
|
||||
{
|
||||
pointField cc(cellLabels_.size());
|
||||
|
||||
forAll(cellLabels_, i)
|
||||
{
|
||||
cc[i] = mesh_.cellCentres()[cellLabels_[i]];
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
||||
// Check if any point on shape is inside cubeBb.
|
||||
bool Foam::treeDataCell::overlaps
|
||||
(
|
||||
const label index,
|
||||
const treeBoundBox& cubeBb
|
||||
) const
|
||||
{
|
||||
if (cacheBb_)
|
||||
{
|
||||
return cubeBb.intersects(bbs_[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return cubeBb.intersects(calcCellBb(cellLabels_[index]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Calculate nearest point to sample. Updates (if any) nearestDistSqr, minIndex,
|
||||
// nearestPoint.
|
||||
void Foam::treeDataCell::findNearest
|
||||
(
|
||||
const labelList& indices,
|
||||
const point& sample,
|
||||
|
||||
scalar& nearestDistSqr,
|
||||
label& minIndex,
|
||||
point& nearestPoint
|
||||
) const
|
||||
{
|
||||
forAll(indices, i)
|
||||
{
|
||||
label index = indices[i];
|
||||
label cellI = cellLabels_[index];
|
||||
scalar distSqr = magSqr(sample - mesh_.cellCentres()[cellI]);
|
||||
|
||||
if (distSqr < nearestDistSqr)
|
||||
{
|
||||
nearestDistSqr = distSqr;
|
||||
minIndex = index;
|
||||
nearestPoint = mesh_.cellCentres()[cellI];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::treeDataCell::intersects
|
||||
(
|
||||
const label index,
|
||||
const point& start,
|
||||
const point& end,
|
||||
point& intersectionPoint
|
||||
) const
|
||||
{
|
||||
// Do quick rejection test
|
||||
if (cacheBb_)
|
||||
{
|
||||
const treeBoundBox& cellBb = bbs_[index];
|
||||
|
||||
if ((cellBb.posBits(start) & cellBb.posBits(end)) != 0)
|
||||
{
|
||||
// start and end in same block outside of cellBb.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const treeBoundBox cellBb = calcCellBb(cellLabels_[index]);
|
||||
|
||||
if ((cellBb.posBits(start) & cellBb.posBits(end)) != 0)
|
||||
{
|
||||
// start and end in same block outside of cellBb.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Do intersection with all faces of cell
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
// Disable picking up intersections behind us.
|
||||
scalar oldTol = intersection::setPlanarTol(0.0);
|
||||
|
||||
const cell& cFaces = mesh_.cells()[cellLabels_[index]];
|
||||
|
||||
const vector dir(end - start);
|
||||
scalar minDistSqr = magSqr(dir);
|
||||
bool hasMin = false;
|
||||
|
||||
forAll(cFaces, i)
|
||||
{
|
||||
const face& f = mesh_.faces()[cFaces[i]];
|
||||
|
||||
pointHit inter = f.ray
|
||||
(
|
||||
start,
|
||||
dir,
|
||||
mesh_.points(),
|
||||
intersection::HALF_RAY
|
||||
);
|
||||
|
||||
if (inter.hit() && sqr(inter.distance()) <= minDistSqr)
|
||||
{
|
||||
// Note: no extra test on whether intersection is in front of us
|
||||
// since using half_ray AND zero tolerance. (note that tolerance
|
||||
// is used to look behind us)
|
||||
minDistSqr = sqr(inter.distance());
|
||||
intersectionPoint = inter.hitPoint();
|
||||
hasMin = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore picking tolerance
|
||||
intersection::setPlanarTol(oldTol);
|
||||
|
||||
return hasMin;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
202
src/meshTools/indexedOctree/treeDataCell.H
Normal file
202
src/meshTools/indexedOctree/treeDataCell.H
Normal file
@ -0,0 +1,202 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::treeDataCell
|
||||
|
||||
Description
|
||||
Encapsulation of data needed to search in/for cells. Used to find the
|
||||
cell containing a point (e.g. cell-cell mapping).
|
||||
|
||||
SourceFiles
|
||||
treeDataCell.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef treeDataCell_H
|
||||
#define treeDataCell_H
|
||||
|
||||
#include "treeBoundBox.H"
|
||||
#include "treeBoundBoxList.H"
|
||||
#include "labelList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
class polyMesh;
|
||||
template<class Type> class indexedOctree;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class treeDataCell Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class treeDataCell
|
||||
{
|
||||
// Private data
|
||||
|
||||
const polyMesh& mesh_;
|
||||
|
||||
//- Subset of cells to work on
|
||||
const labelList cellLabels_;
|
||||
|
||||
//- Whether to precalculate and store cell bounding box
|
||||
const bool cacheBb_;
|
||||
|
||||
//- cell bounding boxes (valid only if cacheBb_)
|
||||
treeBoundBoxList bbs_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Calculate cell bounding box
|
||||
treeBoundBox calcCellBb(const label cellI) const;
|
||||
|
||||
public:
|
||||
|
||||
// Declare name of the class and its debug switch
|
||||
ClassName("treeDataCell");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from mesh and subset of cells.
|
||||
treeDataCell
|
||||
(
|
||||
const bool cacheBb,
|
||||
const polyMesh&,
|
||||
const labelList&
|
||||
);
|
||||
|
||||
//- Construct from mesh. Uses all cells in mesh.
|
||||
treeDataCell(const bool cacheBb, const polyMesh&);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
const labelList& cellLabels() const
|
||||
{
|
||||
return cellLabels_;
|
||||
}
|
||||
|
||||
const polyMesh& mesh() const
|
||||
{
|
||||
return mesh_;
|
||||
}
|
||||
|
||||
|
||||
label size() const
|
||||
{
|
||||
return cellLabels_.size();
|
||||
}
|
||||
|
||||
//- Get representative point cloud for all shapes inside
|
||||
// (one point per shape)
|
||||
pointField points() const;
|
||||
|
||||
|
||||
// Search
|
||||
|
||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
||||
// Only makes sense for closed surfaces.
|
||||
label getVolumeType
|
||||
(
|
||||
const indexedOctree<treeDataCell>&,
|
||||
const point&
|
||||
) const
|
||||
{
|
||||
notImplemented
|
||||
(
|
||||
"treeDataCell::getVolumeType"
|
||||
"(const indexedOctree<treeDataCell>&, const point&)"
|
||||
);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//- Does (bb of) shape at index overlap bb
|
||||
bool overlaps
|
||||
(
|
||||
const label index,
|
||||
const treeBoundBox& sampleBb
|
||||
) const;
|
||||
|
||||
//- Calculates nearest (to sample) point in shape.
|
||||
// Returns actual point and distance (squared)
|
||||
void findNearest
|
||||
(
|
||||
const labelList& indices,
|
||||
const point& sample,
|
||||
|
||||
scalar& nearestDistSqr,
|
||||
label& nearestIndex,
|
||||
point& nearestPoint
|
||||
) const;
|
||||
|
||||
//- Calculates nearest (to line) point in shape.
|
||||
// Returns point and distance (squared)
|
||||
void findNearest
|
||||
(
|
||||
const labelList& indices,
|
||||
const linePointRef& ln,
|
||||
|
||||
treeBoundBox& tightest,
|
||||
label& minIndex,
|
||||
point& linePoint,
|
||||
point& nearestPoint
|
||||
) const
|
||||
{
|
||||
notImplemented
|
||||
(
|
||||
"treeDataCell::findNearest"
|
||||
"(const labelList&, const linePointRef&, ..)"
|
||||
);
|
||||
}
|
||||
|
||||
//- Calculate intersection of shape with ray. Sets result
|
||||
// accordingly
|
||||
bool intersects
|
||||
(
|
||||
const label index,
|
||||
const point& start,
|
||||
const point& end,
|
||||
point& result
|
||||
) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
209
src/meshTools/indexedOctree/treeDataEdge.C
Normal file
209
src/meshTools/indexedOctree/treeDataEdge.C
Normal file
@ -0,0 +1,209 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Description
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "treeDataEdge.H"
|
||||
#include "indexedOctree.H"
|
||||
#include "polyMesh.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::treeBoundBox Foam::treeDataEdge::calcBb(const label edgeI) const
|
||||
{
|
||||
const edge& e = edges_[edgeI];
|
||||
const point& p0 = points_[e[0]];
|
||||
const point& p1 = points_[e[1]];
|
||||
|
||||
return treeBoundBox(min(p0, p1), max(p0, p1));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct from components
|
||||
Foam::treeDataEdge::treeDataEdge
|
||||
(
|
||||
const bool cacheBb,
|
||||
const edgeList& edges,
|
||||
const pointField& points,
|
||||
const labelList& edgeLabels
|
||||
)
|
||||
:
|
||||
edges_(edges),
|
||||
points_(points),
|
||||
edgeLabels_(edgeLabels),
|
||||
cacheBb_(cacheBb)
|
||||
{
|
||||
if (cacheBb_)
|
||||
{
|
||||
bbs_.setSize(edgeLabels_.size());
|
||||
|
||||
forAll(edgeLabels_, i)
|
||||
{
|
||||
bbs_[i] = calcBb(edgeLabels_[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointField Foam::treeDataEdge::points() const
|
||||
{
|
||||
pointField eMids(edgeLabels_.size());
|
||||
|
||||
forAll(edgeLabels_, i)
|
||||
{
|
||||
const edge& e = edges_[edgeLabels_[i]];
|
||||
|
||||
eMids[i] = e.centre(points_);
|
||||
}
|
||||
return eMids;
|
||||
}
|
||||
|
||||
|
||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
||||
// Only makes sense for closed surfaces.
|
||||
Foam::label Foam::treeDataEdge::getVolumeType
|
||||
(
|
||||
const indexedOctree<treeDataEdge>& oc,
|
||||
const point& sample
|
||||
) const
|
||||
{
|
||||
return indexedOctree<treeDataEdge>::UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
// Check if any point on shape is inside cubeBb.
|
||||
bool Foam::treeDataEdge::overlaps
|
||||
(
|
||||
const label index,
|
||||
const treeBoundBox& cubeBb
|
||||
) const
|
||||
{
|
||||
if (cacheBb_)
|
||||
{
|
||||
return cubeBb.intersects(bbs_[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return cubeBb.intersects(calcBb(edgeLabels_[index]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Calculate nearest point to sample. Updates (if any) nearestDistSqr, minIndex,
|
||||
// nearestPoint.
|
||||
void Foam::treeDataEdge::findNearest
|
||||
(
|
||||
const labelList& indices,
|
||||
const point& sample,
|
||||
|
||||
scalar& nearestDistSqr,
|
||||
label& minIndex,
|
||||
point& nearestPoint
|
||||
) const
|
||||
{
|
||||
forAll(indices, i)
|
||||
{
|
||||
label index = indices[i];
|
||||
|
||||
const edge& e = edges_[index];
|
||||
|
||||
pointHit nearHit = e.line(points_).nearestDist(sample);
|
||||
|
||||
scalar distSqr = sqr(nearHit.distance());
|
||||
|
||||
if (distSqr < nearestDistSqr)
|
||||
{
|
||||
nearestDistSqr = distSqr;
|
||||
minIndex = index;
|
||||
nearestPoint = nearHit.rawPoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//- Calculates nearest (to line) point in shape.
|
||||
// Returns point and distance (squared)
|
||||
void Foam::treeDataEdge::findNearest
|
||||
(
|
||||
const labelList& indices,
|
||||
const linePointRef& ln,
|
||||
|
||||
treeBoundBox& tightest,
|
||||
label& minIndex,
|
||||
point& linePoint,
|
||||
point& nearestPoint
|
||||
) const
|
||||
{
|
||||
// Best so far
|
||||
scalar nearestDistSqr = magSqr(linePoint - nearestPoint);
|
||||
|
||||
forAll(indices, i)
|
||||
{
|
||||
label index = indices[i];
|
||||
|
||||
const edge& e = edges_[index];
|
||||
|
||||
// Note: could do bb test ? Worthwhile?
|
||||
|
||||
// Nearest point on line
|
||||
point ePoint, lnPt;
|
||||
scalar dist = e.line(points_).nearestDist(ln, ePoint, lnPt);
|
||||
scalar distSqr = sqr(dist);
|
||||
|
||||
if (distSqr < nearestDistSqr)
|
||||
{
|
||||
nearestDistSqr = distSqr;
|
||||
minIndex = index;
|
||||
linePoint = lnPt;
|
||||
nearestPoint = ePoint;
|
||||
|
||||
{
|
||||
point& minPt = tightest.min();
|
||||
minPt = min(ln.start(), ln.end());
|
||||
minPt.x() -= dist;
|
||||
minPt.y() -= dist;
|
||||
minPt.z() -= dist;
|
||||
}
|
||||
{
|
||||
point& maxPt = tightest.max();
|
||||
maxPt = max(ln.start(), ln.end());
|
||||
maxPt.x() += dist;
|
||||
maxPt.y() += dist;
|
||||
maxPt.z() += dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
191
src/meshTools/indexedOctree/treeDataEdge.H
Normal file
191
src/meshTools/indexedOctree/treeDataEdge.H
Normal file
@ -0,0 +1,191 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::treeDataEdge
|
||||
|
||||
Description
|
||||
Holds data for octree to work on an edges subset.
|
||||
|
||||
SourceFiles
|
||||
treeDataEdge.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef treeDataEdge_H
|
||||
#define treeDataEdge_H
|
||||
|
||||
#include "treeBoundBox.H"
|
||||
#include "pointField.H"
|
||||
#include "treeBoundBoxList.H"
|
||||
#include "linePointRef.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
template<class Type> class indexedOctree;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class treeDataEdge Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class treeDataEdge
|
||||
{
|
||||
// Static data
|
||||
|
||||
//- tolerance on linear dimensions
|
||||
static scalar tol;
|
||||
|
||||
|
||||
// Private data
|
||||
|
||||
//- Reference to edgeList
|
||||
const edgeList& edges_;
|
||||
|
||||
//- Reference to points
|
||||
const pointField& points_;
|
||||
|
||||
//- labels of edges
|
||||
const labelList edgeLabels_;
|
||||
|
||||
//- Whether to precalculate and store face bounding box
|
||||
const bool cacheBb_;
|
||||
|
||||
//- bbs for all above edges (valid only if cacheBb_)
|
||||
treeBoundBoxList bbs_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Calculate edge bounding box
|
||||
treeBoundBox calcBb(const label edgeI) const;
|
||||
|
||||
public:
|
||||
|
||||
// Declare name of the class and its debug switch
|
||||
ClassName("treeDataEdge");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from selected edges. !Holds references to edges and points
|
||||
treeDataEdge
|
||||
(
|
||||
const bool cacheBb,
|
||||
const edgeList& edges,
|
||||
const pointField& points,
|
||||
const labelList& edgeLabels
|
||||
);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
label size() const
|
||||
{
|
||||
return edgeLabels_.size();
|
||||
}
|
||||
|
||||
//- Get representative point cloud for all shapes inside
|
||||
// (one point per shape)
|
||||
pointField points() const;
|
||||
|
||||
|
||||
// Search
|
||||
|
||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
||||
// Only makes sense for closed surfaces.
|
||||
label getVolumeType
|
||||
(
|
||||
const indexedOctree<treeDataEdge>&,
|
||||
const point&
|
||||
) const;
|
||||
|
||||
//- Does (bb of) shape at index overlap bb
|
||||
bool overlaps
|
||||
(
|
||||
const label index,
|
||||
const treeBoundBox& sampleBb
|
||||
) const;
|
||||
|
||||
//- Calculates nearest (to sample) point in shape.
|
||||
// Returns actual point and distance (squared)
|
||||
void findNearest
|
||||
(
|
||||
const labelList& indices,
|
||||
const point& sample,
|
||||
|
||||
scalar& nearestDistSqr,
|
||||
label& nearestIndex,
|
||||
point& nearestPoint
|
||||
) const;
|
||||
|
||||
//- Calculates nearest (to line) point in shape.
|
||||
// Returns point and distance (squared)
|
||||
void findNearest
|
||||
(
|
||||
const labelList& indices,
|
||||
const linePointRef& ln,
|
||||
|
||||
treeBoundBox& tightest,
|
||||
label& minIndex,
|
||||
point& linePoint,
|
||||
point& nearestPoint
|
||||
) const;
|
||||
|
||||
//- Calculate intersection of shape with ray. Sets result
|
||||
// accordingly
|
||||
bool intersects
|
||||
(
|
||||
const label index,
|
||||
const point& start,
|
||||
const point& end,
|
||||
point& result
|
||||
) const
|
||||
{
|
||||
notImplemented
|
||||
(
|
||||
"treeDataEdge::intersects(const label, const point&,"
|
||||
"const point&, point&)"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
545
src/meshTools/indexedOctree/treeDataFace.C
Normal file
545
src/meshTools/indexedOctree/treeDataFace.C
Normal file
@ -0,0 +1,545 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "treeDataFace.H"
|
||||
#include "polyMesh.H"
|
||||
#include "triangleFuncs.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
defineTypeNameAndDebug(Foam::treeDataFace, 0);
|
||||
|
||||
Foam::scalar Foam::treeDataFace::tolSqr = sqr(1E-6);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::treeBoundBox Foam::treeDataFace::calcBb(const label faceI) const
|
||||
{
|
||||
const pointField& points = mesh_.points();
|
||||
|
||||
const face& f = mesh_.faces()[faceI];
|
||||
|
||||
treeBoundBox bb(points[f[0]], points[f[0]]);
|
||||
|
||||
for (label fp = 1; fp < f.size(); fp++)
|
||||
{
|
||||
const point& p = points[f[fp]];
|
||||
|
||||
bb.min() = min(bb.min(), p);
|
||||
bb.max() = max(bb.max(), p);
|
||||
}
|
||||
return bb;
|
||||
}
|
||||
|
||||
|
||||
void Foam::treeDataFace::update()
|
||||
{
|
||||
forAll(faceLabels_, i)
|
||||
{
|
||||
isTreeFace_.set(faceLabels_[i], 1);
|
||||
}
|
||||
|
||||
if (cacheBb_)
|
||||
{
|
||||
bbs_.setSize(faceLabels_.size());
|
||||
|
||||
forAll(faceLabels_, i)
|
||||
{
|
||||
bbs_[i] = calcBb(faceLabels_[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct from components
|
||||
Foam::treeDataFace::treeDataFace
|
||||
(
|
||||
const bool cacheBb,
|
||||
const primitiveMesh& mesh,
|
||||
const labelList& faceLabels
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
faceLabels_(faceLabels),
|
||||
isTreeFace_(mesh.nFaces(), 0),
|
||||
cacheBb_(cacheBb)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
Foam::treeDataFace::treeDataFace
|
||||
(
|
||||
const bool cacheBb,
|
||||
const primitiveMesh& mesh
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
faceLabels_(identity(mesh_.nFaces())),
|
||||
isTreeFace_(mesh.nFaces(), 0),
|
||||
cacheBb_(cacheBb)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
Foam::treeDataFace::treeDataFace
|
||||
(
|
||||
const bool cacheBb,
|
||||
const polyPatch& patch
|
||||
)
|
||||
:
|
||||
mesh_(patch.boundaryMesh().mesh()),
|
||||
faceLabels_
|
||||
(
|
||||
identity(patch.size())
|
||||
+ patch.start()
|
||||
),
|
||||
isTreeFace_(mesh_.nFaces(), 0),
|
||||
cacheBb_(cacheBb)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointField Foam::treeDataFace::points() const
|
||||
{
|
||||
pointField cc(faceLabels_.size());
|
||||
|
||||
forAll(faceLabels_, i)
|
||||
{
|
||||
cc[i] = mesh_.faceCentres()[faceLabels_[i]];
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
||||
// Only makes sense for closed surfaces.
|
||||
Foam::label Foam::treeDataFace::getVolumeType
|
||||
(
|
||||
const indexedOctree<treeDataFace>& oc,
|
||||
const point& sample
|
||||
) const
|
||||
{
|
||||
// Need to determine whether sample is 'inside' or 'outside'
|
||||
// Done by finding nearest face. This gives back a face which is
|
||||
// guaranteed to contain nearest point. This point can be
|
||||
// - in interior of face: compare to face normal
|
||||
// - on edge of face: compare to edge normal
|
||||
// - on point of face: compare to point normal
|
||||
// Unfortunately the octree does not give us back the intersection point
|
||||
// or where on the face it has hit so we have to recreate all that
|
||||
// information.
|
||||
|
||||
|
||||
// Find nearest face to sample
|
||||
pointIndexHit info = oc.findNearest(sample, sqr(GREAT));
|
||||
|
||||
if (info.index() == -1)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"treeDataFace::getSampleType"
|
||||
"(indexedOctree<treeDataFace>&, const point&)"
|
||||
) << "Could not find " << sample << " in octree."
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
|
||||
// Get actual intersection point on face
|
||||
label faceI = faceLabels_[info.index()];
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< "getSampleType : sample:" << sample
|
||||
<< " nearest face:" << faceI;
|
||||
}
|
||||
|
||||
const pointField& points = mesh_.points();
|
||||
|
||||
// Retest to classify where on face info is. Note: could be improved. We
|
||||
// already have point.
|
||||
|
||||
const face& f = mesh_.faces()[faceI];
|
||||
const vector& area = mesh_.faceAreas()[faceI];
|
||||
const point& fc = mesh_.faceCentres()[faceI];
|
||||
|
||||
pointHit curHit = f.nearestPoint(sample, points);
|
||||
const point& curPt = curHit.rawPoint();
|
||||
|
||||
//
|
||||
// 1] Check whether sample is above face
|
||||
//
|
||||
|
||||
if (curHit.hit())
|
||||
{
|
||||
// Nearest point inside face. Compare to face normal.
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< " -> face hit:" << curPt
|
||||
<< " comparing to face normal " << area << endl;
|
||||
}
|
||||
return indexedOctree<treeDataFace>::getSide(area, sample - curPt);
|
||||
}
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< " -> face miss:" << curPt;
|
||||
}
|
||||
|
||||
//
|
||||
// 2] Check whether intersection is on one of the face vertices or
|
||||
// face centre
|
||||
//
|
||||
|
||||
const scalar typDimSqr = mag(area) + VSMALL;
|
||||
|
||||
forAll(f, fp)
|
||||
{
|
||||
if ((magSqr(points[f[fp]] - curPt)/typDimSqr) < tolSqr)
|
||||
{
|
||||
// Face intersection point equals face vertex fp
|
||||
|
||||
// Calculate point normal (wrong: uses face normals instead of
|
||||
// triangle normals)
|
||||
const labelList& pFaces = mesh_.pointFaces()[f[fp]];
|
||||
|
||||
vector pointNormal(vector::zero);
|
||||
|
||||
forAll(pFaces, i)
|
||||
{
|
||||
if (isTreeFace_.get(pFaces[i]) == 1)
|
||||
{
|
||||
vector n = mesh_.faceAreas()[pFaces[i]];
|
||||
n /= mag(n) + VSMALL;
|
||||
|
||||
pointNormal += n;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< " -> face point hit :" << points[f[fp]]
|
||||
<< " point normal:" << pointNormal
|
||||
<< " distance:"
|
||||
<< magSqr(points[f[fp]] - curPt)/typDimSqr << endl;
|
||||
}
|
||||
return indexedOctree<treeDataFace>::getSide
|
||||
(
|
||||
pointNormal,
|
||||
sample - curPt
|
||||
);
|
||||
}
|
||||
}
|
||||
if ((magSqr(fc - curPt)/typDimSqr) < tolSqr)
|
||||
{
|
||||
// Face intersection point equals face centre. Normal at face centre
|
||||
// is already average of face normals
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< " -> centre hit:" << fc
|
||||
<< " distance:" << magSqr(fc - curPt)/typDimSqr << endl;
|
||||
}
|
||||
|
||||
return indexedOctree<treeDataFace>::getSide(area, sample - curPt);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// 3] Get the 'real' edge the face intersection is on
|
||||
//
|
||||
|
||||
const labelList& myEdges = mesh_.faceEdges()[faceI];
|
||||
|
||||
forAll(myEdges, myEdgeI)
|
||||
{
|
||||
const edge& e = mesh_.edges()[myEdges[myEdgeI]];
|
||||
|
||||
pointHit edgeHit =
|
||||
line<point, const point&>
|
||||
(
|
||||
points[e.start()],
|
||||
points[e.end()]
|
||||
).nearestDist(sample);
|
||||
|
||||
|
||||
if ((magSqr(edgeHit.rawPoint() - curPt)/typDimSqr) < tolSqr)
|
||||
{
|
||||
// Face intersection point lies on edge e
|
||||
|
||||
// Calculate edge normal (wrong: uses face normals instead of
|
||||
// triangle normals)
|
||||
const labelList& eFaces = mesh_.edgeFaces()[myEdges[myEdgeI]];
|
||||
|
||||
vector edgeNormal(vector::zero);
|
||||
|
||||
forAll(eFaces, i)
|
||||
{
|
||||
if (isTreeFace_.get(eFaces[i]) == 1)
|
||||
{
|
||||
vector n = mesh_.faceAreas()[eFaces[i]];
|
||||
n /= mag(n) + VSMALL;
|
||||
|
||||
edgeNormal += n;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< " -> real edge hit point:" << edgeHit.rawPoint()
|
||||
<< " comparing to edge normal:" << edgeNormal
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Found face intersection point on this edge. Compare to edge
|
||||
// normal
|
||||
return indexedOctree<treeDataFace>::getSide
|
||||
(
|
||||
edgeNormal,
|
||||
sample - curPt
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 4] Get the internal edge the face intersection is on
|
||||
//
|
||||
|
||||
forAll(f, fp)
|
||||
{
|
||||
pointHit edgeHit = line<point, const point&>
|
||||
(
|
||||
points[f[fp]],
|
||||
fc
|
||||
).nearestDist(sample);
|
||||
|
||||
if ((magSqr(edgeHit.rawPoint() - curPt)/typDimSqr) < tolSqr)
|
||||
{
|
||||
// Face intersection point lies on edge between two face triangles
|
||||
|
||||
// Calculate edge normal as average of the two triangle normals
|
||||
vector e = points[f[fp]] - fc;
|
||||
vector ePrev = points[f[f.rcIndex(fp)]] - fc;
|
||||
vector eNext = points[f[f.fcIndex(fp)]] - fc;
|
||||
|
||||
vector nLeft = ePrev ^ e;
|
||||
nLeft /= mag(nLeft) + VSMALL;
|
||||
|
||||
vector nRight = e ^ eNext;
|
||||
nRight /= mag(nRight) + VSMALL;
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< " -> internal edge hit point:" << edgeHit.rawPoint()
|
||||
<< " comparing to edge normal "
|
||||
<< 0.5*(nLeft + nRight)
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Found face intersection point on this edge. Compare to edge
|
||||
// normal
|
||||
return indexedOctree<treeDataFace>::getSide
|
||||
(
|
||||
0.5*(nLeft + nRight),
|
||||
sample - curPt
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (debug & 2)
|
||||
{
|
||||
Pout<< "Did not find sample " << sample
|
||||
<< " anywhere related to nearest face " << faceI << endl
|
||||
<< "Face:";
|
||||
|
||||
forAll(f, fp)
|
||||
{
|
||||
Pout<< " vertex:" << f[fp] << " coord:" << points[f[fp]]
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Can't determine status of sample with respect to nearest face.
|
||||
// Either
|
||||
// - tolerances are wrong. (if e.g. face has zero area)
|
||||
// - or (more likely) surface is not closed.
|
||||
|
||||
return indexedOctree<treeDataFace>::UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
// Check if any point on shape is inside cubeBb.
|
||||
bool Foam::treeDataFace::overlaps
|
||||
(
|
||||
const label index,
|
||||
const treeBoundBox& cubeBb
|
||||
) const
|
||||
{
|
||||
// 1. Quick rejection: bb does not intersect face bb at all
|
||||
if (cacheBb_)
|
||||
{
|
||||
if (!cubeBb.intersects(bbs_[index]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!cubeBb.intersects(calcBb(faceLabels_[index])))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const pointField& points = mesh_.points();
|
||||
|
||||
|
||||
// 2. Check if one or more face points inside
|
||||
label faceI = faceLabels_[index];
|
||||
|
||||
const face& f = mesh_.faces()[faceI];
|
||||
|
||||
forAll(f, fp)
|
||||
{
|
||||
if (cubeBb.contains(points[f[fp]]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Difficult case: all points are outside but connecting edges might
|
||||
// go through cube. Use triangle-bounding box intersection.
|
||||
const point& fc = mesh_.faceCentres()[faceI];
|
||||
|
||||
forAll(f, fp)
|
||||
{
|
||||
bool triIntersects = triangleFuncs::intersectBb
|
||||
(
|
||||
points[f[fp]],
|
||||
points[f[f.fcIndex(fp)]],
|
||||
fc,
|
||||
cubeBb
|
||||
);
|
||||
|
||||
if (triIntersects)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Calculate nearest point to sample. Updates (if any) nearestDistSqr, minIndex,
|
||||
// nearestPoint.
|
||||
void Foam::treeDataFace::findNearest
|
||||
(
|
||||
const labelList& indices,
|
||||
const point& sample,
|
||||
|
||||
scalar& nearestDistSqr,
|
||||
label& minIndex,
|
||||
point& nearestPoint
|
||||
) const
|
||||
{
|
||||
forAll(indices, i)
|
||||
{
|
||||
label index = indices[i];
|
||||
|
||||
const face& f = mesh_.faces()[faceLabels_[index]];
|
||||
|
||||
pointHit nearHit = f.nearestPoint(sample, mesh_.points());
|
||||
scalar distSqr = sqr(nearHit.distance());
|
||||
|
||||
if (distSqr < nearestDistSqr)
|
||||
{
|
||||
nearestDistSqr = distSqr;
|
||||
minIndex = index;
|
||||
nearestPoint = nearHit.rawPoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::treeDataFace::intersects
|
||||
(
|
||||
const label index,
|
||||
const point& start,
|
||||
const point& end,
|
||||
point& intersectionPoint
|
||||
) const
|
||||
{
|
||||
// Do quick rejection test
|
||||
if (cacheBb_)
|
||||
{
|
||||
const treeBoundBox& faceBb = bbs_[index];
|
||||
|
||||
if ((faceBb.posBits(start) & faceBb.posBits(end)) != 0)
|
||||
{
|
||||
// start and end in same block outside of faceBb.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
label faceI = faceLabels_[index];
|
||||
|
||||
const vector dir(end - start);
|
||||
|
||||
pointHit inter = mesh_.faces()[faceI].intersection
|
||||
(
|
||||
start,
|
||||
dir,
|
||||
mesh_.faceCentres()[faceI],
|
||||
mesh_.points(),
|
||||
intersection::HALF_RAY
|
||||
);
|
||||
|
||||
if (inter.hit() && inter.distance() <= 1)
|
||||
{
|
||||
// Note: no extra test on whether intersection is in front of us
|
||||
// since using half_ray
|
||||
intersectionPoint = inter.hitPoint();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
210
src/meshTools/indexedOctree/treeDataFace.H
Normal file
210
src/meshTools/indexedOctree/treeDataFace.H
Normal file
@ -0,0 +1,210 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::treeDataFace
|
||||
|
||||
Description
|
||||
Encapsulation of data needed to search for faces.
|
||||
|
||||
SourceFiles
|
||||
treeDataFace.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef treeDataFace_H
|
||||
#define treeDataFace_H
|
||||
|
||||
#include "face.H"
|
||||
#include "indexedOctree.H"
|
||||
#include "treeBoundBoxList.H"
|
||||
#include "PackedList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
class primitiveMesh;
|
||||
//template<class Type> class indexedOctree;
|
||||
class polyPatch;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class treeDataFace Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class treeDataFace
|
||||
{
|
||||
// Static data
|
||||
|
||||
//- tolerance on linear dimensions
|
||||
static scalar tolSqr;
|
||||
|
||||
|
||||
|
||||
// Private data
|
||||
|
||||
const primitiveMesh& mesh_;
|
||||
|
||||
//- Subset of faces to work on
|
||||
const labelList faceLabels_;
|
||||
|
||||
//- Inverse of faceLabels. For every mesh whether face is in faceLabels.
|
||||
PackedList<1> isTreeFace_;
|
||||
|
||||
//- Whether to precalculate and store face bounding box
|
||||
const bool cacheBb_;
|
||||
|
||||
//- face bounding boxes (valid only if cacheBb_)
|
||||
treeBoundBoxList bbs_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Calculate face bounding box
|
||||
treeBoundBox calcBb(const label cellI) const;
|
||||
|
||||
//- Initialise all member data
|
||||
void update();
|
||||
|
||||
public:
|
||||
|
||||
// Declare name of the class and its debug switch
|
||||
ClassName("treeDataFace");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from mesh and subset of cells.
|
||||
treeDataFace
|
||||
(
|
||||
const bool cacheBb,
|
||||
const primitiveMesh&,
|
||||
const labelList&
|
||||
);
|
||||
|
||||
//- Construct from mesh. Uses all faces in mesh.
|
||||
treeDataFace(const bool cacheBb, const primitiveMesh&);
|
||||
|
||||
//- Construct from mesh. Uses all faces in patch.
|
||||
treeDataFace(const bool cacheBb, const polyPatch&);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
const labelList& faceLabels() const
|
||||
{
|
||||
return faceLabels_;
|
||||
}
|
||||
|
||||
const primitiveMesh& mesh() const
|
||||
{
|
||||
return mesh_;
|
||||
}
|
||||
|
||||
label size() const
|
||||
{
|
||||
return faceLabels_.size();
|
||||
}
|
||||
|
||||
//- Get representative point cloud for all shapes inside
|
||||
// (one point per shape)
|
||||
pointField points() const;
|
||||
|
||||
|
||||
// Search
|
||||
|
||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
||||
// Only makes sense for closed surfaces.
|
||||
label getVolumeType
|
||||
(
|
||||
const indexedOctree<treeDataFace>&,
|
||||
const point&
|
||||
) const;
|
||||
|
||||
//- Does (bb of) shape at index overlap bb
|
||||
bool overlaps
|
||||
(
|
||||
const label index,
|
||||
const treeBoundBox& sampleBb
|
||||
) const;
|
||||
|
||||
//- Calculates nearest (to sample) point in shape.
|
||||
// Returns actual point and distance (squared)
|
||||
void findNearest
|
||||
(
|
||||
const labelList& indices,
|
||||
const point& sample,
|
||||
|
||||
scalar& nearestDistSqr,
|
||||
label& nearestIndex,
|
||||
point& nearestPoint
|
||||
) const;
|
||||
|
||||
//- Calculates nearest (to line) point in shape.
|
||||
// Returns point and distance (squared)
|
||||
void findNearest
|
||||
(
|
||||
const labelList& indices,
|
||||
const linePointRef& ln,
|
||||
|
||||
treeBoundBox& tightest,
|
||||
label& minIndex,
|
||||
point& linePoint,
|
||||
point& nearestPoint
|
||||
) const
|
||||
{
|
||||
notImplemented
|
||||
(
|
||||
"treeDataFace::findNearest"
|
||||
"(const labelList&, const linePointRef&, ..)"
|
||||
);
|
||||
}
|
||||
|
||||
//- Calculate intersection of shape with ray. Sets result
|
||||
// accordingly
|
||||
bool intersects
|
||||
(
|
||||
const label index,
|
||||
const point& start,
|
||||
const point& end,
|
||||
point& result
|
||||
) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
160
src/meshTools/indexedOctree/treeDataPoint.C
Normal file
160
src/meshTools/indexedOctree/treeDataPoint.C
Normal file
@ -0,0 +1,160 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Description
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "treeDataPoint.H"
|
||||
#include "treeBoundBox.H"
|
||||
#include "indexedOctree.H"
|
||||
#include "polyMesh.H"
|
||||
#include "triangleFuncs.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct from components
|
||||
Foam::treeDataPoint::treeDataPoint(const pointField& points)
|
||||
:
|
||||
points_(points)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointField Foam::treeDataPoint::points() const
|
||||
{
|
||||
return points_;
|
||||
}
|
||||
|
||||
|
||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
||||
// Only makes sense for closed surfaces.
|
||||
Foam::label Foam::treeDataPoint::getVolumeType
|
||||
(
|
||||
const indexedOctree<treeDataPoint>& oc,
|
||||
const point& sample
|
||||
) const
|
||||
{
|
||||
return indexedOctree<treeDataPoint>::UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
// Check if any point on shape is inside cubeBb.
|
||||
bool Foam::treeDataPoint::overlaps
|
||||
(
|
||||
const label index,
|
||||
const treeBoundBox& cubeBb
|
||||
) const
|
||||
{
|
||||
return cubeBb.contains(points_[index]);
|
||||
}
|
||||
|
||||
|
||||
// Calculate nearest point to sample. Updates (if any) nearestDistSqr, minIndex,
|
||||
// nearestPoint.
|
||||
void Foam::treeDataPoint::findNearest
|
||||
(
|
||||
const labelList& indices,
|
||||
const point& sample,
|
||||
|
||||
scalar& nearestDistSqr,
|
||||
label& minIndex,
|
||||
point& nearestPoint
|
||||
) const
|
||||
{
|
||||
forAll(indices, i)
|
||||
{
|
||||
label index = indices[i];
|
||||
|
||||
const point& pt = points_[index];
|
||||
|
||||
scalar distSqr = magSqr(pt - sample);
|
||||
|
||||
if (distSqr < nearestDistSqr)
|
||||
{
|
||||
nearestDistSqr = distSqr;
|
||||
minIndex = index;
|
||||
nearestPoint = pt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//- Calculates nearest (to line) point in shape.
|
||||
// Returns point and distance (squared)
|
||||
void Foam::treeDataPoint::findNearest
|
||||
(
|
||||
const labelList& indices,
|
||||
const linePointRef& ln,
|
||||
|
||||
treeBoundBox& tightest,
|
||||
label& minIndex,
|
||||
point& linePoint,
|
||||
point& nearestPoint
|
||||
) const
|
||||
{
|
||||
// Best so far
|
||||
scalar nearestDistSqr = magSqr(linePoint - nearestPoint);
|
||||
|
||||
forAll(indices, i)
|
||||
{
|
||||
label index = indices[i];
|
||||
|
||||
const point& shapePt = points_[index];
|
||||
|
||||
if (tightest.contains(shapePt))
|
||||
{
|
||||
// Nearest point on line
|
||||
pointHit pHit = ln.nearestDist(shapePt);
|
||||
scalar distSqr = sqr(pHit.distance());
|
||||
|
||||
if (distSqr < nearestDistSqr)
|
||||
{
|
||||
nearestDistSqr = distSqr;
|
||||
minIndex = index;
|
||||
linePoint = pHit.rawPoint();
|
||||
nearestPoint = shapePt;
|
||||
|
||||
{
|
||||
point& minPt = tightest.min();
|
||||
minPt = min(ln.start(), ln.end());
|
||||
minPt.x() -= pHit.distance();
|
||||
minPt.y() -= pHit.distance();
|
||||
minPt.z() -= pHit.distance();
|
||||
}
|
||||
{
|
||||
point& maxPt = tightest.max();
|
||||
maxPt = max(ln.start(), ln.end());
|
||||
maxPt.x() += pHit.distance();
|
||||
maxPt.y() += pHit.distance();
|
||||
maxPt.z() += pHit.distance();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
162
src/meshTools/indexedOctree/treeDataPoint.H
Normal file
162
src/meshTools/indexedOctree/treeDataPoint.H
Normal file
@ -0,0 +1,162 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::treeDataPoint
|
||||
|
||||
Description
|
||||
Holds (reference to) pointField. Encapsulation of data needed for
|
||||
octree searches.
|
||||
Used for searching for nearest point. No bounding boxes around points.
|
||||
Only overlaps and calcNearest are implemented, rest makes little sense.
|
||||
|
||||
SourceFiles
|
||||
treeDataPoint.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef treeDataPoint_H
|
||||
#define treeDataPoint_H
|
||||
|
||||
#include "pointField.H"
|
||||
#include "treeBoundBox.H"
|
||||
#include "linePointRef.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
template<class Type> class indexedOctree;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class treeDataPoint Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class treeDataPoint
|
||||
{
|
||||
// Private data
|
||||
|
||||
const pointField& points_;
|
||||
|
||||
public:
|
||||
|
||||
// Declare name of the class and its debug switch
|
||||
ClassName("treeDataPoint");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components. Holds reference to points!
|
||||
treeDataPoint(const pointField& points);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
label size() const
|
||||
{
|
||||
return points_.size();
|
||||
}
|
||||
|
||||
//- Get representative point cloud for all shapes inside
|
||||
// (one point per shape)
|
||||
pointField points() const;
|
||||
|
||||
|
||||
// Search
|
||||
|
||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
||||
// Only makes sense for closed surfaces.
|
||||
label getVolumeType
|
||||
(
|
||||
const indexedOctree<treeDataPoint>&,
|
||||
const point&
|
||||
) const;
|
||||
|
||||
//- Does (bb of) shape at index overlap bb
|
||||
bool overlaps
|
||||
(
|
||||
const label index,
|
||||
const treeBoundBox& sampleBb
|
||||
) const;
|
||||
|
||||
//- Calculates nearest (to sample) point in shape.
|
||||
// Returns actual point and distance (squared)
|
||||
void findNearest
|
||||
(
|
||||
const labelList& indices,
|
||||
const point& sample,
|
||||
|
||||
scalar& nearestDistSqr,
|
||||
label& nearestIndex,
|
||||
point& nearestPoint
|
||||
) const;
|
||||
|
||||
//- Calculates nearest (to line) point in shape.
|
||||
// Returns point and distance (squared)
|
||||
void findNearest
|
||||
(
|
||||
const labelList& indices,
|
||||
const linePointRef& ln,
|
||||
|
||||
treeBoundBox& tightest,
|
||||
label& minIndex,
|
||||
point& linePoint,
|
||||
point& nearestPoint
|
||||
) const;
|
||||
|
||||
//- Calculate intersection of shape with ray. Sets result
|
||||
// accordingly
|
||||
bool intersects
|
||||
(
|
||||
const label index,
|
||||
const point& start,
|
||||
const point& end,
|
||||
point& result
|
||||
) const
|
||||
{
|
||||
notImplemented
|
||||
(
|
||||
"treeDataPoint::intersects(const label, const point&,"
|
||||
"const point&, point&)"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -27,7 +27,6 @@ Description
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "treeDataTriSurface.H"
|
||||
#include "treeBoundBox.H"
|
||||
#include "triSurfaceTools.H"
|
||||
#include "triangleFuncs.H"
|
||||
#include "indexedOctree.H"
|
||||
@ -426,14 +425,12 @@ bool Foam::treeDataTriSurface::intersects
|
||||
|
||||
const labelledTri& f = surface_[index];
|
||||
|
||||
const triPointRef tri(points[f[0]], points[f[1]], points[f[2]]);
|
||||
|
||||
// Do quick rejection test
|
||||
treeBoundBox triBb(tri.a(), tri.a());
|
||||
triBb.min() = min(triBb.min(), tri.b());
|
||||
triBb.max() = max(triBb.max(), tri.b());
|
||||
triBb.min() = min(triBb.min(), tri.c());
|
||||
triBb.max() = max(triBb.max(), tri.c());
|
||||
treeBoundBox triBb(points[f[0]], points[f[0]]);
|
||||
triBb.min() = min(triBb.min(), points[f[1]]);
|
||||
triBb.max() = max(triBb.max(), points[f[1]]);
|
||||
triBb.min() = min(triBb.min(), points[f[2]]);
|
||||
triBb.max() = max(triBb.max(), points[f[2]]);
|
||||
|
||||
const direction startBits(triBb.posBits(start));
|
||||
const direction endBits(triBb.posBits(end));
|
||||
@ -444,20 +441,16 @@ bool Foam::treeDataTriSurface::intersects
|
||||
return false;
|
||||
}
|
||||
|
||||
const triPointRef tri(points[f[0]], points[f[1]], points[f[2]]);
|
||||
|
||||
const vector dir(end - start);
|
||||
|
||||
// Disable picking up intersections behind us.
|
||||
scalar oldTol = intersection::setPlanarTol(0.0);
|
||||
pointHit inter = tri.intersection(start, dir, intersection::HALF_RAY);
|
||||
|
||||
pointHit inter = tri.ray(start, dir, intersection::HALF_RAY);
|
||||
|
||||
intersection::setPlanarTol(oldTol);
|
||||
|
||||
if (inter.hit() && sqr(inter.distance()) <= magSqr(dir))
|
||||
if (inter.hit() && inter.distance() <= 1)
|
||||
{
|
||||
// Note: no extra test on whether intersection is in front of us
|
||||
// since using half_ray AND zero tolerance. (note that tolerance
|
||||
// is used to look behind us)
|
||||
// since using half_ray.
|
||||
intersectionPoint = inter.hitPoint();
|
||||
|
||||
return true;
|
||||
|
||||
@ -37,23 +37,51 @@ namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
treeBoundBox treeBoundBox::greatBox
|
||||
const treeBoundBox treeBoundBox::greatBox
|
||||
(
|
||||
vector(-GREAT, -GREAT, -GREAT),
|
||||
vector(GREAT, GREAT, GREAT)
|
||||
);
|
||||
|
||||
|
||||
const faceList treeBoundBox::faces
|
||||
(
|
||||
Foam::IStringStream
|
||||
(
|
||||
"6("
|
||||
"4(0 4 6 2)" // left
|
||||
"4(1 3 7 5)" // right
|
||||
"4(0 1 5 4)" // bottom
|
||||
"4(2 6 7 3)" // top
|
||||
"4(0 2 3 1)" // back
|
||||
"4(4 5 7 6)" // front
|
||||
")"
|
||||
)()
|
||||
);
|
||||
|
||||
|
||||
const edgeList treeBoundBox::edges
|
||||
(
|
||||
//treeBoundBox::edges()
|
||||
Foam::IStringStream
|
||||
(
|
||||
//(E01)(E13)(E23)(E02)(E45)(E57)(E67)(E46)(E04)(E15)(E37)(E26)
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11
|
||||
"12((0 1)(1 3)(2 3)(0 2)(4 5)(5 7)(6 7)(4 6)(0 4)(1 5)(3 7)(2 6))"
|
||||
)()
|
||||
);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct as the bounding box of the given pointField
|
||||
treeBoundBox::treeBoundBox(const pointField& points)
|
||||
treeBoundBox::treeBoundBox(const UList<point>& points)
|
||||
:
|
||||
boundBox()
|
||||
{
|
||||
if (points.size() == 0)
|
||||
{
|
||||
WarningIn("treeBoundBox::treeBoundBox(const pointField& points)")
|
||||
WarningIn("treeBoundBox::treeBoundBox(const UList<point>&)")
|
||||
<< "cannot find bounding box for zero sized pointField"
|
||||
<< "returning zero" << endl;
|
||||
|
||||
@ -63,7 +91,7 @@ treeBoundBox::treeBoundBox(const pointField& points)
|
||||
min() = points[0];
|
||||
max() = points[0];
|
||||
|
||||
forAll(points, i)
|
||||
for (label i = 1; i < points.size(); i++)
|
||||
{
|
||||
min() = ::Foam::min(min(), points[i]);
|
||||
max() = ::Foam::max(max(), points[i]);
|
||||
@ -71,6 +99,37 @@ treeBoundBox::treeBoundBox(const pointField& points)
|
||||
}
|
||||
|
||||
|
||||
// Construct as the bounding box of the given pointField
|
||||
treeBoundBox::treeBoundBox
|
||||
(
|
||||
const UList<point>& points,
|
||||
const labelList& meshPoints
|
||||
)
|
||||
:
|
||||
boundBox()
|
||||
{
|
||||
if (meshPoints.size() == 0)
|
||||
{
|
||||
WarningIn
|
||||
(
|
||||
"treeBoundBox::treeBoundBox(const UList<point>&, const labelList)"
|
||||
) << "cannot find bounding box for zero sized pointField"
|
||||
<< "returning zero" << endl;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
min() = points[meshPoints[0]];
|
||||
max() = points[meshPoints[0]];
|
||||
|
||||
for (label i = 1; i < meshPoints.size(); i++)
|
||||
{
|
||||
min() = ::Foam::min(min(), points[meshPoints[i]]);
|
||||
max() = ::Foam::max(max(), points[meshPoints[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Construct from Istream
|
||||
treeBoundBox::treeBoundBox(Istream& is)
|
||||
:
|
||||
@ -80,104 +139,18 @@ treeBoundBox::treeBoundBox(Istream& is)
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
scalar treeBoundBox::minDim() const
|
||||
{
|
||||
return ::Foam::min
|
||||
(
|
||||
max().x() - min().x(),
|
||||
::Foam::min
|
||||
(
|
||||
max().y() - min().y(),
|
||||
max().z() - min().z()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
scalar treeBoundBox::maxDim() const
|
||||
{
|
||||
return ::Foam::max
|
||||
(
|
||||
max().x() - min().x(),
|
||||
::Foam::max
|
||||
(
|
||||
max().y() - min().y(),
|
||||
max().z() - min().z()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
scalar treeBoundBox::avgDim() const
|
||||
{
|
||||
return
|
||||
(
|
||||
(max().x() - min().x()) +
|
||||
(max().y() - min().y()) +
|
||||
(max().z() - min().z())
|
||||
)/3.0;
|
||||
}
|
||||
|
||||
|
||||
scalar treeBoundBox::typDim() const
|
||||
{
|
||||
return avgDim();
|
||||
}
|
||||
|
||||
|
||||
point treeBoundBox::mid() const
|
||||
{
|
||||
return 0.5*(min() + max());
|
||||
}
|
||||
|
||||
|
||||
pointField treeBoundBox::points() const
|
||||
{
|
||||
pointField points(8);
|
||||
label pointI = 0;
|
||||
|
||||
points[pointI++] = min();
|
||||
points[pointI++] = point(min().x(), max().y(), min().z());
|
||||
points[pointI++] = point(max().x(), max().y(), min().z());
|
||||
points[pointI++] = point(max().x(), min().y(), min().z());
|
||||
|
||||
points[pointI++] = point(min().x(), min().y(), max().z());
|
||||
points[pointI++] = point(min().x(), max().y(), max().z());
|
||||
points[pointI++] = max();
|
||||
points[pointI++] = point(max().x(), min().y(), max().z());
|
||||
forAll(points, octant)
|
||||
{
|
||||
points[octant] = corner(octant);
|
||||
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
|
||||
edgeList treeBoundBox::edges() const
|
||||
{
|
||||
edgeList edges(12);
|
||||
label edgeI = 0;
|
||||
|
||||
// bottom face
|
||||
edges[edgeI++] = edge(0, 1);
|
||||
edges[edgeI++] = edge(1, 2);
|
||||
edges[edgeI++] = edge(2, 3);
|
||||
edges[edgeI++] = edge(3, 0);
|
||||
|
||||
// top face
|
||||
edges[edgeI++] = edge(4, 5);
|
||||
edges[edgeI++] = edge(5, 6);
|
||||
edges[edgeI++] = edge(6, 7);
|
||||
edges[edgeI++] = edge(7, 4);
|
||||
|
||||
// side edges
|
||||
edges[edgeI++] = edge(0, 4);
|
||||
edges[edgeI++] = edge(1, 5);
|
||||
edges[edgeI++] = edge(2, 6);
|
||||
edges[edgeI++] = edge(3, 7);
|
||||
|
||||
return edges;
|
||||
}
|
||||
|
||||
|
||||
// Octant to bounding box
|
||||
treeBoundBox treeBoundBox::subBbox(const direction octant) const
|
||||
{
|
||||
if (octant > 7)
|
||||
@ -362,7 +335,7 @@ bool treeBoundBox::intersects
|
||||
}
|
||||
}
|
||||
|
||||
if (ptBits & BELOWBIT)
|
||||
if (ptBits & BOTTOMBIT)
|
||||
{
|
||||
// Intersect with plane V=min, n=0,-1,0
|
||||
if (Foam::mag(vec.y()) > VSMALL)
|
||||
@ -373,7 +346,7 @@ bool treeBoundBox::intersects
|
||||
pt.z() = pt.z() + vec.z()*s;
|
||||
}
|
||||
}
|
||||
if (ptBits & ABOVEBIT)
|
||||
if (ptBits & TOPBIT)
|
||||
{
|
||||
// Intersect with plane V=max, n=0,1,0
|
||||
if (Foam::mag(vec.y()) > VSMALL)
|
||||
@ -385,7 +358,7 @@ bool treeBoundBox::intersects
|
||||
}
|
||||
}
|
||||
|
||||
if (ptBits & BEHINDBIT)
|
||||
if (ptBits & BACKBIT)
|
||||
{
|
||||
// Intersect with plane V=min, n=0,0,-1
|
||||
if (Foam::mag(vec.z()) > VSMALL)
|
||||
@ -396,7 +369,7 @@ bool treeBoundBox::intersects
|
||||
pt.z() = min().z();
|
||||
}
|
||||
}
|
||||
if (ptBits & INFRONTBIT)
|
||||
if (ptBits & FRONTBIT)
|
||||
{
|
||||
// Intersect with plane V=max, n=0,0,1
|
||||
if (Foam::mag(vec.z()) > VSMALL)
|
||||
@ -487,20 +460,20 @@ direction treeBoundBox::posBits(const point& pt) const
|
||||
|
||||
if (pt.y() < min().y())
|
||||
{
|
||||
posBits |= BELOWBIT;
|
||||
posBits |= BOTTOMBIT;
|
||||
}
|
||||
if (pt.y() > max().y())
|
||||
{
|
||||
posBits |= ABOVEBIT;
|
||||
posBits |= TOPBIT;
|
||||
}
|
||||
|
||||
if (pt.z() < min().z())
|
||||
{
|
||||
posBits |= BEHINDBIT;
|
||||
posBits |= BACKBIT;
|
||||
}
|
||||
if (pt.z() > max().z())
|
||||
{
|
||||
posBits |= INFRONTBIT;
|
||||
posBits |= FRONTBIT;
|
||||
}
|
||||
return posBits;
|
||||
}
|
||||
|
||||
@ -26,7 +26,25 @@ Class
|
||||
Foam::treeBoundBox
|
||||
|
||||
Description
|
||||
Standard boundBox with extra functionality for use in octree.
|
||||
Standard boundBox + extra functionality for use in octree.
|
||||
|
||||
Numbering of corner points is according to octant numbering.
|
||||
|
||||
On the back plane (z=0):
|
||||
|
||||
Y
|
||||
^
|
||||
|
|
||||
+--------+
|
||||
|2 3|
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
|0 1|
|
||||
+--------+->X
|
||||
|
||||
For the front plane add 4 to the point labels.
|
||||
|
||||
|
||||
SourceFiles
|
||||
treeBoundBoxI.H
|
||||
@ -40,7 +58,7 @@ SourceFiles
|
||||
#include "boundBox.H"
|
||||
#include "direction.H"
|
||||
#include "pointField.H"
|
||||
#include "edgeList.H"
|
||||
#include "faceList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -62,21 +80,66 @@ public:
|
||||
|
||||
// Static data members
|
||||
|
||||
static treeBoundBox greatBox;
|
||||
static const treeBoundBox greatBox;
|
||||
|
||||
// Bits used for octant coding
|
||||
static const direction RIGHTHALF = 0x1 << 0;
|
||||
static const direction TOPHALF = 0x1 << 1;
|
||||
static const direction FRONTHALF = 0x1 << 2;
|
||||
//- Bits used for octant/point coding. Every octant/corner point
|
||||
// is the combination of three faces.
|
||||
enum octantBit
|
||||
{
|
||||
RIGHTHALF = 0x1 << 0,
|
||||
TOPHALF = 0x1 << 1,
|
||||
FRONTHALF = 0x1 << 2
|
||||
};
|
||||
|
||||
//- Face codes
|
||||
enum faceId
|
||||
{
|
||||
LEFT = 0,
|
||||
RIGHT = 1,
|
||||
BOTTOM = 2,
|
||||
TOP = 3,
|
||||
BACK = 4,
|
||||
FRONT = 5
|
||||
};
|
||||
|
||||
//- Bits used for face coding
|
||||
enum faceBit
|
||||
{
|
||||
NOFACE = 0,
|
||||
LEFTBIT = 0x1 << LEFT,
|
||||
RIGHTBIT = 0x1 << RIGHT,
|
||||
BOTTOMBIT = 0x1 << BOTTOM,
|
||||
TOPBIT = 0x1 << TOP,
|
||||
BACKBIT = 0x1 << BACK,
|
||||
FRONTBIT = 0x1 << FRONT,
|
||||
};
|
||||
|
||||
//- Edges codes.
|
||||
// E01 = edge between 0 and 1.
|
||||
enum edgeId
|
||||
{
|
||||
E01 = 0,
|
||||
E13 = 1,
|
||||
E23 = 2,
|
||||
E02 = 3,
|
||||
|
||||
E45 = 4,
|
||||
E57 = 5,
|
||||
E67 = 6,
|
||||
E46 = 7,
|
||||
|
||||
E04 = 8,
|
||||
E15 = 9,
|
||||
E37 = 10,
|
||||
E26 = 11
|
||||
};
|
||||
|
||||
//- Face to point addressing
|
||||
static const faceList faces;
|
||||
|
||||
//- Edge to point addressing
|
||||
static const edgeList edges;
|
||||
|
||||
// Bits used for face coding
|
||||
static const direction NOFACE = 0;
|
||||
static const direction LEFTBIT = 0x1 << 0;
|
||||
static const direction RIGHTBIT = 0x1 << 1;
|
||||
static const direction BELOWBIT = 0x1 << 2;
|
||||
static const direction ABOVEBIT = 0x1 << 3;
|
||||
static const direction BEHINDBIT = 0x1 << 4;
|
||||
static const direction INFRONTBIT = 0x1 << 5;
|
||||
|
||||
//- Face on which neighbour is
|
||||
static direction neighbourFaceBits(const label&);
|
||||
@ -95,7 +158,10 @@ public:
|
||||
|
||||
//- Construct as the bounding box of the given pointField. Local
|
||||
// processor domain only (no reduce as in boundBox)
|
||||
treeBoundBox(const pointField& points);
|
||||
treeBoundBox(const UList<point>& points);
|
||||
|
||||
//- Construct as subset of points
|
||||
treeBoundBox(const UList<point>&, const labelList& meshPoints);
|
||||
|
||||
//- Construct from Istream
|
||||
treeBoundBox(Istream&);
|
||||
@ -106,28 +172,28 @@ public:
|
||||
// Access
|
||||
|
||||
//- Smallest of length,height,width
|
||||
scalar minDim() const;
|
||||
inline scalar minDim() const;
|
||||
|
||||
//- Largest of length,height,width
|
||||
scalar maxDim() const;
|
||||
inline scalar maxDim() const;
|
||||
|
||||
//- Average of length,height,width
|
||||
scalar avgDim() const;
|
||||
inline scalar avgDim() const;
|
||||
|
||||
//- Typical dimension length,height,width
|
||||
scalar typDim() const;
|
||||
inline scalar typDim() const;
|
||||
|
||||
//- vertex coordinates
|
||||
//- vertex coordinates. In octant coding.
|
||||
pointField points() const;
|
||||
|
||||
//- edges expressed in terms of points()
|
||||
edgeList edges() const;
|
||||
|
||||
|
||||
// Check
|
||||
|
||||
//- Corner point given octant
|
||||
inline point corner(const direction) const;
|
||||
|
||||
//- Calculates midpoint
|
||||
point mid() const;
|
||||
inline point mid() const;
|
||||
|
||||
//- Sub box given by octant number. Midpoint calculated.
|
||||
treeBoundBox subBbox(const direction) const;
|
||||
@ -178,6 +244,15 @@ public:
|
||||
bool& onEdge
|
||||
);
|
||||
|
||||
//- Calculates optimal order to look for nearest to sample. First
|
||||
// will be the octant containing the sample, second the octant
|
||||
// with boundary nearest to the sample etc.
|
||||
inline void searchOrder
|
||||
(
|
||||
const point& sample,
|
||||
FixedList<direction, 8>& octantOrder
|
||||
) const;
|
||||
|
||||
//- Intersects other boundingbox?
|
||||
inline bool intersects(const treeBoundBox&) const;
|
||||
|
||||
|
||||
@ -59,26 +59,85 @@ inline treeBoundBox::treeBoundBox(const boundBox& bb)
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
inline scalar treeBoundBox::minDim() const
|
||||
{
|
||||
return ::Foam::min
|
||||
(
|
||||
max().x() - min().x(),
|
||||
::Foam::min
|
||||
(
|
||||
max().y() - min().y(),
|
||||
max().z() - min().z()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
inline scalar treeBoundBox::maxDim() const
|
||||
{
|
||||
return ::Foam::max
|
||||
(
|
||||
max().x() - min().x(),
|
||||
::Foam::max
|
||||
(
|
||||
max().y() - min().y(),
|
||||
max().z() - min().z()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
inline scalar treeBoundBox::avgDim() const
|
||||
{
|
||||
return
|
||||
(
|
||||
(max().x() - min().x()) +
|
||||
(max().y() - min().y()) +
|
||||
(max().z() - min().z())
|
||||
)/3.0;
|
||||
}
|
||||
|
||||
|
||||
inline scalar treeBoundBox::typDim() const
|
||||
{
|
||||
return avgDim();
|
||||
}
|
||||
|
||||
|
||||
inline point treeBoundBox::mid() const
|
||||
{
|
||||
return 0.5*(min() + max());
|
||||
}
|
||||
|
||||
|
||||
inline point treeBoundBox::corner(const direction octant) const
|
||||
{
|
||||
return point
|
||||
(
|
||||
(octant&RIGHTHALF) ? max().x() : min().x(),
|
||||
(octant&TOPHALF) ? max().y() : min().y(),
|
||||
(octant&FRONTHALF) ? max().z() : min().z()
|
||||
);
|
||||
}
|
||||
|
||||
// Returns octant in which sample resides. Reverse of subBbox.
|
||||
inline direction treeBoundBox::subOctant(const point& sample) const
|
||||
{
|
||||
scalar midx = 0.5*(max().x() + min().x());
|
||||
scalar midy = 0.5*(max().y() + min().y());
|
||||
scalar midz = 0.5*(max().z() + min().z());
|
||||
point mid = 0.5*(max() + min());
|
||||
|
||||
direction octant = 0;
|
||||
|
||||
if (sample.x() > midx)
|
||||
if (sample.x() > mid.x())
|
||||
{
|
||||
octant |= treeBoundBox::RIGHTHALF;
|
||||
}
|
||||
|
||||
if (sample.y() > midy)
|
||||
if (sample.y() > mid.y())
|
||||
{
|
||||
octant |= treeBoundBox::TOPHALF;
|
||||
}
|
||||
|
||||
if (sample.z() > midz)
|
||||
if (sample.z() > mid.z())
|
||||
{
|
||||
octant |= treeBoundBox::FRONTHALF;
|
||||
}
|
||||
@ -262,6 +321,97 @@ inline direction treeBoundBox::subOctant
|
||||
}
|
||||
|
||||
|
||||
// Returns reference to octantOrder which defines the
|
||||
// order to do the search.
|
||||
inline void treeBoundBox::searchOrder
|
||||
(
|
||||
const point& sample,
|
||||
FixedList<direction,8>& octantOrder
|
||||
) const
|
||||
{
|
||||
vector dist = mid() - sample;
|
||||
|
||||
direction octant = 0;
|
||||
|
||||
if (dist.x() < 0)
|
||||
{
|
||||
octant |= treeBoundBox::RIGHTHALF;
|
||||
dist.x() *= -1;
|
||||
}
|
||||
|
||||
if (dist.y() < 0)
|
||||
{
|
||||
octant |= treeBoundBox::TOPHALF;
|
||||
dist.y() *= -1;
|
||||
}
|
||||
|
||||
if (dist.z() < 0)
|
||||
{
|
||||
octant |= treeBoundBox::FRONTHALF;
|
||||
dist.z() *= -1;
|
||||
}
|
||||
|
||||
direction min = 0;
|
||||
direction mid = 0;
|
||||
direction max = 0;
|
||||
|
||||
if( dist.x() < dist.y())
|
||||
{
|
||||
if( dist.y() < dist.z())
|
||||
{
|
||||
min = treeBoundBox::RIGHTHALF;
|
||||
mid = treeBoundBox::TOPHALF;
|
||||
max = treeBoundBox::FRONTHALF;
|
||||
}
|
||||
else if( dist.z() < dist.x())
|
||||
{
|
||||
min = treeBoundBox::FRONTHALF;
|
||||
mid = treeBoundBox::RIGHTHALF;
|
||||
max = treeBoundBox::TOPHALF;
|
||||
}
|
||||
else
|
||||
{
|
||||
min = treeBoundBox::RIGHTHALF;
|
||||
mid = treeBoundBox::FRONTHALF;
|
||||
max = treeBoundBox::TOPHALF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dist.z() < dist.y())
|
||||
{
|
||||
min = treeBoundBox::FRONTHALF;
|
||||
mid = treeBoundBox::TOPHALF;
|
||||
max = treeBoundBox::RIGHTHALF;
|
||||
}
|
||||
else if( dist.x() < dist.z())
|
||||
{
|
||||
min = treeBoundBox::TOPHALF;
|
||||
mid = treeBoundBox::RIGHTHALF;
|
||||
max = treeBoundBox::FRONTHALF;
|
||||
}
|
||||
else
|
||||
{
|
||||
min = treeBoundBox::TOPHALF;
|
||||
mid = treeBoundBox::FRONTHALF;
|
||||
max = treeBoundBox::RIGHTHALF;
|
||||
}
|
||||
}
|
||||
// Primary subOctant
|
||||
octantOrder[0] = octant;
|
||||
// subOctants joined to the primary by faces.
|
||||
octantOrder[1] = octant ^ min;
|
||||
octantOrder[2] = octant ^ mid;
|
||||
octantOrder[3] = octant ^ max;
|
||||
// subOctants joined to the primary by edges.
|
||||
octantOrder[4] = octantOrder[1] ^ mid;
|
||||
octantOrder[5] = octantOrder[1] ^ max;
|
||||
octantOrder[6] = octantOrder[2] ^ max;
|
||||
// subOctants joined to the primary by corner.
|
||||
octantOrder[7] = octantOrder[4] ^ max;
|
||||
}
|
||||
|
||||
|
||||
// true if bb's intersect or overlap.
|
||||
// Note: <= to make sure we catch all.
|
||||
inline bool treeBoundBox::intersects(const treeBoundBox& bb) const
|
||||
|
||||
@ -41,8 +41,64 @@ defineTypeNameAndDebug(regionSplit, 0);
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
// Handle (non-processor) coupled faces.
|
||||
void Foam::regionSplit::transferCoupledFaceRegion
|
||||
(
|
||||
const label faceI,
|
||||
const label otherFaceI,
|
||||
|
||||
labelList& faceRegion,
|
||||
DynamicList<label>& newChangedFaces
|
||||
) const
|
||||
{
|
||||
if (faceRegion[faceI] >= 0)
|
||||
{
|
||||
if (faceRegion[otherFaceI] == -1)
|
||||
{
|
||||
faceRegion[otherFaceI] = faceRegion[faceI];
|
||||
newChangedFaces.append(otherFaceI);
|
||||
}
|
||||
else if (faceRegion[otherFaceI] == -2)
|
||||
{
|
||||
// otherFaceI blocked but faceI is not. Is illegal for coupled
|
||||
// faces, not for explicit connections.
|
||||
}
|
||||
else if (faceRegion[otherFaceI] != faceRegion[faceI])
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"regionSplit::transferCoupledFaceRegion"
|
||||
"(const label, const label, labelList&, labelList&) const"
|
||||
) << "Problem : coupled face " << faceI
|
||||
<< " on patch " << mesh_.boundaryMesh().whichPatch(faceI)
|
||||
<< " has region " << faceRegion[faceI]
|
||||
<< " but coupled face " << otherFaceI
|
||||
<< " has region " << faceRegion[otherFaceI]
|
||||
<< endl
|
||||
<< "Is your blocked faces specification"
|
||||
<< " synchronized across coupled boundaries?"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
else if (faceRegion[faceI] == -1)
|
||||
{
|
||||
if (faceRegion[otherFaceI] >= 0)
|
||||
{
|
||||
faceRegion[faceI] = faceRegion[otherFaceI];
|
||||
newChangedFaces.append(faceI);
|
||||
}
|
||||
else if (faceRegion[otherFaceI] == -2)
|
||||
{
|
||||
// otherFaceI blocked but faceI is not. Is illegal for coupled
|
||||
// faces, not for explicit connections.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::regionSplit::fillSeedMask
|
||||
(
|
||||
const List<labelPair>& explicitConnections,
|
||||
labelList& cellRegion,
|
||||
labelList& faceRegion,
|
||||
const label seedCellID,
|
||||
@ -77,11 +133,11 @@ void Foam::regionSplit::fillSeedMask
|
||||
|
||||
while (changedFaces.size() > 0)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "regionSplit::fillSeedMask : changedFaces:"
|
||||
<< changedFaces.size() << endl;
|
||||
}
|
||||
//if (debug)
|
||||
//{
|
||||
// Pout<< "regionSplit::fillSeedMask : changedFaces:"
|
||||
// << changedFaces.size() << endl;
|
||||
//}
|
||||
|
||||
DynamicList<label> changedCells(changedFaces.size());
|
||||
|
||||
@ -110,11 +166,11 @@ void Foam::regionSplit::fillSeedMask
|
||||
}
|
||||
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "regionSplit::fillSeedMask : changedCells:"
|
||||
<< changedCells.size() << endl;
|
||||
}
|
||||
//if (debug)
|
||||
//{
|
||||
// Pout<< "regionSplit::fillSeedMask : changedCells:"
|
||||
// << changedCells.size() << endl;
|
||||
//}
|
||||
|
||||
// Loop over changedCells and collect faces
|
||||
DynamicList<label> newChangedFaces(changedCells.size());
|
||||
@ -138,11 +194,11 @@ void Foam::regionSplit::fillSeedMask
|
||||
}
|
||||
|
||||
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "regionSplit::fillSeedMask : changedFaces before sync:"
|
||||
<< changedFaces.size() << endl;
|
||||
}
|
||||
//if (debug)
|
||||
//{
|
||||
// Pout<< "regionSplit::fillSeedMask : changedFaces before sync:"
|
||||
// << changedFaces.size() << endl;
|
||||
//}
|
||||
|
||||
|
||||
// Check for changes to any locally coupled face.
|
||||
@ -165,46 +221,35 @@ void Foam::regionSplit::fillSeedMask
|
||||
label otherFaceI = refCast<const cyclicPolyPatch>(pp)
|
||||
.transformGlobalFace(faceI);
|
||||
|
||||
if (faceRegion[faceI] >= 0)
|
||||
{
|
||||
if (faceRegion[otherFaceI] == -1)
|
||||
{
|
||||
faceRegion[otherFaceI] = faceRegion[faceI];
|
||||
newChangedFaces.append(otherFaceI);
|
||||
}
|
||||
else if
|
||||
(
|
||||
faceRegion[otherFaceI] == -2
|
||||
|| faceRegion[otherFaceI] != faceRegion[faceI]
|
||||
)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"regionSplit::fillSeedMask"
|
||||
"(labelList&, labelList&, const label"
|
||||
", const label) const"
|
||||
) << "Problem : coupled face " << faceI
|
||||
<< " on patch " << pp.name()
|
||||
<< " has region " << faceRegion[faceI]
|
||||
<< " but coupled face " << otherFaceI
|
||||
<< " has region " << faceRegion[otherFaceI]
|
||||
<< endl
|
||||
<< "Is your blocked faces specification"
|
||||
<< " synchronized across coupled boundaries?"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
transferCoupledFaceRegion
|
||||
(
|
||||
faceI,
|
||||
otherFaceI,
|
||||
faceRegion,
|
||||
newChangedFaces
|
||||
);
|
||||
|
||||
faceI++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
forAll(explicitConnections, i)
|
||||
{
|
||||
Pout<< "regionSplit::fillSeedMask : changedFaces after sync:"
|
||||
<< changedFaces.size() << endl;
|
||||
transferCoupledFaceRegion
|
||||
(
|
||||
explicitConnections[i][0],
|
||||
explicitConnections[i][1],
|
||||
faceRegion,
|
||||
newChangedFaces
|
||||
);
|
||||
}
|
||||
|
||||
//if (debug)
|
||||
//{
|
||||
// Pout<< "regionSplit::fillSeedMask : changedFaces after sync:"
|
||||
// << newChangedFaces.size() << endl;
|
||||
//}
|
||||
|
||||
changedFaces.transfer(newChangedFaces.shrink());
|
||||
newChangedFaces.clear();
|
||||
}
|
||||
@ -214,6 +259,8 @@ void Foam::regionSplit::fillSeedMask
|
||||
Foam::label Foam::regionSplit::calcRegionSplit
|
||||
(
|
||||
const boolList& blockedFace,
|
||||
const List<labelPair>& explicitConnections,
|
||||
|
||||
labelList& cellRegion
|
||||
) const
|
||||
{
|
||||
@ -231,8 +278,7 @@ Foam::label Foam::regionSplit::calcRegionSplit
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"regionSplit::calcRegionSplit"
|
||||
"(const boolList&, labelList&)"
|
||||
"regionSplit::calcRegionSplit(..)"
|
||||
) << "Face " << faceI << " not synchronised. My value:"
|
||||
<< blockedFace[faceI] << " coupled value:"
|
||||
<< syncBlockedFace[faceI]
|
||||
@ -275,7 +321,7 @@ Foam::label Foam::regionSplit::calcRegionSplit
|
||||
{
|
||||
if (cellRegion[unsetCellI] == -1)
|
||||
{
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,7 +330,14 @@ Foam::label Foam::regionSplit::calcRegionSplit
|
||||
break;
|
||||
}
|
||||
|
||||
fillSeedMask(cellRegion, faceRegion, unsetCellI, nRegions);
|
||||
fillSeedMask
|
||||
(
|
||||
explicitConnections,
|
||||
cellRegion,
|
||||
faceRegion,
|
||||
unsetCellI,
|
||||
nRegions
|
||||
);
|
||||
|
||||
// Current unsetCell has now been handled. Go to next region.
|
||||
nRegions++;
|
||||
@ -299,7 +352,7 @@ Foam::label Foam::regionSplit::calcRegionSplit
|
||||
{
|
||||
if (cellRegion[cellI] < 0)
|
||||
{
|
||||
FatalErrorIn("regionSplit::calcRegionSplit")
|
||||
FatalErrorIn("regionSplit::calcRegionSplit(..)")
|
||||
<< "cell:" << cellI << " region:" << cellRegion[cellI]
|
||||
<< abort(FatalError);
|
||||
}
|
||||
@ -309,7 +362,7 @@ Foam::label Foam::regionSplit::calcRegionSplit
|
||||
{
|
||||
if (faceRegion[faceI] == -1)
|
||||
{
|
||||
FatalErrorIn("regionSplit::calcRegionSplit")
|
||||
FatalErrorIn("regionSplit::calcRegionSplit(..)")
|
||||
<< "face:" << faceI << " region:" << faceRegion[faceI]
|
||||
<< abort(FatalError);
|
||||
}
|
||||
@ -415,7 +468,7 @@ Foam::label Foam::regionSplit::calcRegionSplit
|
||||
{
|
||||
if (faceRegion[faceI] != nbrRegions[i])
|
||||
{
|
||||
FatalErrorIn("regionSplit::calcRegionSplit")
|
||||
FatalErrorIn("regionSplit::calcRegionSplit(..)")
|
||||
<< "On patch:" << pp.name()
|
||||
<< " face:" << faceI
|
||||
<< " my local region:" << faceRegion[faceI]
|
||||
@ -526,7 +579,7 @@ Foam::regionSplit::regionSplit(const polyMesh& mesh)
|
||||
:
|
||||
labelList(mesh.nCells(), -1),
|
||||
mesh_(mesh),
|
||||
nRegions_(calcRegionSplit(boolList(0, false), *this))
|
||||
nRegions_(calcRegionSplit(boolList(0, false), List<labelPair>(0), *this))
|
||||
{}
|
||||
|
||||
|
||||
@ -538,7 +591,20 @@ Foam::regionSplit::regionSplit
|
||||
:
|
||||
labelList(mesh.nCells(), -1),
|
||||
mesh_(mesh),
|
||||
nRegions_(calcRegionSplit(blockedFace, *this))
|
||||
nRegions_(calcRegionSplit(blockedFace, List<labelPair>(0), *this))
|
||||
{}
|
||||
|
||||
|
||||
Foam::regionSplit::regionSplit
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const boolList& blockedFace,
|
||||
const List<labelPair>& explicitConnections
|
||||
)
|
||||
:
|
||||
labelList(mesh.nCells(), -1),
|
||||
mesh_(mesh),
|
||||
nRegions_(calcRegionSplit(blockedFace, explicitConnections, *this))
|
||||
{}
|
||||
|
||||
|
||||
|
||||
@ -64,11 +64,21 @@ class regionSplit
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Transfer faceRegion data from one face to the other (or vice versa)
|
||||
void transferCoupledFaceRegion
|
||||
(
|
||||
const label faceI,
|
||||
const label otherFaceI,
|
||||
|
||||
labelList& faceRegion,
|
||||
DynamicList<label>& newChangedFaces
|
||||
) const;
|
||||
|
||||
//- Given a seed cell label, fill cellRegion/faceRegion with markValue
|
||||
// for contiguous region around it
|
||||
void fillSeedMask
|
||||
(
|
||||
const List<labelPair>& explicitConnections,
|
||||
labelList& cellRegion,
|
||||
labelList& faceRegion,
|
||||
const label seedCellID,
|
||||
@ -79,6 +89,7 @@ class regionSplit
|
||||
label calcRegionSplit
|
||||
(
|
||||
const boolList& blockedFace,
|
||||
const List<labelPair>& explicitConnections,
|
||||
labelList& cellRegion
|
||||
) const;
|
||||
|
||||
@ -96,6 +107,16 @@ public:
|
||||
// NOTE: blockedFace has to be consistent across coupled faces!
|
||||
regionSplit(const polyMesh&, const boolList& blockedFace);
|
||||
|
||||
//- Construct from mesh and whether face is blocked. Additional explicit
|
||||
// connections between normal boundary faces.
|
||||
// NOTE: blockedFace has to be consistent across coupled faces!
|
||||
regionSplit
|
||||
(
|
||||
const polyMesh&,
|
||||
const boolList& blockedFace,
|
||||
const List<labelPair>&
|
||||
);
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return number of regions
|
||||
|
||||
228
src/meshTools/sets/cellSources/regionToCell/regionToCell.C
Normal file
228
src/meshTools/sets/cellSources/regionToCell/regionToCell.C
Normal file
@ -0,0 +1,228 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "regionToCell.H"
|
||||
#include "polyMesh.H"
|
||||
#include "regionSplit.H"
|
||||
#include "globalMeshData.H"
|
||||
#include "cellSet.H"
|
||||
#include "syncTools.H"
|
||||
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
defineTypeNameAndDebug(regionToCell, 0);
|
||||
|
||||
addToRunTimeSelectionTable(topoSetSource, regionToCell, word);
|
||||
|
||||
addToRunTimeSelectionTable(topoSetSource, regionToCell, istream);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Foam::topoSetSource::addToUsageTable Foam::regionToCell::usage_
|
||||
(
|
||||
regionToCell::typeName,
|
||||
"\n Usage: regionToCell subCellSet (x y z)\n\n"
|
||||
" Select all cells in the connected region containing point.\n"
|
||||
" If started inside the subCellSet keeps to it;\n"
|
||||
" if started outside stays outside.\n"
|
||||
);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::regionToCell::combine(topoSet& set, const bool add) const
|
||||
{
|
||||
label cellI = mesh_.findCell(insidePoint_);
|
||||
|
||||
// Load the subset of cells
|
||||
boolList blockedFace(mesh_.nFaces(), false);
|
||||
{
|
||||
Info<< "Loading subset " << setName_ << " to delimit search region."
|
||||
<< endl;
|
||||
cellSet subSet(mesh_, setName_);
|
||||
|
||||
boolList inSubset(mesh_.nCells(), false);
|
||||
forAllConstIter(cellSet, subSet, iter)
|
||||
{
|
||||
inSubset[iter.key()] = true;
|
||||
}
|
||||
|
||||
if (cellI != -1 && inSubset[cellI])
|
||||
{
|
||||
Pout<< "Point " << insidePoint_ << " is inside cellSet "
|
||||
<< setName_ << endl
|
||||
<< "Collecting all cells connected to " << cellI
|
||||
<< " and inside cellSet " << setName_ << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Pout<< "Point " << insidePoint_ << " is outside cellSet "
|
||||
<< setName_ << endl
|
||||
<< "Collecting all cells connected to " << cellI
|
||||
<< " and outside cellSet " << setName_ << endl;
|
||||
}
|
||||
|
||||
// Get coupled cell status
|
||||
label nInt = mesh_.nInternalFaces();
|
||||
boolList neiSet(mesh_.nFaces()-nInt, false);
|
||||
for (label faceI = nInt; faceI < mesh_.nFaces(); faceI++)
|
||||
{
|
||||
neiSet[faceI-nInt] = inSubset[mesh_.faceOwner()[faceI]];
|
||||
}
|
||||
syncTools::swapBoundaryFaceList(mesh_, neiSet, false);
|
||||
|
||||
// Find faces inbetween subSet and non-subset.
|
||||
for (label faceI = 0; faceI < nInt; faceI++)
|
||||
{
|
||||
bool ownInSet = inSubset[mesh_.faceOwner()[faceI]];
|
||||
bool neiInSet = inSubset[mesh_.faceNeighbour()[faceI]];
|
||||
blockedFace[faceI] = (ownInSet != neiInSet);
|
||||
}
|
||||
for (label faceI = nInt; faceI < mesh_.nFaces(); faceI++)
|
||||
{
|
||||
bool ownInSet = inSubset[mesh_.faceOwner()[faceI]];
|
||||
bool neiInSet = neiSet[faceI-nInt];
|
||||
blockedFace[faceI] = (ownInSet != neiInSet);
|
||||
}
|
||||
}
|
||||
|
||||
// Find connected regions without crossing boundary of the cellset.
|
||||
regionSplit regions(mesh_, blockedFace);
|
||||
|
||||
// Get the region containing the insidePoint
|
||||
label regionI = -1;
|
||||
|
||||
if (cellI != -1)
|
||||
{
|
||||
// On processor that has found cell.
|
||||
regionI = regions[cellI];
|
||||
}
|
||||
|
||||
reduce(regionI, maxOp<label>());
|
||||
|
||||
if (regionI == -1)
|
||||
{
|
||||
WarningIn
|
||||
(
|
||||
"regionToCell::combine(topoSet&, const bool) const"
|
||||
) << "Point " << insidePoint_
|
||||
<< " is not inside the mesh." << nl
|
||||
<< "Bounding box of the mesh:" << mesh_.globalData().bb()
|
||||
<< endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Pick up the cells of the region
|
||||
const labelList regionCells(findIndices(regions, regionI));
|
||||
|
||||
forAll(regionCells, i)
|
||||
{
|
||||
addOrDelete(set, regionCells[i], add);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct from components
|
||||
Foam::regionToCell::regionToCell
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const word& setName,
|
||||
const point& insidePoint
|
||||
)
|
||||
:
|
||||
topoSetSource(mesh),
|
||||
setName_(setName),
|
||||
insidePoint_(insidePoint)
|
||||
{}
|
||||
|
||||
|
||||
// Construct from dictionary
|
||||
Foam::regionToCell::regionToCell
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
topoSetSource(mesh),
|
||||
setName_(dict.lookup("set")),
|
||||
insidePoint_(dict.lookup("insidePoint"))
|
||||
{}
|
||||
|
||||
|
||||
// Construct from Istream
|
||||
Foam::regionToCell::regionToCell
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
Istream& is
|
||||
)
|
||||
:
|
||||
topoSetSource(mesh),
|
||||
setName_(checkIs(is)),
|
||||
insidePoint_(checkIs(is))
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::regionToCell::~regionToCell()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::regionToCell::applyToSet
|
||||
(
|
||||
const topoSetSource::setAction action,
|
||||
topoSet& set
|
||||
) const
|
||||
{
|
||||
if ((action == topoSetSource::NEW) || (action == topoSetSource::ADD))
|
||||
{
|
||||
Info<< " Adding all cells of connected region containing point "
|
||||
<< insidePoint_ << " ..." << endl;
|
||||
|
||||
combine(set, true);
|
||||
}
|
||||
else if (action == topoSetSource::DELETE)
|
||||
{
|
||||
Info<< " Removing all cells of connected region containing point "
|
||||
<< insidePoint_ << " ..." << endl;
|
||||
|
||||
combine(set, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
124
src/meshTools/sets/cellSources/regionToCell/regionToCell.H
Normal file
124
src/meshTools/sets/cellSources/regionToCell/regionToCell.H
Normal file
@ -0,0 +1,124 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::regionToCell
|
||||
|
||||
Description
|
||||
TopoSetSource. Select cells belonging to topological connected region
|
||||
(that contains given point)
|
||||
|
||||
SourceFiles
|
||||
regionToCell.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef regionToCell_H
|
||||
#define regionToCell_H
|
||||
|
||||
#include "topoSetSource.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class regionToCell Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class regionToCell
|
||||
:
|
||||
public topoSetSource
|
||||
{
|
||||
|
||||
// Private data
|
||||
|
||||
//- Add usage string
|
||||
static addToUsageTable usage_;
|
||||
|
||||
//- Name of cellSet to keep to
|
||||
word setName_;
|
||||
|
||||
//- Coordinate that is inside connected region
|
||||
point insidePoint_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
void combine(topoSet& set, const bool add) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("regionToCell");
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
regionToCell
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const word& setName,
|
||||
const point& insidePoint
|
||||
);
|
||||
|
||||
//- Construct from dictionary
|
||||
regionToCell
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
//- Construct from Istream
|
||||
regionToCell
|
||||
(
|
||||
const polyMesh& mesh,
|
||||
Istream&
|
||||
);
|
||||
|
||||
|
||||
// Destructor
|
||||
|
||||
virtual ~regionToCell();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
virtual void applyToSet(const topoSetSource::setAction action, topoSet&)
|
||||
const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
247
src/meshTools/triSurface/searchableSurface/searchableBox.C
Normal file
247
src/meshTools/triSurface/searchableSurface/searchableBox.C
Normal file
@ -0,0 +1,247 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "searchableBox.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
defineTypeNameAndDebug(searchableBox, 0);
|
||||
addToRunTimeSelectionTable(searchableSurface, searchableBox, dict);
|
||||
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::searchableBox::searchableBox
|
||||
(
|
||||
const word& name,
|
||||
const treeBoundBox& bb
|
||||
)
|
||||
:
|
||||
searchableSurface(name),
|
||||
treeBoundBox(bb)
|
||||
{}
|
||||
|
||||
|
||||
Foam::searchableBox::searchableBox
|
||||
(
|
||||
const word& name,
|
||||
const objectRegistry& obj,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
searchableSurface(name),
|
||||
treeBoundBox(dict.lookup("min"), dict.lookup("max"))
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::searchableBox::~searchableBox()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointIndexHit Foam::searchableBox::findNearest
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const
|
||||
{
|
||||
// Point can be inside or outside. For every component direction can be
|
||||
// left of min, right of max or inbetween.
|
||||
// - outside points: project first one x plane (either min().x()
|
||||
// or max().x()), then onto y plane and finally z. You should be left
|
||||
// with intersection point
|
||||
// - inside point: find nearest side (compare to mid point). Pick any
|
||||
// one of three points.
|
||||
|
||||
const point bbMid(mid());
|
||||
|
||||
// Outside point projected onto cube
|
||||
point interPt(sample);
|
||||
bool outside = false;
|
||||
|
||||
// (for internal points) Per direction what nearest cube side is
|
||||
point near;
|
||||
|
||||
for (direction dir = 0; dir < vector::nComponents; dir++)
|
||||
{
|
||||
if (interPt[dir] < min()[dir])
|
||||
{
|
||||
interPt[dir] = min()[dir];
|
||||
outside = true;
|
||||
}
|
||||
else if (interPt[dir] > max()[dir])
|
||||
{
|
||||
interPt[dir] = max()[dir];
|
||||
outside = true;
|
||||
}
|
||||
else if (interPt[dir] > bbMid[dir])
|
||||
{
|
||||
near[dir] = max()[dir];
|
||||
}
|
||||
else
|
||||
{
|
||||
near[dir] = min()[dir];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// For outside points the interPt will be correct now. Handle inside points
|
||||
// using the three near distances. Project onto the nearest plane.
|
||||
if (!outside)
|
||||
{
|
||||
vector dist(cmptMag(interPt - near));
|
||||
|
||||
if (dist.x() < dist.y())
|
||||
{
|
||||
if (dist.x() < dist.z())
|
||||
{
|
||||
interPt.x() = near.x();
|
||||
}
|
||||
else
|
||||
{
|
||||
interPt.z() = near.z();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dist.y() < dist.z())
|
||||
{
|
||||
interPt.y() = near.y();
|
||||
}
|
||||
else
|
||||
{
|
||||
interPt.z() = near.z();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pointIndexHit(true, interPt, 0);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::searchableBox::findNearestOnEdge
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const
|
||||
{
|
||||
const point bbMid(mid());
|
||||
|
||||
point interPt(sample);
|
||||
|
||||
for (direction dir = 0; dir < vector::nComponents; dir++)
|
||||
{
|
||||
// Project onto left or right depending on mid
|
||||
if (interPt[dir] > bbMid[dir])
|
||||
{
|
||||
interPt[dir] = max()[dir];
|
||||
}
|
||||
else
|
||||
{
|
||||
interPt[dir] = min()[dir];
|
||||
}
|
||||
}
|
||||
|
||||
return pointIndexHit(true, interPt, 0);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::searchableBox::findNearest
|
||||
(
|
||||
const linePointRef& ln,
|
||||
treeBoundBox& tightest,
|
||||
point& linePoint
|
||||
) const
|
||||
{
|
||||
notImplemented
|
||||
(
|
||||
"searchableBox::findNearest"
|
||||
"(const linePointRef&, treeBoundBox&, point&)"
|
||||
);
|
||||
return pointIndexHit();
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::searchableBox::findLine
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const
|
||||
{
|
||||
point intPt;
|
||||
bool foundInter = intersects(start, end, intPt);
|
||||
|
||||
return pointIndexHit(foundInter, intPt, 0);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::searchableBox::findLineAny
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const
|
||||
{
|
||||
return findLine(start, end);
|
||||
}
|
||||
|
||||
|
||||
Foam::searchableSurface::volumeType Foam::searchableBox::getVolumeType
|
||||
(
|
||||
const point& pt
|
||||
) const
|
||||
{
|
||||
for (direction dir = 0; dir < vector::nComponents; dir++)
|
||||
{
|
||||
if (pt[dir] < min()[dir] || pt[dir] > max()[dir])
|
||||
{
|
||||
return OUTSIDE;
|
||||
}
|
||||
}
|
||||
|
||||
return INSIDE;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
161
src/meshTools/triSurface/searchableSurface/searchableBox.H
Normal file
161
src/meshTools/triSurface/searchableSurface/searchableBox.H
Normal file
@ -0,0 +1,161 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::searchableBox
|
||||
|
||||
Description
|
||||
Searching on bounding box
|
||||
|
||||
SourceFiles
|
||||
searchableBox.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef searchableBox_H
|
||||
#define searchableBox_H
|
||||
|
||||
#include "searchableSurface.H"
|
||||
#include "treeBoundBox.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class searchableBox Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class searchableBox
|
||||
:
|
||||
public searchableSurface,
|
||||
public treeBoundBox
|
||||
{
|
||||
private:
|
||||
|
||||
// Private member data
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
searchableBox(const searchableBox&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const searchableBox&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("searchableBox");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
searchableBox(const word& name, const treeBoundBox& bb);
|
||||
|
||||
searchableBox
|
||||
(
|
||||
const word& name,
|
||||
const objectRegistry& obj,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
// Destructor
|
||||
|
||||
virtual ~searchableBox();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Calculate nearest point on surface. Returns
|
||||
// - bool : any point found nearer than nearestDistSqr
|
||||
// - label: relevant index in surface
|
||||
// - point: actual nearest point found
|
||||
virtual pointIndexHit findNearest
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const;
|
||||
|
||||
//- Calculate nearest point on edge. Returns
|
||||
// - bool : any point found nearer than nearestDistSqr
|
||||
// - label: relevant index in surface
|
||||
// - point: actual nearest point found
|
||||
virtual pointIndexHit findNearestOnEdge
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const;
|
||||
|
||||
//- Find nearest to line. Returns
|
||||
// - bool : any point found?
|
||||
// - label: relevant index in shapes
|
||||
// - point: actual nearest point found
|
||||
// sets:
|
||||
// - tightest : bounding box
|
||||
// - linePoint : corresponding nearest point on line
|
||||
virtual pointIndexHit findNearest
|
||||
(
|
||||
const linePointRef& ln,
|
||||
treeBoundBox& tightest,
|
||||
point& linePoint
|
||||
) const;
|
||||
|
||||
//- Find nearest intersection of line between start and end.
|
||||
virtual pointIndexHit findLine
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const;
|
||||
|
||||
//- Find any intersection of line between start and end.
|
||||
virtual pointIndexHit findLineAny
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const;
|
||||
|
||||
//- Determine type (inside/outside/mixed) for point. unknown if
|
||||
// cannot be determined (e.g. non-manifold surface)
|
||||
virtual volumeType getVolumeType(const point&) const;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
116
src/meshTools/triSurface/searchableSurface/searchableSurface.C
Normal file
116
src/meshTools/triSurface/searchableSurface/searchableSurface.C
Normal file
@ -0,0 +1,116 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "searchableSurface.H"
|
||||
#include "long.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
defineTypeNameAndDebug(searchableSurface, 0);
|
||||
defineRunTimeSelectionTable(searchableSurface, dict);
|
||||
//defineRunTimeSelectionTable(searchableSurface, istream);
|
||||
|
||||
|
||||
// Construct named object from dictionary
|
||||
autoPtr<searchableSurface> searchableSurface::New
|
||||
(
|
||||
const word& searchableSurfaceType,
|
||||
const word& name,
|
||||
const objectRegistry& obj,
|
||||
const dictionary& dict
|
||||
)
|
||||
{
|
||||
dictConstructorTable::iterator cstrIter =
|
||||
dictConstructorTablePtr_
|
||||
->find(searchableSurfaceType);
|
||||
|
||||
if (cstrIter == dictConstructorTablePtr_->end())
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"searchableSurface::New(const word&, const word&"
|
||||
", const objectRegistry&, const dictionary&)"
|
||||
) << "Unknown searchableSurface type " << searchableSurfaceType
|
||||
<< endl << endl
|
||||
<< "Valid searchableSurface types : " << endl
|
||||
<< dictConstructorTablePtr_->toc()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
return autoPtr<searchableSurface>(cstrIter()(name, obj, dict));
|
||||
}
|
||||
|
||||
|
||||
//// Construct named object from Istream
|
||||
//autoPtr<searchableSurface> searchableSurface::New
|
||||
//(
|
||||
// const word& searchableSurfaceType,
|
||||
// const objectRegistry& obj,
|
||||
// Istream& is
|
||||
//)
|
||||
//{
|
||||
// istreamConstructorTable::iterator cstrIter =
|
||||
// istreamConstructorTablePtr_
|
||||
// ->find(searchableSurfaceType);
|
||||
//
|
||||
// if (cstrIter == istreamConstructorTablePtr_->end())
|
||||
// {
|
||||
// FatalErrorIn
|
||||
// (
|
||||
// "searchableSurface::New(const word&, const objectRegistry&"
|
||||
// ", Istream&)"
|
||||
// ) << "Unknown searchableSurface type " << searchableSurfaceType
|
||||
// << endl << endl
|
||||
// << "Valid searchableSurface types : " << endl
|
||||
// << istreamConstructorTablePtr_->toc()
|
||||
// << exit(FatalError);
|
||||
// }
|
||||
//
|
||||
// return autoPtr<searchableSurface>(cstrIter()(obj, is));
|
||||
//}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::searchableSurface::searchableSurface(const word& name)
|
||||
:
|
||||
name_(name)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::searchableSurface::~searchableSurface()
|
||||
{}
|
||||
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
257
src/meshTools/triSurface/searchableSurface/searchableSurface.H
Normal file
257
src/meshTools/triSurface/searchableSurface/searchableSurface.H
Normal file
@ -0,0 +1,257 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::searchableSurface
|
||||
|
||||
Description
|
||||
Base class of (analytical or triangulated) surface.
|
||||
Encapsulates all the search routines.
|
||||
|
||||
SourceFiles
|
||||
searchableSurface.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef searchableSurface_H
|
||||
#define searchableSurface_H
|
||||
|
||||
#include "pointField.H"
|
||||
#include "typeInfo.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
#include "pointIndexHit.H"
|
||||
#include "linePointRef.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
class objectRegistry;
|
||||
class treeBoundBox;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class searchableSurface Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class searchableSurface
|
||||
{
|
||||
public:
|
||||
|
||||
// Data types
|
||||
|
||||
//- volume types
|
||||
enum volumeType
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
MIXED = 1,
|
||||
INSIDE = 2,
|
||||
OUTSIDE = 3
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// Private data
|
||||
|
||||
const word name_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
searchableSurface(const searchableSurface&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const searchableSurface&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("searchableSurface");
|
||||
|
||||
// Declare run-time constructor selection table
|
||||
|
||||
// For the dictionary constructor
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
searchableSurface,
|
||||
dict,
|
||||
(
|
||||
const word& name,
|
||||
const objectRegistry& obj,
|
||||
const dictionary& dict
|
||||
),
|
||||
(name, obj, dict)
|
||||
);
|
||||
|
||||
//// For the Istream constructor
|
||||
//declareRunTimeSelectionTable
|
||||
//(
|
||||
// autoPtr,
|
||||
// searchableSurface,
|
||||
// istream,
|
||||
// (
|
||||
// const objectRegistry& obj,
|
||||
// Istream& is
|
||||
// ),
|
||||
// (obj, is)
|
||||
//);
|
||||
|
||||
|
||||
//- Class used for the read-construction of
|
||||
// PtrLists of searchableSurface
|
||||
class iNew
|
||||
{
|
||||
const objectRegistry& obj_;
|
||||
|
||||
public:
|
||||
|
||||
iNew(const objectRegistry& obj)
|
||||
:
|
||||
obj_(obj)
|
||||
{}
|
||||
|
||||
autoPtr<searchableSurface> operator()(Istream& is) const
|
||||
{
|
||||
word surfaceType(is);
|
||||
word name(is);
|
||||
dictionary dict(is);
|
||||
return searchableSurface::New(surfaceType, name, obj_, dict);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
searchableSurface(const word& name);
|
||||
|
||||
//- Clone
|
||||
virtual autoPtr<searchableSurface> clone() const
|
||||
{
|
||||
notImplemented("autoPtr<searchableSurface> clone() const");
|
||||
return autoPtr<searchableSurface>(NULL);
|
||||
}
|
||||
|
||||
|
||||
// Selectors
|
||||
|
||||
//- Return a reference to the selected searchableSurface
|
||||
static autoPtr<searchableSurface> New
|
||||
(
|
||||
const word& surfaceType,
|
||||
const word& name,
|
||||
const objectRegistry& obj,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
////- Return a reference to the selected searchableSurface
|
||||
//static autoPtr<searchableSurface> New
|
||||
//(
|
||||
// const word& surfaceType,
|
||||
// const objectRegistry& obj,
|
||||
// Istream& is
|
||||
//);
|
||||
|
||||
|
||||
// Destructor
|
||||
|
||||
virtual ~searchableSurface();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return name
|
||||
const word& name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
//- Calculate nearest point on surface. Returns
|
||||
// - bool : any point found nearer than nearestDistSqr
|
||||
// - label: relevant index in surface
|
||||
// - point: actual nearest point found
|
||||
virtual pointIndexHit findNearest
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const = 0;
|
||||
|
||||
//- Calculate nearest point on edge. Returns
|
||||
// - bool : any point found nearer than nearestDistSqr
|
||||
// - label: relevant index in surface
|
||||
// - point: actual nearest point found
|
||||
virtual pointIndexHit findNearestOnEdge
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const = 0;
|
||||
|
||||
//- Find nearest to segment. Returns
|
||||
// - bool : any point found?
|
||||
// - label: relevant index in shapes
|
||||
// - point: actual nearest point found
|
||||
// sets:
|
||||
// - tightest : bounding box
|
||||
// - linePoint : corresponding nearest point on line
|
||||
virtual pointIndexHit findNearest
|
||||
(
|
||||
const linePointRef& ln,
|
||||
treeBoundBox& tightest,
|
||||
point& linePoint
|
||||
) const = 0;
|
||||
|
||||
//- Find nearest intersection of line between start and end.
|
||||
virtual pointIndexHit findLine
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const = 0;
|
||||
|
||||
//- Find any intersection of line between start and end.
|
||||
virtual pointIndexHit findLineAny
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const = 0;
|
||||
|
||||
//- Determine type (inside/outside/mixed) for point. unknown if
|
||||
// cannot be determined (e.g. non-manifold surface)
|
||||
virtual volumeType getVolumeType(const point&) const = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
271
src/meshTools/triSurface/searchableSurface/triSurfaceMesh.C
Normal file
271
src/meshTools/triSurface/searchableSurface/triSurfaceMesh.C
Normal file
@ -0,0 +1,271 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "triSurfaceMesh.H"
|
||||
#include "Random.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
defineTypeNameAndDebug(triSurfaceMesh, 0);
|
||||
addToRunTimeSelectionTable(searchableSurface, triSurfaceMesh, dict);
|
||||
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
//- Check file existence
|
||||
const Foam::fileName& Foam::triSurfaceMesh::checkFile
|
||||
(
|
||||
const fileName& fName,
|
||||
const fileName& objectName
|
||||
)
|
||||
{
|
||||
if (fName == fileName::null)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"triSurfaceMesh::checkFile(const fileName&, const fileName&)"
|
||||
) << "Cannot find triSurfaceMesh starting from "
|
||||
<< objectName << exit(FatalError);
|
||||
}
|
||||
return fName;
|
||||
}
|
||||
|
||||
|
||||
const Foam::indexedOctree<Foam::treeDataTriSurface>&
|
||||
Foam::triSurfaceMesh::tree() const
|
||||
{
|
||||
if (!tree_.valid())
|
||||
{
|
||||
treeBoundBox bb(points(), meshPoints());
|
||||
|
||||
// Random number generator. Bit dodgy since not exactly random ;-)
|
||||
Random rndGen(65431);
|
||||
|
||||
tree_.reset
|
||||
(
|
||||
new indexedOctree<treeDataTriSurface>
|
||||
(
|
||||
treeDataTriSurface(*this),
|
||||
bb.extend(rndGen, 1E-3), // slightly randomize bb
|
||||
8, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return tree_();
|
||||
}
|
||||
|
||||
|
||||
const Foam::indexedOctree<Foam::treeDataEdge>&
|
||||
Foam::triSurfaceMesh::edgeTree() const
|
||||
{
|
||||
if (!edgeTree_.valid())
|
||||
{
|
||||
treeBoundBox bb(localPoints());
|
||||
|
||||
// Boundary edges
|
||||
labelList bEdges
|
||||
(
|
||||
identity
|
||||
(
|
||||
nEdges()
|
||||
-nInternalEdges()
|
||||
)
|
||||
+ nInternalEdges()
|
||||
);
|
||||
|
||||
// Random number generator. Bit dodgy since not exactly random ;-)
|
||||
Random rndGen(65431);
|
||||
|
||||
edgeTree_.reset
|
||||
(
|
||||
new indexedOctree<treeDataEdge>
|
||||
(
|
||||
treeDataEdge
|
||||
(
|
||||
false, // cachebb
|
||||
edges(), // edges
|
||||
localPoints(), // points
|
||||
bEdges // selected edges
|
||||
),
|
||||
bb.extend(rndGen, 1E-3), // slightly randomize bb
|
||||
8, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
)
|
||||
);
|
||||
}
|
||||
return edgeTree_();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
//- Construct from triangles, patches, points.
|
||||
Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s)
|
||||
:
|
||||
searchableSurface(io.name()),
|
||||
objectRegistry(io),
|
||||
triSurface(s)
|
||||
{}
|
||||
|
||||
|
||||
Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io)
|
||||
:
|
||||
searchableSurface(io.name()),
|
||||
objectRegistry(io),
|
||||
triSurface(checkFile(filePath(), objectPath()))
|
||||
{}
|
||||
|
||||
|
||||
Foam::triSurfaceMesh::triSurfaceMesh
|
||||
(
|
||||
const word& name,
|
||||
const objectRegistry& obj,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
searchableSurface(name),
|
||||
objectRegistry
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
name,
|
||||
"constant",
|
||||
"triSurface",
|
||||
obj,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
)
|
||||
),
|
||||
triSurface(checkFile(filePath(), objectPath()))
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::triSurfaceMesh::~triSurfaceMesh()
|
||||
{}
|
||||
|
||||
|
||||
void Foam::triSurfaceMesh::clearOut()
|
||||
{
|
||||
tree_.clear();
|
||||
edgeTree_.clear();
|
||||
triSurface::clearOut();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::triSurfaceMesh::movePoints(const pointField& newPoints)
|
||||
{
|
||||
tree_.clear();
|
||||
edgeTree_.clear();
|
||||
triSurface::movePoints(newPoints);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::triSurfaceMesh::findNearest
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const
|
||||
{
|
||||
return tree().findNearest(sample, nearestDistSqr);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::triSurfaceMesh::findNearestOnEdge
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const
|
||||
{
|
||||
return edgeTree().findNearest(sample, nearestDistSqr);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::triSurfaceMesh::findNearest
|
||||
(
|
||||
const linePointRef& ln,
|
||||
treeBoundBox& tightest,
|
||||
point& linePoint
|
||||
) const
|
||||
{
|
||||
return tree().findNearest(ln, tightest, linePoint);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::triSurfaceMesh::findLine
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const
|
||||
{
|
||||
return tree().findLine(start, end);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::triSurfaceMesh::findLineAny
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const
|
||||
{
|
||||
return tree().findLineAny(start, end);
|
||||
}
|
||||
|
||||
|
||||
Foam::searchableSurface::volumeType
|
||||
Foam::triSurfaceMesh::getVolumeType
|
||||
(
|
||||
const point& pt
|
||||
) const
|
||||
{
|
||||
// - use cached volume type per each tree node
|
||||
// - cheat conversion since same values
|
||||
return static_cast<volumeType>(tree().getVolumeType(pt));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
194
src/meshTools/triSurface/searchableSurface/triSurfaceMesh.H
Normal file
194
src/meshTools/triSurface/searchableSurface/triSurfaceMesh.H
Normal file
@ -0,0 +1,194 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
triSurfaceMesh
|
||||
|
||||
Description
|
||||
IOoject and searching on triSurface
|
||||
|
||||
SourceFiles
|
||||
triSurfaceMesh.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef triSurfaceMesh_H
|
||||
#define triSurfaceMesh_H
|
||||
|
||||
#include "searchableSurface.H"
|
||||
#include "objectRegistry.H"
|
||||
#include "indexedOctree.H"
|
||||
#include "treeDataTriSurface.H"
|
||||
#include "treeDataEdge.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class triSurfaceMesh Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class triSurfaceMesh
|
||||
:
|
||||
public searchableSurface,
|
||||
public objectRegistry,
|
||||
public triSurface
|
||||
{
|
||||
private:
|
||||
|
||||
// Private member data
|
||||
|
||||
//- Search tree (triangles)
|
||||
mutable autoPtr<indexedOctree<treeDataTriSurface> > tree_;
|
||||
|
||||
//- Search tree for boundary edges.
|
||||
mutable autoPtr<indexedOctree<treeDataEdge> > edgeTree_;
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Check file existence
|
||||
static const fileName& checkFile
|
||||
(
|
||||
const fileName& fName,
|
||||
const fileName& objectName
|
||||
);
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
triSurfaceMesh(const triSurfaceMesh&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const triSurfaceMesh&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("triSurfaceMesh");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from triSurface
|
||||
triSurfaceMesh(const IOobject&, const triSurface&);
|
||||
|
||||
//- Construct read
|
||||
triSurfaceMesh(const IOobject& io);
|
||||
|
||||
//- Construct as searchableSurface
|
||||
triSurfaceMesh
|
||||
(
|
||||
const word& name,
|
||||
const objectRegistry& obj,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
// Destructor
|
||||
|
||||
virtual ~triSurfaceMesh();
|
||||
|
||||
//- Clear storage
|
||||
void clearOut();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Move points
|
||||
virtual void movePoints(const pointField&);
|
||||
|
||||
//- Demand driven contruction of octree
|
||||
const indexedOctree<treeDataTriSurface>& tree() const;
|
||||
|
||||
//- Demand driven contruction of octree for boundary edges
|
||||
const indexedOctree<treeDataEdge>& edgeTree() const;
|
||||
|
||||
|
||||
// searchableSurface implementation
|
||||
|
||||
//- Calculate nearest point on surface. Returns
|
||||
// - bool : any point found nearer than nearestDistSqr
|
||||
// - label: relevant index in surface
|
||||
// - point: actual nearest point found
|
||||
virtual pointIndexHit findNearest
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const;
|
||||
|
||||
//- Calculate nearest point on edge. Returns
|
||||
// - bool : any point found nearer than nearestDistSqr
|
||||
// - label: relevant index in surface
|
||||
// - point: actual nearest point found
|
||||
virtual pointIndexHit findNearestOnEdge
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const;
|
||||
|
||||
//- Find nearest to line. Returns
|
||||
// - bool : any point found?
|
||||
// - label: relevant index in shapes
|
||||
// - point: actual nearest point found
|
||||
// sets:
|
||||
// - tightest : bounding box
|
||||
// - linePoint : corresponding nearest point on line
|
||||
virtual pointIndexHit findNearest
|
||||
(
|
||||
const linePointRef& ln,
|
||||
treeBoundBox& tightest,
|
||||
point& linePoint
|
||||
) const;
|
||||
|
||||
//- Find nearest intersection of line between start and end.
|
||||
virtual pointIndexHit findLine
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const;
|
||||
|
||||
//- Find any intersection of line between start and end.
|
||||
virtual pointIndexHit findLineAny
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const;
|
||||
|
||||
//- Determine type (inside/outside/mixed) for point. unknown if
|
||||
// cannot be determined (e.g. non-manifold surface)
|
||||
virtual volumeType getVolumeType(const point&) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -45,37 +45,6 @@ defineTypeNameAndDebug(triSurfaceMeshes, 0);
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::triSurfaceMeshes::calcTrees() const
|
||||
{
|
||||
// Random number generator
|
||||
Random rndGen(65431);
|
||||
|
||||
treesPtr_.reset(new PtrList<indexedOctree<treeDataTriSurface> >(size()));
|
||||
PtrList<indexedOctree<treeDataTriSurface> >& trees = treesPtr_();
|
||||
|
||||
forAll(*this, i)
|
||||
{
|
||||
const triSurface& s = operator[](i);
|
||||
|
||||
// bb of surface
|
||||
treeBoundBox bb(s.localPoints());
|
||||
|
||||
trees.set
|
||||
(
|
||||
i,
|
||||
new indexedOctree<treeDataTriSurface>
|
||||
(
|
||||
treeDataTriSurface(s),
|
||||
bb.extend(rndGen, 1E-3), // slightly randomize bb
|
||||
8, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Calculate sum of distance to surfaces.
|
||||
Foam::scalar Foam::triSurfaceMeshes::sumDistSqr
|
||||
(
|
||||
@ -84,15 +53,13 @@ Foam::scalar Foam::triSurfaceMeshes::sumDistSqr
|
||||
const point& pt
|
||||
) const
|
||||
{
|
||||
const PtrList<indexedOctree<treeDataTriSurface> >& surfaceQueries = trees();
|
||||
|
||||
scalar sum = 0;
|
||||
|
||||
forAll(surfacesToTest, i)
|
||||
{
|
||||
label surfI = surfacesToTest[i];
|
||||
|
||||
pointIndexHit hit(surfaceQueries[surfI].findNearest(pt, initDistSqr));
|
||||
pointIndexHit hit(operator[](surfI).findNearest(pt, initDistSqr));
|
||||
|
||||
// Note: make it fall over if not hit.
|
||||
sum += magSqr(hit.hitPoint()-pt);
|
||||
@ -252,8 +219,7 @@ Foam::triSurfaceMeshes::triSurfaceMeshes
|
||||
)
|
||||
:
|
||||
PtrList<triSurfaceMesh>(names.size()),
|
||||
allSurfaces_(identity(names.size())),
|
||||
treesPtr_(NULL)
|
||||
allSurfaces_(identity(names.size()))
|
||||
{
|
||||
forAll(names, i)
|
||||
{
|
||||
@ -262,20 +228,20 @@ Foam::triSurfaceMeshes::triSurfaceMeshes
|
||||
|
||||
Info<< "Loading surface " << surfaceIO().name() << endl;
|
||||
|
||||
fileName fullPath = surfaceIO().filePath();
|
||||
//fileName fullPath = surfaceIO().filePath();
|
||||
//
|
||||
//if (fullPath.size() == 0)
|
||||
//{
|
||||
// FatalErrorIn
|
||||
// (
|
||||
// "triSurfaceMeshes::triSurfaceMeshes"
|
||||
// "(const IOobject&, const fileNameList&)"
|
||||
// ) << "Cannot load surface " << surfaceIO().name()
|
||||
// << " starting from path " << surfaceIO().path()
|
||||
// << exit(FatalError);
|
||||
//}
|
||||
|
||||
if (fullPath.size() == 0)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"triSurfaceMeshes::triSurfaceMeshes"
|
||||
"(const IOobject&, const fileNameList&)"
|
||||
) << "Cannot load surface " << surfaceIO().name()
|
||||
<< " starting from path " << surfaceIO().path()
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
set(i, new triSurfaceMesh(surfaceIO(), fullPath));
|
||||
set(i, new triSurfaceMesh(surfaceIO()));
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
@ -288,12 +254,6 @@ Foam::triSurfaceMeshes::triSurfaceMeshes
|
||||
}
|
||||
|
||||
|
||||
void Foam::triSurfaceMeshes::clearOut()
|
||||
{
|
||||
treesPtr_.reset(NULL);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fileNameList Foam::triSurfaceMeshes::allNames(const IOobject& io)
|
||||
@ -308,7 +268,7 @@ Foam::fileNameList Foam::triSurfaceMeshes::names() const
|
||||
|
||||
forAll(surfNames, surfI)
|
||||
{
|
||||
surfNames[surfI] = operator[](surfI).name();
|
||||
surfNames[surfI] = operator[](surfI).IOobject::name();
|
||||
}
|
||||
return surfNames;
|
||||
}
|
||||
@ -323,13 +283,11 @@ Foam::label Foam::triSurfaceMeshes::findAnyIntersection
|
||||
pointIndexHit& hitInfo
|
||||
) const
|
||||
{
|
||||
const PtrList<indexedOctree<treeDataTriSurface> >& surfaceQueries = trees();
|
||||
|
||||
forAll(surfaces, i)
|
||||
{
|
||||
label surfI = surfaces[i];
|
||||
|
||||
hitInfo = surfaceQueries[surfI].findLineAny(start, end);
|
||||
hitInfo = operator[](surfI).findLineAny(start, end);
|
||||
|
||||
if (hitInfo.hit())
|
||||
{
|
||||
@ -368,15 +326,13 @@ void Foam::triSurfaceMeshes::findAllIntersections
|
||||
List<pointIndexHit>& surfaceHitInfo
|
||||
) const
|
||||
{
|
||||
const PtrList<indexedOctree<treeDataTriSurface> >& surfaceQueries = trees();
|
||||
|
||||
DynamicList<label> hitSurfaces(surfaceQueries.size());
|
||||
DynamicList<pointIndexHit> hitInfos(surfaceQueries.size());
|
||||
DynamicList<scalar> hitDistSqr(surfaceQueries.size());
|
||||
DynamicList<label> hitSurfaces(surfaces.size());
|
||||
DynamicList<pointIndexHit> hitInfos(surfaces.size());
|
||||
DynamicList<scalar> hitDistSqr(surfaces.size());
|
||||
|
||||
const vector dirVec(end-start);
|
||||
const scalar magSqrDirVec(magSqr(dirVec));
|
||||
const vector smallVec(1E-6*dirVec);
|
||||
const vector smallVec(Foam::sqrt(SMALL)*dirVec);
|
||||
|
||||
forAll(surfaces, i)
|
||||
{
|
||||
@ -388,7 +344,7 @@ void Foam::triSurfaceMeshes::findAllIntersections
|
||||
while (true)
|
||||
{
|
||||
// See if any intersection between pt and end
|
||||
pointIndexHit inter = surfaceQueries[surfI].findLine(pt, end);
|
||||
pointIndexHit inter = operator[](surfI).findLine(pt, end);
|
||||
|
||||
if (!inter.hit())
|
||||
{
|
||||
@ -407,23 +363,26 @@ void Foam::triSurfaceMeshes::findAllIntersections
|
||||
}
|
||||
}
|
||||
}
|
||||
hitSurfaces.shrink();
|
||||
hitInfos.shrink();
|
||||
hitDistSqr.shrink();
|
||||
|
||||
// Sort and transfer to arguments
|
||||
|
||||
surfacesIndex.setSize(hitSurfaces.size());
|
||||
surfaceHitInfo.setSize(hitSurfaces.size());
|
||||
|
||||
// Sort from start to end.
|
||||
SortableList<scalar> sortedDist(hitDistSqr);
|
||||
|
||||
forAll(sortedDist.indices(), newPos)
|
||||
if (hitSurfaces.size() > 0)
|
||||
{
|
||||
label oldPos = sortedDist.indices()[newPos];
|
||||
surfacesIndex[newPos] = hitSurfaces[oldPos];
|
||||
surfaceHitInfo[newPos] = hitInfos[oldPos];
|
||||
// Sort and transfer to arguments
|
||||
|
||||
hitSurfaces.shrink();
|
||||
hitInfos.shrink();
|
||||
hitDistSqr.shrink();
|
||||
|
||||
// Sort from start to end.
|
||||
SortableList<scalar> sortedDist(hitDistSqr);
|
||||
|
||||
forAll(sortedDist.indices(), newPos)
|
||||
{
|
||||
label oldPos = sortedDist.indices()[newPos];
|
||||
surfacesIndex[newPos] = hitSurfaces[oldPos];
|
||||
surfaceHitInfo[newPos] = hitInfos[oldPos];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,8 +420,6 @@ void Foam::triSurfaceMeshes::findNearestIntersection
|
||||
pointIndexHit& hit2
|
||||
) const
|
||||
{
|
||||
const PtrList<indexedOctree<treeDataTriSurface> >& surfaceQueries = trees();
|
||||
|
||||
surface1 = -1;
|
||||
// Initialize to endpoint
|
||||
hit1 = pointIndexHit(false, end, -1);
|
||||
@ -477,7 +434,7 @@ void Foam::triSurfaceMeshes::findNearestIntersection
|
||||
}
|
||||
|
||||
// See if any intersection between start and current nearest
|
||||
pointIndexHit inter = surfaceQueries[surfI].findLine
|
||||
pointIndexHit inter = operator[](surfI).findLine
|
||||
(
|
||||
start,
|
||||
hit1.rawPoint()
|
||||
@ -509,7 +466,7 @@ void Foam::triSurfaceMeshes::findNearestIntersection
|
||||
}
|
||||
|
||||
// See if any intersection between end and current nearest
|
||||
pointIndexHit inter = surfaceQueries[surfI].findLine
|
||||
pointIndexHit inter = operator[](surfI).findLine
|
||||
(
|
||||
end,
|
||||
hit2.rawPoint()
|
||||
@ -558,8 +515,6 @@ Foam::label Foam::triSurfaceMeshes::findNearest
|
||||
pointIndexHit& nearestHit
|
||||
) const
|
||||
{
|
||||
const PtrList<indexedOctree<treeDataTriSurface> >& surfaceQueries = trees();
|
||||
|
||||
// nearest surface
|
||||
label minSurface = -1;
|
||||
scalar minDistSqr = Foam::sqr(GREAT);
|
||||
@ -570,7 +525,7 @@ Foam::label Foam::triSurfaceMeshes::findNearest
|
||||
|
||||
pointIndexHit hit
|
||||
(
|
||||
surfaceQueries[surfI].findNearest(pt, nearestDistSqr)
|
||||
operator[](surfI).findNearest(pt, nearestDistSqr)
|
||||
);
|
||||
|
||||
if (hit.hit())
|
||||
@ -734,7 +689,7 @@ Foam::surfaceLocation Foam::triSurfaceMeshes::facesIntersectionTrack
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Nearest onto surface " << surfI
|
||||
<< ' ' << operator[](surfI).name() << " : "
|
||||
<< ' ' << operator[](surfI).IOobject::name() << " : "
|
||||
<< current.info() << " written as point " << vertI
|
||||
<< endl;
|
||||
}
|
||||
@ -769,7 +724,7 @@ Foam::surfaceLocation Foam::triSurfaceMeshes::facesIntersectionTrack
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Nearest onto next surface " << nextSurfI
|
||||
<< ' ' << operator[](nextSurfI).name() << " : "
|
||||
<< ' ' << operator[](nextSurfI).IOobject::name() << " : "
|
||||
<< next.info() << endl;
|
||||
}
|
||||
|
||||
@ -794,9 +749,10 @@ Foam::surfaceLocation Foam::triSurfaceMeshes::facesIntersectionTrack
|
||||
if (debug)
|
||||
{
|
||||
Pout<< "Sliding along surface "
|
||||
<< surfI << ' ' << operator[](surfI).name()
|
||||
<< surfI << ' ' << operator[](surfI).IOobject::name()
|
||||
<< " in direction of "
|
||||
<< nextSurfI << ' ' << operator[](nextSurfI).name()
|
||||
<< nextSurfI << ' '
|
||||
<< operator[](nextSurfI).IOobject::name()
|
||||
<< " stopped at " << current.info()
|
||||
<< " written as point " << vertI << endl;
|
||||
}
|
||||
@ -849,8 +805,6 @@ Foam::pointIndexHit Foam::triSurfaceMeshes::facesIntersection
|
||||
const point& start
|
||||
) const
|
||||
{
|
||||
const PtrList<indexedOctree<treeDataTriSurface> >& surfaceQueries = trees();
|
||||
|
||||
// Get four starting points. Take these as the projection of the
|
||||
// starting point onto the surfaces and the mid point
|
||||
List<point> nearest(surfacesToTest.size()+1);
|
||||
@ -863,7 +817,7 @@ Foam::pointIndexHit Foam::triSurfaceMeshes::facesIntersection
|
||||
|
||||
pointIndexHit hit
|
||||
(
|
||||
surfaceQueries[surfI].findNearest(start, initDistSqr)
|
||||
operator[](surfI).findNearest(start, initDistSqr)
|
||||
);
|
||||
|
||||
if (hit.hit())
|
||||
@ -879,7 +833,7 @@ Foam::pointIndexHit Foam::triSurfaceMeshes::facesIntersection
|
||||
"(const labelList&, const scalar, const scalar, const point&)"
|
||||
) << "Did not find point within distance "
|
||||
<< initDistSqr << " of starting point " << start
|
||||
<< " on surface " << operator[](surfI).name()
|
||||
<< " on surface " << operator[](surfI).IOobject::name()
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
@ -914,7 +868,7 @@ Foam::pointIndexHit Foam::triSurfaceMeshes::facesIntersection
|
||||
if (converged)
|
||||
{
|
||||
// Project nearest onto 0th surface.
|
||||
intersection = surfaceQueries[surfacesToTest[0]].findNearest
|
||||
intersection = operator[](surfacesToTest[0]).findNearest
|
||||
(
|
||||
nearest[0],
|
||||
nearestDist[0]
|
||||
|
||||
@ -63,14 +63,9 @@ class triSurfaceMeshes
|
||||
//- Indices of all surfaces. Precalculated and stored.
|
||||
const labelList allSurfaces_;
|
||||
|
||||
//- Trees
|
||||
mutable autoPtr<PtrList<indexedOctree<treeDataTriSurface> > > treesPtr_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
void calcTrees() const;
|
||||
|
||||
//- Calculate sum of distances to nearest point on surfaces. Is used
|
||||
// in minimisation to find intersection. Returns sum of (square of)
|
||||
// distances to the surfaces.
|
||||
@ -125,25 +120,12 @@ public:
|
||||
//- Construct from directory (io.instance()) and list of local filenames
|
||||
triSurfaceMeshes(const IOobject& io, const fileNameList&);
|
||||
|
||||
//- Clear derived storage
|
||||
void clearOut();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Get all surfaces in directory
|
||||
static fileNameList allNames(const IOobject&);
|
||||
|
||||
//- Get trees for searching
|
||||
const PtrList<indexedOctree<treeDataTriSurface> >& trees() const
|
||||
{
|
||||
if (!treesPtr_.valid())
|
||||
{
|
||||
calcTrees();
|
||||
}
|
||||
return treesPtr_();
|
||||
}
|
||||
|
||||
//- Get names of surfaces
|
||||
fileNameList names() const;
|
||||
|
||||
|
||||
@ -22,15 +22,12 @@ License
|
||||
along with OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Description
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "triSurfaceSearch.H"
|
||||
#include "octree.H"
|
||||
#include "indexedOctree.H"
|
||||
#include "boolList.H"
|
||||
#include "octreeDataTriSurface.H"
|
||||
#include "octreeDataPoint.H"
|
||||
#include "treeDataTriSurface.H"
|
||||
#include "triSurface.H"
|
||||
#include "line.H"
|
||||
#include "cpuTime.H"
|
||||
@ -53,10 +50,7 @@ triSurfaceSearch::triSurfaceSearch(const triSurface& surface)
|
||||
surface_(surface),
|
||||
treePtr_(NULL)
|
||||
{
|
||||
// Wrap surface information into helper object
|
||||
octreeDataTriSurface shapes(surface_);
|
||||
|
||||
treeBoundBox treeBb(surface_.localPoints());
|
||||
treeBoundBox treeBb(surface_.points(), surface_.meshPoints());
|
||||
|
||||
scalar tol = 1E-6*treeBb.avgDim();
|
||||
|
||||
@ -66,37 +60,28 @@ triSurfaceSearch::triSurfaceSearch(const triSurface& surface)
|
||||
bbMin.z() -= tol;
|
||||
|
||||
point& bbMax = treeBb.max();
|
||||
bbMax.x() += tol;
|
||||
bbMax.y() += tol;
|
||||
bbMax.z() += tol;
|
||||
bbMax.x() += 2*tol;
|
||||
bbMax.y() += 2*tol;
|
||||
bbMax.z() += 2*tol;
|
||||
|
||||
treePtr_ = new octree<octreeDataTriSurface>
|
||||
treePtr_.reset
|
||||
(
|
||||
treeBb,
|
||||
shapes,
|
||||
1,
|
||||
100.0,
|
||||
10.0
|
||||
new indexedOctree<treeDataTriSurface>
|
||||
(
|
||||
treeDataTriSurface(surface_),
|
||||
treeBb,
|
||||
8, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
triSurfaceSearch::~triSurfaceSearch()
|
||||
{
|
||||
if (treePtr_)
|
||||
{
|
||||
delete treePtr_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
// Determine inside/outside for samples
|
||||
boolList triSurfaceSearch::calcInside(const pointField& samples)
|
||||
const
|
||||
boolList triSurfaceSearch::calcInside(const pointField& samples) const
|
||||
{
|
||||
boolList inside(samples.size());
|
||||
|
||||
@ -104,14 +89,14 @@ boolList triSurfaceSearch::calcInside(const pointField& samples)
|
||||
{
|
||||
const point& sample = samples[sampleI];
|
||||
|
||||
if (!tree().octreeBb().contains(sample))
|
||||
if (!tree().bb().contains(sample))
|
||||
{
|
||||
inside[sampleI] = false;
|
||||
}
|
||||
else if
|
||||
(
|
||||
tree().getSampleType(sample)
|
||||
== octree<octreeDataTriSurface>::INSIDE
|
||||
tree().getVolumeType(sample)
|
||||
== indexedOctree<treeDataTriSurface>::INSIDE
|
||||
)
|
||||
{
|
||||
inside[sampleI] = true;
|
||||
@ -133,39 +118,21 @@ labelList triSurfaceSearch::calcNearestTri
|
||||
{
|
||||
labelList nearest(samples.size());
|
||||
|
||||
const scalar nearestDistSqr = 0.25*magSqr(span);
|
||||
|
||||
pointIndexHit hitInfo;
|
||||
|
||||
forAll(samples, sampleI)
|
||||
{
|
||||
const point& sample = samples[sampleI];
|
||||
hitInfo = tree().findNearest(samples[sampleI], nearestDistSqr);
|
||||
|
||||
treeBoundBox tightest(sample, sample);
|
||||
tightest.min() -= span;
|
||||
tightest.max() += span;
|
||||
|
||||
scalar tightestDist = Foam::GREAT;
|
||||
|
||||
nearest[sampleI] = tree().findNearest
|
||||
(
|
||||
sample,
|
||||
tightest,
|
||||
tightestDist
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Bit ropy - comparison of coordinate but is just check.
|
||||
if (span == greatPoint)
|
||||
{
|
||||
forAll(nearest, sampleI)
|
||||
if (hitInfo.hit())
|
||||
{
|
||||
if (nearest[sampleI] == -1)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"triSurfaceSearch::calcNearestTri(const pointField&)"
|
||||
) << "Did not find point " << samples[sampleI]
|
||||
<< " in octree spanning "
|
||||
<< tree().octreeBb() << abort(FatalError);
|
||||
}
|
||||
nearest[sampleI] = hitInfo.index();
|
||||
}
|
||||
else
|
||||
{
|
||||
nearest[sampleI] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,35 +147,24 @@ tmp<pointField> triSurfaceSearch::calcNearest
|
||||
const vector& span
|
||||
) const
|
||||
{
|
||||
const pointField& points = surface_.points();
|
||||
const scalar nearestDistSqr = 0.25*magSqr(span);
|
||||
|
||||
tmp<pointField> tnearest(new pointField(samples.size()));
|
||||
pointField& nearest = tnearest();
|
||||
|
||||
labelList nearestTri(calcNearestTri(samples, span));
|
||||
pointIndexHit hitInfo;
|
||||
|
||||
forAll(nearestTri, sampleI)
|
||||
forAll(samples, sampleI)
|
||||
{
|
||||
label triI = nearestTri[sampleI];
|
||||
hitInfo = tree().findNearest(samples[sampleI], nearestDistSqr);
|
||||
|
||||
if (triI == -1)
|
||||
if (hitInfo.hit())
|
||||
{
|
||||
nearest[sampleI] = greatPoint;
|
||||
nearest[sampleI] = hitInfo.hitPoint();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unfortunately octree does not return nearest point
|
||||
// so we have to recalculate it.
|
||||
const labelledTri& f = surface_[triI];
|
||||
|
||||
triPointRef tri
|
||||
(
|
||||
points[f[0]],
|
||||
points[f[1]],
|
||||
points[f[2]]
|
||||
);
|
||||
|
||||
nearest[sampleI] = tri.nearestPoint(samples[sampleI]).rawPoint();
|
||||
nearest[sampleI] = greatPoint;
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,40 +175,9 @@ tmp<pointField> triSurfaceSearch::calcNearest
|
||||
pointIndexHit triSurfaceSearch::nearest(const point& pt, const vector& span)
|
||||
const
|
||||
{
|
||||
pointIndexHit pInter;
|
||||
const scalar nearestDistSqr = 0.25*magSqr(span);
|
||||
|
||||
treeBoundBox tightest(pt, pt);
|
||||
tightest.min() -= span;
|
||||
tightest.max() += span;
|
||||
|
||||
scalar tightestDist = Foam::GREAT;
|
||||
|
||||
label triI = tree().findNearest(pt, tightest, tightestDist);
|
||||
|
||||
if (triI == -1)
|
||||
{
|
||||
pInter.setMiss();
|
||||
}
|
||||
else
|
||||
{
|
||||
pInter.setHit();
|
||||
pInter.setIndex(triI);
|
||||
|
||||
const labelledTri& f = surface_[triI];
|
||||
|
||||
const pointField& points = surface_.points();
|
||||
|
||||
triPointRef tri
|
||||
(
|
||||
points[f[0]],
|
||||
points[f[1]],
|
||||
points[f[2]]
|
||||
);
|
||||
|
||||
pInter.setPoint(tri.nearestPoint(pt).rawPoint());
|
||||
}
|
||||
|
||||
return pInter;
|
||||
return tree().findNearest(pt, nearestDistSqr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -49,8 +49,8 @@ namespace Foam
|
||||
|
||||
// Forward declaration of classes
|
||||
class triSurface;
|
||||
class octreeDataTriSurface;
|
||||
template<class Type> class octree;
|
||||
class treeDataTriSurface;
|
||||
template<class Type> class indexedOctree;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class triSurfaceSearch Declaration
|
||||
@ -64,7 +64,7 @@ class triSurfaceSearch
|
||||
const triSurface& surface_;
|
||||
|
||||
//- Octree for searches
|
||||
const octree<octreeDataTriSurface>* treePtr_;
|
||||
autoPtr<indexedOctree<treeDataTriSurface> > treePtr_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
@ -89,16 +89,13 @@ public:
|
||||
//- Construct from surface. Holds reference to surface!
|
||||
triSurfaceSearch(const triSurface&);
|
||||
|
||||
// Destructor
|
||||
|
||||
~triSurfaceSearch();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
const octree<octreeDataTriSurface>& tree() const
|
||||
const indexedOctree<treeDataTriSurface>& tree() const
|
||||
{
|
||||
return *treePtr_;
|
||||
return treePtr_();
|
||||
}
|
||||
|
||||
const triSurface& surface() const
|
||||
|
||||
@ -52,7 +52,7 @@ class STLtriangle
|
||||
// Private data
|
||||
|
||||
STLpoint normal_, a_, b_, c_;
|
||||
short region_;
|
||||
unsigned short region_;
|
||||
|
||||
|
||||
public:
|
||||
@ -69,7 +69,7 @@ public:
|
||||
const STLpoint& a,
|
||||
const STLpoint& b,
|
||||
const STLpoint& c,
|
||||
short region
|
||||
unsigned short region
|
||||
);
|
||||
|
||||
//- Construct from istream (read binary)
|
||||
@ -83,7 +83,7 @@ public:
|
||||
inline const STLpoint& a() const;
|
||||
inline const STLpoint& b() const;
|
||||
inline const STLpoint& c() const;
|
||||
inline short region() const;
|
||||
inline unsigned short region() const;
|
||||
|
||||
// Read
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ inline STLtriangle::STLtriangle
|
||||
const STLpoint& a,
|
||||
const STLpoint& b,
|
||||
const STLpoint& c,
|
||||
short region
|
||||
unsigned short region
|
||||
)
|
||||
:
|
||||
normal_(normal),
|
||||
@ -80,7 +80,7 @@ inline const STLpoint& STLtriangle::c() const
|
||||
return c_;
|
||||
}
|
||||
|
||||
inline short STLtriangle::region() const
|
||||
inline unsigned short STLtriangle::region() const
|
||||
{
|
||||
return region_;
|
||||
}
|
||||
|
||||
@ -504,13 +504,22 @@ bool triSurface::read(Istream& is)
|
||||
|
||||
|
||||
// Read from file in given format
|
||||
bool triSurface::read(const fileName& name, const word& ext)
|
||||
bool triSurface::read(const fileName& name, const word& ext, const bool check)
|
||||
{
|
||||
if (check && !exists(name))
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"triSurface::read(const fileName&, const word&, const bool)"
|
||||
) << "Cannnot read " << name << exit(FatalError);
|
||||
}
|
||||
|
||||
if (ext == "gz")
|
||||
{
|
||||
fileName unzipName = name.lessExt();
|
||||
|
||||
return read(unzipName, unzipName.ext());
|
||||
// Do not check for existence. Let IFstream do the unzipping.
|
||||
return read(unzipName, unzipName.ext(), false);
|
||||
}
|
||||
else if (ext == "ftr")
|
||||
{
|
||||
@ -1203,10 +1212,27 @@ void triSurface::write(const Time& d) const
|
||||
|
||||
void triSurface::writeStats(Ostream& os) const
|
||||
{
|
||||
// Calculate bounding box without any additional addressing
|
||||
// Copy of treeBoundBox code. Cannot use meshTools from triSurface...
|
||||
boundBox bb;
|
||||
forAll(*this, triI)
|
||||
{
|
||||
const labelledTri& f = operator[](triI);
|
||||
|
||||
forAll(f, fp)
|
||||
{
|
||||
const point& pt = points()[f[fp]];
|
||||
bb.min() = ::Foam::min(bb.min(), pt);
|
||||
bb.max() = ::Foam::max(bb.max(), pt);
|
||||
}
|
||||
}
|
||||
|
||||
// Unfortunately nPoints constructs meshPoints() ...
|
||||
|
||||
os << "Triangles : " << size() << endl
|
||||
<< "Edges : " << nEdges() << endl
|
||||
//<< "Edges : " << nEdges() << endl
|
||||
<< "Vertices : " << nPoints() << endl
|
||||
<< "Bounding Box : " << boundBox(localPoints(), false) << endl;
|
||||
<< "Bounding Box : " << bb << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -108,7 +108,7 @@ class triSurface
|
||||
bool read(Istream&);
|
||||
|
||||
//- Generic read routine. Chooses reader based on extension.
|
||||
bool read(const fileName&, const word& ext);
|
||||
bool read(const fileName&, const word& ext, const bool check = true);
|
||||
|
||||
bool readSTL(const fileName&);
|
||||
bool readSTLASCII(const fileName&);
|
||||
|
||||
Reference in New Issue
Block a user