Merge branch 'cvm'

This commit is contained in:
mattijs
2011-07-21 13:06:10 +01:00
330 changed files with 65001 additions and 533 deletions

View File

@ -3,4 +3,3 @@
const int nNonOrthCorr =
potentialFlow.lookupOrDefault<int>("nNonOrthogonalCorrectors", 0);

View File

@ -13,4 +13,3 @@ EXE_LIBS = \
-lmolecule \
-lpotential \
-lmolecularMeasurements

View File

@ -13,4 +13,3 @@ EXE_LIBS = \
-lmolecule \
-lpotential \
-lmolecularMeasurements

View File

@ -0,0 +1,55 @@
Info<< "\nReading field U\n" << endl;
volVectorField U
(
IOobject
(
"U",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
word polyatomicCloudName("polyatomicCloud");
potential polyPot
(
mesh,
IOdictionary
(
IOobject
(
polyatomicCloudName + "Properties",
mesh.time().constant(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE,
false
)
)
);
polyatomicCloud polyatomics(polyatomicCloudName, mesh, polyPot);
word monoatomicCloudName("monoatomicCloud");
potential monoPot
(
mesh,
IOdictionary
(
IOobject
(
monoatomicCloudName + "Properties",
mesh.time().constant(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE,
false
)
)
);
monoatomicCloud monoatomics(monoatomicCloudName, mesh, monoPot);

View File

@ -0,0 +1,3 @@
mdEquilibrationFoam.C
EXE = $(FOAM_APPBIN)/mdEquilibrationFoam

View File

@ -0,0 +1,16 @@
EXE_INC = \
-I$(LIB_SRC)/lagrangian/molecularDynamics/molecule/lnInclude \
-I$(LIB_SRC)/lagrangian/molecularDynamics/potential/lnInclude \
-I$(LIB_SRC)/lagrangian/molecularDynamics/molecularMeasurements/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-lmeshTools \
-lfiniteVolume \
-llagrangian \
-lmolecule \
-lpotential \
-lmolecularMeasurements

View File

@ -0,0 +1,101 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
mdEquilibrationFoam
Description
Equilibrates and/or preconditions molecular dynamics systems
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "md.H"
int main(int argc, char *argv[])
{
#include "setRootCase.H"
#include "createTime.H"
#include "createMesh.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nReading field U\n" << endl;
volVectorField U
(
IOobject
(
"U",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);
potential pot(mesh);
moleculeCloud molecules(mesh, pot);
#include "temperatureAndPressureVariables.H"
#include "readmdEquilibrationDict.H"
label nAveragingSteps = 0;
Info<< "\nStarting time loop\n" << endl;
while (runTime.loop())
{
nAveragingSteps++;
Info<< "Time = " << runTime.timeName() << endl;
molecules.evolve();
#include "meanMomentumEnergyAndNMols.H"
#include "temperatureAndPressure.H"
#include "temperatureEquilibration.H"
runTime.write();
if (runTime.outputTime())
{
nAveragingSteps = 0;
}
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< nl << endl;
}
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,18 @@
Info<< nl << "Reading MD Equilibration Dictionary" << nl << endl;
IOdictionary mdEquilibrationDict
(
IOobject
(
"mdEquilibrationDict",
runTime.system(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
);
scalar targetTemperature = readScalar
(
mdEquilibrationDict.lookup("targetTemperature")
);

View File

@ -16,4 +16,3 @@
{
solve(UEqn == -fvc::grad(p));
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -26,7 +26,7 @@ Application
Description
Calculates the inertia tensor and principal axes and moments of a
test face, tetrahedron and mesh.
test face, tetrahedron and cell.
\*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,3 @@
cvMesh.C
EXE = $(FOAM_APPBIN)/cvMesh

View File

@ -0,0 +1,26 @@
EXE_DEBUG = -DFULLDEBUG -g -O0
EXE_FROUNDING_MATH = -frounding-math
EXE_NDEBUG = -DNDEBUG
include $(GENERAL_RULES)/CGAL
EXE_INC = \
${EXE_FROUNDING_MATH} \
${EXE_NDEBUG} \
${CGAL_INC} \
-I$(LIB_SRC)/mesh/conformalVoronoiMesh/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude \
-I$(LIB_SRC)/edgeMesh/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude
EXE_LIBS = \
$(CGAL_LIBS) \
-lconformalVoronoiMesh \
-lmeshTools \
-ldecompositionMethods -L$(FOAM_LIBBIN)/dummy -lscotchDecomp \
-ledgeMesh \
-ltriSurface \
-ldynamicMesh

View File

@ -0,0 +1,82 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
cvMesh
Description
Conformal Voronoi automatic mesh generator
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "conformalVoronoiMesh.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
# include "setRootCase.H"
# include "createTime.H"
runTime.functionObjects().off();
IOdictionary cvMeshDict
(
IOobject
(
"cvMeshDict",
runTime.system(),
runTime,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
);
conformalVoronoiMesh mesh(runTime, cvMeshDict);
while (runTime.loop())
{
Info<< nl << "Time = " << runTime.timeName() << endl;
mesh.move();
Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< nl << endl;
}
mesh.writeMesh(runTime.constant());
Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< nl << endl;
Info<< nl << "End" << nl << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,496 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object cvMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
/*
Control dictionary for cvMesh - polyhedral mesh generator.
cvMesh phases:
1. fill volume with initial points (initialPoints subdictionary). An option
is to reread from previous set of points.
2. internal point motion (motionControl subdictionary)
3. every once in a while add point duplets/triplets to conform to
surfaces and features (surfaceConformation subdictionary)
4. back to 2
5. construct polyMesh.
- filter (polyMeshFiltering subdictionary)
- check (meshQualityControls subdictionary) and undo filtering
See also cvControls.H in the conformalVoronoiMesh library
*/
// Important:
// ----------
// Any scalar with a name <name>Coeff specifies a value that will be implemented
// as a faction of the local target cell size
// Any scalar with a name <name>Size specifies an absolute size.
// Geometry. Definition of all surfaces. All surfaces are of class
// searchableSurface.
// Surfaces need to be (almost) closed - use closedTriSurfaceMesh
// if they are not topologically closed. Surfaces need to be oriented so
// the space to be meshed is always on the inside of all surfaces. Use e.g.
// surfaceOrient.
geometry
{
// Surface to conform to
flange.obj
{
type triSurfaceMesh;
}
// Surface used for cell size control
ref7.stl
{
name ref7;
type triSurfaceMesh;
}
// Surface used for cell size control
tunnel_APPROACH_INLET.obj
{
type triSurfaceMesh;
}
}
// Controls for conforming to the surfaces.
surfaceConformation
{
// A point inside surfaces that is inside mesh.
locationInMesh (0 0 0);
// How far apart are point-duplets generated. Balance this between
// - very low distance: little chance of interference from other
// surfaces
// - largish distance: less non-orthogonality in final cell
// (circumcentre far away from centroid)
pointPairDistanceCoeff 0.1;
// Mixed feature points - connected to both inside and outside edges.
// Recreated by inserting triplets of points to recreate a single edge.
// Done for all edges emanating from point. triplets of points get inserted
// mixedFeaturePointPPDistanceCoeff distance away from feature point.
// Set to a negative number to disable.
mixedFeaturePointPPDistanceCoeff 5.0; //-1;
// Distance to a feature point within which surface and edge
// conformation points are excluded - fraction of the local target
// cell size
featurePointExclusionDistanceCoeff 0.4;
// Distance to an existing feature edge conformation location
// within which other edge conformation location are excluded -
// fraction of the local target cell size
featureEdgeExclusionDistanceCoeff 0.2;
// Optimisation: do not check for surface intersection (of dual edges)
// for points near to surface.
surfaceSearchDistanceCoeff 2.5;
// Maximum allowable protrusion through the surface before
// conformation points are added - fraction of the local target
// cell size. These small protusions are (hopefully) done by mesh filtering
// instead.
maxSurfaceProtrusionCoeff 0.1;
// If feature edge with large angle (so more than 125 degrees) introduce
// additional points to create two half angled cells (= mitering).
maxQuadAngle 125;
// Frequency to redo surface conformation (expensive).
surfaceConformationRebuildFrequency 10;
// Initial and intermediate controls
coarseConformationControls
{
// Initial conformation
initial
{
// We've got a point poking through the surface. Don't do any
// surface conformation if near feature edge (since feature edge
// conformation should have priority)
// distance to search for near feature edges
edgeSearchDistCoeff 1.1;
// Proximity to a feature edge where a surface hit is
// not created, only the edge conformation is created
// - fraction of the local target cell size. Coarse
// conformation, initial protrusion tests.
surfacePtReplaceDistCoeff 0.5;
}
// Same for iterations
iteration
{
edgeSearchDistCoeff 1.25;
surfacePtReplaceDistCoeff 0.7;
}
// Stop either at maxIterations or if the number of surface pokes
// is very small (iterationToInitialHitRatioLimit * initial number)
// Note: perhaps iterationToInitialHitRatioLimit should be absolute
// count?
maxIterations 15;
iterationToInitialHitRatioLimit 0.001;
}
// Final (at endTime) controls
fineConformationControls
{
initial
{
edgeSearchDistCoeff 1.1;
surfacePtReplaceDistCoeff 0.5;
}
iteration
{
edgeSearchDistCoeff 1.25;
surfacePtReplaceDistCoeff 0.7;
}
maxIterations 15;
iterationToInitialHitRatioLimit 0.001;
}
// Geometry to mesh to
geometryToConformTo
{
flange.obj
{
featureMethod extendedFeatureEdgeMesh; // or none;
extendedFeatureEdgeMesh "flange.extendedFeatureEdgeMesh";
}
}
// Additional features.
additionalFeatures
{
//line
//{
// featureMethod extendedFeatureEdgeMesh; // or none;
// extendedFeatureEdgeMesh "line.extendedFeatureEdgeMesh";
//}
}
}
// Controls for seeding initial points and general control of the target
// cell size (used everywhere)
initialPoints
{
// Do not place point closer than minimumSurfaceDistanceCoeff
// to the surface. Is fraction of local target cell size (see below)
minimumSurfaceDistanceCoeff 0.55;
initialPointsMethod autoDensity;
// initialPointsMethod uniformGrid;
// initialPointsMethod bodyCentredCubic;
// initialPointsMethod pointFile;
// Take boundbox of all geometry. Sample with this box. If too much
// samples in box (due to target cell size) split box.
autoDensityDetails
{
// Initial number of refinement levels. Needs to be enough to pick
// up features due to size ratio. If not enough it will take longer
// to determine point seeding.
minLevels 4;
// Split box if ratio of min to max cell size larger than maxSizeRatio
maxSizeRatio 5.0;
// Per box sample 5x5x5 internally
sampleResolution 5;
// Additionally per face of the box sample 5x5
surfaceSampleResolution 5;
}
uniformGridDetails
{
// Absolute cell size.
initialCellSize 0.0015;
randomiseInitialGrid yes;
randomPerturbationCoeff 0.02;
}
bodyCentredCubicDetails
{
initialCellSize 0.0015;
randomiseInitialGrid no;
randomPerturbationCoeff 0.1;
}
pointFileDetails
{
// Reads points from file. Still rejects points that are too
// close to the surface (minimumSurfaceDistanceCoeff) or on the
// wrong side of the surfaces.
pointFile "constant/internalDelaunayVertices";
}
}
// Control size of voronoi cells i.e. distance between points. This
// determines the target cell size which is used everywhere.
// It determines the cell size given a location. It then uses all
// the rules
// - defaultCellSize
// - cellSizeControlGeometry
// to determine target cell size. Rule with highest priority wins. If same
// priority smallest cell size wins.
motionControl
{
// Absolute cell size of back ground mesh. This is the maximum cell size.
defaultCellSize 0.00075;
// Assign a priority to all requests for cell sizes, the highest overrules.
defaultPriority 0;
cellSizeControlGeometry
{
ref7_outside
{
// optional name of geometry
surface ref7;
priority 1;
mode outside;//inside/bothSides
cellSizeFunction linearDistance;
// cellSizeFunctions:
// uniform : uniform size
// uniformDistance : fixed size for all within distance
// linearSpatial : grading in specified direction only
// linearDistance : vary linearly as distance to surface
// surfaceOffsetLinearDistance : constant close to surface then
// fade like linearDistance
// Vary from surfaceCellSize (close to the surface) to
// distanceCellSize (further than 'distance')
linearDistanceCoeffs
{
surfaceCellSize 1e-5; // absolute size
distanceCellSize $defaultCellSize;
distance 1.0;
}
}
tunnel_APPROACH_INLET.obj
{
priority 1;
mode bothSides;
cellSizeFunction surfaceOffsetLinearDistance;
// Constant within a certain distance then linear fade away.
// Good for layers.
surfaceOffsetLinearDistanceCoeffs
{
surfaceCellSize 1e-5;
distanceCellSize $defaultCellSize;
surfaceOffset 0.1;
totalDistance 1.0;
}
}
}
// Underrelaxation for point motion. Simulated annealing: starts off at 1
// and lowers to 0 (at simulation endTime) to converge points.
// adaptiveLinear is preferred choice.
// Points move by e.g. 10% of tet size.
relaxationModel adaptiveLinear; //rampHoldFall
adaptiveLinearCoeffs
{
relaxationStart 1.0;
relaxationEnd 0.0;
}
// Output lots and lots of .obj files
objOutput no;
// Timing and memory usage.
timeChecks yes;
// Number of rays in plane parallel to nearest surface. Used to detect
// next closest surfaces. Used to work out alignment (three vectors)
// to surface.
// Note that only the initial points (from the seeding) calculate this
// information so if these are not fine enough the alignment will
// not be correct. (any points added during the running will lookup
// this information from the nearest initial point since it is
// expensive)
alignmentSearchSpokes 36;
// For each delaunay edge (between two vertices, becomes
// the Voronoi face normal) snap to the alignment direction if within
// alignmentAcceptanceAngle. Slightly > 45 is a good choice - prevents
// flipping.
alignmentAcceptanceAngle 48;
// How often to rebuild the alignment info (expensive)
sizeAndAlignmentRebuildFrequency 20;
// When to insert points. Not advisable change to
// these settings.
pointInsertionCriteria
{
// If edge larger than 1.75 target cell size
// (so tets too large/stretched) insert point
cellCentreDistCoeff 1.75;
// Do not insert point if voronoi face (on edge) very small.
faceAreaRatioCoeff 0.0025;
// Insert point only if edge closely aligned to local alignment
// direction.
acceptanceAngle 21.5;
}
// Opposite: remove point if mesh too compressed. Do not change these
// settings.
pointRemovalCriteria
{
cellCentreDistCoeff 0.65;
}
// How to determine the point motion. All edges got some direction.
// Sum all edge contributions to determine point motion. Weigh by
// face area so motion is preferentially determined by large faces
// (or more importantly ignore contribution from small faces).
// Do not change these settings.
faceAreaWeightModel piecewiseLinearRamp;
piecewiseLinearRampCoeffs
{
lowerAreaFraction 0.5;
upperAreaFraction 1.0;
}
}
// After simulation, when converting to polyMesh, filter out small faces/edges.
// Do not change. See cvControls.H
polyMeshFiltering
{
// Write the underlying Delaunay tet mesh at output time
writeTetDualMesh false; //true;
// Upper limit on the size of faces to be filtered.
// fraction of the local target cell size
filterSizeCoeff 0.2;
// Upper limit on how close two dual vertices can be before
// being merged, fraction of the local target cell size
mergeClosenessCoeff 1e-9;
// To not filter: set maxNonOrtho to 1 (so check fails) and then
// set continueFilteringOnBadInitialPolyMesh to false.
continueFilteringOnBadInitialPolyMesh true;
// When a face is "bad", what fraction should the filterSizeCoeff be
// reduced by. Recursive, so for a filterCount value of fC, the
// filterSizeCoeff is reduced by pow(filterErrorReductionCoeff, fC)
filterErrorReductionCoeff 0.5;
// Maximum number of filterCount applications before a face
// is not attempted to be filtered
filterCountSkipThreshold 4;
// Maximum number of permissible iterations of the face collapse
// algorithm. The value to choose will be related the maximum number
// of points on a face that is to be collapsed and how many faces
// around it need to be collapsed.
maxCollapseIterations 25;
// Maximum number of times an to allow an equal faceSet to be
// returned from the face quality assessment before stopping iterations
// to break an infinitie loop.
maxConsecutiveEqualFaceSets 5;
// Remove little steps (almost perp to surface) by collapsing face.
surfaceStepFaceAngle 80;
// Do not collapse face to edge if should become edges
edgeCollapseGuardFraction 0.3;
// Only collapse face to point if high aspect ratio
maxCollapseFaceToPointSideLengthCoeff 0.35;
}
// Generic mesh quality settings. At any undoable phase these determine
// where to undo. Same as in snappyHexMeshDict
meshQualityControls
{
//- Maximum non-orthogonality allowed. Set to 180 to disable.
maxNonOrtho 65;
//- Max skewness allowed. Set to <0 to disable.
maxBoundarySkewness 50;
maxInternalSkewness 10;
//- 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;
//- Minimum pyramid volume. Is absolute volume of cell pyramid.
// Set to a sensible fraction of the smallest cell volume expected.
// Set to very negative number (e.g. -1E30) to disable.
minVol -1E30;
//- Minimum quality of the tet formed by the
// variable base point minimum decomposition triangles and
// the cell centre (so not face-centre decomposition).
// This has to be a positive number for tracking
// to work. Set to very negative number (e.g. -1E30) to
// disable.
// <0 = inside out tet,
// 0 = flat tet
// 1 = regular tet
minTetQuality 1e-30;
//- Minimum absolute 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.02;
//- minimum normalised cell determinant
//- 1 = hex, <= 0 = folded or flattened illegal cell
minDeterminant 0.001;
//- minFaceWeight (0 -> 0.5)
minFaceWeight 0.02;
//- minVolRatio (0 -> 1)
minVolRatio 0.01;
//must be >0 for Fluent compatibility
minTriangleTwist -1;
}
// ************************************************************************* //

View File

@ -91,6 +91,26 @@ int main(int argc, char *argv[])
// Clear mesh before checking
mesh.clearOut();
pointIOField overrideCCs
(
IOobject
(
"cellCentres",
mesh.pointsInstance(),
polyMesh::meshSubDir,
runTime,
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE
)
);
if (overrideCCs.headerOk())
{
Info<< "Read " << overrideCCs.size() << " cell centres" << endl;
mesh.overrideCellCentres(overrideCCs);
}
// Reconstruct globalMeshData
mesh.globalData();

View File

@ -208,7 +208,8 @@ int main(int argc, char *argv[])
IOobject::MUST_READ
);
Info<< "Read set " << setName << " with size "
<< currentSet().size() << endl;
<< returnReduce(currentSet().size(), sumOp<label>())
<< endl;
}
@ -292,7 +293,8 @@ int main(int argc, char *argv[])
if (currentSet.valid())
{
Info<< " Set " << currentSet().name()
<< " now size " << currentSet().size()
<< " now size "
<< returnReduce(currentSet().size(), sumOp<label>())
<< endl;
}
}

View File

@ -0,0 +1,4 @@
foamToTetDualMesh.C
EXE = $(FOAM_USER_APPBIN)/foamToTetDualMesh

View File

@ -0,0 +1,5 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude
EXE_LIBS = \
-lfiniteVolume

View File

@ -0,0 +1,313 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
foamToTetDualMesh
Description
Converts polyMesh results to tetDualMesh.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "fvMesh.H"
#include "volFields.H"
#include "pointFields.H"
#include "Time.H"
#include "IOobjectList.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class ReadGeoField, class MappedGeoField>
void ReadAndMapFields
(
const fvMesh& mesh,
const IOobjectList& objects,
const fvMesh& tetDualMesh,
const labelList& map,
const typename MappedGeoField::value_type& nullValue,
PtrList<MappedGeoField>& tetFields
)
{
typedef typename MappedGeoField::value_type Type;
// Search list of objects for wanted type
IOobjectList fieldObjects(objects.lookupClass(ReadGeoField::typeName));
tetFields.setSize(fieldObjects.size());
label i = 0;
forAllConstIter(IOobjectList, fieldObjects, iter)
{
Info<< "Converting " << ReadGeoField::typeName << ' ' << iter.key()
<< endl;
ReadGeoField readField(*iter(), mesh);
tetFields.set
(
i,
new MappedGeoField
(
IOobject
(
readField.name(),
readField.instance(),
readField.local(),
tetDualMesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE,
readField.registerObject()
),
pointMesh::New(tetDualMesh),
dimensioned<Type>
(
"zero",
readField.dimensions(),
pTraits<Type>::zero
)
)
);
Field<Type>& fld = tetFields[i].internalField();
// Map from read field. Set unmapped entries to nullValue.
fld.setSize(map.size(), nullValue);
forAll(map, pointI)
{
label index = map[pointI];
if (index > 0)
{
label cellI = index-1;
fld[pointI] = readField[cellI];
}
else if (index < 0)
{
label faceI = -index-1;
label bFaceI = faceI - mesh.nInternalFaces();
if (bFaceI >= 0)
{
label patchI = mesh.boundaryMesh().patchID()[bFaceI];
label localFaceI = mesh.boundaryMesh()[patchI].whichFace
(
faceI
);
fld[pointI] = readField.boundaryField()[patchI][localFaceI];
}
//else
//{
// FatalErrorIn("ReadAndMapFields(..)")
// << "Face " << faceI << " from index " << index
// << " is not a boundary face." << abort(FatalError);
//}
}
//else
//{
// WarningIn("ReadAndMapFields(..)")
// << "Point " << pointI << " at "
// << tetDualMesh.points()[pointI]
// << " has no dual correspondence." << endl;
//}
}
tetFields[i].correctBoundaryConditions();
i++;
}
}
// Main program:
int main(int argc, char *argv[])
{
# include "addOverwriteOption.H"
# include "addTimeOptions.H"
# include "setRootCase.H"
# include "createTime.H"
// Get times list
instantList Times = runTime.times();
# include "checkTimeOptions.H"
runTime.setTime(Times[startTime], startTime);
// Read the mesh
# include "createMesh.H"
// Read the tetDualMesh
Info<< "Create tetDualMesh for time = "
<< runTime.timeName() << nl << endl;
fvMesh tetDualMesh
(
IOobject
(
"tetDualMesh",
runTime.timeName(),
runTime,
IOobject::MUST_READ
)
);
// From tet vertices to poly cells/faces
const labelIOList pointDualAddressing
(
IOobject
(
"pointDualAddressing",
tetDualMesh.facesInstance(),
tetDualMesh.meshSubDir,
tetDualMesh,
IOobject::MUST_READ
)
);
if (pointDualAddressing.size() != tetDualMesh.nPoints())
{
FatalErrorIn(args.executable())
<< "Size " << pointDualAddressing.size()
<< " of addressing map " << pointDualAddressing.objectPath()
<< " differs from number of points in mesh "
<< tetDualMesh.nPoints()
<< exit(FatalError);
}
// Some stats on addressing
label nCells = 0;
label nPatchFaces = 0;
label nUnmapped = 0;
forAll(pointDualAddressing, pointI)
{
label index = pointDualAddressing[pointI];
if (index > 0)
{
nCells++;
}
else if (index == 0)
{
nUnmapped++;
}
else
{
label faceI = -index-1;
if (faceI < mesh.nInternalFaces())
{
FatalErrorIn(args.executable())
<< "Face " << faceI << " from index " << index
<< " is not a boundary face."
<< " nInternalFaces:" << mesh.nInternalFaces()
<< exit(FatalError);
}
else
{
nPatchFaces++;
}
}
}
reduce(nCells, sumOp<label>());
reduce(nPatchFaces, sumOp<label>());
reduce(nUnmapped, sumOp<label>());
Info<< "tetDualMesh points : " << tetDualMesh.nPoints()
<< " of which mapped to" << nl
<< " cells : " << nCells << nl
<< " patch faces : " << nPatchFaces << nl
<< " not mapped : " << nUnmapped << nl
<< endl;
// Read objects in time directory
IOobjectList objects(mesh, runTime.timeName());
// Read vol fields, interpolate onto tet points
PtrList<pointScalarField> psFlds;
ReadAndMapFields<volScalarField, pointScalarField>
(
mesh,
objects,
tetDualMesh,
pointDualAddressing,
pTraits<scalar>::zero, // nullValue
psFlds
);
PtrList<pointVectorField> pvFlds;
ReadAndMapFields<volVectorField, pointVectorField>
(
mesh,
objects,
tetDualMesh,
pointDualAddressing,
pTraits<vector>::zero, // nullValue
pvFlds
);
PtrList<pointSphericalTensorField> pstFlds;
ReadAndMapFields<volSphericalTensorField, pointSphericalTensorField>
(
mesh,
objects,
tetDualMesh,
pointDualAddressing,
pTraits<sphericalTensor>::zero, // nullValue
pstFlds
);
PtrList<pointSymmTensorField> psymmtFlds;
ReadAndMapFields<volSymmTensorField, pointSymmTensorField>
(
mesh,
objects,
tetDualMesh,
pointDualAddressing,
pTraits<symmTensor>::zero, // nullValue
psymmtFlds
);
PtrList<pointTensorField> ptFlds;
ReadAndMapFields<volTensorField, pointTensorField>
(
mesh,
objects,
tetDualMesh,
pointDualAddressing,
pTraits<tensor>::zero, // nullValue
ptFlds
);
tetDualMesh.objectRegistry::write();
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -0,0 +1,3 @@
surfaceBooleanFeatures.C
EXE = $(FOAM_APPBIN)/surfaceBooleanFeatures

View File

@ -0,0 +1,9 @@
EXE_INC = \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/edgeMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-ltriSurface \
-ledgeMesh \
-lmeshTools

View File

@ -0,0 +1,462 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2010-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
surfaceBooleanFeatures
Description
Generates the extendedFeatureEdgeMesh for the interface between a boolean
operation on two surfaces. Assumes that the orientation of the surfaces is
correct:
+ if the operation is union or intersection, that both surface's normals
(n) have the same orientation with respect to a point, i.e. surfaces and b
are orientated the same with respect to point x:
@verbatim
_______
| |--> n
| ___|___ x
|a | | |--> n
|___|___| b|
| |
|_______|
@endverbatim
+ if the operation is a subtraction, the surfaces should be oppositely
oriented with respect to a point, i.e. for (a - b), then b's orientation
should be such that x is "inside", and a's orientation such that x is
"outside"
@verbatim
_______
| |--> n
| ___|___ x
|a | | |
|___|___| b|
| n <--|
|_______|
@endverbatim
When the operation is peformed - for union, all of the edges generates where
one surfaces cuts another are all "internal" for union, and "external" for
intersection, b - a and a - b. This has been assumed, formal (dis)proof is
invited.
\*---------------------------------------------------------------------------*/
#include "triSurface.H"
#include "argList.H"
#include "Time.H"
#include "extendedFeatureEdgeMesh.H"
#include "triSurfaceSearch.H"
#include "OFstream.H"
#include "booleanSurface.H"
#include "edgeIntersections.H"
#include "meshTools.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Keep on shuffling surface points until no more degenerate intersections.
// Moves both surfaces and updates set of edge cuts.
bool intersectSurfaces
(
triSurface& surf1,
edgeIntersections& edgeCuts1,
triSurface& surf2,
edgeIntersections& edgeCuts2
)
{
bool hasMoved1 = false;
bool hasMoved2 = false;
for (label iter = 0; iter < 10; iter++)
{
Info<< "Determining intersections of surf1 edges with surf2"
<< " faces" << endl;
// Determine surface1 edge intersections. Allow surface to be moved.
// Number of iterations needed to resolve degenerates
label nIters1 = 0;
{
triSurfaceSearch querySurf2(surf2);
scalarField surf1PointTol
(
1e-3*edgeIntersections::minEdgeLength(surf1)
);
// Determine raw intersections
edgeCuts1 = edgeIntersections
(
surf1,
querySurf2,
surf1PointTol
);
// Shuffle a bit to resolve degenerate edge-face hits
{
pointField points1(surf1.points());
nIters1 =
edgeCuts1.removeDegenerates
(
5, // max iterations
surf1,
querySurf2,
surf1PointTol,
points1 // work array
);
if (nIters1 != 0)
{
// Update geometric quantities
surf1.movePoints(points1);
hasMoved1 = true;
}
}
}
Info<< "Determining intersections of surf2 edges with surf1"
<< " faces" << endl;
label nIters2 = 0;
{
triSurfaceSearch querySurf1(surf1);
scalarField surf2PointTol
(
1e-3*edgeIntersections::minEdgeLength(surf2)
);
// Determine raw intersections
edgeCuts2 = edgeIntersections
(
surf2,
querySurf1,
surf2PointTol
);
// Shuffle a bit to resolve degenerate edge-face hits
{
pointField points2(surf2.points());
nIters2 =
edgeCuts2.removeDegenerates
(
5, // max iterations
surf2,
querySurf1,
surf2PointTol,
points2 // work array
);
if (nIters2 != 0)
{
// Update geometric quantities
surf2.movePoints(points2);
hasMoved2 = true;
}
}
}
if (nIters1 == 0 && nIters2 == 0)
{
Info<< "** Resolved all intersections to be proper edge-face pierce"
<< endl;
break;
}
}
if (hasMoved1)
{
fileName newFile("surf1.obj");
Info<< "Surface 1 has been moved. Writing to " << newFile
<< endl;
surf1.write(newFile);
}
if (hasMoved2)
{
fileName newFile("surf2.obj");
Info<< "Surface 2 has been moved. Writing to " << newFile
<< endl;
surf2.write(newFile);
}
return hasMoved1 || hasMoved2;
}
int main(int argc, char *argv[])
{
argList::validArgs.clear();
argList::noParallel();
argList::validArgs.append("action");
argList::validArgs.append("surface file");
argList::validArgs.append("surface file");
argList::addBoolOption
(
"perturb",
"Perturb surface points to escape degenerate intersections"
);
argList::addBoolOption
(
"invertedSpace",
"do the surfaces have inverted space orientation, "
"i.e. a point at infinity is considered inside. "
"This is only sensible for union and intersection."
);
# include "setRootCase.H"
# include "createTime.H"
word action(args.args()[1]);
HashTable<booleanSurface::booleanOpType> validActions;
validActions.insert("intersection", booleanSurface::INTERSECTION);
validActions.insert("union", booleanSurface::UNION);
validActions.insert("difference", booleanSurface::DIFFERENCE);
if (!validActions.found(action))
{
FatalErrorIn(args.executable())
<< "Unsupported action " << action << endl
<< "Supported actions:" << validActions.toc() << exit(FatalError);
}
fileName surf1Name(args[2]);
Info<< "Reading surface " << surf1Name << endl;
triSurface surf1(surf1Name);
Info<< surf1Name << " statistics:" << endl;
surf1.writeStats(Info);
Info<< endl;
fileName surf2Name(args[3]);
Info<< "Reading surface " << surf2Name << endl;
triSurface surf2(surf2Name);
Info<< surf2Name << " statistics:" << endl;
surf2.writeStats(Info);
Info<< endl;
edgeIntersections edge1Cuts;
edgeIntersections edge2Cuts;
bool invertedSpace = args.optionFound("invertedSpace");
if (invertedSpace && validActions[action] == booleanSurface::DIFFERENCE)
{
FatalErrorIn(args.executable())
<< "Inverted space only makes sense for union or intersection."
<< exit(FatalError);
}
if (args.optionFound("perturb"))
{
intersectSurfaces
(
surf1,
edge1Cuts,
surf2,
edge2Cuts
);
}
else
{
triSurfaceSearch querySurf2(surf2);
Info<< "Determining intersections of surf1 edges with surf2 faces"
<< endl;
edge1Cuts = edgeIntersections
(
surf1,
querySurf2,
1e-3*edgeIntersections::minEdgeLength(surf1)
);
triSurfaceSearch querySurf1(surf1);
Info<< "Determining intersections of surf2 edges with surf1 faces"
<< endl;
edge2Cuts = edgeIntersections
(
surf2,
querySurf1,
1e-3*edgeIntersections::minEdgeLength(surf2)
);
}
// Determine intersection edges
surfaceIntersection inter(surf1, edge1Cuts, surf2, edge2Cuts);
fileName sFeatFileName =
surf1Name.lessExt().name()
+ "_"
+ surf2Name.lessExt().name()
+ "_"
+ action;
label nFeatEds = inter.cutEdges().size();
vectorField normals(2*nFeatEds, vector::zero);
vectorField edgeDirections(nFeatEds, vector::zero);
labelListList edgeNormals(nFeatEds, labelList(2, -1));
triSurfaceSearch querySurf1(surf1);
triSurfaceSearch querySurf2(surf2);
OFstream normalFile(sFeatFileName + "_normals.obj");
scalar scale = 0.05*min
(
querySurf1.tree().bb().mag(),
querySurf2.tree().bb().mag()
);
forAll(inter.cutEdges(), i)
{
const edge& fE(inter.cutEdges()[i]);
point fEC = fE.centre(inter.cutPoints());
pointIndexHit nearest1 = querySurf1.tree().findNearest(fEC, sqr(GREAT));
pointIndexHit nearest2 = querySurf2.tree().findNearest(fEC, sqr(GREAT));
normals[2*i] = surf1.faceNormals()[nearest1.index()];
normals[2*i + 1] = surf2.faceNormals()[nearest2.index()];
edgeNormals[i][0] = 2*i;
edgeNormals[i][1] = 2*i + 1;
edgeDirections[i] = fE.vec(inter.cutPoints());
{
meshTools::writeOBJ(normalFile, inter.cutPoints()[fE.start()]);
meshTools::writeOBJ(normalFile, inter.cutPoints()[fE.end()]);
normalFile<< "l " << (5*i) + 1 << " " << (5*i) + 2<< endl;
meshTools::writeOBJ(normalFile, fEC);
meshTools::writeOBJ(normalFile, fEC + scale*normals[2*i]);
meshTools::writeOBJ(normalFile, fEC + scale*normals[2*i + 1]);
normalFile<< "l " << (5*i) + 3 << " " << (5*i) + 4 << endl;
normalFile<< "l " << (5*i) + 3 << " " << (5*i) + 5 << endl;
}
}
label internalStart = -1;
if (validActions[action] == booleanSurface::UNION)
{
if (!invertedSpace)
{
// All edges are internal
internalStart = 0;
}
else
{
// All edges are external
internalStart = nFeatEds;
}
}
else if (validActions[action] == booleanSurface::INTERSECTION)
{
if (!invertedSpace)
{
// All edges are external
internalStart = nFeatEds;
}
else
{
// All edges are internal
internalStart = 0;
}
}
else if (validActions[action] == booleanSurface::DIFFERENCE)
{
// All edges are external
internalStart = nFeatEds;
}
else
{
FatalErrorIn(args.executable())
<< "Unsupported booleanSurface:booleanOpType and space "
<< action << " " << invertedSpace
<< abort(FatalError);
}
// There are no feature points supported by surfaceIntersection
// Flat, open or multiple edges are assumed to be impossible
// Region edges are not explicitly supported by surfaceIntersection
extendedFeatureEdgeMesh feMesh
(
IOobject
(
sFeatFileName + ".extendedFeatureEdgeMesh",
runTime.constant(),
"featureEdgeMesh",
runTime,
IOobject::NO_READ,
IOobject::NO_WRITE
),
inter.cutPoints(),
inter.cutEdges(),
0, // concaveStart,
0, // mixedStart,
0, // nonFeatureStart,
internalStart, // internalStart,
nFeatEds, // flatStart,
nFeatEds, // openStart,
nFeatEds, // multipleStart,
normals,
edgeDirections,
edgeNormals,
labelListList(0), // featurePointNormals,
labelList(0) // regionEdges
);
feMesh.write();
feMesh.writeObj(sFeatFileName);
Info << "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -315,32 +315,12 @@ int main(int argc, char *argv[])
}
else
{
triPointRef tri
triQ[faceI] = triPointRef
(
surf.points()[f[0]],
surf.points()[f[1]],
surf.points()[f[2]]
);
vector ba(tri.b() - tri.a());
ba /= mag(ba) + VSMALL;
vector ca(tri.c() - tri.a());
ca /= mag(ca) + VSMALL;
if (mag(ba&ca) > 1-1E-3)
{
triQ[faceI] = SMALL;
}
else
{
triQ[faceI] = triPointRef
(
surf.points()[f[0]],
surf.points()[f[1]],
surf.points()[f[2]]
).quality();
}
).quality();
}
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -66,8 +66,8 @@ static void writeRegionOBJ
triSurface regionSurf(surf.subsetMesh(include, pointMap, faceMap));
//Pout<< "Region " << regionI << " surface:" << nl;
//regionSurf.writeStats(Pout);
Pout<< "Region " << regionI << " surface:" << nl;
regionSurf.writeStats(Pout);
regionSurf.write(regionName);
@ -97,7 +97,7 @@ static void splitTri
DynamicList<labelledTri>& tris
)
{
label oldNTris = tris.size();
//label oldNTris = tris.size();
label fp = findIndex(f, e[0]);
label fp1 = f.fcIndex(fp);
@ -175,7 +175,7 @@ static void splitTri
}
else
{
FatalErrorIn("splitTri")
FatalErrorIn("splitTri(..)")
<< "Edge " << e << " not part of triangle " << f
<< " fp:" << fp
<< " fp1:" << fp1
@ -183,13 +183,13 @@ static void splitTri
<< abort(FatalError);
}
Pout<< "Split face " << f << " along edge " << e
<< " into triangles:" << endl;
for (label i = oldNTris; i < tris.size(); i++)
{
Pout<< " " << tris[i] << nl;
}
//Pout<< "Split face " << f << " along edge " << e
// << " into triangles:" << endl;
//
//for (label i = oldNTris; i < tris.size(); i++)
//{
// Pout<< " " << tris[i] << nl;
//}
}
@ -206,14 +206,14 @@ static bool insertSorted
{
if (findIndex(sortedVerts, vertI) != -1)
{
FatalErrorIn("insertSorted") << "Trying to insert vertex " << vertI
FatalErrorIn("insertSorted(..)") << "Trying to insert vertex " << vertI
<< " which is already in list of sorted vertices "
<< sortedVerts << abort(FatalError);
}
if (weight <= 0 || weight >= 1)
{
FatalErrorIn("insertSorted") << "Trying to insert vertex " << vertI
FatalErrorIn("insertSorted(..)") << "Trying to insert vertex " << vertI
<< " with illegal weight " << weight
<< " into list of sorted vertices "
<< sortedVerts << abort(FatalError);
@ -228,7 +228,7 @@ static bool insertSorted
if (mag(w - weight) < SMALL)
{
WarningIn("insertSorted")
WarningIn("insertSorted(..)")
<< "Trying to insert weight " << weight << " which is close to"
<< " existing weight " << w << " in " << sortedWeights
<< endl;
@ -263,64 +263,103 @@ static bool insertSorted
}
// Is triangle candidate for collapse? Small height or small quality
bool isSliver
(
const triSurface& surf,
const scalar minLen,
const scalar minQuality,
const label faceI,
const label edgeI
)
{
const pointField& localPoints = surf.localPoints();
// Check
// - opposite vertex projects onto base edge
// - normal distance is small
// - or triangle quality is small
label opposite0 =
triSurfaceTools::oppositeVertex
(
surf,
faceI,
edgeI
);
const edge& e = surf.edges()[edgeI];
const labelledTri& f = surf[faceI];
pointHit pHit =
e.line(localPoints).nearestDist
(
localPoints[opposite0]
);
if
(
pHit.hit()
&& (
pHit.distance() < minLen
|| f.tri(surf.points()).quality() < minQuality
)
)
{
// Remove faceI and split all other faces using this
// edge. This is done by 'replacing' the edgeI with the
// opposite0 vertex
//Pout<< "Splitting face " << faceI << " since distance "
// << pHit.distance()
// << " from vertex " << opposite0
// << " to edge " << edgeI
// << " points "
// << localPoints[e[0]]
// << localPoints[e[1]]
// << " is too small or triangle quality "
// << f.tri(surf.points()).quality()
// << " too small." << endl;
return true;
}
else
{
return false;
}
}
// Mark all faces that are going to be collapsed.
// faceToEdge: per face -1 or the base edge of the face.
static void markCollapsedFaces
(
const triSurface& surf,
const scalar minLen,
const scalar minQuality,
labelList& faceToEdge
)
{
faceToEdge.setSize(surf.size());
faceToEdge = -1;
const pointField& localPoints = surf.localPoints();
const labelListList& edgeFaces = surf.edgeFaces();
forAll(edgeFaces, edgeI)
{
const edge& e = surf.edges()[edgeI];
const labelList& eFaces = surf.edgeFaces()[edgeI];
forAll(eFaces, i)
{
label faceI = eFaces[i];
// Check distance of vertex to edge.
label opposite0 =
triSurfaceTools::oppositeVertex
(
surf,
faceI,
edgeI
);
bool isCandidate = isSliver(surf, minLen, minQuality, faceI, edgeI);
pointHit pHit =
e.line(localPoints).nearestDist
(
localPoints[opposite0]
);
if (pHit.hit() && pHit.distance() < minLen)
if (isCandidate)
{
// Remove faceI and split all other faces using this
// edge. This is done by 'replacing' the edgeI with the
// opposite0 vertex
Pout<< "Splitting face " << faceI << " since distance "
<< pHit.distance()
<< " from vertex " << opposite0
<< " to edge " << edgeI
<< " points "
<< localPoints[e[0]]
<< localPoints[e[1]]
<< " is too small" << endl;
// Mark face as being collapsed
if (faceToEdge[faceI] != -1)
{
FatalErrorIn("markCollapsedFaces")
FatalErrorIn("markCollapsedFaces(..)")
<< "Cannot collapse face " << faceI << " since "
<< " is marked to be collapsed both to edge "
<< faceToEdge[faceI] << " and " << edgeI
@ -347,7 +386,7 @@ static void markRegion
{
if (faceToEdge[faceI] == -1 || collapseRegion[faceI] != -1)
{
FatalErrorIn("markRegion")
FatalErrorIn("markRegion(..)")
<< "Problem : crossed into uncollapsed/regionized face"
<< abort(FatalError);
}
@ -383,7 +422,7 @@ static void markRegion
}
else if (collapseRegion[nbrFaceI] != regionI)
{
FatalErrorIn("markRegion")
FatalErrorIn("markRegion(..)")
<< "Edge:" << edgeI << " between face " << faceI
<< " with region " << regionI
<< " and face " << nbrFaceI
@ -411,8 +450,8 @@ static label markRegions
{
if (collapseRegion[faceI] == -1 && faceToEdge[faceI] != -1)
{
Pout<< "markRegions : Marking region:" << regionI
<< " starting from face " << faceI << endl;
//Pout<< "markRegions : Marking region:" << regionI
// << " starting from face " << faceI << endl;
// Collapsed face. Mark connected region with current region number
markRegion(surf, faceToEdge, regionI++, faceI, collapseRegion);
@ -728,7 +767,12 @@ static void getSplitVerts
}
label collapseBase(triSurface& surf, const scalar minLen)
label collapseBase
(
triSurface& surf,
const scalar minLen,
const scalar minQuality
)
{
label nTotalSplit = 0;
@ -743,7 +787,7 @@ label collapseBase(triSurface& surf, const scalar minLen)
labelList faceToEdge(surf.size(), -1);
// Calculate faceToEdge (face collapses)
markCollapsedFaces(surf, minLen, faceToEdge);
markCollapsedFaces(surf, minLen, minQuality, faceToEdge);
// Find regions of connected collapsed faces
@ -754,8 +798,8 @@ label collapseBase(triSurface& surf, const scalar minLen)
label nRegions = markRegions(surf, faceToEdge, collapseRegion);
Pout<< "Detected " << nRegions << " regions of faces to be collapsed"
<< nl << endl;
//Pout<< "Detected " << nRegions << " regions of faces to be collapsed"
// << nl << endl;
// Pick up all vertices on outside of region
labelListList outsideVerts
@ -772,10 +816,10 @@ label collapseBase(triSurface& surf, const scalar minLen)
{
spanPoints[regionI] = getSpanPoints(surf, outsideVerts[regionI]);
Pout<< "For region " << regionI << " found extrema at points "
<< surf.localPoints()[spanPoints[regionI][0]]
<< surf.localPoints()[spanPoints[regionI][1]]
<< endl;
//Pout<< "For region " << regionI << " found extrema at points "
// << surf.localPoints()[spanPoints[regionI][0]]
// << surf.localPoints()[spanPoints[regionI][1]]
// << endl;
// Project all non-span points onto the span edge.
projectNonSpanPoints
@ -787,21 +831,21 @@ label collapseBase(triSurface& surf, const scalar minLen)
orderedWeights[regionI]
);
Pout<< "For region:" << regionI
<< " span:" << spanPoints[regionI]
<< " orderedVerts:" << orderedVertices[regionI]
<< " orderedWeights:" << orderedWeights[regionI]
<< endl;
//Pout<< "For region:" << regionI
// << " span:" << spanPoints[regionI]
// << " orderedVerts:" << orderedVertices[regionI]
// << " orderedWeights:" << orderedWeights[regionI]
// << endl;
writeRegionOBJ
(
surf,
regionI,
collapseRegion,
outsideVerts[regionI]
);
//writeRegionOBJ
//(
// surf,
// regionI,
// collapseRegion,
// outsideVerts[regionI]
//);
Pout<< endl;
//Pout<< endl;
}
@ -864,20 +908,19 @@ label collapseBase(triSurface& surf, const scalar minLen)
// Split edge using splitVerts. All non-collapsed triangles
// using edge will get split.
{
const pointField& localPoints = surf.localPoints();
Pout<< "edge " << edgeI << ' ' << e
<< " points "
<< localPoints[e[0]] << ' ' << localPoints[e[1]]
<< " split into edges with extra points:"
<< endl;
forAll(splitVerts, i)
{
Pout<< " " << splitVerts[i] << " weight "
<< splitWeights[i] << nl;
}
}
//{
// const pointField& localPoints = surf.localPoints();
// Pout<< "edge " << edgeI << ' ' << e
// << " points "
// << localPoints[e[0]] << ' ' << localPoints[e[1]]
// << " split into edges with extra points:"
// << endl;
// forAll(splitVerts, i)
// {
// Pout<< " " << splitVerts[i] << " weight "
// << splitWeights[i] << nl;
// }
//}
const labelList& eFaces = surf.edgeFaces()[edgeI];
@ -914,7 +957,8 @@ label collapseBase(triSurface& surf, const scalar minLen)
}
}
Pout<< "collapseBase : splitting " << nSplit << " triangles"
Info<< "collapseBase : collapsing " << nSplit
<< " triangles by splitting their base edge."
<< endl;
nTotalSplit += nSplit;
@ -927,15 +971,15 @@ label collapseBase(triSurface& surf, const scalar minLen)
// Pack the triangles
newTris.shrink();
Pout<< "Resetting surface from " << surf.size() << " to "
<< newTris.size() << " triangles" << endl;
//Pout<< "Resetting surface from " << surf.size() << " to "
// << newTris.size() << " triangles" << endl;
surf = triSurface(newTris, surf.patches(), surf.localPoints());
{
fileName fName("bla" + name(iter) + ".obj");
Pout<< "Writing surf to " << fName << endl;
surf.write(fName);
}
//{
// fileName fName("bla" + name(iter) + ".obj");
// Pout<< "Writing surf to " << fName << endl;
// surf.write(fName);
//}
iter++;
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -41,9 +41,14 @@ using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Keep collapsing all triangles whose height is < minLen.
//- Keep collapsing all triangles whose height is < minLen or quality < minQ.
// Returns number of triangles collapsed.
label collapseBase(triSurface& surf, const scalar minLen);
label collapseBase
(
triSurface& surf,
const scalar minLen,
const scalar minQuality
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -121,8 +121,8 @@ label collapseEdge(triSurface& surf, const scalar minLen)
pointMap[v1] = v;
newPoints[v] = 0.5*(localPoints[v1] + localPoints[v]);
Pout<< "Collapsing triange " << faceI << " to edge mid "
<< newPoints[v] << endl;
//Pout<< "Collapsing triange " << faceI
// << " to edge mid " << newPoints[v] << endl;
nCollapsed++;
okToCollapse[faceI] = false;
@ -136,7 +136,8 @@ label collapseEdge(triSurface& surf, const scalar minLen)
}
}
Pout<< "collapseEdge : collapsing " << nCollapsed << " triangles"
Info<< "collapseEdge : collapsing " << nCollapsed
<< " triangles to a single edge."
<< endl;
nTotalCollapsed += nCollapsed;

View File

@ -50,6 +50,7 @@ int main(int argc, char *argv[])
argList::noParallel();
argList::validArgs.append("surfaceFile");
argList::validArgs.append("min length");
argList::validArgs.append("min quality");
argList::validArgs.append("output surfaceFile");
argList::addBoolOption
(
@ -60,10 +61,13 @@ int main(int argc, char *argv[])
const fileName inFileName = args[1];
const scalar minLen = args.argRead<scalar>(2);
const fileName outFileName = args[3];
const scalar minQuality = args.argRead<scalar>(3);
const fileName outFileName = args[4];
Info<< "Reading surface " << inFileName << nl
<< "Collapsing all triangles with edges or heights < " << minLen << nl
<< "Collapsing all triangles with" << nl
<< " edges or heights < " << minLen << nl
<< " quality < " << minQuality << nl
<< "Writing result to " << outFileName << nl << endl;
@ -90,7 +94,7 @@ int main(int argc, char *argv[])
}
while (true)
{
label nSplitEdge = collapseBase(surf, minLen);
label nSplitEdge = collapseBase(surf, minLen, minQuality);
if (nSplitEdge == 0)
{

View File

@ -0,0 +1,203 @@
#ifndef CGAL_PSURF_RINGS_H_
#define CGAL_PSURF_RINGS_H_
// This file adapted from
// CGAL-3.7/examples/Jet_fitting_3//PolyhedralSurf_rings.h
// Licensed under CGAL-3.7/LICENSE.FREE_USE
// Copyright (c) 1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007
// Utrecht University (The Netherlands), ETH Zurich (Switzerland), Freie
// Universitaet Berlin (Germany), INRIA Sophia-Antipolis (France),
// Martin-Luther-University Halle-Wittenberg (Germany), Max-Planck-Institute
// Saarbruecken (Germany), RISC Linz (Austria), and Tel-Aviv University
// (Israel). All rights reserved.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <cassert>
using namespace std;
template
<
class TPoly,
class VertexPropertyMap
>
class T_PolyhedralSurf_rings
{
protected:
//Polyhedron
typedef typename TPoly::Vertex Vertex;
typedef typename TPoly::Halfedge Halfedge;
typedef typename TPoly::Facet Facet;
typedef typename TPoly::Halfedge_around_vertex_circulator
Halfedge_around_vertex_circulator;
typedef typename TPoly::Vertex_iterator Vertex_iterator;
//vertex indices are initialised to -1
static void reset_ring_indices(std::vector < Vertex * >&vces,
VertexPropertyMap& vpm);
// i >= 1; from a start vertex on the current i-1 ring, push non-visited
// neighbors of start in the nextRing and set indices to i. Also add these
// vertices in all.
static void push_neighbours_of(Vertex * start, int ith,
std::vector < Vertex * >&nextRing,
std::vector < Vertex * >&all,
VertexPropertyMap& vpm);
// i >= 1, from a currentRing i-1, collect all neighbors, set indices
// to i and store them in nextRing and all.
static void collect_ith_ring(int ith,
std::vector < Vertex * >&currentRing,
std::vector < Vertex * >&nextRing,
std::vector < Vertex * >&all,
VertexPropertyMap& vpm);
public:
// collect i>=1 rings : all neighbours up to the ith ring,
static void
collect_i_rings(Vertex* v,
int ring_i,
std::vector < Vertex * >& all,
VertexPropertyMap& vpm);
//collect enough rings (at least 1), to get at least min_nb of neighbors
static void
collect_enough_rings(Vertex* v,
unsigned int min_nb,
std::vector < Vertex * >& all,
VertexPropertyMap& vpm);
};
////IMPLEMENTATION////////////////////////////////////////////////////
template < class TPoly , class VertexPropertyMap>
void T_PolyhedralSurf_rings <TPoly, VertexPropertyMap>::
push_neighbours_of(Vertex * start, int ith,
std::vector < Vertex * >&nextRing,
std::vector < Vertex * >&all,
VertexPropertyMap& vpm)
{
Vertex *v;
Halfedge_around_vertex_circulator
hedgeb = start->vertex_begin(), hedgee = hedgeb;
CGAL_For_all(hedgeb, hedgee)
{
v = &*(hedgeb->opposite()->vertex());
if(get(vpm, v) != -1) continue;//if visited: next
put(vpm, v, ith);
nextRing.push_back(v);
all.push_back(v);
}
}
template <class TPoly, class VertexPropertyMap>
void T_PolyhedralSurf_rings <TPoly, VertexPropertyMap>::
collect_ith_ring(int ith, std::vector < Vertex * >&currentRing,
std::vector < Vertex * >&nextRing,
std::vector < Vertex * >&all,
VertexPropertyMap& vpm)
{
typename std::vector < Vertex * >::iterator
itb = currentRing.begin(), ite = currentRing.end();
CGAL_For_all(itb, ite) push_neighbours_of(*itb, ith, nextRing, all, vpm);
}
template <class TPoly, class VertexPropertyMap>
void T_PolyhedralSurf_rings <TPoly, VertexPropertyMap>::
reset_ring_indices(std::vector < Vertex * >&vces,
VertexPropertyMap& vpm)
{
typename std::vector < Vertex * >::iterator
itb = vces.begin(), ite = vces.end();
CGAL_For_all(itb, ite) put(vpm, *itb, -1);
}
template <class TPoly, class VertexPropertyMap>
void T_PolyhedralSurf_rings <TPoly, VertexPropertyMap>::
collect_i_rings(Vertex* v,
int ring_i,
std::vector < Vertex * >& all,
VertexPropertyMap& vpm)
{
std::vector<Vertex*> current_ring, next_ring;
std::vector<Vertex*> *p_current_ring, *p_next_ring;
assert(ring_i >= 1);
//initialize
p_current_ring = &current_ring;
p_next_ring = &next_ring;
put(vpm, v, 0);
current_ring.push_back(v);
all.push_back(v);
for (int i=1; i<=ring_i; i++)
{
collect_ith_ring(i, *p_current_ring, *p_next_ring, all, vpm);
//next round must be launched from p_nextRing...
p_current_ring->clear();
std::swap(p_current_ring, p_next_ring);
}
//clean up
reset_ring_indices(all, vpm);
}
template <class TPoly, class VertexPropertyMap>
void T_PolyhedralSurf_rings <TPoly, VertexPropertyMap>::
collect_enough_rings(Vertex* v,
unsigned int min_nb,
std::vector < Vertex * >& all,
VertexPropertyMap& vpm)
{
std::vector<Vertex*> current_ring, next_ring;
std::vector<Vertex*> *p_current_ring, *p_next_ring;
//initialize
p_current_ring = &current_ring;
p_next_ring = &next_ring;
put(vpm, v, 0);
current_ring.push_back(v);
all.push_back(v);
int i = 1;
while ( (all.size() < min_nb) && (p_current_ring->size() != 0) )
{
collect_ith_ring(i, *p_current_ring, *p_next_ring, all, vpm);
//next round must be launched from p_nextRing...
p_current_ring->clear();
std::swap(p_current_ring, p_next_ring);
i++;
}
//clean up
reset_ring_indices(all, vpm);
}
#endif

View File

@ -0,0 +1,89 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "buildCGALPolyhedron.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::buildCGALPolyhedron::buildCGALPolyhedron
(
const Foam::triSurface& surf
)
:
CGAL::Modifier_base<HalfedgeDS>(),
surf_(surf)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::buildCGALPolyhedron::~buildCGALPolyhedron()
{}
// * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
void Foam::buildCGALPolyhedron::operator()
(
HalfedgeDS& hds
)
{
typedef HalfedgeDS::Traits Traits;
typedef Traits::Point_3 Point;
// Postcondition: `hds' is a valid polyhedral surface.
CGAL::Polyhedron_incremental_builder_3<HalfedgeDS> B(hds, false);
B.begin_surface
(
surf_.points().size(), // n points
surf_.size(), // n facets
2*surf_.edges().size() // n halfedges
);
forAll(surf_.points(), pI)
{
const Foam::point& p = surf_.points()[pI];
B.add_vertex(Point(p.x(), p.y(), p.z()));
}
forAll(surf_, fI)
{
B.begin_facet();
B.add_vertex_to_facet(surf_[fI][0]);
B.add_vertex_to_facet(surf_[fI][1]);
B.add_vertex_to_facet(surf_[fI][2]);
B.end_facet();
}
B.end_surface();
}
// ************************************************************************* //

View File

@ -0,0 +1,106 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::buildCGALPolyhedron
Description
Convert a triSurface into a CGAL Polyhedron
SourceFiles
buildCGALPolyhedron.C
\*---------------------------------------------------------------------------*/
#ifndef buildCGALPolyhedron_H
#define buildCGALPolyhedron_H
#include "triSurface.H"
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Polyhedron_incremental_builder_3.h>
#include <CGAL/Polyhedron_3.h>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
typedef Polyhedron::HalfedgeDS HalfedgeDS;
typedef Polyhedron::Vertex Vertex;
typedef Polyhedron::Vertex_iterator Vertex_iterator;
typedef Kernel::Point_3 Point_3;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class buildCGALPolyhedron Declaration
\*---------------------------------------------------------------------------*/
class buildCGALPolyhedron
:
public CGAL::Modifier_base<HalfedgeDS>
{
// Private data
//- Reference to triSurface to convert
const Foam::triSurface& surf_;
// Private Member Functions
//- Disallow default bitwise copy construct
buildCGALPolyhedron(const buildCGALPolyhedron&);
//- Disallow default bitwise assignment
void operator=(const buildCGALPolyhedron&);
public:
// Constructors
//- Construct with reference to triSurface
buildCGALPolyhedron(const triSurface& surf);
//- Destructor
~buildCGALPolyhedron();
// Member Operators
//- operator() of this `modifier' called by delegate function of
// Polyhedron
void operator()(HalfedgeDS& hds);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,3 +1,4 @@
surfaceFeatureExtract.C
CGALPolyhedron/buildCGALPolyhedron.C
EXE = $(FOAM_APPBIN)/surfaceFeatureExtract

View File

@ -1,9 +1,29 @@
EXE_FROUNDING_MATH = -frounding-math
EXE_NDEBUG = -DNDEBUG
USE_F2C = -DCGAL_USE_F2C
include $(GENERAL_RULES)/CGAL
EXE_INC = \
${EXE_FROUNDING_MATH} \
${EXE_NDEBUG} \
${USE_F2C} \
${CGAL_INC} \
-ICGALPolyhedron \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/edgeMesh/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/surfMesh/lnInclude \
-I$(LIB_SRC)/sampling/lnInclude
EXE_LIBS = \
$(CGAL_LIBS) \
-L$(CGAL_ARCH_PATH)/lib \
-llapack \
-lblas \
-lCGAL \
-lmeshTools \
-ledgeMesh \
-ltriSurface
-ltriSurface \
-lsampling

View File

@ -40,7 +40,19 @@ Description
#include "treeBoundBox.H"
#include "meshTools.H"
#include "OFstream.H"
#include "triSurfaceMesh.H"
#include "vtkSurfaceWriter.H"
#include "triSurfaceFields.H"
#include "unitConversion.H"
#include "indexedOctree.H"
#include "treeDataEdge.H"
#include "unitConversion.H"
#include "buildCGALPolyhedron.H"
#include "CGALPolyhedronRings.H"
#include <CGAL/Monge_via_jet_fitting.h>
#include <CGAL/Lapack/Linear_algebra_lapack.h>
#include <CGAL/property_map.h>
using namespace Foam;
@ -91,6 +103,201 @@ void deleteBox
}
void drawHitProblem
(
label fI,
const triSurface& surf,
const pointField& start,
const pointField& faceCentres,
const pointField& end,
const List<pointIndexHit>& hitInfo
)
{
Info<< nl << "# findLineAll did not hit its own face."
<< nl << "# fI " << fI
<< nl << "# start " << start[fI]
<< nl << "# f centre " << faceCentres[fI]
<< nl << "# end " << end[fI]
<< nl << "# hitInfo " << hitInfo
<< endl;
meshTools::writeOBJ(Info, start[fI]);
meshTools::writeOBJ(Info, faceCentres[fI]);
meshTools::writeOBJ(Info, end[fI]);
Info<< "l 1 2 3" << endl;
meshTools::writeOBJ(Info, surf.points()[surf[fI][0]]);
meshTools::writeOBJ(Info, surf.points()[surf[fI][1]]);
meshTools::writeOBJ(Info, surf.points()[surf[fI][2]]);
Info<< "f 4 5 6" << endl;
forAll(hitInfo, hI)
{
label hFI = hitInfo[hI].index();
meshTools::writeOBJ(Info, surf.points()[surf[hFI][0]]);
meshTools::writeOBJ(Info, surf.points()[surf[hFI][1]]);
meshTools::writeOBJ(Info, surf.points()[surf[hFI][2]]);
Info<< "f "
<< 3*hI + 7 << " "
<< 3*hI + 8 << " "
<< 3*hI + 9
<< endl;
}
}
scalarField calcCurvature(const triSurface& surf)
{
scalarField k(surf.points().size(), 0);
Polyhedron P;
buildCGALPolyhedron convert(surf);
P.delegate(convert);
// Info<< "Created CGAL Polyhedron with " << label(P.size_of_vertices())
// << " vertices and " << label(P.size_of_facets())
// << " facets. " << endl;
// The rest of this function adapted from
// CGAL-3.7/examples/Jet_fitting_3/Mesh_estimation.cpp
// Licensed under CGAL-3.7/LICENSE.FREE_USE
// Copyright (c) 1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007
// Utrecht University (The Netherlands), ETH Zurich (Switzerland), Freie
// Universitaet Berlin (Germany), INRIA Sophia-Antipolis (France),
// Martin-Luther-University Halle-Wittenberg (Germany), Max-Planck-Institute
// Saarbruecken (Germany), RISC Linz (Austria), and Tel-Aviv University
// (Israel). All rights reserved.
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
// THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//Vertex property map, with std::map
typedef std::map<Vertex*, int> Vertex2int_map_type;
typedef boost::associative_property_map< Vertex2int_map_type >
Vertex_PM_type;
typedef T_PolyhedralSurf_rings<Polyhedron, Vertex_PM_type > Poly_rings;
typedef CGAL::Monge_via_jet_fitting<Kernel> Monge_via_jet_fitting;
typedef Monge_via_jet_fitting::Monge_form Monge_form;
std::vector<Point_3> in_points; //container for data points
// default parameter values and global variables
unsigned int d_fitting = 2;
unsigned int d_monge = 2;
unsigned int min_nb_points = (d_fitting + 1)*(d_fitting + 2)/2;
//initialize the tag of all vertices to -1
Vertex_iterator vitb = P.vertices_begin();
Vertex_iterator vite = P.vertices_end();
Vertex2int_map_type vertex2props;
Vertex_PM_type vpm(vertex2props);
CGAL_For_all(vitb, vite)
{
put(vpm, &(*vitb), -1);
}
vite = P.vertices_end();
label vertI = 0;
for (vitb = P.vertices_begin(); vitb != vite; vitb++)
{
//initialize
Vertex* v = &(*vitb);
//gather points around the vertex using rings
// From: gather_fitting_points(v, in_points, vpm);
{
std::vector<Vertex*> gathered;
in_points.clear();
Poly_rings::collect_enough_rings(v, min_nb_points, gathered, vpm);
//store the gathered points
std::vector<Vertex*>::iterator itb = gathered.begin();
std::vector<Vertex*>::iterator ite = gathered.end();
CGAL_For_all(itb, ite)
{
in_points.push_back((*itb)->point());
}
}
//skip if the nb of points is to small
if ( in_points.size() < min_nb_points )
{
std::cerr
<< "not enough pts for fitting this vertex"
<< in_points.size()
<< std::endl;
continue;
}
// perform the fitting
Monge_via_jet_fitting monge_fit;
Monge_form monge_form = monge_fit
(
in_points.begin(),
in_points.end(),
d_fitting,
d_monge
);
// std::cout<< monge_form << std::endl;
// std::cout<< "k1 " << monge_form.principal_curvatures(0) << std::endl;
// std::cout<< "k2 " << monge_form.principal_curvatures(1) << std::endl;
// std::vector<Point_3>::iterator itbp = in_points.begin();
// std::vector<Point_3>::iterator itep = in_points.end();
// std::cout << "in_points list : " << std::endl;
// for (; itbp != itep; itbp++)
// {
// std::cout << *itbp << std::endl;
// }
// std::cout << "--- vertex " << vertI
// << " : " << v->point() << std::endl
// << "number of points used : " << in_points.size()
// << std::endl;
k[vertI++] = Foam::sqrt
(
sqr(monge_form.principal_curvatures(0))
+ sqr(monge_form.principal_curvatures(1))
);
}
return k;
}
// Unmark non-manifold edges if individual triangles are not features
void unmarkBaffles
(
@ -111,7 +318,7 @@ void unmarkBaffles
{
label i0 = eFaces[0];
//const labelledTri& f0 = surf[i0];
const vector& n0 = surf.faceNormals()[i0];
const Foam::vector& n0 = surf.faceNormals()[i0];
//Pout<< "edge:" << edgeI << " n0:" << n0 << endl;
@ -120,7 +327,7 @@ void unmarkBaffles
for (label i = 1; i < eFaces.size(); i++)
{
//const labelledTri& f = surf[i];
const vector& n = surf.faceNormals()[eFaces[i]];
const Foam::vector& n = surf.faceNormals()[eFaces[i]];
//Pout<< " mag(n&n0): " << mag(n&n0) << endl;
@ -193,15 +400,63 @@ int main(int argc, char *argv[])
"writeObj",
"write extendedFeatureEdgeMesh obj files"
);
argList::addBoolOption
(
"writeVTK",
"write extendedFeatureEdgeMesh vtk files"
);
argList::addBoolOption
(
"calcCurvature",
"calculate curvature and closeness fields"
);
argList::addOption
(
"closeness",
"scalar",
"span to look for surface closeness"
);
argList::addOption
(
"featureProximity",
"scalar",
"distance to look for close features"
);
argList::addBoolOption
(
"writeVTK",
"write surface property VTK files"
);
argList::addBoolOption
(
"manifoldEdgesOnly",
"remove any non-manifold (open or more than two connected faces) edges"
);
# include "setRootCase.H"
# include "createTime.H"
Info<< "Feature line extraction is only valid on closed manifold surfaces."
<< endl;
bool writeVTK = args.optionFound("writeVTK");
bool writeObj = args.optionFound("writeObj");
bool curvature = args.optionFound("curvature");
if (curvature && env("FOAM_SIGFPE"))
{
WarningIn(args.executable())
<< "Detected floating point exception trapping (FOAM_SIGFPE)."
<< " This might give" << nl
<< " problems when calculating curvature on straight angles"
<< " (infinite curvature)" << nl
<< " Switch it off in case of problems." << endl;
}
Info<< "Feature line extraction is only valid on closed manifold surfaces."
<< endl;
const fileName surfFileName = args[1];
const fileName outFileName = args[2];
@ -221,6 +476,12 @@ int main(int argc, char *argv[])
surf.writeStats(Info);
Info<< endl;
faceList faces(surf.size());
forAll(surf, fI)
{
faces[fI] = surf[fI].triFaceFace();
}
// Either construct features from surface&featureangle or read set.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -334,11 +595,25 @@ int main(int argc, char *argv[])
);
}
if (args.optionFound("manifoldEdgesOnly"))
{
Info<< "Removing all non-manifold edges" << endl;
forAll(edgeStat, edgeI)
{
if (surf.edgeFaces()[edgeI].size() != 2)
{
edgeStat[edgeI] = surfaceFeatures::NONE;
}
}
}
surfaceFeatures newSet(surf);
newSet.setFromStatus(edgeStat);
Info<< endl << "Writing trimmed features to " << outFileName << endl;
newSet.write(outFileName);
//Info<< endl << "Writing trimmed features to " << outFileName << endl;
//newSet.write(outFileName);
// Info<< endl << "Writing edge objs." << endl;
// newSet.writeObj("final");
@ -397,6 +672,358 @@ int main(int argc, char *argv[])
bfeMesh.regIOobject::write();
}
triSurfaceMesh searchSurf
(
IOobject
(
sFeatFileName + ".closeness",
runTime.constant(),
"extendedFeatureEdgeMesh",
runTime,
IOobject::NO_READ,
IOobject::NO_WRITE
),
surf
);
if (!curvature)
{
Info<< "End\n" << endl;
return 0;
}
// Find close features
// // Dummy trim operation to mark features
// labelList featureEdgeIndexing = newSet.trimFeatures(-GREAT, 0);
// scalarField surfacePtFeatureIndex(surf.points().size(), -1);
// forAll(newSet.featureEdges(), eI)
// {
// const edge& e = surf.edges()[newSet.featureEdges()[eI]];
// surfacePtFeatureIndex[surf.meshPoints()[e.start()]] =
// featureEdgeIndexing[newSet.featureEdges()[eI]];
// surfacePtFeatureIndex[surf.meshPoints()[e.end()]] =
// featureEdgeIndexing[newSet.featureEdges()[eI]];
// }
// if (writeVTK)
// {
// vtkSurfaceWriter().write
// (
// runTime.constant()/"triSurface", // outputDir
// sFeatFileName, // surfaceName
// surf.points(),
// faces,
// "surfacePtFeatureIndex", // fieldName
// surfacePtFeatureIndex,
// true, // isNodeValues
// true // verbose
// );
// }
// Random rndGen(343267);
// treeBoundBox surfBB
// (
// treeBoundBox(searchSurf.bounds()).extend(rndGen, 1e-4)
// );
// surfBB.min() -= Foam::point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
// surfBB.max() += Foam::point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
// indexedOctree<treeDataEdge> ftEdTree
// (
// treeDataEdge
// (
// false,
// surf.edges(),
// surf.localPoints(),
// newSet.featureEdges()
// ),
// surfBB,
// 8, // maxLevel
// 10, // leafsize
// 3.0 // duplicity
// );
// labelList nearPoints = ftEdTree.findBox
// (
// treeBoundBox
// (
// sPt - featureSearchSpan*Foam::vector::one,
// sPt + featureSearchSpan*Foam::vector::one
// )
// );
Info<< "Examine curvature, feature proximity and internal and "
<< "external closeness." << endl;
// Internal and external closeness
// Prepare start and end points for intersection tests
const vectorField& normals = searchSurf.faceNormals();
scalar span = searchSurf.bounds().mag();
args.optionReadIfPresent("closeness", span);
scalar externalAngleTolerance = 10;
scalar externalToleranceCosAngle = Foam::cos
(
degToRad(180 - externalAngleTolerance)
);
scalar internalAngleTolerance = 45;
scalar internalToleranceCosAngle = Foam::cos
(
degToRad(180 - internalAngleTolerance)
);
Info<< "externalToleranceCosAngle: " << externalToleranceCosAngle << nl
<< "internalToleranceCosAngle: " << internalToleranceCosAngle
<< endl;
// Info<< "span " << span << endl;
pointField start = searchSurf.faceCentres() - span*normals;
pointField end = searchSurf.faceCentres() + span*normals;
const pointField& faceCentres = searchSurf.faceCentres();
List<List<pointIndexHit> > allHitInfo;
// Find all intersections (in order)
searchSurf.findLineAll(start, end, allHitInfo);
scalarField internalCloseness(start.size(), GREAT);
scalarField externalCloseness(start.size(), GREAT);
forAll(allHitInfo, fI)
{
const List<pointIndexHit>& hitInfo = allHitInfo[fI];
if (hitInfo.size() < 1)
{
drawHitProblem(fI, surf, start, faceCentres, end, hitInfo);
// FatalErrorIn(args.executable())
// << "findLineAll did not hit its own face."
// << exit(FatalError);
}
else if (hitInfo.size() == 1)
{
if (!hitInfo[0].hit())
{
// FatalErrorIn(args.executable())
// << "findLineAll did not hit any face."
// << exit(FatalError);
}
else if (hitInfo[0].index() != fI)
{
drawHitProblem(fI, surf, start, faceCentres, end, hitInfo);
// FatalErrorIn(args.executable())
// << "findLineAll did not hit its own face."
// << exit(FatalError);
}
}
else
{
label ownHitI = -1;
forAll(hitInfo, hI)
{
// Find the hit on the triangle that launched the ray
if (hitInfo[hI].index() == fI)
{
ownHitI = hI;
break;
}
}
if (ownHitI < 0)
{
drawHitProblem(fI, surf, start, faceCentres, end, hitInfo);
// FatalErrorIn(args.executable())
// << "findLineAll did not hit its own face."
// << exit(FatalError);
}
else if (ownHitI == 0)
{
// There are no internal hits, the first hit is the closest
// external hit
if
(
(normals[fI] & normals[hitInfo[ownHitI + 1].index()])
< externalToleranceCosAngle
)
{
externalCloseness[fI] = mag
(
faceCentres[fI] - hitInfo[ownHitI + 1].hitPoint()
);
}
}
else if (ownHitI == hitInfo.size() - 1)
{
// There are no external hits, the last but one hit is the
// closest internal hit
if
(
(normals[fI] & normals[hitInfo[ownHitI - 1].index()])
< internalToleranceCosAngle
)
{
internalCloseness[fI] = mag
(
faceCentres[fI] - hitInfo[ownHitI - 1].hitPoint()
);
}
}
else
{
if
(
(normals[fI] & normals[hitInfo[ownHitI + 1].index()])
< externalToleranceCosAngle
)
{
externalCloseness[fI] = mag
(
faceCentres[fI] - hitInfo[ownHitI + 1].hitPoint()
);
}
if
(
(normals[fI] & normals[hitInfo[ownHitI - 1].index()])
< internalToleranceCosAngle
)
{
internalCloseness[fI] = mag
(
faceCentres[fI] - hitInfo[ownHitI - 1].hitPoint()
);
}
}
}
}
triSurfaceScalarField internalClosenessField
(
IOobject
(
sFeatFileName + ".internalCloseness",
runTime.constant(),
"extendedFeatureEdgeMesh",
runTime,
IOobject::NO_READ,
IOobject::NO_WRITE
),
surf,
dimLength,
internalCloseness
);
internalClosenessField.write();
triSurfaceScalarField externalClosenessField
(
IOobject
(
sFeatFileName + ".externalCloseness",
runTime.constant(),
"extendedFeatureEdgeMesh",
runTime,
IOobject::NO_READ,
IOobject::NO_WRITE
),
surf,
dimLength,
externalCloseness
);
externalClosenessField.write();
scalarField k = calcCurvature(surf);
// Modify the curvature values on feature edges and points to be zero.
forAll(newSet.featureEdges(), fEI)
{
const edge& e = surf.edges()[newSet.featureEdges()[fEI]];
k[surf.meshPoints()[e.start()]] = 0.0;
k[surf.meshPoints()[e.end()]] = 0.0;
}
triSurfacePointScalarField kField
(
IOobject
(
sFeatFileName + ".curvature",
runTime.constant(),
"extendedFeatureEdgeMesh",
runTime,
IOobject::NO_READ,
IOobject::NO_WRITE
),
surf,
dimLength,
k
);
kField.write();
if (writeVTK)
{
vtkSurfaceWriter().write
(
runTime.constant()/"triSurface", // outputDir
sFeatFileName, // surfaceName
surf.points(),
faces,
"internalCloseness", // fieldName
internalCloseness,
false, // isNodeValues
true // verbose
);
vtkSurfaceWriter().write
(
runTime.constant()/"triSurface", // outputDir
sFeatFileName, // surfaceName
surf.points(),
faces,
"externalCloseness", // fieldName
externalCloseness,
false, // isNodeValues
true // verbose
);
vtkSurfaceWriter().write
(
runTime.constant()/"triSurface", // outputDir
sFeatFileName, // surfaceName
surf.points(),
faces,
"curvature", // fieldName
k,
true, // isNodeValues
true // verbose
);
}
Info<< "End\n" << endl;
return 0;

View File

@ -0,0 +1,4 @@
surfaceSplitByTopology.C
EXE = $(FOAM_APPBIN)/surfaceSplitByTopology

View File

@ -0,0 +1,7 @@
EXE_INC = \
-I$(LIB_SRC)/triSurface/lnInclude
EXE_LIBS = \
-lmeshTools \
-ltriSurface

View File

@ -0,0 +1,220 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2010 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description
Strips any baffle parts of a surface. A baffle region is one which is
reached by walking from an open edge, and stopping when a multiply connected
edge is reached.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "triSurface.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::noParallel();
argList::validArgs.clear();
argList::validArgs.append("input surface file");
argList::validArgs.append("output surface file");
argList args(argc, argv);
fileName surfFileName(args.additionalArgs()[0]);
Info<< "Reading surface from " << surfFileName << endl;
fileName outFileName(args.additionalArgs()[1]);
fileName outFileBaseName = outFileName.lessExt();
word outExtension = outFileName.ext();
// Load surface
triSurface surf(surfFileName);
bool anyZoneRemoved = false;
label iterationNo = 0;
label iterationLimit = 10;
Info<< "Splitting off baffle parts " << endl;
do
{
anyZoneRemoved = false;
labelList faceZone;
const labelListList& edFaces = surf.edgeFaces();
const labelListList& faceEds = surf.faceEdges();
boolList multipleEdges(edFaces.size(), false);
forAll(multipleEdges, i)
{
if (edFaces[i].size() > 2)
{
multipleEdges[i] = true;
}
}
label nZones = surf.markZones(multipleEdges, faceZone);
if (nZones < 2)
{
break;
}
boolList nonBaffle(faceZone.size(), true);
boolList baffle(faceZone.size(), true);
labelList pointMap;
labelList faceMap;
for (label z = 0; z < nZones; z++)
{
bool keepZone = true;
forAll(faceZone, f)
{
if (faceZone[f] == z)
{
forAll (faceEds[f], fe)
{
if (edFaces[faceEds[f][fe]].size() < 2)
{
keepZone = false;
anyZoneRemoved = true;
break;
}
}
}
if (!keepZone)
{
break;
}
}
forAll(faceZone, f)
{
if (faceZone[f] == z)
{
nonBaffle[f] = keepZone;
baffle[f] = !keepZone;
}
}
}
Info<< " Iteration " << iterationNo << endl;
triSurface baffleSurf = surf.subsetMesh(baffle, pointMap, faceMap);
if (baffleSurf.size())
{
fileName bafflePartFileName =
outFileBaseName
+ "_bafflePart_"
+ name(iterationNo)
+ "." + outExtension;
Info<< " Writing baffle part to " << bafflePartFileName << endl;
baffleSurf.write(bafflePartFileName);
}
surf = surf.subsetMesh(nonBaffle, pointMap, faceMap);
if (iterationNo == iterationLimit)
{
WarningIn("surfaceSplitByTopology")
<< "Iteration limit of " << iterationLimit << "reached" << endl;
}
iterationNo++;
} while (anyZoneRemoved && iterationNo < iterationLimit);
Info<< "Writing new surface to " << outFileName << endl;
surf.write(outFileName);
labelList faceZone;
const labelListList& edFaces = surf.edgeFaces();
boolList multipleEdges(edFaces.size(), false);
forAll(multipleEdges, i)
{
if (edFaces[i].size() > 2)
{
multipleEdges[i] = true;
}
}
label nZones = surf.markZones(multipleEdges, faceZone);
Info<< "Splitting remaining multiply connected parts" << endl;
for (label z = 0; z < nZones; z++)
{
boolList include(faceZone.size(), false);
labelList pointMap;
labelList faceMap;
forAll(faceZone, f)
{
if (faceZone[f] == z)
{
include[f] = true;
}
}
triSurface zoneSurf = surf.subsetMesh(include, pointMap, faceMap);
fileName remainingPartFileName =
outFileBaseName
+ "_multiplePart_"
+ name(z)
+ "." + outExtension;
Info<< " Writing mulitple part "
<< z << " to " << remainingPartFileName << endl;
zoneSurf.write(remainingPartFileName);
}
Info << "End\n" << endl;
return 0;
}
// ************************************************************************* //

135
differencesWrtDev.txt Normal file
View File

@ -0,0 +1,135 @@
src/
mesh/conformalVoronoiMesh
- all the meshing. See separate section below.
polyMeshGeometry:
- disabled tetquality check on face-center decomp tet.
Check only minTetDecomp tet.
limits face filtering if enabled. So cv3d can generate neg.
(face-centre decomp) tets but pyramid volumes are still positive!
indexedOctree:
- findSphere routine
closedTriSurfaceMesh :
triSurface which is defined closed even though topologically it isn't.
searchableSurface :
- bounds_ member data
- bool overlaps() const routine
searchableSurfaces, searhcableSurfacesQueries :
- findNearestIntersection routine
- bounds routines
surfaceFeatures:
- trimFeatures function returns trimmed bits
triSurfaceTools:
- surfaceSide.
the edge code is irrelevant. Use dev bits.
indexedOctree:
- findSphere
polyMeshTetDecomposition:
- disabled face-centre tet quality check (but kept minTetDecomp)
polyMesh.C:
- read cell centres if present.
Can be scrapped. Not useful. Does not write cell centres, does not
do decomposition, reconstruction, moving meshes.
primitiveMesh:
- overrideCellCentres
triangleI.H:
- stabilised triangle quality. Ok.
memInfo:
- added I/O operators. Useful.
distributedTrisurfaceMesh:
- additional reduce on boundBox. Can be removed only on the one
constructed from boundBox (line 2300)
Utilities/
cvMesh:
- top level mesher
checkMesh:
- override cellCentres. Remove if the polyMesh stuff gets removed.
surfaceCheck:
- moved triSurface quality into triangle. Use cvm.
surfaceBooleanFeatures:
- new application. Determines features straight from intersection.
More stable than surfaceBooleanOp. Used to e.g. get the features
between the wheels and wind tunnel.
So if surfaceBooleanOp fails:
- use this to extract features
- use snappyHexMesh to defeature
- use cvMesh with extracted features
This does not work very well! Since there might still be overlapping
bits of triSurface that will be meshed.
surfaceFeatureExtract:
- uses cgal only for curvature calculation. See cgal.
- writes a triSurfaceField of 'curvature' and 'internal closeness'
and 'external closeness'. This is just a normal intersection, not
a nearest point. These fields get used by cvMesh. Or not yet - is part
of proposal to seed points according to curvature.
- detects features that are near?
surfaceSplitByTopology:
- for fuel tank of Brawn. Detects baffles (markZones) and splits
it accordingly.
conformalVoronoiMesh/
--------------------
- Make sure the surface does not have any sliver triangles. These are
hard to get the surface normal correct for so might cause bleeding.
- Use surfaceCheck to find out triangle quality and size of smallest edges
- Use surfaceClean .. 1e-5 .. to get rid of any edges < 1e-5m.
- If you get bleeding you might see in face filtering:
...
cells with with zero or one non-boundary face : 1
...
Initial check before face collapse, found 48 bad quality faces
but this was real - the cell that got created inside the cone and sphere by the
bad triangle was actually attached to a lot of faces. This screwed up the
subsequent filtering as it stopped too early.
I ran:
surfaceClean coneAndSphere.obj 1e-5 coneAndSphere_clean.obj
and re-ran with that surface and got
...
cells with with zero or one non-boundary face : 0
...
Initial check before face collapse, found 0 bad quality faces
and the bad cells inside are gone.
That group of cells would be picked up at the end of the meshing as the
cvMesh_remainingProtrusions
cellSet which can be deleted.

View File

@ -32,7 +32,7 @@
#------------------------------------------------------------------------------
export WM_PROJECT=OpenFOAM
export WM_PROJECT_VERSION=dev
export WM_PROJECT_VERSION=dev.cvm
################################################################################
# USER EDITABLE PART: Changes made here may be lost with the next upgrade

View File

@ -302,11 +302,13 @@ DebugSwitches
ash 0;
atomizationModel 0;
attachDetach 0;
autoDensity 0;
autoHexMeshDriver 0;
autoLayerDriver 0;
autoRefineDriver 0;
autoSnapDriver 0;
bC11H10 0;
backgroundMeshDecomposition 0;
backward 0;
basePatch 0;
basicKinematicCloud 0;
@ -345,6 +347,7 @@ DebugSwitches
cellPointFace 0;
cellPointWeight 0;
cellSet 0;
cellSizeControlSurfaces 0;
cellToCell 0;
cellToFace 0;
cellToPoint 0;
@ -406,7 +409,7 @@ DebugSwitches
displacementLaplacian 0;
displacementSBRStress 0;
distanceSurface 0;
distribution 0;
Distribution 0;
downwind 0;
dragModel 0;
duplicatePoints 0;

View File

@ -31,7 +31,7 @@
#------------------------------------------------------------------------------
setenv WM_PROJECT OpenFOAM
setenv WM_PROJECT_VERSION dev
setenv WM_PROJECT_VERSION dev.cvm #dev
################################################################################
# USER EDITABLE PART: Changes made here may be lost with the next upgrade

View File

@ -0,0 +1,70 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2010-2010 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "memInfo.H"
#include "IOstreams.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::memInfo::memInfo(Istream& is)
:
base1(is),
base2(is),
member1(is),
member2(is)
{
// Check state of Istream
is.check("Foam::memInfo::memInfo(Foam::Istream&)");
}
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
Foam::Istream& Foam::operator>>(Istream& is, memInfo&)
{
// Check state of Istream
is.check
(
"Foam::Istream& Foam::operator>>(Foam::Istream&, Foam::memInfo&)"
);
return is;
}
Foam::Ostream& Foam::operator<<(Ostream& os, const memInfo&)
{
// Check state of Ostream
os.check
(
"Foam::Ostream& Foam::operator<<(Foam::Ostream&, "
"const Foam::memInfo&)"
);
return os;
}
// ************************************************************************* //

View File

@ -2054,6 +2054,54 @@ void Foam::indexedOctree<Type>::findBox
}
template <class Type>
void Foam::indexedOctree<Type>::findSphere
(
const label nodeI,
const point& centre,
const scalar radiusSqr,
labelHashSet& elements
) const
{
const node& nod = nodes_[nodeI];
const treeBoundBox& nodeBb = nod.bb_;
for (direction octant = 0; octant < nod.subNodes_.size(); octant++)
{
labelBits index = nod.subNodes_[octant];
if (isNode(index))
{
const treeBoundBox& subBb = nodes_[getNode(index)].bb_;
if (subBb.overlaps(centre, radiusSqr))
{
findSphere(getNode(index), centre, radiusSqr, elements);
}
}
else if (isContent(index))
{
const treeBoundBox subBb(nodeBb.subBbox(octant));
if (subBb.overlaps(centre, radiusSqr))
{
const labelList& indices = contents_[getContent(index)];
forAll(indices, i)
{
label shapeI = indices[i];
if (shapes_.overlaps(shapeI, centre, radiusSqr))
{
elements.insert(shapeI);
}
}
}
}
}
}
template <class Type>
template <class CompareOp>
void Foam::indexedOctree<Type>::findNear
@ -2614,6 +2662,25 @@ Foam::labelList Foam::indexedOctree<Type>::findBox
}
template <class Type>
Foam::labelList Foam::indexedOctree<Type>::findSphere
(
const point& centre,
const scalar radiusSqr
) const
{
// Storage for labels of shapes inside bb. Size estimate.
labelHashSet elements(shapes_.size() / 100);
if (nodes_.size())
{
findSphere(0, centre, radiusSqr, elements);
}
return elements.toc();
}
// Find node (as parent+octant) containing point
template <class Type>
Foam::labelBits Foam::indexedOctree<Type>::findNode

View File

@ -337,6 +337,16 @@ private:
) const;
//- Find all elements intersecting sphere.
void findSphere
(
const label nodeI,
const point& centre,
const scalar radiusSqr,
labelHashSet& elements
) const;
template <class CompareOp>
static void findNear
(
@ -565,6 +575,15 @@ public:
// overlapping bounding box (i.e. all shapes not outside box)
labelList findBox(const treeBoundBox& bb) const;
//- Find (in no particular order) indices of all shapes inside or
// overlapping a bounding sphere (i.e. all shapes not outside
// sphere)
labelList findSphere
(
const point& centre,
const scalar radiusSqr
) const;
//- Find deepest node (as parent+octant) containing point. Starts
// off from starting index in nodes_ (use 0 to start from top)
// Use getNode and getOctant to extract info, or call findIndices.

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -295,6 +295,31 @@ Foam::polyMesh::polyMesh(const IOobject& io)
neighbour_.write();
}
// Read cell centres if present
pointIOField cellCentres
(
IOobject
(
"cellCentres",
time().findInstance
(
meshDir(),
"cellCentres",
IOobject::READ_IF_PRESENT
),
meshSubDir,
*this,
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE
)
);
if (cellCentres.headerOk())
{
Pout<< "Reading cell centres" << endl;
overrideCellCentres(cellCentres);
}
// Calculate topology for the patches (processor-processor comms etc.)
boundary_.updateMesh();

View File

@ -380,11 +380,11 @@ bool Foam::polyMeshTetDecomposition::checkFaceTets
)
{
const labelList& own = mesh.faceOwner();
const labelList& nei = mesh.faceNeighbour();
// const labelList& nei = mesh.faceNeighbour();
const polyBoundaryMesh& patches = mesh.boundaryMesh();
const vectorField& cc = mesh.cellCentres();
const vectorField& fc = mesh.faceCentres();
// const vectorField& fc = mesh.faceCentres();
// Calculate coupled cell centre
pointField neiCc(mesh.nFaces() - mesh.nInternalFaces());
@ -398,62 +398,62 @@ bool Foam::polyMeshTetDecomposition::checkFaceTets
const faceList& fcs = mesh.faces();
const pointField& p = mesh.points();
// const pointField& p = mesh.points();
label nErrorTets = 0;
forAll(fcs, faceI)
{
const face& f = fcs[faceI];
// const face& f = fcs[faceI];
forAll(f, fPtI)
{
scalar tetQual = tetPointRef
(
p[f[fPtI]],
p[f.nextLabel(fPtI)],
fc[faceI],
cc[own[faceI]]
).quality();
// forAll(f, fPtI)
// {
// scalar tetQual = tetPointRef
// (
// p[f[fPtI]],
// p[f.nextLabel(fPtI)],
// fc[faceI],
// cc[own[faceI]]
// ).quality();
if (tetQual > -tol)
{
if (setPtr)
{
setPtr->insert(faceI);
}
// if (tetQual > -tol)
// {
// if (setPtr)
// {
// setPtr->insert(faceI);
// }
nErrorTets++;
break; // no need to check other tets
}
}
// nErrorTets++;
// break; // no need to check other tets
// }
// }
if (mesh.isInternalFace(faceI))
{
// Create the neighbour tet - it will have positive volume
const face& f = fcs[faceI];
// const face& f = fcs[faceI];
forAll(f, fPtI)
{
scalar tetQual = tetPointRef
(
p[f[fPtI]],
p[f.nextLabel(fPtI)],
fc[faceI],
cc[nei[faceI]]
).quality();
// forAll(f, fPtI)
// {
// scalar tetQual = tetPointRef
// (
// p[f[fPtI]],
// p[f.nextLabel(fPtI)],
// fc[faceI],
// cc[nei[faceI]]
// ).quality();
if (tetQual < tol)
{
if (setPtr)
{
setPtr->insert(faceI);
}
// if (tetQual < tol)
// {
// if (setPtr)
// {
// setPtr->insert(faceI);
// }
nErrorTets++;
break;
}
}
// nErrorTets++;
// break;
// }
// }
if (findSharedBasePoint(mesh, faceI, tol, report) == -1)
{

View File

@ -201,10 +201,34 @@ void Foam::processorPolyPatch::calcGeometry(PstreamBuffers& pBufs)
boundaryMesh().mesh().time().path()
/name()+"_faces.obj"
);
Pout<< "processorPolyPatch::order : Writing my " << size()
Pout<< "processorPolyPatch::calcGeometry : Writing my "
<< size()
<< " faces to OBJ file " << nm << endl;
writeOBJ(nm, *this, points());
OFstream ccStr
(
boundaryMesh().mesh().time().path()
/name() + "_faceCentresConnections.obj"
);
Pout<< "processorPolyPatch::calcGeometry :"
<< " Dumping cell centre lines between"
<< " corresponding face centres to OBJ file" << ccStr.name()
<< endl;
label vertI = 0;
forAll(faceCentres(), faceI)
{
const point& c0 = neighbFaceCentres_[faceI];
const point& c1 = faceCentres()[faceI];
writeOBJ(ccStr, c0, c1, vertI);
}
FatalErrorIn
(
"processorPolyPatch::calcGeometry()"

View File

@ -496,6 +496,12 @@ public:
const scalarField& cellVolumes() const;
const vectorField& faceAreas() const;
// Override cell centres with supplied positions
void overrideCellCentres
(
const vectorField& cellCtrs
) const;
// Mesh motion

View File

@ -28,6 +28,7 @@ Description
\*---------------------------------------------------------------------------*/
#include "primitiveMesh.H"
#include "demandDrivenData.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
@ -168,4 +169,66 @@ const Foam::scalarField& Foam::primitiveMesh::cellVolumes() const
}
void Foam::primitiveMesh::overrideCellCentres
(
const vectorField& newCellCtrs
) const
{
if (newCellCtrs.size() != nCells())
{
FatalErrorIn
(
"void Foam::primitiveMesh::overrideCellCentres"
"("
"const vectorField& newCellCtrs"
") const"
)
<< "Size of new cell centres for override " << newCellCtrs.size()
<< " not equal to the number of cells in the mesh " << nCells()
<< abort(FatalError);
}
if (debug)
{
Pout<< "void Foam::primitiveMesh::overrideCellCentres"
<< "(const vectorField& newCellCtrs) const : "
<< "overriding cell centres." << endl;
}
deleteDemandDrivenData(cellCentresPtr_);
deleteDemandDrivenData(cellVolumesPtr_);
// Calculate the cell volumes - these are invariant with respect
// to the centre.
calcCellCentresAndVols();
*cellCentresPtr_ = newCellCtrs;
// Set internal face centres to the midpoint of the cell-centre delta vector
// if (debug)
// {
// Pout<< "void Foam::primitiveMesh::overrideCellCentres"
// << "(const vectorField& newCellCtrs) const : "
// << "overriding internal face centres." << endl;
// }
// deleteDemandDrivenData(faceCentresPtr_);
// deleteDemandDrivenData(faceAreasPtr_);
// calcFaceCentresAndAreas();
// vectorField& fCtrs = *faceCentresPtr_;
// const vectorField& C = cellCentres();
// const labelUList& owner = faceOwner();
// const labelUList& neighbour = faceNeighbour();
// forAll(neighbour, faceI)
// {
// fCtrs[faceI] = 0.5*(C[neighbour[faceI]] + C[owner[faceI]]);
// }
}
// ************************************************************************* //

View File

@ -701,7 +701,8 @@ bool Foam::primitiveMesh::checkFaceSkewness
// Skewness vector
vector sv = Cpf - ((fAreas[faceI]&Cpf)/((fAreas[faceI]&d)+VSMALL))*d;
vector sv =
Cpf - ((fAreas[faceI] & Cpf)/((fAreas[faceI] & d) + VSMALL))*d;
vector svHat = sv/(mag(sv) + VSMALL);
// Normalisation distance calculated as the approximate distance

View File

@ -191,7 +191,7 @@ public:
// - point : centre of sphere
// - distance : radius of sphere
// - eligiblemiss: false
// Tol (small compared to 1, e.g. 1E-9) is used to determine
// Tol (small compared to 1, e.g. 1e-9) is used to determine
// whether point is inside: mag(pt - ctr) < (1+tol)*radius.
pointHit containmentSphere(const scalar tol) const;

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -160,7 +160,15 @@ inline Foam::scalar Foam::triangle<Point, PointRef>::circumRadius() const
template<class Point, class PointRef>
inline Foam::scalar Foam::triangle<Point, PointRef>::quality() const
{
return mag()/(Foam::sqr(circumRadius())*3.0*sqrt(3.0)/4.0 + VSMALL);
scalar c = circumRadius();
if (c < ROOTVSMALL)
{
// zero circumRadius, something has gone wrong.
return SMALL;
}
return mag()/(Foam::sqr(c)*3.0*sqrt(3.0)/4.0);
}

View File

@ -174,7 +174,6 @@ Foam::tmp<Foam::pointField> Foam::treeBoundBox::points() const
forAll(points, octant)
{
points[octant] = corner(octant);
}
return tPts;

View File

@ -309,7 +309,6 @@ Foam::scalar Foam::polyMeshGeometry::calcSkewness
}
// Create the neighbour pyramid - it will have positive volume
bool Foam::polyMeshGeometry::checkFaceTet
(
const polyMesh& mesh,
@ -788,7 +787,7 @@ bool Foam::polyMeshGeometry::checkFaceTets
// check whether decomposing each cell into tets results in
// positive volume, non-flat tets
const labelList& own = mesh.faceOwner();
const labelList& nei = mesh.faceNeighbour();
// const labelList& nei = mesh.faceNeighbour();
const polyBoundaryMesh& patches = mesh.boundaryMesh();
// Calculate coupled cell centre
@ -803,48 +802,50 @@ bool Foam::polyMeshGeometry::checkFaceTets
label nErrorTets = 0;
// bool tetError = false
forAll(checkFaces, i)
{
label faceI = checkFaces[i];
// Create the owner pyramid - note: exchange cell and face centre
// to get positive volume.
bool tetError = checkFaceTet
(
mesh,
report,
minTetQuality,
p,
faceI,
cellCentres[own[faceI]], // face centre
faceCentres[faceI], // cell centre
setPtr
);
// tetError = checkFaceTet
// (
// mesh,
// report,
// minTetQuality,
// p,
// faceI,
// cellCentres[own[faceI]], // face centre
// faceCentres[faceI], // cell centre
// setPtr
// );
if (tetError)
{
nErrorTets++;
}
// if (tetError)
// {
// nErrorTets++;
// }
if (mesh.isInternalFace(faceI))
{
// Create the neighbour tets - they will have positive volume
bool tetError = checkFaceTet
(
mesh,
report,
minTetQuality,
p,
faceI,
faceCentres[faceI], // face centre
cellCentres[nei[faceI]], // cell centre
setPtr
);
// tetError = checkFaceTet
// (
// mesh,
// report,
// minTetQuality,
// p,
// faceI,
// faceCentres[faceI], // face centre
// cellCentres[nei[faceI]], // cell centre
// setPtr
// );
if (tetError)
{
nErrorTets++;
}
// if (tetError)
// {
// nErrorTets++;
// }
if
(
@ -920,40 +921,40 @@ bool Foam::polyMeshGeometry::checkFaceTets
label face0 = baffles[i].first();
label face1 = baffles[i].second();
bool tetError = checkFaceTet
(
mesh,
report,
minTetQuality,
p,
face0,
cellCentres[own[face0]], // face centre
faceCentres[face0], // cell centre
setPtr
);
// tetError = checkFaceTet
// (
// mesh,
// report,
// minTetQuality,
// p,
// face0,
// cellCentres[own[face0]], // face centre
// faceCentres[face0], // cell centre
// setPtr
// );
if (tetError)
{
nErrorTets++;
}
// if (tetError)
// {
// nErrorTets++;
// }
// Create the neighbour tets - they will have positive volume
tetError = checkFaceTet
(
mesh,
report,
minTetQuality,
p,
face0,
faceCentres[face0], // face centre
cellCentres[own[face1]], // cell centre
setPtr
);
// // Create the neighbour tets - they will have positive volume
// tetError = checkFaceTet
// (
// mesh,
// report,
// minTetQuality,
// p,
// face0,
// faceCentres[face0], // face centre
// cellCentres[own[face1]], // cell centre
// setPtr
// );
if (tetError)
{
nErrorTets++;
}
// if (tetError)
// {
// nErrorTets++;
// }
if
(

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -584,10 +584,7 @@ void Foam::InteractionLists<ParticleType>::buildInteractionLists()
);
// Find all cells intersecting extendedBb
labelList interactingElems
(
allCellsTree.findBox(extendedBb)
);
labelList interactingElems(allCellsTree.findBox(extendedBb));
// Reserve space to avoid multiple resizing
DynamicList<label> cellDIL(interactingElems.size());
@ -660,10 +657,7 @@ void Foam::InteractionLists<ParticleType>::findExtendedProcBbsInRange
if (procBb.overlaps(extendedReferredProcBb))
{
tmpExtendedProcBbsInRange.append
(
extendedReferredProcBb
);
tmpExtendedProcBbsInRange.append(extendedReferredProcBb);
// Dummy index, there are no transforms, so there will
// be no resultant transform when this is decoded.
@ -903,7 +897,6 @@ void Foam::InteractionLists<ParticleType>::buildMap
(
new mapDistribute
(
constructSize,
sendMap.xfer(),
constructMap.xfer()
@ -921,7 +914,6 @@ void Foam::InteractionLists<ParticleType>::prepareParticlesToRefer
const globalIndexAndTransform& globalTransforms =
mesh_.globalData().globalTransforms();
referredParticles_.setSize(cellIndexAndTransformToDistribute_.size());
// Clear all existing referred particles

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -0,0 +1,252 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::MoleculeCloud
Description
SourceFiles
MoleculeCloudI.H
MoleculeCloud.C
\*---------------------------------------------------------------------------*/
#ifndef MoleculeCloud_H
#define MoleculeCloud_H
#include "Cloud.H"
#include "moleculeCloud.H"
#include "IOdictionary.H"
#include "potential.H"
#include "InteractionLists.H"
#include "labelVector.H"
#include "Random.H"
#include "fileName.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class MoleculeCloud Declaration
\*---------------------------------------------------------------------------*/
template<class MoleculeType>
class MoleculeCloud
:
public Cloud<MoleculeType>,
public moleculeCloud
{
private:
// Private data
//-
const polyMesh& mesh_;
//-
const potential& pot_;
//-
List<DynamicList<MoleculeType*> > cellOccupancy_;
//-
InteractionLists<MoleculeType> il_;
//-
List<typename MoleculeType::constantProperties> constPropList_;
//-
Random rndGen_;
// Private Member Functions
//-
void buildConstProps();
//-
void setSiteSizesAndPositions();
//- Determine which molecules are in which cells
void buildCellOccupancy();
//-
void calculatePairForce();
//-
inline void evaluatePair
(
MoleculeType& molI,
MoleculeType& molJ
);
//-
inline bool evaluatePotentialLimit
(
MoleculeType& molI,
MoleculeType& molJ
) const;
//-
void calculateTetherForce();
//-
void calculateExternalForce();
//-
void removeHighEnergyOverlaps();
//-
void initialiseMolecules(const dictionary& mdInitialiseDict);
//-
void createMolecule
(
const point& position,
label cell,
label tetFace,
label tetPt,
label id,
bool tethered,
scalar temperature,
const vector& bulkVelocity
);
//-
label nSites() const;
//- Disallow default bitwise copy construct
MoleculeCloud(const MoleculeCloud&);
//- Disallow default bitwise assignment
void operator=(const MoleculeCloud&);
public:
// Constructors
//- Construct given mesh and potential references
MoleculeCloud
(
const word& cloudName,
const polyMesh& mesh,
const potential& pot,
bool readFields = true
);
//- Construct given mesh, potential and mdInitialiseDict
MoleculeCloud
(
const word& cloudName,
const polyMesh& mesh,
const potential& pot,
const dictionary& mdInitialiseDict,
bool readFields = true
);
// Member Functions
//- Evolve the molecules (move, calculate forces, control state etc)
void evolve();
//-
void calculateForce();
//- Print cloud information
void info();
// Access
//-
inline const polyMesh& mesh() const;
//-
inline const potential& pot() const;
//-
inline const List<DynamicList<MoleculeType*> >&
cellOccupancy() const;
//-
inline const InteractionLists<MoleculeType>& il() const;
//-
inline const List<typename MoleculeType::constantProperties>
constProps() const;
//-
inline const typename MoleculeType::constantProperties&
constProps(label id) const;
//-
inline Random& rndGen();
//-
inline vector equipartitionLinearVelocity
(
scalar temperature,
scalar mass
);
//-
inline vector equipartitionAngularMomentum
(
scalar temperature,
const typename MoleculeType::constantProperties& cP
);
// Member Operators
//- Write molecule sites in XYZ format
void writeXYZ(const fileName& fName) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "MoleculeCloudI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "MoleculeCloud.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,416 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "constants.H"
using namespace Foam::constant;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class MoleculeType>
inline void Foam::MoleculeCloud<MoleculeType>::evaluatePair
(
MoleculeType& molI,
MoleculeType& molJ
)
{
const pairPotentialList& pairPot = pot_.pairPotentials();
const pairPotential& electrostatic = pairPot.electrostatic();
label idI = molI.id();
label idJ = molJ.id();
const typename MoleculeType::constantProperties& constPropI
(
constProps(idI)
);
const typename MoleculeType::constantProperties& constPropJ
(
constProps(idJ)
);
forAll(constPropI.pairPotSites(), pI)
{
label sI = constPropI.pairPotSites()[pI];
label idsI = constPropI.sites()[sI].siteId();
forAll(constPropJ.pairPotSites(), pJ)
{
label sJ = constPropJ.pairPotSites()[pJ];
label idsJ = constPropJ.sites()[sJ].siteId();
vector rsIsJ =
molI.sitePositions()[sI] - molJ.sitePositions()[sJ];
scalar rsIsJMagSq = magSqr(rsIsJ);
if (pairPot.rCutSqr(idsI, idsJ, rsIsJMagSq))
{
scalar rsIsJMag = mag(rsIsJ);
vector fsIsJ =
(rsIsJ/rsIsJMag)
*pairPot.force(idsI, idsJ, rsIsJMag);
molI.siteForces()[sI] += fsIsJ;
molJ.siteForces()[sJ] += -fsIsJ;
scalar potentialEnergy
(
pairPot.energy(idsI, idsJ, rsIsJMag)
);
molI.potentialEnergy() += 0.5*potentialEnergy;
molJ.potentialEnergy() += 0.5*potentialEnergy;
vector rIJ = molI.position() - molJ.position();
tensor virialContribution =
(rsIsJ*fsIsJ)*(rsIsJ & rIJ)/rsIsJMagSq;
molI.rf() += virialContribution;
molJ.rf() += virialContribution;
}
}
}
forAll(constPropI.electrostaticSites(), pI)
{
label sI = constPropI.electrostaticSites()[pI];
forAll(constPropJ.electrostaticSites(), pJ)
{
label sJ = constPropJ.electrostaticSites()[pJ];
vector rsIsJ =
molI.sitePositions()[sI] - molJ.sitePositions()[sJ];
scalar rsIsJMagSq = magSqr(rsIsJ);
if (rsIsJMagSq <= electrostatic.rCutSqr())
{
scalar rsIsJMag = mag(rsIsJ);
scalar chargeI = constPropI.sites()[sI].siteCharge();
scalar chargeJ = constPropJ.sites()[sJ].siteCharge();
vector fsIsJ =
(rsIsJ/rsIsJMag)
*chargeI*chargeJ*electrostatic.force(rsIsJMag);
molI.siteForces()[sI] += fsIsJ;
molJ.siteForces()[sJ] += -fsIsJ;
scalar potentialEnergy =
chargeI*chargeJ
*electrostatic.energy(rsIsJMag);
molI.potentialEnergy() += 0.5*potentialEnergy;
molJ.potentialEnergy() += 0.5*potentialEnergy;
vector rIJ = molI.position() - molJ.position();
tensor virialContribution =
(rsIsJ*fsIsJ)*(rsIsJ & rIJ)/rsIsJMagSq;
molI.rf() += virialContribution;
molJ.rf() += virialContribution;
}
}
}
}
template<class MoleculeType>
inline bool Foam::MoleculeCloud<MoleculeType>::evaluatePotentialLimit
(
MoleculeType& molI,
MoleculeType& molJ
) const
{
const pairPotentialList& pairPot = pot_.pairPotentials();
const pairPotential& electrostatic = pairPot.electrostatic();
label idI = molI.id();
label idJ = molJ.id();
const typename MoleculeType::constantProperties& constPropI
(
constProps(idI)
);
const typename MoleculeType::constantProperties& constPropJ
(
constProps(idJ)
);
forAll(constPropI.pairPotSites(), pI)
{
label sI = constPropI.pairPotSites()[pI];
label idsI = constPropI.sites()[sI].siteId();
forAll(constPropJ.pairPotSites(), pJ)
{
label sJ = constPropJ.pairPotSites()[pJ];
label idsJ = constPropJ.sites()[sJ].siteId();
vector rsIsJ =
molI.sitePositions()[sI] - molJ.sitePositions()[sJ];
scalar rsIsJMagSq = magSqr(rsIsJ);
if (pairPot.rCutSqr(idsI, idsJ, rsIsJMagSq))
{
scalar rsIsJMag = mag(rsIsJ);
// Guard against pairPot.energy being evaluated
// if rIJMag < SMALL. A floating point exception will
// happen otherwise.
if (rsIsJMag < SMALL)
{
WarningIn
(
"MoleculeCloud<MoleculeType>::"
"removeHighEnergyOverlaps()"
)
<< "Molecule site pair closer than "
<< SMALL
<< ": mag separation = " << rsIsJMag
<< ". These may have been placed on top of each"
<< " other by a rounding error in mdInitialise in"
<< " parallel or a block filled with moleculess"
<< " twice. Removing one of the molecules."
<< endl;
return true;
}
// Guard against pairPot.energy being evaluated if rIJMag <
// rMin. A tabulation lookup error will occur otherwise.
if (rsIsJMag < pairPot.rMin(idsI, idsJ))
{
return true;
}
if
(
mag(pairPot.energy(idsI, idsJ, rsIsJMag))
> pot_.potentialEnergyLimit()
)
{
return true;
};
}
}
}
forAll(constPropI.electrostaticSites(), pI)
{
label sI = constPropI.electrostaticSites()[pI];
forAll(constPropJ.electrostaticSites(), pJ)
{
label sJ = constPropJ.electrostaticSites()[pJ];
vector rsIsJ =
molI.sitePositions()[sI] - molJ.sitePositions()[sJ];
scalar rsIsJMagSq = magSqr(rsIsJ);
if (pairPot.rCutMaxSqr(rsIsJMagSq))
{
scalar rsIsJMag = mag(rsIsJ);
// Guard against pairPot.energy being evaluated
// if rIJMag < SMALL. A floating point exception will
// happen otherwise.
if (rsIsJMag < SMALL)
{
WarningIn
(
"MoleculeCloud<MoleculeType>::"
"removeHighEnergyOverlaps()"
)
<< "Molecule site pair closer than "
<< SMALL
<< ": mag separation = " << rsIsJMag
<< ". These may have been placed on top of each"
<< " other by a rounding error in mdInitialise in"
<< " parallel or a block filled with molecules"
<< " twice. Removing one of the molecules."
<< endl;
return true;
}
if (rsIsJMag < electrostatic.rMin())
{
return true;
}
scalar chargeI = constPropI.sites()[sI].siteCharge();
scalar chargeJ = constPropJ.sites()[sJ].siteCharge();
if
(
mag(chargeI*chargeJ*electrostatic.energy(rsIsJMag))
> pot_.potentialEnergyLimit()
)
{
return true;
};
}
}
}
return false;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class MoleculeType>
inline const Foam::polyMesh& Foam::MoleculeCloud<MoleculeType>::mesh() const
{
return mesh_;
}
template<class MoleculeType>
inline const Foam::potential& Foam::MoleculeCloud<MoleculeType>::pot() const
{
return pot_;
}
template<class MoleculeType>
inline const Foam::List<Foam::DynamicList<MoleculeType*> >&
Foam::MoleculeCloud<MoleculeType>::cellOccupancy() const
{
return cellOccupancy_;
}
template<class MoleculeType>
inline const Foam::InteractionLists<MoleculeType>&
Foam::MoleculeCloud<MoleculeType>::il() const
{
return il_;
}
template<class MoleculeType>
inline const Foam::List<typename MoleculeType::constantProperties>
Foam::MoleculeCloud<MoleculeType>::constProps() const
{
return constPropList_;
}
template<class MoleculeType>
inline const typename MoleculeType::constantProperties&
Foam::MoleculeCloud<MoleculeType>::constProps(label id) const
{
return constPropList_[id];
}
template<class MoleculeType>
inline Foam::Random& Foam::MoleculeCloud<MoleculeType>::rndGen()
{
return rndGen_;
}
template<class MoleculeType>
inline Foam::vector
Foam::MoleculeCloud<MoleculeType>::equipartitionLinearVelocity
(
scalar temperature,
scalar mass
)
{
return sqrt(physicoChemical::k.value()*temperature/mass)*vector
(
rndGen_.GaussNormal(),
rndGen_.GaussNormal(),
rndGen_.GaussNormal()
);
}
template<class MoleculeType>
inline Foam::vector
Foam::MoleculeCloud<MoleculeType>::equipartitionAngularMomentum
(
scalar temperature,
const typename MoleculeType::constantProperties& cP
)
{
scalar sqrtKbT = sqrt(physicoChemical::k.value()*temperature);
if (cP.linearMolecule())
{
return sqrtKbT*vector
(
0.0,
sqrt(cP.momentOfInertia().yy())*rndGen_.GaussNormal(),
sqrt(cP.momentOfInertia().zz())*rndGen_.GaussNormal()
);
}
else
{
return sqrtKbT*vector
(
sqrt(cP.momentOfInertia().xx())*rndGen_.GaussNormal(),
sqrt(cP.momentOfInertia().yy())*rndGen_.GaussNormal(),
sqrt(cP.momentOfInertia().zz())*rndGen_.GaussNormal()
);
}
}
// ************************************************************************* //

View File

@ -0,0 +1,48 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "moleculeCloud.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(moleculeCloud, 0);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::moleculeCloud::moleculeCloud()
{}
// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * //
Foam::moleculeCloud::~moleculeCloud()
{}
// ************************************************************************* //

View File

@ -0,0 +1,83 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::moleculeCloud
Description
Virtual abstract base class for templated moleculeCloud
SourceFiles
moleculeCloud.C
\*---------------------------------------------------------------------------*/
#ifndef moleculeCloud_H
#define moleculeCloud_H
#include "volFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class moleculeCloud Declaration
\*---------------------------------------------------------------------------*/
class moleculeCloud
{
// Private Member Functions
//- Disallow default bitwise copy construct
moleculeCloud(const moleculeCloud&);
//- Disallow default bitwise assignment
void operator=(const moleculeCloud&);
public:
//- Runtime type information
TypeName("moleculeCloud");
// Constructors
//- Null constructor
moleculeCloud();
//- Destructor
virtual ~moleculeCloud();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,52 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::monoatomicCloud
Description
Cloud class to simulate monoatomic molecules
SourceFiles
monoatomicCloud.C
\*---------------------------------------------------------------------------*/
#ifndef monoatomicCloud_H
#define monoatomicCloud_H
#include "MoleculeCloud.H"
#include "monoatomic.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
typedef MoleculeCloud<monoatomic> monoatomicCloud;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,52 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::polyatomicCloud
Description
Cloud class to simulate polyatomic molecules
SourceFiles
polyatomicCloud.C
\*---------------------------------------------------------------------------*/
#ifndef polyatomicCloud_H
#define polyatomicCloud_H
#include "MoleculeCloud.H"
#include "polyatomic.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
typedef MoleculeCloud<polyatomic> polyatomicCloud;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,573 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "controllers.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::controllers::controllers
(
const polyMesh& mesh
)
:
time_(mesh.time()),
controllersDict_
(
IOobject
(
"controllersDict",
time_.system(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE
)
),
stateControllersList_(),
sCNames_(),
sCIds_(),
sCFixedPathNames_(),
stateControllers_(),
fluxControllersList_(),
fCNames_(),
fCIds_(),
fCFixedPathNames_(),
fluxControllers_()
{}
Foam::controllers::controllers
(
const polyMesh& mesh,
polyatomicCloud& cloud
)
:
time_(mesh.time()),
controllersDict_
(
IOobject
(
"controllersDict",
time_.system(),
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
),
stateControllersList_(controllersDict_.lookup("stateControllers")),
sCNames_(stateControllersList_.size()),
sCIds_(stateControllersList_.size()),
sCFixedPathNames_(stateControllersList_.size()),
stateControllers_(stateControllersList_.size()),
fluxControllersList_(controllersDict_.lookup("fluxControllers")),
fCNames_(fluxControllersList_.size()),
fCIds_(fluxControllersList_.size()),
fCFixedPathNames_(fluxControllersList_.size()),
fluxControllers_(fluxControllersList_.size())
{
Info << nl << "Creating controllers" << nl << endl;
// state controllers
if (!stateControllers_.empty())
{
forAll(stateControllers_, sC)
{
const entry& controllersI = stateControllersList_[sC];
const dictionary& controllersIDict = controllersI.dict();
stateControllers_[sC] = autoPtr<stateController>
(
stateController::New(time_, cloud, controllersIDict)
);
sCNames_[sC] = stateControllers_[sC]->type();
sCIds_[sC] = sC;
}
}
//- flux controllers
if (!fluxControllers_.empty())
{
forAll(fluxControllers_, fC)
{
const entry& controllersI = fluxControllersList_[fC];
const dictionary& controllersIDict = controllersI.dict();
fluxControllers_[fC] = autoPtr<fluxController>
(
fluxController::New(time_, cloud, controllersIDict)
);
fCNames_[fC] = fluxControllers_[fC]->type();
fCIds_[fC] = fC;
}
}
// creating directories for state controllers
if (!nStateControllers_.empty())
{
// case/controllers
fileName controllersPath(time_.path()/"controllers");
if (!isDir(controllersPath))
{
mkDir(controllersPath);
}
// case/controllers/<cloudName>
fileName controllersPath(controllersPath/cloud.name());
if (!isDir(controllersPath))
{
mkDir(controllersPath);
}
// case/controllers/<cloudName>/stateControllers
fileName stateControllersPath(controllersPath/"stateControllers");
if (!isDir(stateControllersPath))
{
mkDir(stateControllersPath);
}
forAll(stateControllers_, sC)
{
if (stateControllers_[sC]->writeInCase())
{
// case/controllers/<cloudName>/
// stateControllers/<stateControllerModel>
fileName stateControllerPath(stateControllersPath/sCNames_[sC]);
if (!isDir(stateControllerPath))
{
mkDir(stateControllerPath);
}
const word& regionName = stateControllers_[sC]->regionName();
// case/controllers/<cloudName>/
// stateControllers/<stateControllerModel>/<cellZoneName>
fileName zonePath(stateControllerPath/regionName);
if (!isDir(zonePath))
{
mkDir(zonePath);
}
sCFixedPathNames_[sC] = zonePath;
}
}
}
// creating directories for flux controllers
if (nFluxControllers_ > 0)
{
// case/controllers
fileName controllersPath(time_.path()/"controllers");
if ( !isDir(controllersPath) )
{
mkDir(controllersPath);
}
// case/controllers/<cloudName>
fileName controllersPath(time_.path()/cloud.name());
if ( !isDir(controllersPath) )
{
mkDir(controllersPath);
}
// case/controllers/<cloudName>/fluxControllers
fileName fluxControllersPath(controllersPath/"fluxControllers");
if (!isDir(fluxControllersPath))
{
mkDir(fluxControllersPath);
}
forAll(fluxControllers_, fC)
{
if (fluxControllers_[fC]->writeInCase())
{
// case/controllers/<cloudName>/
// fluxControllers/<fluxControllerModel>
fileName fluxControllerPath(fluxControllersPath/fCNames_[fC]);
if (!isDir(fluxControllerPath))
{
mkDir(fluxControllerPath);
}
const word& regionName = fluxControllers_[fC]->regionName();
// case/controllers/<cloudName>/
// fluxControllers/<fluxControllerModel>/<faceZoneName>
fileName zonePath(fluxControllerPath/regionName);
if (!isDir(zonePath))
{
mkDir(zonePath);
}
fCFixedPathNames_[fC] = zonePath;
}
}
}
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
controllers::~controllers()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void controllers::initialConfig()
{
forAll(stateControllers_, sC)
{
stateControllers_[sC]->initialConfiguration();
}
forAll(fluxControllers_, fC)
{
fluxControllers_[fC]->initialConfiguration();
}
}
void controllers::updateTimeInfo()
{
forAll(stateControllers_, sC)
{
stateControllers_[sC]->updateTime();
}
forAll(fluxControllers_, fC)
{
fluxControllers_[fC]->updateTime();
}
}
void controllers::controlState()
{
forAll(stateControllers_, sC)
{
stateControllers_[sC]->controlMols();
}
}
void controllers::controlVelocitiesI()
{
forAll(stateControllers_, sC)
{
stateControllers_[sC]->controlMolsBeg();
}
}
void controllers::controlVelocitiesII()
{
forAll(stateControllers_, sC)
{
stateControllers_[sC]->controlMolsEnd();
}
}
void controllers::controlPriorToForces()
{
forAll(stateControllers_, sC)
{
stateControllers_[sC]->controlBeforeForces();
}
}
void controllers::calculateStateProps()
{
forAll(stateControllers_, sC)
{
stateControllers_[sC]->calculateProperties();
}
forAll(fluxControllers_, fC)
{
fluxControllers_[fC]->calculateProperties();
}
}
void controllers::outputStateResults()
{
const Time& runTime = time_;
if (runTime.outputTime())
{
// creating a set of directories in the current time directory
{
List<fileName> timePathNames(sCFixedPathNames_.size());
if (nStateControllers_ > 0)
{
if (Pstream::master())
{
// case/<timeDir>/uniform
fileName uniformTimePath
(
runTime.path()/runTime.timeName()/"uniform"
);
if (!isDir(uniformTimePath))
{
mkDir(uniformTimePath);
}
if (!stateControllers_.empty())
{
// case/<timeDir>/uniform/controllers
fileName controllersTimePath
(
uniformTimePath/"controllers"
);
if (!isDir(controllersTimePath))
{
mkDir(controllersTimePath);
}
// case/<timeDir>/uniform/controllers/<cloudName>
fileName cloudTimePath
(
controllersTimePath/cloud.name()
);
if (!isDir(cloudTimePath))
{
mkDir(cloudTimePath);
}
// case/<timeDir>/uniform/controllers/<cloudName>/
fileName stateControllersTimePath
(
cloudTimePath/"stateControllers"
);
if (!isDir(stateControllersTimePath))
{
mkDir(stateControllersTimePath);
}
forAll(stateControllers_, sC)
{
if (stateControllers_[sC]->writeInTimeDir())
{
// case/<timeDir>/uniform/controllers/
// <cloudName>/<stateControllerModel>
fileName sCTimePath
(
stateControllersTimePath/sCNames_[sC]
);
if (!isDir(sCTimePath))
{
mkDir(sCTimePath);
}
// Creating directory for different zones but
// of the same model
const word& regionName =
stateControllers_[sC]->regionName();
// case/<timeDir>/uniform/controllers/
// <cloudName>/<stateControllerModel>/
// <cellZoneName>
fileName zoneTimePath(sCTimePath/regionName);
if (!isDir(zoneTimePath))
{
mkDir(zoneTimePath);
}
timePathNames[sC] = zoneTimePath;
}
}
}
}
}
// write out data
forAll(stateControllers_, sC)
{
stateControllers_[sC]->output
(
sCFixedPathNames_[sC],
timePathNames[sC]
);
}
}
{
List<fileName> timePathNames(fCFixedPathNames_.size());
if (nFluxControllers_ > 0)
{
if (Pstream::master())
{
// case/<timeDir>/uniform
fileName uniformTimePath
(
runTime.path()/runTime.timeName()/"uniform"
);
if (!isDir(uniformTimePath))
{
mkDir(uniformTimePath);
}
if (!fluxControllers_.empty())
{
// case/<timeDir>/uniform/controllers
fileName controllersTimePath
(
uniformTimePath/"controllers"
);
if (!isDir(controllersTimePath))
{
mkDir(controllersTimePath);
}
// case/<timeDir>/uniform/controllers/<cloudName>
fileName cloudTimePath
(
controllersTimePath/cloud.name()
);
if (!isDir(cloudTimePath))
{
mkDir(cloudTimePath);
}
// case/<timeDir>/uniform/fluxControllers
fileName controllersTimePath
(
cloudTimePath/"fluxControllers"
);
if (!isDir(controllersTimePath))
{
mkDir(controllersTimePath);
}
forAll(fluxControllers_, fC)
{
if (stateControllers_[fC]->writeInTimeDir())
{
// case/<timeDir>/uniform/controllers/
// <cloudName>/<fluxControllerModel>
fileName fCTimePath
(
controllersTimePath/fCNames_[fC]
);
if (!isDir(fCTimePath))
{
mkDir(fCTimePath);
}
const word& regionName =
fluxControllers_[fC]->regionName();
// case/<timeDir>/uniform/controllers/
// <cloudName>/<fluxControllerModel>/
// <faceZoneName>
fileName zoneTimePath(fCTimePath/regionName);
if (!isDir(zoneTimePath))
{
mkDir(zoneTimePath);
}
timePathNames[fC] = zoneTimePath;
}
}
}
}
}
// write out data
forAll(fluxControllers_, fC)
{
fluxControllers_[fC]->output
(
fCFixedPathNames_[fC],
timePathNames[fC]
);
}
}
// Re-read dictionaries for modified properties (run-time selection)
{
stateControllersList_.clear();
stateControllersList_ = controllersDict_.lookup("stateControllers");
forAll(stateControllers_, sC)
{
const entry& controllersI = stateControllersList_[sC];
const dictionary& controllersIDict = controllersI.dict();
stateControllers_[sC]->updateProperties(controllersIDict);
}
}
{
fluxControllersList_.clear();
fluxControllersList_ = controllersDict_.lookup("fluxControllers");
forAll(fluxControllers_, fC)
{
const entry& controllersI = fluxControllersList_[fC];
const dictionary& controllersIDict = controllersI.dict();
fluxControllers_[fC]->updateProperties(controllersIDict);
}
}
}
}
// ************************************************************************* //

View File

@ -0,0 +1,163 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
controllers
Description
Stores all the information for the controllers models defined within
the controllersDict, and selects & builds the models automatically.
\*---------------------------------------------------------------------------*/
#ifndef controllers_H
#define controllers_H
#include "List.H"
#include "IOdictionary.H"
#include "autoPtr.H"
#include "polyMesh.H"
#include "timeData.H"
#include "stateController.H"
#include "fluxController.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class controllers Declaration
\*---------------------------------------------------------------------------*/
class controllers
{
// Private data
Time& time_;
//- The entire dictionary (containing multiple subDictionaries)
IOdictionary controllersDict_;
//- state controllers
PtrList<entry> stateControllersList_;
List<word> sCNames_;
List<label> sCIds_;
List<fileName> sCFixedPathNames_;
List< autoPtr<stateController> > stateControllers_;
//- flux controllers
PtrList<entry> fluxControllersList_;
List<word> fCNames_;
List<label> fCIds_;
List<fileName> fCFixedPathNames_;
List< autoPtr<fluxController> > fluxControllers_;
public:
// Constructors
//- Null Constructor
controllers
(
const polyMesh& mesh
);
//- Constructor for with cloud
controllers
(
const polyMesh& mesh,
polyatomicCloud& cloud
);
//- Destructor
~controllers();
// Member Functions
//- Initial configuration call this function after the polyatomicCloud
// is completely initialised
void initialConfig();
//- this function is to be called at the beginning of the MD time-step.
// since we have placed a non-referenced time-data class in the
// state-controller class.
void updateTimeInfo();
//- control molecular state -- call this after the intermolecular force
// calulation
void controlState();
//-
void controlVelocitiesI();
//-
void controlVelocitiesII();
//-
void controlPriorToForces();
//- calculate properties -- call this at the end of the MD time-step.
void calculateStateProps();
//- output -- call this function at the end of the MD time-step
void outputStateResults();
// Access
//-
inline List< autoPtr<stateController> >& stateControllers();
//-
inline const List< autoPtr<stateController> >&
stateControllers() const;
//-
inline List< autoPtr<fluxController> >& fluxControllers();
//-
inline const List< autoPtr<fluxController> >&
fluxControllers() const;
//-
inline const List<word>& stateControllersNames() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "controllersI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,64 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::List<Foam::autoPtr<Foam::stateController> >&
Foam::controllers::stateControllers()
{
return stateControllers_;
}
const Foam::List<Foam::autoPtr<Foam::stateController> >&
Foam::controllers::stateControllers() const
{
return stateControllers_;
}
Foam::List<Foam::autoPtr<Foam::fluxController> >&
Foam::controllers::fluxControllers()
{
return fluxControllers_;
}
const Foam::List< autoPtr<fluxController> >&
Foam::controllers::fluxControllers() const
{
return fluxControllers_;
}
const Foam::List<Foam::word>& Foam::controllers::stateControllersNames() const
{
return sCNames_;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,524 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "waterFluxController.H"
#include "IFstream.H"
#include "graph.H"
#include "polyatomicCloud.H"
namespace Foam
{
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
defineTypeNameAndDebug(waterFluxController, 0);
defineRunTimeSelectionTable(waterFluxController, dictionary);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct from components
waterFluxController::waterFluxController
(
Time& t,
polyatomicCloud& cloud,
const dictionary& dict
)
:
mesh_(refCast<const fvMesh>(cloud.mesh())),
cloud_(cloud),
rndGen_(clock::getTime()),
controllerDict_(dict.subDict("controllerProperties")),
timeDict_(controllerDict_.subDict("timeProperties")),
time_(t, timeDict_),
regionName_(controllerDict_.lookup("zoneName")),
regionId_(-1),
zoneSurfaceArea_(0.0),
internalFaces_(),
processorFaces_(),
control_(true),
readStateFromFile_(true),
singleValueController_(false),
density_(0.0),
velocity_(vector::zero),
temperature_(0.0),
pressure_(0.0),
strainRate_(tensor::zero),
tempGradient_(vector::zero),
fieldController_(false),
densities_(),
velocities_(),
temperatures_(),
pressures_(),
writeInTimeDir_(true),
writeInCase_(true)
{
const faceZoneMesh& faceZones = mesh_.faceZones();
regionId_ = faceZones.findZoneID(regionName_);
if (regionId_ == -1)
{
FatalErrorIn("waterFluxController::waterFluxController()")
<< "Cannot find region (faceZone): " << regionName_ << nl << "in: "
<< t.time().system()/"controllersDict"
<< exit(FatalError);
}
control_ = Switch(controllerDict_.lookup("controlSwitch"));
readStateFromFile_ = Switch(controllerDict_.lookup("readStateFromFile"));
setFacesInfo();
}
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
autoPtr<waterFluxController> waterFluxController::New
(
Time& t,
polyatomicCloud& cloud,
const dictionary& dict
)
{
word waterFluxControllerName
(
dict.lookup("fluxControllerModel")
);
Info<< "Selecting fluxController "
<< waterFluxControllerName << endl;
dictionaryConstructorTable::iterator cstrIter =
dictionaryConstructorTablePtr_->find(waterFluxControllerName);
if (cstrIter == dictionaryConstructorTablePtr_->end())
{
FatalError
<< "waterFluxController::New(const dictionary&) : " << endl
<< " unknown waterFluxController type "
<< waterFluxControllerName
<< ", constructor not in hash table" << endl << endl
<< " Valid injector types are :" << endl;
Info<< dictionaryConstructorTablePtr_->toc() << abort(FatalError);
}
return autoPtr<waterFluxController>
(
cstrIter()(t, cloud, dict)
);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
waterFluxController::~waterFluxController()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// void waterFluxController::updateTime()
// {
// time_++;
//
// const scalar& t = time_.time().timeOutputValue();
//
// if ((t - initialTime_) < timePeriod_)
// {
// time_.controlTimeInterval().endTime() = false;
// // control_ = false;
// }
// else
// {
// // control_ = true;
// }
// }
void waterFluxController::setFacesInfo()
{
const labelList& faces = controlZone();
if (Pstream::parRun())
{
DynamicList<label> processorFaces(0);
forAll(mesh_.boundaryMesh(), patchI)
{
const polyPatch& patch = mesh_.boundaryMesh()[patchI];
if (isA<processorPolyPatch>(patch))
{
for (label p = 0; p < patch.size(); p++)
{
label patchFaceI = p + patch.start();
label faceId = findIndex (faces, patchFaceI);
if (faceId != -1)
{
processorFaces.append(patchFaceI);
}
}
}
}
processorFaces.shrink();
processorFaces_.setSize(processorFaces.size(), -1);
forAll(processorFaces, f)
{
processorFaces_[f] = processorFaces[f];
}
label nInternalFaces = faces.size() - processorFaces.size();
internalFaces_.setSize(nInternalFaces, -1);
label counter = 0;
forAll(faces, f)
{
const label& faceI = faces[f];
if (findIndex(processorFaces, faceI) == -1)
{
internalFaces_[counter] = faceI;
counter++;
}
}
// Pout << "processorFaces: " << processorFaces_ << endl;
// Pout << "internalFaces: " << internalFaces_ << endl;
forAll(internalFaces_, f)
{
const label& faceI = internalFaces_[f];
zoneSurfaceArea_ += mag(mesh_.faceAreas()[faceI]);
}
// faces on a zone located on a processor cut belong to both processors
// (hence the 0.5)
forAll(processorFaces_, f)
{
const label& faceI = processorFaces_[f];
zoneSurfaceArea_ += 0.5*mag(mesh_.faceAreas()[faceI]);
}
if (Pstream::parRun())
{
for (int p = 0; p < Pstream::nProcs(); p++)
{
if (p != Pstream::myProcNo())
{
const int proc = p;
{
OPstream toNeighbour(Pstream::blocking, proc);
toNeighbour << zoneSurfaceArea_;
}
}
}
//- receiving
for (int p = 0; p < Pstream::nProcs(); p++)
{
if (p != Pstream::myProcNo())
{
scalar zoneSurfaceAreaProc;
const int proc = p;
{
IPstream fromNeighbour(Pstream::blocking, proc);
fromNeighbour >> zoneSurfaceAreaProc;
}
zoneSurfaceArea_ += zoneSurfaceAreaProc;
}
}
}
}
else
{
forAll(faces, f)
{
const label& faceI = faces[f];
zoneSurfaceArea_ += mag(mesh_.faceAreas()[faceI]);
}
}
}
void waterFluxController::updateTime()
{
time_++;
// const scalar& t = time_.time().timeOutputValue();
//
// if ((t - initialTime_) < timePeriod_)
// {
// time_.controlTimeInterval().endTime() = false;
// // control_ = false;
// }
// else
// {
// // control_ = true;
// }
}
void waterFluxController::updateFluxControllerProperties
(
const dictionary& newDict
)
{
controllerDict_ = newDict.subDict("controllerProperties");
//- you can reset the controlling zone from here. This essentially
// means that the coupling zone can infact move arbitrarily. To make
// this happen we probably need to devise a technique for automatically
// changing the cellZone else where, and then calling this function to
// reset the controlling zone in which the controller operates in.
if (controllerDict_.found("controlSwitch"))
{
control_ = Switch(controllerDict_.lookup("controlSwitch"));
}
if (controllerDict_.found("readStateFromFile"))
{
readStateFromFile_ = Switch
(
controllerDict_.lookup("readStateFromFile")
);
}
}
const labelList& waterFluxController::controlZone() const
{
return mesh_.faceZones()[regionId_];
}
label waterFluxController::isFaceOnControlZone(const label& faceI)
{
const label f = findIndex(controlZone(), faceI);
return f;
}
const word& waterFluxController::regionName() const
{
return regionName_;
}
const scalar& waterFluxController::density() const
{
return density_;
}
scalar& waterFluxController::density()
{
return density_;
}
const vector& waterFluxController::velocity() const
{
return velocity_;
}
vector& waterFluxController::velocity()
{
return velocity_;
}
const scalar& waterFluxController::temperature() const
{
return temperature_;
}
scalar& waterFluxController::temperature()
{
return temperature_;
}
const scalar& waterFluxController::pressure() const
{
return pressure_;
}
scalar& waterFluxController::pressure()
{
return pressure_;
}
const tensor& waterFluxController::strainRate() const
{
return strainRate_;
}
tensor& waterFluxController::strainRate()
{
return strainRate_;
}
const vector& waterFluxController::tempGradient() const
{
return tempGradient_;
}
vector& waterFluxController::tempGradient()
{
return tempGradient_;
}
const scalarField& waterFluxController::densityField() const
{
return densities_;
}
scalarField& waterFluxController::densityField()
{
return densities_;
}
const vectorField& waterFluxController::velocityField() const
{
return velocities_;
}
vectorField& waterFluxController::velocityField()
{
return velocities_;
}
const scalarField& waterFluxController::temperatureField() const
{
return temperatures_;
}
scalarField& waterFluxController::temperatureField()
{
return temperatures_;
}
const scalarField& waterFluxController::pressureField() const
{
return pressures_;
}
scalarField& waterFluxController::pressureField()
{
return pressures_;
}
const bool& waterFluxController::singleValueController() const
{
return singleValueController_;
}
bool& waterFluxController::singleValueController()
{
return singleValueController_;
}
const bool& waterFluxController::fieldController() const
{
return fieldController_;
}
bool& waterFluxController::fieldController()
{
return fieldController_;
}
const bool& waterFluxController::writeInTimeDir() const
{
return writeInTimeDir_;
}
const bool& waterFluxController::writeInCase() const
{
return writeInCase_;
}
// const scalar waterFluxController::avReqDensity() const
// {
// scalar totalDensity = 0.0;
//
// forAll(densities_, c)
// {
// totalDensity += densities_[c];
// }
//
// if (cells_.size() > 0)
// {
// totalDensity /= scalar(cells_.size());
// }
//
// return totalDensity;
// }
//
// const vector waterFluxController::avReqVelocity() const
// {
// vector totalVel = vector::zero;
//
// forAll(velocities_, c)
// {
// totalVel += velocities_[c];
// }
//
// if (cells_.size() > 0)
// {
// totalVel /= scalar(cells_.size());
// }
//
// return totalVel;
// }
//
// const scalar waterFluxController::avReqTemperature() const
// {
// scalar totalTemp = 0.0;
//
// forAll(densities_, c)
// {
// totalTemp += temperatures_[c];
// }
//
// if (cells_.size() > 0)
// {
// totalTemp /= scalar(cells_.size());
// }
//
// return totalTemp;
// }
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,272 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
waterFluxController
Description
SourceFiles
waterFluxControllerI.H
waterFluxController.C
waterFluxControllerIO.C
\*---------------------------------------------------------------------------*/
#ifndef waterFluxController_H
#define waterFluxController_H
#include "IOdictionary.H"
#include "Time.H"
#include "autoPtr.H"
#include "runTimeSelectionTables.H"
#include "vector.H"
#include "volFields.H"
#include "Random.H"
#include "polyatomic.H"
#include "timeData.H"
#include "writeTimeData.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class waterFluxController Declaration
\*---------------------------------------------------------------------------*/
class waterFluxController
{
protected:
// Protected data
// Time& time_;
const fvMesh& mesh_;
polyatomicCloud& cloud_;
Random rndGen_;
//- subDictionary containing the properties
dictionary controllerDict_;
dictionary timeDict_;
timeData time_;
//- name of face zone
word regionName_;
label regionId_;
// labelList faces_;
scalar zoneSurfaceArea_;
labelList internalFaces_;
labelList processorFaces_;
bool control_;
bool readStateFromFile_;
//- set all the properties below from model if required
bool singleValueController_;
// target values
scalar density_;
vector velocity_;
scalar temperature_;
scalar pressure_;
tensor strainRate_;
vector tempGradient_;
bool fieldController_;
//- targeted fields
scalarField densities_;
vectorField velocities_;
scalarField temperatures_;
scalarField pressures_;
bool writeInTimeDir_;
bool writeInCase_;
// Private Member Functions
void setFacesInfo();
public:
//- Runtime type information
TypeName("waterFluxController");
// Declare runtime constructor selection table
declareRunTimeSelectionTable
(
autoPtr,
waterFluxController,
dictionary,
(
Time& t,
polyatomicCloud& cloud,
const dictionary& dict
),
(t, cloud, dict)
);
// Constructors
//- Construct from components
waterFluxController
(
Time& t,
polyatomicCloud& cloud,
const dictionary& dict
);
// Selectors
static autoPtr<waterFluxController> New
(
Time& t,
polyatomicCloud& cloud,
const dictionary& dict
);
// Destructor
virtual ~waterFluxController();
// Member Functions
void updateTime();
//- create an initial configuration
virtual void initialConfiguration() = 0;
//- calculate any required properties
virtual void calculateProperties() = 0;
//- control the polyatomic from the tracking function
virtual void controlMol
(
polyatomic& mol,
polyatomic::trackData& td
) = 0;
//- output data
virtual void output
(
const fileName& fixedPathName,
const fileName& timePath
) = 0;
//- E. update properties from a modified dictionary
virtual void updateProperties(const dictionary&) = 0;
void updateFluxControllerProperties(const dictionary&);
// Access
//- return the control zone cells
const labelList& controlZone() const;
label isFaceOnControlZone(const label& faceI);
//- return the control zone name
const word& regionName() const;
//- return the targeted values
const scalar& density() const;
scalar& density();
const vector& velocity() const;
vector& velocity();
const scalar& temperature() const;
scalar& temperature();
const scalar& pressure() const;
scalar& pressure();
const tensor& strainRate() const;
tensor& strainRate();
const vector& tempGradient() const;
vector& tempGradient();
//- return the targeted fields
const scalarField& densityField() const;
scalarField& densityField();
const vectorField& velocityField() const;
vectorField& velocityField();
const scalarField& temperatureField() const;
scalarField& temperatureField();
const scalarField& pressureField() const;
scalarField& pressureField();
const bool& singleValueController() const;
bool& singleValueController();
const bool& fieldController() const;
bool& fieldController();
const bool& writeInTimeDir() const;
const bool& writeInCase() const;
// const scalar avReqDensity() const;
// const vector avReqVelocity() const;
// const scalar avReqTemperature() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,490 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "stateController.H"
#include "IFstream.H"
#include "polyatomicCloud.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(stateController, 0);
defineRunTimeSelectionTable(stateController, dictionary);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::stateController::stateController
(
polyatomicCloud& cloud,
const dictionary& dict
)
:
mesh_(refCast<const fvMesh>(cloud.mesh())),
cloud_(cloud),
rndGen_(clock::getTime()),
controllerDict_(dict.subDict("controllerProperties")),
timeDict_(controllerDict_.subDict("timeProperties")),
time_(mesh_.time(), timeDict_),
timePeriod_(readScalar(timeDict_.lookup("initialTimePeriod"))), //temp
initialTime_(time_.time().startTime().value()),
regionName_(controllerDict_.lookup("zoneName")),
regionId_(-1),
control_(true),
readStateFromFile_(true),
singleValueController_(false),
density_(0.0),
velocity_(vector::zero),
temperature_(0.0),
pressure_(0.0),
strainRate_(tensor::zero),
tempGradient_(vector::zero),
fieldController_(false),
densities_(),
velocities_(),
temperatures_(),
pressures_(),
writeInTimeDir_(true),
writeInCase_(true)
{
const cellZoneMesh& cellZones = mesh_.cellZones();
regionId_ = cellZones.findZoneID(regionName_);
if (regionId_ == -1)
{
FatalErrorIn("stateController::stateController()")
<< "Cannot find region: " << regionName_ << nl << "in: "
<< time_.time().system()/"controllersDict"
<< exit(FatalError);
}
control_ = Switch(controllerDict_.lookup("controlSwitch"));
readStateFromFile_ = Switch(controllerDict_.lookup("readStateFromFile"));
const scalar& avTimeInterval = time_.averageTimeInterval().deltaT();
if ((timePeriod_ < avTimeInterval) && (timePeriod_ > 0.0))
{
timePeriod_ = avTimeInterval;
}
}
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
Foam::autoPtr<Foam::stateController> Foam::stateController::New
(
polyatomicCloud& cloud,
const dictionary& dict
)
{
word stateControllerName
(
dict.lookup("stateControllerModel")
);
Info<< "Selecting stateController "
<< stateControllerName << endl;
dictionaryConstructorTable::iterator cstrIter =
dictionaryConstructorTablePtr_->find(stateControllerName);
if (cstrIter == dictionaryConstructorTablePtr_->end())
{
FatalError
<< "stateController::New(const dictionary&) : " << endl
<< " unknown stateController type "
<< stateControllerName
<< ", constructor not in hash table" << endl << endl
<< " Valid types are :" << endl;
Info<< dictionaryConstructorTablePtr_->toc() << abort(FatalError);
}
return autoPtr<stateController>
(
cstrIter()(cloud, dict)
);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::stateController::~stateController()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::stateController::updateTime()
{
time_++;
const scalar& t = time_.time().timeOutputValue();
if ((t - initialTime_) < timePeriod_)
{
time_.controlTimeInterval().endTime() = false;
}
}
void Foam::stateController::updateStateControllerProperties
(
const dictionary& newDict
)
{
controllerDict_ = newDict.subDict("controllerProperties");
if (controllerDict_.found("controlSwitch"))
{
control_ = Switch(controllerDict_.lookup("controlSwitch"));
}
if (controllerDict_.found("readStateFromFile"))
{
readStateFromFile_ = Switch
(
controllerDict_.lookup("readStateFromFile")
);
}
timeDict_ = controllerDict_.subDict("timeProperties");
if (timeDict_.found("resetAtOutput"))
{
time_.resetFieldsAtOutput() = Switch(timeDict_.lookup("resetAtOutput"));
}
}
const Foam::labelList& Foam::stateController::controlZone() const
{
return mesh_.cellZones()[regionId_];
}
const Foam::word& Foam::stateController::regionName() const
{
return regionName_;
}
Foam::scalar Foam::stateController::density() const
{
return density_;
}
Foam::scalar& Foam::stateController::density()
{
return density_;
}
const Foam::vector& Foam::stateController::velocity() const
{
return velocity_;
}
Foam::vector& Foam::stateController::velocity()
{
return velocity_;
}
Foam::scalar Foam::stateController::temperature() const
{
return temperature_;
}
Foam::scalar& Foam::stateController::temperature()
{
return temperature_;
}
const Foam::scalar& Foam::stateController::pressure() const
{
return pressure_;
}
Foam::scalar& Foam::stateController::pressure()
{
return pressure_;
}
const Foam::tensor& Foam::stateController::strainRate() const
{
return strainRate_;
}
Foam::tensor& Foam::stateController::strainRate()
{
return strainRate_;
}
const Foam::vector& Foam::stateController::tempGradient() const
{
return tempGradient_;
}
Foam::vector& Foam::stateController::tempGradient()
{
return tempGradient_;
}
const Foam::scalarField& Foam::stateController::densityField() const
{
return densities_;
}
Foam::scalarField& Foam::stateController::densityField()
{
return densities_;
}
const Foam::vectorField& Foam::stateController::velocityField() const
{
return velocities_;
}
Foam::vectorField& Foam::stateController::velocityField()
{
return velocities_;
}
const Foam::scalarField& Foam::stateController::temperatureField() const
{
return temperatures_;
}
Foam::scalarField& Foam::stateController::temperatureField()
{
return temperatures_;
}
const Foam::scalarField& Foam::stateController::pressureField() const
{
return pressures_;
}
Foam::scalarField& Foam::stateController::pressureField()
{
return pressures_;
}
bool Foam::stateController::singleValueController() const
{
return singleValueController_;
}
bool& Foam::stateController::singleValueController()
{
return singleValueController_;
}
bool Foam::stateController::fieldController() const
{
return fieldController_;
}
bool& Foam::stateController::fieldController()
{
return fieldController_;
}
bool Foam::stateController::writeInTimeDir() const
{
return writeInTimeDir_;
}
bool Foam::stateController::writeInCase() const
{
return writeInCase_;
}
Foam::scalar Foam::stateController::avReqDensity()
{
scalar totalDensity = 0.0;
if (singleValueController_)
{
totalDensity = density_;
}
else if (fieldController_)
{
label controlCells = controlZone().size();
forAll(densities_, c)
{
totalDensity += densities_[c];
}
if (Pstream::parRun())
{
reduce(totalDensity, sumOp<scalar>());
reduce(controlCells, sumOp<label>());
}
if (controlCells > 0)
{
totalDensity /= scalar(controlCells);
}
}
return totalDensity;
}
Foam::vector Foam::stateController::avReqVelocity()
{
vector totalVel = vector::zero;
if (singleValueController_)
{
totalVel = velocity_;
}
else if (fieldController_)
{
label controlCells = controlZone().size();
forAll(velocities_, c)
{
totalVel += velocities_[c];
}
if (Pstream::parRun())
{
reduce(totalVel, sumOp<vector>());
reduce(controlCells, sumOp<label>());
}
if (controlCells > 0)
{
totalVel /= scalar(controlCells);
}
}
return totalVel;
}
Foam::scalar Foam::stateController::avReqTemperature()
{
scalar totalTemp = 0.0;
if (singleValueController_)
{
totalTemp = temperature_;
}
else if (fieldController_)
{
label controlCells = controlZone().size();
forAll(temperatures_, c)
{
totalTemp += temperatures_[c];
}
if (Pstream::parRun())
{
reduce(totalTemp, sumOp<scalar>());
reduce(controlCells, sumOp<label>());
}
if (controlCells > 0)
{
totalTemp /= scalar(controlCells);
}
}
return totalTemp;
}
Foam::scalar Foam::stateController::avReqPressure()
{
scalar totalPressure = 0.0;
if (singleValueController_)
{
totalPressure = pressure_;
}
else if (fieldController_)
{
label controlCells = controlZone().size();
forAll(pressures_, c)
{
totalPressure += pressures_[c];
}
if (Pstream::parRun())
{
reduce(totalPressure, sumOp<scalar>());
reduce(controlCells, sumOp<label>());
}
if (controlCells > 0)
{
totalPressure /= scalar(controlCells);
}
}
return totalPressure;
}
// ************************************************************************* //

View File

@ -0,0 +1,270 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
stateController
Description
Basic/abstract class of a state controller
SourceFiles
stateControllerI.H
stateController.C
stateControllerIO.C
\*---------------------------------------------------------------------------*/
#ifndef stateController_H
#define stateController_H
#include "IOdictionary.H"
#include "autoPtr.H"
#include "runTimeSelectionTables.H"
#include "vector.H"
#include "volFields.H"
#include "Random.H"
#include "polyatomic.H"
#include "timeData.H"
#include "writeTimeData.H"
#include "selectIds.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class stateController Declaration
\*---------------------------------------------------------------------------*/
class stateController
{
protected:
// Protected data
//-
const fvMesh& mesh_;
//-
polyatomicCloud& cloud_;
//-
Random rndGen_;
//- subDictionary containing the properties
dictionary controllerDict_;
//-
dictionary timeDict_;
//-
timeData time_;
//-
scalar timePeriod_;
//-
scalar initialTime_;
//- name of control zone
word regionName_;
//-
label regionId_;
//-
bool control_;
//-
bool readStateFromFile_;
//- set all the properties below from model if required
//-
bool singleValueController_;
//- target values
scalar density_;
vector velocity_;
scalar temperature_;
scalar pressure_;
tensor strainRate_;
vector tempGradient_;
//- set this in model
bool fieldController_;
//- targeted fields
scalarField densities_;
vectorField velocities_;
scalarField temperatures_;
scalarField pressures_;
// set these in model
bool writeInTimeDir_;
bool writeInCase_;
public:
//- Runtime type information
TypeName("stateController");
//- Declare runtime constructor selection table
declareRunTimeSelectionTable
(
autoPtr,
stateController,
dictionary,
(
polyatomicCloud& cloud,
const dictionary& dict
),
(t, cloud, dict)
);
// Constructors
//- Construct from components
stateController
(
polyatomicCloud& cloud,
const dictionary& dict
);
// Selectors
static autoPtr<stateController> New
(
polyatomicCloud& cloud,
const dictionary& dict
);
// Destructor
virtual ~stateController();
// Member Functions
void updateTime();
//- create an initial configuration
virtual void initialConfiguration() = 0;
//- calculate any required properties
virtual void calculateProperties() = 0;
//- control molecules at different stages of the integration time-step
virtual void controlMolsBeg() = 0;
virtual void controlBeforeForces() = 0;
virtual void controlMols() = 0;
virtual void controlMolsEnd() = 0;
//- output data
virtual void output
(
const fileName& fixedPathName,
const fileName& timePath
) = 0;
//- update properties from a modified dictionary
virtual void updateProperties(const dictionary&) = 0;
void updateStateControllerProperties(const dictionary&);
// Access
//- return the control zone cells
const labelList& controlZone() const;
//- return the control zone name
const word& regionName() const;
//- return the targeted fields
scalar density() const;
scalar& density();
const vector& velocity() const;
vector& velocity();
scalar temperature() const;
scalar& temperature();
scalar pressure() const;
scalar& pressure();
const tensor& strainRate() const;
tensor& strainRate();
const vector& tempGradient() const;
vector& tempGradient();
//- return the targeted fields
const scalarField& densityField() const;
scalarField& densityField();
const vectorField& velocityField() const;
vectorField& velocityField();
const scalarField& temperatureField() const;
scalarField& temperatureField();
const scalarField& pressureField() const;
scalarField& pressureField();
bool singleValueController() const;
bool& singleValueController();
bool fieldController() const;
bool& fieldController();
bool writeInTimeDir() const;
bool writeInCase() const;
scalar avReqDensity();
vector avReqVelocity();
scalar avReqTemperature();
scalar avReqPressure();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -220,4 +220,3 @@ if (runTime.outputTime())
}
}
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -6,4 +6,3 @@
#include "distribution.H"
#include "reducedUnits.H"
#endif

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2010 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2008-2011 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License

View File

@ -0,0 +1,114 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "constPropSite.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::constPropSite::constPropSite()
:
siteReferencePosition_(vector::zero),
siteMass_(0.0),
siteCharge_(0.0),
siteId_(0),
name_(),
pairPotentialSite_(false),
electrostaticSite_(false)
{}
Foam::constPropSite::constPropSite
(
const vector& siteReferencePosition,
const scalar& siteMass,
const scalar& siteCharge,
const label& siteId,
const word& name,
const bool& pairPotentialSite,
const bool& electrostaticSite
)
:
siteReferencePosition_(siteReferencePosition),
siteMass_(siteMass),
siteCharge_(siteCharge),
siteId_(siteId),
name_(name),
pairPotentialSite_(pairPotentialSite),
electrostaticSite_(electrostaticSite)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::constPropSite::~constPropSite()
{}
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
Foam::Istream& Foam::operator>>(Istream& is, constPropSite& cPS)
{
is >> cPS.siteReferencePosition_
>> cPS.siteMass_
>> cPS.siteCharge_
>> cPS.siteId_
>> cPS.name_
>> cPS.pairPotentialSite_
>> cPS.electrostaticSite_;
// Check state of Istream
is.check
(
"Foam::Istream& Foam::operator>>"
"(Foam::Istream&, Foam::constPropSite&)"
);
return is;
}
Foam::Ostream& Foam::operator<<(Ostream& os, const constPropSite& cPS)
{
os << token::SPACE << cPS.siteReferencePosition()
<< token::SPACE << cPS.siteMass()
<< token::SPACE << cPS.siteCharge()
<< token::SPACE << cPS.siteId()
<< token::SPACE << cPS.name()
<< token::SPACE << cPS.pairPotentialSite()
<< token::SPACE << cPS.electrostaticSite();
// Check state of Ostream
os.check
(
"Foam::Ostream& Foam::operator<<(Foam::Ostream&, "
"const Foam::constPropSite&)"
);
return os;
}
// ************************************************************************* //

View File

@ -0,0 +1,185 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Description
SourceFiles
constPropSiteI.H
constPropSite.C
\*---------------------------------------------------------------------------*/
#ifndef constPropSite_H
#define constPropSite_H
#include "vector.H"
#include "IOstreams.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class Istream;
class Ostream;
// Forward declaration of friend functions and operators
class constPropSite;
Istream& operator>>(Istream&, constPropSite&);
Ostream& operator<<(Ostream&, const constPropSite&);
/*---------------------------------------------------------------------------*\
Class constPropSite Declaration
\*---------------------------------------------------------------------------*/
class constPropSite
{
// Private data
//-
vector siteReferencePosition_;
//-
scalar siteMass_;
//-
scalar siteCharge_;
//-
label siteId_;
//-
word name_;
//-
bool pairPotentialSite_;
//-
bool electrostaticSite_;
public:
// Constructors
//- Construct null
constPropSite();
//- Construct from components
constPropSite
(
const vector& siteReferencePosition,
const scalar& siteMass,
const scalar& siteCharge,
const label& siteId,
const word& name,
const bool& pairPotentialSite,
const bool& electrostaticSite
);
// Selectors
// Destructor
~constPropSite();
// Member Functions
// Access
//-
inline const vector& siteReferencePosition() const;
//-
inline vector& siteReferencePosition();
//-
inline const scalar& siteMass() const;
//-
inline scalar& siteMass();
//-
inline const scalar& siteCharge() const;
//-
inline scalar& siteCharge();
//-
inline const label& siteId() const;
//-
inline label& siteId();
//-
inline const word& name() const;
//-
inline word& name();
//-
inline const bool& pairPotentialSite() const;
//-
inline bool& pairPotentialSite();
//-
inline const bool& electrostaticSite() const;
//-
inline bool& electrostaticSite();
// Member Operators
inline bool operator==(const constPropSite&) const;
inline bool operator!=(const constPropSite&) const;
// IOstream Operators
friend Istream& operator>>(Istream&, constPropSite&);
friend Ostream& operator<<(Ostream&, const constPropSite&);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "constPropSiteI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,139 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline const Foam::vector& Foam::constPropSite::siteReferencePosition() const
{
return siteReferencePosition_;
}
inline Foam::vector& Foam::constPropSite::siteReferencePosition()
{
return siteReferencePosition_;
}
inline const Foam::scalar& Foam::constPropSite::siteMass() const
{
return siteMass_;
}
inline Foam::scalar& Foam::constPropSite::siteMass()
{
return siteMass_;
}
inline const Foam::scalar& Foam::constPropSite::siteCharge() const
{
return siteCharge_;
}
inline Foam::scalar& Foam::constPropSite::siteCharge()
{
return siteCharge_;
}
inline const Foam::label& Foam::constPropSite::siteId() const
{
return siteId_;
}
inline Foam::label& Foam::constPropSite::siteId()
{
return siteId_;
}
inline const Foam::word& Foam::constPropSite::name() const
{
return name_;
}
inline Foam::word& Foam::constPropSite::name()
{
return name_;
}
inline const bool& Foam::constPropSite::pairPotentialSite() const
{
return pairPotentialSite_;
}
inline bool& Foam::constPropSite::pairPotentialSite()
{
return pairPotentialSite_;
}
inline const bool& Foam::constPropSite::electrostaticSite() const
{
return electrostaticSite_;
}
inline bool& Foam::constPropSite::electrostaticSite()
{
return electrostaticSite_;
}
// * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
bool Foam::constPropSite::operator==
(
const constPropSite& rhs
) const
{
return
siteReferencePosition_ == rhs.siteReferencePosition_
&& siteMass_ == rhs.siteMass_
&& siteCharge_ == rhs.siteCharge_
&& siteId_ == rhs.siteId_
&& name_ == rhs.name_
&& pairPotentialSite_ == rhs.pairPotentialSite_
&& electrostaticSite_ == rhs.electrostaticSite_;
}
bool Foam::constPropSite::operator!=
(
const constPropSite& rhs
) const
{
return !(*this == rhs);
}
// ************************************************************************* //

View File

@ -0,0 +1,199 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*----------------------------------------------------------------------------*/
#include "monoatomic.H"
#include "Random.H"
#include "Time.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(monoatomic, 0);
defineTemplateTypeNameAndDebug(Cloud<monoatomic>, 0);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::monoatomic::move
(
monoatomic::trackingData& td,
const scalar trackTime
)
{
td.switchProcessor = false;
td.keepParticle = true;
if (special_ != SPECIAL_FROZEN)
{
return td.keepParticle;
}
const constantProperties& constProps(td.cloud().constProps(id_));
if (td.part() == trackingData::tpFirstVelocityHalfStep)
{
// First leapfrog velocity adjust part, required before tracking+force
// part
v_ += 0.5*trackTime*a_;
}
else if (td.part() == trackingData::tpLinearTrack)
{
// Leapfrog tracking part
scalar tEnd = (1.0 - stepFraction())*trackTime;
scalar dtMax = tEnd;
while (td.keepParticle && !td.switchProcessor && tEnd > ROOTVSMALL)
{
// set the lagrangian time-step
scalar dt = min(dtMax, tEnd);
dt *= trackToFace(position() + dt*v_, td);
tEnd -= dt;
stepFraction() = 1.0 - tEnd/trackTime;
}
setSitePositions(constProps);
}
else if (td.part() == trackingData::tpSecondVelocityHalfStep)
{
// Second leapfrog velocity adjust part, required after tracking+force
// part
a_ = siteForces_[0]/constProps.mass();
v_ += 0.5*trackTime*a_;
}
else if (td.part() != trackingData::tpRotationalTrack)
{
FatalErrorIn("monoatomic::move(trackingData&, const scalar)") << nl
<< td.part() << " is an invalid part of the integration method."
<< abort(FatalError);
}
return td.keepParticle;
}
void Foam::monoatomic::transformProperties(const tensor& T)
{
particle::transformProperties(T);
v_ = transform(T, v_);
a_ = transform(T, a_);
rf_ = transform(T, rf_);
sitePositions_[0] = position_ + (T & (sitePositions_[0] - position_));
siteForces_[0] = T & siteForces_[0];
}
void Foam::monoatomic::transformProperties(const vector& separation)
{
particle::transformProperties(separation);
if (special_ == SPECIAL_TETHERED)
{
specialPosition_ += separation;
}
sitePositions_[0] += separation;
}
void Foam::monoatomic::setSitePositions(const constantProperties& constProps)
{
sitePositions_[0] = position_;
}
void Foam::monoatomic::setSiteSizes(label size)
{
// Nothing required, size controlled internally
}
bool Foam::monoatomic::hitPatch
(
const polyPatch&,
trackingData&,
const label,
const scalar,
const tetIndices&
)
{
return false;
}
void Foam::monoatomic::hitProcessorPatch
(
const processorPolyPatch&,
trackingData& td
)
{
td.switchProcessor = true;
}
void Foam::monoatomic::hitWallPatch
(
const wallPolyPatch& wpp,
trackingData& td,
const tetIndices& tetIs
)
{
// Use of the normal from tetIs is not required as
// hasWallImpactDistance is false.
vector nw = normal();
nw /= mag(nw);
scalar vn = v_ & nw;
// Specular reflection
if (vn > 0)
{
v_ -= 2*vn*nw;
}
}
void Foam::monoatomic::hitPatch
(
const polyPatch&,
trackingData& td
)
{
td.keepParticle = false;
}
// ************************************************************************* //

View File

@ -0,0 +1,418 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2008-2011 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 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::monoatomic
Description
Foam::monoatomic
SourceFiles
monoatomicI.H
monoatomic.C
monoatomicIO.C
\*---------------------------------------------------------------------------*/
#ifndef monoatomic_H
#define monoatomic_H
#include "particle.H"
#include "IOstream.H"
#include "autoPtr.H"
#include "diagTensor.H"
#include "constPropSite.H"
#include "MoleculeCloud.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class monoatomic Declaration
\*---------------------------------------------------------------------------*/
class monoatomic
:
public particle
{
public:
// Values of special that are less than zero are for built-in functionality.
// Values greater than zero are user specifiable/expandable (i.e. test
// special_ >= SPECIAL_USER)
enum specialTypes
{
SPECIAL_TETHERED = -1,
SPECIAL_FROZEN = -2,
NOT_SPECIAL = 0,
SPECIAL_USER = 1
};
//- Class to hold monoatomic constant properties
class constantProperties
{
// Private data
//- Sites of mass, charge or interaction
FixedList<constPropSite, 1> sites_;
//- Which sites require electrostatic interactions
FixedList<label, 1> electrostaticSites_;
//- Which sites require pair interactions
FixedList<label, 1> pairPotSites_;
//-
scalar mass_;
public:
//-
inline constantProperties();
//- Construct from dictionary
inline constantProperties
(
const dictionary& dict,
const List<label>& siteIds
);
// Member functions
//-
inline const FixedList<constPropSite, 1>& sites() const;
//-
inline const FixedList<label, 1>& pairPotSites() const;
//-
inline const FixedList<label, 1>& electrostaticSites() const;
//-
inline label degreesOfFreedom() const;
//-
inline scalar mass() const;
//-
inline label nSites() const;
};
//- Class used to pass tracking data to the trackToFace function
class trackingData
:
public particle::TrackingData<MoleculeCloud<monoatomic> >
{
public:
enum trackPart
{
tpFirstVelocityHalfStep,
tpLinearTrack,
tpRotationalTrack,
tpSecondVelocityHalfStep,
tpAccess
};
private:
// label specifying which part of the integration algorithm is taking
label part_;
public:
// Constructors
trackingData(MoleculeCloud<monoatomic>& cloud, trackPart part)
:
particle::TrackingData<MoleculeCloud<monoatomic> >(cloud),
part_(part)
{}
// Member functions
inline label part() const
{
return part_;
}
};
private:
// Private data
//- Linear velocity of monoatomic
vector v_;
//- Total linear acceleration of monoatomic
vector a_;
//-
vector specialPosition_;
//-
scalar potentialEnergy_;
// - r_ij f_ij, stress dyad
tensor rf_;
// // - r_ij outer product f_ij: virial contribution
// tensor rDotf_;
//-
label special_;
//-
label id_;
//-
FixedList<vector, 1> siteForces_;
//-
FixedList<vector, 1> sitePositions_;
public:
//- Runtime type information
TypeName("monoatomic");
friend class Cloud<monoatomic>;
// Constructors
//- Construct with macroscopic description
inline monoatomic
(
const polyMesh& mesh,
const vector& position,
const label cellI,
const label tetFaceI,
const label tetPtI,
const scalar temperature,
const vector& bulkVelocity,
const vector& specialPosition,
const constantProperties& constProps,
trackingData& td,
const label special,
const label id
);
//- Construct from all components
inline monoatomic
(
const polyMesh& mesh,
const vector& position,
const label cellI,
const label tetFaceI,
const label tetPtI,
const vector& v,
const vector& a,
const vector& specialPosition,
const constantProperties& constProps,
const label special,
const label id
);
//- Construct from Istream
monoatomic
(
const polyMesh& mesh,
Istream& is,
bool readFields = true
);
//- Construct and return a clone
autoPtr<particle> clone() const
{
return autoPtr<particle>(new monoatomic(*this));
}
//- Factory class to read-construct particles used for
// parallel transfer
class iNew
{
const polyMesh& mesh_;
public:
iNew(const polyMesh& mesh)
:
mesh_(mesh)
{}
autoPtr<monoatomic> operator()(Istream& is) const
{
return autoPtr<monoatomic>(new monoatomic(mesh_, is, true));
}
};
// Member Functions
// Tracking
//-
bool move(trackingData&, const scalar trackTime);
//-
virtual void transformProperties(const tensor& T);
//-
virtual void transformProperties(const vector& separation);
//-
void setSitePositions(const constantProperties& constProps);
//-
void setSiteSizes(label size);
// Access
//-
inline const vector& v() const;
//-
inline vector& v();
//-
inline const vector& a() const;
//-
inline vector& a();
//-
inline const FixedList<vector, 1>& siteForces() const;
//-
inline FixedList<vector, 1>& siteForces();
//-
inline const FixedList<vector, 1>& sitePositions() const;
//-
inline FixedList<vector, 1>& sitePositions();
//-
inline const vector& specialPosition() const;
//-
inline vector& specialPosition();
//-
inline scalar potentialEnergy() const;
//-
inline scalar& potentialEnergy();
//-
inline const tensor& rf() const;
//-
inline tensor& rf();
//-
inline label special() const;
//-
inline bool tethered() const;
//-
inline label id() const;
// Member Operators
//- Overridable function to handle the particle hitting a patch
// Executed before other patch-hitting functions
bool hitPatch
(
const polyPatch&,
trackingData& td,
const label patchI,
const scalar trackFraction,
const tetIndices& tetIs
);
//- Overridable function to handle the particle hitting a processorPatch
void hitProcessorPatch
(
const processorPolyPatch&,
trackingData& td
);
//- Overridable function to handle the particle hitting a wallPatch
void hitWallPatch
(
const wallPolyPatch&,
trackingData& td,
const tetIndices&
);
//- Overridable function to handle the particle hitting a polyPatch
void hitPatch
(
const polyPatch&,
trackingData& td
);
// I-O
//- Read
static void readFields(Cloud<monoatomic>& mC);
//- Write
static void writeFields(const Cloud<monoatomic>& mC);
//- Show info
static void info(trackingData& td);
// IOstream Operators
friend Ostream& operator<<(Ostream&, const monoatomic&);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "monoatomicI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

Some files were not shown because too many files have changed in this diff Show More