Initial mattijsLib merge

This commit is contained in:
mattijs
2008-04-23 12:20:12 +01:00
parent 27d6f542ed
commit 7faf688709
98 changed files with 9511 additions and 1997 deletions

View File

@ -1,7 +1,7 @@
#!/bin/sh
set -x
( cd $FOAM_SRC/other && ./Allwmake )
#( cd $FOAM_SRC/other && ./Allwmake )
( cd $FOAM_SRC/OpenFOAM && wmakeLnInclude . )

View File

@ -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

View File

@ -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();

View File

@ -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_;

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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
(

View File

@ -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,

View File

@ -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;

View File

@ -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 * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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 * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //

View File

@ -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);
}
}
// ************************************************************************* //

View File

@ -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);
}
}
}
}

View File

@ -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
);

View File

@ -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;
}

View File

@ -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;

View File

@ -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()

View File

@ -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;

View File

@ -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())
{

View File

@ -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();

View File

@ -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>&
);
};

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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

View File

@ -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();

View File

@ -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_)
{

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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
(

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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)
{

View File

@ -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;

View File

@ -78,7 +78,7 @@ bool Foam::layerAdditionRemoval::validCollapse() const
<< nBoundaryHits << endl;
}
if (nBoundaryHits > 0)
if (returnReduce(nBoundaryHits, sumOp<label>()) > 0)
{
return false;
}

View File

@ -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();

View File

@ -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)
{

View File

@ -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

View File

@ -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
);

View File

@ -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]);

View File

@ -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
);
}

View File

@ -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;

View File

@ -136,7 +136,7 @@ void Foam::motionSolver::twoDCorrectPoints(pointField& p) const
}
void Foam::motionSolver::updateMesh()
void Foam::motionSolver::updateMesh(const mapPolyMesh& mpm)
{
twoDPointCorrector_.updateMesh();
}

View File

@ -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;
};

View File

@ -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(),

View File

@ -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;
}
// ************************************************************************* //

View File

@ -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&
);
};

View File

@ -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);

View File

@ -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
);
};

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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

View 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
);
// ************************************************************************* //

View 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
// ************************************************************************* //

View 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;
}
// ************************************************************************* //

View File

@ -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.

View File

@ -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

View 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;
}
// ************************************************************************* //

View 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
// ************************************************************************* //

View 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;
}
}
}
}
// ************************************************************************* //

View 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
// ************************************************************************* //

View 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;
}
}
// ************************************************************************* //

View 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
// ************************************************************************* //

View 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();
}
}
}
}
}
// ************************************************************************* //

View 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
// ************************************************************************* //

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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))
{}

View File

@ -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

View 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);
}
}
// ************************************************************************* //

View 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
// ************************************************************************* //

View 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 * * * * * * * * * * * * * //
// ************************************************************************* //

View 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
// ************************************************************************* //

View 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
// ************************************************************************* //

View 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
// ************************************************************************* //

View 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 * * * * * * * * * * * * * //
// ************************************************************************* //

View 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
// ************************************************************************* //

View File

@ -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]

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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_;
}

View File

@ -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;
}

View File

@ -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&);