Add the OpenFOAM source tree

This commit is contained in:
Henry
2014-12-10 22:40:10 +00:00
parent ee487c860d
commit 446e5777f0
13379 changed files with 3983377 additions and 0 deletions

View File

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

View File

@ -0,0 +1,10 @@
EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude
EXE_LIBS = \
-lmeshTools \
-ldynamicMesh \
-lfiniteVolume \
-lcompressibleRASModels

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object PDRMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Per faceSet the patch the faces should go into blocked baffles
blockedFaces ((blockedFacesSet blockedFaces));
//- Per faceSet the patch the faces should go into coupled baffles
coupledFaces
{
coupledFacesSet
{
wallPatchName baffleWall;
cyclicMasterPatchName baffleCyclic_half0;
}
}
//- Name of cellSet that holds the cells to fully remove
blockedCells blockedCellsSet;
//- All exposed faces that are not specified in blockedFaces go into
// this patch
defaultPatch outer;
// ************************************************************************* //

View File

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

View File

@ -0,0 +1,11 @@
EXE_INC = \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude
EXE_LIBS = \
-ldynamicMesh \
-lmeshTools \
-ltriSurface \
-llagrangian

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,112 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object autoRefineMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Surface to keep to
surface "plexi.obj";
// What is outside. These points have to be inside a cell (so not on a face!)
outsidePoints ((-0.99001 -0.99001 -0.99001));
//
// Selection of cells to refine
//
// If smallest edge of mesh > maxEdgeLen select all cut cells for refinement.
// If < maxEdgeLen select only those cut cells which are closer than
// curvatureDistance to surface
// and with cos of angle between normals on surface < curvature.
maxEdgeLen 0.1;
curvatureDistance 1.0;
curvature 0.9;
// if > 0: Remove inside cells at every step. Inside is given by number of
// layers separating outside from inside.
// (note that we cannot remove outside
// cells since these contain the outsidePoints)
// Do not use this option if you want mesh to spill through a hole which is
// not visible on the coarsest level but only becomes visible after refinement
nCutLayers 2;
// Refine until smallest edge of mesh < minEdgeLen
minEdgeLen 0.1;
// Or until the number of cells would become more than (stops one level before
// this)
cellLimit 2500000;
//
// Selection of final set
//
// Select based on side of surface. Usually select inside cells and project
// outwards or select outside cells and project inwards.
selectCut false;
selectInside false;
selectOutside true;
// Leave out cell closer than nearDistance to the surface. Usually
// 0.5*minEdgeLen. Set to -1 to disable.
nearDistance -1;
// Some cells on the surface of the selected cells might have all their
// points on the 'outside'. These would get flattened when projecting so
// are either kept and refined (selectHanging) or removed from the set
selectHanging false;
//
// Refinement parameters
//
// Type of coordinate system
coordinateSystem global;
//coordinateSystem patchLocal;
// .. and its coefficients. x,y in this case. (normal = tan1^tan2)
globalCoeffs
{
tan1 (1 0 0);
tan2 (0 1 0);
}
patchLocalCoeffs
{
patch outside; // Normal direction is facenormal of zero'th face of patch
tan1 (1 0 0);
}
// List of directions to refine
directions
(
tan1
tan2
normal
);
// refinement level difference between neighbouring cells. Set to large if
// there is no need for a limit.
splitLevel 2;
// Cut purely geometric (will cut hexes through vertices) or take topology
// into account.
geometricCut false;
// Whether to use hex topology. This will never cut hex through vertices.
useHexTopology yes;
// Write meshes from intermediate steps
writeMesh true;
// ************************************************************************* //

View File

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

View File

@ -0,0 +1,9 @@
EXE_INC = \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude
EXE_LIBS = \
-ldynamicMesh \
-lmeshTools \
-lfiniteVolume

View File

@ -0,0 +1,97 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: http://www.openfoam.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
root "";
case "";
instance "";
local "";
class dictionary;
object collapseDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// If on, after collapsing check the quality of the mesh. If bad faces are
// generated then redo the collapsing with stricter filtering.
controlMeshQuality on;
collapseEdgesCoeffs
{
// Edges shorter than this absolute value will be merged
minimumEdgeLength 1e-6;
// The maximum angle between two edges that share a point attached to
// no other edges
maximumMergeAngle 30;
}
collapseFacesCoeffs
{
// The initial face length factor
initialFaceLengthFactor 0.5;
// If the face can't be collapsed to an edge, and it has a span less than
// the target face length multiplied by this coefficient, collapse it
// to a point.
maxCollapseFaceToPointSideLengthCoeff 0.3;
// Allow early collapse of edges to a point
allowEarlyCollapseToPoint on;
// Fraction to premultiply maxCollapseFaceToPointSideLengthCoeff by if
// allowEarlyCollapseToPoint is enabled
allowEarlyCollapseCoeff 0.2;
// Defining how close to the midpoint (M) of the projected
// vertices line a projected vertex (X) can be before making this
// an invalid edge collapse
//
// X---X-g----------------M----X-----------g----X--X
//
// Only allow a collapse if all projected vertices are outwith
// guardFraction (g) of the distance form the face centre to the
// furthest vertex in the considered direction
guardFraction 0.1;
}
controlMeshQualityCoeffs
{
// Name of the dictionary that has the mesh quality coefficients used
// by motionSmoother::checkMesh
#include "meshQualityDict";
// The amount that minimumEdgeLength will be reduced by for each
// edge if that edge's collapse generates a poor quality face
edgeReductionFactor 0.5;
// The amount that initialFaceLengthFactor will be reduced by for each
// face if its collapse generates a poor quality face
faceReductionFactor 0.5;
// Maximum number of smoothing iterations for the reductionFactors
maximumSmoothingIterations 2;
// Maximum number of outer iterations is mesh quality checking is enabled
maximumIterations 10;
// Maximum number of iterations deletion of a point can cause a bad face
// to be constructed before it is forced to not be deleted
maxPointErrorCount 5;
}
// ************************************************************************* //

View File

@ -0,0 +1,247 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
collapseEdges
Description
Collapses short edges and combines edges that are in line.
- collapse short edges. Length of edges to collapse provided as argument.
- merge two edges if they are in line. Maximum angle provided as argument.
- remove unused points.
- collapse faces:
- with small areas to a single point
- that have a high aspect ratio (i.e. sliver face) to a single edge
Optionally checks the resulting mesh for bad faces and reduces the desired
face length factor for those faces attached to the bad faces.
When collapsing an edge with one point on the boundary it will leave
the boundary point intact. When both points inside it chooses random. When
both points on boundary random again.
Usage
- collapseEdges [OPTION]
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "timeSelector.H"
#include "polyTopoChange.H"
#include "fvMesh.H"
#include "polyMeshFilter.H"
#include "faceSet.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
timeSelector::addOptions(true, false);
argList::addNote
(
"Collapses small edges to a point.\n"
"Optionally collapse small faces to a point and thin faces to an edge."
);
argList::addBoolOption
(
"collapseFaces",
"Collapse small and sliver faces as well as small edges"
);
argList::addOption
(
"collapseFaceSet",
"faceSet",
"Collapse faces that are in the supplied face set"
);
# include "addOverwriteOption.H"
# include "setRootCase.H"
# include "createTime.H"
runTime.functionObjects().off();
instantList timeDirs = timeSelector::selectIfPresent(runTime, args);
# include "createMesh.H"
const word oldInstance = mesh.pointsInstance();
const bool overwrite = args.optionFound("overwrite");
const bool collapseFaces = args.optionFound("collapseFaces");
const bool collapseFaceSet = args.optionFound("collapseFaceSet");
if (collapseFaces && collapseFaceSet)
{
FatalErrorIn("main(int, char*[])")
<< "Both face zone collapsing and face collapsing have been"
<< "selected. Choose only one of:" << nl
<< " -collapseFaces" << nl
<< " -collapseFaceSet <faceSet>"
<< abort(FatalError);
}
// maintain indirectPatchFaces if it is there (default) or force
// (if collapseFaceSet option provided)
word faceSetName("indirectPatchFaces");
IOobject::readOption readFlag = IOobject::READ_IF_PRESENT;
if (args.optionReadIfPresent("collapseFaceSet", faceSetName))
{
readFlag = IOobject::MUST_READ;
}
labelIOList pointPriority
(
IOobject
(
"pointPriority",
runTime.timeName(),
runTime,
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
),
labelList(mesh.nPoints(), labelMin)
);
forAll(timeDirs, timeI)
{
runTime.setTime(timeDirs[timeI], timeI);
Info<< "Time = " << runTime.timeName() << endl;
autoPtr<polyMeshFilter> meshFilterPtr;
label nBadFaces = 0;
faceSet indirectPatchFaces
(
mesh,
faceSetName,
readFlag,
IOobject::AUTO_WRITE
);
Info<< "Read faceSet " << indirectPatchFaces.name()
<< " with "
<< returnReduce(indirectPatchFaces.size(), sumOp<label>())
<< " faces" << endl;
{
meshFilterPtr.set(new polyMeshFilter(mesh, pointPriority));
polyMeshFilter& meshFilter = meshFilterPtr();
// newMesh will be empty until it is filtered
const autoPtr<fvMesh>& newMesh = meshFilter.filteredMesh();
// Filter small edges only. This reduces the number of faces so that
// the face filtering is sped up.
nBadFaces = meshFilter.filterEdges(0);
{
polyTopoChange meshMod(newMesh());
meshMod.changeMesh(mesh, false);
polyMeshFilter::copySets(newMesh(), mesh);
}
pointPriority = meshFilter.pointPriority();
}
if (collapseFaceSet)
{
meshFilterPtr.reset(new polyMeshFilter(mesh, pointPriority));
polyMeshFilter& meshFilter = meshFilterPtr();
const autoPtr<fvMesh>& newMesh = meshFilter.filteredMesh();
// Filter faces. Pass in the number of bad faces that are present
// from the previous edge filtering to use as a stopping criterion.
meshFilter.filter(indirectPatchFaces);
{
polyTopoChange meshMod(newMesh);
meshMod.changeMesh(mesh, false);
polyMeshFilter::copySets(newMesh(), mesh);
}
pointPriority = meshFilter.pointPriority();
}
if (collapseFaces)
{
meshFilterPtr.reset(new polyMeshFilter(mesh, pointPriority));
polyMeshFilter& meshFilter = meshFilterPtr();
const autoPtr<fvMesh>& newMesh = meshFilter.filteredMesh();
// Filter faces. Pass in the number of bad faces that are present
// from the previous edge filtering to use as a stopping criterion.
meshFilter.filter(nBadFaces);
{
polyTopoChange meshMod(newMesh);
meshMod.changeMesh(mesh, false);
polyMeshFilter::copySets(newMesh(), mesh);
}
pointPriority = meshFilter.pointPriority();
}
// Write resulting mesh
if (!overwrite)
{
runTime++;
}
else
{
mesh.setInstance(oldInstance);
}
Info<< nl << "Writing collapsed mesh to time "
<< runTime.timeName() << nl << endl;
mesh.write();
pointPriority.write();
}
Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< nl << endl;
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,67 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object meshQualityDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Maximum non-orthogonality allowed. Set to 180 to disable.
maxNonOrtho 65;
//- Max skewness allowed. Set to <0 to disable.
maxBoundarySkewness 50;
//- Max skewness allowed. Set to <0 to disable.
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 1e-20;
//- Minimum quality of the tet formed by the face-centre
// and variable base point minimum decomposition triangles and
// the cell centre. 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 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.0;
//- 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

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

View File

@ -0,0 +1,9 @@
EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
EXE_LIBS = \
-lfiniteVolume \
-ldynamicMesh

View File

@ -0,0 +1,462 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
combinePatchFaces
Description
Checks for multiple patch faces on same cell and combines them.
Multiple patch faces can result from e.g. removal of refined
neighbouring cells, leaving 4 exposed faces with same owner.
Rules for merging:
- only boundary faces (since multiple internal faces between two cells
not allowed anyway)
- faces have to have same owner
- faces have to be connected via edge which are not features (so angle
between them < feature angle)
- outside of faces has to be single loop
- outside of face should not be (or just slightly) concave (so angle
between consecutive edges < concaveangle
E.g. to allow all faces on same patch to be merged:
combinePatchFaces 180 -concaveAngle 90
\*---------------------------------------------------------------------------*/
#include "PstreamReduceOps.H"
#include "argList.H"
#include "Time.H"
#include "polyTopoChange.H"
#include "polyModifyFace.H"
#include "polyAddFace.H"
#include "combineFaces.H"
#include "removePoints.H"
#include "polyMesh.H"
#include "mapPolyMesh.H"
#include "unitConversion.H"
#include "motionSmoother.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Merge faces on the same patch (usually from exposing refinement)
// Can undo merges if these cause problems.
label mergePatchFaces
(
const scalar minCos,
const scalar concaveSin,
const autoPtr<IOdictionary>& qualDictPtr,
const Time& runTime,
polyMesh& mesh
)
{
// Patch face merging engine
combineFaces faceCombiner(mesh);
// Get all sets of faces that can be merged
labelListList allFaceSets(faceCombiner.getMergeSets(minCos, concaveSin));
label nFaceSets = returnReduce(allFaceSets.size(), sumOp<label>());
Info<< "Merging " << nFaceSets << " sets of faces." << endl;
if (nFaceSets > 0)
{
// Store the faces of the face sets
List<faceList> allFaceSetsFaces(allFaceSets.size());
forAll(allFaceSets, setI)
{
allFaceSetsFaces[setI] = UIndirectList<face>
(
mesh.faces(),
allFaceSets[setI]
);
}
autoPtr<mapPolyMesh> map;
{
// Topology changes container
polyTopoChange meshMod(mesh);
// Merge all faces of a set into the first face of the set.
faceCombiner.setRefinement(allFaceSets, meshMod);
// Change the mesh (no inflation)
map = meshMod.changeMesh(mesh, false, true);
// Update fields
mesh.updateMesh(map);
// Move mesh (since morphing does not do this)
if (map().hasMotionPoints())
{
mesh.movePoints(map().preMotionPoints());
}
else
{
// Delete mesh volumes. No other way to do this?
mesh.clearOut();
}
}
// Check for errors and undo
// ~~~~~~~~~~~~~~~~~~~~~~~~~
// Faces in error.
labelHashSet errorFaces;
if (qualDictPtr.valid())
{
motionSmoother::checkMesh(false, mesh, qualDictPtr(), errorFaces);
}
else
{
mesh.checkFacePyramids(false, -SMALL, &errorFaces);
}
// Sets where the master is in error
labelHashSet errorSets;
forAll(allFaceSets, setI)
{
label newMasterI = map().reverseFaceMap()[allFaceSets[setI][0]];
if (errorFaces.found(newMasterI))
{
errorSets.insert(setI);
}
}
label nErrorSets = returnReduce(errorSets.size(), sumOp<label>());
Info<< "Detected " << nErrorSets
<< " error faces on boundaries that have been merged."
<< " These will be restored to their original faces."
<< endl;
if (nErrorSets > 0)
{
// Renumber stored faces to new vertex numbering.
forAllConstIter(labelHashSet, errorSets, iter)
{
label setI = iter.key();
faceList& setFaceVerts = allFaceSetsFaces[setI];
forAll(setFaceVerts, i)
{
inplaceRenumber(map().reversePointMap(), setFaceVerts[i]);
// Debug: check that all points are still there.
forAll(setFaceVerts[i], j)
{
label newVertI = setFaceVerts[i][j];
if (newVertI < 0)
{
FatalErrorIn("mergePatchFaces")
<< "In set:" << setI << " old face labels:"
<< allFaceSets[setI] << " new face vertices:"
<< setFaceVerts[i] << " are unmapped vertices!"
<< abort(FatalError);
}
}
}
}
// Topology changes container
polyTopoChange meshMod(mesh);
// Restore faces
forAllConstIter(labelHashSet, errorSets, iter)
{
label setI = iter.key();
const labelList& setFaces = allFaceSets[setI];
const faceList& setFaceVerts = allFaceSetsFaces[setI];
label newMasterI = map().reverseFaceMap()[setFaces[0]];
// Restore. Get face properties.
label own = mesh.faceOwner()[newMasterI];
label zoneID = mesh.faceZones().whichZone(newMasterI);
bool zoneFlip = false;
if (zoneID >= 0)
{
const faceZone& fZone = mesh.faceZones()[zoneID];
zoneFlip = fZone.flipMap()[fZone.whichFace(newMasterI)];
}
label patchID = mesh.boundaryMesh().whichPatch(newMasterI);
Pout<< "Restoring new master face " << newMasterI
<< " to vertices " << setFaceVerts[0] << endl;
// Modify the master face.
meshMod.setAction
(
polyModifyFace
(
setFaceVerts[0], // original face
newMasterI, // label of face
own, // owner
-1, // neighbour
false, // face flip
patchID, // patch for face
false, // remove from zone
zoneID, // zone for face
zoneFlip // face flip in zone
)
);
// Add the previously removed faces
for (label i = 1; i < setFaces.size(); i++)
{
Pout<< "Restoring removed face " << setFaces[i]
<< " with vertices " << setFaceVerts[i] << endl;
meshMod.setAction
(
polyAddFace
(
setFaceVerts[i], // vertices
own, // owner,
-1, // neighbour,
-1, // masterPointID,
-1, // masterEdgeID,
newMasterI, // masterFaceID,
false, // flipFaceFlux,
patchID, // patchID,
zoneID, // zoneID,
zoneFlip // zoneFlip
)
);
}
}
// Change the mesh (no inflation)
map = meshMod.changeMesh(mesh, false, true);
// Update fields
mesh.updateMesh(map);
// Move mesh (since morphing does not do this)
if (map().hasMotionPoints())
{
mesh.movePoints(map().preMotionPoints());
}
else
{
// Delete mesh volumes. No other way to do this?
mesh.clearOut();
}
}
}
else
{
Info<< "No faces merged ..." << endl;
}
return nFaceSets;
}
// Remove points not used by any face or points used by only two faces where
// the edges are in line
label mergeEdges(const scalar minCos, polyMesh& mesh)
{
Info<< "Merging all points on surface that" << nl
<< "- are used by only two boundary faces and" << nl
<< "- make an angle with a cosine of more than " << minCos
<< "." << nl << endl;
// Point removal analysis engine
removePoints pointRemover(mesh);
// Count usage of points
boolList pointCanBeDeleted;
label nRemove = pointRemover.countPointUsage(minCos, pointCanBeDeleted);
if (nRemove > 0)
{
Info<< "Removing " << nRemove
<< " straight edge points ..." << endl;
// Topology changes container
polyTopoChange meshMod(mesh);
pointRemover.setRefinement(pointCanBeDeleted, meshMod);
// Change the mesh (no inflation)
autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false, true);
// Update fields
mesh.updateMesh(map);
// Move mesh (since morphing does not do this)
if (map().hasMotionPoints())
{
mesh.movePoints(map().preMotionPoints());
}
else
{
// Delete mesh volumes. No other way to do this?
mesh.clearOut();
}
}
else
{
Info<< "No straight edges simplified and no points removed ..." << endl;
}
return nRemove;
}
int main(int argc, char *argv[])
{
# include "addOverwriteOption.H"
argList::validArgs.append("featureAngle [0..180]");
argList::addOption
(
"concaveAngle",
"degrees",
"specify concave angle [0..180] (default: 30 degrees)"
);
argList::addBoolOption
(
"meshQuality",
"read user-defined mesh quality criterions from system/meshQualityDict"
);
# include "setRootCase.H"
# include "createTime.H"
runTime.functionObjects().off();
# include "createPolyMesh.H"
const word oldInstance = mesh.pointsInstance();
const scalar featureAngle = args.argRead<scalar>(1);
const scalar minCos = Foam::cos(degToRad(featureAngle));
// Sin of angle between two consecutive edges on a face.
// If sin(angle) larger than this the face will be considered concave.
scalar concaveAngle = args.optionLookupOrDefault("concaveAngle", 30.0);
scalar concaveSin = Foam::sin(degToRad(concaveAngle));
const bool overwrite = args.optionFound("overwrite");
const bool meshQuality = args.optionFound("meshQuality");
Info<< "Merging all faces of a cell" << nl
<< " - which are on the same patch" << nl
<< " - which make an angle < " << featureAngle << " degrees"
<< nl
<< " (cos:" << minCos << ')' << nl
<< " - even when resulting face becomes concave by more than "
<< concaveAngle << " degrees" << nl
<< " (sin:" << concaveSin << ')' << nl
<< endl;
autoPtr<IOdictionary> qualDict;
if (meshQuality)
{
Info<< "Enabling user-defined geometry checks." << nl << endl;
qualDict.reset
(
new IOdictionary
(
IOobject
(
"meshQualityDict",
mesh.time().system(),
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
)
)
);
}
if (!overwrite)
{
runTime++;
}
// Merge faces on same patch
label nChanged = mergePatchFaces
(
minCos,
concaveSin,
qualDict,
runTime,
mesh
);
// Merge points on straight edges and remove unused points
if (qualDict.valid())
{
Info<< "Merging all 'loose' points on surface edges, "
<< "regardless of the angle they make." << endl;
// Surface bnound to be used to extrude. Merge all loose points.
nChanged += mergeEdges(-1, mesh);
}
else
{
nChanged += mergeEdges(minCos, mesh);
}
if (nChanged > 0)
{
if (overwrite)
{
mesh.setInstance(oldInstance);
}
Info<< "Writing morphed mesh to time " << runTime.timeName() << endl;
mesh.write();
}
else
{
Info<< "Mesh unchanged." << endl;
}
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //

View File

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

View File

@ -0,0 +1,7 @@
EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude
EXE_LIBS = \
-lmeshTools \
-ldynamicMesh

View File

@ -0,0 +1,491 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "cellSplitter.H"
#include "polyMesh.H"
#include "polyTopoChange.H"
#include "polyAddCell.H"
#include "polyAddFace.H"
#include "polyAddPoint.H"
#include "polyModifyFace.H"
#include "mapPolyMesh.H"
#include "meshTools.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(cellSplitter, 0);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::cellSplitter::getFaceInfo
(
const label faceI,
label& patchID,
label& zoneID,
label& zoneFlip
) const
{
patchID = -1;
if (!mesh_.isInternalFace(faceI))
{
patchID = mesh_.boundaryMesh().whichPatch(faceI);
}
zoneID = mesh_.faceZones().whichZone(faceI);
zoneFlip = false;
if (zoneID >= 0)
{
const faceZone& fZone = mesh_.faceZones()[zoneID];
zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
}
}
// Find the new owner of faceI (since the original cell has been split into
// newCells
Foam::label Foam::cellSplitter::newOwner
(
const label faceI,
const Map<labelList>& cellToCells
) const
{
label oldOwn = mesh_.faceOwner()[faceI];
Map<labelList>::const_iterator fnd = cellToCells.find(oldOwn);
if (fnd == cellToCells.end())
{
// Unsplit cell
return oldOwn;
}
else
{
// Look up index of face in the cells' faces.
const labelList& newCells = fnd();
const cell& cFaces = mesh_.cells()[oldOwn];
return newCells[findIndex(cFaces, faceI)];
}
}
Foam::label Foam::cellSplitter::newNeighbour
(
const label faceI,
const Map<labelList>& cellToCells
) const
{
label oldNbr = mesh_.faceNeighbour()[faceI];
Map<labelList>::const_iterator fnd = cellToCells.find(oldNbr);
if (fnd == cellToCells.end())
{
// Unsplit cell
return oldNbr;
}
else
{
// Look up index of face in the cells' faces.
const labelList& newCells = fnd();
const cell& cFaces = mesh_.cells()[oldNbr];
return newCells[findIndex(cFaces, faceI)];
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct from components
Foam::cellSplitter::cellSplitter(const polyMesh& mesh)
:
mesh_(mesh),
addedPoints_()
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::cellSplitter::~cellSplitter()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::cellSplitter::setRefinement
(
const Map<point>& cellToMidPoint,
polyTopoChange& meshMod
)
{
addedPoints_.clear();
addedPoints_.resize(cellToMidPoint.size());
//
// Introduce cellToMidPoints.
//
forAllConstIter(Map<point>, cellToMidPoint, iter)
{
label cellI = iter.key();
label anchorPoint = mesh_.cellPoints()[cellI][0];
label addedPointI =
meshMod.setAction
(
polyAddPoint
(
iter(), // point
anchorPoint, // master point
-1, // zone for point
true // supports a cell
)
);
addedPoints_.insert(cellI, addedPointI);
//Pout<< "Added point " << addedPointI
// << iter() << " in cell " << cellI << " with centre "
// << mesh_.cellCentres()[cellI] << endl;
}
//
// Add cells (first one is modified original cell)
//
Map<labelList> cellToCells(cellToMidPoint.size());
forAllConstIter(Map<point>, cellToMidPoint, iter)
{
label cellI = iter.key();
const cell& cFaces = mesh_.cells()[cellI];
// Cells created for this cell.
labelList newCells(cFaces.size());
// First pyramid is the original cell
newCells[0] = cellI;
// Add other pyramids
for (label i = 1; i < cFaces.size(); i++)
{
label addedCellI =
meshMod.setAction
(
polyAddCell
(
-1, // master point
-1, // master edge
-1, // master face
cellI, // master cell
-1 // zone
)
);
newCells[i] = addedCellI;
}
cellToCells.insert(cellI, newCells);
//Pout<< "Split cell " << cellI
// << " with centre " << mesh_.cellCentres()[cellI] << nl
// << " faces:" << cFaces << nl
// << " into :" << newCells << endl;
}
//
// Introduce internal faces. These go from edges of the cell to the mid
// point.
//
forAllConstIter(Map<point>, cellToMidPoint, iter)
{
label cellI = iter.key();
label midPointI = addedPoints_[cellI];
const cell& cFaces = mesh_.cells()[cellI];
const labelList& cEdges = mesh_.cellEdges()[cellI];
forAll(cEdges, i)
{
label edgeI = cEdges[i];
const edge& e = mesh_.edges()[edgeI];
// Get the faces on the cell using the edge
label face0, face1;
meshTools::getEdgeFaces(mesh_, cellI, edgeI, face0, face1);
// Get the cells on both sides of the face by indexing into cFaces.
// (since newly created cells are stored in cFaces order)
const labelList& newCells = cellToCells[cellI];
label cell0 = newCells[findIndex(cFaces, face0)];
label cell1 = newCells[findIndex(cFaces, face1)];
if (cell0 < cell1)
{
// Construct face to midpoint that is pointing away from
// (pyramid split off from) cellI
const face& f0 = mesh_.faces()[face0];
label index = findIndex(f0, e[0]);
bool edgeInFaceOrder = (f0[f0.fcIndex(index)] == e[1]);
// Check if cellI is the face owner
face newF(3);
if (edgeInFaceOrder == (mesh_.faceOwner()[face0] == cellI))
{
// edge used in face order.
newF[0] = e[1];
newF[1] = e[0];
newF[2] = midPointI;
}
else
{
newF[0] = e[0];
newF[1] = e[1];
newF[2] = midPointI;
}
// Now newF points away from cell0
meshMod.setAction
(
polyAddFace
(
newF, // face
cell0, // owner
cell1, // neighbour
-1, // master point
-1, // master edge
face0, // master face for addition
false, // flux flip
-1, // patch for face
-1, // zone for face
false // face zone flip
)
);
}
else
{
// Construct face to midpoint that is pointing away from
// (pyramid split off from) cellI
const face& f1 = mesh_.faces()[face1];
label index = findIndex(f1, e[0]);
bool edgeInFaceOrder = (f1[f1.fcIndex(index)] == e[1]);
// Check if cellI is the face owner
face newF(3);
if (edgeInFaceOrder == (mesh_.faceOwner()[face1] == cellI))
{
// edge used in face order.
newF[0] = e[1];
newF[1] = e[0];
newF[2] = midPointI;
}
else
{
newF[0] = e[0];
newF[1] = e[1];
newF[2] = midPointI;
}
// Now newF points away from cell1
meshMod.setAction
(
polyAddFace
(
newF, // face
cell1, // owner
cell0, // neighbour
-1, // master point
-1, // master edge
face0, // master face for addition
false, // flux flip
-1, // patch for face
-1, // zone for face
false // face zone flip
)
);
}
}
}
//
// Update all existing faces for split owner or neighbour.
//
// Mark off affected face.
boolList faceUpToDate(mesh_.nFaces(), true);
forAllConstIter(Map<point>, cellToMidPoint, iter)
{
label cellI = iter.key();
const cell& cFaces = mesh_.cells()[cellI];
forAll(cFaces, i)
{
label faceI = cFaces[i];
faceUpToDate[faceI] = false;
}
}
forAll(faceUpToDate, faceI)
{
if (!faceUpToDate[faceI])
{
const face& f = mesh_.faces()[faceI];
if (mesh_.isInternalFace(faceI))
{
label newOwn = newOwner(faceI, cellToCells);
label newNbr = newNeighbour(faceI, cellToCells);
if (newOwn < newNbr)
{
meshMod.setAction
(
polyModifyFace
(
f,
faceI,
newOwn, // owner
newNbr, // neighbour
false, // flux flip
-1, // patch for face
false, // remove from zone
-1, // zone for face
false // face zone flip
)
);
}
else
{
meshMod.setAction
(
polyModifyFace
(
f.reverseFace(),
faceI,
newNbr, // owner
newOwn, // neighbour
false, // flux flip
-1, // patch for face
false, // remove from zone
-1, // zone for face
false // face zone flip
)
);
}
}
else
{
label newOwn = newOwner(faceI, cellToCells);
label patchID, zoneID, zoneFlip;
getFaceInfo(faceI, patchID, zoneID, zoneFlip);
meshMod.setAction
(
polyModifyFace
(
mesh_.faces()[faceI],
faceI,
newOwn, // owner
-1, // neighbour
false, // flux flip
patchID, // patch for face
false, // remove from zone
zoneID, // zone for face
zoneFlip // face zone flip
)
);
}
faceUpToDate[faceI] = true;
}
}
}
void Foam::cellSplitter::updateMesh(const mapPolyMesh& morphMap)
{
// Create copy since we're deleting entries. Only if both cell and added
// point get mapped do they get inserted.
Map<label> newAddedPoints(addedPoints_.size());
forAllConstIter(Map<label>, addedPoints_, iter)
{
label oldCellI = iter.key();
label newCellI = morphMap.reverseCellMap()[oldCellI];
label oldPointI = iter();
label newPointI = morphMap.reversePointMap()[oldPointI];
if (newCellI >= 0 && newPointI >= 0)
{
newAddedPoints.insert(newCellI, newPointI);
}
}
// Copy
addedPoints_.transfer(newAddedPoints);
}
// ************************************************************************* //

View File

@ -0,0 +1,149 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::cellSplitter
Description
Does pyramidal decomposition of selected cells. So all faces will become
base of pyramid with as top a user-supplied point (usually the cell centre)
SourceFiles
cellSplitter.C
\*---------------------------------------------------------------------------*/
#ifndef cellSplitter_H
#define cellSplitter_H
#include "Map.H"
#include "edge.H"
#include "typeInfo.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class polyTopoChange;
class mapPolyMesh;
class polyMesh;
/*---------------------------------------------------------------------------*\
Class cellSplitter Declaration
\*---------------------------------------------------------------------------*/
class cellSplitter
{
// Private data
//- Reference to mesh
const polyMesh& mesh_;
//- Per cell the mid point added.
Map<label> addedPoints_;
// Private Member Functions
//- Get patch and zone info for face
void getFaceInfo
(
const label faceI,
label& patchID,
label& zoneID,
label& zoneFlip
) const;
//- Find the new owner (if any) of the face.
label newOwner
(
const label faceI,
const Map<labelList>& cellToCells
) const;
//- Find the new neighbour (if any) of the face.
label newNeighbour
(
const label faceI,
const Map<labelList>& cellToCells
) const;
//- Disallow default bitwise copy construct
cellSplitter(const cellSplitter&);
//- Disallow default bitwise assignment
void operator=(const cellSplitter&);
public:
//- Runtime type information
ClassName("cellSplitter");
// Constructors
//- Construct from mesh
cellSplitter(const polyMesh& mesh);
//- Destructor
~cellSplitter();
// Member Functions
// Edit
//- Insert mesh changes into meshMod.
// cellToMidPoint : cell to cut and position of its new midpoint
void setRefinement
(
const Map<point>& cellToMidPoint,
polyTopoChange& meshMod
);
//- Force recalculation of locally stored data on topological change
void updateMesh(const mapPolyMesh&);
// Access
//- Per cell the mid point added.
const Map<label>& addedPoints() const
{
return addedPoints_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,692 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
modifyMesh
Description
Manipulates mesh elements.
Actions are:
(boundary)points:
- move
(boundary)edges:
- split and move introduced point
(boundary)faces:
- split(triangulate) and move introduced point
edges:
- collapse
cells:
- split into polygonal base pyramids around newly introduced mid
point
Is a bit of a loose collection of mesh change drivers.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "polyMesh.H"
#include "polyTopoChange.H"
#include "mapPolyMesh.H"
#include "boundaryCutter.H"
#include "cellSplitter.H"
#include "edgeCollapser.H"
#include "meshTools.H"
#include "Pair.H"
#include "globalIndex.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Locate point on patch. Returns (mesh) point label.
label findPoint(const primitivePatch& pp, const point& nearPoint)
{
const pointField& points = pp.points();
const labelList& meshPoints = pp.meshPoints();
// Find nearest and next nearest
scalar minDistSqr = GREAT;
label minI = -1;
scalar almostMinDistSqr = GREAT;
label almostMinI = -1;
forAll(meshPoints, i)
{
label pointI = meshPoints[i];
scalar distSqr = magSqr(nearPoint - points[pointI]);
if (distSqr < minDistSqr)
{
almostMinDistSqr = minDistSqr;
almostMinI = minI;
minDistSqr = distSqr;
minI = pointI;
}
else if (distSqr < almostMinDistSqr)
{
almostMinDistSqr = distSqr;
almostMinI = pointI;
}
}
// Decide if nearPoint unique enough.
Info<< "Found to point " << nearPoint << nl
<< " nearest point : " << minI
<< " distance " << Foam::sqrt(minDistSqr)
<< " at " << points[minI] << nl
<< " next nearest point : " << almostMinI
<< " distance " << Foam::sqrt(almostMinDistSqr)
<< " at " << points[almostMinI] << endl;
if (almostMinDistSqr < 4*minDistSqr)
{
Info<< "Next nearest too close to nearest. Aborting" << endl;
return -1;
}
else
{
return minI;
}
}
// Locate edge on patch. Return mesh edge label.
label findEdge
(
const primitiveMesh& mesh,
const primitivePatch& pp,
const point& nearPoint
)
{
const pointField& localPoints = pp.localPoints();
const pointField& points = pp.points();
const labelList& meshPoints = pp.meshPoints();
const edgeList& edges = pp.edges();
// Find nearest and next nearest
scalar minDist = GREAT;
label minI = -1;
scalar almostMinDist = GREAT;
label almostMinI = -1;
forAll(edges, edgeI)
{
const edge& e = edges[edgeI];
pointHit pHit(e.line(localPoints).nearestDist(nearPoint));
if (pHit.hit())
{
if (pHit.distance() < minDist)
{
almostMinDist = minDist;
almostMinI = minI;
minDist = pHit.distance();
minI = meshTools::findEdge
(
mesh,
meshPoints[e[0]],
meshPoints[e[1]]
);
}
else if (pHit.distance() < almostMinDist)
{
almostMinDist = pHit.distance();
almostMinI = meshTools::findEdge
(
mesh,
meshPoints[e[0]],
meshPoints[e[1]]
);
}
}
}
if (minI == -1)
{
Info<< "Did not find edge close to point " << nearPoint << endl;
return -1;
}
// Decide if nearPoint unique enough.
Info<< "Found to point " << nearPoint << nl
<< " nearest edge : " << minI
<< " distance " << minDist << " endpoints "
<< mesh.edges()[minI].line(points) << nl
<< " next nearest edge : " << almostMinI
<< " distance " << almostMinDist << " endpoints "
<< mesh.edges()[almostMinI].line(points) << nl
<< endl;
if (almostMinDist < 2*minDist)
{
Info<< "Next nearest too close to nearest. Aborting" << endl;
return -1;
}
else
{
return minI;
}
}
// Find face on patch. Return mesh face label.
label findFace
(
const primitiveMesh& mesh,
const primitivePatch& pp,
const point& nearPoint
)
{
const pointField& points = pp.points();
// Find nearest and next nearest
scalar minDist = GREAT;
label minI = -1;
scalar almostMinDist = GREAT;
label almostMinI = -1;
forAll(pp, patchFaceI)
{
pointHit pHit(pp[patchFaceI].nearestPoint(nearPoint, points));
if (pHit.hit())
{
if (pHit.distance() < minDist)
{
almostMinDist = minDist;
almostMinI = minI;
minDist = pHit.distance();
minI = patchFaceI + mesh.nInternalFaces();
}
else if (pHit.distance() < almostMinDist)
{
almostMinDist = pHit.distance();
almostMinI = patchFaceI + mesh.nInternalFaces();
}
}
}
if (minI == -1)
{
Info<< "Did not find face close to point " << nearPoint << endl;
return -1;
}
// Decide if nearPoint unique enough.
Info<< "Found to point " << nearPoint << nl
<< " nearest face : " << minI
<< " distance " << minDist
<< " to face centre " << mesh.faceCentres()[minI] << nl
<< " next nearest face : " << almostMinI
<< " distance " << almostMinDist
<< " to face centre " << mesh.faceCentres()[almostMinI] << nl
<< endl;
if (almostMinDist < 2*minDist)
{
Info<< "Next nearest too close to nearest. Aborting" << endl;
return -1;
}
else
{
return minI;
}
}
// Find cell with cell centre close to given point.
label findCell(const primitiveMesh& mesh, const point& nearPoint)
{
label cellI = mesh.findCell(nearPoint);
if (cellI != -1)
{
scalar distToCcSqr = magSqr(nearPoint - mesh.cellCentres()[cellI]);
const labelList& cPoints = mesh.cellPoints()[cellI];
label minI = -1;
scalar minDistSqr = GREAT;
forAll(cPoints, i)
{
label pointI = cPoints[i];
scalar distSqr = magSqr(nearPoint - mesh.points()[pointI]);
if (distSqr < minDistSqr)
{
minDistSqr = distSqr;
minI = pointI;
}
}
// Decide if nearPoint unique enough.
Info<< "Found to point " << nearPoint << nl
<< " nearest cell : " << cellI
<< " distance " << Foam::sqrt(distToCcSqr)
<< " to cell centre " << mesh.cellCentres()[cellI] << nl
<< " nearest mesh point : " << minI
<< " distance " << Foam::sqrt(minDistSqr)
<< " to " << mesh.points()[minI] << nl
<< endl;
if (minDistSqr < 4*distToCcSqr)
{
Info<< "Mesh point too close to nearest cell centre. Aborting"
<< endl;
cellI = -1;
}
}
return cellI;
}
int main(int argc, char *argv[])
{
# include "addOverwriteOption.H"
# include "setRootCase.H"
# include "createTime.H"
runTime.functionObjects().off();
# include "createPolyMesh.H"
const word oldInstance = mesh.pointsInstance();
const bool overwrite = args.optionFound("overwrite");
Info<< "Reading modifyMeshDict\n" << endl;
IOdictionary dict
(
IOobject
(
"modifyMeshDict",
runTime.system(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
);
// Read all from the dictionary.
List<Pair<point> > pointsToMove(dict.lookup("pointsToMove"));
List<Pair<point> > edgesToSplit(dict.lookup("edgesToSplit"));
List<Pair<point> > facesToTriangulate
(
dict.lookup("facesToTriangulate")
);
bool cutBoundary =
(
pointsToMove.size()
|| edgesToSplit.size()
|| facesToTriangulate.size()
);
List<Pair<point> > edgesToCollapse(dict.lookup("edgesToCollapse"));
bool collapseEdge = edgesToCollapse.size();
List<Pair<point> > cellsToPyramidise(dict.lookup("cellsToSplit"));
bool cellsToSplit = cellsToPyramidise.size();
// List<Tuple2<pointField,point> >
// cellsToCreate(dict.lookup("cellsToCreate"));
Info<< "Read from " << dict.name() << nl
<< " Boundary cutting module:" << nl
<< " points to move :" << pointsToMove.size() << nl
<< " edges to split :" << edgesToSplit.size() << nl
<< " faces to triangulate:" << facesToTriangulate.size() << nl
<< " Cell splitting module:" << nl
<< " cells to split :" << cellsToPyramidise.size() << nl
<< " Edge collapsing module:" << nl
<< " edges to collapse :" << edgesToCollapse.size() << nl
//<< " cells to create :" << cellsToCreate.size() << nl
<< endl;
if
(
(cutBoundary && collapseEdge)
|| (cutBoundary && cellsToSplit)
|| (collapseEdge && cellsToSplit)
)
{
FatalErrorIn(args.executable())
<< "Used more than one mesh modifying module "
<< "(boundary cutting, cell splitting, edge collapsing)" << nl
<< "Please do them in separate passes." << exit(FatalError);
}
// Get calculating engine for all of outside
const SubList<face> outsideFaces
(
mesh.faces(),
mesh.nFaces() - mesh.nInternalFaces(),
mesh.nInternalFaces()
);
primitivePatch allBoundary(outsideFaces, mesh.points());
// Look up mesh labels and convert to input for boundaryCutter.
bool validInputs = true;
Info<< nl << "Looking up points to move ..." << nl << endl;
Map<point> pointToPos(pointsToMove.size());
forAll(pointsToMove, i)
{
const Pair<point>& pts = pointsToMove[i];
label pointI = findPoint(allBoundary, pts.first());
if (pointI == -1 || !pointToPos.insert(pointI, pts.second()))
{
Info<< "Could not insert mesh point " << pointI
<< " for input point " << pts.first() << nl
<< "Perhaps the point is already marked for moving?" << endl;
validInputs = false;
}
}
Info<< nl << "Looking up edges to split ..." << nl << endl;
Map<List<point> > edgeToCuts(edgesToSplit.size());
forAll(edgesToSplit, i)
{
const Pair<point>& pts = edgesToSplit[i];
label edgeI = findEdge(mesh, allBoundary, pts.first());
if
(
edgeI == -1
|| !edgeToCuts.insert(edgeI, List<point>(1, pts.second()))
)
{
Info<< "Could not insert mesh edge " << edgeI
<< " for input point " << pts.first() << nl
<< "Perhaps the edge is already marked for cutting?" << endl;
validInputs = false;
}
}
Info<< nl << "Looking up faces to triangulate ..." << nl << endl;
Map<point> faceToDecompose(facesToTriangulate.size());
forAll(facesToTriangulate, i)
{
const Pair<point>& pts = facesToTriangulate[i];
label faceI = findFace(mesh, allBoundary, pts.first());
if (faceI == -1 || !faceToDecompose.insert(faceI, pts.second()))
{
Info<< "Could not insert mesh face " << faceI
<< " for input point " << pts.first() << nl
<< "Perhaps the face is already marked for splitting?" << endl;
validInputs = false;
}
}
Info<< nl << "Looking up cells to convert to pyramids around"
<< " cell centre ..." << nl << endl;
Map<point> cellToPyrCentre(cellsToPyramidise.size());
forAll(cellsToPyramidise, i)
{
const Pair<point>& pts = cellsToPyramidise[i];
label cellI = findCell(mesh, pts.first());
if (cellI == -1 || !cellToPyrCentre.insert(cellI, pts.second()))
{
Info<< "Could not insert mesh cell " << cellI
<< " for input point " << pts.first() << nl
<< "Perhaps the cell is already marked for splitting?" << endl;
validInputs = false;
}
}
Info<< nl << "Looking up edges to collapse ..." << nl << endl;
Map<point> edgeToPos(edgesToCollapse.size());
forAll(edgesToCollapse, i)
{
const Pair<point>& pts = edgesToCollapse[i];
label edgeI = findEdge(mesh, allBoundary, pts.first());
if (edgeI == -1 || !edgeToPos.insert(edgeI, pts.second()))
{
Info<< "Could not insert mesh edge " << edgeI
<< " for input point " << pts.first() << nl
<< "Perhaps the edge is already marked for collaping?" << endl;
validInputs = false;
}
}
if (!validInputs)
{
Info<< nl << "There was a problem in one of the inputs in the"
<< " dictionary. Not modifying mesh." << endl;
}
else if (cellToPyrCentre.size())
{
Info<< nl << "All input cells located. Modifying mesh." << endl;
// Mesh change engine
cellSplitter cutter(mesh);
// Topo change container
polyTopoChange meshMod(mesh);
// Insert commands into meshMod
cutter.setRefinement(cellToPyrCentre, meshMod);
// Do changes
autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh, false);
if (morphMap().hasMotionPoints())
{
mesh.movePoints(morphMap().preMotionPoints());
}
cutter.updateMesh(morphMap());
if (!overwrite)
{
runTime++;
}
else
{
mesh.setInstance(oldInstance);
}
// Write resulting mesh
Info<< "Writing modified mesh to time " << runTime.timeName() << endl;
mesh.write();
}
else if (edgeToPos.size())
{
Info<< nl << "All input edges located. Modifying mesh." << endl;
// Mesh change engine
edgeCollapser cutter(mesh);
const edgeList& edges = mesh.edges();
const pointField& points = mesh.points();
pointField newPoints(points);
PackedBoolList collapseEdge(mesh.nEdges());
Map<point> collapsePointToLocation(mesh.nPoints());
// Get new positions and construct collapse network
forAllConstIter(Map<point>, edgeToPos, iter)
{
label edgeI = iter.key();
const edge& e = edges[edgeI];
collapseEdge[edgeI] = true;
collapsePointToLocation.set(e[1], points[e[0]]);
newPoints[e[0]] = iter();
}
// Move master point to destination.
mesh.movePoints(newPoints);
List<pointEdgeCollapse> allPointInfo;
const globalIndex globalPoints(mesh.nPoints());
labelList pointPriority(mesh.nPoints(), 0);
cutter.consistentCollapse
(
globalPoints,
pointPriority,
collapsePointToLocation,
collapseEdge,
allPointInfo
);
// Topo change container
polyTopoChange meshMod(mesh);
// Insert
cutter.setRefinement(allPointInfo, meshMod);
// Do changes
autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh, false);
if (morphMap().hasMotionPoints())
{
mesh.movePoints(morphMap().preMotionPoints());
}
// Not implemented yet:
//cutter.updateMesh(morphMap());
if (!overwrite)
{
runTime++;
}
else
{
mesh.setInstance(oldInstance);
}
// Write resulting mesh
Info<< "Writing modified mesh to time " << runTime.timeName() << endl;
mesh.write();
}
else
{
Info<< nl << "All input points located. Modifying mesh." << endl;
// Mesh change engine
boundaryCutter cutter(mesh);
// Topo change container
polyTopoChange meshMod(mesh);
// Insert commands into meshMod
cutter.setRefinement
(
pointToPos,
edgeToCuts,
Map<labelPair>(0), // Faces to split diagonally
faceToDecompose, // Faces to triangulate
meshMod
);
// Do changes
autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh, false);
if (morphMap().hasMotionPoints())
{
mesh.movePoints(morphMap().preMotionPoints());
}
cutter.updateMesh(morphMap());
if (!overwrite)
{
runTime++;
}
else
{
mesh.setInstance(oldInstance);
}
// Write resulting mesh
Info<< "Writing modified mesh to time " << runTime.timeName() << endl;
mesh.write();
}
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,79 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object modifyMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Move boundary points:
// Every entry is two coordinates. First one is location of the point to move,
// the second is the position to move to.
pointsToMove
(
(( -0.17861 -0.45073 0.75276)( -0.18 -0.45073 0.75276))
);
// Split boundary edge in two:
// First coord is a point on the (boundary) edge to cut, second is the
// position of the newly introduced point
edgesToSplit
(
(( -0.17692 -0.45312 0.74516)( -0.18 -0.45 0.742))
);
// Triangulate a boundary face:
// First coord is a point on the face to triangulate. It will introduce a
// point on the face, triangulate and move the point to the second coordinate.
facesToTriangulate
(
(( -0.039123 -0.45045 0.74083) (-0.03844 -0.45049 0.73572))
);
// Boundary edges to collapse. First coord is point on the edge, second
// is coordinate to collapse to.
edgesToCollapse
(
((0.054975 0.099987 0.0044074)(0.054975 0.099987 0.0044074))
);
// Split cells:
// First coord is a point inside the cell to split. A point inside the cell will
// be introduced and the cell will get decomposed into polygonal base pyramids
// with this new point as top. (so the original faces will not get split)
cellsToSplit
(
(( -0.039123 -0.45045 0.74083) (-0.03844 -0.45049 0.73572))
);
// Change patch:
// Changes patchID of boundary faces. Coord selects the face, label is the
// patch index.
facesToRepatch
(
(( -0.039123 -0.45045 0.74083) 1)
);
//// Create cell:
//// Creates a cell on the boundary given a face covering a cavity. Gets
//// the vertices of the face (outwards pointing normal) and a point internal
//// to the new cell. (used to check the orientation of the face). Walks all
//// boundary faces reachable from any edge on the face and constructs cell
//// from it.
//cellsToCreate
//(
// (
// ((0 0 0) (1 0 0) (1 1 0) (0 1 0)) // vertices of face
// (0.5 0.5 0.1) // cell centre
// )
//);
// ************************************************************************* //

View File

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

View File

@ -0,0 +1,11 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-ldynamicMesh \
-lmeshTools \
-lfiniteVolume \
-lgenericPatchFields

View File

@ -0,0 +1,204 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
refineHexMesh
Description
Refines a hex mesh by 2x2x2 cell splitting.
\*---------------------------------------------------------------------------*/
#include "fvMesh.H"
#include "pointMesh.H"
#include "argList.H"
#include "Time.H"
#include "hexRef8.H"
#include "cellSet.H"
#include "OFstream.H"
#include "meshTools.H"
#include "IFstream.H"
#include "polyTopoChange.H"
#include "mapPolyMesh.H"
#include "volMesh.H"
#include "surfaceMesh.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "pointFields.H"
#include "ReadFields.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
#include "addOverwriteOption.H"
#include "addRegionOption.H"
argList::validArgs.append("cellSet");
argList::addBoolOption
(
"minSet",
"remove cells from input cellSet to keep to 2:1 ratio"
" (default is to extend set)"
);
#include "setRootCase.H"
#include "createTime.H"
runTime.functionObjects().off();
#include "createNamedMesh.H"
const word oldInstance = mesh.pointsInstance();
word cellSetName(args.args()[1]);
const bool overwrite = args.optionFound("overwrite");
const bool minSet = args.optionFound("minSet");
Info<< "Reading cells to refine from cellSet " << cellSetName
<< nl << endl;
cellSet cellsToRefine(mesh, cellSetName);
Info<< "Read " << returnReduce(cellsToRefine.size(), sumOp<label>())
<< " cells to refine from cellSet " << cellSetName << nl
<< endl;
// Read objects in time directory
IOobjectList objects(mesh, runTime.timeName());
// Read vol fields.
PtrList<volScalarField> vsFlds;
ReadFields(mesh, objects, vsFlds);
PtrList<volVectorField> vvFlds;
ReadFields(mesh, objects, vvFlds);
PtrList<volSphericalTensorField> vstFlds;
ReadFields(mesh, objects, vstFlds);
PtrList<volSymmTensorField> vsymtFlds;
ReadFields(mesh, objects, vsymtFlds);
PtrList<volTensorField> vtFlds;
ReadFields(mesh, objects, vtFlds);
// Read surface fields.
PtrList<surfaceScalarField> ssFlds;
ReadFields(mesh, objects, ssFlds);
PtrList<surfaceVectorField> svFlds;
ReadFields(mesh, objects, svFlds);
PtrList<surfaceSphericalTensorField> sstFlds;
ReadFields(mesh, objects, sstFlds);
PtrList<surfaceSymmTensorField> ssymtFlds;
ReadFields(mesh, objects, ssymtFlds);
PtrList<surfaceTensorField> stFlds;
ReadFields(mesh, objects, stFlds);
// Read point fields
PtrList<pointScalarField> psFlds;
ReadFields(pointMesh::New(mesh), objects, psFlds);
PtrList<pointVectorField> pvFlds;
ReadFields(pointMesh::New(mesh), objects, pvFlds);
// Construct refiner without unrefinement. Read existing point/cell level.
hexRef8 meshCutter(mesh);
// Some stats
Info<< "Read mesh:" << nl
<< " cells:" << mesh.globalData().nTotalCells() << nl
<< " faces:" << mesh.globalData().nTotalFaces() << nl
<< " points:" << mesh.globalData().nTotalPoints() << nl
<< " cellLevel :"
<< " min:" << gMin(meshCutter.cellLevel())
<< " max:" << gMax(meshCutter.cellLevel()) << nl
<< " pointLevel :"
<< " min:" << gMin(meshCutter.pointLevel())
<< " max:" << gMax(meshCutter.pointLevel()) << nl
<< endl;
// Maintain 2:1 ratio
labelList newCellsToRefine
(
meshCutter.consistentRefinement
(
cellsToRefine.toc(),
!minSet // extend set
)
);
// Mesh changing engine.
polyTopoChange meshMod(mesh);
// Play refinement commands into mesh changer.
meshCutter.setRefinement(newCellsToRefine, meshMod);
if (!overwrite)
{
runTime++;
}
// Create mesh, return map from old to new mesh.
autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
// Update fields
mesh.updateMesh(map);
// Update numbering of cells/vertices.
meshCutter.updateMesh(map);
// Optionally inflate mesh
if (map().hasMotionPoints())
{
mesh.movePoints(map().preMotionPoints());
}
Info<< "Refined from " << returnReduce(map().nOldCells(), sumOp<label>())
<< " to " << mesh.globalData().nTotalCells() << " cells." << nl << endl;
if (overwrite)
{
mesh.setInstance(oldInstance);
meshCutter.setInstance(oldInstance);
}
Info<< "Writing mesh to " << runTime.timeName() << endl;
mesh.write();
meshCutter.write();
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

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

View File

@ -0,0 +1,7 @@
EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude
EXE_LIBS = \
-ldynamicMesh \
-lmeshTools

View File

@ -0,0 +1,244 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
refineWallLayer
Description
Utility to refine cells next to patches.
Takes a patchName and number of layers to refine. Works out cells within
these layers and refines those in the wall-normal direction.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "polyTopoChange.H"
#include "polyTopoChanger.H"
#include "mapPolyMesh.H"
#include "polyMesh.H"
#include "cellCuts.H"
#include "cellSet.H"
#include "meshCutter.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
#include "addOverwriteOption.H"
argList::noParallel();
argList::validArgs.append("patchName");
argList::validArgs.append("edgeWeight");
argList::addOption
(
"useSet",
"name",
"restrict cells to refine based on specified cellSet name"
);
# include "setRootCase.H"
# include "createTime.H"
runTime.functionObjects().off();
# include "createPolyMesh.H"
const word oldInstance = mesh.pointsInstance();
const word patchName = args[1];
const scalar weight = args.argRead<scalar>(2);
const bool overwrite = args.optionFound("overwrite");
label patchID = mesh.boundaryMesh().findPatchID(patchName);
if (patchID == -1)
{
FatalErrorIn(args.executable())
<< "Cannot find patch " << patchName << endl
<< "Valid patches are " << mesh.boundaryMesh().names()
<< exit(FatalError);
}
const polyPatch& pp = mesh.boundaryMesh()[patchID];
// Cells cut
labelHashSet cutCells(4*pp.size());
const labelList& meshPoints = pp.meshPoints();
forAll(meshPoints, pointI)
{
label meshPointI = meshPoints[pointI];
const labelList& pCells = mesh.pointCells()[meshPointI];
forAll(pCells, pCellI)
{
cutCells.insert(pCells[pCellI]);
}
}
Info<< "Selected " << cutCells.size()
<< " cells connected to patch " << pp.name() << endl << endl;
//
// List of cells to refine
//
word setName;
if (args.optionReadIfPresent("useSet", setName))
{
Info<< "Subsetting cells to cut based on cellSet"
<< setName << nl << endl;
cellSet cells(mesh, setName);
Info<< "Read " << cells.size() << " cells from cellSet "
<< cells.instance()/cells.local()/cells.name()
<< nl << endl;
forAllConstIter(cellSet, cells, iter)
{
cutCells.erase(iter.key());
}
Info<< "Removed from cells to cut all the ones not in set "
<< setName << nl << endl;
}
// Mark all meshpoints on patch
boolList vertOnPatch(mesh.nPoints(), false);
forAll(meshPoints, pointI)
{
const label meshPointI = meshPoints[pointI];
vertOnPatch[meshPointI] = true;
}
// Mark cut edges.
DynamicList<label> allCutEdges(pp.nEdges());
DynamicList<scalar> allCutEdgeWeights(pp.nEdges());
forAll(meshPoints, pointI)
{
label meshPointI = meshPoints[pointI];
const labelList& pEdges = mesh.pointEdges()[meshPointI];
forAll(pEdges, pEdgeI)
{
const label edgeI = pEdges[pEdgeI];
const edge& e = mesh.edges()[edgeI];
label otherPointI = e.otherVertex(meshPointI);
if (!vertOnPatch[otherPointI])
{
allCutEdges.append(edgeI);
if (e.start() == meshPointI)
{
allCutEdgeWeights.append(weight);
}
else
{
allCutEdgeWeights.append(1 - weight);
}
}
}
}
allCutEdges.shrink();
allCutEdgeWeights.shrink();
Info<< "Cutting:" << nl
<< " cells:" << cutCells.size() << nl
<< " edges:" << allCutEdges.size() << nl
<< endl;
// Transfer DynamicLists to straight ones.
scalarField cutEdgeWeights;
cutEdgeWeights.transfer(allCutEdgeWeights);
allCutEdgeWeights.clear();
// Gets cuts across cells from cuts through edges.
cellCuts cuts
(
mesh,
cutCells.toc(), // cells candidate for cutting
labelList(0), // cut vertices
allCutEdges, // cut edges
cutEdgeWeights // weight on cut edges
);
polyTopoChange meshMod(mesh);
// Cutting engine
meshCutter cutter(mesh);
// Insert mesh refinement into polyTopoChange.
cutter.setRefinement(cuts, meshMod);
// Do all changes
Info<< "Morphing ..." << endl;
if (!overwrite)
{
runTime++;
}
autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh, false);
if (morphMap().hasMotionPoints())
{
mesh.movePoints(morphMap().preMotionPoints());
}
// Update stored labels on meshCutter.
cutter.updateMesh(morphMap());
if (overwrite)
{
mesh.setInstance(oldInstance);
}
// Write resulting mesh
Info<< "Writing refined morphMesh to time " << runTime.timeName() << endl;
mesh.write();
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

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

View File

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

View File

@ -0,0 +1,368 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
refinementLevel
Description
Tries to figure out what the refinement level is on refined cartesian
meshes. Run BEFORE snapping.
Writes
- volScalarField 'refinementLevel' with current refinement level.
- cellSet 'refCells' which are the cells that need to be refined to satisfy
2:1 refinement.
Works by dividing cells into volume bins.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "polyMesh.H"
#include "cellSet.H"
#include "SortableList.H"
#include "labelIOList.H"
#include "fvMesh.H"
#include "volFields.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Return true if any cells had to be split to keep a difference between
// neighbouring refinement levels < limitDiff. Puts cells into refCells and
// update refLevel to account for refinement.
bool limitRefinementLevel
(
const primitiveMesh& mesh,
labelList& refLevel,
cellSet& refCells
)
{
const labelListList& cellCells = mesh.cellCells();
label oldNCells = refCells.size();
forAll(cellCells, cellI)
{
const labelList& cCells = cellCells[cellI];
forAll(cCells, i)
{
if (refLevel[cCells[i]] > (refLevel[cellI]+1))
{
// Found neighbour with >=2 difference in refLevel.
refCells.insert(cellI);
refLevel[cellI]++;
break;
}
}
}
if (refCells.size() > oldNCells)
{
Info<< "Added an additional " << refCells.size() - oldNCells
<< " cells to satisfy 1:2 refinement level"
<< endl;
return true;
}
else
{
return false;
}
}
int main(int argc, char *argv[])
{
argList::addBoolOption
(
"readLevel",
"read level from refinementLevel file"
);
#include "setRootCase.H"
#include "createTime.H"
#include "createPolyMesh.H"
Info<< "Dividing cells into bins depending on cell volume.\nThis will"
<< " correspond to refinement levels for a mesh with only 2x2x2"
<< " refinement\n"
<< "The upper range for every bin is always 1.1 times the lower range"
<< " to allow for some truncation error."
<< nl << endl;
const bool readLevel = args.optionFound("readLevel");
const scalarField& vols = mesh.cellVolumes();
SortableList<scalar> sortedVols(vols);
// All cell labels, sorted per bin.
DynamicList<DynamicList<label> > bins;
// Lower/upper limits
DynamicList<scalar> lowerLimits;
DynamicList<scalar> upperLimits;
// Create bin0. Have upperlimit as factor times lowerlimit.
bins.append(DynamicList<label>());
lowerLimits.append(sortedVols[0]);
upperLimits.append(1.1 * lowerLimits.last());
forAll(sortedVols, i)
{
if (sortedVols[i] > upperLimits.last())
{
// New value outside of current bin
// Shrink old bin.
DynamicList<label>& bin = bins.last();
bin.shrink();
Info<< "Collected " << bin.size() << " elements in bin "
<< lowerLimits.last() << " .. "
<< upperLimits.last() << endl;
// Create new bin.
bins.append(DynamicList<label>());
lowerLimits.append(sortedVols[i]);
upperLimits.append(1.1 * lowerLimits.last());
Info<< "Creating new bin " << lowerLimits.last()
<< " .. " << upperLimits.last()
<< endl;
}
// Append to current bin.
DynamicList<label>& bin = bins.last();
bin.append(sortedVols.indices()[i]);
}
Info<< endl;
bins.last().shrink();
bins.shrink();
lowerLimits.shrink();
upperLimits.shrink();
//
// Write to cellSets.
//
Info<< "Volume bins:" << nl;
forAll(bins, binI)
{
const DynamicList<label>& bin = bins[binI];
cellSet cells(mesh, "vol" + name(binI), bin.size());
forAll(bin, i)
{
cells.insert(bin[i]);
}
Info<< " " << lowerLimits[binI] << " .. " << upperLimits[binI]
<< " : writing " << bin.size() << " cells to cellSet "
<< cells.name() << endl;
cells.write();
}
//
// Convert bins into refinement level.
//
// Construct fvMesh to be able to construct volScalarField
fvMesh fMesh
(
IOobject
(
fvMesh::defaultRegion,
runTime.timeName(),
runTime
),
xferCopy(mesh.points()), // could we safely re-use the data?
xferCopy(mesh.faces()),
xferCopy(mesh.cells())
);
// Add the boundary patches
const polyBoundaryMesh& patches = mesh.boundaryMesh();
List<polyPatch*> p(patches.size());
forAll(p, patchI)
{
p[patchI] = patches[patchI].clone(fMesh.boundaryMesh()).ptr();
}
fMesh.addFvPatches(p);
// Refinement level
IOobject refHeader
(
"refinementLevel",
runTime.timeName(),
polyMesh::defaultRegion,
runTime
);
if (!readLevel && refHeader.headerOk())
{
WarningIn(args.executable())
<< "Detected " << refHeader.name() << " file in "
<< polyMesh::defaultRegion << " directory. Please remove to"
<< " recreate it or use the -readLevel option to use it"
<< endl;
return 1;
}
labelIOList refLevel
(
IOobject
(
"refinementLevel",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
labelList(mesh.nCells(), 0)
);
if (readLevel)
{
refLevel = labelIOList(refHeader);
}
// Construct volScalarField with same info for post processing
volScalarField postRefLevel
(
IOobject
(
"refinementLevel",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
fMesh,
dimensionedScalar("zero", dimless/dimTime, 0)
);
// Set cell values
forAll(bins, binI)
{
const DynamicList<label>& bin = bins[binI];
forAll(bin, i)
{
refLevel[bin[i]] = bins.size() - binI - 1;
postRefLevel[bin[i]] = refLevel[bin[i]];
}
}
// For volScalarField: set boundary values to same as cell.
// Note: could also put
// zeroGradient b.c. on postRefLevel and do evaluate.
forAll(postRefLevel.boundaryField(), patchI)
{
const polyPatch& pp = patches[patchI];
fvPatchScalarField& bField = postRefLevel.boundaryField()[patchI];
Info<< "Setting field for patch "<< endl;
forAll(bField, faceI)
{
label own = mesh.faceOwner()[pp.start() + faceI];
bField[faceI] = postRefLevel[own];
}
}
Info<< "Determined current refinement level and writing to "
<< postRefLevel.name() << " (as volScalarField; for post processing)"
<< nl
<< polyMesh::defaultRegion/refLevel.name()
<< " (as labelIOList; for meshing)" << nl
<< endl;
refLevel.write();
postRefLevel.write();
// Find out cells to refine to keep to 2:1 refinement level restriction
// Cells to refine
cellSet refCells(mesh, "refCells", 100);
while
(
limitRefinementLevel
(
mesh,
refLevel, // current refinement level
refCells // cells to refine
)
)
{}
if (refCells.size())
{
Info<< "Collected " << refCells.size() << " cells that need to be"
<< " refined to get closer to overall 2:1 refinement level limit"
<< nl
<< "Written cells to be refined to cellSet " << refCells.name()
<< nl << endl;
refCells.write();
Info<< "After refinement this tool can be run again to see if the 2:1"
<< " limit is observed all over the mesh" << nl << endl;
}
else
{
Info<< "All cells in the mesh observe the 2:1 refinement level limit"
<< nl << endl;
}
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //

View File

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

View File

@ -0,0 +1,10 @@
EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude
EXE_LIBS = \
-lmeshTools \
-ldynamicMesh \
-lfiniteVolume \
-lgenericPatchFields

View File

@ -0,0 +1,186 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
removeFaces
Description
Utility to remove faces (combines cells on both sides).
Takes faceSet of candidates for removal and writes faceSet with faces that
will actually be removed. (because e.g. would cause two faces between the
same cells). See removeFaces in dynamicMesh library for constraints.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "polyTopoChange.H"
#include "faceSet.H"
#include "removeFaces.H"
#include "ReadFields.H"
#include "volFields.H"
#include "surfaceFields.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
# include "addOverwriteOption.H"
argList::validArgs.append("faceSet");
# include "setRootCase.H"
# include "createTime.H"
runTime.functionObjects().off();
# include "createMesh.H"
const word oldInstance = mesh.pointsInstance();
const word setName = args[1];
const bool overwrite = args.optionFound("overwrite");
// Read faces
faceSet candidateSet(mesh, setName);
Pout<< "Read " << candidateSet.size() << " faces to remove" << nl
<< endl;
labelList candidates(candidateSet.toc());
// Face removal engine. No checking for not merging boundary faces.
removeFaces faceRemover(mesh, 2);
// Get compatible set of faces and connected sets of cells.
labelList cellRegion;
labelList cellRegionMaster;
labelList facesToRemove;
faceRemover.compatibleRemoves
(
candidates,
cellRegion,
cellRegionMaster,
facesToRemove
);
{
faceSet compatibleRemoves(mesh, "compatibleRemoves", facesToRemove);
Pout<< "Original faces to be removed:" << candidateSet.size() << nl
<< "New faces to be removed:" << compatibleRemoves.size() << nl
<< endl;
Pout<< "Writing new faces to be removed to faceSet "
<< compatibleRemoves.instance()
/compatibleRemoves.local()
/compatibleRemoves.name()
<< endl;
compatibleRemoves.write();
}
// Read objects in time directory
IOobjectList objects(mesh, runTime.timeName());
// Read vol fields.
PtrList<volScalarField> vsFlds;
ReadFields(mesh, objects, vsFlds);
PtrList<volVectorField> vvFlds;
ReadFields(mesh, objects, vvFlds);
PtrList<volSphericalTensorField> vstFlds;
ReadFields(mesh, objects, vstFlds);
PtrList<volSymmTensorField> vsymtFlds;
ReadFields(mesh, objects, vsymtFlds);
PtrList<volTensorField> vtFlds;
ReadFields(mesh, objects, vtFlds);
// Read surface fields.
PtrList<surfaceScalarField> ssFlds;
ReadFields(mesh, objects, ssFlds);
PtrList<surfaceVectorField> svFlds;
ReadFields(mesh, objects, svFlds);
PtrList<surfaceSphericalTensorField> sstFlds;
ReadFields(mesh, objects, sstFlds);
PtrList<surfaceSymmTensorField> ssymtFlds;
ReadFields(mesh, objects, ssymtFlds);
PtrList<surfaceTensorField> stFlds;
ReadFields(mesh, objects, stFlds);
// Topo changes container
polyTopoChange meshMod(mesh);
// Insert mesh refinement into polyTopoChange.
faceRemover.setRefinement
(
facesToRemove,
cellRegion,
cellRegionMaster,
meshMod
);
autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh, false);
mesh.updateMesh(morphMap);
// Move mesh (since morphing does not do this)
if (morphMap().hasMotionPoints())
{
mesh.movePoints(morphMap().preMotionPoints());
}
// Update numbering of cells/vertices.
faceRemover.updateMesh(morphMap);
if (!overwrite)
{
runTime++;
}
else
{
mesh.setInstance(oldInstance);
}
// Take over refinement levels and write to new time directory.
Pout<< "Writing mesh to time " << runTime.timeName() << endl;
mesh.write();
Pout<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,5 @@
edgeStats.C
selectCells.C
EXE = $(FOAM_APPBIN)/selectCells

View File

@ -0,0 +1,12 @@
EXE_INC = \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude
EXE_LIBS = \
-ldynamicMesh \
-lmeshTools \
-ltriSurface \
-llagrangian

View File

@ -0,0 +1,221 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "edgeStats.H"
#include "Time.H"
#include "polyMesh.H"
#include "Ostream.H"
#include "twoDPointCorrector.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const Foam::scalar Foam::edgeStats::edgeTol_ = 1e-3;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::direction Foam::edgeStats::getNormalDir
(
const twoDPointCorrector* correct2DPtr
) const
{
direction dir = 3;
if (correct2DPtr)
{
const vector& normal = correct2DPtr->planeNormal();
if (mag(normal & vector(1, 0, 0)) > 1-edgeTol_)
{
dir = 0;
}
else if (mag(normal & vector(0, 1, 0)) > 1-edgeTol_)
{
dir = 1;
}
else if (mag(normal & vector(0, 0, 1)) > 1-edgeTol_)
{
dir = 2;
}
}
return dir;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct from mesh
Foam::edgeStats::edgeStats(const polyMesh& mesh)
:
mesh_(mesh),
normalDir_(3)
{
IOobject motionObj
(
"motionProperties",
mesh.time().constant(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
);
if (motionObj.headerOk())
{
Info<< "Reading " << mesh.time().constant() / "motionProperties"
<< endl << endl;
IOdictionary motionProperties(motionObj);
Switch twoDMotion(motionProperties.lookup("twoDMotion"));
if (twoDMotion)
{
Info<< "Correcting for 2D motion" << endl << endl;
autoPtr<twoDPointCorrector> correct2DPtr
(
new twoDPointCorrector(mesh)
);
normalDir_ = getNormalDir(&correct2DPtr());
}
}
}
// Construct from components
Foam::edgeStats::edgeStats
(
const polyMesh& mesh,
const twoDPointCorrector* correct2DPtr
)
:
mesh_(mesh),
normalDir_(getNormalDir(correct2DPtr))
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::scalar Foam::edgeStats::minLen(Ostream& os) const
{
label nX = 0;
label nY = 0;
label nZ = 0;
scalar minX = GREAT;
scalar maxX = -GREAT;
vector x(1, 0, 0);
scalar minY = GREAT;
scalar maxY = -GREAT;
vector y(0, 1, 0);
scalar minZ = GREAT;
scalar maxZ = -GREAT;
vector z(0, 0, 1);
scalar minOther = GREAT;
scalar maxOther = -GREAT;
const edgeList& edges = mesh_.edges();
forAll(edges, edgeI)
{
const edge& e = edges[edgeI];
vector eVec(e.vec(mesh_.points()));
scalar eMag = mag(eVec);
eVec /= eMag;
if (mag(eVec & x) > 1-edgeTol_)
{
minX = min(minX, eMag);
maxX = max(maxX, eMag);
nX++;
}
else if (mag(eVec & y) > 1-edgeTol_)
{
minY = min(minY, eMag);
maxY = max(maxY, eMag);
nY++;
}
else if (mag(eVec & z) > 1-edgeTol_)
{
minZ = min(minZ, eMag);
maxZ = max(maxZ, eMag);
nZ++;
}
else
{
minOther = min(minOther, eMag);
maxOther = max(maxOther, eMag);
}
}
os << "Mesh bounding box:" << boundBox(mesh_.points()) << nl << nl
<< "Mesh edge statistics:" << nl
<< " x aligned : number:" << nX << "\tminLen:" << minX
<< "\tmaxLen:" << maxX << nl
<< " y aligned : number:" << nY << "\tminLen:" << minY
<< "\tmaxLen:" << maxY << nl
<< " z aligned : number:" << nZ << "\tminLen:" << minZ
<< "\tmaxLen:" << maxZ << nl
<< " other : number:" << mesh_.nEdges() - nX - nY - nZ
<< "\tminLen:" << minOther
<< "\tmaxLen:" << maxOther << nl << endl;
if (normalDir_ == 0)
{
return min(minY, min(minZ, minOther));
}
else if (normalDir_ == 1)
{
return min(minX, min(minZ, minOther));
}
else if (normalDir_ == 2)
{
return min(minX, min(minY, minOther));
}
else
{
return min(minX, min(minY, min(minZ, minOther)));
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,110 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::edgeStats
Description
Helper class to calculate minimum edge length on mesh.
SourceFiles
edgeStats.C
\*---------------------------------------------------------------------------*/
#ifndef edgeStats_H
#define edgeStats_H
#include "direction.H"
#include "scalar.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class polyMesh;
class Ostream;
class twoDPointCorrector;
/*---------------------------------------------------------------------------*\
Class edgeStats Declaration
\*---------------------------------------------------------------------------*/
class edgeStats
{
// Private data
//- Reference to mesh.
const polyMesh& mesh_;
//- Component (0,1,2) of normal direction or 3 if 3D case.
direction normalDir_;
// Private Member Functions
//- If 2d get component of normal dir.
direction getNormalDir(const twoDPointCorrector*) const;
//- Disallow default bitwise copy construct
edgeStats(const edgeStats&);
//- Disallow default bitwise assignment
void operator=(const edgeStats&);
public:
// Static data members
// Max (cos of) angle for edges to be considered aligned with axis.
static const scalar edgeTol_;
// Constructors
//- Construct from mesh
edgeStats(const polyMesh& mesh);
//- Construct from mesh and corrector
edgeStats(const polyMesh& mesh, const twoDPointCorrector* );
// Member Functions
//- Calculate minimum edge length and print
scalar minLen(Ostream& os) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,522 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
selectCells
Description
Select cells in relation to surface.
Divides cells into three sets:
- cutCells : cells cut by surface or close to surface.
- outside : cells not in cutCells and reachable from set of
user-defined points (outsidePoints)
- inside : same but not reachable.
Finally the wanted sets are combined into a cellSet 'selected'. Apart
from straightforward adding the contents there are a few extra rules to
make sure that the surface of the 'outside' of the mesh is singly
connected.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "polyMesh.H"
#include "IOdictionary.H"
#include "twoDPointCorrector.H"
#include "OFstream.H"
#include "meshTools.H"
#include "triSurface.H"
#include "triSurfaceSearch.H"
#include "meshSearch.H"
#include "cellClassification.H"
#include "cellSet.H"
#include "cellInfo.H"
#include "MeshWave.H"
#include "edgeStats.H"
#include "treeDataTriSurface.H"
#include "indexedOctree.H"
#include "globalMeshData.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// cellType for cells included/not included in mesh.
static const label MESH = cellClassification::INSIDE;
static const label NONMESH = cellClassification::OUTSIDE;
void writeSet(const cellSet& cells, const string& msg)
{
Info<< "Writing " << msg << " (" << cells.size() << ") to cellSet "
<< cells.instance()/cells.local()/cells.name()
<< endl << endl;
cells.write();
}
void getType(const labelList& elems, const label type, labelHashSet& set)
{
forAll(elems, i)
{
if (elems[i] == type)
{
set.insert(i);
}
}
}
void cutBySurface
(
const polyMesh& mesh,
const meshSearch& queryMesh,
const triSurfaceSearch& querySurf,
const pointField& outsidePts,
const bool selectCut,
const bool selectInside,
const bool selectOutside,
const scalar nearDist,
cellClassification& cellType
)
{
// Cut with surface and classify as inside/outside/cut
cellType =
cellClassification
(
mesh,
queryMesh,
querySurf,
outsidePts
);
// Get inside/outside/cutCells cellSets.
cellSet inside(mesh, "inside", mesh.nCells()/10);
getType(cellType, cellClassification::INSIDE, inside);
writeSet(inside, "inside cells");
cellSet outside(mesh, "outside", mesh.nCells()/10);
getType(cellType, cellClassification::OUTSIDE, outside);
writeSet(outside, "outside cells");
cellSet cutCells(mesh, "cutCells", mesh.nCells()/10);
getType(cellType, cellClassification::CUT, cutCells);
writeSet(cutCells, "cells cut by surface");
// Change cellType to reflect selected part of mesh. Use
// MESH to denote selected part, NONMESH for all
// other cells.
// Is a bit of a hack but allows us to reuse all the functionality
// in cellClassification.
forAll(cellType, cellI)
{
label cType = cellType[cellI];
if (cType == cellClassification::CUT)
{
if (selectCut)
{
cellType[cellI] = MESH;
}
else
{
cellType[cellI] = NONMESH;
}
}
else if (cType == cellClassification::INSIDE)
{
if (selectInside)
{
cellType[cellI] = MESH;
}
else
{
cellType[cellI] = NONMESH;
}
}
else if (cType == cellClassification::OUTSIDE)
{
if (selectOutside)
{
cellType[cellI] = MESH;
}
else
{
cellType[cellI] = NONMESH;
}
}
else
{
FatalErrorIn("cutBySurface")
<< "Multiple mesh regions in original mesh" << endl
<< "Please use splitMeshRegions to separate these"
<< exit(FatalError);
}
}
if (nearDist > 0)
{
Info<< "Removing cells with points closer than " << nearDist
<< " to the surface ..." << nl << endl;
const pointField& pts = mesh.points();
const indexedOctree<treeDataTriSurface>& tree = querySurf.tree();
label nRemoved = 0;
forAll(pts, pointI)
{
const point& pt = pts[pointI];
pointIndexHit hitInfo = tree.findNearest(pt, sqr(nearDist));
if (hitInfo.hit())
{
const labelList& pCells = mesh.pointCells()[pointI];
forAll(pCells, i)
{
if (cellType[pCells[i]] != NONMESH)
{
cellType[pCells[i]] = NONMESH;
nRemoved++;
}
}
}
}
// tmp<pointField> tnearest = querySurf.calcNearest(pts);
// const pointField& nearest = tnearest();
//
// label nRemoved = 0;
//
// forAll(nearest, pointI)
// {
// if (mag(nearest[pointI] - pts[pointI]) < nearDist)
// {
// const labelList& pCells = mesh.pointCells()[pointI];
//
// forAll(pCells, i)
// {
// if (cellType[pCells[i]] != NONMESH)
// {
// cellType[pCells[i]] = NONMESH;
// nRemoved++;
// }
// }
// }
// }
Info<< "Removed " << nRemoved << " cells since too close to surface"
<< nl << endl;
}
}
// We're meshing the outside. Subset the currently selected mesh cells with the
// ones reachable from the outsidepoints.
label selectOutsideCells
(
const polyMesh& mesh,
const meshSearch& queryMesh,
const pointField& outsidePts,
cellClassification& cellType
)
{
//
// Check all outsidePts and for all of them inside a mesh cell
// collect the faces to start walking from
//
// Outside faces
labelHashSet outsideFacesMap(outsidePts.size() * 6 * 2);
DynamicList<label> outsideFaces(outsideFacesMap.size());
// CellInfo on outside faces
DynamicList<cellInfo> outsideFacesInfo(outsideFacesMap.size());
// cellInfo for mesh cell
const cellInfo meshInfo(MESH);
forAll(outsidePts, outsidePtI)
{
// Find cell containing point. Linear search.
label cellI = queryMesh.findCell(outsidePts[outsidePtI], -1, false);
if (cellI != -1 && cellType[cellI] == MESH)
{
Info<< "Marking cell " << cellI << " containing outside point "
<< outsidePts[outsidePtI] << " with type " << cellType[cellI]
<< " ..." << endl;
//
// Mark this cell and its faces to start walking from
//
// Mark faces of cellI
const labelList& cFaces = mesh.cells()[cellI];
forAll(cFaces, i)
{
label faceI = cFaces[i];
if (outsideFacesMap.insert(faceI))
{
outsideFaces.append(faceI);
outsideFacesInfo.append(meshInfo);
}
}
}
}
// Floodfill starting from outsideFaces (of type meshInfo)
MeshWave<cellInfo> regionCalc
(
mesh,
outsideFaces.shrink(),
outsideFacesInfo.shrink(),
mesh.globalData().nTotalCells()+1 // max iterations
);
// Now regionCalc should hold info on cells that are reachable from
// changedFaces. Use these to subset cellType
const List<cellInfo>& allCellInfo = regionCalc.allCellInfo();
label nChanged = 0;
forAll(allCellInfo, cellI)
{
if (cellType[cellI] == MESH)
{
// Original cell was selected for meshing. Check if cell was
// reached from outsidePoints
if (allCellInfo[cellI].type() != MESH)
{
cellType[cellI] = NONMESH;
nChanged++;
}
}
}
return nChanged;
}
int main(int argc, char *argv[])
{
argList::noParallel();
# include "setRootCase.H"
# include "createTime.H"
# include "createPolyMesh.H"
// Mesh edge statistics calculator
edgeStats edgeCalc(mesh);
IOdictionary refineDict
(
IOobject
(
"selectCellsDict",
runTime.system(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
);
fileName surfName(refineDict.lookup("surface"));
pointField outsidePts(refineDict.lookup("outsidePoints"));
bool useSurface(readBool(refineDict.lookup("useSurface")));
bool selectCut(readBool(refineDict.lookup("selectCut")));
bool selectInside(readBool(refineDict.lookup("selectInside")));
bool selectOutside(readBool(refineDict.lookup("selectOutside")));
scalar nearDist(readScalar(refineDict.lookup("nearDistance")));
if (useSurface)
{
Info<< "Cells to be used for meshing (0=false, 1=true):" << nl
<< " cells cut by surface : " << selectCut << nl
<< " cells inside of surface : " << selectInside << nl
<< " cells outside of surface : " << selectOutside << nl
<< " cells with points further than : " << nearDist << nl
<< endl;
}
else
{
Info<< "Cells to be used for meshing (0=false, 1=true):" << nl
<< " cells reachable from outsidePoints:" << selectOutside << nl
<< endl;
}
// Print edge stats on original mesh.
(void)edgeCalc.minLen(Info);
// Search engine on mesh. Face decomposition since faces might be warped.
meshSearch queryMesh(mesh);
// Check all 'outside' points
forAll(outsidePts, outsideI)
{
const point& outsidePoint = outsidePts[outsideI];
label cellI = queryMesh.findCell(outsidePoint, -1, false);
if (returnReduce(cellI, maxOp<label>()) == -1)
{
FatalErrorIn(args.executable())
<< "outsidePoint " << outsidePoint
<< " is not inside any cell"
<< exit(FatalError);
}
}
// Cell status (compared to surface if provided): inside/outside/cut.
// Start off from everything selected and cut later.
cellClassification cellType
(
mesh,
labelList
(
mesh.nCells(),
cellClassification::MESH
)
);
// Surface
autoPtr<triSurface> surf(NULL);
// Search engine on surface.
autoPtr<triSurfaceSearch> querySurf(NULL);
if (useSurface)
{
surf.reset(new triSurface(surfName));
// Dump some stats
surf().writeStats(Info);
// Search engine on surface.
querySurf.reset(new triSurfaceSearch(surf));
// Set cellType[cellI] according to relation to surface
cutBySurface
(
mesh,
queryMesh,
querySurf,
outsidePts,
selectCut,
selectInside,
selectOutside,
nearDist,
cellType
);
}
// Now 'trim' all the corners from the mesh so meshing/surface extraction
// becomes easier.
label nHanging, nRegionEdges, nRegionPoints, nOutside;
do
{
Info<< "Removing cells which after subsetting would have all points"
<< " on outside ..." << nl << endl;
nHanging = cellType.fillHangingCells
(
MESH, // meshType
NONMESH, // fill type
mesh.nCells()
);
Info<< "Removing edges connecting cells unconnected by faces ..."
<< nl << endl;
nRegionEdges = cellType.fillRegionEdges
(
MESH, // meshType
NONMESH, // fill type
mesh.nCells()
);
Info<< "Removing points connecting cells unconnected by faces ..."
<< nl << endl;
nRegionPoints = cellType.fillRegionPoints
(
MESH, // meshType
NONMESH, // fill type
mesh.nCells()
);
nOutside = 0;
if (selectOutside)
{
// Since we're selecting the cells reachable from outsidePoints
// and the set might have changed, redo the outsideCells
// calculation
nOutside = selectOutsideCells
(
mesh,
queryMesh,
outsidePts,
cellType
);
}
} while
(
nHanging != 0
|| nRegionEdges != 0
|| nRegionPoints != 0
|| nOutside != 0
);
cellSet selectedCells(mesh, "selected", mesh.nCells()/10);
getType(cellType, MESH, selectedCells);
writeSet(selectedCells, "cells selected for meshing");
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,40 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object selectCellsDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Whether to use surface. If false no surface will be read and only
// outsidePoints/selectOutside will be used to determine cells to keep.
useSurface false;
// Surface to keep to
surface "plexi.obj";
// What is outside
outsidePoints ((-1 -1 -1));
//
// Selection of final set
//
// Select based on side of surface. Usually select inside cells and project
// outwards or select outside cells and project inwards.
selectCut false;
selectInside false;
selectOutside true;
// Leave out cell closer than nearDistance to the surface. Usually
// 0.5*of the cell size. Set to <0 to disable.
nearDistance -1;
// ************************************************************************* //

View File

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

View File

@ -0,0 +1,7 @@
EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude
EXE_LIBS = \
-ldynamicMesh \
-lmeshTools

View File

@ -0,0 +1,721 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
splitCells
Description
Utility to split cells with flat faces.
Uses a geometric cut with a plane dividing the edge angle into two so
might produce funny cells. For hexes it will use by default a cut from
edge onto opposite edge (i.e. purely topological).
Options:
- split cells from cellSet only
- use geometric cut for hexes as well
The angle is the angle between two faces sharing an edge as seen from
inside each cell. So a cube will have all angles 90. If you want
to split cells with cell centre outside use e.g. angle 200
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "polyTopoChange.H"
#include "polyTopoChanger.H"
#include "mapPolyMesh.H"
#include "polyMesh.H"
#include "cellCuts.H"
#include "cellSet.H"
#include "cellModeller.H"
#include "meshCutter.H"
#include "unitConversion.H"
#include "geomCellLooper.H"
#include "plane.H"
#include "edgeVertex.H"
#include "meshTools.H"
#include "ListOps.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
labelList pack(const boolList& lst)
{
labelList packedLst(lst.size());
label packedI = 0;
forAll(lst, i)
{
if (lst[i])
{
packedLst[packedI++] = i;
}
}
packedLst.setSize(packedI);
return packedLst;
}
scalarField pack(const boolList& lst, const scalarField& elems)
{
scalarField packedElems(lst.size());
label packedI = 0;
forAll(lst, i)
{
if (lst[i])
{
packedElems[packedI++] = elems[i];
}
}
packedElems.setSize(packedI);
return packedElems;
}
// Given sin and cos of max angle between normals calculate whether f0 and f1
// on cellI make larger angle. Uses sinAngle only for quadrant detection.
bool largerAngle
(
const primitiveMesh& mesh,
const scalar cosAngle,
const scalar sinAngle,
const label cellI,
const label f0, // face label
const label f1,
const vector& n0, // normal at f0
const vector& n1
)
{
const labelList& own = mesh.faceOwner();
bool sameFaceOrder = !((own[f0] == cellI) ^ (own[f1] == cellI));
// Get cos between faceArea vectors. Correct so flat angle (180 degrees)
// gives -1.
scalar normalCosAngle = n0 & n1;
if (sameFaceOrder)
{
normalCosAngle = -normalCosAngle;
}
// Get cos between faceCentre and normal vector to determine in
// which quadrant angle is. (Is correct for unwarped faces only!)
// Correct for non-outwards pointing normal.
vector c1c0(mesh.faceCentres()[f1] - mesh.faceCentres()[f0]);
c1c0 /= mag(c1c0) + VSMALL;
scalar fcCosAngle = n0 & c1c0;
if (own[f0] != cellI)
{
fcCosAngle = -fcCosAngle;
}
if (sinAngle < 0.0)
{
// Looking for concave angles (quadrant 3 or 4)
if (fcCosAngle <= 0)
{
// Angle is convex so smaller.
return false;
}
else
{
if (normalCosAngle < cosAngle)
{
return false;
}
else
{
return true;
}
}
}
else
{
// Looking for convex angles (quadrant 1 or 2)
if (fcCosAngle > 0)
{
// Concave angle
return true;
}
else
{
// Convex. Check cos of normal vectors.
if (normalCosAngle > cosAngle)
{
return false;
}
else
{
return true;
}
}
}
}
// Split hex (and hex only) along edgeI creating two prisms
bool splitHex
(
const polyMesh& mesh,
const label cellI,
const label edgeI,
DynamicList<label>& cutCells,
DynamicList<labelList>& cellLoops,
DynamicList<scalarField>& cellEdgeWeights
)
{
// cut handling functions
edgeVertex ev(mesh);
const edgeList& edges = mesh.edges();
const faceList& faces = mesh.faces();
const edge& e = edges[edgeI];
// Get faces on the side, i.e. faces not using edge but still using one of
// the edge endpoints.
label leftI = -1;
label rightI = -1;
label leftFp = -1;
label rightFp = -1;
const cell& cFaces = mesh.cells()[cellI];
forAll(cFaces, i)
{
label faceI = cFaces[i];
const face& f = faces[faceI];
label fp0 = findIndex(f, e[0]);
label fp1 = findIndex(f, e[1]);
if (fp0 == -1)
{
if (fp1 != -1)
{
// Face uses e[1] but not e[0]
rightI = faceI;
rightFp = fp1;
if (leftI != -1)
{
// Have both faces so exit
break;
}
}
}
else
{
if (fp1 != -1)
{
// Face uses both e[1] and e[0]
}
else
{
leftI = faceI;
leftFp = fp0;
if (rightI != -1)
{
break;
}
}
}
}
if (leftI == -1 || rightI == -1)
{
FatalErrorIn("splitHex") << "Problem : leftI:" << leftI
<< " rightI:" << rightI << abort(FatalError);
}
// Walk two vertices further on faces.
const face& leftF = faces[leftI];
label leftV = leftF[(leftFp + 2) % leftF.size()];
const face& rightF = faces[rightI];
label rightV = rightF[(rightFp + 2) % rightF.size()];
labelList loop(4);
loop[0] = ev.vertToEVert(e[0]);
loop[1] = ev.vertToEVert(leftV);
loop[2] = ev.vertToEVert(rightV);
loop[3] = ev.vertToEVert(e[1]);
scalarField loopWeights(4);
loopWeights[0] = -GREAT;
loopWeights[1] = -GREAT;
loopWeights[2] = -GREAT;
loopWeights[3] = -GREAT;
cutCells.append(cellI);
cellLoops.append(loop);
cellEdgeWeights.append(loopWeights);
return true;
}
// Split cellI along edgeI with a plane along halfNorm direction.
bool splitCell
(
const polyMesh& mesh,
const geomCellLooper& cellCutter,
const label cellI,
const label edgeI,
const vector& halfNorm,
const boolList& vertIsCut,
const boolList& edgeIsCut,
const scalarField& edgeWeight,
DynamicList<label>& cutCells,
DynamicList<labelList>& cellLoops,
DynamicList<scalarField>& cellEdgeWeights
)
{
const edge& e = mesh.edges()[edgeI];
vector eVec = e.vec(mesh.points());
eVec /= mag(eVec);
vector planeN = eVec ^ halfNorm;
// Slightly tilt plane to make it not cut edges exactly
// halfway on fully regular meshes (since we want cuts
// to be snapped to vertices)
planeN += 0.01*halfNorm;
planeN /= mag(planeN);
// Define plane through edge
plane cutPlane(mesh.points()[e.start()], planeN);
labelList loop;
scalarField loopWeights;
if
(
cellCutter.cut
(
cutPlane,
cellI,
vertIsCut,
edgeIsCut,
edgeWeight,
loop,
loopWeights
)
)
{
// Did manage to cut cell. Copy into overall list.
cutCells.append(cellI);
cellLoops.append(loop);
cellEdgeWeights.append(loopWeights);
return true;
}
else
{
return false;
}
}
// Collects cuts for all cells in cellSet
void collectCuts
(
const polyMesh& mesh,
const geomCellLooper& cellCutter,
const bool geometry,
const scalar minCos,
const scalar minSin,
const cellSet& cellsToCut,
DynamicList<label>& cutCells,
DynamicList<labelList>& cellLoops,
DynamicList<scalarField>& cellEdgeWeights
)
{
// Get data from mesh
const cellShapeList& cellShapes = mesh.cellShapes();
const labelList& own = mesh.faceOwner();
const labelListList& cellEdges = mesh.cellEdges();
const vectorField& faceAreas = mesh.faceAreas();
// Hex shape
const cellModel& hex = *(cellModeller::lookup("hex"));
// cut handling functions
edgeVertex ev(mesh);
// Cut information per mesh entity
boolList vertIsCut(mesh.nPoints(), false);
boolList edgeIsCut(mesh.nEdges(), false);
scalarField edgeWeight(mesh.nEdges(), -GREAT);
forAllConstIter(cellSet, cellsToCut, iter)
{
const label cellI = iter.key();
const labelList& cEdges = cellEdges[cellI];
forAll(cEdges, i)
{
label edgeI = cEdges[i];
label f0, f1;
meshTools::getEdgeFaces(mesh, cellI, edgeI, f0, f1);
vector n0 = faceAreas[f0];
n0 /= mag(n0);
vector n1 = faceAreas[f1];
n1 /= mag(n1);
if
(
largerAngle
(
mesh,
minCos,
minSin,
cellI,
f0,
f1,
n0,
n1
)
)
{
bool splitOk = false;
if (!geometry && cellShapes[cellI].model() == hex)
{
splitOk =
splitHex
(
mesh,
cellI,
edgeI,
cutCells,
cellLoops,
cellEdgeWeights
);
}
else
{
vector halfNorm;
if ((own[f0] == cellI) ^ (own[f1] == cellI))
{
// Opposite owner orientation
halfNorm = 0.5*(n0 - n1);
}
else
{
// Faces have same owner or same neighbour so
// normals point in same direction
halfNorm = 0.5*(n0 + n1);
}
splitOk =
splitCell
(
mesh,
cellCutter,
cellI,
edgeI,
halfNorm,
vertIsCut,
edgeIsCut,
edgeWeight,
cutCells,
cellLoops,
cellEdgeWeights
);
}
if (splitOk)
{
// Update cell/edge/vertex wise info.
label index = cellLoops.size() - 1;
const labelList& loop = cellLoops[index];
const scalarField& loopWeights = cellEdgeWeights[index];
forAll(loop, i)
{
label cut = loop[i];
if (ev.isEdge(cut))
{
edgeIsCut[ev.getEdge(cut)] = true;
edgeWeight[ev.getEdge(cut)] = loopWeights[i];
}
else
{
vertIsCut[ev.getVertex(cut)] = true;
}
}
// Stop checking edges for this cell.
break;
}
}
}
}
cutCells.shrink();
cellLoops.shrink();
cellEdgeWeights.shrink();
}
int main(int argc, char *argv[])
{
argList::addNote
(
"split cells with flat faces"
);
#include "addOverwriteOption.H"
argList::noParallel();
argList::validArgs.append("edgeAngle [0..360]");
argList::addOption
(
"set",
"name",
"split cells from specified cellSet only"
);
argList::addBoolOption
(
"geometry",
"use geometric cut for hexes as well"
);
argList::addOption
(
"tol",
"scalar", "edge snap tolerance (default 0.2)"
);
#include "setRootCase.H"
#include "createTime.H"
runTime.functionObjects().off();
#include "createPolyMesh.H"
const word oldInstance = mesh.pointsInstance();
const scalar featureAngle = args.argRead<scalar>(1);
const scalar minCos = Foam::cos(degToRad(featureAngle));
const scalar minSin = Foam::sin(degToRad(featureAngle));
const bool readSet = args.optionFound("set");
const bool geometry = args.optionFound("geometry");
const bool overwrite = args.optionFound("overwrite");
const scalar edgeTol = args.optionLookupOrDefault("tol", 0.2);
Info<< "Trying to split cells with internal angles > feature angle\n" << nl
<< "featureAngle : " << featureAngle << nl
<< "edge snapping tol : " << edgeTol << nl;
if (readSet)
{
Info<< "candidate cells : cellSet " << args["set"] << nl;
}
else
{
Info<< "candidate cells : all cells" << nl;
}
if (geometry)
{
Info<< "hex cuts : geometric; using edge tolerance" << nl;
}
else
{
Info<< "hex cuts : topological; cut to opposite edge" << nl;
}
Info<< endl;
// Cell circumference cutter
geomCellLooper cellCutter(mesh);
// Snap all edge cuts close to endpoints to vertices.
geomCellLooper::setSnapTol(edgeTol);
// Candidate cells to cut
cellSet cellsToCut(mesh, "cellsToCut", mesh.nCells()/100);
if (readSet)
{
// Read cells to cut from cellSet
cellSet cells(mesh, args["set"]);
cellsToCut = cells;
}
while (true)
{
if (!readSet)
{
// Try all cells for cutting
for (label cellI = 0; cellI < mesh.nCells(); cellI++)
{
cellsToCut.insert(cellI);
}
}
// Cut information per cut cell
DynamicList<label> cutCells(mesh.nCells()/10 + 10);
DynamicList<labelList> cellLoops(mesh.nCells()/10 + 10);
DynamicList<scalarField> cellEdgeWeights(mesh.nCells()/10 + 10);
collectCuts
(
mesh,
cellCutter,
geometry,
minCos,
minSin,
cellsToCut,
cutCells,
cellLoops,
cellEdgeWeights
);
cellSet cutSet(mesh, "cutSet", cutCells.size());
forAll(cutCells, i)
{
cutSet.insert(cutCells[i]);
}
// Gets cuts across cells from cuts through edges.
Info<< "Writing " << cutSet.size() << " cells to cut to cellSet "
<< cutSet.instance()/cutSet.local()/cutSet.name()
<< endl << endl;
cutSet.write();
// Analyze cuts for clashes.
cellCuts cuts
(
mesh,
cutCells, // cells candidate for cutting
cellLoops,
cellEdgeWeights
);
Info<< "Actually cut cells:" << cuts.nLoops() << nl << endl;
if (cuts.nLoops() == 0)
{
break;
}
// Remove cut cells from cellsToCut (Note:only relevant if -readSet)
forAll(cuts.cellLoops(), cellI)
{
if (cuts.cellLoops()[cellI].size())
{
//Info<< "Removing cut cell " << cellI << " from wishlist"
// << endl;
cellsToCut.erase(cellI);
}
}
// At least some cells are cut.
polyTopoChange meshMod(mesh);
// Cutting engine
meshCutter cutter(mesh);
// Insert mesh refinement into polyTopoChange.
cutter.setRefinement(cuts, meshMod);
// Do all changes
Info<< "Morphing ..." << endl;
if (!overwrite)
{
runTime++;
}
autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh(mesh, false);
if (morphMap().hasMotionPoints())
{
mesh.movePoints(morphMap().preMotionPoints());
}
// Update stored labels on meshCutter
cutter.updateMesh(morphMap());
// Update cellSet
cellsToCut.updateMesh(morphMap());
Info<< "Remaining:" << cellsToCut.size() << endl;
// Write resulting mesh
if (overwrite)
{
mesh.setInstance(oldInstance);
}
Info<< "Writing refined morphMesh to time " << runTime.timeName()
<< endl;
mesh.write();
}
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,17 @@
#!/bin/sh
#
# Build optional components (eg, may depend on third-party libraries)
# -----------------------------------------------------------------------------
cd ${0%/*} || exit 1 # run from this directory
set -x
# build libccmio and create lnInclude directory
$WM_THIRD_PARTY_DIR/AllwmakeLibccmio
# if the library built properly, the headers should exist too
if [ -e $FOAM_EXT_LIBBIN/libccmio.so ]
then
wmake ccm26ToFoam
fi
# ----------------------------------------------------------------- end-of-file

View File

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

View File

@ -0,0 +1,12 @@
LIBCCMIO_DIR = $(WM_THIRD_PARTY_DIR)/libccmio-2.6.1
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIBCCMIO_DIR) \
-I$(LIBCCMIO_DIR)/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-lmeshTools \
-L$(FOAM_EXT_LIBBIN) -lccmio

View File

@ -0,0 +1,36 @@
1. how to write mesh from prostar
Type ngeom,[name].ngeom,star in the command line. This will create a
.ngeom file of your Prostar model.
If you have boundaries defined, these will be kept in the .ngeom file so
you won't have to rename and redefine the boundaries in ccm+. However,
the values (properties) are not exported.
If you don't have boundaries you'll get a single wall patch in ccm+ that
you'll have to split accordingly.
2. how to load it into star-ccm+
In ccm+ create a new simulation and do File>Import...
Browse to the location where you have your .ngeom file, select it, press
OK and that's it.
3. how to do merging (or is automatic?)
If you had couples in your Prostar model, your meshes will all be
"fused" together automatically in ccm+ when you import the .ngeom file.
Keep a look on the output window in Prostar when you run the ngeom
command to make sure the couples are exported OK.
Alternatively, you can "fuse" the different fluid regions in ccm+. To do
this select all the fluid regions you want to merge together from the
command tree on the left of your screen, under Regions. Press control
and click on top of each one, once you've selected all, click the
right-hand buttom of your mouse and select Fuse...
4. how to save it from star-ccm+
Once your model is ready in ccm+ (i.e. all regions and boundary patches
defined), go to File>Export... and select .ccm format.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
ansysToFoam.L
EXE = $(FOAM_APPBIN)/ansysToFoam

View File

@ -0,0 +1,711 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
ansysToFoam
Description
Converts an ANSYS input mesh file, exported from I-DEAS,
to OpenFOAM format.
\*---------------------------------------------------------------------------*/
%{
#undef yyFlexLexer
/* ------------------------------------------------------------------------- *\
------ local definitions
\* ------------------------------------------------------------------------- */
#include <sstream>
// For EOF only
#include <cstdio>
#include "scalar.H"
#include "IStringStream.H"
using namespace Foam;
#include "argList.H"
#include "Time.H"
#include "polyMesh.H"
#include "emptyPolyPatch.H"
#include "preservePatchTypes.H"
#include "cellShape.H"
#include "cellModeller.H"
#include "SLList.H"
#include "SLPtrList.H"
SLList<point> slPoints;
SLList<label> slPointMap;
label maxNodei = 0;
SLPtrList<labelList> slCellLabels;
SLList<label> slCellMap;
SLList<label> slCellType;
label maxCelli = 0;
PtrList<SLList<label> > slPatchCells;
PtrList<SLList<label> > slPatchCellFaces;
// Cell types
Map<word> cellTypes;
label currentTypei = -1;
// Dummy yywrap to keep yylex happy at compile time.
// It is called by yylex but is not used as the mechanism to change file.
// See <<EOF>>
#if YY_FLEX_SUBMINOR_VERSION < 34
extern "C" int yywrap()
#else
int yyFlexLexer::yywrap()
#endif
{
return 1;
}
%}
one_space [ \t\f\r]
space {one_space}*
some_space {one_space}+
cspace ","{space}
alpha [_A-Za-z]
digit [0-9]
identifier {alpha}({alpha}|{digit})*
integer {digit}+
label [1-9]{digit}*
exponent_part [eE][-+]?{digit}+
fractional_constant [-+]?(({digit}*"."{digit}+)|({digit}+"."?))
floatNum (({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))
x {floatNum}
y {floatNum}
z {floatNum}
value {floatNum}
node ^{space}"N"{cspace}
element ^{space}"EN"{cspace}
bface ^{space}"SFE"{cspace}
elementTypeName ^{space}"ET"{cspace}
elementType ^{space}"TYPE"{cspace}
%%
%{
labelList labels(8);
%}
/* ------------------------------------------------------------------------- *\
------ Start Lexing ------
\* ------------------------------------------------------------------------- */
{node}{label}{cspace}{x}{cspace}{y}{cspace}{z}{space}\n {
IStringStream nodeStream(YYText());
char tag, c;
label nodei;
point node;
nodeStream
>> tag
>> c >> nodei
>> c >> node.x()
>> c >> node.y()
>> c >> node.z();
if (nodei > maxNodei) maxNodei = nodei;
slPointMap.append(nodei);
slPoints.append(node);
}
{element}{label}{cspace}{label}{cspace}{label}{cspace}{label}{cspace}{label}{cspace}{label}{cspace}{label}{cspace}{label}{cspace}{label}{space}\n {
IStringStream elementStream(YYText());
char tag, c;
label celli;
elementStream
>> tag >> tag
>> c >> celli
>> c >> labels[0]
>> c >> labels[1]
>> c >> labels[2]
>> c >> labels[3]
>> c >> labels[4]
>> c >> labels[5]
>> c >> labels[6]
>> c >> labels[7];
if (celli > maxCelli) maxCelli = celli;
slCellMap.append(celli);
slCellLabels.append(new labelList(labels));
slCellType.append(currentTypei);
}
{bface}{label}{cspace}{label}{cspace}{identifier}{cspace}{integer}{cspace}{value}{space}\n {
IStringStream bfaceStream(YYText());
char tag, c;
label elementi;
label facei;
scalar indexValue, unknown;
bfaceStream
>> tag >> tag >> tag
>> c >> elementi
>> c >> facei
>> c >> tag >> tag >> tag >> tag
>> c >> unknown
>> c >> indexValue;
label patchi = label(indexValue);
if (patchi > slPatchCells.size())
{
slPatchCells.setSize(patchi);
forAll(slPatchCells, i)
{
if (!slPatchCells(i))
{
slPatchCells.set(i, new SLList<label>);
}
}
}
if (patchi > slPatchCellFaces.size())
{
slPatchCellFaces.setSize(patchi);
forAll(slPatchCells, i)
{
if (!slPatchCellFaces(i))
{
slPatchCellFaces.set(i, new SLList<label>);
}
}
}
slPatchCells[patchi-1].append(elementi);
slPatchCellFaces[patchi-1].append(facei);
}
{elementTypeName}{label}{cspace}{identifier}{space}\n {
IStringStream elementStream(YYText());
char tag,c;
label cellTypei;
word cellTypeName;
elementStream
>> tag >> tag // skip 'ET'
>> c >> cellTypei
>> c >> cellTypeName;
Info<< "Read typeName " << cellTypeName
<< " for type " << cellTypei << endl;
cellTypes.insert(cellTypei, cellTypeName);
}
{elementType}{label}{space}\n {
IStringStream elementStream(YYText());
char tag,c;
label cellTypei;
elementStream
>> tag >> tag >> tag >> tag // skip 'TYPE'
>> c >> cellTypei;
currentTypei = cellTypei;
}
/* ------------------------------------------------------------------------- *\
------ Ignore remaining space and \n s. Any other characters are errors.
\* ------------------------------------------------------------------------- */
.|\n {}
/* ------------------------------------------------------------------------- *\
------ On EOF return to previous file, if none exists terminate.
\* ------------------------------------------------------------------------- */
<<EOF>> {
yyterminate();
}
%%
#include "fileName.H"
#include <fstream>
using std::ifstream;
label findFace(const polyMesh& mesh, const face& f)
{
const labelList& pFaces = mesh.pointFaces()[f[0]];
forAll(pFaces, i)
{
label faceI = pFaces[i];
if (mesh.faces()[faceI] == f)
{
return faceI;
}
}
FatalErrorIn("findFace(const polyMesh&, const face&)")
<< "Cannot find a face matching " << f
<< exit(FatalError);
return -1;
}
int main(int argc, char *argv[])
{
argList::noParallel();
argList::validArgs.append("ANSYS input file");
argList::addOption
(
"scale",
"factor",
"geometry scaling factor - default is 1"
);
argList args(argc, argv);
if (!args.check())
{
FatalError.exit();
}
const scalar scaleFactor = args.optionLookupOrDefault("scale", 1.0);
# include "createTime.H"
fileName ansysFile(args.additionalArgs()[0]);
ifstream ansysStream(ansysFile.c_str());
if (!ansysStream)
{
FatalErrorIn("ansysToFoam::main(int argc, char *argv[])")
<< args.executable()
<< ": file " << ansysFile << " not found"
<< exit(FatalError);
}
yyFlexLexer lexer(&ansysStream);
while (lexer.yylex() != 0)
{}
Info<< "Creating points" << endl;
pointField points(slPoints.size());
label i = 0;
forAllConstIter(SLList<point>, slPoints, pointIter)
{
// Scale points for the given scale factor
points[i++] = scaleFactor * pointIter();
}
labelList pointMap(maxNodei+1);
i = 0;
forAllConstIter(SLList<label>, slPointMap, pointMapIter)
{
pointMap[pointMapIter()] = i++;
}
Info<< "Creating cells" << endl;
labelList cellMap(maxCelli+1);
i = 0;
forAllConstIter(SLList<label>, slCellMap, cellMapIter)
{
cellMap[cellMapIter()] = i++;
}
const cellModel& hex = *(cellModeller::lookup("hex"));
const cellModel& prism = *(cellModeller::lookup("prism"));
const cellModel& pyr = *(cellModeller::lookup("pyr"));
const cellModel& tet = *(cellModeller::lookup("tet"));
labelList labelsHex(8);
labelList labelsPrism(6);
labelList labelsPyramid(5);
labelList labelsTet(4);
cellShapeList cellShapes(slCellLabels.size());
label nCells = 0;
forAllConstIter(SLPtrList<labelList>, slCellLabels, cellIter)
{
if // Tetrahedron
(
cellIter()[2] == cellIter()[3]
&& cellIter()[4] == cellIter()[5]
&& cellIter()[5] == cellIter()[6]
&& cellIter()[6] == cellIter()[7]
)
{
labelsTet[0] = pointMap[cellIter()[0] ];
labelsTet[1] = pointMap[cellIter()[1] ];
labelsTet[2] = pointMap[cellIter()[2] ];
labelsTet[3] = pointMap[cellIter()[4] ];
cellShapes[nCells++] = cellShape(tet, labelsTet);
}
else if // Square-based pyramid
(
cellIter()[4] == cellIter()[5]
&& cellIter()[5] == cellIter()[6]
&& cellIter()[6] == cellIter()[7]
)
{
labelsPyramid[0] = pointMap[cellIter()[0] ];
labelsPyramid[1] = pointMap[cellIter()[1] ];
labelsPyramid[2] = pointMap[cellIter()[2] ];
labelsPyramid[3] = pointMap[cellIter()[3] ];
labelsPyramid[4] = pointMap[cellIter()[4] ];
cellShapes[nCells++] = cellShape(pyr, labelsPyramid);
}
else if // Triangular prism
(
cellIter()[2] == cellIter()[3]
&& cellIter()[6] == cellIter()[7]
)
{
labelsPrism[0] = pointMap[cellIter()[0] ];
labelsPrism[1] = pointMap[cellIter()[1] ];
labelsPrism[2] = pointMap[cellIter()[2] ];
labelsPrism[3] = pointMap[cellIter()[4] ];
labelsPrism[4] = pointMap[cellIter()[5] ];
labelsPrism[5] = pointMap[cellIter()[6] ];
cellShapes[nCells++] = cellShape(prism, labelsPrism);
}
else // Hex
{
labelsHex[0] = pointMap[cellIter()[0] ];
labelsHex[1] = pointMap[cellIter()[1] ];
labelsHex[2] = pointMap[cellIter()[2] ];
labelsHex[3] = pointMap[cellIter()[3] ];
labelsHex[4] = pointMap[cellIter()[4] ];
labelsHex[5] = pointMap[cellIter()[5] ];
labelsHex[6] = pointMap[cellIter()[6] ];
labelsHex[7] = pointMap[cellIter()[7] ];
cellShapes[nCells++] = cellShape(hex, labelsHex);
}
}
const word defaultFacesName = "defaultFaces";
word defaultFacesType = emptyPolyPatch::typeName;
// Create dummy mesh just to find out what are internal/external
// faces
autoPtr<polyMesh> dummyMesh
(
new polyMesh
(
IOobject
(
"dummyMesh",
runTime.constant(),
runTime
),
xferCopy(points),
cellShapes,
faceListList(0),
wordList(0),
wordList(0),
defaultFacesName,
defaultFacesType,
wordList(0)
)
);
// Warning: tet face order has changed between version 1.9.6 and 2.0
//
label faceIndex[7][6] =
{
{-1, -1, -1, -1, -1, -1}, // 0
{-1, -1, -1, -1, -1, -1}, // 1
{-1, -1, -1, -1, -1, -1}, // 2
{-1, -1, -1, -1, -1, -1}, // 3
{ 3, 2, 0, -1, 1, -1}, // tet (version 2.0)
{ 0, 4, 3, -1, 2, 1}, // prism
{ 4, 2, 1, 3, 0, 5}, // hex
};
Info<< "Creating boundary patches" << endl;
faceListList boundary(slPatchCells.size());
wordList patchNames(slPatchCells.size());
forAll(slPatchCells, patchI)
{
SLList<face> patchFaces;
SLList<label>::iterator cellIter(slPatchCells[patchI].begin());
SLList<label>::iterator faceIter(slPatchCellFaces[patchI].begin());
for
(
;
cellIter != slPatchCells[patchI].end()
&& faceIter != slPatchCellFaces[patchI].end();
++cellIter, ++faceIter
)
{
const cellShape& shape = cellShapes[cellMap[cellIter()]];
patchFaces.append
(
shape.faces()
[
faceIndex
[shape.nFaces()]
[faceIter()-1]
]
);
}
boundary[patchI] = patchFaces;
patchNames[patchI] = word("patch") + name(patchI + 1);
}
//
// Lookup the face labels for all the boundary faces
//
labelListList boundaryFaceLabels(boundary.size());
forAll(boundary, patchI)
{
const faceList& bFaces = boundary[patchI];
labelList& bFaceLabels = boundaryFaceLabels[patchI];
bFaceLabels.setSize(bFaces.size());
forAll(bFaces, i)
{
bFaceLabels[i] = findFace(dummyMesh(), bFaces[i]);
}
}
// Now split the boundary faces into external and internal faces. All
// faces go into faceZones and external faces go into patches.
List<faceList> patchFaces(slPatchCells.size());
labelList patchNFaces(slPatchCells.size(), 0);
forAll(boundary, patchI)
{
const faceList& bFaces = boundary[patchI];
const labelList& bFaceLabels = boundaryFaceLabels[patchI];
patchFaces[patchI].setSize(bFaces.size());
forAll(bFaces, i)
{
if (!dummyMesh().isInternalFace(bFaceLabels[i]))
{
patchFaces[patchI][patchNFaces[patchI]++] = bFaces[i];
}
}
patchFaces[patchI].setSize(patchNFaces[patchI]);
Info<< "Patch " << patchI << " named " << patchNames[patchI]
<< ": " << boundary[patchI].size() << " faces" << endl;
}
// We no longer need the dummyMesh
dummyMesh.clear();
Info<< "ansysToFoam: " << endl
<< "Ansys file format does not provide information about the type of "
<< "the patch (eg. wall, symmetry plane, cyclic etc)." << endl
<< "All the patches have been created "
<< "as type patch. Please reset after mesh conversion as necessary."
<< endl;
PtrList<dictionary> patchDicts;
preservePatchTypes
(
runTime,
runTime.constant(),
polyMesh::meshSubDir,
patchNames,
patchDicts,
defaultFacesName,
defaultFacesType
);
// Add information to dictionary
forAll(patchNames, patchI)
{
if (!patchDicts.set(patchI))
{
patchDicts.set(patchI, new dictionary());
}
// Add but not overwrite
patchDicts[patchI].add("type", polyPatch::typeName, false);
}
polyMesh pShapeMesh
(
IOobject
(
polyMesh::defaultRegion,
runTime.constant(),
runTime
),
xferMove(points),
cellShapes,
patchFaces,
patchNames,
patchDicts,
defaultFacesName,
defaultFacesType
);
if (cellTypes.size() > 0 || patchNames.size() > 0)
{
DynamicList<pointZone*> pz;
DynamicList<faceZone*> fz;
DynamicList<cellZone*> cz;
// FaceZones
forAll(boundaryFaceLabels, patchI)
{
if (boundaryFaceLabels[patchI].size())
{
// Re-do the boundaryFaceLabels since the boundary face
// labels will be different on the pShapeMesh.
const faceList& bFaces = boundary[patchI];
labelList& bFaceLabels = boundaryFaceLabels[patchI];
forAll(bFaceLabels, i)
{
bFaceLabels[i] = findFace(pShapeMesh, bFaces[i]);
}
Info<< "Creating faceZone " << patchNames[patchI]
<< " with " << bFaceLabels.size() << " faces" << endl;
fz.append
(
new faceZone
(
patchNames[patchI],
bFaceLabels,
boolList(bFaceLabels.size(), false),
fz.size(),
pShapeMesh.faceZones()
)
);
}
}
// CellZones
labelList types = cellTypes.sortedToc();
forAll(types, j)
{
label cellType = types[j];
// Pick up cells in zone
DynamicList<label> addr;
SLList<label>::iterator cellMapIter = slCellMap.begin();
SLList<label>::iterator typeIter = slCellType.begin();
for
(
;
typeIter != slCellType.end();
++typeIter, ++cellMapIter
)
{
if (typeIter() == cellType)
{
addr.append(cellMap[cellMapIter()]);
}
}
Info<< "Creating cellZone " << cellTypes[cellType]
<< " with " << addr.size() << " cells" << endl;
cz.append
(
new cellZone
(
cellTypes[cellType],
addr,
j,
pShapeMesh.cellZones()
)
);
}
pShapeMesh.addZones(pz, fz, cz);
}
// Set the precision of the points data to 10
IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision()));
Info<< "Writing polyMesh" << endl;
pShapeMesh.write();
Info<< nl << "end" << endl;
return 0;
}
/* ------------------------------------------------------------------------- *\
------ End of ansysToFoam.L
\* ------------------------------------------------------------------------- */

View File

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

View File

@ -0,0 +1,761 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
cfx4ToFoam
Description
Converts a CFX 4 mesh to OpenFOAM format.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "IFstream.H"
#include "hexBlock.H"
#include "polyMesh.H"
#include "wallPolyPatch.H"
#include "symmetryPolyPatch.H"
#include "preservePatchTypes.H"
#include "cellShape.H"
#include "cellModeller.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::noParallel();
argList::validArgs.append("CFX geom file");
argList::addOption
(
"scale",
"factor",
"geometry scaling factor - default is 1"
);
argList args(argc, argv);
if (!args.check())
{
FatalError.exit();
}
const scalar scaleFactor = args.optionLookupOrDefault("scale", 1.0);
# include "createTime.H"
IFstream cfxFile(args[1]);
// Read the cfx information using a fixed format reader.
// Comments in the file are in C++ style, so the stream parser will remove
// them with no intervention
label nblock, npatch, nglue, nelem, npoint;
cfxFile >> nblock >> npatch >> nglue >> nelem >> npoint;
Info<< "Reading blocks" << endl;
PtrList<hexBlock> blocks(nblock);
{
word blockName;
label nx, ny, nz;
forAll(blocks, blockI)
{
cfxFile >> blockName;
cfxFile >> nx >> ny >> nz;
blocks.set(blockI, new hexBlock(nx, ny, nz));
}
}
Info<< "Reading patch definitions" << endl;
wordList cfxPatchTypes(npatch);
wordList cfxPatchNames(npatch);
labelList patchMasterBlocks(npatch);
labelList patchDirections(npatch);
labelListList patchRanges(npatch);
{
label no, blkNo, patchLabel;
forAll(cfxPatchTypes, patchI)
{
// Grab patch type and name
cfxFile >> cfxPatchTypes[patchI] >> cfxPatchNames[patchI] >> no;
// Grab patch range
patchRanges[patchI].setSize(6);
labelList& curRange = patchRanges[patchI];
forAll(curRange, rI)
{
cfxFile >> curRange[rI];
}
// Grab patch direction and master block ID
// Note: direc is the direction, from the cfx manual
// 0 = solid (3-D patch),
// 1 = high i, 2 = high j, 3 = high k
// 4 = low i, 5 = low j, 6 = low k
cfxFile >> patchDirections[patchI] >> blkNo >> patchLabel;
patchMasterBlocks[patchI] = blkNo - 1;
}
}
Info<< "Reading block glueing information" << endl;
labelList glueMasterPatches(nglue, -1);
labelList glueSlavePatches(nglue, -1);
{
label masterPatch, slavePatch;
label dirIndex1, dirIndex2, dirIndex3, joinNumber;
for (label glueI = 0; glueI < nglue; glueI++)
{
cfxFile >> masterPatch >> slavePatch;
cfxFile >> dirIndex1 >> dirIndex2 >> dirIndex3 >> joinNumber;
glueMasterPatches[glueI] = masterPatch - 1;
glueSlavePatches[glueI] = slavePatch - 1;
}
}
Info<< "Reading block points" << endl;
forAll(blocks, blockI)
{
Info<< "block " << blockI << " is a ";
blocks[blockI].readPoints(cfxFile);
}
Info<< "Calculating block offsets" << endl;
labelList blockOffsets(nblock, -1);
blockOffsets[0] = 0;
label nMeshPoints = blocks[0].nBlockPoints();
label nMeshCells = blocks[0].nBlockCells();
for (label blockI = 1; blockI < nblock; blockI++)
{
nMeshPoints += blocks[blockI].nBlockPoints();
nMeshCells += blocks[blockI].nBlockCells();
blockOffsets[blockI] =
blockOffsets[blockI - 1]
+ blocks[blockI - 1].nBlockPoints();
}
Info<< "Assembling patches" << endl;
faceListList rawPatches(npatch);
forAll(rawPatches, patchI)
{
const word& patchType = cfxPatchTypes[patchI];
// reject volume patches
if
(
patchType == "POROUS" || patchType == "SOLID"
|| patchType == "SOLCON" || patchType == "USER3D"
)
{
patchMasterBlocks[patchI] = -1;
rawPatches[patchI].setSize(0);
}
else
{
// read and create a 2-D patch
rawPatches[patchI] =
blocks[patchMasterBlocks[patchI]].patchFaces
(
patchDirections[patchI],
patchRanges[patchI]
);
}
}
Info<< "Merging points ";
labelList pointMergeList(nMeshPoints, -1);
// In order to ensure robust merging, it is necessary to traverse
// the patch glueing list until the pointMergeList stops changing.
//
// For efficiency, create merge pairs in the first pass
labelListListList glueMergePairs(glueMasterPatches.size());
forAll(glueMasterPatches, glueI)
{
const label masterPatch = glueMasterPatches[glueI];
const label slavePatch = glueSlavePatches[glueI];
const label blockPlabel = patchMasterBlocks[masterPatch];
const label blockNlabel = patchMasterBlocks[slavePatch];
const pointField& blockPpoints = blocks[blockPlabel].points();
const pointField& blockNpoints = blocks[blockNlabel].points();
const faceList& blockPFaces = rawPatches[masterPatch];
const faceList& blockNFaces = rawPatches[slavePatch];
labelListList& curPairs = glueMergePairs[glueI];
curPairs.setSize(blockPFaces.size());
if (blockPFaces.size() != blockNFaces.size())
{
FatalErrorIn(args.executable())
<< "Inconsistent number of faces for glue pair "
<< glueI << " between blocks " << blockPlabel + 1
<< " and " << blockNlabel + 1
<< abort(FatalError);
}
// Calculate sqr of the merge tolerance as 1/10th of the min
// sqr point to point distance on the block face. This is an
// N^2 algorithm, sorry but I cannot quickly come up with
// something better.
scalar sqrMergeTol = GREAT;
forAll(blockPFaces, blockPFaceLabel)
{
const labelList& blockPFacePoints =
blockPFaces[blockPFaceLabel];
forAll(blockPFacePoints, blockPFacePointI)
{
forAll(blockPFacePoints, blockPFacePointI2)
{
if (blockPFacePointI != blockPFacePointI2)
{
sqrMergeTol =
min
(
sqrMergeTol,
magSqr
(
blockPpoints
[blockPFacePoints[blockPFacePointI]]
- blockPpoints
[blockPFacePoints[blockPFacePointI2]]
)
);
}
}
}
}
sqrMergeTol /= 10.0;
register bool found = false;
// N-squared point search over all points of all faces of
// master block over all point of all faces of slave block
forAll(blockPFaces, blockPFaceLabel)
{
const labelList& blockPFacePoints =
blockPFaces[blockPFaceLabel];
labelList& cp = curPairs[blockPFaceLabel];
cp.setSize(blockPFacePoints.size());
forAll(blockPFacePoints, blockPFacePointI)
{
found = false;
forAll(blockNFaces, blockNFaceLabel)
{
const labelList& blockNFacePoints =
blockNFaces[blockNFaceLabel];
forAll(blockNFacePoints, blockNFacePointI)
{
if
(
magSqr
(
blockPpoints
[blockPFacePoints[blockPFacePointI]]
- blockNpoints
[blockNFacePoints[blockNFacePointI]]
)
< sqrMergeTol
)
{
// Found a new pair
found = true;
cp[blockPFacePointI] =
blockNFacePoints[blockNFacePointI];
label PpointLabel =
blockPFacePoints[blockPFacePointI]
+ blockOffsets[blockPlabel];
label NpointLabel =
blockNFacePoints[blockNFacePointI]
+ blockOffsets[blockNlabel];
label minPN = min(PpointLabel, NpointLabel);
if (pointMergeList[PpointLabel] != -1)
{
minPN = min(minPN, pointMergeList[PpointLabel]);
}
if (pointMergeList[NpointLabel] != -1)
{
minPN = min(minPN, pointMergeList[NpointLabel]);
}
pointMergeList[PpointLabel]
= pointMergeList[NpointLabel]
= minPN;
break;
}
}
if (found) break;
}
}
}
}
register bool changedPointMerge = false;
label nPasses = 0;
do
{
changedPointMerge = false;
nPasses++;
forAll(glueMasterPatches, glueI)
{
const label masterPatch = glueMasterPatches[glueI];
const label slavePatch = glueSlavePatches[glueI];
const label blockPlabel = patchMasterBlocks[masterPatch];
const label blockNlabel = patchMasterBlocks[slavePatch];
const faceList& blockPFaces = rawPatches[masterPatch];
const labelListList& curPairs = glueMergePairs[glueI];
forAll(blockPFaces, blockPFaceLabel)
{
const labelList& blockPFacePoints =
blockPFaces[blockPFaceLabel];
const labelList& cp = curPairs[blockPFaceLabel];
forAll(cp, blockPFacePointI)
{
label PpointLabel =
blockPFacePoints[blockPFacePointI]
+ blockOffsets[blockPlabel];
label NpointLabel =
cp[blockPFacePointI]
+ blockOffsets[blockNlabel];
if
(
pointMergeList[PpointLabel]
!= pointMergeList[NpointLabel]
)
{
changedPointMerge = true;
pointMergeList[PpointLabel]
= pointMergeList[NpointLabel]
= min
(
pointMergeList[PpointLabel],
pointMergeList[NpointLabel]
);
}
}
}
}
Info<< "." << flush;
}
while (changedPointMerge && nPasses < 8);
Info<< endl;
if (changedPointMerge == true)
{
FatalErrorIn(args.executable())
<< "Point merging failed after max number of passes."
<< abort(FatalError);
}
forAll(glueMasterPatches, glueI)
{
const label masterPatch = glueMasterPatches[glueI];
const label slavePatch = glueSlavePatches[glueI];
const label blockPlabel = patchMasterBlocks[masterPatch];
const label blockNlabel = patchMasterBlocks[slavePatch];
const faceList& blockPFaces = rawPatches[masterPatch];
const faceList& blockNFaces = rawPatches[slavePatch];
forAll(blockPFaces, blockPFaceLabel)
{
const labelList& blockPFacePoints
= blockPFaces[blockPFaceLabel];
forAll(blockPFacePoints, blockPFacePointI)
{
label PpointLabel =
blockPFacePoints[blockPFacePointI]
+ blockOffsets[blockPlabel];
if (pointMergeList[PpointLabel] == -1)
{
FatalErrorIn(args.executable())
<< "Unable to merge point " << blockPFacePointI
<< " of face " << blockPFaceLabel
<< " of block " << blockPlabel
<< abort(FatalError);
}
}
}
forAll(blockNFaces, blockNFaceLabel)
{
const labelList& blockNFacePoints
= blockNFaces[blockNFaceLabel];
forAll(blockNFacePoints, blockNFacePointI)
{
label NpointLabel =
blockNFacePoints[blockNFacePointI]
+ blockOffsets[blockNlabel];
if (pointMergeList[NpointLabel] == -1)
{
FatalErrorIn(args.executable())
<< "Unable to merge point " << blockNFacePointI
<< " of face " << blockNFaceLabel
<< " of block " << blockNlabel
<< abort(FatalError);
}
}
}
}
// sort merge list to return new point label (in new shorter list)
// given old point label
label nNewPoints = 0;
forAll(pointMergeList, pointLabel)
{
if (pointMergeList[pointLabel] > pointLabel)
{
FatalErrorIn(args.executable())
<< "ouch" << abort(FatalError);
}
if
(
(pointMergeList[pointLabel] == -1)
|| pointMergeList[pointLabel] == pointLabel
)
{
pointMergeList[pointLabel] = nNewPoints;
nNewPoints++;
}
else
{
pointMergeList[pointLabel] =
pointMergeList[pointMergeList[pointLabel]];
}
}
nMeshPoints = nNewPoints;
Info<< "Creating points" << endl;
pointField points(nMeshPoints);
forAll(blocks, blockI)
{
const pointField& blockPoints = blocks[blockI].points();
forAll(blockPoints, blockPointLabel)
{
points
[
pointMergeList
[
blockPointLabel
+ blockOffsets[blockI]
]
] = blockPoints[blockPointLabel];
}
}
// Scale the points
if (scaleFactor > 1.0 + SMALL || scaleFactor < 1.0 - SMALL)
{
points *= scaleFactor;
}
Info<< "Creating cells" << endl;
cellShapeList cellShapes(nMeshCells);
const cellModel& hex = *(cellModeller::lookup("hex"));
label nCreatedCells = 0;
forAll(blocks, blockI)
{
labelListList curBlockCells = blocks[blockI].blockCells();
forAll(curBlockCells, blockCellI)
{
labelList cellPoints(curBlockCells[blockCellI].size());
forAll(cellPoints, pointI)
{
cellPoints[pointI] =
pointMergeList
[
curBlockCells[blockCellI][pointI]
+ blockOffsets[blockI]
];
}
cellShapes[nCreatedCells] = cellShape(hex, cellPoints);
nCreatedCells++;
}
}
Info<< "Creating boundary patches" << endl;
faceListList boundary(npatch);
wordList patchNames(npatch);
wordList patchTypes(npatch);
word defaultFacesName = "defaultFaces";
word defaultFacesType = wallPolyPatch::typeName;
label nCreatedPatches = 0;
forAll(rawPatches, patchI)
{
if (rawPatches[patchI].size() && cfxPatchTypes[patchI] != "BLKBDY")
{
// Check if this name has been already created
label existingPatch = -1;
for (label oldPatchI = 0; oldPatchI < nCreatedPatches; oldPatchI++)
{
if (patchNames[oldPatchI] == cfxPatchNames[patchI])
{
existingPatch = oldPatchI;
break;
}
}
const faceList& curRawPatch = rawPatches[patchI];
label curBlock = patchMasterBlocks[patchI];
if (existingPatch >= 0)
{
Info<< "CFX patch " << patchI
<< ", of type " << cfxPatchTypes[patchI]
<< ", name " << cfxPatchNames[patchI]
<< " already exists as OpenFOAM patch " << existingPatch
<< ". Adding faces." << endl;
faceList& renumberedPatch = boundary[existingPatch];
label oldSize = renumberedPatch.size();
renumberedPatch.setSize(oldSize + curRawPatch.size());
forAll(curRawPatch, faceI)
{
const face& oldFace = curRawPatch[faceI];
face& newFace = renumberedPatch[oldSize + faceI];
newFace.setSize(oldFace.size());
forAll(oldFace, pointI)
{
newFace[pointI] =
pointMergeList
[
oldFace[pointI]
+ blockOffsets[curBlock]
];
}
}
}
else
{
// Real patch to be created
faceList& renumberedPatch = boundary[nCreatedPatches];
renumberedPatch.setSize(curRawPatch.size());
forAll(curRawPatch, faceI)
{
const face& oldFace = curRawPatch[faceI];
face& newFace = renumberedPatch[faceI];
newFace.setSize(oldFace.size());
forAll(oldFace, pointI)
{
newFace[pointI] =
pointMergeList
[
oldFace[pointI]
+ blockOffsets[curBlock]
];
}
}
Info<< "CFX patch " << patchI
<< ", of type " << cfxPatchTypes[patchI]
<< ", name " << cfxPatchNames[patchI]
<< " converted into OpenFOAM patch " << nCreatedPatches
<< " type ";
if (cfxPatchTypes[patchI] == "WALL")
{
Info<< "wall." << endl;
patchTypes[nCreatedPatches] = wallPolyPatch::typeName;
patchNames[nCreatedPatches] = cfxPatchNames[patchI];
nCreatedPatches++;
}
else if (cfxPatchTypes[patchI] == "SYMMET")
{
Info<< "symmetryPlane." << endl;
patchTypes[nCreatedPatches] = symmetryPolyPatch::typeName;
patchNames[nCreatedPatches] = cfxPatchNames[patchI];
nCreatedPatches++;
}
else if
(
cfxPatchTypes[patchI] == "INLET"
|| cfxPatchTypes[patchI] == "OUTLET"
|| cfxPatchTypes[patchI] == "PRESS"
|| cfxPatchTypes[patchI] == "CNDBDY"
|| cfxPatchTypes[patchI] == "USER2D"
)
{
Info<< "generic." << endl;
patchTypes[nCreatedPatches] = polyPatch::typeName;
patchNames[nCreatedPatches] = cfxPatchNames[patchI];
nCreatedPatches++;
}
else
{
FatalErrorIn(args.executable())
<< "Unrecognised CFX patch type "
<< cfxPatchTypes[patchI]
<< abort(FatalError);
}
}
}
}
boundary.setSize(nCreatedPatches);
patchTypes.setSize(nCreatedPatches);
patchNames.setSize(nCreatedPatches);
PtrList<dictionary> patchDicts;
preservePatchTypes
(
runTime,
runTime.constant(),
polyMesh::meshSubDir,
patchNames,
patchDicts,
defaultFacesName,
defaultFacesType
);
// Add information to dictionary
forAll(patchNames, patchI)
{
if (!patchDicts.set(patchI))
{
patchDicts.set(patchI, new dictionary());
}
// Add but not overwrite
patchDicts[patchI].add("type", patchTypes[patchI], false);
}
polyMesh pShapeMesh
(
IOobject
(
polyMesh::defaultRegion,
runTime.constant(),
runTime
),
xferMove(points),
cellShapes,
boundary,
patchNames,
patchDicts,
defaultFacesName,
defaultFacesType
);
// Set the precision of the points data to 10
IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision()));
Info<< "Writing polyMesh" << endl;
pShapeMesh.write();
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,390 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "hexBlock.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
label hexBlock::vtxLabel(label a, label b, label c) const
{
return (a + b*(xDim_ + 1) + c*(xDim_ + 1)*(yDim_ + 1));
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct from components
hexBlock::hexBlock(const label nx, const label ny, const label nz)
:
xDim_(nx),
yDim_(ny),
zDim_(nz),
blockHandedness_(noPoints),
points_((xDim_ + 1)*(yDim_ + 1)*(zDim_ + 1))
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void hexBlock::readPoints(Istream& is)
{
forAll(points_, i)
{
is >> points_[i].x() >> points_[i].y() >> points_[i].z();
}
// Calculate the handedness of the block
vector i = points_[xDim_] - points_[0];
vector j = points_[(xDim_ + 1)*yDim_] - points_[0];
vector k = points_[(xDim_ + 1)*(yDim_ + 1)*zDim_] - points_[0];
if (((i ^ j) & k) > 0)
{
Info<< "right-handed block" << endl;
blockHandedness_ = right;
}
else
{
Info<< "left-handed block" << endl;
blockHandedness_ = left;
}
}
labelListList hexBlock::blockCells() const
{
labelListList result(xDim_*yDim_*zDim_);
label cellNo = 0;
if (blockHandedness_ == right)
{
for (label k = 0; k <= zDim_ - 1; k++)
{
for (label j = 0; j <= yDim_ - 1; j++)
{
for (label i = 0; i <= xDim_ - 1; i++)
{
labelList& hexLabels = result[cellNo];
hexLabels.setSize(8);
hexLabels[0] = vtxLabel(i, j, k);
hexLabels[1] = vtxLabel(i+1, j, k);
hexLabels[2] = vtxLabel(i+1, j+1, k);
hexLabels[3] = vtxLabel(i, j+1, k);
hexLabels[4] = vtxLabel(i, j, k+1);
hexLabels[5] = vtxLabel(i+1, j, k+1);
hexLabels[6] = vtxLabel(i+1, j+1, k+1);
hexLabels[7] = vtxLabel(i, j+1, k+1);
cellNo++;
}
}
}
}
else if (blockHandedness_ == left)
{
for (label k = 0; k <= zDim_ - 1; k++)
{
for (label j = 0; j <= yDim_ - 1; j++)
{
for (label i = 0; i <= xDim_ - 1; i++)
{
labelList& hexLabels = result[cellNo];
hexLabels.setSize(8);
hexLabels[0] = vtxLabel(i, j, k+1);
hexLabels[1] = vtxLabel(i+1, j, k+1);
hexLabels[2] = vtxLabel(i+1, j+1, k+1);
hexLabels[3] = vtxLabel(i, j+1, k+1);
hexLabels[4] = vtxLabel(i, j, k);
hexLabels[5] = vtxLabel(i+1, j, k);
hexLabels[6] = vtxLabel(i+1, j+1, k);
hexLabels[7] = vtxLabel(i, j+1, k);
cellNo++;
}
}
}
}
else
{
FatalErrorIn("hexBlock::cellShapes()")
<< "Unable to determine block handedness as points "
<< "have not been read in yet"
<< abort(FatalError);
}
return result;
}
// Return block patch faces given direction and range limits
// From the cfx manual: direction
// 0 = solid (3-D patch),
// 1 = high i, 2 = high j, 3 = high k
// 4 = low i, 5 = low j, 6 = low k
faceList hexBlock::patchFaces(const label direc, const labelList& range) const
{
if (range.size() != 6)
{
FatalErrorIn
(
"patchFaces(const label direc, const labelList& range) const"
) << "Invalid size of the range array: " << range.size()
<< ". Should be 6 (xMin, xMax, yMin, yMax, zMin, zMax"
<< abort(FatalError);
}
label xMinRange = range[0];
label xMaxRange = range[1];
label yMinRange = range[2];
label yMaxRange = range[3];
label zMinRange = range[4];
label zMaxRange = range[5];
faceList result(0);
switch (direc)
{
case 1:
{
// high i = xmax
result.setSize
(
(yMaxRange - yMinRange + 1)*(zMaxRange - zMinRange + 1)
);
label p = 0;
for (label k = zMinRange - 1; k <= zMaxRange - 1; k++)
{
for (label j = yMinRange - 1; j <= yMaxRange - 1; j++)
{
result[p].setSize(4);
// set the points
result[p][0] = vtxLabel(xDim_, j, k);
result[p][1] = vtxLabel(xDim_, j+1, k);
result[p][2] = vtxLabel(xDim_, j+1, k+1);
result[p][3] = vtxLabel(xDim_, j, k+1);
p++;
}
}
result.setSize(p);
break;
}
case 2:
{
// high j = ymax
result.setSize
(
(xMaxRange - xMinRange + 1)*(zMaxRange - zMinRange + 1)
);
label p = 0;
for (label i = xMinRange - 1; i <= xMaxRange - 1; i++)
{
for (label k = zMinRange - 1; k <= zMaxRange - 1; k++)
{
result[p].setSize(4);
// set the points
result[p][0] = vtxLabel(i, yDim_, k);
result[p][1] = vtxLabel(i, yDim_, k + 1);
result[p][2] = vtxLabel(i + 1, yDim_, k + 1);
result[p][3] = vtxLabel(i + 1, yDim_, k);
p++;
}
}
result.setSize(p);
break;
}
case 3:
{
// high k = zmax
result.setSize
(
(xMaxRange - xMinRange + 1)*(yMaxRange - yMinRange + 1)
);
label p = 0;
for (label i = xMinRange - 1; i <= xMaxRange - 1; i++)
{
for (label j = yMinRange - 1; j <= yMaxRange - 1; j++)
{
result[p].setSize(4);
// set the points
result[p][0] = vtxLabel(i, j, zDim_);
result[p][1] = vtxLabel(i + 1, j, zDim_);
result[p][2] = vtxLabel(i + 1, j + 1, zDim_);
result[p][3] = vtxLabel(i, j + 1, zDim_);
p++;
}
}
result.setSize(p);
break;
}
case 4:
{
// low i = xmin
result.setSize
(
(yMaxRange - yMinRange + 1)*(zMaxRange - zMinRange + 1)
);
label p = 0;
for (label k = zMinRange - 1; k <= zMaxRange - 1; k++)
{
for (label j = yMinRange - 1; j <= yMaxRange - 1; j++)
{
result[p].setSize(4);
// set the points
result[p][0] = vtxLabel(0, j, k);
result[p][1] = vtxLabel(0, j, k + 1);
result[p][2] = vtxLabel(0, j + 1, k + 1);
result[p][3] = vtxLabel(0, j + 1, k);
p++;
}
}
result.setSize(p);
break;
}
case 5:
{
// low j = ymin
result.setSize
(
(xMaxRange - xMinRange + 1)*(zMaxRange - zMinRange + 1)
);
label p = 0;
for (label i = xMinRange - 1; i <= xMaxRange - 1; i++)
{
for (label k = zMinRange - 1; k <= zMaxRange - 1; k++)
{
result[p].setSize(4);
// set the points
result[p][0] = vtxLabel(i, 0, k);
result[p][1] = vtxLabel(i + 1, 0, k);
result[p][2] = vtxLabel(i + 1, 0, k + 1);
result[p][3] = vtxLabel(i, 0, k + 1);
p++;
}
}
result.setSize(p);
break;
}
case 6:
{
// low k = zmin
result.setSize
(
(xMaxRange - xMinRange + 1)*(yMaxRange - yMinRange + 1)
);
label p = 0;
for (label i = xMinRange - 1; i <= xMaxRange - 1; i++)
{
for (label j = yMinRange - 1; j <= yMaxRange - 1; j++)
{
result[p].setSize(4);
// set the points
result[p][0] = vtxLabel(i, j, 0);
result[p][1] = vtxLabel(i, j + 1, 0);
result[p][2] = vtxLabel(i + 1, j + 1, 0);
result[p][3] = vtxLabel(i + 1, j, 0);
p++;
}
}
result.setSize(p);
break;
}
default:
{
FatalErrorIn
(
"patchFaces(const label direc, const labelList& range) const"
) << "direction out of range (1 to 6): " << direc
<< abort(FatalError);
}
}
// Correct the face orientation based on the handedness of the block.
// Do nothing for the right-handed block
if (blockHandedness_ == noPoints)
{
FatalErrorIn
(
"patchFaces(const label direc, const labelList& range) const"
) << "Unable to determine block handedness as points "
<< "have not been read in yet"
<< abort(FatalError);
}
else if (blockHandedness_ == left)
{
// turn all faces inside out
forAll(result, faceI)
{
result[faceI].flip();
}
}
return result;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,159 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::hexBlock
Description
Hex block definition used in the cfx converter.
SourceFiles
hexBlock.C
\*---------------------------------------------------------------------------*/
#ifndef hexBlock_H
#define hexBlock_H
#include "labelList.H"
#include "pointField.H"
#include "faceList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class hexBlock Declaration
\*---------------------------------------------------------------------------*/
class hexBlock
{
// Private data
//- Handedness of the block
enum handed
{
noPoints,
right,
left
};
//- Number of point in each direction
label xDim_;
label yDim_;
label zDim_;
//- Handedness of the block
handed blockHandedness_;
//- List of points
pointField points_;
// Private Member Functions
//- Disallow default bitwise copy construct
hexBlock(const hexBlock&);
//- Disallow default bitwise assignment
void operator=(const hexBlock&);
//- Vertex addressing inside the block
inline label vtxLabel(label i, label j, label k) const;
public:
// Constructors
//- Construct from components
hexBlock(const label nx, const label ny, const label nz);
// Member Functions
//- Number of points
label xDim() const
{
return xDim_;
}
label yDim() const
{
return yDim_;
}
label zDim() const
{
return zDim_;
}
label nBlockPoints() const
{
return (xDim_ + 1)*(yDim_ + 1)*(zDim_ + 1);
}
label nBlockCells() const
{
return xDim_*yDim_*zDim_;
}
//- Return block points
const pointField& points() const
{
if (blockHandedness_ == noPoints)
{
FatalErrorIn("hexBlock::points() const")
<< "points not read in yet"
<< abort(FatalError);
}
return points_;
}
//- Return block cells
labelListList blockCells() const;
//- Return block patch faces given direction and range limits
// From the cfx manual: direction
// 0 = solid (3-D patch),
// 1 = high i, 2 = high j, 3 = high k
// 4 = low i, 5 = low j, 6 = low k
faceList patchFaces(label direc, const labelList& range) const;
//- Read block points
void readPoints(Istream&);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

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

View File

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

View File

@ -0,0 +1,151 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
datToFoam
Description
Reads in a datToFoam mesh file and outputs a points file. Used in
conjunction with blockMesh.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "IFstream.H"
#include "OFstream.H"
#include "pointField.H"
#include "unitConversion.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::noParallel();
argList::validArgs.append("dat file");
argList args(argc, argv);
if (!args.check())
{
FatalError.exit();
}
#include "createTime.H"
std::ifstream plot3dFile(args.args()[1].c_str());
string line;
std::getline(plot3dFile, line);
std::getline(plot3dFile, line);
IStringStream Istring(line);
word block;
string zoneName;
token punctuation;
label iPoints;
label jPoints;
Istring >> block;
Istring >> block;
Istring >> zoneName;
Istring >> punctuation;
Istring >> block;
Istring >> iPoints;
Istring >> block;
Istring >> jPoints;
Info<< "Number of vertices in i direction = " << iPoints << endl
<< "Number of vertices in j direction = " << jPoints << endl;
// We ignore the first layer of points in i and j the biconic meshes
label nPointsij = (iPoints - 1)*(jPoints - 1);
pointField points(nPointsij, vector::zero);
for (direction comp = 0; comp < 2; comp++)
{
label p(0);
for (label j = 0; j < jPoints; j++)
{
for (label i = 0; i < iPoints; i++)
{
double coord;
plot3dFile >> coord;
// if statement ignores the first layer in i and j
if (i>0 && j>0)
{
points[p++][comp] = coord;
}
}
}
}
// correct error in biconic meshes
forAll(points, i)
{
if (points[i][1] < 1e-07)
{
points[i][1] = 0.0;
}
}
pointField pointsWedge(nPointsij*2, vector::zero);
fileName pointsFile(runTime.constantPath()/"points.tmp");
OFstream pFile(pointsFile);
scalar a(degToRad(0.1));
tensor rotateZ =
tensor
(
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, -::sin(a), ::cos(a)
);
forAll(points, i)
{
pointsWedge[i] = (rotateZ & points[i]);
pointsWedge[i+nPointsij] = cmptMultiply
(
vector(1.0, 1.0, -1.0),
pointsWedge[i]
);
}
Info<< "Writing points to: " << nl
<< " " << pointsFile << endl;
pFile << pointsWedge;
Info<< "End" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,3 @@
fluent3DMeshToFoam.L
EXE = $(FOAM_APPBIN)/fluent3DMeshToFoam

View File

@ -0,0 +1,7 @@
EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude
EXE_LIBS = \
-lmeshTools \
-ldynamicMesh

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
extrudedTriangleCellShape.C
extrudedQuadCellShape.C
create3DCellShape.C
fluentMeshToFoam.L
EXE = $(FOAM_APPBIN)/fluentMeshToFoam

View File

@ -0,0 +1,7 @@
EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude
EXE_LIBS = \
-lmeshTools \
-ldynamicMesh

View File

@ -0,0 +1,35 @@
Notes for fluentMeshToFoam with zone preservation
#################################################
1. New option added:
- writeSets:
Writes all Fluent boundaries faceSets preserving Fluent names
Writes all Fluent regions to cellSets preserving Fluent names
lines: 1375 - 1393 & 1673 - 1741
sets are useful for post-processing using foamToVTK with the "-faceSet
<name>" and "-cellSet <name>" options.
- writeZones:
Writes all regions to cellZones preserving Fluent names
Writes all region internal face to faceZones preserving Fluent names
lines: 1545 - 1667
Zones are usefull for porous media and MRF calculations
2. Zone Access
- Zones are simple lists of label lists that can be accessed from polyMesh
with the cellZones(), faceZones() and pointZones() member functions
- Example (Members from polyMesh.H and ZoneMesh.H):
const labelList& thisCellZone = mesh.cellZones()["thisZoneName"];
- Zone integrity is preserved during mesh modification and decompomposition.
- Once created via addZones, zones allow modification through non-const
access
3. Fluent boundary types.
- All internal and baffle elements are ignored during conversion
- Boundary faces labelled as internal (i.e. interior, interface, internal,
solid, fan, radiator, porous-jump) but that are in fact external boundaries
will be added to a default wall boundary.

View File

@ -0,0 +1,87 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
InClass
Foam::cellShapeRecognition
Description
\*---------------------------------------------------------------------------*/
#ifndef cellShapeRecognition_H
#define cellShapeRecognition_H
#include "cellShape.H"
#include "cellModeller.H"
#include "faceList.H"
#include "PtrList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
cellShape extrudedTriangleCellShape
(
const label cellIndex,
const labelList& faceLabels,
const faceList& faces,
const labelList& owner,
const labelList& neighbour,
const label pointOffset,
faceList& frontAndBackFaces
);
cellShape extrudedQuadCellShape
(
const label cellIndex,
const labelList& faceLabels,
const faceList& faces,
const labelList& owner,
const labelList& neighbour,
const label pointOffset,
faceList& frontAndBackFaces
);
cellShape create3DCellShape
(
const label cellIndex,
const labelList& faceLabels,
const faceList& faces,
const labelList& owner,
const labelList& neighbour,
const label fluentCellModelID
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,297 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description
Construct a cell shape from face information
\*---------------------------------------------------------------------------*/
#include "cellShapeRecognition.H"
#include "labelList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
cellShape create3DCellShape
(
const label cellIndex,
const labelList& faceLabels,
const faceList& faces,
const labelList& owner,
const labelList& neighbour,
const label fluentCellModelID
)
{
// List of pointers to shape models for 3-D shape recognition
static List<const cellModel*> fluentCellModelLookup
(
7,
reinterpret_cast<const cellModel*>(0)
);
fluentCellModelLookup[2] = cellModeller::lookup("tet");
fluentCellModelLookup[4] = cellModeller::lookup("hex");
fluentCellModelLookup[5] = cellModeller::lookup("pyr");
fluentCellModelLookup[6] = cellModeller::lookup("prism");
static label faceMatchingOrder[7][6] =
{
{-1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1},
{ 0, 1, 2, 3, -1, -1}, // tet
{-1, -1, -1, -1, -1, -1},
{ 0, 2, 4, 3, 5, 1}, // hex
{ 0, 1, 2, 3, 4, -1}, // pyr
{ 0, 2, 3, 4, 1, -1}, // prism
};
const cellModel& curModel = *fluentCellModelLookup[fluentCellModelID];
// Checking
if (faceLabels.size() != curModel.nFaces())
{
FatalErrorIn
(
"create3DCellShape(const label cellIndex, "
"const labelList& faceLabels, const labelListList& faces, "
"const labelList& owner, const labelList& neighbour, "
"const label fluentCellModelID)"
) << "Number of face labels not equal to"
<< "number of face in the model. "
<< "Number of face labels: " << faceLabels.size()
<< " number of faces in model: " << curModel.nFaces()
<< abort(FatalError);
}
// make a list of outward-pointing faces
labelListList localFaces(faceLabels.size());
forAll(faceLabels, faceI)
{
const label curFaceLabel = faceLabels[faceI];
const labelList& curFace = faces[curFaceLabel];
if (owner[curFaceLabel] == cellIndex)
{
localFaces[faceI] = curFace;
}
else if (neighbour[curFaceLabel] == cellIndex)
{
// Reverse the face
localFaces[faceI].setSize(curFace.size());
forAllReverse(curFace, i)
{
localFaces[faceI][curFace.size() - i - 1] =
curFace[i];
}
}
else
{
FatalErrorIn
(
"create3DCellShape(const label cellIndex, "
"const labelList& faceLabels, const labelListList& faces, "
"const labelList& owner, const labelList& neighbour, "
"const label fluentCellModelID)"
) << "face " << curFaceLabel
<< " does not belong to cell " << cellIndex
<< ". Face owner: " << owner[curFaceLabel] << " neighbour: "
<< neighbour[curFaceLabel]
<< abort(FatalError);
}
}
// Algorithm:
// Make an empty list of pointLabels and initialise it with -1. Pick the
// first face from modelFaces and look through the faces to find one with
// the same number of labels. Insert face by copying its labels into
// pointLabels. Mark the face as used. Loop through all model faces.
// For each model face loop through faces. If the face is unused and the
// numbers of labels fit, try to match the face onto the point labels. If
// at least one edge is matched, insert the face into pointLabels. If at
// any stage the matching algorithm reaches the end of faces, the matching
// algorithm has failed. Once all the faces are matched, the list of
// pointLabels defines the model.
// Make a list of empty pointLabels
labelList pointLabels(curModel.nPoints(), -1);
// Follow the used mesh faces
List<bool> meshFaceUsed(localFaces.size(), false);
// Get the raw model faces
const faceList& modelFaces = curModel.modelFaces();
// Insert the first face into the list
const labelList& firstModelFace =
modelFaces[faceMatchingOrder[fluentCellModelID][0]];
bool found = false;
forAll(localFaces, meshFaceI)
{
if (localFaces[meshFaceI].size() == firstModelFace.size())
{
// Match. Insert points into the pointLabels
found = true;
const labelList& curMeshFace = localFaces[meshFaceI];
meshFaceUsed[meshFaceI] = true;
forAll(curMeshFace, pointI)
{
pointLabels[firstModelFace[pointI]] = curMeshFace[pointI];
}
break;
}
}
if (!found)
{
FatalErrorIn
(
"create3DCellShape(const label cellIndex, "
"const labelList& faceLabels, const labelListList& faces, "
"const labelList& owner, const labelList& neighbour, "
"const label fluentCellModelID)"
) << "Cannot find match for first face. "
<< "cell model: " << curModel.name() << " first model face: "
<< firstModelFace << " Mesh faces: " << localFaces
<< abort(FatalError);
}
for (label modelFaceI = 1; modelFaceI < modelFaces.size(); modelFaceI++)
{
// get the next model face
const labelList& curModelFace =
modelFaces
[faceMatchingOrder[fluentCellModelID][modelFaceI]];
found = false;
// Loop through mesh faces until a match is found
forAll(localFaces, meshFaceI)
{
if
(
!meshFaceUsed[meshFaceI]
&& localFaces[meshFaceI].size() == curModelFace.size()
)
{
// A possible match. A mesh face will be rotated, so make a copy
labelList meshFaceLabels = localFaces[meshFaceI];
for
(
label rotation = 0;
rotation < meshFaceLabels.size();
rotation++
)
{
// try matching the face
label nMatchedLabels = 0;
forAll(meshFaceLabels, pointI)
{
if
(
pointLabels[curModelFace[pointI]]
== meshFaceLabels[pointI]
)
{
nMatchedLabels++;
}
}
if (nMatchedLabels >= 2)
{
// match!
found = true;
}
if (found)
{
// match found. Insert mesh face
forAll(meshFaceLabels, pointI)
{
pointLabels[curModelFace[pointI]] =
meshFaceLabels[pointI];
}
meshFaceUsed[meshFaceI] = true;
break;
}
else
{
// No match found. Rotate face
label firstLabel = meshFaceLabels[0];
for (label i = 1; i < meshFaceLabels.size(); i++)
{
meshFaceLabels[i - 1] = meshFaceLabels[i];
}
meshFaceLabels.last() = firstLabel;
}
}
if (found) break;
}
}
if (!found)
{
// A model face is not matched. Shape detection failed
FatalErrorIn
(
"create3DCellShape(const label cellIndex, "
"const labelList& faceLabels, const labelListList& faces, "
"const labelList& owner, const labelList& neighbour, "
"const label fluentCellModelID)"
) << "Cannot find match for face "
<< modelFaceI
<< ".\nModel: " << curModel.name() << " model face: "
<< curModelFace << " Mesh faces: " << localFaces
<< "Matched points: " << pointLabels
<< abort(FatalError);
}
}
return cellShape(curModel, pointLabels);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,275 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description
Construct an extruded hex cell shape from four straight edges
\*---------------------------------------------------------------------------*/
#include "cellShapeRecognition.H"
#include "labelList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
cellShape extrudedQuadCellShape
(
const label cellIndex,
const labelList& faceLabels,
const faceList& faces,
const labelList& owner,
const labelList& neighbour,
const label pointOffset,
faceList& frontAndBackFaces
)
{
static const cellModel* hexModelPtr_ = NULL;
if (!hexModelPtr_)
{
hexModelPtr_ = cellModeller::lookup("hex");
}
const cellModel& hex = *hexModelPtr_;
// Checking
if (faceLabels.size() != 4)
{
FatalErrorIn
(
"extrudedQuadCellShape(const label cellIndex, "
"const labelList& faceLabels, const faceList& faces, "
"const labelList& owner, const labelList& neighbour, "
"const label pointOffset, faceList& frontAndBackFaces)"
) << "Trying to create a quad with " << faceLabels.size() << " faces"
<< abort(FatalError);
}
// make a list of outward-pointing faces
labelListList localFaces(4);
forAll(faceLabels, faceI)
{
const label curFaceLabel = faceLabels[faceI];
const face& curFace = faces[curFaceLabel];
if (curFace.size() != 2)
{
FatalErrorIn
(
"extrudedQuadCellShape(const label cellIndex, "
"const labelList& faceLabels, const faceList& faces, "
"const labelList& owner, const labelList& neighbour, "
"const label pointOffset, faceList& frontAndBackFaces)"
) << "face " << curFaceLabel
<< "does not have 2 vertices. Number of vertices: " << curFace
<< abort(FatalError);
}
if (owner[curFaceLabel] == cellIndex)
{
localFaces[faceI] = curFace;
}
else if (neighbour[curFaceLabel] == cellIndex)
{
// Reverse the face. Note: it is necessary to reverse by
// hand to preserve connectivity of a 2-D mesh.
//
localFaces[faceI].setSize(curFace.size());
forAllReverse(curFace, i)
{
localFaces[faceI][curFace.size() - i - 1] =
curFace[i];
}
}
else
{
FatalErrorIn
(
"extrudedQuadCellShape(const label cellIndex, "
"const labelList& faceLabels, const faceList& faces, "
"const labelList& owner, const labelList& neighbour, "
"const label pointOffset, faceList& frontAndBackFaces)"
) << "face " << curFaceLabel
<< " does not belong to cell " << cellIndex
<< ". Face owner: " << owner[curFaceLabel] << " neighbour: "
<< neighbour[curFaceLabel]
<< abort(FatalError);
}
}
// Create a label list for the model
// This is done by finding two edges that do not share any vertices.
// Knowing the opposite pair of edges (with normals poining outward
// is enough to make a cell
if
(
localFaces[0][0] != localFaces[1][1]
&& localFaces[0][1] != localFaces[1][0]
)
{
// Set front and back plane faces
labelList missingPlaneFace(4);
// front plane
missingPlaneFace[0] = localFaces[0][0];
missingPlaneFace[1] = localFaces[1][1];
missingPlaneFace[2] = localFaces[1][0];
missingPlaneFace[3] = localFaces[0][1];
frontAndBackFaces[2*cellIndex] = face(missingPlaneFace);
// back plane
missingPlaneFace[0] = localFaces[0][0] + pointOffset;
missingPlaneFace[1] = localFaces[0][1] + pointOffset;
missingPlaneFace[2] = localFaces[1][0] + pointOffset;
missingPlaneFace[3] = localFaces[1][1] + pointOffset;
frontAndBackFaces[2*cellIndex + 1] = face(missingPlaneFace);
// make a cell
labelList cellShapeLabels(8);
cellShapeLabels[0] = localFaces[0][0];
cellShapeLabels[1] = localFaces[0][1];
cellShapeLabels[2] = localFaces[1][0];
cellShapeLabels[3] = localFaces[1][1];
cellShapeLabels[4] = localFaces[0][0] + pointOffset;
cellShapeLabels[5] = localFaces[0][1] + pointOffset;
cellShapeLabels[6] = localFaces[1][0] + pointOffset;
cellShapeLabels[7] = localFaces[1][1] + pointOffset;
return cellShape(hex, cellShapeLabels);
}
else if
(
localFaces[0][0] != localFaces[2][1]
&& localFaces[0][1] != localFaces[2][0]
)
{
// Set front and back plane faces
labelList missingPlaneFace(4);
// front plane
missingPlaneFace[0] = localFaces[0][0];
missingPlaneFace[1] = localFaces[2][1];
missingPlaneFace[2] = localFaces[2][0];
missingPlaneFace[3] = localFaces[0][1];
frontAndBackFaces[2*cellIndex] = face(missingPlaneFace);
// back plane
missingPlaneFace[0] = localFaces[0][0] + pointOffset;
missingPlaneFace[1] = localFaces[0][1] + pointOffset;
missingPlaneFace[2] = localFaces[2][0] + pointOffset;
missingPlaneFace[3] = localFaces[2][1] + pointOffset;
frontAndBackFaces[2*cellIndex + 1] = face(missingPlaneFace);
// make a cell
labelList cellShapeLabels(8);
cellShapeLabels[0] = localFaces[0][0];
cellShapeLabels[1] = localFaces[0][1];
cellShapeLabels[2] = localFaces[2][0];
cellShapeLabels[3] = localFaces[2][1];
cellShapeLabels[4] = localFaces[0][0] + pointOffset;
cellShapeLabels[5] = localFaces[0][1] + pointOffset;
cellShapeLabels[6] = localFaces[2][0] + pointOffset;
cellShapeLabels[7] = localFaces[2][1] + pointOffset;
return cellShape(hex, cellShapeLabels);
}
else if
(
localFaces[0][0] != localFaces[3][1]
&& localFaces[0][1] != localFaces[3][0]
)
{
// Set front and back plane faces
labelList missingPlaneFace(4);
// front plane
missingPlaneFace[0] = localFaces[0][0];
missingPlaneFace[1] = localFaces[3][1];
missingPlaneFace[2] = localFaces[3][0];
missingPlaneFace[3] = localFaces[0][1];
frontAndBackFaces[2*cellIndex] = face(missingPlaneFace);
// back plane
missingPlaneFace[0] = localFaces[0][0] + pointOffset;
missingPlaneFace[1] = localFaces[0][1] + pointOffset;
missingPlaneFace[2] = localFaces[3][0] + pointOffset;
missingPlaneFace[3] = localFaces[3][1] + pointOffset;
frontAndBackFaces[2*cellIndex + 1] = face(missingPlaneFace);
// make a cell
labelList cellShapeLabels(8);
cellShapeLabels[0] = localFaces[0][0];
cellShapeLabels[1] = localFaces[0][1];
cellShapeLabels[2] = localFaces[3][0];
cellShapeLabels[3] = localFaces[3][1];
cellShapeLabels[4] = localFaces[0][0] + pointOffset;
cellShapeLabels[5] = localFaces[0][1] + pointOffset;
cellShapeLabels[6] = localFaces[3][0] + pointOffset;
cellShapeLabels[7] = localFaces[3][1] + pointOffset;
return cellShape(hex, cellShapeLabels);
}
else
{
FatalErrorIn
(
"extrudedQuadCellShape(const label cellIndex, "
"const labelList& faceLabels, const faceList& faces, "
"const labelList& owner, const labelList& neighbour, "
"const label pointOffset, faceList& frontAndBackFaces)"
) << "Problem with edge matching. Edges: " << localFaces
<< abort(FatalError);
}
// Return added to keep compiler happy
return cellShape(hex, labelList(0));
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,215 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description
Construct an extruded triangular prism cell shape from three straight edges
\*---------------------------------------------------------------------------*/
#include "cellShapeRecognition.H"
#include "labelList.H"
#include "cellModeller.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
cellShape extrudedTriangleCellShape
(
const label cellIndex,
const labelList& faceLabels,
const faceList& faces,
const labelList& owner,
const labelList& neighbour,
const label pointOffset,
faceList& frontAndBackFaces
)
{
static const cellModel* prismModelPtr_ = NULL;
if (!prismModelPtr_)
{
prismModelPtr_ = cellModeller::lookup("prism");
}
const cellModel& prism = *prismModelPtr_;
// Checking
if (faceLabels.size() != 3)
{
FatalErrorIn
(
"extrudedTriangleCellShape(const label cellIndex, "
"const labelList& faceLabels, const faceList& faces, "
"const labelList& owner, const labelList& neighbour, "
"const label pointOffset, faceList& frontAndBackFaces)"
) << "Trying to create a triangle with " << faceLabels.size()
<< " faces"
<< abort(FatalError);
}
// make a list of outward-pointing faces
labelListList localFaces(3);
forAll(faceLabels, faceI)
{
const label curFaceLabel = faceLabels[faceI];
const face& curFace = faces[curFaceLabel];
if (curFace.size() != 2)
{
FatalErrorIn
(
"extrudedTriangleCellShape(const label cellIndex, "
"const labelList& faceLabels, const faceList& faces, "
"const labelList& owner, const labelList& neighbour, "
"const label pointOffset, faceList& frontAndBackFaces)"
) << "face " << curFaceLabel
<< "does not have 2 vertices. Number of vertices: " << curFace
<< abort(FatalError);
}
if (owner[curFaceLabel] == cellIndex)
{
localFaces[faceI] = curFace;
}
else if (neighbour[curFaceLabel] == cellIndex)
{
// Reverse the face. Note: it is necessary to reverse by
// hand to preserve connectivity of a 2-D mesh.
//
localFaces[faceI].setSize(curFace.size());
forAllReverse(curFace, i)
{
localFaces[faceI][curFace.size() - i - 1] =
curFace[i];
}
}
else
{
FatalErrorIn
(
"extrudedTriangleCellShape(const label cellIndex, "
"const labelList& faceLabels, const faceList& faces, "
"const labelList& owner, const labelList& neighbour, "
"const label pointOffset, faceList& frontAndBackFaces)"
) << "face " << curFaceLabel
<< " does not belong to cell " << cellIndex
<< ". Face owner: " << owner[curFaceLabel] << " neighbour: "
<< neighbour[curFaceLabel]
<< abort(FatalError);
}
}
// Create a label list for the model
if (localFaces[0][1] == localFaces[1][0])
{
// Set front and back plane faces
labelList missingPlaneFace(3);
// front plane
missingPlaneFace[0] = localFaces[0][0];
missingPlaneFace[1] = localFaces[1][1];
missingPlaneFace[2] = localFaces[0][1];
frontAndBackFaces[2*cellIndex] = face(missingPlaneFace);
// back plane
missingPlaneFace[0] = localFaces[0][0] + pointOffset;
missingPlaneFace[1] = localFaces[0][1] + pointOffset;
missingPlaneFace[2] = localFaces[1][1] + pointOffset;
frontAndBackFaces[2*cellIndex + 1] = face(missingPlaneFace);
// make a cell
labelList cellShapeLabels(6);
cellShapeLabels[0] = localFaces[0][0];
cellShapeLabels[1] = localFaces[0][1];
cellShapeLabels[2] = localFaces[1][1];
cellShapeLabels[3] = localFaces[0][0] + pointOffset;
cellShapeLabels[4] = localFaces[0][1] + pointOffset;
cellShapeLabels[5] = localFaces[1][1] + pointOffset;
return cellShape(prism, cellShapeLabels);
}
else if (localFaces[0][1] == localFaces[2][0])
{
// Set front and back plane faces
labelList missingPlaneFace(3);
// front plane
missingPlaneFace[0] = localFaces[0][0];
missingPlaneFace[1] = localFaces[2][1];
missingPlaneFace[2] = localFaces[0][1];
frontAndBackFaces[2*cellIndex] = face(missingPlaneFace);
// back plane
missingPlaneFace[0] = localFaces[0][0] + pointOffset;
missingPlaneFace[1] = localFaces[0][1] + pointOffset;
missingPlaneFace[2] = localFaces[2][1] + pointOffset;
frontAndBackFaces[2*cellIndex + 1] = face(missingPlaneFace);
// make a cell
labelList cellShapeLabels(6);
cellShapeLabels[0] = localFaces[0][0];
cellShapeLabels[1] = localFaces[0][1];
cellShapeLabels[2] = localFaces[2][1];
cellShapeLabels[3] = localFaces[0][0] + pointOffset;
cellShapeLabels[4] = localFaces[0][1] + pointOffset;
cellShapeLabels[5] = localFaces[2][1] + pointOffset;
return cellShape(prism, cellShapeLabels);
}
else
{
FatalErrorIn
(
"extrudedTriangleCellShape(const label cellIndex, "
"const labelList& faceLabels, const faceList& faces, "
"const labelList& owner, const labelList& neighbour, "
"const label pointOffset, faceList& frontAndBackFaces)"
) << "Problem with edge matching. Edges: " << localFaces
<< abort(FatalError);
}
// Return added to keep compiler happy
return cellShape(prism, labelList(0));
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@ -0,0 +1,307 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include <fstream>
#include <iostream>
using std::ofstream;
using std::ios;
#include "Time.H"
#include "fluentFvMesh.H"
#include "primitiveMesh.H"
#include "wallFvPatch.H"
#include "symmetryPlaneFvPatch.H"
#include "symmetryFvPatch.H"
#include "cellModeller.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fluentFvMesh::fluentFvMesh(const IOobject& io)
:
fvMesh(io)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::fluentFvMesh::writeFluentMesh() const
{
// make a directory called proInterface in the case
mkDir(time().rootPath()/time().caseName()/"fluentInterface");
// open a file for the mesh
ofstream fluentMeshFile
(
(
time().rootPath()/
time().caseName()/
"fluentInterface"/
time().caseName() + ".msh"
).c_str()
);
Info<< "Writing Header" << endl;
fluentMeshFile
<< "(0 \"FOAM to Fluent Mesh File\")" << std::endl << std::endl
<< "(0 \"Dimension:\")" << std::endl
<< "(2 3)" << std::endl << std::endl
<< "(0 \"Grid dimensions:\")" << std::endl;
// Writing number of points
fluentMeshFile
<< "(10 (0 1 ";
// Writing hex
fluentMeshFile.setf(ios::hex, ios::basefield);
fluentMeshFile
<< nPoints() << " 0 3))" << std::endl;
// Writing number of cells
fluentMeshFile
<< "(12 (0 1 "
<< nCells() << " 0 0))" << std::endl;
// Writing number of faces
label nFcs = nFaces();
fluentMeshFile
<< "(13 (0 1 ";
// Still writing hex
fluentMeshFile
<< nFcs << " 0 0))" << std::endl << std::endl;
// Return to dec
fluentMeshFile.setf(ios::dec, ios::basefield);
// Writing points
fluentMeshFile
<< "(10 (1 1 ";
fluentMeshFile.setf(ios::hex, ios::basefield);
fluentMeshFile
<< nPoints() << " 1 3)"
<< std::endl << "(" << std::endl;
fluentMeshFile.precision(10);
fluentMeshFile.setf(ios::scientific);
const pointField& p = points();
forAll(p, pointI)
{
fluentMeshFile
<< " "
<< p[pointI].x() << " "
<< p[pointI].y()
<< " " << p[pointI].z() << std::endl;
}
fluentMeshFile
<< "))" << std::endl << std::endl;
const labelUList& own = owner();
const labelUList& nei = neighbour();
const faceList& fcs = faces();
// Writing (mixed) internal faces
fluentMeshFile
<< "(13 (2 1 "
<< own.size() << " 2 0)" << std::endl << "(" << std::endl;
forAll(own, faceI)
{
const labelList& l = fcs[faceI];
fluentMeshFile << " ";
fluentMeshFile << l.size() << " ";
forAll(l, lI)
{
fluentMeshFile << l[lI] + 1 << " ";
}
fluentMeshFile << nei[faceI] + 1 << " ";
fluentMeshFile << own[faceI] + 1 << std::endl;
}
fluentMeshFile << "))" << std::endl;
label nWrittenFaces = own.size();
// Writing boundary faces
forAll(boundary(), patchI)
{
const faceUList& patchFaces = boundaryMesh()[patchI];
const labelList& patchFaceCells =
boundaryMesh()[patchI].faceCells();
// The face group will be offset by 10 from the patch label
// Write header
fluentMeshFile
<< "(13 (" << patchI + 10 << " " << nWrittenFaces + 1
<< " " << nWrittenFaces + patchFaces.size() << " ";
nWrittenFaces += patchFaces.size();
// Write patch type
if (isA<wallFvPatch>(boundary()[patchI]))
{
fluentMeshFile << 3;
}
else if
(
isA<symmetryPlaneFvPatch>(boundary()[patchI])
|| isA<symmetryFvPatch>(boundary()[patchI])
)
{
fluentMeshFile << 7;
}
else
{
fluentMeshFile << 4;
}
fluentMeshFile
<<" 0)" << std::endl << "(" << std::endl;
forAll(patchFaces, faceI)
{
const labelList& l = patchFaces[faceI];
fluentMeshFile << " ";
fluentMeshFile << l.size() << " ";
// Note: In Fluent, all boundary faces point inwards, which is
// opposite from the OpenFOAM convention.
// Turn them around on printout
forAllReverse (l, lI)
{
fluentMeshFile << l[lI] + 1 << " ";
}
fluentMeshFile << patchFaceCells[faceI] + 1 << " 0" << std::endl;
}
fluentMeshFile << "))" << std::endl;
}
// Writing cells
fluentMeshFile
<< "(12 (1 1 "
<< nCells() << " 1 0)(" << std::endl;
const cellModel& hex = *(cellModeller::lookup("hex"));
const cellModel& prism = *(cellModeller::lookup("prism"));
const cellModel& pyr = *(cellModeller::lookup("pyr"));
const cellModel& tet = *(cellModeller::lookup("tet"));
const cellShapeList& cells = cellShapes();
bool hasWarned = false;
forAll(cells, cellI)
{
if (cells[cellI].model() == tet)
{
fluentMeshFile << " " << 2;
}
else if (cells[cellI].model() == hex)
{
fluentMeshFile << " " << 4;
}
else if (cells[cellI].model() == pyr)
{
fluentMeshFile << " " << 5;
}
else if (cells[cellI].model() == prism)
{
fluentMeshFile << " " << 6;
}
else
{
if (!hasWarned)
{
hasWarned = true;
WarningIn("void fluentFvMesh::writeFluentMesh() const")
<< "foamMeshToFluent: cell shape for cell "
<< cellI << " only supported by Fluent polyhedral meshes."
<< nl
<< " Suppressing any further messages for polyhedral"
<< " cells." << endl;
}
fluentMeshFile << " " << 7;
}
}
fluentMeshFile << ")())" << std::endl;
// Return to dec
fluentMeshFile.setf(ios::dec, ios::basefield);
// Writing patch types
fluentMeshFile << "(39 (1 fluid fluid-1)())" << std::endl;
fluentMeshFile << "(39 (2 interior interior-1)())" << std::endl;
// Writing boundary patch types
forAll(boundary(), patchI)
{
fluentMeshFile
<< "(39 (" << patchI + 10 << " ";
// Write patch type
if (isA<wallFvPatch>(boundary()[patchI]))
{
fluentMeshFile << "wall ";
}
else if
(
isA<symmetryPlaneFvPatch>(boundary()[patchI])
|| isA<symmetryFvPatch>(boundary()[patchI])
)
{
fluentMeshFile << "symmetry ";
}
else
{
fluentMeshFile << "pressure-outlet ";
}
fluentMeshFile
<< boundary()[patchI].name() << ")())" << std::endl;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,75 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::fluentFvMesh
Description
SourceFiles
fluentFvMesh.C
\*---------------------------------------------------------------------------*/
#ifndef fluentFvMesh_H
#define fluentFvMesh_H
#include "fvMesh.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class fluentFvMesh Declaration
\*---------------------------------------------------------------------------*/
class fluentFvMesh
:
public fvMesh
{
public:
// Constructors
//- Construct from IOobject
fluentFvMesh(const IOobject& io);
// Member functions
//- Write Fluent mesh
void writeFluentMesh() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,67 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
foamMeshToFluent
Description
Writes out the OpenFOAM mesh in Fluent mesh format.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "fluentFvMesh.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::noParallel();
# include "setRootCase.H"
# include "createTime.H"
Info<< "Create mesh for time = "
<< runTime.timeName() << nl << endl;
fluentFvMesh mesh
(
IOobject
(
fluentFvMesh::defaultRegion,
runTime.constant(),
runTime
)
);
mesh.writeFluentMesh();
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

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

View File

@ -0,0 +1,7 @@
EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/conversion/lnInclude \
-I$(LIB_SRC)/fileFormats/lnInclude
EXE_LIBS = \
-lconversion

View File

@ -0,0 +1,140 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
foamToStarMesh
Description
Reads an OpenFOAM mesh and writes a pro-STAR (v4) bnd/cel/vrt format.
Usage
- foamToStarMesh [OPTION] \n
Reads an OpenFOAM mesh and writes a pro-STAR (v4) bnd/cel/vrt format.
\param -noBnd \n
Suppress writing the \c .bnd file
\param -scale \<factor\>\n
Specify an alternative geometry scaling factor.
The default is \b 1000 (scale \em [m] to \em [mm]).
Note
The cellTable information available in the files
\c constant/cellTable and \c constant/polyMesh/cellTableId
will be used if available. Otherwise the cellZones are used when
creating the cellTable information.
See Also
Foam::cellTable, Foam::meshWriter and Foam::meshWriters::STARCD
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "timeSelector.H"
#include "Time.H"
#include "polyMesh.H"
#include "STARCDMeshWriter.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::addNote
(
"read OpenFOAM mesh and write a pro-STAR (v4) bnd/cel/vrt format"
);
argList::noParallel();
timeSelector::addOptions();
argList::addOption
(
"scale",
"factor",
"geometry scaling factor - default is 1000 ([m] to [mm])"
);
argList::addBoolOption
(
"noBnd",
"suppress writing a boundary (.bnd) file"
);
# include "setRootCase.H"
# include "createTime.H"
instantList timeDirs = timeSelector::select0(runTime, args);
fileName exportName = meshWriter::defaultMeshName;
if (args.optionFound("case"))
{
exportName += '-' + args.globalCaseName();
}
// default: rescale from [m] to [mm]
scalar scaleFactor = 1000;
if (args.optionReadIfPresent("scale", scaleFactor))
{
if (scaleFactor <= 0)
{
scaleFactor = 1;
}
}
# include "createPolyMesh.H"
forAll(timeDirs, timeI)
{
runTime.setTime(timeDirs[timeI], timeI);
# include "getTimeIndex.H"
polyMesh::readUpdateState state = mesh.readUpdate();
if (!timeI || state != polyMesh::UNCHANGED)
{
meshWriters::STARCD writer(mesh, scaleFactor);
if (args.optionFound("noBnd"))
{
writer.noBoundary();
}
fileName meshName(exportName);
if (state != polyMesh::UNCHANGED)
{
meshName += '_' + runTime.timeName();
}
writer.write(meshName);
}
Info<< nl << endl;
}
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,51 @@
// Read time index from */uniform/time, but treat 0 and constant specially
word timeName = "0";
if
(
runTime.timeName() != runTime.constant()
&& runTime.timeName() != "0"
)
{
IOobject io
(
"time",
runTime.timeName(),
"uniform",
runTime,
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE,
false
);
if (io.headerOk())
{
IOdictionary timeObject
(
IOobject
(
"time",
runTime.timeName(),
"uniform",
runTime,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE,
false
)
);
label index;
timeObject.lookup("index") >> index;
timeName = Foam::name(index);
}
else
{
timeName = runTime.timeName();
// Info<< "skip ... missing entry " << io.objectPath() << endl;
// continue;
}
}
Info<< "\nTime [" << timeName << "] = " << runTime.timeName() << nl;

View File

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

View File

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

View File

@ -0,0 +1,140 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
foamToSurface
Description
Reads an OpenFOAM mesh and writes the boundaries in a surface format.
Usage
- foamToSurface [OPTION] \n
Reads an OpenFOAM mesh and writes the boundaries in a surface format.
\param -scale \<factor\>\n
Specify an alternative geometry scaling factor.
Eg, use \b 1000 to scale \em [m] to \em [mm].
\param -tri \n
Triangulate surface.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "timeSelector.H"
#include "Time.H"
#include "polyMesh.H"
#include "MeshedSurfaces.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::noParallel();
argList::validArgs.append("outputFile.ext");
timeSelector::addOptions();
argList::addOption
(
"scale",
"factor",
"geometry scaling factor - default is 1"
);
argList::addBoolOption
(
"tri",
"triangulate surface"
);
# include "setRootCase.H"
fileName exportName = args[1];
scalar scaleFactor = 0;
args.optionReadIfPresent<scalar>("scale", scaleFactor);
const bool doTriangulate = args.optionFound("tri");
fileName exportBase = exportName.lessExt();
word exportExt = exportName.ext();
if (!meshedSurface::canWriteType(exportExt, true))
{
return 1;
}
# include "createTime.H"
instantList timeDirs = timeSelector::select0(runTime, args);
# include "createPolyMesh.H"
forAll(timeDirs, timeI)
{
runTime.setTime(timeDirs[timeI], timeI);
# include "getTimeIndex.H"
polyMesh::readUpdateState state = mesh.readUpdate();
if (timeI == 0 || state != polyMesh::UNCHANGED)
{
if (state == polyMesh::UNCHANGED)
{
exportName = exportBase + "." + exportExt;
}
else
{
exportName =
exportBase + '_' + runTime.timeName() + "." + exportExt;
}
meshedSurface surf(mesh.boundaryMesh());
surf.scalePoints(scaleFactor);
Info<< "writing " << exportName;
if (doTriangulate)
{
Info<< " triangulated";
surf.triangulate();
}
if (scaleFactor <= 0)
{
Info<< " without scaling" << endl;
}
else
{
Info<< " with scaling " << scaleFactor << endl;
}
surf.write(exportName);
}
Info<< nl << endl;
}
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,51 @@
// Read time index from */uniform/time, but treat 0 and constant specially
word timeName = "0";
if
(
runTime.timeName() != runTime.constant()
&& runTime.timeName() != "0"
)
{
IOobject io
(
"time",
runTime.timeName(),
"uniform",
runTime,
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE,
false
);
if (io.headerOk())
{
IOdictionary timeObject
(
IOobject
(
"time",
runTime.timeName(),
"uniform",
runTime,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE,
false
)
);
label index;
timeObject.lookup("index") >> index;
timeName = Foam::name(index);
}
else
{
timeName = runTime.timeName();
// Info<< "skip ... missing entry " << io.objectPath() << endl;
// continue;
}
}
Info<< "\nTime [" << timeName << "] = " << runTime.timeName() << nl;

View File

@ -0,0 +1,3 @@
gambitToFoam.L
EXE = $(FOAM_APPBIN)/gambitToFoam

View File

@ -0,0 +1,877 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
gambitToFoam
Description
Converts a GAMBIT mesh to OpenFOAM format.
\*---------------------------------------------------------------------------*/
%{
#undef yyFlexLexer
/* ------------------------------------------------------------------------- *\
------ local definitions
\* ------------------------------------------------------------------------- */
#include "scalarList.H"
#include "IStringStream.H"
// For EOF only
#include <cstdio>
using namespace Foam;
#include "argList.H"
#include "Time.H"
#include "polyMesh.H"
#include "emptyPolyPatch.H"
#include "preservePatchTypes.H"
#include "cellModeller.H"
#include "cellShape.H"
#include "SLList.H"
#include "SLPtrList.H"
label nPoints = 0;
label nCells = 0;
label nCellStreams = 0;
label nPatches = 0;
label nCoordDirections = 0;
label nVectorComponents = 0;
pointField points(0);
labelList pointMap(0);
PtrList<labelList> cellLabels(0);
labelList cellMap(0);
labelList cellTypes(0);
labelList cellStreamIDs(0);
wordList patchNames(0);
labelListList patchCells(0);
labelListList patchCellFaces(0);
label nValuesForPatchFaces = 0;
// Dummy yywrap to keep yylex happy at compile time.
// It is called by yylex but is not used as the mechanism to change file.
// See <<EOF>>
#if YY_FLEX_SUBMINOR_VERSION < 34
extern "C" int yywrap()
#else
int yyFlexLexer::yywrap()
#endif
{
return 1;
}
%}
one_space [ \t\f\r]
space {one_space}*
some_space {one_space}+
spaceNl ({space}|\n)*
alpha [_[:alpha:]]
digit [[:digit:]]
dotColonDash [.:-]
label [0-9]{digit}*
zeroLabel {digit}*
word ({alpha}|{digit}|{dotColonDash})*
exponent_part [eE][-+]?{digit}+
fractional_constant [-+]?(({digit}*"."{digit}+)|({digit}+"."?))
floatNum ((({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))|0)
x {floatNum}
y {floatNum}
z {floatNum}
labelListElement {space}{zeroLabel}
scalarListElement {space}{floatNum}
labelList ({labelListElement}+{space})
scalarList ({scalarListElement}+{space})
starStar ("**")
text ({space}({word}*{space})*\n)
dateDDMMYYYY ({digit}{digit}"/"{digit}{digit}"/"{digit}{digit}{digit}{digit})
dateDDMonYYYY ((({digit}{digit}{space})|({digit}{space})){alpha}*{space}{digit}{digit}{digit}{digit})
time ({digit}{digit}":"{digit}{digit}":"{digit}{digit})
versionNumber ({digit}|".")*
controlInfo ^{space}"CONTROL INFO"{space}{versionNumber}
applicationData ^{space}"APPLICATION DATA"{space}{versionNumber}
nodalCoords ^{space}"NODAL COORDINATES"{space}{versionNumber}
cellsAndElements ^{space}"ELEMENTS/CELLS"{space}{versionNumber}
cellStreams ^{space}"ELEMENT GROUP"{space}{versionNumber}
boundaryPatch ^{space}"BOUNDARY CONDITIONS"{space}{versionNumber}
faceConnectivity ^{space}"FACE CONNECTIVITY"{space}{versionNumber}
endOfSection ^{space}"ENDOFSECTION"{space}
program {space}"PROGRAM:"{space}
version {space}"VERSION:"{space}
group {space}"GROUP:"{space}
elements {space}"ELEMENTS:"{space}
material {space}"MATERIAL:"{space}
nFlags {space}"NFLAGS:"{space}
mtype {space}"MTYPE:"{space}
/* ------------------------------------------------------------------------- *\
----- Exclusive start states -----
\* ------------------------------------------------------------------------- */
%option stack
%x controlInfo
%x readControlHeader
%x readTitle
%x readProgramID
%x readVersionID
%x applicationData
%x nodalCoords
%x cellsAndElements
%x cellStreams
%x cellStreamTitle
%x cellStreamFlags
%x cellStreamLabels
%x readCellStreamGroupID
%x readCellStreamNElements
%x readCellStreamMaterial
%x readCellStreamNFlags
%x boundaryPatch
%x boundaryPatchParams
%x boundaryPatchFaces
%x faceConnectivity
%x globalMeshData
%x cellContLine
%%
%{
label nCellContinuationLines = 0;
label curNumberOfNodes = 0;
label curNumberOfCells = 0;
label curGroupID = 0;
label nFlagsForStream = 0;
label curBoundaryPatch = 0;
label curPatchFace = 0;
%}
/* ------------------------------------------------------------------------- *\
------ Start Lexing ------
\* ------------------------------------------------------------------------- */
/* ------ Reading control header ------ */
{controlInfo} {
BEGIN(readControlHeader);
}
<readControlHeader>{starStar}{space}{text} {
BEGIN(readTitle);
}
<readTitle>{text} {
Info << "Title: " << YYText();
BEGIN(controlInfo);
}
<controlInfo>{spaceNl}{program} {
BEGIN(readProgramID);
}
<readProgramID>{space}{word} {
Info<< "Written by " << YYText() << " ";
BEGIN(controlInfo);
}
<controlInfo>{spaceNl}{version} {
BEGIN(readVersionID);
}
<readVersionID>{space}{versionNumber} {
Info<< " version " << YYText() << endl;
BEGIN(controlInfo);
}
<controlInfo>{space}{dateDDMonYYYY}{space}{time} {
Info<< "File written on " << YYText() << endl;
}
<controlInfo>{space}{dateDDMMYYYY}{space}{time} {
Info<< "File written on " << YYText() << endl;
}
<controlInfo>{spaceNl}"NUMNP"{space}"NELEM"{space}"NGRPS"{space}"NBSETS"{space}("NDFCD"|"NDCFD"){space}"NDFVL"{space}\n {
BEGIN(globalMeshData);
}
<globalMeshData>{spaceNl}{label}{space}{label}{space}{label}{space}{label}{space}{label}{space}{label}{space}\n {
IStringStream nodeStream(YYText());
nPoints = readLabel(nodeStream);
nCells = readLabel(nodeStream);
nCellStreams = readLabel(nodeStream);
nPatches = readLabel(nodeStream);
nCoordDirections = readLabel(nodeStream);
nVectorComponents = readLabel(nodeStream);
// reset list sizes - now known!
points.setSize(nPoints);
pointMap.setSize(nPoints);
cellLabels.setSize(nCells);
cellMap.setSize(nCells);
cellTypes.setSize(nCells);
cellStreamIDs.setSize(nCells);
patchNames.setSize(nPatches);
patchCells.setSize(nPatches);
patchCellFaces.setSize(nPatches);
Info<< " number of points: " << nPoints << endl
<< " number of cells: " << nCells << endl
<< " number of patches: " << nPatches << endl;
BEGIN(controlInfo);
}
/* ------ Reading nodal coordinates ------ */
{nodalCoords}{spaceNl} {
curNumberOfNodes = 0;
Info<< "Reading nodal coordinates" << endl;
BEGIN(nodalCoords);
}
<nodalCoords>{spaceNl}{label}{space}{x}{space}{y}{space}{z}{space}\n {
IStringStream nodeStream(YYText());
label nodeI(readLabel(nodeStream));
// Note: coordinates must be read one at the time.
scalar x = readScalar(nodeStream);
scalar y = readScalar(nodeStream);
scalar z = readScalar(nodeStream);
// add mapping and scalced node to the list
pointMap[curNumberOfNodes] = nodeI;
points[curNumberOfNodes] = point(x, y, z);
curNumberOfNodes++;
}
/* ------ Reading cells and elements ------ */
{cellsAndElements}{spaceNl} {
curNumberOfCells = 0;
Info<< "Reading cells" << endl;
BEGIN(cellsAndElements);
}
<cellsAndElements>{spaceNl}{label}{space}{label}{space}{label}{labelList} {
IStringStream elementStream(YYText());
label cellI(readLabel(elementStream));
label cellType(readLabel(elementStream));
label nVertices(readLabel(elementStream));
// reset number of continuation lines
nCellContinuationLines = 0;
cellMap[curNumberOfCells] = cellI;
cellTypes[curNumberOfCells] = cellType;
cellLabels.set(curNumberOfCells, new labelList(nVertices));
labelList& curLabels = cellLabels[curNumberOfCells];
// Find out how many labels are expected. If less or equal to
// seven, read them all and finish with it. If there is more,
// set read of the next line
label labelsToRead = min(8, nVertices);
label labelI = 0;
for (; labelI < labelsToRead; labelI++)
{
if (elementStream.eof()) break;
// Check token to avoid trailing space.
token curLabelTok(elementStream);
if (curLabelTok.isLabel())
{
curLabels[labelI] = curLabelTok.labelToken();
}
else
{
break;
}
}
if (labelI < nVertices)
{
BEGIN(cellContLine);
}
else
{
curNumberOfCells++;
}
}
<cellContLine>{spaceNl}{labelList} {
IStringStream elementStream(YYText());
nCellContinuationLines++;
labelList& curLabels = cellLabels[curNumberOfCells];
label labelsToRead = min
(
(nCellContinuationLines + 1)*7,
curLabels.size()
);
for
(
label labelI = nCellContinuationLines*7;
labelI < labelsToRead;
labelI++
)
{
curLabels[labelI] = readLabel(elementStream);
}
// if read is finished, go back to reading cells
if (curLabels.size() < (nCellContinuationLines + 1)*7)
{
curNumberOfCells++;
BEGIN(cellsAndElements);
}
}
/* ------ Reading element group information ------ */
{cellStreams}{spaceNl} {
Info<< "Reading cell streams" << endl;
BEGIN(cellStreams);
}
<cellStreams>{spaceNl}{group} {
BEGIN(readCellStreamGroupID);
}
<readCellStreamGroupID>{space}{label} {
IStringStream groupStream(YYText());
if (curGroupID > 0)
{
FatalErrorIn("gambitToFoam::main")
<< "<readCellStreamGroupID>{space}{label} : "
<< "trying to reset group ID while active"
<< abort(FatalError);
}
else
{
curGroupID = readLabel(groupStream);
}
BEGIN(cellStreams);
}
<cellStreams>{spaceNl}{elements} {
BEGIN(readCellStreamNElements);
}
<readCellStreamNElements>{space}{label} {
IStringStream nElementsStream(YYText());
readLabel(nElementsStream);
BEGIN(cellStreams);
}
<cellStreams>{spaceNl}{material} {
BEGIN(readCellStreamMaterial);
}
<readCellStreamMaterial>{space}{label} {
IStringStream materialIDstream(YYText());
readLabel(materialIDstream);
BEGIN(cellStreams);
}
<cellStreams>{spaceNl}{nFlags} {
BEGIN(readCellStreamNFlags);
}
<readCellStreamNFlags>{space}{label} {
IStringStream nFlagsStream(YYText());
nFlagsForStream = readLabel(nFlagsStream);
BEGIN(cellStreamTitle);
}
<cellStreamTitle>{spaceNl}{word}{spaceNl} {
word streamName(Foam::string::validate<word>(YYText()));
BEGIN(cellStreamFlags);
}
<cellStreamFlags>{labelList} {
Info<< "Reading cell stream labels" << endl;
BEGIN(cellStreamLabels);
}
<cellStreamLabels>{spaceNl}{labelList} {
IStringStream nFlagsStream(YYText());
label cellLabel;
while (nFlagsStream.read(cellLabel))
{
cellStreamIDs[cellLabel - 1] = curGroupID;
}
// reset current group ID and a number of flags
curGroupID = 0;
nFlagsForStream = 0;
}
/* ------ Reading end of section and others ------ */
<cellStreamLabels>{endOfSection}\n {
Info<< "Finished reading cell stream labels" << endl;
// reset current group ID and a number of flags
curGroupID = 0;
nFlagsForStream = 0;
BEGIN(INITIAL);
}
{boundaryPatch}{spaceNl} {
curPatchFace = 0;
Info<< "Reading patches" << endl;
BEGIN(boundaryPatchParams);
}
<boundaryPatchParams>{spaceNl}{word}{labelList} {
IStringStream patchParamsStream(YYText());
patchParamsStream.read(patchNames[curBoundaryPatch]);
readLabel(patchParamsStream);
label nEntry(readLabel(patchParamsStream));
nValuesForPatchFaces = readLabel(patchParamsStream);
patchCells[curBoundaryPatch].setSize(nEntry);
patchCellFaces[curBoundaryPatch].setSize(nEntry);
Info<< "patch " << curBoundaryPatch
<< ": name: " << patchNames[curBoundaryPatch]
<< endl;
BEGIN(boundaryPatchFaces);
}
<boundaryPatchFaces>{spaceNl}{label}{space}{label}{space}{label}({scalarList}|{space}\n) {
// Face-based boundary condition
IStringStream patchFacesStream(YYText());
patchCells[curBoundaryPatch][curPatchFace] =
readLabel(patchFacesStream);
readLabel(patchFacesStream);
patchCellFaces[curBoundaryPatch][curPatchFace] =
readLabel(patchFacesStream);
// patch face values currently discarded
if (nValuesForPatchFaces > 0)
{
scalarList patchFaceValues(nValuesForPatchFaces);
forAll(patchFaceValues, fI)
{
patchFaceValues[fI] = readScalar(patchFacesStream);
}
}
curPatchFace++;
}
<boundaryPatchFaces>{spaceNl}{label}({scalarList}|\n) {
// Vertex-based boundary condition
FatalErrorIn("gambitToFoam::main")
<< "<boundaryPatchFaces>{spaceNl}{label}{scalarList} : "
<< "boundary condition specified on vertices not supported"
<< abort(FatalError);
}
<boundaryPatchFaces>{endOfSection}\n {
curBoundaryPatch++;
BEGIN(INITIAL);
}
/* ------ Reading end of section and others ------ */
<controlInfo,nodalCoords,cellsAndElements>{endOfSection}\n {
BEGIN(INITIAL);
}
/* ------ Ignore remaining space and \n s. Any other characters are errors. */
.|\n {}
/* ------ On EOF return to previous file, if none exists terminate. ------ */
<<EOF>> {
yyterminate();
}
%%
#include "fileName.H"
#include <fstream>
using std::ifstream;
int main(int argc, char *argv[])
{
argList::noParallel();
argList::validArgs.append("GAMBIT file");
argList::addOption
(
"scale",
"factor",
"geometry scaling factor - default is 1"
);
argList args(argc, argv);
if (!args.check())
{
FatalError.exit();
}
const scalar scaleFactor = args.optionLookupOrDefault("scale", 1.0);
# include "createTime.H"
const fileName gambitFile = args[1];
ifstream gambitStream(gambitFile.c_str());
if (!gambitStream)
{
FatalErrorIn("gambitToFoam::main")
<< args.executable()
<< ": file " << gambitFile << " not found"
<< abort(FatalError);
}
yyFlexLexer lexer(&gambitStream);
while (lexer.yylex() != 0)
{}
Info<< "Finished lexing" << endl;
// make a point mapping array
label maxPointIndex = 0;
forAll(pointMap, pointI)
{
if (pointMap[pointI] > maxPointIndex)
{
maxPointIndex = pointMap[pointI];
}
}
labelList pointLookup(maxPointIndex + 1, -1);
forAll(pointMap, pointI)
{
pointLookup[pointMap[pointI] ] = pointI;
}
// make a cell mapping array
label maxCellIndex = 0;
forAll(cellMap, cellI)
{
if (cellMap[cellI] > maxCellIndex)
{
maxCellIndex = cellMap[cellI];
}
}
labelList cellLookup(maxCellIndex + 1);
forAll(cellMap, cellI)
{
cellLookup[cellMap[cellI] ] = cellI;
}
const cellModel& hex = *(cellModeller::lookup("hex"));
const cellModel& prism = *(cellModeller::lookup("prism"));
const cellModel& pyr = *(cellModeller::lookup("pyr"));
const cellModel& tet = *(cellModeller::lookup("tet"));
labelList labelsHex(8);
labelList labelsPrism(6);
labelList labelsPyramid(5);
labelList labelsTet(4);
cellShapeList cells(cellLabels.size());
forAll(cellTypes, cellI)
{
const labelList& curCellLabels = cellLabels[cellI];
// Tetrahedron
if (cellTypes[cellI] == 6)
{
labelsTet[0] = pointLookup[curCellLabels[0] ];
labelsTet[1] = pointLookup[curCellLabels[2] ];
labelsTet[2] = pointLookup[curCellLabels[3] ];
labelsTet[3] = pointLookup[curCellLabels[1] ];
cells[cellI] = cellShape(tet, labelsTet);
}
// Square-based pyramid
else if (cellTypes[cellI] == 7)
{
labelsPyramid[0] = pointLookup[curCellLabels[0] ];
labelsPyramid[1] = pointLookup[curCellLabels[1] ];
labelsPyramid[2] = pointLookup[curCellLabels[3] ];
labelsPyramid[3] = pointLookup[curCellLabels[2] ];
labelsPyramid[4] = pointLookup[curCellLabels[4] ];
cells[cellI] = cellShape(pyr, labelsPyramid);
}
// Triangular prism
else if (cellTypes[cellI] == 5)
{
labelsPrism[0] = pointLookup[curCellLabels[0] ];
labelsPrism[1] = pointLookup[curCellLabels[1] ];
labelsPrism[2] = pointLookup[curCellLabels[2] ];
labelsPrism[3] = pointLookup[curCellLabels[3] ];
labelsPrism[4] = pointLookup[curCellLabels[4] ];
labelsPrism[5] = pointLookup[curCellLabels[5] ];
cells[cellI] = cellShape(prism, labelsPrism);
}
// Hex
else if (cellTypes[cellI] == 4)
{
labelsHex[0] = pointLookup[curCellLabels[0] ];
labelsHex[1] = pointLookup[curCellLabels[1] ];
labelsHex[2] = pointLookup[curCellLabels[3] ];
labelsHex[3] = pointLookup[curCellLabels[2] ];
labelsHex[4] = pointLookup[curCellLabels[4] ];
labelsHex[5] = pointLookup[curCellLabels[5] ];
labelsHex[6] = pointLookup[curCellLabels[7] ];
labelsHex[7] = pointLookup[curCellLabels[6] ];
cells[cellI] = cellShape(hex, labelsHex);
}
}
// give foam model face number given a fluent model face number
label faceIndex[8][6] =
{
{-1, -1, -1, -1, -1, -1}, // 0
{-1, -1, -1, -1, -1, -1}, // 1
{-1, -1, -1, -1, -1, -1}, // 2
{ 2, 1, 3, 0, 4, 5}, // Hex (3)
{-1, -1, -1, -1, -1, -1}, // 4
{ 4, 3, 2, 0, 1, -1}, // Triangular prism (5)
{ 0, 4, 3, 2, 1, -1}, // Pyramid (6)
{ 2, 1, 0, 3, -1, -1} // Tet (7)
};
faceListList boundary(patchCells.size());
forAll(patchCells, patchI)
{
labelList& curCells = patchCells[patchI];
labelList& curFaces = patchCellFaces[patchI];
faceList& patchFaces = boundary[patchI];
patchFaces.setSize(curCells.size());
forAll(curCells, faceI)
{
patchFaces[faceI] =
cells[cellLookup[curCells[faceI] ] ].faces()
[
faceIndex
[
// this picks a cell type
cells[cellLookup[curCells[faceI] ] ]
.model().index()
]
[curFaces[faceI] - 1] // this gives a fluent face - 1
];
}
}
Info<< "gambitToFoam: " << endl
<< "Gambit file format does not provide information about the type of "
<< "the patch (eg. wall, symmetry plane, cyclic etc)." << endl
<< "All the patches have been created "
<< "as type patch. Please reset after mesh conversion as necessary."
<< endl;
// Scale points
points *= scaleFactor;
PtrList<dictionary> patchDicts(boundary.size());
word defaultFacesName = "defaultFaces";
word defaultFacesType = emptyPolyPatch::typeName;
preservePatchTypes
(
runTime,
runTime.constant(),
polyMesh::meshSubDir,
patchNames,
patchDicts,
defaultFacesName,
defaultFacesType
);
// Add information to dictionary
forAll(patchNames, patchI)
{
if (!patchDicts.set(patchI))
{
patchDicts.set(patchI, new dictionary());
}
// Add but not overwrite
patchDicts[patchI].add("type", polyPatch::typeName, false);
}
polyMesh pShapeMesh
(
IOobject
(
polyMesh::defaultRegion,
runTime.constant(),
runTime
),
xferMove(points),
cells,
boundary,
patchNames,
patchDicts,
defaultFacesName,
defaultFacesType
);
// Set the precision of the points data to 10
IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision()));
Info<< "Writing polyMesh" << endl;
pShapeMesh.write();
Info<< "\nEnd\n" << endl;
return 0;
}
/* ------------------------------------------------------------------------- *\
------ End of gambitToFoam.L
\* ------------------------------------------------------------------------- */

View File

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

View File

@ -0,0 +1,7 @@
EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude
EXE_LIBS = \
-ldynamicMesh \
-lmeshTools

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,79 @@
// Parametres geometriques
r1 = 200*Cos(Pi/4)/1000;
r2 = 200*Cos(Pi/4)/1000;
h1 = 250/1000;
h2 = 360/1000;
h3 = 900/1000;
h4 = 1900/1000;
// Parametres de maillage
// selon le rayon
rCells = 10/2; rRatio = 0.85;
// selon S1
S1Cells = 30/2; S1ratio = 1;
// selon S2
S2Cells = 35/2; S2ratio = 0.95;
// selon S3
S3Cells = 20/2; S3ratio = 1;
Point(1) = {r1, r1, h4};
Point(2) = {r1, r1, h3};
Point(3) = {r2, r2, h2};
Point(4) = {r2, r2, h1};
Point(5) = {0, 0, h1};
Point(6) = {0, 0, h2};
Point(7) = {0, 0, h3};
Point(8) = {0, 0, h4};
Line(1) = {8, 1};
Line(2) = {1, 2};
Line(3) = {7, 2};
Line(4) = {8, 7};
Line(5) = {2, 3};
Line(6) = {6, 3};
Line(7) = {7, 6};
Line(8) = {3, 4};
Line(9) = {5, 4};
Line(10) = {6, 5};
Line Loop(11) = {1, 2, -3, -4};
Ruled Surface(12) = {11};
Line Loop(13) = {5, -6, -7, 3};
Ruled Surface(14) = {13};
Line Loop(15) = {8, -9, -10, 6};
Ruled Surface(16) = {15};
Transfinite Line {1, 3, 6, 9} = rCells Using Progression rRatio;
Transfinite Line {4, 2} = S1Cells Using Progression S1ratio;
Transfinite Line {7, 5} = S2Cells Using Progression S2ratio;
Transfinite Line {10, 8} = S3Cells Using Progression S3ratio;
Transfinite Surface {12} = {8, 1, 2, 7};
Transfinite Surface {14} = {7, 2, 3, 6};
Transfinite Surface {16} = {6, 3, 4, 5};
Recombine Surface {12, 14, 16};
Extrude {{0, 0, 1}, {0, 0, 0}, Pi/2} {
Surface{12, 14, 16};
Layers{25};
Recombine;
}
Extrude {{0, 0, 1}, {0, 0, 0}, Pi/2} {
Surface{33, 50, 67};
Layers{25};
Recombine;
}
Extrude {{0, 0, 1}, {0, 0, 0}, Pi/2} {
Surface{84, 101, 118};
Layers{25};
Recombine;
}
Extrude {{0, 0, 1}, {0, 0, 0}, Pi/2} {
Surface{135, 152, 169};
Layers{25};
Recombine;
}
Physical Surface("entree") = {126, 75, 24, 177};
Physical Surface("S1") = {28, 181, 130, 79};
Physical Surface("S2") = {93, 42, 193, 144};
Physical Surface("S3") = {110, 59, 205, 161};
Physical Surface("fond") = {113, 62, 208, 164};
Physical Volume("fluide") = {4, 7, 10, 1, 5, 8, 11, 2, 9, 12, 3, 6};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -0,0 +1,7 @@
EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/surfMesh/lnInclude
EXE_LIBS = \
-lmeshTools \
-lsurfMesh

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,768 @@
-1
151
D:\CFD Test Cases\FEMAP\block1.MOD
D:\CFD Test Cases\FEMAP\block1.MOD
NEiNastran for Windows
20-Jan-07 04:54:48 9 20 0
Never Never
NEiNastran for Windows
20-Jan-07 04:54:48 9 20 10 0 0
-1
-1
180
00 2000
01 2001
02 2002
03 2003
04 2004
05 2005
06 2006
07 2007
08 2008
09 2009
10 2010
11 2011
12 2012
13 2013
14 2014
15 2015
16 2016
17 2017
18 2018
19 2019
20 2020
21 2021
22 2022
23 2023
24 2024
25 2025
26 2026
27 2027
28 2028
29 2029
30 2030
31 2031
32 2032
33 2033
34 2034
35 2035
36 2036
37 2037
38 2038
39 2039
40 2040
41 2041
42 2042
43 2043
44 2044
45 2045
46 2046
47 2047
48 2048
49 2049
50 2050
51 2051
52 2052
53 2053
54 2054
55 2055
56 2056
57 2057
58 2058
59 2059
60 2060
61 2061
62 2062
63 2063
64 2064
65 2065
66 2066
67 2067
68 2068
69 2069
70 1970
71 1971
72 1972
73 1973
74 1974
75 1975
76 1976
77 1977
78 1978
79 1979
80 1980
81 1981
82 1982
83 1983
84 1984
85 1985
86 1986
87 1987
88 1988
89 1989
90 1990
91 1991
92 1992
93 1993
94 1994
95 1995
96 1996
97 1997
98 1998
99 1999
-1
-1
164
1Meter (newton) 1
1.00000000000000000E+0 1.00000000000000000E+0 1.00000000000000000E+0
2.73149999999999980E+2
-1
-1
1710
================================================================================
MATERIAL
================================================================================
1 fluid (1)
0 LINE(S) OF TEXT
0 MATERIAL CLASS(ES)
0 MATERIAL ATTRIBUTE(S)
0 MATERIAL COMPONENT(S)
0 MATERIAL SPECIFICATION(S)
--------------------------------------------------------------------------------
0 MATERIAL VARIABLE(S)
--------------------------------------------------------------------------------
27 MATERIAL PROPERT(IES)
--------------------------------------------------------------------------------
MODULUS OF ELASTICITY
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
PRESSURE PASCAL
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
SHEAR MODULUS
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
PRESSURE PASCAL
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
POISSONS RATIO
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
DIMENSIONLESS UNITLESS
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
COEFFICIENT OF THERMAL EXPANSION
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
COEFFICIENT OF THERMAL EXPANSION 1/KELVIN
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
THERMAL CONDUCTIVITY
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
CONDUCTIVITY J/M/K/SEC
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
SPECIFIC HEAT
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
SPECIFIC HEAT J/KG/K
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
HEAT GENERATION RATE
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
HEAT FLUX PER UNIT VOLUME J/M^3/SEC
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
MASS DENSITY
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
MASS DENSITY KILOGRAM/METER^3
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
STRUCTURAL ELEMENT DAMPING COEFFICIENT
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
DIMENSIONLESS UNITLESS
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
THERMAL EXPANSION REFERENCE TEMPERATURE
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
TEMPERATURE KELVIN
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
ALLOWABLE STRESS IN TENSION X-DIR
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
PRESSURE PASCAL
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
ALLOWABLE STRESS IN COMPRESSION X-DIR
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
PRESSURE PASCAL
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
ALLOWABLE STRESS IN TENSION Y-DIR
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
PRESSURE PASCAL
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
ALLOWABLE STRESS IN COMPRESSION Y-DIR
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
PRESSURE PASCAL
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
ALLOWABLE IN-PLANE SHEAR STRESS
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
PRESSURE PASCAL
CONSTANT
0.00000000000000000E+0
--------------------------------------------------------------------------------
YIELD STRESS
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
PRESSURE PASCAL
NULL_PROPERTY
--------------------------------------------------------------------------------
CONVECTIVE FILM COEFFICIENT
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
CONVECTION COEFFICIENT J/M^2/K/SEC
NULL_PROPERTY
--------------------------------------------------------------------------------
THERMAL CAPACITY PER UNIT AREA
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
THERMAL CAPACITY PER UNIT AREA J/M^2/K
NULL_PROPERTY
--------------------------------------------------------------------------------
SURFACE HEAT FLUX RATE
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
HEAT FLUX PER UNIT AREA J/M^2/SEC
NULL_PROPERTY
--------------------------------------------------------------------------------
VISCOSITY
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
VISCOSITY KG/M/SEC
NULL_PROPERTY
--------------------------------------------------------------------------------
COEFFICIENT OF FRICTION
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
DIMENSIONLESS UNITLESS
NULL_PROPERTY
--------------------------------------------------------------------------------
AREA FACTOR
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
DIMENSIONLESS UNITLESS
NULL_PROPERTY
--------------------------------------------------------------------------------
EMISSIVITY
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
DIMENSIONLESS UNITLESS
NULL_PROPERTY
--------------------------------------------------------------------------------
ABSORPTIVITY
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
DIMENSIONLESS UNITLESS
NULL_PROPERTY
--------------------------------------------------------------------------------
HEAT FLUX RATE
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
HEAT FLUX PER UNIT LENGTH J/M/SEC
NULL_PROPERTY
--------------------------------------------------------------------------------
INTERACTION TERM FOR TSAI-WU
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
DIMENSIONLESS UNITLESS
NULL_PROPERTY
--------------------------------------------------------------------------------
SWELLING COEFFICIENT
1 VERSION NUMBER
0 LINE(S) OF TEXT
DIMENSIONS AND UNITS:
DIMENSIONLESS UNITLESS
NULL_PROPERTY
--------------------------------------------------------------------------------
DEFAULT MATERIAL PROPERT(IES):
MODULUS OF ELASTICITY VERSION : 1
SHEAR MODULUS VERSION : 1
POISSONS RATIO VERSION : 1
COEFFICIENT OF THERMAL EXPANSION VERSION : 1
THERMAL CONDUCTIVITY VERSION : 1
SPECIFIC HEAT VERSION : 1
HEAT GENERATION RATE VERSION : 1
MASS DENSITY VERSION : 1
STRUCTURAL ELEMENT DAMPING COEFFICIENT VERSION : 1
THERMAL EXPANSION REFERENCE TEMPERATURE VERSION : 1
ALLOWABLE STRESS IN TENSION X-DIR VERSION : 1
ALLOWABLE STRESS IN COMPRESSION X-DIR VERSION : 1
ALLOWABLE STRESS IN TENSION Y-DIR VERSION : 1
ALLOWABLE STRESS IN COMPRESSION Y-DIR VERSION : 1
ALLOWABLE IN-PLANE SHEAR STRESS VERSION : 1
YIELD STRESS VERSION : 1
CONVECTIVE FILM COEFFICIENT VERSION : 1
THERMAL CAPACITY PER UNIT AREA VERSION : 1
SURFACE HEAT FLUX RATE VERSION : 1
VISCOSITY VERSION : 1
COEFFICIENT OF FRICTION VERSION : 1
AREA FACTOR VERSION : 1
EMISSIVITY VERSION : 1
ABSORPTIVITY VERSION : 1
HEAT FLUX RATE VERSION : 1
INTERACTION TERM FOR TSAI-WU VERSION : 1
SWELLING COEFFICIENT VERSION : 1
--------------------------------------------------------------------------------
1 REFERENCE ENTITIES
1 MATERIAL TYPES
FEM ISOTROPIC MATERIALS
================================================================================
-1
-1
2420
100
Untitled
1 0 8
CS1
1.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 1.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 1.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
4 0 15
NEiNastran for Windows Global Rectangular (4)
1.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 1.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 1.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
5 1 15
NEiNastran for Windows Global Cylindrical (5)
1.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 1.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 1.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
6 2 15
NEiNastran for Windows Global Spherical (6)
1.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 1.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 1.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
3 0 2
Coordinate System 3
1.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 1.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 1.00000000000000000E+0
5.00000000000000000E-1 5.00000000000000000E-1 1.00000000000000000E+0
-1
-1
2411
5 4 3 7
0.5 0.5 1.
6 4 4 7
0. 0.5 1.
9 4 4 7
0. 0. 1.
10 4 3 7
0.5 -0.5 0.
11 4 3 7
0.5 -0.5 0.5
12 4 3 7
0.5 -0.5 1.
13 4 4 7
0. -0.5 1.
15 4 4 7
-0.5 -0.5 0.5
16 4 4 7
-0.5 -0.5 0.
17 4 4 7
0. -0.5 0.
18 4 4 7
0. -0.5 0.5
21 4 4 7
-0.5 -0.5 1.
22 4 4 7
-0.5 0. 1.
24 4 4 7
-0.5 0.5 0.5
27 4 4 7
-0.5 0. 0.5
28 4 4 7
-0.5 0.5 0.
30 4 4 7
-0.5 0.5 1.
35 4 4 7
0. 0.5 0.
36 4 4 7
0. 0.5 0.5
37 4 3 7
0.5 0.5 0.
38 4 3 7
0.5 0. 0.
42 4 4 7
-0.5 0. 0.
45 4 4 7
0. 0. 0.
49 4 3 7
0.5 0.5 0.5
51 4 3 7
0.5 0. 1.
54 4 3 7
0.5 0. 0.5
55 4 4 7
0. 0. 0.5
60 4 3 7
0.5 0.5 1.
61 4 4 7
0. 0.5 1.
64 4 4 7
0. 0. 1.
65 4 3 7
0.5 -0.5 0.
66 4 3 7
0.5 -0.5 0.5
67 4 3 7
0.5 -0.5 1.
68 4 4 7
0. -0.5 1.
70 4 4 7
-0.5 -0.5 0.5
71 4 4 7
-0.5 -0.5 0.
72 4 4 7
0. -0.5 0.
73 4 4 7
0. -0.5 0.5
76 4 4 7
-0.5 -0.5 1.
77 4 4 7
-0.5 0. 1.
79 4 4 7
-0.5 0.5 0.5
82 4 4 7
-0.5 0. 0.5
83 4 4 7
-0.5 0.5 0.
85 4 4 7
-0.5 0.5 1.
90 4 4 7
0. 0.5 0.
91 4 4 7
0. 0.5 0.5
92 4 3 7
0.5 0.5 0.
93 4 3 7
0.5 0. 0.
97 4 4 7
-0.5 0. 0.
100 4 4 7
0. 0. 0.
104 4 3 7
0.5 0.5 0.5
106 4 3 7
0.5 0. 1.
109 4 3 7
0.5 0. 0.5
110 4 4 7
0. 0. 0.5
-1
-1
2431
-1
-1
2437
1 110 0
Property 1
-1
-1
776
-1
-1
2412
57 115 1 1 15 8
76 77 64 68 70 82 110 73
58 115 1 1 15 8
68 64 106 67 73 110 109 66
59 115 1 1 15 8
77 85 61 64 82 79 91 110
60 115 1 1 15 8
64 61 60 106 110 91 104 109
61 115 1 1 15 8
70 82 110 73 71 97 100 72
62 115 1 1 15 8
73 110 109 66 72 100 93 65
63 115 1 1 15 8
82 79 91 110 97 83 90 100
64 115 1 1 15 8
110 91 104 109 100 90 92 93
-1
-1
748
57 115
1.0000000E+0 0.0000000E+0 0.0000000E+0 0.0000000E+0 1.0000000E+0 0.0000000E+0
58 115
1.0000000E+0 0.0000000E+0 0.0000000E+0 0.0000000E+0 1.0000000E+0 0.0000000E+0
59 115
1.0000000E+0 0.0000000E+0 0.0000000E+0 0.0000000E+0 1.0000000E+0 0.0000000E+0
60 115
1.0000000E+0 0.0000000E+0 0.0000000E+0 0.0000000E+0 1.0000000E+0 0.0000000E+0
61 115
1.0000000E+0 0.0000000E+0 0.0000000E+0 0.0000000E+0 1.0000000E+0 0.0000000E+0
62 115
1.0000000E+0 0.0000000E+0 0.0000000E+0 0.0000000E+0 1.0000000E+0 0.0000000E+0
63 115
1.0000000E+0 0.0000000E+0 0.0000000E+0 0.0000000E+0 1.0000000E+0 0.0000000E+0
64 115
1.0000000E+0 0.0000000E+0 0.0000000E+0 0.0000000E+0 1.0000000E+0 0.0000000E+0
-1
-1
757
1
inlet ( 1)
15 4 1 1 1 1 1 1
16 4 1 1 1 1 1 1
21 4 1 1 1 1 1 1
22 4 1 1 1 1 1 1
24 4 1 1 1 1 1 1
27 4 1 1 1 1 1 1
28 4 1 1 1 1 1 1
30 4 1 1 1 1 1 1
42 4 1 1 1 1 1 1
70 4 1 1 1 1 1 1
71 4 1 1 1 1 1 1
76 4 1 1 1 1 1 1
77 4 1 1 1 1 1 1
79 4 1 1 1 1 1 1
82 4 1 1 1 1 1 1
83 4 1 1 1 1 1 1
85 4 1 1 1 1 1 1
97 4 1 1 1 1 1 1
-1
-1
757
2
Outlet ( 2)
5 4 1 0 0 0 0 0
10 4 1 0 0 0 0 0
11 4 1 0 0 0 0 0
12 4 1 0 0 0 0 0
37 4 1 0 0 0 0 0
38 4 1 0 0 0 0 0
49 4 1 0 0 0 0 0
51 4 1 0 0 0 0 0
54 4 1 0 0 0 0 0
60 4 1 0 0 0 0 0
65 4 1 0 0 0 0 0
66 4 1 0 0 0 0 0
67 4 1 0 0 0 0 0
92 4 1 0 0 0 0 0
93 4 1 0 0 0 0 0
104 4 1 0 0 0 0 0
106 4 1 0 0 0 0 0
109 4 1 0 0 0 0 0
-1
-1
791
1 1
inlet (1)
15 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
16 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
21 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
22 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
24 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
27 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
28 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
30 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
42 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
70 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
71 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
76 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
77 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
79 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
82 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
83 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
85 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
97 4 1 1 1 1 1 1 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
-1
-1
791
2 1
Outlet (2)
5 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
10 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
11 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
12 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
37 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
38 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
49 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
51 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
54 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
60 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
65 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
66 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
67 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
92 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
93 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
104 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
106 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
109 4 1 0 0 0 0 0 0 7 0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0.00000000000000000E+0 0.00000000000000000E+0 0.00000000000000000E+0
0 0 0 0 0 0
-1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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