Merge branch 'master' into dsmc

This commit is contained in:
graham
2009-03-02 13:11:18 +00:00
56 changed files with 2862 additions and 790 deletions

4
.gitignore vendored
View File

@ -55,7 +55,7 @@ doc/[Dd]oxygen/man
# ignore .timeStamp in the main directory # ignore .timeStamp in the main directory
/.timeStamp /.timeStamp
# ignore .ebrowse in the main directory # ignore .tags in the main directory
/.ebrowse /.tags
# end-of-file # end-of-file

View File

@ -8,5 +8,4 @@ EXE_INC = \
EXE_LIBS = \ EXE_LIBS = \
-lincompressibleRASModels \ -lincompressibleRASModels \
-lincompressibleTransportModels \ -lincompressibleTransportModels \
-lfiniteVolume \ -lfiniteVolume
-lmeshTools

View File

@ -316,6 +316,11 @@ meshQualityControls
//must be >0 for Fluent compatibility //must be >0 for Fluent compatibility
minTriangleTwist -1; minTriangleTwist -1;
//- if >0 : preserve single cells with all points on the surface if the
// resulting volume after snapping is larger than minVolFraction times old
// volume. If <0 : delete always.
minVolFraction 0.1;
// Advanced // Advanced

View File

@ -23,16 +23,13 @@ Foam::label Foam::checkGeometry(const polyMesh& mesh, const bool allGeometry)
scalar minDistSqr = magSqr(1e-6 * globalBb.span()); scalar minDistSqr = magSqr(1e-6 * globalBb.span());
// Non-empty directions // Non-empty directions
const Vector<label> validDirs = (mesh.directions() + Vector<label>::one)/2; const Vector<label> validDirs = (mesh.geometricD() + Vector<label>::one)/2;
Info<< " Mesh (non-empty, non-wedge) directions " << validDirs << endl;
Info<< " Mesh (non-empty) directions " << validDirs << endl; const Vector<label> solDirs = (mesh.solutionD() + Vector<label>::one)/2;
Info<< " Mesh (non-empty) directions " << solDirs << endl;
scalar nGeomDims = mesh.nGeometricD(); if (mesh.nGeometricD() < 3)
Info<< " Mesh (non-empty, non-wedge) dimensions "
<< nGeomDims << endl;
if (nGeomDims < 3)
{ {
pointSet nonAlignedPoints(mesh, "nonAlignedEdges", mesh.nPoints()/100); pointSet nonAlignedPoints(mesh, "nonAlignedEdges", mesh.nPoints()/100);

View File

@ -30,16 +30,16 @@
<!-- Global settings --> <!-- Global settings -->
<!-- Extrapolate Walls check-box --> <!-- Extrapolate Patches check-box -->
<IntVectorProperty <IntVectorProperty
name="ExtrapolateWalls" name="ExtrapolatePatches"
command="SetExtrapolateWalls" command="SetExtrapolatePatches"
number_of_elements="1" number_of_elements="1"
default_values="0" default_values="0"
animateable="0"> animateable="0">
<BooleanDomain name="bool"/> <BooleanDomain name="bool"/>
<Documentation> <Documentation>
Extrapolate internalField to wall and empty patches Extrapolate internalField to non-constraint patches
</Documentation> </Documentation>
</IntVectorProperty> </IntVectorProperty>

View File

@ -64,7 +64,7 @@ vtkPV3FoamReader::vtkPV3FoamReader()
CacheMesh = 1; CacheMesh = 1;
ExtrapolateWalls = 0; ExtrapolatePatches = 0;
IncludeSets = 0; IncludeSets = 0;
IncludeZones = 0; IncludeZones = 0;
ShowPatchNames = 0; ShowPatchNames = 0;

View File

@ -65,9 +65,9 @@ public:
vtkGetMacro(CacheMesh, int); vtkGetMacro(CacheMesh, int);
// Description: // Description:
// FOAM extrapolate internal values onto the walls // FOAM extrapolate internal values onto the patches
vtkSetMacro(ExtrapolateWalls, int); vtkSetMacro(ExtrapolatePatches, int);
vtkGetMacro(ExtrapolateWalls, int); vtkGetMacro(ExtrapolatePatches, int);
// FOAM read sets control // FOAM read sets control
vtkSetMacro(IncludeSets, int); vtkSetMacro(IncludeSets, int);
@ -183,7 +183,7 @@ private:
int TimeStepRange[2]; int TimeStepRange[2];
int CacheMesh; int CacheMesh;
int ExtrapolateWalls; int ExtrapolatePatches;
int IncludeSets; int IncludeSets;
int IncludeZones; int IncludeZones;
int ShowPatchNames; int ShowPatchNames;

View File

@ -659,29 +659,55 @@ void Foam::vtkPV3Foam::addPatchNames(vtkRenderer* renderer)
} }
} }
// Count number of zones we're actually going to display. This is truncated
// to a max per patch
const label MAXPATCHZONES = 20;
label displayZoneI = 0;
forAll(pbMesh, patchI)
{
displayZoneI += min(MAXPATCHZONES, nZones[patchI]);
}
zoneCentre.shrink(); zoneCentre.shrink();
if (debug) if (debug)
{ {
Info<< "patch zone centres = " << zoneCentre << nl Info<< "patch zone centres = " << zoneCentre << nl
<< "displayed zone centres = " << displayZoneI << nl
<< "zones per patch = " << nZones << endl; << "zones per patch = " << nZones << endl;
} }
// Set the size of the patch labels to max number of zones // Set the size of the patch labels to max number of zones
patchTextActorsPtrs_.setSize(zoneCentre.size()); patchTextActorsPtrs_.setSize(displayZoneI);
if (debug) if (debug)
{ {
Info<< "constructing patch labels" << endl; Info<< "constructing patch labels" << endl;
} }
// Actor index
displayZoneI = 0;
// Index in zone centres
label globalZoneI = 0; label globalZoneI = 0;
forAll(pbMesh, patchI) forAll(pbMesh, patchI)
{ {
const polyPatch& pp = pbMesh[patchI]; const polyPatch& pp = pbMesh[patchI];
// Only selected patches will have a non-zero number of zones // Only selected patches will have a non-zero number of zones
for (label i=0; i<nZones[patchI]; i++) label nDisplayZones = min(MAXPATCHZONES, nZones[patchI]);
label increment = 1;
if (nZones[patchI] >= MAXPATCHZONES)
{
increment = nZones[patchI]/MAXPATCHZONES;
}
for (label i = 0; i < nDisplayZones; i++)
{ {
if (debug) if (debug)
{ {
@ -719,14 +745,15 @@ void Foam::vtkPV3Foam::addPatchNames(vtkRenderer* renderer)
// Maintain a list of text labels added so that they can be // Maintain a list of text labels added so that they can be
// removed later // removed later
patchTextActorsPtrs_[globalZoneI] = txt; patchTextActorsPtrs_[displayZoneI] = txt;
globalZoneI++; globalZoneI += increment;
displayZoneI++;
} }
} }
// Resize the patch names list to the actual number of patch names added // Resize the patch names list to the actual number of patch names added
patchTextActorsPtrs_.setSize(globalZoneI); patchTextActorsPtrs_.setSize(displayZoneI);
if (debug) if (debug)
{ {

View File

@ -132,8 +132,8 @@ void Foam::vtkPV3Foam::convertVolFields
isType<emptyFvPatchField<Type> >(ptf) isType<emptyFvPatchField<Type> >(ptf)
|| ||
( (
typeid(patches[patchId]) == typeid(wallPolyPatch) reader_->GetExtrapolatePatches()
&& reader_->GetExtrapolateWalls() && !polyPatch::constraintType(patches[patchId].type())
) )
) )
{ {

View File

@ -27,26 +27,27 @@
# foamEbrowse # foamEbrowse
# #
# Description # Description
# Build the Ebrowse database for all the .C and .H files # Build the Ebrowse database for all the .H and .C files
# #
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
headersFile=${TMPDIR:-/tmp}/headersFile.$$
sourcesFile=${TMPDIR:-/tmp}/sourcesFile.$$ sourcesFile=${TMPDIR:-/tmp}/sourcesFile.$$
if [ $# -ne 0 ]; then if [ $# -ne 0 ]; then
echo "Usage : ${0##*/}" echo "Usage : ${0##*/}"
echo "" echo ""
echo "Build the Ebrowse dadbase for all the .C and .H files" echo "Build the Ebrowse dadbase for all the .H and .C files"
echo "" echo ""
exit 1 exit 1
fi fi
# Clean up on termination and on Ctrl-C # Clean up on termination and on Ctrl-C
trap 'rm -f $headersFile $sourcesFile 2>/dev/null; exit 0' EXIT TERM INT trap 'rm -f $sourcesFile 2>/dev/null; exit 0' EXIT TERM INT
cd $WM_PROJECT_DIR cd $WM_PROJECT_DIR
find -H . -name "*.H" | fgrep -v lnInclude > $headersFile mkdir .tags 2>/dev/null
find -H . -name "*.C" | fgrep -v lnInclude > $sourcesFile cd .tags
ebrowse --files=$headersFile --files=$sourcesFile --output-file=.ebrowse
find -H .. \( -name "*.[HC]" -not -name "lnInclude" -not -name "Doxygen" \) -print > $sourcesFile
ebrowse --files=$sourcesFile --output-file=ebrowse
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------

56
bin/foamTags Executable file
View File

@ -0,0 +1,56 @@
#!/bin/sh
#------------------------------------------------------------------------------
# ========= |
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
# \\ / O peration |
# \\ / A nd | Copyright (C) 1991-2009 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
#
# Script
# foamTags
#
# Description
# Build the tags files for all the .C and .H files
#
#------------------------------------------------------------------------------
if [ $# -ne 0 ]; then
echo "Usage : ${0##*/}"
echo ""
echo "Build the tags files for all the .C and .H files"
echo ""
exit 1
fi
cd $WM_PROJECT_DIR
mkdir .tags 2>/dev/null
find -H . \( -name "*.[HC]" -not -name "lnInclude" -not -name "Doxygen" \) | \
etags --declarations -l c++ -o .tags/etags -
find -H . \( -name "*.[HC]" -not -name "lnInclude" -not -name "Doxygen" \) | \
etags -l c++ -o .tags/etagsDef -
find -H . \( -name "*.H" -not -name "lnInclude" -not -name "Doxygen" \) | \
etags --declarations -l c++ -o .tags/etagsDec -
gtags -i --gtagsconf bin/tools/gtagsrc .tags
foamEbrowse
#------------------------------------------------------------------------------

63
bin/tools/gtagsrc Normal file
View File

@ -0,0 +1,63 @@
#------------------------------------------------------------------------------
# ========= |
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
# \\ / O peration |
# \\ / A nd | Copyright (C) 1991-2009 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
#
# Canfiguration file
# gtagsrc
#
# Description
# Configuration file for gtags(1).
#
#------------------------------------------------------------------------------
default:\
:tc=gtags:tc=htags:
#------------------------------------------------------------------------------
# Configuration for gtags(1)
# See gtags(1).
#------------------------------------------------------------------------------
common:\
:skip=GPATH,GTAGS,GRTAGS,GSYMS,HTML/,HTML.pub/,html/,tags,TAGS,ID,.ebrowse,.etags,.etagsDef,.etagsDec,y.tab.c,y.tab.h,.notfunction,cscope.out,cscope.po.out,cscope.in.out,.gdbinit,SCCS/,RCS/,CVS/,CVSROOT/,{arch}/,.svn/,.git/,.cvsrc,.cvsignore,.gitignore,.cvspass,.cvswrappers,.deps/,autom4te.cache/,.snprj/:\
:langmap=c\:.c.h,yacc\:.y,asm\:.s.S,java\:.java,cpp\:.c++.cc.cpp.cxx.hxx.hpp.C.H,php\:.php.php3.phtml:
gtags:\
:tc=common:\
:GTAGS=gtags-parser %s:\
:GRTAGS=gtags-parser -r %s:\
:GSYMS=gtags-parser -s %s:\
:skip=lnInclude/,tutorials/,wmake/,doc/,lib/,etc/:
#
#------------------------------------------------------------------------------
# Configuration for htags(1)
#------------------------------------------------------------------------------
htags:\
:body_begin=<body text='#191970' bgcolor='#f5f5dc' vlink='gray'>:body_end=</body>:\
:table_begin=<table>:table_end=</table>:\
:title_begin=<h1><font color='#cc0000'>:title_end=</font></h1>:\
:comment_begin=<i><font color='green'>:comment_end=</font></i>:\
:sharp_begin=<font color='darkred'>:sharp_end=</font>:\
:brace_begin=<font color='red'>:brace_end=</font>:\
:warned_line_begin=<span style='background-color\:yellow'>:warned_line_end=</span>:\
:reserved_begin=<b>:reserved_end=</b>:script_alias=/cgi-bin/:\
:ncol#4:tabs#8:normal_suffix=html:gzipped_suffix=ghtml:\
:definition_header=no:
#------------------------------------------------------------------------------

View File

@ -5,8 +5,8 @@ set -x
# update OpenFOAM version strings if required # update OpenFOAM version strings if required
wmakePrintBuild -check || /bin/rm -f OpenFOAM/Make/$WM_OPTIONS/global.? 2>/dev/null wmakePrintBuild -check || /bin/rm -f OpenFOAM/Make/$WM_OPTIONS/global.? 2>/dev/null
wmakeLnInclude -f OpenFOAM wmakeLnInclude -f OpenFOAM -sf
wmakeLnInclude -f OSspecific/$WM_OS wmakeLnInclude -f OSspecific/$WM_OS -sf
Pstream/Allwmake Pstream/Allwmake
wmake libo OSspecific/$WM_OS wmake libo OSspecific/$WM_OS

View File

@ -58,8 +58,9 @@ Foam::word Foam::Time::findInstance
{ {
if (debug) if (debug)
{ {
Info<< "Time::findInstance(const fileName&, const word&) : " Info<< "Time::findInstance"
<< "found \"" << name "(const fileName&, const word&, const IOobject::readOption)"
<< " : found \"" << name
<< "\" in " << timeName()/dir << "\" in " << timeName()/dir
<< endl; << endl;
} }
@ -98,8 +99,8 @@ Foam::word Foam::Time::findInstance
if (debug) if (debug)
{ {
Info<< "Time::findInstance" Info<< "Time::findInstance"
"(const fileName&,const word&) : " "(const fileName&, const word&, const IOobject::readOption)"
<< "found \"" << name << " : found \"" << name
<< "\" in " << ts[instanceI].name()/dir << "\" in " << ts[instanceI].name()/dir
<< endl; << endl;
} }
@ -129,8 +130,8 @@ Foam::word Foam::Time::findInstance
if (debug) if (debug)
{ {
Info<< "Time::findInstance" Info<< "Time::findInstance"
"(const fileName&,const word&) : " "(const fileName&, const word&, const IOobject::readOption)"
<< "found \"" << name << " : found \"" << name
<< "\" in " << constant()/dir << "\" in " << constant()/dir
<< endl; << endl;
} }
@ -141,10 +142,10 @@ Foam::word Foam::Time::findInstance
if (rOpt == IOobject::MUST_READ) if (rOpt == IOobject::MUST_READ)
{ {
FatalErrorIn FatalErrorIn
( (
"Time::findInstance(const fileName&,const word&)" "Time::findInstance"
) "(const fileName&, const word&, const IOobject::readOption)"
<< "Cannot find file \"" << name << "\" in directory " ) << "Cannot find file \"" << name << "\" in directory "
<< constant()/dir << constant()/dir
<< exit(FatalError); << exit(FatalError);
} }

View File

@ -154,7 +154,7 @@ tmp<GeometricField<scalar, PatchField, GeoMesh> > pow
pow pow
( (
gsf1.dimensions(), gsf1.dimensions(),
dimensionedScalar("1", 1.0, gsf2.dimensions()) dimensionedScalar("1", gsf2.dimensions(), 1.0)
) )
) )
); );
@ -183,7 +183,7 @@ tmp<GeometricField<scalar, PatchField, GeoMesh> > pow
pow pow
( (
gsf1.dimensions(), gsf1.dimensions(),
dimensionedScalar("1", 1.0, gsf2.dimensions()) dimensionedScalar("1", gsf2.dimensions(), 1.0)
) )
) )
); );
@ -214,7 +214,7 @@ tmp<GeometricField<scalar, PatchField, GeoMesh> > pow
pow pow
( (
gsf1.dimensions(), gsf1.dimensions(),
dimensionedScalar("1", 1.0, gsf2.dimensions()) dimensionedScalar("1", gsf2.dimensions(), 1.0)
) )
) )
); );
@ -247,7 +247,7 @@ tmp<GeometricField<scalar, PatchField, GeoMesh> > pow
pow pow
( (
gsf1.dimensions(), gsf1.dimensions(),
dimensionedScalar("1", 1.0, gsf2.dimensions()) dimensionedScalar("1", gsf2.dimensions(), 1.0)
) )
) )
); );

View File

@ -60,7 +60,7 @@ void Foam::lduMatrix::Amul
interfaceBouCoeffs, interfaceBouCoeffs,
interfaces, interfaces,
psi, psi,
Apsi, Apsi,
cmpt cmpt
); );
@ -79,7 +79,7 @@ void Foam::lduMatrix::Amul
register const label nFaces = upper().size(); register const label nFaces = upper().size();
#ifdef ICC_IA64_PREFETCH #ifdef ICC_IA64_PREFETCH
#pragma swp #pragma swp
#endif #endif
for (register label face=0; face<nFaces; face++) for (register label face=0; face<nFaces; face++)
{ {
@ -227,7 +227,7 @@ void Foam::lduMatrix::sumA
} }
#ifdef ICC_IA64_PREFETCH #ifdef ICC_IA64_PREFETCH
#pragma swp #pragma swp
#endif #endif
for (register label face=0; face<nFaces; face++) for (register label face=0; face<nFaces; face++)
@ -316,7 +316,7 @@ void Foam::lduMatrix::residual
mBouCoeffs, mBouCoeffs,
interfaces, interfaces,
psi, psi,
rA, rA,
cmpt cmpt
); );
@ -336,7 +336,7 @@ void Foam::lduMatrix::residual
register const label nFaces = upper().size(); register const label nFaces = upper().size();
#ifdef ICC_IA64_PREFETCH #ifdef ICC_IA64_PREFETCH
#pragma swp #pragma swp
#endif #endif
for (register label face=0; face<nFaces; face++) for (register label face=0; face<nFaces; face++)
{ {

View File

@ -54,40 +54,79 @@ void Foam::polyMesh::calcDirections() const
{ {
for (direction cmpt=0; cmpt<vector::nComponents; cmpt++) for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
{ {
directions_[cmpt] = 1; solutionD_[cmpt] = 1;
} }
label nEmptyPatches = 0; // Knock out empty and wedge directions. Note:they will be present on all
// domains.
vector dirVec = vector::zero; label nEmptyPatches = 0;
label nWedgePatches = 0;
vector emptyDirVec = vector::zero;
vector wedgeDirVec = vector::zero;
forAll(boundaryMesh(), patchi) forAll(boundaryMesh(), patchi)
{ {
if (isA<emptyPolyPatch>(boundaryMesh()[patchi])) if (boundaryMesh()[patchi].size())
{ {
if (boundaryMesh()[patchi].size()) if (isA<emptyPolyPatch>(boundaryMesh()[patchi]))
{ {
nEmptyPatches++; nEmptyPatches++;
dirVec += sum(cmptMag(boundaryMesh()[patchi].faceAreas())); emptyDirVec += sum(cmptMag(boundaryMesh()[patchi].faceAreas()));
}
else if (isA<wedgePolyPatch>(boundaryMesh()[patchi]))
{
const wedgePolyPatch& wpp = refCast<const wedgePolyPatch>
(
boundaryMesh()[patchi]
);
nWedgePatches++;
wedgeDirVec += cmptMag(wpp.centreNormal());
} }
} }
} }
if (nEmptyPatches) if (nEmptyPatches)
{ {
reduce(dirVec, sumOp<vector>()); reduce(emptyDirVec, sumOp<vector>());
dirVec /= mag(dirVec); emptyDirVec /= mag(emptyDirVec);
for (direction cmpt=0; cmpt<vector::nComponents; cmpt++) for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
{ {
if (dirVec[cmpt] > 1e-6) if (emptyDirVec[cmpt] > 1e-6)
{ {
directions_[cmpt] = -1; solutionD_[cmpt] = -1;
} }
else else
{ {
directions_[cmpt] = 1; solutionD_[cmpt] = 1;
}
}
}
// Knock out wedge directions
geometricD_ = solutionD_;
if (nWedgePatches)
{
reduce(wedgeDirVec, sumOp<vector>());
wedgeDirVec /= mag(wedgeDirVec);
for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
{
if (wedgeDirVec[cmpt] > 1e-6)
{
geometricD_[cmpt] = -1;
}
else
{
geometricD_[cmpt] = 1;
} }
} }
} }
@ -163,7 +202,8 @@ Foam::polyMesh::polyMesh(const IOobject& io)
*this *this
), ),
bounds_(points_), bounds_(points_),
directions_(Vector<label>::zero), geometricD_(Vector<label>::zero),
solutionD_(Vector<label>::zero),
pointZones_ pointZones_
( (
IOobject IOobject
@ -350,7 +390,8 @@ Foam::polyMesh::polyMesh
0 0
), ),
bounds_(points_, syncPar), bounds_(points_, syncPar),
directions_(Vector<label>::zero), geometricD_(Vector<label>::zero),
solutionD_(Vector<label>::zero),
pointZones_ pointZones_
( (
IOobject IOobject
@ -505,7 +546,8 @@ Foam::polyMesh::polyMesh
0 0
), ),
bounds_(points_, syncPar), bounds_(points_, syncPar),
directions_(Vector<label>::zero), geometricD_(Vector<label>::zero),
solutionD_(Vector<label>::zero),
pointZones_ pointZones_
( (
IOobject IOobject
@ -766,44 +808,37 @@ const Foam::fileName& Foam::polyMesh::facesInstance() const
} }
const Foam::Vector<Foam::label>& Foam::polyMesh::directions() const const Foam::Vector<Foam::label>& Foam::polyMesh::geometricD() const
{ {
if (directions_.x() == 0) if (geometricD_.x() == 0)
{ {
calcDirections(); calcDirections();
} }
return directions_; return geometricD_;
} }
Foam::label Foam::polyMesh::nGeometricD() const Foam::label Foam::polyMesh::nGeometricD() const
{ {
label nWedges = 0; return cmptSum(geometricD() + Vector<label>::one)/2;
}
forAll(boundary_, patchi)
const Foam::Vector<Foam::label>& Foam::polyMesh::solutionD() const
{
if (solutionD_.x() == 0)
{ {
if (isA<wedgePolyPatch>(boundary_[patchi])) calcDirections();
{
nWedges++;
}
} }
if (nWedges != 0 && nWedges != 2 && nWedges != 4) return solutionD_;
{
FatalErrorIn("label polyMesh::nGeometricD() const")
<< "Number of wedge patches " << nWedges << " is incorrect, "
"should be 0, 2 or 4"
<< exit(FatalError);
}
return nSolutionD() - nWedges/2;
} }
Foam::label Foam::polyMesh::nSolutionD() const Foam::label Foam::polyMesh::nSolutionD() const
{ {
return cmptSum(directions() + Vector<label>::one)/2; return cmptSum(solutionD() + Vector<label>::one)/2;
} }
@ -823,6 +858,10 @@ void Foam::polyMesh::addPatches
<< abort(FatalError); << abort(FatalError);
} }
// Reset valid directions
geometricD_ = Vector<label>::zero;
solutionD_ = Vector<label>::zero;
boundary_.setSize(p.size()); boundary_.setSize(p.size());
// Copy the patch pointers // Copy the patch pointers
@ -1037,6 +1076,10 @@ Foam::tmp<Foam::scalarField> Foam::polyMesh::movePoints
faceZones_.movePoints(points_); faceZones_.movePoints(points_);
cellZones_.movePoints(points_); cellZones_.movePoints(points_);
// Reset valid directions (could change with rotation)
geometricD_ = Vector<label>::zero;
solutionD_ = Vector<label>::zero;
// Hack until proper callbacks. Below are all the polyMeh MeshObjects with a // Hack until proper callbacks. Below are all the polyMeh MeshObjects with a
// movePoints function. // movePoints function.

View File

@ -120,9 +120,13 @@ private:
// Created from points on construction, updated when the mesh moves // Created from points on construction, updated when the mesh moves
boundBox bounds_; boundBox bounds_;
//- vector of non-constrained directions in mesh
// defined according to the presence of empty and wedge patches
mutable Vector<label> geometricD_;
//- vector of valid directions in mesh //- vector of valid directions in mesh
// defined according to the presence of empty patches // defined according to the presence of empty patches
mutable Vector<label> directions_; mutable Vector<label> solutionD_;
// Zoning information // Zoning information
@ -309,17 +313,22 @@ public:
return bounds_; return bounds_;
} }
//- Return the vector of valid directions in mesh. //- Return the vector of geometric directions in mesh.
// Defined according to the presence of empty patches. // Defined according to the presence of empty and wedge patches.
// 1 indicates valid direction and -1 an invalid direction. // 1 indicates unconstrained direction and -1 a constrained
const Vector<label>& directions() const; // direction.
const Vector<label>& geometricD() const;
//- Return the number of valid geometric dimensions in the mesh //- Return the number of valid geometric dimensions in the mesh
label nGeometricD() const; label nGeometricD() const;
//- Return the number of valid solution dimensions in the mesh. //- Return the vector of solved-for directions in mesh.
// For wedge cases this includes the circumferential direction // Differs from geometricD in that it includes for wedge cases
// in case of swirl. // the circumferential direction in case of swirl.
// 1 indicates valid direction and -1 an invalid direction.
const Vector<label>& solutionD() const;
//- Return the number of valid solved-for dimensions in the mesh
label nSolutionD() const; label nSolutionD() const;
//- Return point zone mesh //- Return point zone mesh

View File

@ -68,6 +68,10 @@ void Foam::polyMesh::clearGeom()
boundary_[patchI].clearGeom(); boundary_[patchI].clearGeom();
} }
// Reset valid directions (could change with rotation)
geometricD_ = Vector<label>::zero;
solutionD_ = Vector<label>::zero;
pointMesh::Delete(*this); pointMesh::Delete(*this);
} }
@ -87,6 +91,10 @@ void Foam::polyMesh::clearAddressing()
// recalculation // recalculation
deleteDemandDrivenData(globalMeshDataPtr_); deleteDemandDrivenData(globalMeshDataPtr_);
// Reset valid directions
geometricD_ = Vector<label>::zero;
solutionD_ = Vector<label>::zero;
pointMesh::Delete(*this); pointMesh::Delete(*this);
} }

View File

@ -217,7 +217,8 @@ Foam::polyMesh::polyMesh
boundaryFaces.size() + 1 // add room for a default patch boundaryFaces.size() + 1 // add room for a default patch
), ),
bounds_(points_, syncPar), bounds_(points_, syncPar),
directions_(Vector<label>::zero), geometricD_(Vector<label>::zero),
solutionD_(Vector<label>::zero),
pointZones_ pointZones_
( (
IOobject IOobject

View File

@ -68,6 +68,11 @@ void Foam::polyMesh::updateMesh(const mapPolyMesh& mpm)
newMotionPoints.map(oldMotionPoints, mpm.pointMap()); newMotionPoints.map(oldMotionPoints, mpm.pointMap());
} }
// Reset valid directions (could change by faces put into empty patches)
geometricD_ = Vector<label>::zero;
solutionD_ = Vector<label>::zero;
// Hack until proper callbacks. Below are all the polyMesh-MeshObjects. // Hack until proper callbacks. Below are all the polyMesh-MeshObjects.
// pointMesh // pointMesh

View File

@ -29,6 +29,7 @@ License
#include "mathematicalConstants.H" #include "mathematicalConstants.H"
#include "refinementSurfaces.H" #include "refinementSurfaces.H"
#include "searchableSurfaces.H" #include "searchableSurfaces.H"
#include "regExp.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -300,10 +301,44 @@ Foam::layerParameters::layerParameters
// readScalar(layerDict.lookup("minThickness")); // readScalar(layerDict.lookup("minThickness"));
} }
} }
// Check whether layer specification matches any patches
const List<keyType> wildCards = layersDict.keys(true);
forAll(wildCards, i)
{
regExp re(wildCards[i]);
bool hasMatch = false;
forAll(boundaryMesh, patchI)
{
if (re.match(boundaryMesh[patchI].name()))
{
hasMatch = true;
break;
}
}
if (!hasMatch)
{
IOWarningIn("layerParameters::layerParameters(..)", layersDict)
<< "Wildcard layer specification for " << wildCards[i]
<< " does not match any patch." << endl;
}
}
const List<keyType> nonWildCards = layersDict.keys(false);
forAll(nonWildCards, i)
{
if (boundaryMesh.findPatchID(nonWildCards[i]) == -1)
{
IOWarningIn("layerParameters::layerParameters(..)", layersDict)
<< "Layer specification for " << nonWildCards[i]
<< " does not match any patch." << endl;
}
}
} }
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// ************************************************************************* // // ************************************************************************* //

View File

@ -265,101 +265,112 @@ Foam::refinementSurfaces::refinementSurfaces
zoneInside_(surfacesDict.size()), zoneInside_(surfacesDict.size()),
regionOffset_(surfacesDict.size()) regionOffset_(surfacesDict.size())
{ {
labelList globalMinLevel(surfacesDict.size(), 0); // Wilcard specification : loop over all surface, all regions
labelList globalMaxLevel(surfacesDict.size(), 0); // and try to find a match.
scalarField globalAngle(surfacesDict.size(), -GREAT);
List<Map<label> > regionMinLevel(surfacesDict.size());
List<Map<label> > regionMaxLevel(surfacesDict.size());
List<Map<scalar> > regionAngle(surfacesDict.size());
// Count number of surfaces.
label surfI = 0; label surfI = 0;
forAllConstIter(dictionary, surfacesDict, iter) forAll(allGeometry.names(), geomI)
{ {
names_[surfI] = iter().keyword(); const word& geomName = allGeometry_.names()[geomI];
surfaces_[surfI] = allGeometry_.findSurfaceID(names_[surfI]); if (surfacesDict.found(geomName))
if (surfaces_[surfI] == -1)
{ {
FatalErrorIn surfI++;
(
"refinementSurfaces::refinementSurfaces"
"(const searchableSurfaces&, const dictionary>&"
) << "No surface called " << iter().keyword() << endl
<< "Valid surfaces are " << allGeometry_.names()
<< exit(FatalError);
} }
const dictionary& dict = surfacesDict.subDict(iter().keyword()); }
const labelPair refLevel(dict.lookup("level")); // Size lists
globalMinLevel[surfI] = refLevel[0]; surfaces_.setSize(surfI);
globalMaxLevel[surfI] = refLevel[1]; names_.setSize(surfI);
faceZoneNames_.setSize(surfI);
cellZoneNames_.setSize(surfI);
zoneInside_.setSize(surfI);
regionOffset_.setSize(surfI);
// Global zone names per surface labelList globalMinLevel(surfI, 0);
if (dict.found("faceZone")) labelList globalMaxLevel(surfI, 0);
scalarField globalAngle(surfI, -GREAT);
List<Map<label> > regionMinLevel(surfI);
List<Map<label> > regionMaxLevel(surfI);
List<Map<scalar> > regionAngle(surfI);
surfI = 0;
forAll(allGeometry.names(), geomI)
{
const word& geomName = allGeometry_.names()[geomI];
if (surfacesDict.found(geomName))
{ {
dict.lookup("faceZone") >> faceZoneNames_[surfI]; const dictionary& dict = surfacesDict.subDict(geomName);
dict.lookup("cellZone") >> cellZoneNames_[surfI];
dict.lookup("zoneInside") >> zoneInside_[surfI];
}
// Global perpendicular angle names_[surfI] = geomName;
if (dict.found("perpendicularAngle")) surfaces_[surfI] = geomI;
{
globalAngle[surfI] = readScalar(dict.lookup("perpendicularAngle"));
}
if (dict.found("regions")) const labelPair refLevel(dict.lookup("level"));
{ globalMinLevel[surfI] = refLevel[0];
const dictionary& regionsDict = dict.subDict("regions"); globalMaxLevel[surfI] = refLevel[1];
const wordList& regionNames =
allGeometry_[surfaces_[surfI]].regions();
forAllConstIter(dictionary, regionsDict, iter) // Global zone names per surface
if (dict.found("faceZone"))
{ {
const word& key = iter().keyword(); dict.lookup("faceZone") >> faceZoneNames_[surfI];
dict.lookup("cellZone") >> cellZoneNames_[surfI];
dict.lookup("zoneInside") >> zoneInside_[surfI];
}
if (regionsDict.isDict(key)) // Global perpendicular angle
if (dict.found("perpendicularAngle"))
{
globalAngle[surfI] = readScalar
(
dict.lookup("perpendicularAngle")
);
}
if (dict.found("regions"))
{
const dictionary& regionsDict = dict.subDict("regions");
const wordList& regionNames =
allGeometry_[surfaces_[surfI]].regions();
forAll(regionNames, regionI)
{ {
// Get the dictionary for region iter.keyword() if (regionsDict.found(regionNames[regionI]))
const dictionary& regionDict = regionsDict.subDict(key);
label regionI = findIndex(regionNames, key);
if (regionI == -1)
{ {
FatalErrorIn // Get the dictionary for region
const dictionary& regionDict = regionsDict.subDict
( (
"refinementSurfaces::refinementSurfaces" regionNames[regionI]
"(const searchableSurfaces&, const dictionary>&"
) << "No region called " << key << " on surface "
<< allGeometry_[surfaces_[surfI]].name() << endl
<< "Valid regions are " << regionNames
<< exit(FatalError);
}
const labelPair refLevel(regionDict.lookup("level"));
regionMinLevel[surfI].insert(regionI, refLevel[0]);
regionMaxLevel[surfI].insert(regionI, refLevel[1]);
if (regionDict.found("perpendicularAngle"))
{
regionAngle[surfI].insert
(
regionI,
readScalar(regionDict.lookup("perpendicularAngle"))
); );
const labelPair refLevel(regionDict.lookup("level"));
regionMinLevel[surfI].insert(regionI, refLevel[0]);
regionMaxLevel[surfI].insert(regionI, refLevel[1]);
if (regionDict.found("perpendicularAngle"))
{
regionAngle[surfI].insert
(
regionI,
readScalar
(
regionDict.lookup("perpendicularAngle")
)
);
}
} }
} }
} }
surfI++;
} }
surfI++;
} }
// Calculate local to global region offset // Calculate local to global region offset
label nRegions = 0; label nRegions = 0;
forAll(surfacesDict, surfI) forAll(surfaces_, surfI)
{ {
regionOffset_[surfI] = nRegions; regionOffset_[surfI] = nRegions;
nRegions += allGeometry_[surfaces_[surfI]].regions().size(); nRegions += allGeometry_[surfaces_[surfI]].regions().size();

View File

@ -29,6 +29,10 @@ License
#include "volFields.H" #include "volFields.H"
#include "surfaceFields.H" #include "surfaceFields.H"
#include "fvMatrices.H" #include "fvMatrices.H"
#include "PackedList.H"
#include "syncTools.H"
#include "faceSet.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -39,12 +43,15 @@ Foam::MRFZone::MRFZone(const fvMesh& mesh, Istream& is)
dict_(is), dict_(is),
cellZoneID_(mesh_.cellZones().findZoneID(name_)), cellZoneID_(mesh_.cellZones().findZoneID(name_)),
faceZoneID_(mesh_.faceZones().findZoneID(name_)), faceZoneID_(mesh_.faceZones().findZoneID(name_)),
outsideFaces_(0),
patchNames_(dict_.lookup("patches")), patchNames_(dict_.lookup("patches")),
origin_(dict_.lookup("origin")), origin_(dict_.lookup("origin")),
axis_(dict_.lookup("axis")), axis_(dict_.lookup("axis")),
omega_(dict_.lookup("omega")), omega_(dict_.lookup("omega")),
Omega_("Omega", omega_*axis_) Omega_("Omega", omega_*axis_)
{ {
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
axis_ = axis_/mag(axis_); axis_ = axis_/mag(axis_);
Omega_ = omega_*axis_; Omega_ = omega_*axis_;
@ -65,18 +72,71 @@ Foam::MRFZone::MRFZone(const fvMesh& mesh, Istream& is)
if (!faceZoneFound) if (!faceZoneFound)
{ {
FatalErrorIn // Determine faces in cell zone
( // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"Foam::MRFZone::MRFZone(const fvMesh& , const dictionary&)" // (does not construct cells)
) << "cannot find MRF faceZone " << name_
<< exit(FatalError); const labelList& own = mesh_.faceOwner();
const labelList& nei = mesh_.faceNeighbour();
// Cells in zone
PackedBoolList zoneCell(mesh_.nCells());
if (cellZoneID_ != -1)
{
const labelList& cellLabels = mesh_.cellZones()[cellZoneID_];
forAll(cellLabels, i)
{
zoneCell[cellLabels[i]] = 1u;
}
}
// Faces in zone
PackedBoolList zoneFacesSet(mesh_.nFaces());
for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
{
if
(
zoneCell.get(own[faceI]) == 1u
|| zoneCell.get(nei[faceI]) == 1u
)
{
zoneFacesSet[faceI] = 1u;
}
}
syncTools::syncFaceList(mesh_, zoneFacesSet, orEqOp<unsigned int>());
// Transfer to labelList
label n = zoneFacesSet.count();
outsideFaces_.setSize(n);
n = 0;
forAll(zoneFacesSet, faceI)
{
if (zoneFacesSet.get(faceI) == 1u)
{
outsideFaces_[n++] = faceI;
}
}
Info<< nl
<< "MRFZone " << name_ << " : did not find a faceZone; using "
<< returnReduce(outsideFaces_.size(), sumOp<label>())
<< " faces internal to cellZone instead." << endl;
// Flag use of outsideFaces
faceZoneID_ = -2;
} }
patchLabels_.setSize(patchNames_.size()); patchLabels_.setSize(patchNames_.size());
forAll(patchNames_, i) forAll(patchNames_, i)
{ {
patchLabels_[i] = mesh_.boundaryMesh().findPatchID(patchNames_[i]); patchLabels_[i] = patches.findPatchID(patchNames_[i]);
if (patchLabels_[i] == -1) if (patchLabels_[i] == -1)
{ {
@ -125,7 +185,13 @@ void Foam::MRFZone::relativeFlux(surfaceScalarField& phi) const
const vector& origin = origin_.value(); const vector& origin = origin_.value();
const vector& Omega = Omega_.value(); const vector& Omega = Omega_.value();
const labelList& faces = mesh_.faceZones()[faceZoneID_]; // Use either zone faces or outsideFaces_
const labelList& faces =
(
faceZoneID_ == -2
? outsideFaces_
: mesh_.faceZones()[faceZoneID_]
);
forAll(faces, i) forAll(faces, i)
{ {

View File

@ -26,7 +26,7 @@ Class
Foam::MRFZone Foam::MRFZone
Description Description
MRF zone definition based on both cell and face zones and parameters MRF zone definition based on cell zone and optional face zone and parameters
obtained from a control dictionary constructed from the given stream. obtained from a control dictionary constructed from the given stream.
The rotation of the MRF region is defined by an origin and axis of The rotation of the MRF region is defined by an origin and axis of
@ -68,18 +68,26 @@ class MRFZone
const fvMesh& mesh_; const fvMesh& mesh_;
word name_; const word name_;
dictionary dict_; const dictionary dict_;
label cellZoneID_; label cellZoneID_;
//- label of face zone with faces on outside of cell zone.
// If -2 determines outside faces itself
label faceZoneID_; label faceZoneID_;
wordList patchNames_;
//- outside faces (only if faceZoneID = -2)
labelList outsideFaces_;
const wordList patchNames_;
labelList patchLabels_; labelList patchLabels_;
dimensionedVector origin_; const dimensionedVector origin_;
dimensionedVector axis_; dimensionedVector axis_;
dimensionedScalar omega_; const dimensionedScalar omega_;
dimensionedVector Omega_; dimensionedVector Omega_;

View File

@ -140,11 +140,11 @@ void Foam::quadraticFitSnGradData::findFaceDirs
#ifndef SPHERICAL_GEOMETRY #ifndef SPHERICAL_GEOMETRY
if (mesh.nGeometricD() <= 2) // find the normal direcion if (mesh.nGeometricD() <= 2) // find the normal direcion
{ {
if (mesh.directions()[0] == -1) if (mesh.geometricD()[0] == -1)
{ {
kdir = vector(1, 0, 0); kdir = vector(1, 0, 0);
} }
else if (mesh.directions()[1] == -1) else if (mesh.geometricD()[1] == -1)
{ {
kdir = vector(0, 1, 0); kdir = vector(0, 1, 0);
} }
@ -153,7 +153,7 @@ void Foam::quadraticFitSnGradData::findFaceDirs
kdir = vector(0, 0, 1); kdir = vector(0, 0, 1);
} }
} }
else // 3D so find a direction in the place of the face else // 3D so find a direction in the plane of the face
{ {
const face& f = mesh.faces()[faci]; const face& f = mesh.faces()[faci];
kdir = mesh.points()[f[0]] - mesh.points()[f[1]]; kdir = mesh.points()[f[0]] - mesh.points()[f[1]];

View File

@ -713,7 +713,7 @@ Foam::fvMatrix<Type>::H() const
( (
pow pow
( (
psi_.mesh().directions(), psi_.mesh().solutionD(),
pTraits<typename powProduct<Vector<label>, Type::rank>::type>::zero pTraits<typename powProduct<Vector<label>, Type::rank>::type>::zero
) )
); );

View File

@ -82,7 +82,7 @@ Foam::lduMatrix::solverPerformance Foam::fvMatrix<Type>::solve
( (
pow pow
( (
psi_.mesh().directions(), psi_.mesh().solutionD(),
pTraits<typename powProduct<Vector<label>, Type::rank>::type>::zero pTraits<typename powProduct<Vector<label>, Type::rank>::type>::zero
) )
); );

View File

@ -83,11 +83,11 @@ void Foam::FitData<FitDataType, ExtendedStencil, Polynomial>::findFaceDirs
# ifndef SPHERICAL_GEOMETRY # ifndef SPHERICAL_GEOMETRY
if (mesh.nGeometricD() <= 2) // find the normal direction if (mesh.nGeometricD() <= 2) // find the normal direction
{ {
if (mesh.directions()[0] == -1) if (mesh.geometricD()[0] == -1)
{ {
kdir = vector(1, 0, 0); kdir = vector(1, 0, 0);
} }
else if (mesh.directions()[1] == -1) else if (mesh.geometricD()[1] == -1)
{ {
kdir = vector(0, 1, 0); kdir = vector(0, 1, 0);
} }
@ -115,7 +115,7 @@ void Foam::FitData<FitDataType, ExtendedStencil, Polynomial>::findFaceDirs
if (magk < SMALL) if (magk < SMALL)
{ {
FatalErrorIn("findFaceDirs") << " calculated kdir = zero" FatalErrorIn("findFaceDirs(..)") << " calculated kdir = zero"
<< exit(FatalError); << exit(FatalError);
} }
else else

View File

@ -60,6 +60,7 @@ $(searchableSurface)/searchablePlane.C
$(searchableSurface)/searchablePlate.C $(searchableSurface)/searchablePlate.C
$(searchableSurface)/searchableSphere.C $(searchableSurface)/searchableSphere.C
$(searchableSurface)/searchableSurface.C $(searchableSurface)/searchableSurface.C
$(searchableSurface)/searchableSurfaceCollection.C
$(searchableSurface)/searchableSurfaces.C $(searchableSurface)/searchableSurfaces.C
$(searchableSurface)/searchableSurfacesQueries.C $(searchableSurface)/searchableSurfacesQueries.C
$(searchableSurface)/searchableSurfaceWithGaps.C $(searchableSurface)/searchableSurfaceWithGaps.C

View File

@ -51,6 +51,12 @@ namespace Foam
// Forward declaration of classes // Forward declaration of classes
class polyPatch; class polyPatch;
class polyMesh; class polyMesh;
class wallPoint;
// Forward declaration of friend functions and operators
Ostream& operator<<(Ostream&, const wallPoint&);
Istream& operator>>(Istream&, wallPoint&);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class wallPoint Declaration Class wallPoint Declaration
@ -78,12 +84,15 @@ class wallPoint
const scalar tol const scalar tol
); );
public: public:
// Static data members // Static data members
//- initial point far away. //- initial point far away.
static point greatPoint; static point greatPoint;
// Constructors // Constructors
//- Construct null //- Construct null
@ -102,6 +111,7 @@ public:
const wallPoint& const wallPoint&
); );
// Member Functions // Member Functions
// Access // Access
@ -184,11 +194,11 @@ public:
const scalar tol const scalar tol
); );
// Member Operators // Member Operators
// Needed for List IO // Needed for List IO
inline bool operator==(const wallPoint&) const; inline bool operator==(const wallPoint&) const;
inline bool operator!=(const wallPoint&) const; inline bool operator!=(const wallPoint&) const;

View File

@ -25,7 +25,7 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "meshTools.H" #include "meshTools.H"
#include "primitiveMesh.H" #include "polyMesh.H"
#include "hexMatcher.H" #include "hexMatcher.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -635,6 +635,103 @@ Foam::label Foam::meshTools::walkFace
} }
void Foam::meshTools::constrainToMeshCentre(const polyMesh& mesh, point& pt)
{
const Vector<label>& dirs = mesh.geometricD();
const point& min = mesh.bounds().min();
const point& max = mesh.bounds().max();
for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
{
if (dirs[cmpt] == -1)
{
pt[cmpt] = 0.5*(min[cmpt]+max[cmpt]);
}
}
}
void Foam::meshTools::constrainToMeshCentre
(
const polyMesh& mesh,
pointField& pts
)
{
const Vector<label>& dirs = mesh.geometricD();
const point& min = mesh.bounds().min();
const point& max = mesh.bounds().max();
bool isConstrained = false;
for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
{
if (dirs[cmpt] == -1)
{
isConstrained = true;
break;
}
}
if (isConstrained)
{
forAll(pts, i)
{
for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
{
if (dirs[cmpt] == -1)
{
pts[i][cmpt] = 0.5*(min[cmpt]+max[cmpt]);
}
}
}
}
}
//- Set the constrained components of directions/velocity to zero
void Foam::meshTools::constrainDirection(const polyMesh& mesh, vector& d)
{
const Vector<label>& dirs = mesh.geometricD();
for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
{
if (dirs[cmpt] == -1)
{
d[cmpt] = 0.0;
}
}
}
void Foam::meshTools::constrainDirection(const polyMesh& mesh, vectorField& d)
{
const Vector<label>& dirs = mesh.geometricD();
bool isConstrained = false;
for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
{
if (dirs[cmpt] == -1)
{
isConstrained = true;
break;
}
}
if (isConstrained)
{
forAll(d, i)
{
for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
{
if (dirs[cmpt] == -1)
{
d[i][cmpt] = 0.0;
}
}
}
}
}
void Foam::meshTools::getParallelEdges void Foam::meshTools::getParallelEdges
( (
const primitiveMesh& mesh, const primitiveMesh& mesh,

View File

@ -50,7 +50,7 @@ namespace Foam
{ {
class primitiveMesh; class primitiveMesh;
class polyMesh;
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Namespace meshTools Declaration Namespace meshTools Declaration
@ -81,196 +81,212 @@ namespace meshTools
static const label pXpYpZMask = 1 << pXpYpZ; static const label pXpYpZMask = 1 << pXpYpZ;
//- Check if n is in same direction as normals of all faceLabels // Normal handling
bool visNormal
(
const vector& n,
const vectorField& faceNormals,
const labelList& faceLabels
);
//- Calculate point normals on a 'box' mesh (all edges aligned with //- Check if n is in same direction as normals of all faceLabels
// coordinate axes) bool visNormal
vectorField calcBoxPointNormals(const primitivePatch& pp); (
const vector& n,
const vectorField& faceNormals,
const labelList& faceLabels
);
//- Normalized edge vector //- Calculate point normals on a 'box' mesh (all edges aligned with
vector normEdgeVec(const primitiveMesh&, const label edgeI); // coordinate axes)
vectorField calcBoxPointNormals(const primitivePatch& pp);
//- Write obj representation of point //- Normalized edge vector
void writeOBJ vector normEdgeVec(const primitiveMesh&, const label edgeI);
(
Ostream& os,
const point& pt
);
//- Write obj representation of faces subset // OBJ writing
void writeOBJ
(
Ostream& os,
const faceList&,
const pointField&,
const labelList& faceLabels
);
//- Write obj representation of faces //- Write obj representation of point
void writeOBJ void writeOBJ
( (
Ostream& os, Ostream& os,
const faceList&, const point& pt
const pointField& );
);
//- Write obj representation of cell subset //- Write obj representation of faces subset
void writeOBJ void writeOBJ
( (
Ostream& os, Ostream& os,
const cellList&, const faceList&,
const faceList&, const pointField&,
const pointField&, const labelList& faceLabels
const labelList& cellLabels );
);
//- Is edge used by cell //- Write obj representation of faces
bool edgeOnCell void writeOBJ
( (
const primitiveMesh&, Ostream& os,
const label cellI, const faceList&,
const label edgeI const pointField&
); );
//- Is edge used by face //- Write obj representation of cell subset
bool edgeOnFace void writeOBJ
( (
const primitiveMesh&, Ostream& os,
const label faceI, const cellList&,
const label edgeI const faceList&,
); const pointField&,
const labelList& cellLabels
//- Is face used by cell );
bool faceOnCell
(
const primitiveMesh&,
const label cellI,
const label faceI
);
//- Return edge among candidates that uses the two vertices.
label findEdge
(
const edgeList& edges,
const labelList& candidates,
const label v0,
const label v1
);
//- Return edge between two vertices. Returns -1 if no edge. // Cell/face/edge walking
label findEdge
(
const primitiveMesh&,
const label v0,
const label v1
);
//- Return edge shared by two faces. Throws error if no edge found. //- Is edge used by cell
label getSharedEdge bool edgeOnCell
( (
const primitiveMesh&, const primitiveMesh&,
const label f0, const label cellI,
const label f1 const label edgeI
); );
//- Return face shared by two cells. Throws error if none found.
label getSharedFace
(
const primitiveMesh&,
const label cell0,
const label cell1
);
//- Get faces on cell using edgeI. Throws error if no two found. //- Is edge used by face
void getEdgeFaces bool edgeOnFace
( (
const primitiveMesh&, const primitiveMesh&,
const label cellI, const label faceI,
const label edgeI, const label edgeI
label& face0, );
label& face1
);
//- Return label of other edge (out of candidates edgeLabels) //- Is face used by cell
// connected to vertex but not edgeI. Throws error if none found. bool faceOnCell
label otherEdge (
( const primitiveMesh&,
const primitiveMesh&, const label cellI,
const labelList& edgeLabels, const label faceI
const label edgeI, );
const label vertI
);
//- Return face on cell using edgeI but not faceI. Throws error
// if none found.
label otherFace
(
const primitiveMesh&,
const label cellI,
const label faceI,
const label edgeI
);
//- Return cell on other side of face. Throws error //- Return edge among candidates that uses the two vertices.
// if face not internal. label findEdge
label otherCell (
( const edgeList& edges,
const primitiveMesh&, const labelList& candidates,
const label cellI, const label v0,
const label faceI const label v1
); );
//- Returns label of edge nEdges away from startEdge (in the direction //- Return edge between two vertices. Returns -1 if no edge.
// of startVertI) label findEdge
label walkFace (
( const primitiveMesh&,
const primitiveMesh&, const label v0,
const label faceI, const label v1
const label startEdgeI, );
const label startVertI,
const label nEdges //- Return edge shared by two faces. Throws error if no edge found.
); label getSharedEdge
(
const primitiveMesh&,
const label f0,
const label f1
);
//- Return face shared by two cells. Throws error if none found.
label getSharedFace
(
const primitiveMesh&,
const label cell0,
const label cell1
);
//- Get faces on cell using edgeI. Throws error if no two found.
void getEdgeFaces
(
const primitiveMesh&,
const label cellI,
const label edgeI,
label& face0,
label& face1
);
//- Return label of other edge (out of candidates edgeLabels)
// connected to vertex but not edgeI. Throws error if none found.
label otherEdge
(
const primitiveMesh&,
const labelList& edgeLabels,
const label edgeI,
const label vertI
);
//- Return face on cell using edgeI but not faceI. Throws error
// if none found.
label otherFace
(
const primitiveMesh&,
const label cellI,
const label faceI,
const label edgeI
);
//- Return cell on other side of face. Throws error
// if face not internal.
label otherCell
(
const primitiveMesh&,
const label cellI,
const label faceI
);
//- Returns label of edge nEdges away from startEdge (in the direction
// of startVertI)
label walkFace
(
const primitiveMesh&,
const label faceI,
const label startEdgeI,
const label startVertI,
const label nEdges
);
// Constraints on position
//- Set the constrained components of position to mesh centre
void constrainToMeshCentre(const polyMesh&, point&);
void constrainToMeshCentre(const polyMesh&, pointField&);
//- Set the constrained components of directions/velocity to zero
void constrainDirection(const polyMesh&, vector&);
void constrainDirection(const polyMesh&, vectorField&);
//
// Hex only functionality. // Hex only functionality.
//
//- Given edge on hex find other 'parallel', non-connected edges. //- Given edge on hex find other 'parallel', non-connected edges.
void getParallelEdges void getParallelEdges
( (
const primitiveMesh&, const primitiveMesh&,
const label cellI, const label cellI,
const label e0, const label e0,
label&, label&,
label&, label&,
label& label&
); );
//- Given edge on hex find all 'parallel' (i.e. non-connected) //- Given edge on hex find all 'parallel' (i.e. non-connected)
// edges and average direction of them // edges and average direction of them
vector edgeToCutDir vector edgeToCutDir
( (
const primitiveMesh&, const primitiveMesh&,
const label cellI, const label cellI,
const label edgeI const label edgeI
); );
//- Reverse of edgeToCutDir: given direction find edge bundle and //- Reverse of edgeToCutDir: given direction find edge bundle and
// return one of them. // return one of them.
label cutDirToEdge label cutDirToEdge
( (
const primitiveMesh&, const primitiveMesh&,
const label cellI, const label cellI,
const vector& cutDir const vector& cutDir
); );
} // End namespace meshTools } // End namespace meshTools

View File

@ -76,10 +76,8 @@ bool Foam::distributedTriSurfaceMesh::read()
// Distribution type // Distribution type
distType_ = distributionTypeNames_.read(dict_.lookup("distributionType")); distType_ = distributionTypeNames_.read(dict_.lookup("distributionType"));
if (dict_.found("mergeDistance")) // Merge distance
{ mergeDist_ = readScalar(dict_.lookup("mergeDistance"));
dict_.lookup("mergeDistance") >> mergeDist_;
}
return true; return true;
} }
@ -1341,25 +1339,44 @@ Foam::distributedTriSurfaceMesh::distributedTriSurfaceMesh
dict_(io, dict) dict_(io, dict)
{ {
read(); read();
if (debug)
{
Info<< "Constructed from triSurface:" << endl;
writeStats(Info);
labelList nTris(Pstream::nProcs());
nTris[Pstream::myProcNo()] = triSurface::size();
Pstream::gatherList(nTris);
Pstream::scatterList(nTris);
Info<< endl<< "\tproc\ttris\tbb" << endl;
forAll(nTris, procI)
{
Info<< '\t' << procI << '\t' << nTris[procI]
<< '\t' << procBb_[procI] << endl;
}
Info<< endl;
}
} }
Foam::distributedTriSurfaceMesh::distributedTriSurfaceMesh(const IOobject& io) Foam::distributedTriSurfaceMesh::distributedTriSurfaceMesh(const IOobject& io)
: :
triSurfaceMesh(io), //triSurfaceMesh(io),
// triSurfaceMesh triSurfaceMesh
// ( (
// IOobject IOobject
// ( (
// io.name(), io.name(),
// io.db().time().findInstanceDir(io.local()), io.time().findInstance(io.local(), word::null),
// io.local(), io.local(),
// io.db(), io.db(),
// io.readOpt(), io.readOpt(),
// io.writeOpt(), io.writeOpt(),
// io.registerObject() io.registerObject()
// ) )
// ), ),
dict_ dict_
( (
IOobject IOobject
@ -1375,6 +1392,26 @@ Foam::distributedTriSurfaceMesh::distributedTriSurfaceMesh(const IOobject& io)
) )
{ {
read(); read();
if (debug)
{
Info<< "Read distributedTriSurface from " << io.objectPath()
<< ':' << endl;
writeStats(Info);
labelList nTris(Pstream::nProcs());
nTris[Pstream::myProcNo()] = triSurface::size();
Pstream::gatherList(nTris);
Pstream::scatterList(nTris);
Info<< endl<< "\tproc\ttris\tbb" << endl;
forAll(nTris, procI)
{
Info<< '\t' << procI << '\t' << nTris[procI]
<< '\t' << procBb_[procI] << endl;
}
Info<< endl;
}
} }
@ -1384,21 +1421,21 @@ Foam::distributedTriSurfaceMesh::distributedTriSurfaceMesh
const dictionary& dict const dictionary& dict
) )
: :
triSurfaceMesh(io, dict), //triSurfaceMesh(io, dict),
// triSurfaceMesh triSurfaceMesh
// ( (
// IOobject IOobject
// ( (
// io.name(), io.name(),
// io.db().time().findInstanceDir(io.local()), io.time().findInstance(io.local(), word::null),
// io.local(), io.local(),
// io.db(), io.db(),
// io.readOpt(), io.readOpt(),
// io.writeOpt(), io.writeOpt(),
// io.registerObject() io.registerObject()
// ), ),
// dict dict
// ), ),
dict_ dict_
( (
IOobject IOobject
@ -1414,6 +1451,26 @@ Foam::distributedTriSurfaceMesh::distributedTriSurfaceMesh
) )
{ {
read(); read();
if (debug)
{
Info<< "Read distributedTriSurface from " << io.objectPath()
<< " and dictionary:" << endl;
writeStats(Info);
labelList nTris(Pstream::nProcs());
nTris[Pstream::myProcNo()] = triSurface::size();
Pstream::gatherList(nTris);
Pstream::scatterList(nTris);
Info<< endl<< "\tproc\ttris\tbb" << endl;
forAll(nTris, procI)
{
Info<< '\t' << procI << '\t' << nTris[procI]
<< '\t' << procBb_[procI] << endl;
}
Info<< endl;
}
} }
@ -2416,6 +2473,8 @@ void Foam::distributedTriSurfaceMesh::writeStats(Ostream& os) const
boundBox bb; boundBox bb;
label nPoints; label nPoints;
calcBounds(bb, nPoints); calcBounds(bb, nPoints);
reduce(bb.min(), minOp<point>());
reduce(bb.max(), maxOp<point>());
os << "Triangles : " << returnReduce(triSurface::size(), sumOp<label>()) os << "Triangles : " << returnReduce(triSurface::size(), sumOp<label>())
<< endl << endl

View File

@ -91,15 +91,14 @@ public:
private: private:
// Private member data
//- Merging distance //- Merging distance
scalar mergeDist_; scalar mergeDist_;
//- Decomposition used when independently decomposing surface. //- Decomposition used when independently decomposing surface.
autoPtr<decompositionMethod> decomposer_; autoPtr<decompositionMethod> decomposer_;
// Private member data
//- Bounding box settings //- Bounding box settings
IOdictionary dict_; IOdictionary dict_;
@ -317,10 +316,11 @@ public:
const dictionary& dict const dictionary& dict
); );
//- Construct read //- Construct read. Does findInstance to find io.local().
distributedTriSurfaceMesh(const IOobject& io); distributedTriSurfaceMesh(const IOobject& io);
//- Construct from dictionary (used by searchableSurface) //- Construct from dictionary (used by searchableSurface).
// Does read. Does findInstance to find io.local().
distributedTriSurfaceMesh distributedTriSurfaceMesh
( (
const IOobject& io, const IOobject& io,

View File

@ -53,7 +53,14 @@ Foam::pointIndexHit Foam::searchableSphere::findNearest
if (nearestDistSqr > sqr(magN-radius_)) if (nearestDistSqr > sqr(magN-radius_))
{ {
info.rawPoint() = centre_ + n/magN*radius_; if (magN < ROOTVSMALL)
{
info.rawPoint() = centre_ + vector(1,0,0)/magN*radius_;
}
else
{
info.rawPoint() = centre_ + n/magN*radius_;
}
info.setHit(); info.setHit();
info.setIndex(0); info.setIndex(0);
} }

View File

@ -0,0 +1,525 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "searchableSurfaceCollection.H"
#include "addToRunTimeSelectionTable.H"
#include "SortableList.H"
#include "Time.H"
#include "ListOps.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(searchableSurfaceCollection, 0);
addToRunTimeSelectionTable(searchableSurface, searchableSurfaceCollection, dict);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::searchableSurfaceCollection::findNearest
(
const pointField& samples,
scalarField& minDistSqr,
List<pointIndexHit>& nearestInfo,
labelList& nearestSurf
) const
{
// Initialise
nearestInfo.setSize(samples.size());
nearestInfo = pointIndexHit();
nearestSurf.setSize(samples.size());
nearestSurf = -1;
List<pointIndexHit> hitInfo(samples.size());
const scalarField localMinDistSqr(samples.size(), GREAT);
forAll(subGeom_, surfI)
{
// Transform then divide
tmp<pointField> localSamples = cmptDivide
(
transform_[surfI].localPosition(samples),
scale_[surfI]
);
subGeom_[surfI].findNearest(localSamples, localMinDistSqr, hitInfo);
forAll(hitInfo, pointI)
{
if (hitInfo[pointI].hit())
{
// Rework back into global coordinate sys. Multiply then
// transform
point globalPt = transform_[surfI].globalPosition
(
cmptMultiply
(
hitInfo[pointI].rawPoint(),
scale_[surfI]
)
);
scalar distSqr = magSqr(globalPt - samples[pointI]);
if (distSqr < minDistSqr[pointI])
{
minDistSqr[pointI] = distSqr;
nearestInfo[pointI].setPoint(globalPt);
nearestInfo[pointI].setHit();
nearestInfo[pointI].setIndex(hitInfo[pointI].index());
nearestSurf[pointI] = surfI;
}
}
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::searchableSurfaceCollection::searchableSurfaceCollection
(
const IOobject& io,
const dictionary& dict
)
:
searchableSurface(io),
instance_(dict.size()),
scale_(dict.size()),
transform_(dict.size()),
subGeom_(dict.size())
{
Info<< "SearchableCollection : " << name() << endl;
label surfI = 0;
forAllConstIter(dictionary, dict, iter)
{
if (dict.isDict(iter().keyword()))
{
instance_[surfI] = iter().keyword();
const dictionary& subDict = dict.subDict(instance_[surfI]);
scale_[surfI] = subDict.lookup("scale");
transform_.set
(
surfI,
coordinateSystem::New
(
"",
subDict.subDict("transform")
)
);
const word subGeomName(subDict.lookup("surface"));
//Pout<< "Trying to find " << subGeomName << endl;
const searchableSurface& s =
io.db().lookupObject<searchableSurface>(subGeomName);
subGeom_.set(surfI, &const_cast<searchableSurface&>(s));
Info<< " instance : " << instance_[surfI] << endl;
Info<< " surface : " << s.name() << endl;
Info<< " scale : " << scale_[surfI] << endl;
Info<< " coordsys : " << transform_[surfI] << endl;
surfI++;
}
}
instance_.setSize(surfI);
scale_.setSize(surfI);
transform_.setSize(surfI);
subGeom_.setSize(surfI);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::searchableSurfaceCollection::~searchableSurfaceCollection()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::wordList& Foam::searchableSurfaceCollection::regions() const
{
if (regions_.size() == 0)
{
regionOffset_.setSize(subGeom_.size());
DynamicList<word> allRegions;
forAll(subGeom_, surfI)
{
regionOffset_[surfI] = allRegions.size();
const wordList& subRegions = subGeom_[surfI].regions();
forAll(subRegions, i)
{
//allRegions.append(subRegions[i] + "_" + Foam::name(surfI));
allRegions.append(instance_[surfI] + "_" + subRegions[i]);
}
}
regions_.transfer(allRegions.shrink());
}
return regions_;
}
Foam::label Foam::searchableSurfaceCollection::size() const
{
label n = 0;
forAll(subGeom_, surfI)
{
n += subGeom_[surfI].size();
}
return n;
}
void Foam::searchableSurfaceCollection::findNearest
(
const pointField& samples,
const scalarField& nearestDistSqr,
List<pointIndexHit>& nearestInfo
) const
{
// How to scale distance?
scalarField minDistSqr(nearestDistSqr);
labelList nearestSurf;
findNearest
(
samples,
minDistSqr,
nearestInfo,
nearestSurf
);
}
void Foam::searchableSurfaceCollection::findLine
(
const pointField& start,
const pointField& end,
List<pointIndexHit>& info
) const
{
info.setSize(start.size());
info = pointIndexHit();
// Current nearest (to start) intersection
pointField nearest(end);
List<pointIndexHit> hitInfo(start.size());
forAll(subGeom_, surfI)
{
// Starting point
tmp<pointField> e0 = cmptDivide
(
transform_[surfI].localPosition
(
start
),
scale_[surfI]
);
// Current best end point
tmp<pointField> e1 = cmptDivide
(
transform_[surfI].localPosition
(
nearest
),
scale_[surfI]
);
subGeom_[surfI].findLine(e0, e1, hitInfo);
forAll(hitInfo, pointI)
{
if (hitInfo[pointI].hit())
{
// Transform back to global coordinate sys.
nearest[pointI] = transform_[surfI].globalPosition
(
cmptMultiply
(
hitInfo[pointI].rawPoint(),
scale_[surfI]
)
);
info[pointI] = hitInfo[pointI];
info[pointI].rawPoint() = nearest[pointI];
}
}
}
// Debug check
if (false)
{
forAll(info, pointI)
{
if (info[pointI].hit())
{
vector n(end[pointI] - start[pointI]);
scalar magN = mag(n);
if (magN > SMALL)
{
n /= mag(n);
scalar s = ((info[pointI].rawPoint()-start[pointI])&n);
if (s < 0 || s > 1)
{
FatalErrorIn
(
"searchableSurfaceCollection::findLine(..)"
) << "point:" << info[pointI]
<< " s:" << s
<< " outside vector "
<< " start:" << start[pointI]
<< " end:" << end[pointI]
<< abort(FatalError);
}
}
}
}
}
}
void Foam::searchableSurfaceCollection::findLineAny
(
const pointField& start,
const pointField& end,
List<pointIndexHit>& info
) const
{
// To be done ...
findLine(start, end, info);
}
void Foam::searchableSurfaceCollection::findLineAll
(
const pointField& start,
const pointField& end,
List<List<pointIndexHit> >& info
) const
{
// To be done. Assume for now only one intersection.
List<pointIndexHit> nearestInfo;
findLine(start, end, nearestInfo);
info.setSize(start.size());
forAll(info, pointI)
{
if (nearestInfo[pointI].hit())
{
info[pointI].setSize(1);
info[pointI][0] = nearestInfo[pointI];
}
else
{
info[pointI].clear();
}
}
}
void Foam::searchableSurfaceCollection::getRegion
(
const List<pointIndexHit>& info,
labelList& region
) const
{
if (subGeom_.size() == 0)
{}
else if (subGeom_.size() == 1)
{
subGeom_[0].getRegion(info, region);
}
else
{
region.setSize(info.size());
region = -1;
// Which region did point come from. Retest for now to see which
// surface it originates from - crap solution! Should use global indices
// in index inside pointIndexHit to do this better.
pointField samples(info.size());
forAll(info, pointI)
{
if (info[pointI].hit())
{
samples[pointI] = info[pointI].hitPoint();
}
else
{
samples[pointI] = vector::zero;
}
}
//scalarField minDistSqr(info.size(), SMALL);
scalarField minDistSqr(info.size(), GREAT);
labelList nearestSurf;
List<pointIndexHit> nearestInfo;
findNearest
(
samples,
minDistSqr,
nearestInfo,
nearestSurf
);
// Check
{
forAll(info, pointI)
{
if (info[pointI].hit() && nearestSurf[pointI] == -1)
{
FatalErrorIn
(
"searchableSurfaceCollection::getRegion(..)"
) << "pointI:" << pointI
<< " sample:" << samples[pointI]
<< " nearest:" << nearestInfo[pointI]
<< " nearestsurf:" << nearestSurf[pointI]
<< abort(FatalError);
}
}
}
forAll(subGeom_, surfI)
{
// Collect points from my surface
labelList indices(findIndices(nearestSurf, surfI));
labelList surfRegion;
subGeom_[surfI].getRegion
(
IndirectList<pointIndexHit>(info, indices),
surfRegion
);
forAll(indices, i)
{
region[indices[i]] = regionOffset_[surfI] + surfRegion[i];
}
}
}
}
void Foam::searchableSurfaceCollection::getNormal
(
const List<pointIndexHit>& info,
vectorField& normal
) const
{
if (subGeom_.size() == 0)
{}
else if (subGeom_.size() == 1)
{
subGeom_[0].getNormal(info, normal);
}
else
{
normal.setSize(info.size());
// See above - crap retest to find surface point originates from.
pointField samples(info.size());
forAll(info, pointI)
{
if (info[pointI].hit())
{
samples[pointI] = info[pointI].hitPoint();
}
else
{
samples[pointI] = vector::zero;
}
}
//scalarField minDistSqr(info.size(), SMALL);
scalarField minDistSqr(info.size(), GREAT);
labelList nearestSurf;
List<pointIndexHit> nearestInfo;
findNearest
(
samples,
minDistSqr,
nearestInfo,
nearestSurf
);
forAll(subGeom_, surfI)
{
// Collect points from my surface
labelList indices(findIndices(nearestSurf, surfI));
vectorField surfNormal;
subGeom_[surfI].getNormal
(
IndirectList<pointIndexHit>(info, indices),
surfNormal
);
forAll(indices, i)
{
normal[indices[i]] = surfNormal[i];
}
}
}
}
void Foam::searchableSurfaceCollection::getVolumeType
(
const pointField& points,
List<volumeType>& volType
) const
{
FatalErrorIn
(
"searchableSurfaceCollection::getVolumeType(const pointField&"
", List<volumeType>&) const"
) << "Volume type not supported for collection."
<< exit(FatalError);
}
// ************************************************************************* //

View File

@ -0,0 +1,212 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::searchableSurfaceCollection
Description
Union of transformed searchableSurfaces
SourceFiles
searchableSurfaceCollection.C
\*---------------------------------------------------------------------------*/
#ifndef searchableSurfaceCollection_H
#define searchableSurfaceCollection_H
#include "searchableSurface.H"
#include "treeBoundBox.H"
#include "coordinateSystem.H"
#include "UPtrList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
/*---------------------------------------------------------------------------*\
Class searchableSurfaceCollection Declaration
\*---------------------------------------------------------------------------*/
class searchableSurfaceCollection
:
public searchableSurface
{
private:
// Private Member Data
// Per instance data
//- instance name
wordList instance_;
//- scaling vector
vectorField scale_;
//- transformation
PtrList<coordinateSystem> transform_;
UPtrList<searchableSurface> subGeom_;
//- Region names
mutable wordList regions_;
//- From individual regions to collection regions
mutable labelList regionOffset_;
// Private Member Functions
//- Find point nearest to sample. Updates minDistSqr. Sets nearestInfo
// and surface index
void findNearest
(
const pointField& samples,
scalarField& minDistSqr,
List<pointIndexHit>& nearestInfo,
labelList& nearestSurf
) const;
//- Disallow default bitwise copy construct
searchableSurfaceCollection(const searchableSurfaceCollection&);
//- Disallow default bitwise assignment
void operator=(const searchableSurfaceCollection&);
public:
//- Runtime type information
TypeName("searchableSurfaceCollection");
// Constructors
//- Construct from dictionary (used by searchableSurface)
searchableSurfaceCollection
(
const IOobject& io,
const dictionary& dict
);
// Destructor
virtual ~searchableSurfaceCollection();
// Member Functions
virtual const wordList& regions() const;
//- Whether supports volume type below
virtual bool hasVolumeType() const
{
return false;
}
//- Range of local indices that can be returned.
virtual label size() const;
// Multiple point queries.
virtual void findNearest
(
const pointField& sample,
const scalarField& nearestDistSqr,
List<pointIndexHit>&
) const;
virtual void findLine
(
const pointField& start,
const pointField& end,
List<pointIndexHit>&
) const;
virtual void findLineAny
(
const pointField& start,
const pointField& end,
List<pointIndexHit>&
) const;
//- Get all intersections in order from start to end.
virtual void findLineAll
(
const pointField& start,
const pointField& end,
List<List<pointIndexHit> >&
) const;
//- From a set of points and indices get the region
virtual void getRegion
(
const List<pointIndexHit>&,
labelList& region
) const;
//- From a set of points and indices get the normal
virtual void getNormal
(
const List<pointIndexHit>&,
vectorField& normal
) const;
//- Determine type (inside/outside/mixed) for point. unknown if
// cannot be determined (e.g. non-manifold surface)
virtual void getVolumeType
(
const pointField&,
List<volumeType>&
) const;
// regIOobject implementation
bool writeData(Ostream&) const
{
notImplemented
(
"searchableSurfaceCollection::writeData(Ostream&) const"
);
return false;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -39,8 +39,6 @@ defineTypeNameAndDebug(searchableSurfaces, 0);
} }
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct with length. // Construct with length.
@ -187,14 +185,6 @@ Foam::searchableSurfaces::searchableSurfaces
// their object name. Maybe have stlTriSurfaceMesh which appends .stl // their object name. Maybe have stlTriSurfaceMesh which appends .stl
// when reading/writing? // when reading/writing?
namedIO().rename(key); // names_[surfI] namedIO().rename(key); // names_[surfI]
if (namedIO().local() != word::null)
{
namedIO().instance() = namedIO().time().findInstance
(
namedIO().local(),
namedIO().name()
);
}
// Create and hook surface // Create and hook surface
set set

View File

@ -69,6 +69,8 @@ class searchableSurfaces
labelList allSurfaces_; labelList allSurfaces_;
// Private Member Functions
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct
searchableSurfaces(const searchableSurfaces&); searchableSurfaces(const searchableSurfaces&);

View File

@ -43,6 +43,64 @@ addToRunTimeSelectionTable(searchableSurface, triSurfaceMesh, dict);
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
//// Special version of Time::findInstance that does not check headerOk
//// to search for instances of raw files
//Foam::word Foam::triSurfaceMesh::findRawInstance
//(
// const Time& runTime,
// const fileName& dir,
// const word& name
//)
//{
// // Check current time first
// if (isFile(runTime.path()/runTime.timeName()/dir/name))
// {
// return runTime.timeName();
// }
// instantList ts = runTime.times();
// label instanceI;
//
// for (instanceI = ts.size()-1; instanceI >= 0; --instanceI)
// {
// if (ts[instanceI].value() <= runTime.timeOutputValue())
// {
// break;
// }
// }
//
// // continue searching from here
// for (; instanceI >= 0; --instanceI)
// {
// if (isFile(runTime.path()/ts[instanceI].name()/dir/name))
// {
// return ts[instanceI].name();
// }
// }
//
//
// // not in any of the time directories, try constant
//
// // Note. This needs to be a hard-coded constant, rather than the
// // constant function of the time, because the latter points to
// // the case constant directory in parallel cases
//
// if (isFile(runTime.path()/runTime.constant()/dir/name))
// {
// return runTime.constant();
// }
//
// FatalErrorIn
// (
// "searchableSurfaces::findRawInstance"
// "(const Time&, const fileName&, const word&)"
// ) << "Cannot find file \"" << name << "\" in directory "
// << runTime.constant()/dir
// << exit(FatalError);
//
// return runTime.constant();
//}
//- Check file existence //- Check file existence
const Foam::fileName& Foam::triSurfaceMesh::checkFile const Foam::fileName& Foam::triSurfaceMesh::checkFile
( (
@ -149,7 +207,19 @@ bool Foam::triSurfaceMesh::isSurfaceClosed() const
Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s) Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s)
: :
searchableSurface(io), searchableSurface(io),
objectRegistry(io), objectRegistry
(
IOobject
(
io.name(),
io.instance(),
io.local(),
io.db(),
io.readOpt(),
io.writeOpt(),
false // searchableSurface already registered under name
)
),
triSurface(s), triSurface(s),
surfaceClosed_(-1) surfaceClosed_(-1)
{} {}
@ -157,8 +227,34 @@ Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s)
Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io) Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io)
: :
// Find instance for triSurfaceMesh
searchableSurface(io), searchableSurface(io),
objectRegistry(io), //(
// IOobject
// (
// io.name(),
// io.time().findInstance(io.local(), word::null),
// io.local(),
// io.db(),
// io.readOpt(),
// io.writeOpt(),
// io.registerObject()
// )
//),
// Reused found instance in objectRegistry
objectRegistry
(
IOobject
(
io.name(),
static_cast<const searchableSurface&>(*this).instance(),
io.local(),
io.db(),
io.readOpt(),
io.writeOpt(),
false // searchableSurface already registered under name
)
),
triSurface triSurface
( (
checkFile checkFile
@ -178,7 +274,32 @@ Foam::triSurfaceMesh::triSurfaceMesh
) )
: :
searchableSurface(io), searchableSurface(io),
objectRegistry(io), //(
// IOobject
// (
// io.name(),
// io.time().findInstance(io.local(), word::null),
// io.local(),
// io.db(),
// io.readOpt(),
// io.writeOpt(),
// io.registerObject()
// )
//),
// Reused found instance in objectRegistry
objectRegistry
(
IOobject
(
io.name(),
static_cast<const searchableSurface&>(*this).instance(),
io.local(),
io.db(),
io.readOpt(),
io.writeOpt(),
false // searchableSurface already registered under name
)
),
triSurface triSurface
( (
checkFile checkFile

View File

@ -76,6 +76,14 @@ private:
// Private Member Functions // Private Member Functions
////- Helper: find instance of files without header
//static word findRawInstance
//(
// const Time&,
// const fileName&,
// const word&
//);
//- Check file existence //- Check file existence
static const fileName& checkFile static const fileName& checkFile
( (
@ -105,10 +113,10 @@ public:
//- Construct from triSurface //- Construct from triSurface
triSurfaceMesh(const IOobject&, const triSurface&); triSurfaceMesh(const IOobject&, const triSurface&);
//- Construct read //- Construct read.
triSurfaceMesh(const IOobject& io); triSurfaceMesh(const IOobject& io);
//- Construct from dictionary (used by searchableSurface) //- Construct from IO and dictionary (used by searchableSurface).
// Dictionary may contain a 'scale' entry (eg, 0.001: mm -> m) // Dictionary may contain a 'scale' entry (eg, 0.001: mm -> m)
triSurfaceMesh triSurfaceMesh
( (

View File

@ -30,6 +30,7 @@ License
#include "syncTools.H" #include "syncTools.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"
#include "slicedVolFields.H" #include "slicedVolFields.H"
#include "surfaceFields.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -84,9 +85,74 @@ bool Foam::isoSurface::isEdgeOfFaceCut
} }
// Get neighbour value and position.
void Foam::isoSurface::getNeighbour
(
const labelList& boundaryRegion,
const volScalarField& cVals,
const label cellI,
const label faceI,
scalar& nbrValue,
point& nbrPoint
) const
{
const labelList& own = mesh_.faceOwner();
const labelList& nei = mesh_.faceNeighbour();
const surfaceScalarField& weights = mesh_.weights();
if (mesh_.isInternalFace(faceI))
{
label nbr = (own[faceI] == cellI ? nei[faceI] : own[faceI]);
nbrValue = cVals[nbr];
nbrPoint = mesh_.cellCentres()[nbr];
}
else
{
label bFaceI = faceI-mesh_.nInternalFaces();
label patchI = boundaryRegion[bFaceI];
const polyPatch& pp = mesh_.boundaryMesh()[patchI];
label patchFaceI = faceI-pp.start();
if (isA<emptyPolyPatch>(pp))
{
// Assume zero gradient
nbrValue = cVals[own[faceI]];
nbrPoint = mesh_.faceCentres()[faceI];
}
else if (pp.coupled())
{
if (!refCast<const coupledPolyPatch>(pp).separated())
{
// Behave as internal face:
// other side value
nbrValue = cVals.boundaryField()[patchI][patchFaceI];
// other side cell centre
nbrPoint = mesh_.C().boundaryField()[patchI][patchFaceI];
}
else
{
// Do some interpolation for now
const scalarField& w = weights.boundaryField()[patchI];
nbrPoint = mesh_.faceCentres()[faceI];
nbrValue =
(1-w[patchFaceI])*cVals[own[faceI]]
+ w[patchFaceI]*cVals.boundaryField()[patchI][patchFaceI];
}
}
else
{
nbrValue = cVals.boundaryField()[patchI][patchFaceI];
nbrPoint = mesh_.faceCentres()[faceI];
}
}
}
// Determine for every face/cell whether it (possibly) generates triangles. // Determine for every face/cell whether it (possibly) generates triangles.
void Foam::isoSurface::calcCutTypes void Foam::isoSurface::calcCutTypes
( (
const labelList& boundaryRegion,
const volScalarField& cVals, const volScalarField& cVals,
const scalarField& pVals const scalarField& pVals
) )
@ -102,7 +168,20 @@ void Foam::isoSurface::calcCutTypes
{ {
// CC edge. // CC edge.
bool ownLower = (cVals[own[faceI]] < iso_); bool ownLower = (cVals[own[faceI]] < iso_);
bool neiLower = (cVals[nei[faceI]] < iso_);
scalar nbrValue;
point nbrPoint;
getNeighbour
(
boundaryRegion,
cVals,
own[faceI],
faceI,
nbrValue,
nbrPoint
);
bool neiLower = (nbrValue < iso_);
if (ownLower != neiLower) if (ownLower != neiLower)
{ {
@ -120,53 +199,47 @@ void Foam::isoSurface::calcCutTypes
} }
} }
} }
forAll(patches, patchI) forAll(patches, patchI)
{ {
const polyPatch& pp = patches[patchI]; const polyPatch& pp = patches[patchI];
label faceI = pp.start(); label faceI = pp.start();
if (isA<emptyPolyPatch>(pp)) forAll(pp, i)
{ {
// Assume zero gradient so owner and neighbour/boundary value equal bool ownLower = (cVals[own[faceI]] < iso_);
forAll(pp, i) scalar nbrValue;
point nbrPoint;
getNeighbour
(
boundaryRegion,
cVals,
own[faceI],
faceI,
nbrValue,
nbrPoint
);
bool neiLower = (nbrValue < iso_);
if (ownLower != neiLower)
{ {
bool ownLower = (cVals[own[faceI]] < iso_); faceCutType_[faceI] = CUT;
}
else
{
// Mesh edge.
const face f = mesh_.faces()[faceI]; const face f = mesh_.faces()[faceI];
if (isEdgeOfFaceCut(pVals, f, ownLower, ownLower)) if (isEdgeOfFaceCut(pVals, f, ownLower, neiLower))
{ {
faceCutType_[faceI] = CUT; faceCutType_[faceI] = CUT;
} }
faceI++;
} }
}
else
{
forAll(pp, i)
{
bool ownLower = (cVals[own[faceI]] < iso_);
bool neiLower = (cVals.boundaryField()[patchI][i] < iso_);
if (ownLower != neiLower) faceI++;
{
faceCutType_[faceI] = CUT;
}
else
{
// Mesh edge.
const face f = mesh_.faces()[faceI];
if (isEdgeOfFaceCut(pVals, f, ownLower, neiLower))
{
faceCutType_[faceI] = CUT;
}
}
faceI++;
}
} }
} }
@ -330,59 +403,6 @@ Foam::pointIndexHit Foam::isoSurface::collapseSurface
} }
// Get neighbour value and position.
void Foam::isoSurface::getNeighbour
(
const labelList& boundaryRegion,
const volScalarField& cVals,
const label cellI,
const label faceI,
scalar& nbrValue,
point& nbrPoint
) const
{
const labelList& own = mesh_.faceOwner();
const labelList& nei = mesh_.faceNeighbour();
if (mesh_.isInternalFace(faceI))
{
label nbr = (own[faceI] == cellI ? nei[faceI] : own[faceI]);
nbrValue = cVals[nbr];
nbrPoint = mesh_.cellCentres()[nbr];
}
else
{
label bFaceI = faceI-mesh_.nInternalFaces();
label patchI = boundaryRegion[bFaceI];
const polyPatch& pp = mesh_.boundaryMesh()[patchI];
label patchFaceI = faceI-pp.start();
if (isA<emptyPolyPatch>(pp))
{
// Assume zero gradient
nbrValue = cVals[own[faceI]];
nbrPoint = mesh_.faceCentres()[faceI];
}
else if
(
pp.coupled()
&& !refCast<const coupledPolyPatch>(pp).separated()
)
{
// other side value
nbrValue = cVals.boundaryField()[patchI][patchFaceI];
// other side cell centre
nbrPoint = mesh_.C().boundaryField()[patchI][patchFaceI];
}
else
{
nbrValue = cVals.boundaryField()[patchI][patchFaceI];
nbrPoint = mesh_.faceCentres()[faceI];
}
}
}
// Determine per cell centre whether all the intersections get collapsed // Determine per cell centre whether all the intersections get collapsed
// to a single point // to a single point
void Foam::isoSurface::calcSnappedCc void Foam::isoSurface::calcSnappedCc
@ -606,13 +626,14 @@ void Foam::isoSurface::calcSnappedPoint
forAll(pFaces, pFaceI) forAll(pFaces, pFaceI)
{ {
// Create points for all intersections close to point
// (i.e. from pyramid edges)
label faceI = pFaces[pFaceI]; label faceI = pFaces[pFaceI];
const face& f = mesh_.faces()[faceI]; const face& f = mesh_.faces()[faceI];
label own = mesh_.faceOwner()[faceI]; label own = mesh_.faceOwner()[faceI];
// Create points for all intersections close to point // Get neighbour value
// (i.e. from pyramid edges)
scalar nbrValue; scalar nbrValue;
point nbrPoint; point nbrPoint;
getNeighbour getNeighbour
@ -831,6 +852,7 @@ Foam::triSurface Foam::isoSurface::stitchTriPoints
} }
// Determine 'flat hole' situation (see RMT paper). // Determine 'flat hole' situation (see RMT paper).
// Two unconnected triangles get connected because (some of) the edges // Two unconnected triangles get connected because (some of) the edges
// separating them get collapsed. Below only checks for duplicate triangles, // separating them get collapsed. Below only checks for duplicate triangles,
@ -846,22 +868,29 @@ Foam::triSurface Foam::isoSurface::stitchTriPoints
forAll(tris, triI) forAll(tris, triI)
{ {
const labelledTri& tri = tris[triI]; const labelledTri& tri = tris[triI];
const labelList& pFaces = pointFaces[tri[0]]; const labelList& pFaces = pointFaces[tri[0]];
// Find the minimum of any duplicates // Find the maximum of any duplicates. Maximum since the tris
// below triI
// get overwritten so we cannot use them in a comparison.
label dupTriI = -1; label dupTriI = -1;
forAll(pFaces, i) forAll(pFaces, i)
{ {
if (pFaces[i] < triI && tris[pFaces[i]] == tri) label nbrTriI = pFaces[i];
if (nbrTriI > triI && (tris[nbrTriI] == tri))
{ {
dupTriI = pFaces[i]; //Pout<< "Duplicate : " << triI << " verts:" << tri
// << " to " << nbrTriI << " verts:" << tris[nbrTriI]
// << endl;
dupTriI = nbrTriI;
break;
} }
} }
if (dupTriI == -1) if (dupTriI == -1)
{ {
// There is no lower triangle // There is no (higher numbered) duplicate triangle
label newTriI = newToOldTri.size(); label newTriI = newToOldTri.size();
newToOldTri.append(triI); newToOldTri.append(triI);
tris[newTriI] = tris[triI]; tris[newTriI] = tris[triI];
@ -876,6 +905,43 @@ Foam::triSurface Foam::isoSurface::stitchTriPoints
Pout<< "isoSurface : merged from " << nTris Pout<< "isoSurface : merged from " << nTris
<< " down to " << tris.size() << " unique triangles." << endl; << " down to " << tris.size() << " unique triangles." << endl;
} }
if (debug)
{
triSurface surf(tris, geometricSurfacePatchList(0), newPoints);
forAll(surf, faceI)
{
const labelledTri& f = surf[faceI];
const labelList& fFaces = surf.faceFaces()[faceI];
forAll(fFaces, i)
{
label nbrFaceI = fFaces[i];
if (nbrFaceI <= faceI)
{
// lower numbered faces already checked
continue;
}
const labelledTri& nbrF = surf[nbrFaceI];
if (f == nbrF)
{
FatalErrorIn("validTri(const triSurface&, const label)")
<< "Check : "
<< " triangle " << faceI << " vertices " << f
<< " fc:" << f.centre(surf.points())
<< " has the same vertices as triangle " << nbrFaceI
<< " vertices " << nbrF
<< " fc:" << nbrF.centre(surf.points())
<< abort(FatalError);
}
}
}
}
} }
return triSurface(tris, geometricSurfacePatchList(0), newPoints, true); return triSurface(tris, geometricSurfacePatchList(0), newPoints, true);
@ -1473,45 +1539,23 @@ Foam::isoSurface::isoSurface
{ {
if (debug) if (debug)
{ {
Pout<< "isoSurface :" << nl Pout<< "isoSurface:" << nl
<< " isoField : " << cVals.name() << nl << " isoField : " << cVals.name() << nl
<< " isoValue : " << iso << nl << " cell min/max : "
<< " regularise : " << regularise << nl << min(cVals.internalField()) << " / "
<< " mergeTol : " << mergeTol << nl << max(cVals.internalField()) << nl
<< " point min/max : "
<< min(pVals) << " / "
<< max(pVals) << nl
<< " isoValue : " << iso << nl
<< " regularise : " << regularise << nl
<< " mergeTol : " << mergeTol << nl
<< endl; << endl;
} }
const polyBoundaryMesh& patches = mesh_.boundaryMesh(); const polyBoundaryMesh& patches = mesh_.boundaryMesh();
// Check // Pre-calculate patch-per-face to avoid whichPatch call.
forAll(patches, patchI)
{
if (isA<emptyPolyPatch>(patches[patchI]))
{
FatalErrorIn
(
"isoSurface::isoSurface\n"
"(\n"
" const volScalarField& cVals,\n"
" const scalarField& pVals,\n"
" const scalar iso,\n"
" const bool regularise,\n"
" const scalar mergeTol\n"
")\n"
) << "Iso surfaces not supported on case with empty patches."
<< exit(FatalError);
}
}
// Determine if any cut through face/cell
calcCutTypes(cVals, pVals);
// Determine if point is on boundary. Points on boundaries are never
// snapped. Coupled boundaries are handled explicitly so not marked here.
PackedBoolList isBoundaryPoint(mesh_.nPoints());
labelList boundaryRegion(mesh_.nFaces()-mesh_.nInternalFaces()); labelList boundaryRegion(mesh_.nFaces()-mesh_.nInternalFaces());
forAll(patches, patchI) forAll(patches, patchI)
@ -1525,33 +1569,13 @@ Foam::isoSurface::isoSurface
boundaryRegion[faceI-mesh_.nInternalFaces()] = patchI; boundaryRegion[faceI-mesh_.nInternalFaces()] = patchI;
faceI++; faceI++;
} }
// Mark all points that are not physically coupled (so anything
// but collocated coupled patches)
if
(
!pp.coupled()
|| refCast<const coupledPolyPatch>(pp).separated()
)
{
label faceI = pp.start();
forAll(pp, i)
{
boundaryRegion[faceI-mesh_.nInternalFaces()] = patchI;
const face& f = mesh_.faces()[faceI];
forAll(f, fp)
{
isBoundaryPoint.set(f[fp], 1);
}
faceI++;
}
}
} }
// Determine if any cut through face/cell
calcCutTypes(boundaryRegion, cVals, pVals);
DynamicList<point> snappedPoints(nCutCells_); DynamicList<point> snappedPoints(nCutCells_);
// Per cc -1 or a point inside snappedPoints. // Per cc -1 or a point inside snappedPoints.
@ -1584,6 +1608,39 @@ Foam::isoSurface::isoSurface
label nCellSnaps = snappedPoints.size(); label nCellSnaps = snappedPoints.size();
// Determine if point is on boundary. Points on boundaries are never
// snapped. Coupled boundaries are handled explicitly so not marked here.
PackedBoolList isBoundaryPoint(mesh_.nPoints());
forAll(patches, patchI)
{
// Mark all boundary points that are not physically coupled (so anything
// but collocated coupled patches)
const polyPatch& pp = patches[patchI];
if
(
!pp.coupled()
|| refCast<const coupledPolyPatch>(pp).separated()
)
{
label faceI = pp.start();
forAll(pp, i)
{
const face& f = mesh_.faces()[faceI];
forAll(f, fp)
{
isBoundaryPoint.set(f[fp], 1);
}
faceI++;
}
}
}
// Per point -1 or a point inside snappedPoints. // Per point -1 or a point inside snappedPoints.
labelList snappedPoint; labelList snappedPoint;
if (regularise) if (regularise)
@ -1613,7 +1670,7 @@ Foam::isoSurface::isoSurface
// Generate field to interpolate. This is identical to the mesh.C() // Generate field to interpolate. This is identical to the mesh.C()
// except on separated coupled patches. // except on separated coupled patches and on empty patches.
slicedVolVectorField meshC slicedVolVectorField meshC
( (
IOobject IOobject
@ -1635,10 +1692,12 @@ Foam::isoSurface::isoSurface
const polyBoundaryMesh& patches = mesh_.boundaryMesh(); const polyBoundaryMesh& patches = mesh_.boundaryMesh();
forAll(patches, patchI) forAll(patches, patchI)
{ {
const polyPatch& pp = patches[patchI];
if if
( (
patches[patchI].coupled() pp.coupled()
&& refCast<const coupledPolyPatch>(patches[patchI]).separated() && refCast<const coupledPolyPatch>(pp).separated()
) )
{ {
fvPatchVectorField& pfld = const_cast<fvPatchVectorField&> fvPatchVectorField& pfld = const_cast<fvPatchVectorField&>
@ -1647,9 +1706,32 @@ Foam::isoSurface::isoSurface
); );
pfld.operator== pfld.operator==
( (
patches[patchI].patchSlice(mesh_.faceCentres()) pp.patchSlice(mesh_.faceCentres())
); );
} }
else if (isA<emptyPolyPatch>(pp))
{
typedef slicedVolVectorField::GeometricBoundaryField bType;
bType& bfld = const_cast<bType&>(meshC.boundaryField());
// Clear old value. Cannot resize it since slice.
bfld.set(patchI, NULL);
// Set new value we can change
bfld.set
(
patchI,
new calculatedFvPatchField<vector>
(
mesh_.boundary()[patchI],
meshC
)
);
// Change to face centres
bfld[patchI] = pp.patchSlice(mesh_.faceCentres());
}
} }
} }
@ -1676,7 +1758,8 @@ Foam::isoSurface::isoSurface
if (debug) if (debug)
{ {
Pout<< "isoSurface : generated " << triMeshCells.size() Pout<< "isoSurface : generated " << triMeshCells.size()
<< " unmerged triangles." << endl; << " unmerged triangles from " << triPoints.size()
<< " unmerged points." << endl;
} }
@ -1773,6 +1856,14 @@ Foam::isoSurface::isoSurface
orientSurface(*this, faceEdges, edgeFace0, edgeFace1, edgeFacesRest); orientSurface(*this, faceEdges, edgeFace0, edgeFace1, edgeFacesRest);
//} //}
if (debug)
{
fileName stlFile = mesh_.time().path() + ".stl";
Pout<< "Dumping surface to " << stlFile << endl;
triSurface::write(stlFile);
}
} }

View File

@ -31,9 +31,6 @@ Description
G.M. Treece, R.W. Prager and A.H. Gee. G.M. Treece, R.W. Prager and A.H. Gee.
Note: Note:
- not possible on patches of type 'empty'. There are no values on
'empty' patch fields so even the api would have to change
(no volScalarField as argument). Too messy.
- in parallel the regularisation (coarsening) always takes place - in parallel the regularisation (coarsening) always takes place
and slightly different surfaces will be created compared to non-parallel. and slightly different surfaces will be created compared to non-parallel.
The surface will still be continuous though! The surface will still be continuous though!
@ -43,6 +40,7 @@ Description
- uses geometric merge with fraction of bounding box as distance. - uses geometric merge with fraction of bounding box as distance.
- triangles can be between two cell centres so constant sampling - triangles can be between two cell centres so constant sampling
does not make sense. does not make sense.
- on empty patches behaves like zero gradient.
- does not do 2D correctly, creates non-flat iso surface. - does not do 2D correctly, creates non-flat iso surface.
SourceFiles SourceFiles
@ -135,9 +133,20 @@ class isoSurface
const bool neiLower const bool neiLower
) const; ) const;
void getNeighbour
(
const labelList& boundaryRegion,
const volScalarField& cVals,
const label cellI,
const label faceI,
scalar& nbrValue,
point& nbrPoint
) const;
//- Set faceCutType,cellCutType. //- Set faceCutType,cellCutType.
void calcCutTypes void calcCutTypes
( (
const labelList& boundaryRegion,
const volScalarField& cVals, const volScalarField& cVals,
const scalarField& pVals const scalarField& pVals
); );
@ -156,16 +165,6 @@ class isoSurface
DynamicList<labelledTri, 64>& localTris DynamicList<labelledTri, 64>& localTris
); );
void getNeighbour
(
const labelList& boundaryRegion,
const volScalarField& cVals,
const label cellI,
const label faceI,
scalar& nbrValue,
point& nbrPoint
) const;
//- Determine per cc whether all near cuts can be snapped to single //- Determine per cc whether all near cuts can be snapped to single
// point. // point.
void calcSnappedCc void calcSnappedCc
@ -193,37 +192,39 @@ class isoSurface
template<class Type> template<class Type>
Type generatePoint Type generatePoint
( (
const DynamicList<Type>& snappedPoints,
const scalar s0, const scalar s0,
const Type& p0, const Type& p0,
const label p0Index, const bool hasSnap0,
const Type& snapP0,
const scalar s1, const scalar s1,
const Type& p1, const Type& p1,
const label p1Index const bool hasSnap1,
const Type& snapP1
) const; ) const;
template<class Type> template<class Type>
void generateTriPoints void generateTriPoints
( (
const DynamicList<Type>& snapped,
const scalar s0, const scalar s0,
const Type& p0, const Type& p0,
const label p0Index, const bool hasSnap0,
const Type& snapP0,
const scalar s1, const scalar s1,
const Type& p1, const Type& p1,
const label p1Index, const bool hasSnap1,
const Type& snapP1,
const scalar s2, const scalar s2,
const Type& p2, const Type& p2,
const label p2Index, const bool hasSnap2,
const Type& snapP2,
const scalar s3, const scalar s3,
const Type& p3, const Type& p3,
const label p3Index, const bool hasSnap3,
const Type& snapP3,
DynamicList<Type>& points DynamicList<Type>& points
) const; ) const;
@ -244,7 +245,8 @@ class isoSurface
const scalar neiVal, const scalar neiVal,
const Type& neiPt, const Type& neiPt,
const label neiSnap, const bool hasNeiSnap,
const Type& neiSnapPt,
DynamicList<Type>& triPoints, DynamicList<Type>& triPoints,
DynamicList<label>& triMeshCells DynamicList<label>& triMeshCells

View File

@ -33,15 +33,15 @@ License
template<class Type> template<class Type>
Type Foam::isoSurface::generatePoint Type Foam::isoSurface::generatePoint
( (
const DynamicList<Type>& snappedPoints,
const scalar s0, const scalar s0,
const Type& p0, const Type& p0,
const label p0Index, const bool hasSnap0,
const Type& snapP0,
const scalar s1, const scalar s1,
const Type& p1, const Type& p1,
const label p1Index const bool hasSnap1,
const Type& snapP1
) const ) const
{ {
scalar d = s1-s0; scalar d = s1-s0;
@ -50,13 +50,13 @@ Type Foam::isoSurface::generatePoint
{ {
scalar s = (iso_-s0)/d; scalar s = (iso_-s0)/d;
if (s >= 0.5 && s <= 1 && p1Index != -1) if (hasSnap1 && s >= 0.5 && s <= 1)
{ {
return snappedPoints[p1Index]; return snapP1;
} }
else if (s >= 0.0 && s <= 0.5 && p0Index != -1) else if (hasSnap0 && s >= 0.0 && s <= 0.5)
{ {
return snappedPoints[p0Index]; return snapP0;
} }
else else
{ {
@ -75,23 +75,25 @@ Type Foam::isoSurface::generatePoint
template<class Type> template<class Type>
void Foam::isoSurface::generateTriPoints void Foam::isoSurface::generateTriPoints
( (
const DynamicList<Type>& snapped,
const scalar s0, const scalar s0,
const Type& p0, const Type& p0,
const label p0Index, const bool hasSnap0,
const Type& snapP0,
const scalar s1, const scalar s1,
const Type& p1, const Type& p1,
const label p1Index, const bool hasSnap1,
const Type& snapP1,
const scalar s2, const scalar s2,
const Type& p2, const Type& p2,
const label p2Index, const bool hasSnap2,
const Type& snapP2,
const scalar s3, const scalar s3,
const Type& p3, const Type& p3,
const label p3Index, const bool hasSnap3,
const Type& snapP3,
DynamicList<Type>& points DynamicList<Type>& points
) const ) const
@ -123,29 +125,55 @@ void Foam::isoSurface::generateTriPoints
case 0x0E: case 0x0E:
case 0x01: case 0x01:
points.append(generatePoint(snapped,s0,p0,p0Index,s1,p1,p1Index)); points.append
points.append(generatePoint(snapped,s0,p0,p0Index,s2,p2,p2Index)); (
points.append(generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index)); generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1)
);
points.append
(
generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2)
);
points.append
(
generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3)
);
break; break;
case 0x0D: case 0x0D:
case 0x02: case 0x02:
points.append(generatePoint(snapped,s1,p1,p1Index,s0,p0,p0Index)); points.append
points.append(generatePoint(snapped,s1,p1,p1Index,s3,p3,p3Index)); (
points.append(generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index)); generatePoint(s1,p1,hasSnap1,snapP1,s0,p0,hasSnap0,snapP0)
);
points.append
(
generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3)
);
points.append
(
generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2)
);
break; break;
case 0x0C: case 0x0C:
case 0x03: case 0x03:
{ {
Type tp1 = generatePoint(snapped,s0,p0,p0Index,s2,p2,p2Index); Type tp1 =
Type tp2 = generatePoint(snapped,s1,p1,p1Index,s3,p3,p3Index); generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2);
Type tp2 =
generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3);
points.append(generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index)); points.append
(
generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3)
);
points.append(tp1); points.append(tp1);
points.append(tp2); points.append(tp2);
points.append(tp2); points.append(tp2);
points.append(generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index)); points.append
(
generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2)
);
points.append(tp1); points.append(tp1);
} }
break; break;
@ -153,23 +181,40 @@ void Foam::isoSurface::generateTriPoints
case 0x0B: case 0x0B:
case 0x04: case 0x04:
{ {
points.append(generatePoint(snapped,s2,p2,p2Index,s0,p0,p0Index)); points.append
points.append(generatePoint(snapped,s2,p2,p2Index,s1,p1,p1Index)); (
points.append(generatePoint(snapped,s2,p2,p2Index,s3,p3,p3Index)); generatePoint(s2,p2,hasSnap2,snapP2,s0,p0,hasSnap0,snapP0)
);
points.append
(
generatePoint(s2,p2,hasSnap2,snapP2,s1,p1,hasSnap1,snapP1)
);
points.append
(
generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3)
);
} }
break; break;
case 0x0A: case 0x0A:
case 0x05: case 0x05:
{ {
Type tp0 = generatePoint(snapped,s0,p0,p0Index,s1,p1,p1Index); Type tp0 =
Type tp1 = generatePoint(snapped,s2,p2,p2Index,s3,p3,p3Index); generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1);
Type tp1 =
generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3);
points.append(tp0); points.append(tp0);
points.append(tp1); points.append(tp1);
points.append(generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index)); points.append
(
generatePoint(s0,p0,hasSnap0,snapP0,s3,p3,hasSnap3,snapP3)
);
points.append(tp0); points.append(tp0);
points.append(generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index)); points.append
(
generatePoint(s1,p1,hasSnap1,snapP1,s2,p2,hasSnap2,snapP2)
);
points.append(tp1); points.append(tp1);
} }
break; break;
@ -177,23 +222,40 @@ void Foam::isoSurface::generateTriPoints
case 0x09: case 0x09:
case 0x06: case 0x06:
{ {
Type tp0 = generatePoint(snapped,s0,p0,p0Index,s1,p1,p1Index); Type tp0 =
Type tp1 = generatePoint(snapped,s2,p2,p2Index,s3,p3,p3Index); generatePoint(s0,p0,hasSnap0,snapP0,s1,p1,hasSnap1,snapP1);
Type tp1 =
generatePoint(s2,p2,hasSnap2,snapP2,s3,p3,hasSnap3,snapP3);
points.append(tp0); points.append(tp0);
points.append(generatePoint(snapped,s1,p1,p1Index,s3,p3,p3Index)); points.append
(
generatePoint(s1,p1,hasSnap1,snapP1,s3,p3,hasSnap3,snapP3)
);
points.append(tp1); points.append(tp1);
points.append(tp0); points.append(tp0);
points.append(generatePoint(snapped,s0,p0,p0Index,s2,p2,p2Index)); points.append
(
generatePoint(s0,p0,hasSnap0,snapP0,s2,p2,hasSnap2,snapP2)
);
points.append(tp1); points.append(tp1);
} }
break; break;
case 0x07: case 0x07:
case 0x08: case 0x08:
points.append(generatePoint(snapped,s3,p3,p3Index,s0,p0,p0Index)); points.append
points.append(generatePoint(snapped,s3,p3,p3Index,s2,p2,p2Index)); (
points.append(generatePoint(snapped,s3,p3,p3Index,s1,p1,p1Index)); generatePoint(s3,p3,hasSnap3,snapP3,s0,p0,hasSnap0,snapP0)
);
points.append
(
generatePoint(s3,p3,hasSnap3,snapP3,s2,p2,hasSnap2,snapP2)
);
points.append
(
generatePoint(s3,p3,hasSnap3,snapP3,s1,p1,hasSnap1,snapP1)
);
break; break;
} }
} }
@ -215,7 +277,8 @@ Foam::label Foam::isoSurface::generateFaceTriPoints
const scalar neiVal, const scalar neiVal,
const Type& neiPt, const Type& neiPt,
const label neiSnap, const bool hasNeiSnap,
const Type& neiSnapPt,
DynamicList<Type>& triPoints, DynamicList<Type>& triPoints,
DynamicList<label>& triMeshCells DynamicList<label>& triMeshCells
@ -234,23 +297,37 @@ Foam::label Foam::isoSurface::generateFaceTriPoints
generateTriPoints generateTriPoints
( (
snappedPoints,
pVals[pointI], pVals[pointI],
pCoords[pointI], pCoords[pointI],
snappedPoint[pointI], snappedPoint[pointI] != -1,
(
snappedPoint[pointI] != -1
? snappedPoints[snappedPoint[pointI]]
: pTraits<Type>::zero
),
pVals[nextPointI], pVals[nextPointI],
pCoords[nextPointI], pCoords[nextPointI],
snappedPoint[nextPointI], snappedPoint[nextPointI] != -1,
(
snappedPoint[nextPointI] != -1
? snappedPoints[snappedPoint[nextPointI]]
: pTraits<Type>::zero
),
cVals[own], cVals[own],
cCoords[own], cCoords[own],
snappedCc[own], snappedCc[own] != -1,
(
snappedCc[own] != -1
? snappedPoints[snappedCc[own]]
: pTraits<Type>::zero
),
neiVal, neiVal,
neiPt, neiPt,
neiSnap, hasNeiSnap,
neiSnapPt,
triPoints triPoints
); );
@ -311,25 +388,6 @@ void Foam::isoSurface::generateTriPoints
<< abort(FatalError); << abort(FatalError);
} }
// Determine neighbouring snap status
labelList neiSnappedCc(mesh_.nFaces()-mesh_.nInternalFaces(), -1);
forAll(patches, patchI)
{
const polyPatch& pp = patches[patchI];
if (pp.coupled())
{
label faceI = pp.start();
forAll(pp, i)
{
neiSnappedCc[faceI-mesh_.nInternalFaces()] =
snappedCc[own[faceI]];
faceI++;
}
}
}
syncTools::swapBoundaryFaceList(mesh_, neiSnappedCc, false);
// Generate triangle points // Generate triangle points
@ -356,7 +414,12 @@ void Foam::isoSurface::generateTriPoints
cVals[nei[faceI]], cVals[nei[faceI]],
cCoords[nei[faceI]], cCoords[nei[faceI]],
snappedCc[nei[faceI]], snappedCc[nei[faceI]] != -1,
(
snappedCc[nei[faceI]] != -1
? snappedPoints[snappedCc[nei[faceI]]]
: pTraits<Type>::zero
),
triPoints, triPoints,
triMeshCells triMeshCells
@ -365,6 +428,34 @@ void Foam::isoSurface::generateTriPoints
} }
// Determine neighbouring snap status
boolList neiSnapped(mesh_.nFaces()-mesh_.nInternalFaces(), false);
List<Type> neiSnappedPoint(neiSnapped.size(), pTraits<Type>::zero);
forAll(patches, patchI)
{
const polyPatch& pp = patches[patchI];
if (pp.coupled())
{
label faceI = pp.start();
forAll(pp, i)
{
label bFaceI = faceI-mesh_.nInternalFaces();
label snappedIndex = snappedCc[own[faceI]];
if (snappedIndex != -1)
{
neiSnapped[bFaceI] = true;
neiSnappedPoint[bFaceI] = snappedPoints[snappedIndex];
}
faceI++;
}
}
}
syncTools::swapBoundaryFaceList(mesh_, neiSnapped, false);
syncTools::swapBoundaryFaceList(mesh_, neiSnappedPoint, false);
forAll(patches, patchI) forAll(patches, patchI)
{ {
const polyPatch& pp = patches[patchI]; const polyPatch& pp = patches[patchI];
@ -372,45 +463,104 @@ void Foam::isoSurface::generateTriPoints
if if
( (
isA<processorPolyPatch>(pp) isA<processorPolyPatch>(pp)
&& refCast<const processorPolyPatch>(pp).owner()
&& !refCast<const processorPolyPatch>(pp).separated() && !refCast<const processorPolyPatch>(pp).separated()
) )
{ {
label faceI = pp.start(); //if (refCast<const processorPolyPatch>(pp).owner())
forAll(pp, i)
{ {
if (faceCutType_[faceI] != NOTCUT) label faceI = pp.start();
forAll(pp, i)
{ {
generateFaceTriPoints if (faceCutType_[faceI] != NOTCUT)
( {
cVals, label bFaceI = faceI-mesh_.nInternalFaces();
pVals, if
(
neiSnapped[bFaceI]
&& (neiSnappedPoint[bFaceI]==pTraits<Type>::zero)
)
{
FatalErrorIn("isoSurface::generateTriPoints(..)")
<< "problem:" << abort(FatalError);
}
cCoords,
pCoords,
snappedPoints, generateFaceTriPoints
snappedCc, (
snappedPoint, cVals,
faceI, pVals,
cVals.boundaryField()[patchI][i], cCoords,
cCoords.boundaryField()[patchI][i], pCoords,
neiSnappedCc[faceI-mesh_.nInternalFaces()],
triPoints, snappedPoints,
triMeshCells snappedCc,
); snappedPoint,
faceI,
cVals.boundaryField()[patchI][i],
cCoords.boundaryField()[patchI][i],
neiSnapped[faceI-mesh_.nInternalFaces()],
neiSnappedPoint[faceI-mesh_.nInternalFaces()],
triPoints,
triMeshCells
);
}
faceI++;
} }
faceI++;
} }
} }
else if (isA<emptyPolyPatch>(pp)) else if (isA<emptyPolyPatch>(pp))
{ {
// Assume zero-gradient. But what about coordinates? // Check if field is there (when generating geometry the
// empty patches have been rewritten to be the face centres),
// otherwise use zero-gradient.
label faceI = pp.start(); label faceI = pp.start();
const fvPatchScalarField& fvp = cVals.boundaryField()[patchI];
// Owner value of cVals
scalarField internalVals;
if (fvp.size() == 0)
{
internalVals.setSize(pp.size());
forAll(pp, i)
{
internalVals[i] = cVals[own[pp.start()+i]];
}
}
const scalarField& bVals =
(
fvp.size() > 0
? static_cast<const scalarField&>(fvp)
: internalVals
);
const fvPatchField<Type>& pc = cCoords.boundaryField()[patchI];
// Owner value of cCoords
Field<Type> internalCoords;
if (pc.size() == 0)
{
internalCoords.setSize(pp.size());
forAll(pp, i)
{
internalCoords[i] = cCoords[own[pp.start()+i]];
}
}
const Field<Type>& bCoords =
(
pc.size() > 0
? static_cast<const Field<Type>&>(pc)
: internalCoords
);
forAll(pp, i) forAll(pp, i)
{ {
if (faceCutType_[faceI] != NOTCUT) if (faceCutType_[faceI] != NOTCUT)
@ -428,9 +578,10 @@ void Foam::isoSurface::generateTriPoints
snappedPoint, snappedPoint,
faceI, faceI,
cVals[own[faceI]], bVals[i],
cCoords.boundaryField()[patchI][i], bCoords[i],
-1, // fc not snapped false, // fc not snapped
pTraits<Type>::zero,
triPoints, triPoints,
triMeshCells triMeshCells
@ -462,7 +613,8 @@ void Foam::isoSurface::generateTriPoints
cVals.boundaryField()[patchI][i], cVals.boundaryField()[patchI][i],
cCoords.boundaryField()[patchI][i], cCoords.boundaryField()[patchI][i],
-1, // fc not snapped false, // fc not snapped
pTraits<Type>::zero,
triPoints, triPoints,
triMeshCells triMeshCells

View File

@ -2,7 +2,7 @@
cd ${0%/*} || exit 1 # run from this directory cd ${0%/*} || exit 1 # run from this directory
set -x set -x
wmakeLnInclude -f ../incompressible/LES wmakeLnInclude -f ../incompressible/LES -sf
wmake libso LESfilters wmake libso LESfilters
wmake libso LESdeltas wmake libso LESdeltas

View File

@ -42,8 +42,7 @@ addToRunTimeSelectionTable(LESdelta, cubeRootVolDelta, dictionary);
void cubeRootVolDelta::calcDelta() void cubeRootVolDelta::calcDelta()
{ {
const Vector<label>& directions = mesh().directions(); label nD = mesh().nGeometricD();
label nD = (directions.nComponents + cmptSum(directions))/2;
if (nD == 3) if (nD == 3)
{ {
@ -55,14 +54,15 @@ void cubeRootVolDelta::calcDelta()
<< "Case is 2D, LES is not strictly applicable\n" << "Case is 2D, LES is not strictly applicable\n"
<< endl; << endl;
const Vector<label>& directions = mesh().geometricD();
scalar thickness = 0.0; scalar thickness = 0.0;
for (direction dir=0; dir<directions.nComponents; dir++) for (direction dir=0; dir<directions.nComponents; dir++)
{ {
if (directions[dir] == -1) if (directions[dir] == -1)
{ {
boundBox bb(mesh().points(), false); thickness = mesh().bounds().span()[dir];
break;
thickness = bb.span()[dir];
} }
} }

View File

@ -41,8 +41,7 @@ namespace Foam
void Foam::IDDESDelta::calcDelta() void Foam::IDDESDelta::calcDelta()
{ {
const Vector<label>& directions = mesh().directions(); label nD = mesh().nGeometricD();
label nD = (directions.nComponents + cmptSum(directions))/2;
// initialise hwn as wall distance // initialise hwn as wall distance
volScalarField hwn = wallDist(mesh()).y(); volScalarField hwn = wallDist(mesh()).y();

View File

@ -32,8 +32,8 @@ Description
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "fvCFD.H" #include "fvCFD.H"
#include "incompressible/singlePhaseTransportModel/singlePhaseTransportModel.H" #include "singlePhaseTransportModel.H"
#include "incompressible/RASModel/RASModel.H" #include "RASModel.H"
#include "MRFZones.H" #include "MRFZones.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -1,7 +1,9 @@
EXE_INC = \ EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \ -I$(LIB_SRC)/turbulenceModels \
-I$(LIB_SRC)/turbulenceModels/RAS \ -I$(LIB_SRC)/turbulenceModels/incompressible/RAS/RASModel \
-I$(LIB_SRC)/transportModels -I$(LIB_SRC)/transportModels \
-I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \
-I$(LIB_SRC)/finiteVolume/lnInclude
EXE_LIBS = \ EXE_LIBS = \
-lincompressibleRASModels \ -lincompressibleRASModels \

View File

@ -3,8 +3,9 @@
m4 < constant/polyMesh/blockMeshDict.m4 > constant/polyMesh/blockMeshDict m4 < constant/polyMesh/blockMeshDict.m4 > constant/polyMesh/blockMeshDict
blockMesh blockMesh
cellSet cellSet
cp system/faceSetDict_rotorFaces system/faceSetDict #- MRF determines its own faceZone if not supplied
faceSet #cp system/faceSetDict_rotorFaces system/faceSetDict
cp system/faceSetDict_noBoundaryFaces system/faceSetDict #faceSet
faceSet #cp system/faceSetDict_noBoundaryFaces system/faceSetDict
#faceSet
setsToZones -noFlipMap setsToZones -noFlipMap

View File

@ -15,10 +15,14 @@ FoamFile
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Seed patches to start layering from
patches ( bottomWall ); patches ( bottomWall );
// Direction in which the layers are
component y; component y;
// Is the mesh symmetric? If so average(symmetric fields) or
// subtract(asymmetric) contributions from both halves
symmetric true; symmetric true;

View File

@ -43,7 +43,35 @@ timePrecision 6;
runTimeModifiable yes; runTimeModifiable yes;
functions ( fieldAverage1 { type fieldAverage ; functionObjectLibs ( "libfieldFunctionObjects.so" ) ; enabled true ; outputControl outputTime ; fields ( U { mean on ; prime2Mean on ; base time ; } p { mean on ; prime2Mean on ; base time ; } ) ; } ); functions
(
fieldAverage1
{
type fieldAverage;
functionObjectLibs ( "libfieldFunctionObjects.so" );
enabled true;
outputControl outputTime;
fields
(
U
{
mean on;
prime2Mean on;
base time;
}
p
{
mean on;
prime2Mean on;
base time;
}
);
}
);
// ************************************************************************* // // ************************************************************************* //

View File

@ -2,7 +2,7 @@
| ========= | | | ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 1.5 | | \\ / O peration | Version: 1.5 |
| \\ / A nd | Web: www.OpenFOAM.org | | \\ / A nd | Web: http://www.OpenFOAM.org |
| \\/ M anipulation | | | \\/ M anipulation | |
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
FoamFile FoamFile
@ -10,138 +10,373 @@ FoamFile
version 2.0; version 2.0;
format ascii; format ascii;
class dictionary; class dictionary;
location "system"; object autoHexMeshDict;
object snappyHexMeshDict;
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Which of the steps to run
castellatedMesh true; castellatedMesh true;
snap true; snap true;
addLayers true; addLayers true;
// Geometry. Definition of all surfaces. All surfaces are of class
// searchableSurface.
// Surfaces are used
// - to specify refinement for any mesh cell intersecting it
// - to specify refinement for any mesh cell inside/outside/near
// - to 'snap' the mesh boundary to the surface
geometry geometry
{ {
fridgeA
{
type searchableBox;
min ( 2 2 0 );
max ( 3 3 2 );
}
fridgeB
{
type searchableBox;
min ( 3.5 3 0 );
max ( 4.3 3.8 1.8 );
}
igloo igloo
{ {
type searchableSphere; type searchableSphere;
centre ( 3 3 0 ); centre (3 3 0);
radius 4; radius 4;
} }
}
box1
{
type searchableBox;
min (0 0 0);
max (1 1 1);
}
fridgeFreezer
{
type searchableSurfaceCollection;
freezer
{
surface box1;
scale (1 1 1);
transform
{
type cartesian;
origin (0 0 0);
e1 (1 0 0);
e3 (0 0 1);
}
}
fridge
{
surface box1;
scale (1 1 1.1);
transform
{
type cartesian;
origin (0 0 1);
e1 (1 0 0);
e3 (0 0 1);
}
}
}
twoFridgeFreezers
{
type searchableSurfaceCollection;
seal
{
surface fridgeFreezer;
scale (1.0 1.0 1.0);
transform
{
type cartesian;
origin (2 2 0);
e1 (1 0 0);
e3 (0 0 1);
}
}
herring
{
surface fridgeFreezer;
scale (1.0 1.0 1.0);
transform
{
type cartesian;
origin (3.5 3 0);
e1 (1 0 0);
e3 (0 0 1);
}
}
}
};
// Settings for the castellatedMesh generation.
castellatedMeshControls castellatedMeshControls
{ {
maxLocalCells 1000000;
maxGlobalCells 2000000; // Refinement parameters
minRefinementCells 0; // ~~~~~~~~~~~~~~~~~~~~~
// While refining maximum number of cells per processor. This is basically
// the number of cells that fit on a processor. If you choose this too small
// it will do just more refinement iterations to obtain a similar mesh.
maxLocalCells 1000000;
// Overall cell limit (approximately). Refinement will stop immediately
// upon reaching this number so a refinement level might not complete.
// Note that this is the number of cells before removing the part which
// is not 'visible' from the keepPoint. The final number of cells might
// actually be a lot less.
maxGlobalCells 2000000;
// The surface refinement loop might spend lots of iterations refining just a
// few cells. This setting will cause refinement to stop if <= minimumRefine
// are selected for refinement. Note: it will at least do one iteration
// (unless the number of cells to refine is 0)
minRefinementCells 100;
// Number of buffer layers between different levels.
// 1 means normal 2:1 refinement restriction, larger means slower
// refinement.
nCellsBetweenLevels 1; nCellsBetweenLevels 1;
features ( );
// Explicit feature edge refinement
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Specifies a level for any cell intersected by its edges.
// This is a featureEdgeMesh, read from constant/triSurface for now.
features
(
// {
// file "fridgeA.eMesh";
// level 3;
// }
);
// Surface based refinement
// ~~~~~~~~~~~~~~~~~~~~~~~~
// Specifies two levels for every surface. The first is the minimum level,
// every cell intersecting a surface gets refined up to the minimum level.
// The second level is the maximum level. Cells that 'see' multiple
// intersections where the intersections make an
// angle > resolveFeatureAngle get refined up to the maximum level.
refinementSurfaces refinementSurfaces
{ {
fridgeA twoFridgeFreezers
{ {
level ( 2 2 ); // Surface-wise min and max refinement level
level (2 2);
regions
{
// Region-wise override
"cook.*"
{
level (3 3);
}
}
} }
fridgeB "iglo.*"
{ {
level ( 2 2 ); // Surface-wise min and max refinement level
} level (1 1);
igloo
{
level ( 1 1 );
} }
} }
// Resolve sharp angles on fridges
resolveFeatureAngle 60; resolveFeatureAngle 60;
// Region-wise refinement
// ~~~~~~~~~~~~~~~~~~~~~~
// Specifies refinement level for cells in relation to a surface. One of
// three modes
// - distance. 'levels' specifies per distance to the surface the
// wanted refinement level. The distances need to be specified in
// descending order.
// - inside. 'levels' is only one entry and only the level is used. All
// cells inside the surface get refined up to the level. The surface
// needs to be closed for this to be possible.
// - outside. Same but cells outside.
refinementRegions refinementRegions
{ {
} }
locationInMesh ( 3 0.28 0.43 );
// Mesh selection
// ~~~~~~~~~~~~~~
// After refinement patches get added for all refinementSurfaces and
// all cells intersecting the surfaces get put into these patches. The
// section reachable from the locationInMesh is kept.
// NOTE: This point should never be on a face, always inside a cell, even
// after refinement.
locationInMesh (3 0.28 0.43);
} }
// Settings for the snapping.
snapControls snapControls
{ {
nSmoothPatch 3; //- Number of patch smoothing iterations before finding correspondence
tolerance 4; // to surface
nSolveIter 30; nSmoothPatch 3;
nRelaxIter 5;
//- Relative distance for points to be attracted by surface feature point
// or edge. True distance is this factor times local
// maximum edge length.
tolerance 4.0;
//- Number of mesh displacement relaxation iterations.
nSolveIter 30;
//- Maximum number of snapping relaxation iterations. Should stop
// before upon reaching a correct mesh.
nRelaxIter 5;
} }
// Settings for the layer addition.
addLayersControls addLayersControls
{ {
// Per final patch (so not geometry!) the layer information
layers layers
{ {
fridgeA_region0 "two.*"
{ {
nSurfaceLayers 1; nSurfaceLayers 3;
} }
"igloo_.*"
fridgeB_region0
{ {
nSurfaceLayers 1; nSurfaceLayers 1;
}
igloo_region0
{
nSurfaceLayers 1;
} }
} }
expansionRatio 1; // Expansion factor for layer mesh
expansionRatio 1.0;
//- Wanted thickness of final added cell layer. If multiple layers
// is the
// thickness of the layer furthest away from the wall.
// Relative to undistorted size of cell outside layer.
finalLayerRatio 0.5; finalLayerRatio 0.5;
minThickness 0.25;
nGrow 0; //- Minimum thickness of cell layer. If for any reason layer
featureAngle 60; // cannot be above minThickness do not add layer.
nRelaxIter 5; // Relative to undistorted size of cell outside layer.
minThickness 0.25;
//- If points get not extruded do nGrow layers of connected faces that are
// also not grown. This helps convergence of the layer addition process
// close to features.
nGrow 0;
// Advanced settings
//- When not to extrude surface. 0 is flat surface, 90 is when two faces
// make straight angle.
featureAngle 60;
//- Maximum number of snapping relaxation iterations. Should stop
// before upon reaching a correct mesh.
nRelaxIter 5;
// Number of smoothing iterations of surface normals
nSmoothSurfaceNormals 1; nSmoothSurfaceNormals 1;
nSmoothNormals 3;
// Number of smoothing iterations of interior mesh movement direction
nSmoothNormals 3;
// Smooth layer thickness over surface patches
nSmoothThickness 10; nSmoothThickness 10;
// Stop layer growth on highly warped cells
maxFaceThicknessRatio 0.5; maxFaceThicknessRatio 0.5;
// Reduce layer growth where ratio thickness to medial
// distance is large
maxThicknessToMedialRatio 0.3; maxThicknessToMedialRatio 0.3;
// Angle used to pick up medial axis points
minMedianAxisAngle 130; minMedianAxisAngle 130;
// Create buffer region for new layer terminations
nBufferCellsNoExtrude 0; nBufferCellsNoExtrude 0;
} }
// Generic mesh quality settings. At any undoable phase these determine
// where to undo.
meshQualityControls meshQualityControls
{ {
maxNonOrtho 65; //- Maximum non-orthogonality allowed. Set to 180 to disable.
maxNonOrtho 65;
//- Max skewness allowed. Set to <0 to disable.
maxBoundarySkewness 20; maxBoundarySkewness 20;
maxInternalSkewness 4; maxInternalSkewness 4;
maxConcave 80;
minFlatness 0.5; //- Max concaveness allowed. Is angle (in degrees) below which concavity
minVol 1e-13; // is allowed. 0 is straight face, <0 would be convex face.
minArea -1; // Set to 180 to disable.
minTwist 0.05; maxConcave 80;
minDeterminant 0.001;
minFaceWeight 0.05; //- Minimum projected area v.s. actual area. Set to -1 to disable.
minVolRatio 0.01; minFlatness 0.5;
//- Minimum pyramid volume. Is absolute volume of cell pyramid.
// Set to very negative number (e.g. -1E30) to disable.
minVol 1e-13;
//- Minimum face area. Set to <0 to disable.
minArea -1;
//- Minimum face twist. Set to <-1 to disable. dot product of face normal
//- and face centre triangles normal
minTwist 0.05;
//- minimum normalised cell determinant
//- 1 = hex, <= 0 = folded or flattened illegal cell
minDeterminant 0.001;
//- minFaceWeight (0 -> 0.5)
minFaceWeight 0.05;
//- minVolRatio (0 -> 1)
minVolRatio 0.01;
//must be >0 for Fluent compatibility
minTriangleTwist -1; minTriangleTwist -1;
nSmoothScale 4;
errorReduction 0.75;
// Advanced
//- Number of error distribution iterations
nSmoothScale 4;
//- amount to scale back displacement at error points
errorReduction 0.75;
} }
debug 0;
mergeTolerance 1e-06; // Advanced
// Flags for optional output
// 0 : only write final meshes
// 1 : write intermediate meshes
// 2 : write volScalarField with cellLevel for postprocessing
// 4 : write current intersections as .obj files
debug 0;
// Merge tolerance. Is fraction of overall bounding box of initial mesh.
// Note: the write tolerance needs to be higher than this.
mergeTolerance 1E-6;
// ************************************************************************* // // ************************************************************************* //

View File

@ -13,14 +13,21 @@ FoamFile
location "system"; location "system";
object snappyHexMeshDict; object snappyHexMeshDict;
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Which of the steps to run
castellatedMesh true; castellatedMesh true;
snap true; snap true;
addLayers true; addLayers true;
// Geometry. Definition of all surfaces. All surfaces are of class
// searchableSurface.
// Surfaces are used
// - to specify refinement for any mesh cell intersecting it
// - to specify refinement for any mesh cell inside/outside/near
// - to 'snap' the mesh boundary to the surface
geometry geometry
{ {
motorBike.stl motorBike.stl
@ -37,22 +44,89 @@ geometry
} }
} }
// Settings for the castellatedMesh generation.
castellatedMeshControls castellatedMeshControls
{ {
// Refinement parameters
// ~~~~~~~~~~~~~~~~~~~~~
// While refining maximum number of cells per processor. This is basically
// the number of cells that fit on a processor. If you choose this too small
// it will do just more refinement iterations to obtain a similar mesh.
maxLocalCells 1000000; maxLocalCells 1000000;
// Overall cell limit (approximately). Refinement will stop immediately
// upon reaching this number so a refinement level might not complete.
// Note that this is the number of cells before removing the part which
// is not 'visible' from the keepPoint. The final number of cells might
// actually be a lot less.
maxGlobalCells 2000000; maxGlobalCells 2000000;
// The surface refinement loop might spend lots of iterations refining just a
// few cells. This setting will cause refinement to stop if <= minimumRefine
// are selected for refinement. Note: it will at least do one iteration
// (unless the number of cells to refine is 0)
minRefinementCells 10; minRefinementCells 10;
// Number of buffer layers between different levels.
// 1 means normal 2:1 refinement restriction, larger means slower
// refinement.
nCellsBetweenLevels 2; nCellsBetweenLevels 2;
features ( );
// Explicit feature edge refinement
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Specifies a level for any cell intersected by its edges.
// This is a featureEdgeMesh, read from constant/triSurface for now.
features
(
//{
// file "someLine.eMesh";
// level 2;
//}
);
// Surface based refinement
// ~~~~~~~~~~~~~~~~~~~~~~~~
// Specifies two levels for every surface. The first is the minimum level,
// every cell intersecting a surface gets refined up to the minimum level.
// The second level is the maximum level. Cells that 'see' multiple
// intersections where the intersections make an
// angle > resolveFeatureAngle get refined up to the maximum level.
refinementSurfaces refinementSurfaces
{ {
motorBike motorBike
{ {
// Surface-wise min and max refinement level
level ( 5 6 ); level ( 5 6 );
} }
} }
// Resolve sharp angles
resolveFeatureAngle 30; resolveFeatureAngle 30;
// Region-wise refinement
// ~~~~~~~~~~~~~~~~~~~~~~
// Specifies refinement level for cells in relation to a surface. One of
// three modes
// - distance. 'levels' specifies per distance to the surface the
// wanted refinement level. The distances need to be specified in
// descending order.
// - inside. 'levels' is only one entry and only the level is used. All
// cells inside the surface get refined up to the level. The surface
// needs to be closed for this to be possible.
// - outside. Same but cells outside.
refinementRegions refinementRegions
{ {
refinementBox refinementBox
@ -62,19 +136,45 @@ castellatedMeshControls
} }
} }
// Mesh selection
// ~~~~~~~~~~~~~~
// After refinement patches get added for all refinementSurfaces and
// all cells intersecting the surfaces get put into these patches. The
// section reachable from the locationInMesh is kept.
// NOTE: This point should never be on a face, always inside a cell, even
// after refinement.
locationInMesh ( 3 3 0.43 ); locationInMesh ( 3 3 0.43 );
} }
// Settings for the snapping.
snapControls snapControls
{ {
//- Number of patch smoothing iterations before finding correspondence
// to surface
nSmoothPatch 3; nSmoothPatch 3;
//- Relative distance for points to be attracted by surface feature point
// or edge. True distance is this factor times local
// maximum edge length.
tolerance 4; tolerance 4;
//- Number of mesh displacement relaxation iterations.
nSolveIter 30; nSolveIter 30;
//- Maximum number of snapping relaxation iterations. Should stop
// before upon reaching a correct mesh.
nRelaxIter 5; nRelaxIter 5;
} }
// Settings for the layer addition.
addLayersControls addLayersControls
{ {
// Per final patch (so not geometry!) the layer information
layers layers
{ {
minZ minZ
@ -418,41 +518,126 @@ addLayersControls
} }
} }
// Expansion factor for layer mesh
expansionRatio 1; expansionRatio 1;
//- Wanted thickness of final added cell layer. If multiple layers
// is the
// thickness of the layer furthest away from the wall.
// Relative to undistorted size of cell outside layer.
finalLayerRatio 0.3; finalLayerRatio 0.3;
//- Minimum thickness of cell layer. If for any reason layer
// cannot be above minThickness do not add layer.
// Relative to undistorted size of cell outside layer.
minThickness 0.1; minThickness 0.1;
//- If points get not extruded do nGrow layers of connected faces that are
// also not grown. This helps convergence of the layer addition process
// close to features.
nGrow 1; nGrow 1;
// Advanced settings
//- When not to extrude surface. 0 is flat surface, 90 is when two faces
// make straight angle.
featureAngle 30; featureAngle 30;
//- Maximum number of snapping relaxation iterations. Should stop
// before upon reaching a correct mesh.
nRelaxIter 3; nRelaxIter 3;
// Number of smoothing iterations of surface normals
nSmoothSurfaceNormals 1; nSmoothSurfaceNormals 1;
// Number of smoothing iterations of interior mesh movement direction
nSmoothNormals 3; nSmoothNormals 3;
// Smooth layer thickness over surface patches
nSmoothThickness 10; nSmoothThickness 10;
// Stop layer growth on highly warped cells
maxFaceThicknessRatio 0.5; maxFaceThicknessRatio 0.5;
// Reduce layer growth where ratio thickness to medial
// distance is large
maxThicknessToMedialRatio 0.3; maxThicknessToMedialRatio 0.3;
// Angle used to pick up medial axis points
minMedianAxisAngle 130; minMedianAxisAngle 130;
// Create buffer region for new layer terminations
nBufferCellsNoExtrude 0; nBufferCellsNoExtrude 0;
} }
// Generic mesh quality settings. At any undoable phase these determine
// where to undo.
meshQualityControls meshQualityControls
{ {
//- Maximum non-orthogonality allowed. Set to 180 to disable.
maxNonOrtho 65; maxNonOrtho 65;
//- Max skewness allowed. Set to <0 to disable.
maxBoundarySkewness 20; maxBoundarySkewness 20;
maxInternalSkewness 4; maxInternalSkewness 4;
//- Max concaveness allowed. Is angle (in degrees) below which concavity
// is allowed. 0 is straight face, <0 would be convex face.
// Set to 180 to disable.
maxConcave 80; maxConcave 80;
//- Minimum projected area v.s. actual area. Set to -1 to disable.
minFlatness 0.5; minFlatness 0.5;
//- Minimum pyramid volume. Is absolute volume of cell pyramid.
// Set to very negative number (e.g. -1E30) to disable.
minVol 1e-13; minVol 1e-13;
//- Minimum face area. Set to <0 to disable.
minArea -1; minArea -1;
//- Minimum face twist. Set to <-1 to disable. dot product of face normal
//- and face centre triangles normal
minTwist 0.02; minTwist 0.02;
//- minimum normalised cell determinant
//- 1 = hex, <= 0 = folded or flattened illegal cell
minDeterminant 0.001; minDeterminant 0.001;
//- minFaceWeight (0 -> 0.5)
minFaceWeight 0.02; minFaceWeight 0.02;
//- minVolRatio (0 -> 1)
minVolRatio 0.01; minVolRatio 0.01;
//must be >0 for Fluent compatibility
minTriangleTwist -1; minTriangleTwist -1;
// Advanced
//- Number of error distribution iterations
nSmoothScale 4; nSmoothScale 4;
//- amount to scale back displacement at error points
errorReduction 0.75; errorReduction 0.75;
} }
// Advanced
// Flags for optional output
// 0 : only write final meshes
// 1 : write intermediate meshes
// 2 : write volScalarField with cellLevel for postprocessing
// 4 : write current intersections as .obj files
debug 0; debug 0;
// Merge tolerance. Is fraction of overall bounding box of initial mesh.
// Note: the write tolerance needs to be higher than this.
mergeTolerance 1e-06; mergeTolerance 1e-06;

View File

@ -145,16 +145,6 @@ find -L . -type l -exec rm \{\} \;
find .. $findOpt \ find .. $findOpt \
\( -name lnInclude -o -name Make -o -name config -o -name noLink \) -prune \ \( -name lnInclude -o -name Make -o -name config -o -name noLink \) -prune \
-o \( -name '*.[CHh]' -o -name '*.[ch]xx' -o -name '*.[ch]pp' -o -name '*.type' \) \ -o \( -name '*.[CHh]' -o -name '*.[ch]xx' -o -name '*.[ch]pp' -o -name '*.type' \) \
-a ! -name ".#*" \ -exec ln $lnOpt {} . \;
-print | \
while read src
do
link=$(readlink ${src##*/})
if [ "$link" != "$src" ]
then
rm $link 2>/dev/null
ln $lnOpt $src .
fi
done
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------