diff --git a/applications/utilities/mesh/conversion/Optional/Allwmake b/applications/utilities/mesh/conversion/Optional/Allwmake index 19654fcf899028dc1f2e9b4f3e027c16e28d5082..a7a614f5cad3ab3c3253a0a6a5a0bc04433708fe 100755 --- a/applications/utilities/mesh/conversion/Optional/Allwmake +++ b/applications/utilities/mesh/conversion/Optional/Allwmake @@ -6,6 +6,7 @@ cd ${0%/*} || exit 1 # Run from this directory # Parse arguments for compilation (at least for error catching) . $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments + # Get version info and arch-path . $WM_PROJECT_DIR/etc/config.sh/functions _foamSource $($WM_PROJECT_DIR/bin/foamEtcFile config.sh/ccmio) diff --git a/applications/utilities/mesh/conversion/ccm/Allwmake b/applications/utilities/mesh/conversion/ccm/Allwmake new file mode 100755 index 0000000000000000000000000000000000000000..7f59349f938d1226dedd2f21374253faba698a27 --- /dev/null +++ b/applications/utilities/mesh/conversion/ccm/Allwmake @@ -0,0 +1,17 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory + +# Parse arguments for compilation (at least for error catching) +. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments + +# Only build if libraries already exist +if [ -e $FOAM_LIBBIN/libccm.so ] +then + echo "Building optional ccm conversion components." + wmake $targetType ccmToFoam + wmake $targetType foamToCcm +else + echo "Skipping optional ccm conversion components (no libccm.so)." +fi + +#------------------------------------------------------------------------------ diff --git a/applications/utilities/mesh/conversion/ccm/ccmToFoam/Make/files b/applications/utilities/mesh/conversion/ccm/ccmToFoam/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..f23232f5e96fec5b699265e74e94cd2d964ea87b --- /dev/null +++ b/applications/utilities/mesh/conversion/ccm/ccmToFoam/Make/files @@ -0,0 +1,3 @@ +ccmToFoam.C + +EXE = $(FOAM_APPBIN)/ccmToFoam diff --git a/applications/utilities/mesh/conversion/ccm/ccmToFoam/Make/options b/applications/utilities/mesh/conversion/ccm/ccmToFoam/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..8b1f005a7833c6c646d3983fc9d54014120a747e --- /dev/null +++ b/applications/utilities/mesh/conversion/ccm/ccmToFoam/Make/options @@ -0,0 +1,12 @@ +EXE_INC = \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/conversion/lnInclude \ + -I$(LIB_SRC)/conversion/ccm/lnInclude \ + -I$(LIB_SRC)/fileFormats/lnInclude + +EXE_LIBS = \ + -lfiniteVolume \ + -lgenericPatchFields \ + -lmeshTools \ + -lconversion -lccm diff --git a/applications/utilities/mesh/conversion/ccm/ccmToFoam/ccmToFoam.C b/applications/utilities/mesh/conversion/ccm/ccmToFoam/ccmToFoam.C new file mode 100644 index 0000000000000000000000000000000000000000..5b0a4cf660521e2a28e9449e7c0954331e83d244 --- /dev/null +++ b/applications/utilities/mesh/conversion/ccm/ccmToFoam/ccmToFoam.C @@ -0,0 +1,314 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Application + ccmToFoam + +Group + grpMeshConversionUtilities + +Description + Reads CCM files as written by PROSTAR/STARCCM and writes an + OPENFOAM polyMesh. + +Usage + \b ccmToFoam [OPTION] ccmMesh + + Options: + - \par -ascii + Write in ASCII format instead of binary + + - \par -export + re-export mesh in CCM format for post-processing + + - \par -list + List some information about the geometry + + - \par -name \<name\> + Provide alternative base name for export. Default is <tt>meshExport</tt>. + + - \par -combine + Combine identically named patches + + - \par -noBaffles + Remove any baffles by merging the faces. + + - \par -merge + Merge in-place interfaces + + - \par -numbered + Use numbered patch/zone (not names) directly from ccm ids. + + - \par -remap \<name\> + use specified remapping dictionary instead of <tt>constant/remapping</tt> + + - \par -scale \<factor\> + Specify an alternative geometry scaling factor. + The default is \b 1 (no scaling). + + - \par -solids + Treat any solid cells present just like fluid cells. + The default is to remove them. + +Note + - sub-domains (fluid | solid | porosity) are stored as separate domains + within the CCM file. These are merged together to form a single mesh. + - baffles are written as interfaces for later use + +See also + Foam::ccm::reader for more information about the File Locations + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "Time.H" +#include "ccm.H" +#include "regionSplit.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char *argv[]) +{ + argList::addNote + ( + "Reads CCM files as written by PROSTAR/STARCCM and writes an" + " OPENFOAM polyMesh." + ); + + argList::noParallel(); + argList::validArgs.append("ccmMesh"); + argList::addBoolOption + ( + "ascii", + "write in ASCII format instead of binary" + ); + argList::addBoolOption + ( + "export", + "re-export mesh in CCM format for post-processing" + ); + argList::addBoolOption + ( + "list", + "list some information about the geometry" + ); + argList::addOption + ( + "remap", + "name", + "use specified remapping dictionary instead of <constant/remapping>" + ); + argList::addOption + ( + "name", + "name", + "provide alternative base name when re-exporting (implies -export). " + "Default is <meshExport>." + ); + argList::addBoolOption + ( + "combine", + "combine identically named patches" + ); + argList::addBoolOption + ( + "noBaffles", + "remove any baffles by merging the faces" + ); + argList::addBoolOption + ( + "merge", + "merge in-place interfaces" + ); + argList::addBoolOption + ( + "numbered", + "use numbered names (eg, patch_0, zone_0) only" + ); + argList::addOption + ( + "scale", + "scale", + "geometry scaling factor - default is 1 (ie, no scaling)" + ); + argList::addBoolOption + ( + "withSolid", + "treat any solid cells present just like fluid cells. " + "the default is to remove them." + ); + + argList args(argc, argv); + Time runTime(args.rootPath(), args.caseName()); + runTime.functionObjects().off(); + + const bool optList = args.optionFound("list"); + + // exportName only has a size when export is in effect + fileName exportName; + if (args.optionReadIfPresent("name", exportName)) + { + const word ext = exportName.ext(); + // strip erroneous extension (.ccm, .ccmg, .ccmp) + if (ext == "ccm" || ext == "ccmg" || ext == "ccmp") + { + exportName = exportName.lessExt(); + } + } + else if (args.optionFound("export")) + { + exportName = ccm::writer::defaultMeshName; + if (args.optionFound("case")) + { + exportName += '-' + args.globalCaseName(); + } + } + + // By default, no scaling + const scalar scaleFactor = args.optionLookupOrDefault("scale", 1.0); + + // Default to binary output, unless otherwise specified + const IOstream::streamFormat format = + ( + args.optionFound("ascii") + ? IOstream::ASCII + : IOstream::BINARY + ); + + // Increase the precision of the points data + IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision())); + + + // Read control options + // ~~~~~~~~~~~~~~~~~~~~ + + ccm::reader::options rOpts; + rOpts.removeBaffles(args.optionFound("noBaffles")); + rOpts.mergeInterfaces(args.optionFound("merge")); + + if (args.optionFound("numbered")) + { + rOpts.useNumberedNames(true); + } + else if (args.optionFound("combine")) + { + rOpts.combineBoundaries(true); + } + + if (args.optionFound("solids")) + { + Info<< "treating solids like fluids" << endl; + rOpts.keepSolid(true); + } + else + { + rOpts.keepSolid(false); + } + + // CCM reader for reading geometry/solution + ccm::reader reader(args[1], rOpts); + + // list the geometry information + if (optList) + { + Info<< "mesh geometry information:" << endl; + if (reader.hasGeometry()) + { + Info<< nl << "cellTable:" << reader.cellTableInfo() + << nl << "boundaryRegion:" << reader.boundaryTableInfo() + << nl << "interfaces:" << reader.interfaceDefinitionsInfo() + << endl; + + if + ( + args.optionFound("remap") + ? reader.remapMeshInfo(runTime, args["remap"]) + : reader.remapMeshInfo(runTime) + ) + { + Info<< nl + << "Remapped cellTable:" << reader.cellTableInfo() << nl + << "Remapped boundaryRegion:" << reader.boundaryTableInfo() + << endl; + } + } + else + { + Info<< "NONE" << endl; + } + + return 0; + } + else if (reader.readGeometry(scaleFactor)) + { + autoPtr<polyMesh> mesh = + ( + args.optionFound("remap") + ? reader.mesh(runTime, args["remap"]) + : reader.mesh(runTime) + ); + + // report mesh bounding box information + Info<< nl << "Bounding box size: " << mesh().bounds().span() << nl; + + // check number of regions + regionSplit rs(mesh); + + Info<< "Number of regions: " << rs.nRegions(); + if (rs.nRegions() == 1) + { + Info<< " (OK)." << nl; + } + else + { + Info<< nl << nl + << "**************************************************" << nl + << "** WARNING: the mesh has disconnected regions **" << nl + << "**************************************************" << nl; + } + Info<< endl; + reader.writeMesh(mesh, format); + + // exportName only has a size when export is in effect + if (exportName.size()) + { + const fileName geomName = exportName + ".ccmg"; + Info<< nl << "Re-exporting geometry as " << geomName << nl; + ccm::writer(geomName, mesh).writeGeometry(); + } + } + else + { + FatalErrorIn("ccmToFoam") + << "could not read geometry" + << exit(FatalError); + } + + Info<< "\nEnd\n" << endl; + + return 0; +} + +// ************************************************************************* // diff --git a/applications/utilities/mesh/conversion/ccm/foamToCcm/Make/files b/applications/utilities/mesh/conversion/ccm/foamToCcm/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..dd5d32f698998c0c1b955605c15096a6deb47c1b --- /dev/null +++ b/applications/utilities/mesh/conversion/ccm/foamToCcm/Make/files @@ -0,0 +1,3 @@ +foamToCcm.C + +EXE = $(FOAM_APPBIN)/foamToCcm diff --git a/applications/utilities/mesh/conversion/ccm/foamToCcm/Make/options b/applications/utilities/mesh/conversion/ccm/foamToCcm/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..df1a41bde0ac5a0fa70a0ee9372ab01cdd4c9b9d --- /dev/null +++ b/applications/utilities/mesh/conversion/ccm/foamToCcm/Make/options @@ -0,0 +1,10 @@ +EXE_INC = \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/conversion/lnInclude \ + -I$(LIB_SRC)/conversion/ccm/lnInclude \ + -I$(LIB_SRC)/fileFormats/lnInclude + +EXE_LIBS = \ + -lfiniteVolume \ + -lgenericPatchFields \ + -lconversion -lccm diff --git a/applications/utilities/mesh/conversion/ccm/foamToCcm/foamToCcm.C b/applications/utilities/mesh/conversion/ccm/foamToCcm/foamToCcm.C new file mode 100644 index 0000000000000000000000000000000000000000..9d64cc09b063abf3e6fb862e797fff8d021402a6 --- /dev/null +++ b/applications/utilities/mesh/conversion/ccm/foamToCcm/foamToCcm.C @@ -0,0 +1,272 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Application + foamToCcm + +Group + grpMeshConversionUtilities + +Description + Translates OPENFOAM mesh and/or results to CCM format + +Usage + \b foamToCcm [OPTION] + + Options: + - \par -mesh + convert mesh only to CCM format + + - \par -name \<name\> + Provide alternative base name. Default is <tt>meshExport</tt>. + + - \par -overwrite + No backup of existing output files. + + - \par -remap \<name\> + use specified remapping dictionary instead of <tt>constant/remapping</tt> + + - \par -results + convert results only to CCM format + +Note + - No parallel data + - No Lagrangian elements + - the -noZero time option can be useful to avoid the often incomplete + initial conditions (missing useful calculated values) + +See also + Foam::ccm::writer for information about the + <tt>constant/remapping</tt> file. + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "timeSelector.H" + +#include "volFields.H" +#include "OFstream.H" +#include "IOobjectList.H" +#include "scalarIOField.H" +#include "tensorIOField.H" + +#include "ccm.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Main program: + +int main(int argc, char *argv[]) +{ + argList::addNote + ( + "Translate OPENFOAM data to CCM format" + ); + + Foam::timeSelector::addOptions(); + argList::noParallel(); + argList::addBoolOption + ( + "mesh", + "convert mesh only" + ); + argList::addOption + ( + "name", + "name", + "provide alternative base name. Default is <meshExport>." + ); + argList::addBoolOption + ( + "overwrite", + "no backup of existing output files" + ); + argList::addOption + ( + "remap", + "name", + "use specified remapping dictionary instead of <constant/remapping>" + ); + argList::addBoolOption + ( + "results", + "convert results only" + ); + + #include "setRootCase.H" + #include "createTime.H" + runTime.functionObjects().off(); + + // get times list + instantList timeDirs = Foam::timeSelector::select0(runTime, args); + + const bool optMesh = args.optionFound("mesh"); + const bool optResults = args.optionFound("results"); + const bool optOverwrite = args.optionFound("overwrite"); + + fileName exportName = ccm::writer::defaultMeshName; + if (args.optionReadIfPresent("name", exportName)) + { + const word ext = exportName.ext(); + // strip erroneous extension (.ccm, .ccmg, .ccmp) + if (ext == "ccm" || ext == "ccmg" || ext == "ccmp") + { + exportName = exportName.lessExt(); + } + } + else if (args.optionFound("case")) + { + exportName += '-' + args.globalCaseName(); + } + + if (optMesh && optResults) + { + Warning + << "\n-mesh and -results options are mutually exclusive\n" + << endl; + args.printUsage(); + FatalError.exit(); + } + +// // skip over time=0, unless some other time option has been specified +// if +// ( +// !args.optionFound("zeroTime") +// && !args.optionFound("time") +// && !args.optionFound("latestTime") +// && Times.size() > 2 +// ) +// { +// startTime = 2; +// } +// +// runTime.setTime(Times[startTime], startTime); + + runTime.setTime(timeDirs[0], 0); + if (optMesh) + { + // convert mesh only + #include "createPolyMesh.H" + + forAll(timeDirs, timeI) + { + runTime.setTime(timeDirs[timeI], timeI); + + #include "getTimeIndex.H" + + if (timeI == 0) + { + ccm::writer writer + ( + exportName + ".ccmg", + mesh, + !optOverwrite + ); + writer.writeGeometry(); + } + else if (mesh.moving()) + { + ccm::writer writer + ( + exportName + ".ccmg_" + timeName, + mesh, + !optOverwrite + ); + writer.writeGeometry(); + } + } + } + else + { + // convert fields with or without converting mesh + #include "createMesh.H" + + // #include "checkHasMovingMesh.H" + // #include "checkHasLagrangian.H" + + IOobjectList objects(mesh, timeDirs[timeDirs.size()-1].name()); + // IOobjectList sprayObjects(mesh, Times[Times.size()-1].name(), "lagrangian"); + + forAll(timeDirs, timeI) + { + runTime.setTime(timeDirs[timeI], timeI); + + #include "getTimeIndex.H" + + Info<< "has " + << mesh.nCells() << " cells, " + << mesh.nPoints() << " points, " + << mesh.boundaryMesh().size() << " patches" + << endl; + + if (!optResults) + { + if (timeI == 0) + { + ccm::writer writer + ( + exportName + ".ccmg", + mesh, + !optOverwrite + ); + writer.writeGeometry(); + } + else if (mesh.moving()) + { + ccm::writer writer + ( + exportName + ".ccmg_" + timeName, + mesh, + !optOverwrite + ); + writer.writeGeometry(); + } + } + + ccm::writer writer + ( + exportName + ".ccmp_" + timeName, + mesh, + !optOverwrite + ); + // writer.setTopologyFile(exportName + ".ccmg"); + Info<< "writing solution:"; + if (args.optionFound("remap")) + { + writer.writeSolution(objects, args["remap"]); + } + else + { + writer.writeSolution(objects); + } + } + } + + Info<< "\nEnd\n" << endl; + return 0; +} + + +// ************************************************************************* // diff --git a/applications/utilities/mesh/conversion/ccm/foamToCcm/getTimeIndex.H b/applications/utilities/mesh/conversion/ccm/foamToCcm/getTimeIndex.H new file mode 100644 index 0000000000000000000000000000000000000000..4547e06457e9faf3f96bc5c0fc35bc28cdd7d1dc --- /dev/null +++ b/applications/utilities/mesh/conversion/ccm/foamToCcm/getTimeIndex.H @@ -0,0 +1,49 @@ +// 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.typeHeaderOk<IOdictionary>(true)) + { + IOdictionary timeObject + ( + IOobject + ( + "time", + runTime.timeName(), + "uniform", + runTime, + IOobject::MUST_READ, + IOobject::NO_WRITE, + false + ) + ); + + label index; + timeObject.lookup("index") >> index; + timeName = Foam::name(index); + } + else + { + timeName = runTime.timeName(); + } + } + + Info<< "\nTime [" << timeName << "] = " << runTime.timeName() << nl; + diff --git a/applications/utilities/mesh/conversion/fireToFoam/Make/files b/applications/utilities/mesh/conversion/fireToFoam/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..a8734855d05090b2b37c953497224a46ac205a5e --- /dev/null +++ b/applications/utilities/mesh/conversion/fireToFoam/Make/files @@ -0,0 +1,3 @@ +fireToFoam.C + +EXE = $(FOAM_APPBIN)/fireToFoam diff --git a/applications/utilities/mesh/conversion/fireToFoam/Make/options b/applications/utilities/mesh/conversion/fireToFoam/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..e3af2fe661b0e1a9cc1f77fbe4b08a9923d2bd35 --- /dev/null +++ b/applications/utilities/mesh/conversion/fireToFoam/Make/options @@ -0,0 +1,7 @@ +EXE_INC = \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/conversion/lnInclude \ + -I$(LIB_SRC)/fileFormats/lnInclude + +EXE_LIBS = \ + -lconversion diff --git a/applications/utilities/mesh/conversion/fireToFoam/fireToFoam.C b/applications/utilities/mesh/conversion/fireToFoam/fireToFoam.C new file mode 100644 index 0000000000000000000000000000000000000000..0f7c32c701dea259c602298d4dc933c4c0eef449 --- /dev/null +++ b/applications/utilities/mesh/conversion/fireToFoam/fireToFoam.C @@ -0,0 +1,123 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Application + fireToFoam + +Group + grpMeshConversionUtilities + +Description + Converts an AVL/FIRE polyhedral mesh to OPENFOAM + +Usage + \b fireToFoam [OPTION] firePolyMesh + + Options: + + - \param -ascii + Write in ASCII format instead of binary + + - \par -check + Perform edge checking + + - \par -scale \<factor\> + Specify an alternative geometry scaling factor. + The default is \b 1 (no scaling). + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "Time.H" +#include "FIREMeshReader.H" +#include "checkFireEdges.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char *argv[]) +{ + argList::addNote + ( + "Convert AVL/FIRE polyhedral mesh to OPENFOAM format" + ); + + argList::noParallel(); + argList::validArgs.append("firePolyMesh"); + argList::addBoolOption + ( + "ascii", + "write in ASCII format instead of binary" + ); + argList::addBoolOption + ( + "check", + "perform edge checking as well" + ); + argList::addOption + ( + "scale", + "scale", + "geometry scaling factor - default is 1 (no scaling)" + ); + + + argList args(argc, argv); + Time runTime(args.rootPath(), args.caseName()); + + + // Binary output, unless otherwise specified + const IOstream::streamFormat format = + ( + args.optionFound("ascii") + ? IOstream::ASCII + : IOstream::BINARY + ); + + // increase the precision of the points data + IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision())); + + + fileFormats::FIREMeshReader reader + ( + args[1], + // Default no scaling + args.optionLookupOrDefault("scale", 1.0) + ); + + + autoPtr<polyMesh> mesh = reader.mesh(runTime); + reader.writeMesh(mesh(), format); + + + if (args.optionFound("check")) + { + checkFireEdges(mesh()); + } + + Info<< "\nEnd\n" << endl; + return 0; +} + +// ************************************************************************* // diff --git a/applications/utilities/mesh/conversion/foamToFireMesh/Make/files b/applications/utilities/mesh/conversion/foamToFireMesh/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..0cc67f4f557a5542705ef177178f54e44518a35e --- /dev/null +++ b/applications/utilities/mesh/conversion/foamToFireMesh/Make/files @@ -0,0 +1,3 @@ +foamToFireMesh.C + +EXE = $(FOAM_APPBIN)/foamToFireMesh diff --git a/applications/utilities/mesh/conversion/foamToFireMesh/Make/options b/applications/utilities/mesh/conversion/foamToFireMesh/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..e3af2fe661b0e1a9cc1f77fbe4b08a9923d2bd35 --- /dev/null +++ b/applications/utilities/mesh/conversion/foamToFireMesh/Make/options @@ -0,0 +1,7 @@ +EXE_INC = \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/conversion/lnInclude \ + -I$(LIB_SRC)/fileFormats/lnInclude + +EXE_LIBS = \ + -lconversion diff --git a/applications/utilities/mesh/conversion/foamToFireMesh/foamToFireMesh.C b/applications/utilities/mesh/conversion/foamToFireMesh/foamToFireMesh.C new file mode 100644 index 0000000000000000000000000000000000000000..87ddd4dff938fdef1f9d626dbd180d92978db89d --- /dev/null +++ b/applications/utilities/mesh/conversion/foamToFireMesh/foamToFireMesh.C @@ -0,0 +1,136 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Application + foamToFireMesh + +Description + Reads an OpenFOAM mesh and writes an AVL/FIRE fpma format + +Usage + \b foamToFireMesh [OPTION] + + Options: + - \par -ascii + Write in ASCII format instead of binary + + - \par -scale \<factor\> + Specify an alternative geometry scaling factor. + The default is \b 1 (ie, no scaling). + +See also + Foam::cellTable, Foam::meshWriter and Foam::fileFormats::FIREMeshWriter + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "timeSelector.H" +#include "Time.H" +#include "polyMesh.H" +#include "FIREMeshWriter.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + argList::addNote + ( + "read OpenFOAM mesh and write an AVL/FIRE fpma format" + ); + argList::noParallel(); + timeSelector::addOptions(); + + argList::addBoolOption + ( + "ascii", + "write in ASCII format instead of binary" + ); + argList::addOption + ( + "scale", + "factor", + "geometry scaling factor - default is 1 (none)" + ); + + #include "setRootCase.H" + #include "createTime.H" + + instantList timeDirs = timeSelector::select0(runTime, args); + + fileName exportName = meshWriter::defaultMeshName; + if (args.optionFound("case")) + { + exportName += '-' + args.globalCaseName(); + } + + + // write control options + // ~~~~~~~~~~~~~~~~~~~~~ + fileFormats::FIREMeshWriter::binary = !args.optionFound("ascii"); + + // default: rescale from [m] to [mm] + scalar scaleFactor = 1; + 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) + { + fileFormats::FIREMeshWriter writer(mesh, scaleFactor); + + fileName meshName(exportName); + if (state != polyMesh::UNCHANGED) + { + meshName += '_' + runTime.timeName(); + } + + writer.write(meshName); + } + + Info<< nl << endl; + } + + Info<< "End\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/utilities/mesh/conversion/foamToFireMesh/getTimeIndex.H b/applications/utilities/mesh/conversion/foamToFireMesh/getTimeIndex.H new file mode 100644 index 0000000000000000000000000000000000000000..11b8993f28bd3efd8f8efd44d2880271d3a0419e --- /dev/null +++ b/applications/utilities/mesh/conversion/foamToFireMesh/getTimeIndex.H @@ -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.typeHeaderOk<IOdictionary>(true)) + { + 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; + diff --git a/applications/utilities/mesh/conversion/foamToStarMesh/foamToStarMesh.C b/applications/utilities/mesh/conversion/foamToStarMesh/foamToStarMesh.C index b4692d201ac15c2d2329fe8867de35766d1b7771..f8fe44f19fc05c81ff81eaa76bf2032e73a89d76 100644 --- a/applications/utilities/mesh/conversion/foamToStarMesh/foamToStarMesh.C +++ b/applications/utilities/mesh/conversion/foamToStarMesh/foamToStarMesh.C @@ -94,15 +94,9 @@ int main(int argc, char *argv[]) exportName += '-' + args.globalCaseName(); } - // default: rescale from [m] to [mm] - scalar scaleFactor = 1000; - if (args.optionReadIfPresent("scale", scaleFactor)) - { - if (scaleFactor <= 0) - { - scaleFactor = 1; - } - } + // Default rescale from [m] to [mm] + const scalar scaleFactor = args.optionLookupOrDefault("scale", 1000.0); + const bool writeBndFile = !args.optionFound("noBnd"); #include "createPolyMesh.H" @@ -116,12 +110,12 @@ int main(int argc, char *argv[]) if (!timeI || state != polyMesh::UNCHANGED) { - fileFormats::STARCDMeshWriter writer(mesh, scaleFactor); - - if (args.optionFound("noBnd")) - { - writer.noBoundary(); - } + fileFormats::STARCDMeshWriter writer + ( + mesh, + scaleFactor, + writeBndFile + ); fileName meshName(exportName); if (state != polyMesh::UNCHANGED) diff --git a/applications/utilities/mesh/conversion/star4ToFoam/star4ToFoam.C b/applications/utilities/mesh/conversion/star4ToFoam/star4ToFoam.C index af57977d788beb9b155e978a82be2f61d8cb11c0..65261399d076de189a31b6c7fbb206ac1a6f36ca 100644 --- a/applications/utilities/mesh/conversion/star4ToFoam/star4ToFoam.C +++ b/applications/utilities/mesh/conversion/star4ToFoam/star4ToFoam.C @@ -48,7 +48,7 @@ Usage Note Baffles are written as interfaces for later use -See Also +See also Foam::cellTable, Foam::meshReader and Foam::fileFormats::STARCDMeshReader \*---------------------------------------------------------------------------*/ @@ -88,32 +88,35 @@ int main(int argc, char *argv[]) "retain solid cells and treat them like fluid cells" ); + argList args(argc, argv); Time runTime(args.rootPath(), args.caseName()); - // default rescale from [mm] to [m] - scalar scaleFactor = args.optionLookupOrDefault("scale", 0.001); - if (scaleFactor <= 0) - { - scaleFactor = 1; - } - - fileFormats::STARCDMeshReader::keepSolids = args.optionFound("solids"); - - // default to binary output, unless otherwise specified - IOstream::streamFormat format = IOstream::BINARY; - if (args.optionFound("ascii")) - { - format = IOstream::ASCII; - } + // Binary output, unless otherwise specified + const IOstream::streamFormat format = + ( + args.optionFound("ascii") + ? IOstream::ASCII + : IOstream::BINARY + ); - // increase the precision of the points data + // Increase the precision of the points data IOstream::defaultPrecision(max(10u, IOstream::defaultPrecision())); - // remove extensions and/or trailing '.' + + // Remove extensions and/or trailing '.' const fileName prefix = fileName(args[1]).lessExt(); - fileFormats::STARCDMeshReader reader(prefix, runTime, scaleFactor); + + fileFormats::STARCDMeshReader reader + ( + prefix, + runTime, + // Default rescale from [mm] to [m] + args.optionLookupOrDefault("scale", 0.001), + args.optionFound("solids") + ); + autoPtr<polyMesh> mesh = reader.mesh(runTime); reader.writeMesh(mesh, format); diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/files b/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/files index 044aa6ae43a0911e12dbc805adeeb202ad3ad864..a474a8fcfc5ca8a0593a612b2f5aceb2246ead9b 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/files +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/Make/files @@ -1,6 +1,4 @@ ensightOutputCloud.C -meshSubsetHelper.C - foamToEnsight.C EXE = $(FOAM_APPBIN)/foamToEnsight diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C b/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C index 1d0f6c3beb3d0e08ec4318c1af86605ad96ee29b..5080d840ebc1e3da0ab29f58a411f2c9a43da133 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C +++ b/applications/utilities/postProcessing/dataConversion/foamToEnsight/foamToEnsight.C @@ -291,7 +291,7 @@ int main(int argc, char *argv[]) << mesh.boundaryMesh()[0].name() << ")" << endl; } - meshSubsetHelper myMesh(mesh, cellZoneName); + meshSubsetHelper myMesh(mesh, meshSubsetHelper::ZONE, cellZoneName); // // Open new ensight case file, initialize header etc. diff --git a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/Make/files b/applications/utilities/postProcessing/dataConversion/foamToTecplot360/Make/files index 270e84931b599af46bf3a9db82024e3202dd5006..3eb58f17730826790e60e9c50a6ecc12f9c81c13 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/Make/files +++ b/applications/utilities/postProcessing/dataConversion/foamToTecplot360/Make/files @@ -1,5 +1,4 @@ tecplotWriter.C -vtkMesh.C foamToTecplot360.C EXE = $(FOAM_APPBIN)/foamToTecplot360 diff --git a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/foamToTecplot360.C b/applications/utilities/postProcessing/dataConversion/foamToTecplot360/foamToTecplot360.C index 6ec9aff2772060d06ea92c5c07e8859aa08428d1..5dbe1581cad2d7edc6860575c82858169bfbf7c6 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/foamToTecplot360.C +++ b/applications/utilities/postProcessing/dataConversion/foamToTecplot360/foamToTecplot360.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -68,9 +68,6 @@ Usage information as a single argument. The double quotes denote a regular expression. - - \par -useTimeName - use the time index in the VTK file name instead of the time index - \*---------------------------------------------------------------------------*/ #include "pointMesh.H" @@ -86,7 +83,7 @@ Usage #include "stringListOps.H" #include "wordRe.H" -#include "vtkMesh.H" +#include "meshSubsetHelper.H" #include "readFields.H" #include "tecplotWriter.H" @@ -99,7 +96,7 @@ Usage // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // template<class GeoField> -void print(const char* msg, Ostream& os, const PtrList<GeoField>& flds) +void print(const char* msg, Ostream& os, const PtrList<const GeoField>& flds) { if (flds.size()) { @@ -140,7 +137,7 @@ labelList getSelectedPatches if ( isType<emptyPolyPatch>(pp) - || (Pstream::parRun() && isType<processorPolyPatch>(pp)) + || (Pstream::parRun() && isType<processorPolyPatch>(pp)) ) { Info<< " discarding empty/processor patch " << patchi @@ -161,8 +158,7 @@ labelList getSelectedPatches } - - +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // int main(int argc, char *argv[]) { @@ -170,10 +166,8 @@ int main(int argc, char *argv[]) ( "Tecplot binary file format writer" ); - timeSelector::addOptions(); #include "addRegionOption.H" - argList::addOption ( "fields", @@ -190,7 +184,7 @@ int main(int argc, char *argv[]) ( "faceSet", "name", - "restrict conversion to the specified cellSet" + "restrict conversion to the specified faceSet" ); argList::addBoolOption ( @@ -248,7 +242,8 @@ int main(int argc, char *argv[]) } word cellSetName; - string vtkName; + word faceSetName; + string vtkName = runTime.caseName(); if (args.optionReadIfPresent("cellSet", cellSetName)) { @@ -266,11 +261,7 @@ int main(int argc, char *argv[]) vtkName = vtkName.substr(i); } } - else - { - vtkName = runTime.caseName(); - } - + args.optionReadIfPresent("faceSet", faceSetName); instantList timeDirs = timeSelector::select0(runTime, args); @@ -294,10 +285,11 @@ int main(int argc, char *argv[]) args.optionFound("time") || args.optionFound("latestTime") || cellSetName.size() + || faceSetName.size() || regionName != polyMesh::defaultRegion ) { - Info<< "Keeping old files in " << fvPath << nl << endl; + Info<< "Keeping old tecplot files in " << fvPath << nl << endl; } else { @@ -309,9 +301,8 @@ int main(int argc, char *argv[]) mkDir(fvPath); - - // mesh wrapper; does subsetting and decomposition - vtkMesh vMesh(mesh, cellSetName); + // Mesh wrapper: does subsetting + meshSubsetHelper myMesh(mesh, meshSubsetHelper::SET, cellSetName); forAll(timeDirs, timeI) { @@ -319,13 +310,12 @@ int main(int argc, char *argv[]) Info<< "Time: " << runTime.timeName() << endl; - const word timeDesc = name(timeI); //name(runTime.timeIndex()); + const word timeDesc = name(timeI); // Foam::name(runTime.timeIndex()); // Check for new polyMesh/ and update mesh, fvMeshSubset and cell // decomposition. - polyMesh::readUpdateState meshState = vMesh.readUpdate(); - - const fvMesh& mesh = vMesh.mesh(); + polyMesh::readUpdateState meshState = myMesh.readUpdate(); + const fvMesh& mesh = myMesh.mesh(); INTEGER4 nFaceNodes = 0; forAll(mesh.faces(), facei) @@ -348,24 +338,24 @@ int main(int argc, char *argv[]) // Construct the vol fields (on the original mesh if subsetted) - PtrList<volScalarField> vsf; - readFields(vMesh, vMesh.baseMesh(), objects, selectedFields, vsf); + PtrList<const volScalarField> vsf; + readFields(myMesh, myMesh.baseMesh(), objects, selectedFields, vsf); print(" volScalarFields :", Info, vsf); - PtrList<volVectorField> vvf; - readFields(vMesh, vMesh.baseMesh(), objects, selectedFields, vvf); + PtrList<const volVectorField> vvf; + readFields(myMesh, myMesh.baseMesh(), objects, selectedFields, vvf); print(" volVectorFields :", Info, vvf); - PtrList<volSphericalTensorField> vSpheretf; - readFields(vMesh, vMesh.baseMesh(), objects, selectedFields, vSpheretf); + PtrList<const volSphericalTensorField> vSpheretf; + readFields(myMesh, myMesh.baseMesh(), objects, selectedFields, vSpheretf); print(" volSphericalTensorFields :", Info, vSpheretf); - PtrList<volSymmTensorField> vSymmtf; - readFields(vMesh, vMesh.baseMesh(), objects, selectedFields, vSymmtf); + PtrList<const volSymmTensorField> vSymmtf; + readFields(myMesh, myMesh.baseMesh(), objects, selectedFields, vSymmtf); print(" volSymmTensorFields :", Info, vSymmtf); - PtrList<volTensorField> vtf; - readFields(vMesh, vMesh.baseMesh(), objects, selectedFields, vtf); + PtrList<const volTensorField> vtf; + readFields(myMesh, myMesh.baseMesh(), objects, selectedFields, vtf); print(" volTensorFields :", Info, vtf); @@ -379,11 +369,11 @@ int main(int argc, char *argv[]) << " (\"-noPointValues\" (at your option)\n"; } - PtrList<pointScalarField> psf; - PtrList<pointVectorField> pvf; - //PtrList<pointSphericalTensorField> pSpheretf; - //PtrList<pointSymmTensorField> pSymmtf; - //PtrList<pointTensorField> ptf; + PtrList<const pointScalarField> psf; + PtrList<const pointVectorField> pvf; + //PtrList<const pointSphericalTensorField> pSpheretf; + //PtrList<const pointSymmTensorField> pSymmtf; + //PtrList<const pointTensorField> ptf; if (!noPointValues) @@ -418,8 +408,8 @@ int main(int argc, char *argv[]) readFields ( - vMesh, - pointMesh::New(vMesh.baseMesh()), + myMesh, + pointMesh::New(myMesh.baseMesh()), objects, selectedFields, psf @@ -428,8 +418,8 @@ int main(int argc, char *argv[]) readFields ( - vMesh, - pointMesh::New(vMesh.baseMesh()), + myMesh, + pointMesh::New(myMesh.baseMesh()), objects, selectedFields, pvf @@ -438,8 +428,8 @@ int main(int argc, char *argv[]) //readFields //( - // vMesh, - // pointMesh::New(vMesh.baseMesh()), + // myMesh, + // pointMesh::New(myMesh.baseMesh()), // objects, // selectedFields, // pSpheretf @@ -448,8 +438,8 @@ int main(int argc, char *argv[]) // //readFields //( - // vMesh, - // pointMesh::New(vMesh.baseMesh()), + // myMesh, + // pointMesh::New(myMesh.baseMesh()), // objects, // selectedFields, // pSymmtf @@ -458,8 +448,8 @@ int main(int argc, char *argv[]) // //readFields //( - // vMesh, - // pointMesh::New(vMesh.baseMesh()), + // myMesh, + // pointMesh::New(myMesh.baseMesh()), // objects, // selectedFields, // ptf @@ -769,11 +759,10 @@ int main(int argc, char *argv[]) // //--------------------------------------------------------------------- - if (args.optionFound("faceSet")) + if (faceSetName.size()) { // Load the faceSet - const word setName = args["faceSet"]; - labelList faceLabels(faceSet(mesh, setName).toc()); + labelList faceLabels(faceSet(mesh, faceSetName).toc()); // Filename as if patch with same name. mkDir(fvPath/setName); @@ -886,7 +875,6 @@ int main(int argc, char *argv[]) } - //--------------------------------------------------------------------- // // Write patches as multi-zone file @@ -901,7 +889,7 @@ int main(int argc, char *argv[]) fileName patchFileName; - if (vMesh.useSubMesh()) + if (myMesh.useSubMesh()) { patchFileName = fvPath/"boundaryMesh"/cellSetName @@ -1072,7 +1060,7 @@ int main(int argc, char *argv[]) fileName patchFileName; - if (vMesh.useSubMesh()) + if (myMesh.useSubMesh()) { patchFileName = fvPath/"faceZoneMesh"/cellSetName diff --git a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/readFields.C b/applications/utilities/postProcessing/dataConversion/foamToTecplot360/readFields.C index c677fe439c7ef0a75b6beb96352a0c67ea42bb15..172a83cf2399cd5f8d4b8678d6e1531fcc16929a 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/readFields.C +++ b/applications/utilities/postProcessing/dataConversion/foamToTecplot360/readFields.C @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -36,37 +36,32 @@ namespace Foam template<class GeoField> void readFields ( - const vtkMesh& vMesh, + const meshSubsetHelper& helper, const typename GeoField::Mesh& mesh, const IOobjectList& objects, const HashSet<word>& selectedFields, - PtrList<GeoField>& fields + PtrList<const GeoField>& fields ) { - // Search list of objects for volScalarFields + // Search list of objects for fields of type GeomField IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName)); - // Construct the vol scalar fields - label nFields = fields.size(); - fields.setSize(nFields + fieldObjects.size()); + // Construct the fields + fields.setSize(fieldObjects.size()); + label nFields = 0; - forAllIter(IOobjectList, fieldObjects, iter) + forAllConstIter(IOobjectList, fieldObjects, iter) { if (selectedFields.empty() || selectedFields.found(iter()->name())) { fields.set ( - nFields, - vMesh.interpolate + nFields++, + helper.interpolate ( - GeoField - ( - *iter(), - mesh - ) - ) + GeoField(*iter(), mesh) + ).ptr() ); - nFields++; } } diff --git a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/readFields.H b/applications/utilities/postProcessing/dataConversion/foamToTecplot360/readFields.H index b25c56755c2f2559bf4076ce57057268cad5b131..510bd11d2536419dea3c29bfce016e2dbd5ddd8e 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/readFields.H +++ b/applications/utilities/postProcessing/dataConversion/foamToTecplot360/readFields.H @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation - \\/ M anipulation | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -34,7 +34,7 @@ SourceFiles #ifndef readFields_H #define readFields_H -#include "fvMesh.H" +#include "meshSubsetHelper.H" #include "PtrList.H" #include "IOobjectList.H" #include "HashSet.H" @@ -48,11 +48,11 @@ namespace Foam template<class GeoField> void readFields ( - const vtkMesh& vMesh, + const meshSubsetHelper&, const typename GeoField::Mesh& mesh, const IOobjectList& objects, const HashSet<word>& selectedFields, - PtrList<GeoField>& fields + PtrList<const GeoField>& fields ); } // End namespace Foam diff --git a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/vtkMesh.H b/applications/utilities/postProcessing/dataConversion/foamToTecplot360/vtkMesh.H deleted file mode 100644 index ec6045b5341b0516fd7742ec5f7a84f215d60f19..0000000000000000000000000000000000000000 --- a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/vtkMesh.H +++ /dev/null @@ -1,178 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | Copyright (C) 2011-2016 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::vtkMesh - -Description - Encapsulation of VTK mesh data. Holds mesh or meshsubset and - polyhedral-cell decomposition on it. - -SourceFiles - vtkMesh.C - -\*---------------------------------------------------------------------------*/ - -#ifndef vtkMesh_H -#define vtkMesh_H - -#include "fvMeshSubset.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -// Forward declaration of classes -class Time; - -/*---------------------------------------------------------------------------*\ - Class vtkMesh Declaration -\*---------------------------------------------------------------------------*/ - -class vtkMesh -{ - // Private data - - //- Reference to mesh - fvMesh& baseMesh_; - - //- Subsetting engine + sub-fvMesh - fvMeshSubset subsetter_; - - //- Current cellSet (or empty) - const word setName_; - -// //- Current decomposition of topology -// mutable autoPtr<vtkTopo> topoPtr_; - - - - // Private Member Functions - - //- Disallow default bitwise copy construct - vtkMesh(const vtkMesh&); - - //- Disallow default bitwise assignment - void operator=(const vtkMesh&); - - -public: - - // Constructors - - //- Construct from components - vtkMesh(fvMesh& baseMesh, const word& setName = ""); - - - // Member Functions - - // Access - - //- Whole mesh - const fvMesh& baseMesh() const - { - return baseMesh_; - } - - const fvMeshSubset& subsetter() const - { - return subsetter_; - } - - //- Check if running subMesh - bool useSubMesh() const - { - return setName_.size(); - } - -// //- topology -// const vtkTopo& topo() const -// { -// if (topoPtr_.empty()) -// { -// topoPtr_.reset(new vtkTopo(mesh())); -// } -// return topoPtr_(); -// } - - //- Access either mesh or submesh - const fvMesh& mesh() const - { - if (useSubMesh()) - { - return subsetter_.subMesh(); - } - else - { - return baseMesh_; - } - } - -// //- Number of field cells -// label nFieldCells() const -// { -// return topo().vertLabels().size(); -// } -// -// //- Number of field points -// label nFieldPoints() const -// { -// return mesh().nPoints() + topo().addPointCellLabels().size(); -// } - - - // Edit - - //- Read mesh - polyMesh::readUpdateState readUpdate(); - - - //- Map volume field (does in fact do very little interpolation; - // just copied from fvMeshSubset) - template<class GeoField> - tmp<GeoField> interpolate(const GeoField& fld) const - { - if (useSubMesh()) - { - tmp<GeoField> subFld = subsetter_.interpolate(fld); - subFld.ref().rename(fld.name()); - return subFld; - } - else - { - return fld; - } - } -}; - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -#endif - -// ************************************************************************* // diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C index 4e42b5afbfaa25c7e4275541de7c96e959aad0f7..c2a6f3b29810977ee869310d9c56f5feb2463420 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C @@ -410,7 +410,6 @@ int main(int argc, char *argv[]) args.optionReadIfPresent("pointSet", pointSetName); - instantList timeDirs = timeSelector::select0(runTime, args); #include "createNamedMesh.H" @@ -450,7 +449,7 @@ int main(int argc, char *argv[]) mkDir(fvPath); - // Mesh wrapper; does subsetting and decomposition + // Mesh wrapper: does subsetting and decomposition vtkMesh vMesh(mesh, cellSetName); Info<< "VTK mesh topology: " @@ -503,7 +502,7 @@ int main(int argc, char *argv[]) Info<< " FaceSet : " << patchFileName << endl; - writeFaceSet(binary, vMesh, set, patchFileName); + writeFaceSet(binary, vMesh.mesh(), set, patchFileName); continue; } @@ -526,7 +525,7 @@ int main(int argc, char *argv[]) Info<< " pointSet : " << patchFileName << endl; - writePointSet(binary, vMesh, set, patchFileName); + writePointSet(binary, vMesh.mesh(), set, patchFileName); continue; } @@ -849,7 +848,7 @@ int main(int argc, char *argv[]) writeSurfFields ( binary, - vMesh, + vMesh.mesh(), surfFileName, svf ); @@ -892,7 +891,7 @@ int main(int argc, char *argv[]) patchWriter writer ( - vMesh, + vMesh.mesh(), binary, nearCellValue, patchFileName, @@ -970,7 +969,7 @@ int main(int argc, char *argv[]) patchWriter writer ( - vMesh, + vMesh.mesh(), binary, nearCellValue, patchFileName, @@ -1188,7 +1187,7 @@ int main(int argc, char *argv[]) lagrangianWriter writer ( - vMesh, + vMesh.mesh(), binary, lagrFileName, cloudName, @@ -1218,7 +1217,7 @@ int main(int argc, char *argv[]) { lagrangianWriter writer ( - vMesh, + vMesh.mesh(), binary, lagrFileName, cloudName, diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/Make/files b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/Make/files index 4deaaa68f07c4ac1117eb8673149c90d195bc8f2..02de5b47e6254aab58ae3557c2f7e2342b7df753 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/Make/files +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/Make/files @@ -6,7 +6,6 @@ writeFuns.C writeFaceSet.C writePointSet.C writeSurfFields.C -vtkMesh.C vtkTopo.C writeVTK/writeVTK.C diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/internalWriter.H b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/internalWriter.H index b61cfd6377aed05e7d85fe681a648c6ef1c63deb..b1836afb60e16c05542594272367a3ea69fdea25 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/internalWriter.H +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/internalWriter.H @@ -41,8 +41,6 @@ SourceFiles #include "pointFields.H" #include "vtkMesh.H" -using namespace Foam; - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/lagrangianWriter.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/lagrangianWriter.C index 6c168a22805b4218ecf89f1366cb15ffb77d3815..6eab8f164666e4767559491354f705df14cc4418 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/lagrangianWriter.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/lagrangianWriter.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -32,23 +32,21 @@ License Foam::lagrangianWriter::lagrangianWriter ( - const vtkMesh& vMesh, + const fvMesh& mesh, const bool binary, const fileName& fName, const word& cloudName, const bool dummyCloud ) : - vMesh_(vMesh), + mesh_(mesh), binary_(binary), fName_(fName), cloudName_(cloudName), os_(fName.c_str()) { - const fvMesh& mesh = vMesh_.mesh(); - // Write header - writeFuns::writeHeader(os_, binary_, mesh.time().caseName()); + writeFuns::writeHeader(os_, binary_, mesh_.time().caseName()); os_ << "DATASET POLYDATA" << std::endl; if (dummyCloud) diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/lagrangianWriter.H b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/lagrangianWriter.H index 113bfe43b0a399554f61dd0d1614491554d91d0a..24dd4a322872c92eb6f2dfa32474c7c676e728d3 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/lagrangianWriter.H +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/lagrangianWriter.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -40,9 +40,6 @@ SourceFiles #include "Cloud.H" #include "volFields.H" #include "pointFields.H" -#include "vtkMesh.H" - -using namespace Foam; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -57,7 +54,7 @@ class volPointInterpolation; class lagrangianWriter { - const vtkMesh& vMesh_; + const fvMesh& mesh_; const bool binary_; @@ -77,7 +74,7 @@ public: //- Construct from components lagrangianWriter ( - const vtkMesh&, + const fvMesh&, const bool binary, const fileName&, const word&, diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/lagrangianWriterTemplates.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/lagrangianWriterTemplates.C index 8d34517dca577652c338114abe8c990fab4816c8..86cec10dc3ee015598988d5ee2b71c5ed036fc0c 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/lagrangianWriterTemplates.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/lagrangianWriterTemplates.C @@ -39,9 +39,9 @@ void Foam::lagrangianWriter::writeIOField(const wordList& objects) IOobject header ( object, - vMesh_.mesh().time().timeName(), + mesh_.time().timeName(), cloud::prefix/cloudName_, - vMesh_.mesh(), + mesh_, IOobject::MUST_READ, IOobject::NO_WRITE, false diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/patchWriter.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/patchWriter.C index 4a9840c1e271d18aa0314b75bf6463cdc388abae..d099745aa259b8f59f9029a52af2b1725a8859c3 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/patchWriter.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/patchWriter.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -30,21 +30,20 @@ License Foam::patchWriter::patchWriter ( - const vtkMesh& vMesh, + const fvMesh& mesh, const bool binary, const bool nearCellValue, const fileName& fName, const labelList& patchIDs ) : - vMesh_(vMesh), + mesh_(mesh), binary_(binary), nearCellValue_(nearCellValue), fName_(fName), patchIDs_(patchIDs), os_(fName.c_str()) { - const fvMesh& mesh = vMesh_.mesh(); const polyBoundaryMesh& patches = mesh.boundaryMesh(); // Write header @@ -115,8 +114,6 @@ Foam::patchWriter::patchWriter void Foam::patchWriter::writePatchIDs() { - const fvMesh& mesh = vMesh_.mesh(); - DynamicList<floatScalar> fField(nFaces_); os_ << "patchID 1 " << nFaces_ << " float" << std::endl; @@ -125,7 +122,7 @@ void Foam::patchWriter::writePatchIDs() { label patchi = patchIDs_[i]; - const polyPatch& pp = mesh.boundaryMesh()[patchi]; + const polyPatch& pp = mesh_.boundaryMesh()[patchi]; if (!isA<emptyPolyPatch>(pp)) { diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/patchWriter.H b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/patchWriter.H index e25bbb1122414163f440f685bc5a6688c92b3cef..aab8075da87052a6ebc22fdc00cbf041e8aede05 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/patchWriter.H +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/patchWriter.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -40,12 +40,9 @@ SourceFiles #include "OFstream.H" #include "volFields.H" #include "pointFields.H" -#include "vtkMesh.H" #include "indirectPrimitivePatch.H" #include "PrimitivePatchInterpolation.H" -using namespace Foam; - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam @@ -59,7 +56,8 @@ class volPointInterpolation; class patchWriter { - const vtkMesh& vMesh_; + //- Reference to the OpenFOAM mesh (or subset) + const fvMesh& mesh_; const bool binary_; @@ -82,7 +80,7 @@ public: //- Construct from components patchWriter ( - const vtkMesh&, + const fvMesh&, const bool binary, const bool nearCellValue, const fileName&, diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/readFields.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/readFields.C index 8d515ab056391eef21df4e8177d942e254eb98a7..172a83cf2399cd5f8d4b8678d6e1531fcc16929a 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/readFields.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/readFields.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -36,37 +36,32 @@ namespace Foam template<class GeoField> void readFields ( - const vtkMesh& vMesh, + const meshSubsetHelper& helper, const typename GeoField::Mesh& mesh, const IOobjectList& objects, const HashSet<word>& selectedFields, PtrList<const GeoField>& fields ) { - // Search list of objects for volScalarFields + // Search list of objects for fields of type GeomField IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName)); - // Construct the vol scalar fields + // Construct the fields fields.setSize(fieldObjects.size()); label nFields = 0; - forAllIter(IOobjectList, fieldObjects, iter) + forAllConstIter(IOobjectList, fieldObjects, iter) { if (selectedFields.empty() || selectedFields.found(iter()->name())) { fields.set ( - nFields, - vMesh.interpolate + nFields++, + helper.interpolate ( - GeoField - ( - *iter(), - mesh - ) + GeoField(*iter(), mesh) ).ptr() ); - nFields++; } } diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/readFields.H b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/readFields.H index 31b7e2632c84a7e493e0f4cd5defd3cf5b0e4c56..510bd11d2536419dea3c29bfce016e2dbd5ddd8e 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/readFields.H +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/readFields.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -34,7 +34,7 @@ SourceFiles #ifndef readFields_H #define readFields_H -#include "fvMesh.H" +#include "meshSubsetHelper.H" #include "PtrList.H" #include "IOobjectList.H" #include "HashSet.H" @@ -48,7 +48,7 @@ namespace Foam template<class GeoField> void readFields ( - const vtkMesh& vMesh, + const meshSubsetHelper&, const typename GeoField::Mesh& mesh, const IOobjectList& objects, const HashSet<word>& selectedFields, diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/surfaceMeshWriter.H b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/surfaceMeshWriter.H index f06da45c3f7f94576fb397e326d3596d60d0b65d..0a5589c26e7edbe6866388d9bb55936b45d02d37 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/surfaceMeshWriter.H +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/surfaceMeshWriter.H @@ -40,11 +40,8 @@ SourceFiles #include "OFstream.H" #include "volFields.H" #include "surfaceFields.H" -#include "vtkMesh.H" #include "indirectPrimitivePatch.H" -using namespace Foam; - // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/surfaceMeshWriterTemplates.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/surfaceMeshWriterTemplates.C index 68fd29d257b538d3b36a789daba2bba931c55d08..92d878f2292b534fe915f2c5e8bae4ed2056fff2 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/surfaceMeshWriterTemplates.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/surfaceMeshWriterTemplates.C @@ -29,7 +29,8 @@ License // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // template<class Type> -Foam::tmp<Field<Type>> Foam::surfaceMeshWriter::getFaceField +Foam::tmp<Foam::Field<Type>> +Foam::surfaceMeshWriter::getFaceField ( const GeometricField<Type, fvsPatchField, surfaceMesh>& sfld ) const diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/vtkMesh.H b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/vtkMesh.H index f536ae04fa2f7e27faa7baf121366ba63e988fc4..f0a80db4ead04f7e4e1c13d77c488225d5acb809 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/vtkMesh.H +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/vtkMesh.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -36,46 +36,35 @@ SourceFiles #ifndef vtkMesh_H #define vtkMesh_H +#include "meshSubsetHelper.H" #include "vtkTopo.H" -#include "fvMeshSubset.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { -// Forward declaration of classes -class Time; - /*---------------------------------------------------------------------------*\ Class vtkMesh Declaration \*---------------------------------------------------------------------------*/ class vtkMesh +: + public meshSubsetHelper { // Private data - //- Reference to mesh - fvMesh& baseMesh_; - - //- Subsetting engine + sub-fvMesh - fvMeshSubset subsetter_; - - //- Current cellSet (or empty) - const word setName_; - //- Current decomposition of topology mutable autoPtr<vtkTopo> topoPtr_; - // Private Member Functions //- Disallow default bitwise copy construct - vtkMesh(const vtkMesh&); + vtkMesh(const vtkMesh&) = delete; //- Disallow default bitwise assignment - void operator=(const vtkMesh&); + void operator=(const vtkMesh&) = delete; public: @@ -83,31 +72,17 @@ public: // Constructors //- Construct from components - vtkMesh(fvMesh& baseMesh, const word& setName = ""); + vtkMesh(fvMesh& baseMesh, const word& setName = word::null) + : + meshSubsetHelper(baseMesh, meshSubsetHelper::SET, setName) + {} // Member Functions // Access - //- Whole mesh - const fvMesh& baseMesh() const - { - return baseMesh_; - } - - const fvMeshSubset& subsetter() const - { - return subsetter_; - } - - //- Check if running subMesh - bool useSubMesh() const - { - return setName_.size(); - } - - //- topology + //- Topology const vtkTopo& topo() const { if (topoPtr_.empty()) @@ -117,18 +92,6 @@ public: return topoPtr_(); } - //- Access either mesh or submesh - const fvMesh& mesh() const - { - if (useSubMesh()) - { - return subsetter_.subMesh(); - } - else - { - return baseMesh_; - } - } //- Number of field cells label nFieldCells() const @@ -136,6 +99,7 @@ public: return topo().cellTypes().size(); } + //- Number of field points label nFieldPoints() const { @@ -145,26 +109,20 @@ public: // Edit - //- Read mesh - polyMesh::readUpdateState readUpdate(); - - - //- Map volume field (does in fact do very little interpolation; - // just copied from fvMeshSubset) - template<class GeoField> - tmp<GeoField> interpolate(const GeoField& fld) const + //- Read mesh, forcing topo update if necessary + polyMesh::readUpdateState readUpdate() { - if (useSubMesh()) - { - tmp<GeoField> subFld = subsetter_.interpolate(fld); - subFld.ref().rename(fld.name()); - return subFld; - } - else + polyMesh::readUpdateState meshState + = meshSubsetHelper::readUpdate(); + + if (meshState != polyMesh::UNCHANGED) { - return fld; + topoPtr_.clear(); } + + return meshState; } + }; diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeFaceSet.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeFaceSet.C index 4ad78d96a0d7075f16dc73444283fd98729ed4bc..0556b7aaf27e0022b82cbb587dea9f818f9409e3 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeFaceSet.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeFaceSet.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -32,12 +32,12 @@ License void Foam::writeFaceSet ( const bool binary, - const vtkMesh& vMesh, + const fvMesh& mesh, const faceSet& set, const fileName& fileName ) { - const faceList& faces = vMesh.mesh().faces(); + const faceList& faces = mesh.faces(); std::ofstream ostr(fileName.c_str()); @@ -69,7 +69,7 @@ void Foam::writeFaceSet setFaces[setFacei] = faces[iter.key()]; setFacei++; } - primitiveFacePatch fp(setFaces, vMesh.mesh().points()); + primitiveFacePatch fp(setFaces, mesh.points()); // Write points and faces as polygons diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeFaceSet.H b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeFaceSet.H index eb7c45203169a0a46c43fcd713c5e0cb4609effe..73ca4f07416e6fc9fdfff79350a6ddefdd876160 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeFaceSet.H +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeFaceSet.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -36,7 +36,7 @@ SourceFiles #ifndef writeFaceSet_H #define writeFaceSet_H -#include "vtkMesh.H" +#include "fvMesh.H" #include "faceSet.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -48,7 +48,7 @@ namespace Foam void writeFaceSet ( const bool binary, - const vtkMesh& vMesh, + const fvMesh&, const faceSet& set, const fileName& fileName ); diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writePointSet.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writePointSet.C index 4cafa01f0a0879ad1e40b5d3039042b18bc37f7d..e5fffb536671144a864004b16ee89eac11416612 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writePointSet.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writePointSet.C @@ -37,7 +37,7 @@ namespace Foam void writePointSet ( const bool binary, - const vtkMesh& vMesh, + const fvMesh& mesh, const pointSet& set, const fileName& fileName ) @@ -68,7 +68,7 @@ void writePointSet writeFuns::insert ( - UIndirectList<point>(vMesh.mesh().points(), set.toc())(), + UIndirectList<point>(mesh.points(), set.toc())(), ptField ); diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writePointSet.H b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writePointSet.H index 32ffd981f6bedc4a3c5b14a92d1986528249a664..d1ad15efe6d7b7b95946f479e695765eebb3aea8 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writePointSet.H +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writePointSet.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -36,7 +36,7 @@ SourceFiles #ifndef writePointSet_H #define writePointSet_H -#include "vtkMesh.H" +#include "fvMesh.H" #include "pointSet.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -48,7 +48,7 @@ namespace Foam void writePointSet ( const bool binary, - const vtkMesh& vMesh, + const fvMesh& mesh, const pointSet& set, const fileName& fileName ); diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeSurfFields.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeSurfFields.C index 4144a579a5497701b36afd23752a98fca3d65e99..9dc889adf4be77423e75cb965625c3cc7b52c590 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeSurfFields.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeSurfFields.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -35,13 +35,11 @@ License void Foam::writeSurfFields ( const bool binary, - const vtkMesh& vMesh, + const fvMesh& mesh, const fileName& fileName, const UPtrList<const surfaceVectorField>& surfVectorFields ) { - const fvMesh& mesh = vMesh.mesh(); - std::ofstream str(fileName.c_str()); writeFuns::writeHeader diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeSurfFields.H b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeSurfFields.H index 798e335fd343cf180e7f579919cf44fa58630718..7740e15f78f48c3817ebfca37e8ab65b17eb3f44 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeSurfFields.H +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/writeSurfFields.H @@ -35,7 +35,7 @@ SourceFiles #ifndef writeSurfFields_H #define writeSurfFields_H -#include "vtkMesh.H" +#include "fvMesh.H" #include "surfaceMesh.H" #include "surfaceFieldsFwd.H" @@ -48,7 +48,7 @@ namespace Foam void writeSurfFields ( const bool binary, - const vtkMesh& vMesh, + const fvMesh&, const fileName& fileName, const UPtrList<const surfaceVectorField>& surfVectorFields ); diff --git a/applications/utilities/postProcessing/graphics/PVReaders/PVFoamReader/vtkPVFoam/Make/options b/applications/utilities/postProcessing/graphics/PVReaders/PVFoamReader/vtkPVFoam/Make/options index d0cdd781d764d8d978df42aa7bd999d0ce185106..9f63402d646402607cc5a547da62abbdbfabfd68 100644 --- a/applications/utilities/postProcessing/graphics/PVReaders/PVFoamReader/vtkPVFoam/Make/options +++ b/applications/utilities/postProcessing/graphics/PVReaders/PVFoamReader/vtkPVFoam/Make/options @@ -3,6 +3,8 @@ EXE_INC = \ -I$(LIB_SRC)/finiteVolume/lnInclude \ -I$(LIB_SRC)/dynamicMesh/lnInclude \ -I$(LIB_SRC)/lagrangian/basic/lnInclude \ + -I$(LIB_SRC)/fileFormats/lnInclude \ + -I$(LIB_SRC)/conversion/lnInclude \ -I$(ParaView_INCLUDE_DIR) \ -I$(ParaView_INCLUDE_DIR)/vtkkwiml \ -I../../vtkPVReaders/lnInclude \ @@ -10,7 +12,7 @@ EXE_INC = \ LIB_LIBS = \ -ldynamicMesh \ - -ldynamicMesh \ + -lconversion \ -lgenericPatchFields \ -llagrangian \ -L$(FOAM_LIBBIN) -lvtkPVReaders \ diff --git a/src/conversion/Allwmake b/src/conversion/Allwmake index 4b81d4b8c1ae4055194d3a4cc096607f750683a1..3187320a6796462cce366fa3845a669791b2042c 100755 --- a/src/conversion/Allwmake +++ b/src/conversion/Allwmake @@ -3,8 +3,15 @@ cd ${0%/*} || exit 1 # Run from this directory # Parse arguments for library compilation . $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments + set -x wmake $targetType +ccm/Allwmake || { + echo + echo "WARNING: skipped optional conversion component (build issues detected)" + echo +} + #------------------------------------------------------------------------------ diff --git a/src/conversion/Make/files b/src/conversion/Make/files index 19af831aeb5a682c329d131f838512a8654cbedf..3f2c0a0c98c7e6ccb2679829519124f5f4fadf6b 100644 --- a/src/conversion/Make/files +++ b/src/conversion/Make/files @@ -15,9 +15,16 @@ ensight/part/ensightPartCells.C ensight/part/ensightPartFaces.C ensight/part/ensightParts.C +fire/FIREMeshReader.C +fire/FIREMeshWriter.C +fire/checkFireEdges.C + starcd/STARCDMeshReader.C starcd/STARCDMeshWriter.C polyDualMesh/polyDualMesh.C +vtk/part/foamVtkCells.C +vtk/output/foamVtkOutput.C + LIB = $(FOAM_LIBBIN)/libconversion diff --git a/src/conversion/ccm/Allwmake b/src/conversion/ccm/Allwmake new file mode 100755 index 0000000000000000000000000000000000000000..a3e067e1dc0b9cdef6e24986923e5cdcd85a866a --- /dev/null +++ b/src/conversion/ccm/Allwmake @@ -0,0 +1,28 @@ +#!/bin/sh +# +# Build optional components (eg, may depend on third-party libraries) +#------------------------------------------------------------------------------ +cd ${0%/*} || exit 1 # Run from this directory + +# Parse arguments for compilation (at least for error catching) +. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments + +. $WM_PROJECT_DIR/etc/config.sh/functions +_foamSource $($WM_PROJECT_DIR/bin/foamEtcFile config.sh/ccmio) + +# Link with static libccmio only (possibly fewer issues) +if [ "$WM_LABEL_SIZE" = 64 ] +then + # The libccmio uses int32_t. + # The OpenFOAM adapter thus requires additional work for 64-bit labels. + echo "Skipping optional component libccm" + echo " does not support 64-bit labels" +elif [ -e $CCMIO_ARCH_PATH/include/libccmio/ccmio.h \ + -a -e $CCMIO_ARCH_PATH/lib/libccmio.a ] +then + wmake libso +else + echo "Skipping optional component libccm" +fi + +#------------------------------------------------------------------------------ diff --git a/src/conversion/ccm/Make/files b/src/conversion/ccm/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..89ec20a1db35f1404009aea7b0e367eff3d00a9a --- /dev/null +++ b/src/conversion/ccm/Make/files @@ -0,0 +1,16 @@ +common/ccmBase.C +common/ccmInternal.C + +reader/ccmReader.C +reader/ccmReaderAux.C +reader/ccmReaderMesh.C +reader/ccmReaderSolution.C +reader/ccmReaderOptions.C + +writer/ccmWriter.C +writer/ccmWriterMesh.C +writer/ccmWriterSolution.C + +/* misc/mergePoints1.C */ + +LIB = $(FOAM_LIBBIN)/libccm diff --git a/src/conversion/ccm/Make/options b/src/conversion/ccm/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..ef4b6bb2798726d4b87bff3808ec8807b560a1c0 --- /dev/null +++ b/src/conversion/ccm/Make/options @@ -0,0 +1,14 @@ +EXE_INC = \ + /* -DWITH_MONITORING -DDEBUG_MONITORING */ \ + /* -DDEBUG_BAFFLES */ \ + /* -DDEBUG_CCMIOREAD */ \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/conversion/lnInclude \ + -I$(LIB_SRC)/fileFormats/lnInclude \ + -I$(CCMIO_ARCH_PATH)/include + +LIB_LIBS = \ + -lfiniteVolume \ + -lconversion \ + -L$(CCMIO_ARCH_PATH)/lib -lccmio diff --git a/src/conversion/ccm/common/ccm.H b/src/conversion/ccm/common/ccm.H new file mode 100644 index 0000000000000000000000000000000000000000..639b6127cb87086bc4d522f37acce276739f7b71 --- /dev/null +++ b/src/conversion/ccm/common/ccm.H @@ -0,0 +1,37 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Description + Reader/writer for handling ccm files. + +\*---------------------------------------------------------------------------*/ + +#ifndef ccm_H +#define ccm_H + +#include "ccmReader.H" +#include "ccmWriter.H" + +#endif + +// ************************************************************************* // diff --git a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/vtkMesh.C b/src/conversion/ccm/common/ccmBase.C similarity index 52% rename from applications/utilities/postProcessing/dataConversion/foamToTecplot360/vtkMesh.C rename to src/conversion/ccm/common/ccmBase.C index 0a58e5d523c41724e0c4ca743a5daef9aab2fa4e..14efe10a5e22fb30a3becd0df48ba238eb16eb52 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToTecplot360/vtkMesh.C +++ b/src/conversion/ccm/common/ccmBase.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -21,62 +21,81 @@ License You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. -\*---------------------------------------------------------------------------*/ +\*----------------------------------------------------------------------------*/ -#include "vtkMesh.H" -#include "fvMeshSubset.H" -#include "Time.H" -#include "cellSet.H" +#include "ccmBase.H" +#include "ccmInternal.H" // include last to avoid any strange interactions -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -// Construct from components -Foam::vtkMesh::vtkMesh +// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * // + +bool Foam::ccm::base::assertNoError ( - fvMesh& baseMesh, - const word& setName + int err, + const char* msg ) -: - baseMesh_(baseMesh), - subsetter_(baseMesh), - setName_(setName) { - if (setName.size()) - { - // Read cellSet using whole mesh - cellSet currentSet(baseMesh_, setName_); + return ccmGlobalState::assertNoError(static_cast<CCMIOError>(err), msg); +} - // Set current subset - subsetter_.setLargeCellSubset(currentSet); - } + +bool Foam::ccm::base::assertNoError +( + int err, + const std::string& msg +) +{ + return ccmGlobalState::assertNoError(static_cast<CCMIOError>(err), msg); } -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +bool Foam::ccm::base::assertNoError(const char* msg) const +{ + return globalState_->assertNoError(msg); +} -Foam::polyMesh::readUpdateState Foam::vtkMesh::readUpdate() + +bool Foam::ccm::base::assertNoError(const std::string& msg) const { - polyMesh::readUpdateState meshState = baseMesh_.readUpdate(); + return globalState_->assertNoError(msg); +} - if (meshState != polyMesh::UNCHANGED) - { - // Note: since fvMeshSubset has no movePoints() functionality - // reconstruct the subset even if only movement. -// topoPtr_.clear(); +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::ccm::base::base() +: + globalState_(new ccmGlobalState) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::ccm::base::~base() +{ + close(); +} - if (setName_.size()) - { - Info<< "Subsetting mesh based on cellSet " << setName_ << endl; - // Read cellSet using whole mesh - cellSet currentSet(baseMesh_, setName_); +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - subsetter_.setLargeCellSubset(currentSet); +bool Foam::ccm::base::close() +{ + if (globalState_) + { + if (CCMIOIsValidEntity(globalState_->root)) + { + CCMIOCloseFile(NULL, globalState_->root); } - } + delete globalState_; + globalState_ = 0; - return meshState; + return true; + } + else + { + return false; + } } diff --git a/src/conversion/ccm/common/ccmBase.H b/src/conversion/ccm/common/ccmBase.H new file mode 100644 index 0000000000000000000000000000000000000000..5f789eadd0aaa100ae07ad4952d7ecc19b627aad --- /dev/null +++ b/src/conversion/ccm/common/ccmBase.H @@ -0,0 +1,131 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::ccm::base + +Description + Base functionality common to reader and writer classes + +Note + this class is in development + - any/all of the class names and members may change + +SourceFiles + ccmBase.C + +\*---------------------------------------------------------------------------*/ + +#ifndef ccmBase_H +#define ccmBase_H + +#include <string> + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace ccm +{ + +// * * * * * * * * * * * * * Forward Declarations * * * * * * * * * * * * * // + +class ccmGlobalState; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +/*---------------------------------------------------------------------------*\ + Class ccm::base Declaration +\*---------------------------------------------------------------------------*/ + +class base +{ + // Private Member Functions + + //- Disallow default bitwise copy construct + base(const base&) = delete; + + //- Disallow default bitwise assignment + void operator=(const base&) = delete; + + +protected: + + // Protected Data + + //- Maintain overall global states (error, root-node) + ccmGlobalState* globalState_; + + + // Protected Member Functions + + //- Die with msg if there is an error + // Return true if there is no error + static bool assertNoError(int err, const char *msg); + + //- Die with msg if there is an error + // Return true if there is no error + static bool assertNoError(int err, const std::string& msg); + + + //- check global state for errors and die as required + // Return true if there is no error + bool assertNoError(const char* msg) const; + + //- check global state for errors and die as required + // Return true if there is no error + bool assertNoError(const std::string& msg) const; + + +public: + + // Constructors + + //- Construct null + base(); + + + //- Destructor: close file + ~base(); + + + // Member Functions + + // Access + + //- Explicity close the file and terminate ccmio access. + // Return false if it was already closed. + bool close(); + +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace ccm +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ccm/common/ccmInternal.C b/src/conversion/ccm/common/ccmInternal.C new file mode 100644 index 0000000000000000000000000000000000000000..47dd0c393397577c56db7e2702c663f1b27fcb54 --- /dev/null +++ b/src/conversion/ccm/common/ccmInternal.C @@ -0,0 +1,171 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*----------------------------------------------------------------------------*/ + +#include "Pstream.H" +#include "ccmInternal.H" // include last to avoid any strange interactions + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +defineTypeNameAndDebug(ccm, 0); +} + + +// * * * * * * * * * * * * * * Static Functions * * * * * * * * * * * * * * // + +// \cond file-scope +// Return the string corresponding to the error +static const char* errorMsg(CCMIOError err) +{ + switch (err) + { + case kCCMIONoErr: + return ""; + break; + case kCCMIONoFileErr: + return "No File Error"; + break; + case kCCMIOPermissionErr: + return "Permission Error"; + break; + case kCCMIOCorruptFileErr: + return "Corrupt File Error"; + break; + case kCCMIOBadLinkErr: + return "Bad Link Error"; + break; + case kCCMIONoNodeErr: + return "No Node Error"; + break; + case kCCMIODuplicateNodeErr: + return "Duplicate Node Error"; + break; + case kCCMIOWrongDataTypeErr: + return "Wrong Data Type Error"; + break; + case kCCMIONoDataErr: + return "NoData Error"; + break; + case kCCMIOWrongParentErr: + return "Wrong Parent Error"; + break; + case kCCMIOBadParameterErr: + return "Bad Parameter Error"; + break; + case kCCMIONoMemoryErr: + return "No Memory Error"; + break; + case kCCMIOIOErr: + return "IO Error"; + break; + case kCCMIOTooManyFacesErr: + return "Too Many Faces Error"; + break; + case kCCMIOVersionErr: + return "Version Error"; + break; + case kCCMIOArrayDimensionToLargeErr: + return "Array Dimension To Large Error"; + break; + case kCCMIOInternalErr: + return "Internal Error"; + break; + default: + return "unclassified error"; + break; + } +} +//! \endcond + + +// * * * * * * * * * * * * * * Public Member Functions * * * * * * * * * * * // + +bool Foam::ccm::ccmGlobalState::assertNoError +( + CCMIOError err, + const char* msg +) +{ + if (err != kCCMIONoErr) + { + Perr<< endl + << "--> FATAL ERROR:" + << "\n " << msg + << "\n libccmio reports -> " << errorMsg(err) << " <-\n" + << endl; + + ::exit(1); + } + + return (err == kCCMIONoErr); +} + + +bool Foam::ccm::ccmGlobalState::assertNoError +( + CCMIOError err, + const std::string& msg +) +{ + if (err != kCCMIONoErr) + { + assertNoError(err, msg.c_str()); + } + + return (err == kCCMIONoErr); +} + + +bool Foam::ccm::ccmGlobalState::assertNoError +( + const char* msg +) const +{ + return assertNoError(error, msg); +} + + +bool Foam::ccm::ccmGlobalState::assertNoError +( + const std::string& msg +) const +{ + return assertNoError(error, msg); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::ccm::ccmGlobalState::ccmGlobalState() +: + error(kCCMIONoErr) +{ + CCMIOInvalidateEntity(&root); +} + + +// ************************************************************************* // diff --git a/src/conversion/ccm/common/ccmInternal.H b/src/conversion/ccm/common/ccmInternal.H new file mode 100644 index 0000000000000000000000000000000000000000..f528438dbea01c9f52e950dbba3774ad4b66ccab --- /dev/null +++ b/src/conversion/ccm/common/ccmInternal.H @@ -0,0 +1,170 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Description + Internal bits for wrapping libccmio - do not use directly + +\*---------------------------------------------------------------------------*/ +#ifndef ccmInternal_H +#define ccmInternal_H + +#include "className.H" +#include "List.H" + +// headers and definitions for using libccmio +#include "libccmio/ccmio.h" + +// low-level routines are also needed +#include "libccmio/ccmiocore.h" +#include "libccmio/ccmioutility.h" + +// don't want these defines to leak through +#undef TRUE +#undef FALSE + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// @cond +// internal use only - skip doxygen documentation +namespace Foam +{ +namespace ccm +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//- Declare namespace and debug information. +NamespaceName("ccm"); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +//- A C++ wrapper for the C struct +class ccmID +: + public CCMIOID +{}; + +//- A C++ wrapper for the C struct +class ccmNODE +: + public CCMIONode +{ +public: + + //- Recast constructor + ccmNODE(CCMIONode node) + : + CCMIONode(node) + {} +}; + + +//- A C++ wrapper for the enum +class ccmDimension +{ + CCMIODimensionality dims_; + +public: + + //- Construct from components + ccmDimension(CCMIODimensionality dims) + : + dims_(dims) + {} + + //- Return underlying enum + CCMIODimensionality operator()() const + { + return dims_; + } +}; + + +//- Maintain overall global states (error, rootNode) +class ccmGlobalState +{ +public: + + //- Maintain error state between calls + CCMIOError error; + + //- Root node in the CCM file + ccmID root; + + //- Null constructor. Start with no error, but root in invalid state. + ccmGlobalState(); + + //- True if there is an error + bool hasError() const + { + return (error != kCCMIONoErr); + } + + //- Die with msg if there is an error + // Return true if there is no error + static bool assertNoError(CCMIOError err, const char *msg); + + //- Die with msg if there is an error + // Return true if there is no error + static bool assertNoError(CCMIOError err, const std::string& msg); + + //- Die with msg if there is an error + // Return true if there is no error + bool assertNoError(const char *msg) const; + + //- Die with msg if there is an error + // Return true if there is no error + bool assertNoError(const std::string& msg) const; + +}; + + +//- MapIds for various parts +class ccmMaps +{ +public: + //- The cell map + ccmID cells; + + //- The internalFaces map + ccmID internalFaces; + + //- Boundary region maps + List<ccmID> boundary; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace ccm +} // End namespace Foam + +// @endcond +// internal use only - skip doxygen documentation + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ccm/misc/ListOps1.H b/src/conversion/ccm/misc/ListOps1.H new file mode 100644 index 0000000000000000000000000000000000000000..7e8490240c748b82493c871ad3b625225c118f32 --- /dev/null +++ b/src/conversion/ccm/misc/ListOps1.H @@ -0,0 +1,84 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. +------------------------------------------------------------------------------- +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/>. + +InNamspace + Foam + +Description + Various functions to operate on Lists. + +SourceFiles + ListOps.C + ListOpsTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef ListOps1_H +#define ListOps1_H + +#include "ListOps.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +//- Reorder the elements (indices, not values) of a list. +// Negative ListType elements are untouched, unless pruning has been selected. +// With pruning, these elements are skipped and the list shrinks accordingly. +template<class ListType> +ListType reorder +( + const labelUList& oldToNew, + const ListType&, + const bool prune +); + +//- Inplace reorder the elements of a list. +// Negative ListType elements are untouched, unless pruning has been selected. +// With pruning, these elements are skipped and the list shrinks accordingly. +template<class ListType> +void inplaceReorder +( + const labelUList& oldToNew, + ListType&, + const bool prune +); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "ListOps1Templates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // + diff --git a/src/conversion/ccm/misc/ListOps1Templates.C b/src/conversion/ccm/misc/ListOps1Templates.C new file mode 100644 index 0000000000000000000000000000000000000000..14a9ac38c9284f3e017187a76b188c73d8391d72 --- /dev/null +++ b/src/conversion/ccm/misc/ListOps1Templates.C @@ -0,0 +1,117 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2015-2016 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 "ListOps1.H" + +// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // + +template<class ListType> +ListType Foam::reorder +( + const labelUList& oldToNew, + const ListType& lst, + const bool prune +) +{ + const label sz = lst.size(); + + // Create copy + ListType newLst(sz); + + // Ensure consistent addressable size (eg, DynamicList) + newLst.setSize(sz); + + + label maxIdx = 0; + forAll(lst, elemI) + { + const label newIdx = oldToNew[elemI]; + if (newIdx >= 0) // could also require newIdx < sz + { + newLst[newIdx] = lst[elemI]; + if (prune && maxIdx < newIdx) + { + maxIdx = newIdx; + } + } + else if (!prune) + { + newLst[elemI] = lst[elemI]; + } + } + + if (prune && maxIdx < sz) + { + newLst.setSize(maxIdx); + } + + return newLst; +} + + +template<class ListType> +void Foam::inplaceReorder +( + const labelUList& oldToNew, + ListType& lst, + const bool prune +) +{ + const label sz = lst.size(); + + // Create copy + ListType newLst(sz); + + // Ensure consistent addressable size (eg, DynamicList) + newLst.setSize(sz); + + label maxIdx = 0; + forAll(lst, elemI) + { + const label newIdx = oldToNew[elemI]; + if (newIdx >= 0) // could also require newIdx < sz + { + newLst[newIdx] = lst[elemI]; + if (prune && maxIdx < newIdx) + { + maxIdx = newIdx; + } + } + else if (!prune) + { + newLst[elemI] = lst[elemI]; + } + } + + if (prune && maxIdx < sz) + { + newLst.setSize(maxIdx); + } + + lst.transfer(newLst); +} + + +// ************************************************************************* // diff --git a/src/conversion/ccm/misc/mergePoints1.C b/src/conversion/ccm/misc/mergePoints1.C new file mode 100644 index 0000000000000000000000000000000000000000..c1114df3ca0b6850af134dc77df5358e9bca9359 --- /dev/null +++ b/src/conversion/ccm/misc/mergePoints1.C @@ -0,0 +1,177 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 "ListOps.H" +#include "point.H" +#include "Field.H" + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + + +// template<class Type, template<class> class ListType=UList> +template<class Type> +Foam::label Foam::mergePoints +( + const bool dummy, + const UIndirectList<Type>& points, + const scalar mergeTol, + const bool verbose, + labelList& pointMap, + const Type& origin +) +{ + // Create a old to new point mapping array + pointMap.setSize(points.size()); + pointMap = -1; + + if (points.empty()) + { + return 0; + } + + // No normal field operations on UIndirectList. + // Use a tmp pointField instead. + tmp<Field<Type>> tPoints(new pointField(points)); + + Type compareOrigin = origin; + if (origin == Type::max) + { + compareOrigin = sum(tPoints())/points.size(); + } + + // We're comparing distance squared to origin first. + // Say if starting from two close points: + // x, y, z + // x+mergeTol, y+mergeTol, z+mergeTol + // Then the magSqr of both will be + // x^2+y^2+z^2 + // x^2+y^2+z^2 + 2*mergeTol*(x+z+y) + mergeTol^2*... + // so the difference will be 2*mergeTol*(x+y+z) + + const scalar mergeTolSqr = Foam::sqr(scalar(mergeTol)); + + // Sort points by magSqr + const Field<Type> d(tPoints - compareOrigin); + + List<scalar> magSqrD(d.size()); + forAll(d, pointI) + { + magSqrD[pointI] = magSqr(d[pointI]); + } + labelList order; + sortedOrder(magSqrD, order); + + + Field<scalar> sortedTol(points.size()); + forAll(order, sortI) + { + label pointI = order[sortI]; + + // Convert to scalar precision + const point pt + ( + scalar(d[pointI].x()), + scalar(d[pointI].y()), + scalar(d[pointI].z()) + ); + sortedTol[sortI] = 2*mergeTol*(mag(pt.x())+mag(pt.y())+mag(pt.z())); + } + + label newPointI = 0; + + // Handle 0th point separately (is always unique) + label pointI = order[0]; + pointMap[pointI] = newPointI++; + + + for (label sortI = 1; sortI < order.size(); sortI++) + { + // Get original point index + label pointI = order[sortI]; + const scalar mag2 = magSqrD[order[sortI]]; + // Convert to scalar precision + const point pt + ( + scalar(points[pointI].x()), + scalar(points[pointI].y()), + scalar(points[pointI].z()) + ); + + + // Compare to previous points to find equal one. + label equalPointI = -1; + + for + ( + label prevSortI = sortI - 1; + prevSortI >= 0 + && (mag(magSqrD[order[prevSortI]] - mag2) <= sortedTol[sortI]); + prevSortI-- + ) + { + label prevPointI = order[prevSortI]; + const point prevPt + ( + scalar(points[prevPointI].x()), + scalar(points[prevPointI].y()), + scalar(points[prevPointI].z()) + ); + + if (magSqr(pt - prevPt) <= mergeTolSqr) + { + // Found match. + equalPointI = prevPointI; + + break; + } + } + + + if (equalPointI != -1) + { + // Same coordinate as equalPointI. Map to same new point. + pointMap[pointI] = pointMap[equalPointI]; + + if (verbose) + { + Pout<< "Foam::mergePoints : Merging points " + << pointI << " and " << equalPointI + << " with coordinates:" << points[pointI] + << " and " << points[equalPointI] + << endl; + } + } + else + { + // Differs. Store new point. + pointMap[pointI] = newPointI++; + } + } + + return newPointI; +} + + +// ************************************************************************* // diff --git a/src/conversion/ccm/misc/mergePoints1.H b/src/conversion/ccm/misc/mergePoints1.H new file mode 100644 index 0000000000000000000000000000000000000000..85fc56210a289be0d488e89985d0edaab10e13dc --- /dev/null +++ b/src/conversion/ccm/misc/mergePoints1.H @@ -0,0 +1,73 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 + Merge points. See below. + +SourceFiles + mergePoints.C + +\*---------------------------------------------------------------------------*/ + +#ifndef mergePoints1_H +#define mergePoints1_H + +#include "scalar.H" +#include "labelList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Function mergePoints Declaration +\*---------------------------------------------------------------------------*/ + +//- Sorts and merges points. All points closer than/equal mergeTol get merged. +// Returns the number of unique points and a map from old to new. +//template<class Type, template<class> class ListType=UList> +template<class Type> +label mergePoints +( + const bool dummy, + const UIndirectList<Type>& points, + const scalar mergeTol, + const bool verbose, + labelList& pointMap, + const Type& origin = Type::zero +); + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "mergePoints1.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ccm/reader/ccmBoundaryInfo.H b/src/conversion/ccm/reader/ccmBoundaryInfo.H new file mode 100644 index 0000000000000000000000000000000000000000..967c6f51e1071f28df17294daa011fb78d22bc59 --- /dev/null +++ b/src/conversion/ccm/reader/ccmBoundaryInfo.H @@ -0,0 +1,126 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Description + Containers for holding STARCCM boundary information + +\*---------------------------------------------------------------------------*/ +#ifndef ccmBoundaryInfo_H +#define ccmBoundaryInfo_H + +#include "word.H" +#include "Ostream.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//! \cond internal-use +// internal use only - skip doxygen documentation +namespace Foam +{ +namespace ccm +{ + +/*---------------------------------------------------------------------------*\ + Class ccm::ccmBoundaryInfo Declaration +\*---------------------------------------------------------------------------*/ + +//- Helper when reading raw boundary information +class ccmBoundaryInfo +{ +public: + //- The ccm region + int ccmIndex; + + //- Number of faces + label size; + + //- The openfoam patch id to map to + label patchId; + + //- The patch name, as per the BoundaryRegion "Label" entry + std::string patchName; + + //- The patch type, as per the BoundaryRegion "BoundaryType" entry + std::string patchType; + + + //- Construct null + ccmBoundaryInfo() + : + ccmIndex(0), + size(0), + patchId(-1), + patchName(), + patchType("patch") + {} + + + //- Set patch name, default to "patch_CCMID" for an empty string + void setPatchName(const std::string& str) + { + if (str.empty()) + { + patchName = "patch_" + ::Foam::name(ccmIndex); + } + else + { + patchName = str; + } + } + + + //- Info doesn't match if the ccm boundaries are different + bool operator!=(const ccmBoundaryInfo& rhs) const + { + return ccmIndex != rhs.ccmIndex; + } + + // IOstream Operators + + friend Ostream& operator<<(Ostream& os, const ccmBoundaryInfo& entry) + { + os << "BoundaryFaces-" << entry.ccmIndex; + os << " size=" << entry.size; + os << " name=" << entry.patchName; + os << " type=" << entry.patchType; + os << " foam-patch=" << entry.patchId; + + return os; + } + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace ccm +} // End namespace Foam + +//! \endcond +// internal use only - skip doxygen documentation + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ccm/reader/ccmInterfaceDefinitions.H b/src/conversion/ccm/reader/ccmInterfaceDefinitions.H new file mode 100644 index 0000000000000000000000000000000000000000..1c9ea2c8e55da3b5ee3642f1afc118a0f339a984 --- /dev/null +++ b/src/conversion/ccm/reader/ccmInterfaceDefinitions.H @@ -0,0 +1,252 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Description + Containers for holding STARCCM interface definitions + +\*---------------------------------------------------------------------------*/ +#ifndef ccmInterfaceDefinitions_H +#define ccmInterfaceDefinitions_H + +#include "Map.H" +#include "Ostream.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace ccm +{ + +/*---------------------------------------------------------------------------*\ + Class ccm::interfaceEntry Declaration +\*---------------------------------------------------------------------------*/ + +//- A STARCCM interface definition is a pair of boundary ids +class interfaceEntry +{ +public: + // Public Data + + //- The internal interface id + label id; + + //- The first boundary + label bnd0; + + //- The second boundary + label bnd1; + + // Constructors + + //- Construct null + interfaceEntry() + : + id(-1), + bnd0(-1), + bnd1(-1) + {} + + + //- Construct empty interface definition + interfaceEntry(const label index) + : + id(index), + bnd0(-1), + bnd1(-1) + {} + + + //- Construct from components + interfaceEntry + ( + const label index, + const label boundary0, + const label boundary1 + ) + : + id(index), + bnd0(boundary0), + bnd1(boundary1) + {} + + + // Access + + //- Check for in-place interfaces + static bool isInPlace(const std::string& configurationType) + { + return configurationType == "IN_PLACE"; + } + + + //- True if the boundary id is in this interface + bool inInterface(label bndId) const + { + return bndId == bnd0 || bndId == bnd1; + } + + + //- Canonical name for boundary 0 + word canonicalName0() const + { + return "Interface" + ::Foam::name(id) + "_0"; + } + + //- Canonical name for boundary 1 + word canonicalName1() const + { + return "Interface" + ::Foam::name(id) + "_1"; + } + + //- Canonical name for boundary + word canonicalName(label bndId) const + { + if (bndId == bnd0) + { + return canonicalName0(); + } + else if (bndId == bnd1) + { + return canonicalName1(); + } + else + { + return word::null; + } + } + + + // IOstream Operators + + friend Ostream& operator<< + ( + Ostream& os, + const interfaceEntry& entry + ) + { + os << "(" << entry.bnd0 << " " << entry.bnd1 << ")"; + return os; + } + +}; + + +/*---------------------------------------------------------------------------*\ + Class ccm::interfaceDefinitions Declaration +\*---------------------------------------------------------------------------*/ + +//- A list of available interface definitions +class interfaceDefinitions +: + public Map<interfaceEntry> +{ +public: + // Constructor + + //- Null construct + interfaceDefinitions() + : + Map<interfaceEntry>() + {} + + + //- Scan available interface entries for one matching this boundary id + bool add(interfaceEntry entry) + { + if + ( + entry.id >= 0 + && entry.bnd0 >= 0 && entry.bnd1 >= 0 + && entry.bnd0 != entry.bnd1 + ) + { + this->set(entry.id, entry); + return true; + } + else + { + return false; + } + } + + + //- Scan available interface entries for one matching this boundary id + bool isInterface(label bndId) + { + forAllConstIter(Map<interfaceEntry>, *this, iter) + { + if (iter().inInterface(bndId)) + { + return true; + } + } + return false; + } + + + //- Scan interface entries for one matching this boundary id + // return the canonical name + word interfaceName(label bndId) + { + word ifname; + forAllConstIter(Map<interfaceEntry>, *this, iter) + { + ifname = iter().canonicalName(bndId); + if (!ifname.empty()) + { + break; + } + } + + return ifname; + } + + + // IOstream Operators + + friend Ostream& operator<< + ( + Ostream& os, + const interfaceDefinitions& defs + ) + { + os << static_cast<const Map<interfaceEntry>& >(defs) + << nl; + + return os; + } + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace ccm +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ccm/reader/ccmReader.C b/src/conversion/ccm/reader/ccmReader.C new file mode 100644 index 0000000000000000000000000000000000000000..5d0c6f11579837bdaf874a34af474e6949a316c8 --- /dev/null +++ b/src/conversion/ccm/reader/ccmReader.C @@ -0,0 +1,801 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*----------------------------------------------------------------------------*/ + +#include "ccmReader.H" +#include "IFstream.H" +#include "IOdictionary.H" +#include "demandDrivenData.H" + +#include "ccmInternal.H" // include last to avoid any strange interactions + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +// The cellTable integer options +const char* Foam::ccm::reader::cellTableOpti[] = +{ + "MaterialId", "PorosityId", "SpinId", "GroupId", "ColorIdx", nullptr +}; + +// The cellTable string options - "Label" handled separately +const char* Foam::ccm::reader::cellTableOptstr[] = +{ + "MaterialType", nullptr +}; + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +// Simulate GetEntityIndex +// CCMIOGetEntityIndex(nullptr, nodeId, &internalId); +int Foam::ccm::reader::ccmGetEntityIndex(ccmNODE node) +{ + int intval = 0; + char name[kCCMIOMaxStringLength + 1]; + + if + ( + CCMIOGetName + ( + nullptr, + node, + name + ) + == kCCMIONoErr + ) + { + char const *pos = strrchr(name, '-'); + + if (!pos) + { + intval = 0; + } + else + { + // Negative ID number + if (pos != name && (*(pos - 1) == '-')) + --pos; + + intval = atoi(++pos); + } + } + + return intval; +} + + +std::string Foam::ccm::reader::ccmReadNodestr +( + const char* opt, + ccmNODE node +) +{ + char *strval = 0; + std::string str; + + if + ( + CCMIOReadNodestr + ( + nullptr, + node, + opt, + &strval + ) + == kCCMIONoErr + && strval + ) + { + str = strval; + } + + // allocated by CCMIOReadNodestr + if (strval) + { + free(strval); + } + + return str; +} + + +std::string Foam::ccm::reader::ccmReadOptstr +( + const char* opt, + ccmID node +) +{ + std::string str; + int len = 0; + + if + ( + CCMIOReadOptstr + ( + nullptr, + node, + opt, + &len, + nullptr + ) + == kCCMIONoErr + && len + ) + { + char* strval = new char[len + 1]; + if + ( + CCMIOReadOptstr + ( + nullptr, + node, + opt, + &len, + strval + ) + == kCCMIONoErr + ) + { + strval[len] = '\0'; + str = strval; + } + delete[] strval; + } + + return str; +} + + +Foam::word Foam::ccm::reader::validateWord +( + const std::string& str +) +{ + std::string::size_type ngood = 0; + bool prefix = false; + bool first = true; + + for + ( + std::string::const_iterator iter = str.begin(); + iter != str.end(); + ++iter + ) + { + if (word::valid(*iter)) + { + ++ngood; + if (first) + { + first = false; + + // start with a digit? need to prefix with '_' + if (isdigit(*iter)) + { + prefix = true; + ++ngood; + } + } + } + } + + if (ngood == str.size() && !prefix) + { + return str; + } + + Foam::word out; + out.resize(ngood); + ngood = 0; + + Foam::word::iterator iter2 = out.begin(); + for + ( + std::string::const_iterator iter1 = str.begin(); + iter1 != str.end(); + ++iter1 + ) + { + register char c = *iter1; + + if (Foam::word::valid(c)) + { + if (prefix) + { + prefix = false; + *(iter2++) = '_'; + ++ngood; + } + *(iter2++) = c; + ++ngood; + } + } + + out.resize(ngood); + + return out; +} + + +// read map data and check error +void Foam::ccm::reader::readMap +( + const ccmID& mapId, + labelList& data +) +{ + if (globalState_->hasError()) + { + return; + } + + CCMIOReadMap + ( + &(globalState_->error), + mapId, + data.begin(), + kCCMIOStart, + kCCMIOEnd + ); + assertNoError("error reading map"); +} + + +// readProblemDescription: +// - get cellTable and boundaryRegion information +// - some regions defined here may be unused by our mesh +void Foam::ccm::reader::readProblemDescription +( + const ccmID& probNode +) +{ + readInterfaceDefinitions(); + readProblemDescription_boundaryRegion(probNode); + readProblemDescription_cellTable(probNode); + +#ifdef DEBUG_CCMIOREAD + Info<< "InterfaceDefinitions: " << interfaceDefinitions_ << nl + << "cellTable" << cellTable_ << nl + << "boundaryRegion" << boundaryRegion_ << endl; +#endif +} + + +// readInterfaceDefinitions: +// - get /InterfaceDefinitions. used by STARCCM to define in-place interfaces, etc +// - only handle in-place one here +void Foam::ccm::reader::readInterfaceDefinitions() +{ + interfaceDefinitions_.clear(); + + // /InterfaceDefinitions + // --------------------- + + CCMIONode rootNode; + CCMIONode interfaceDefNode; + + // CCMIOID -> CCMIONODE + if + ( + CCMIOGetEntityNode + ( + nullptr, + (globalState_->root), + &rootNode + ) + == kCCMIONoErr + + // get "/InterfaceDefinitions" + && + CCMIOGetNode + ( + nullptr, + rootNode, + "InterfaceDefinitions", + &interfaceDefNode + ) + == kCCMIONoErr + ) + { + CCMIONode interfaceNode; + + // simulate CCMIONextEntity + for + ( + int index = 0; + CCMIOGetNextChildWithLabel + ( + nullptr, + interfaceDefNode, + "Interface", + &index, + &interfaceNode + ) == kCCMIONoErr; + /* nop */ + ) + { + interfaceEntry ifentry(ccmGetEntityIndex(interfaceNode)); + + if + ( + CCMIOReadNodei + ( + nullptr, + interfaceNode, + "Boundary0", + &(ifentry.bnd0) + ) + == kCCMIONoErr + + && CCMIOReadNodei + ( + nullptr, + interfaceNode, + "Boundary1", + &(ifentry.bnd1) + ) + == kCCMIONoErr + + // only handle 'IN_PLACE' interfaces + && interfaceEntry::isInPlace + ( + ccmReadNodestr("Configuration", interfaceNode) + ) + ) + { + interfaceDefinitions_.add(ifentry); + } + } + } +} + + +// readProblemDescription - get boundaryRegion information +// +// CCM Node: /ProblemDescriptions/ProblemDescription-N/BoundaryRegion-N +// +// Requires InterfaceDefinitions first +void Foam::ccm::reader::readProblemDescription_boundaryRegion +( + const ccmID& probNode +) +{ + if (option().useNumberedNames()) + { + Info<< "using numbered patch/zone names" << endl; + } + + boundaryRegion_.clear(); + + ccmID node; + + // boundaryRegion information + // -------------------------- + for + ( + int nodeI = 0; + CCMIONextEntity + ( + nullptr, + probNode, + kCCMIOBoundaryRegion, + &nodeI, + &node + ) == kCCMIONoErr; + /* nop */ + ) + { + // read boundaryRegionId + int Id = 0; + CCMIOGetEntityIndex + ( + &(globalState_->error), + node, + &Id + ); + assertNoError("error reading boundaryRegion index"); + + dictionary dict; + + // Read boundary type + // (inlet|outlet|symmetry|wall| + // cyclic|stagnation|pressure|baffle|freestream) + { + const char* opt = "BoundaryType"; + std::string str = ccmReadOptstr(opt, node); + + if (str.empty()) + { + dict.add(opt, "empty"); + } + else if (str == "internal") + { + // old PROSTAR bug: "monitoring" mislabeled as "internal" + dict.add(opt, "monitoring"); + } + else + { + dict.add(opt, validateWord(str)); + } + } + + + // Read boundary name: + // - from 'Label' field (STARCCM+) + // - from 'BoundaryName' field (PROSTAR and/or STARCCM+) + // - fallback: generate one from boundary type and boundaryRegionId + { + const char* opt = "Label"; + std::string str; + + if (option().useNumberedNames()) + { + str = "patch_" + ::Foam::name(Id); + } + else if + ( + option().renameInterfaces() + && interfaceDefinitions_.isInterface(Id) + ) + { +#ifdef DEBUG_CCMIOREAD + Info<< "boundary is on an interface: remap name for " << Id << endl; +#endif + // substitute immediately with interface name + str = interfaceDefinitions_.interfaceName(Id); + } + else if + ( + (str = ccmReadOptstr(opt, node)).empty() + && (str = ccmReadOptstr("BoundaryName", node)).empty() + ) + { + // fallback + str = word(dict["BoundaryType"]) + "_" + ::Foam::name(Id); + } + + if (!str.empty()) + { + dict.add(opt, validateWord(str)); + } + } + + boundaryRegion_.insert(Id, dict); + } +} + + +// readProblemDescription - get cellTable information +// +// CCM Node: /ProblemDescriptions/ProblemDescription-N/CellType-N +// +void Foam::ccm::reader::readProblemDescription_cellTable +( + const ccmID& probNode +) +{ + cellTable_.clear(); + + ccmID node; + + // cellTable information + // --------------------- + for + ( + int nodeI = 0; + CCMIONextEntity + ( + nullptr, + probNode, + kCCMIOCellType, + &nodeI, + &node + ) == kCCMIONoErr; + /* nop */ + ) + { + // Read cellTableId (CellType) + int Id = 0; + CCMIOGetEntityIndex + ( + &(globalState_->error), + node, + &Id + ); + assertNoError("error reading cellTable index"); + + dictionary dict; + + // Special treatment for "Label" + { + const char* opt = "Label"; + std::string str; + + if (!option().useNumberedNames()) + { + str = ccmReadOptstr(opt, node); + } + + if (str.empty()) + { + str = "zone_" + ::Foam::name(Id); + } + + dict.add(opt, validateWord(str)); + } + + + // Other string options + for (int i=0; cellTableOptstr[i]; ++i) + { + const char* opt = cellTableOptstr[i]; + std::string str = ccmReadOptstr(opt, node); + + if (!str.empty()) + { + dict.add(opt, validateWord(str)); + } + } + + // Add non-zero integer options + for (int i=0; cellTableOpti[i]; ++i) + { + const char* opt = cellTableOpti[i]; + int intval; + + if + ( + CCMIOReadOpti + ( + nullptr, + node, + opt, + &intval + ) + == kCCMIONoErr + && intval != 0 + ) + { + dict.add(opt, intval); + } + } + + cellTable_.insert(Id, dict); + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::ccm::reader::printInfo() const +{ + Info<< "Mesh Information" << nl + << "----------------" << nl + << "boundingBox: " << boundBox(points_) << nl + << "nPoints: " << nPoints_ << nl + << "nCells: " << nCells_ << nl + << "nFaces: " << nFaces_ << nl + << "nInternalFaces: " << nInternalFaces_ << nl + << "nBaffles: " << bafInterfaces_.size() << endl; +} + + +bool Foam::ccm::reader::readGeometry +( + const scalar scaleFactor +) +{ + detectGeometry(); + + if (geometryStatus_ == OKAY) + { + // Sanity on the scaling factor + + readMeshTopology(scaleFactor <= VSMALL ? 1 : scaleFactor); + reorderMesh(); + + // assume success if we have points and cells + if (nCells_ && points_.size()) + { + geometryStatus_ = READ; + } + else + { + geometryStatus_ = BAD; + } + } + + return (geometryStatus_ == OKAY || geometryStatus_ == READ); +} + + +bool Foam::ccm::reader::hasGeometry() +{ + detectGeometry(); + return (geometryStatus_ == OKAY || geometryStatus_ == READ); +} + + +bool Foam::ccm::reader::hasSolution() +{ + detectSolution(); + return (solutionStatus_ == OKAY || solutionStatus_ == READ); +} + + +void Foam::ccm::reader::writeMesh +( + const polyMesh& mesh, + IOstream::streamFormat fmt +) const +{ + mesh.removeFiles(); + + Info<< "Writing polyMesh" << endl; + mesh.writeObject + ( + fmt, + IOstream::currentVersion, + IOstream::UNCOMPRESSED + ); + writeAux(mesh); +} + + +bool Foam::ccm::reader::remapMeshInfo +( + const objectRegistry& registry, + const fileName& remappingDictName +) +{ + dictionary remapDict; + + if (remappingDictName.empty()) + { + remapDict = IOdictionary + ( + IOobject + ( + "remapping", + "constant", + registry, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE, + false + ) + ); + } + else + { + // specified (absolute) name: treat like MUST_READ + remapDict = dictionary(IFstream(remappingDictName)()); + } + + bool ok = false; + + if (remapDict.empty()) + { + return false; + } + + + // merge specified cellTable entries together + if (remapDict.isDict("cellTable")) + { + cellTable_.combine(remapDict.subDict("cellTable"), cellTableId_); + ok = true; + } + + // rename boundaries + if (remapDict.isDict("boundaryRegion")) + { + boundaryRegion_.rename(remapDict.subDict("boundaryRegion")); + ok = true; + } + + return ok; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct from reading a file +Foam::ccm::reader::reader +( + const fileName& file, + const reader::options& opts +) +: + base(), + options_(new options(opts)), + geometryStatus_(UNKNOWN), + solutionStatus_(UNKNOWN), + interfaceDefinitions_(), + boundaryRegion_(), + cellTable_(), + nPoints_(0), + nInternalFaces_(0), + nFaces_(0), + nCells_(0), + points_(), + faces_(), + faceOwner_(), + faceNeighbour_(), + bafInterfaces_(), + domInterfaces_(), + origFaceId_(), + origCellId_(), + cellTableId_(), + origBndId_(), + patchSizes_(), + solutionTable_(), + fieldTable_(), + lagrangianTable_() +{ + if (!option().keptSomeRegion()) + { + FatalErrorIn("ccm::reader(const fileName&)") + << "must retain at least one region type: fluid | porous | solid" + << exit(FatalError); + } + + if (!isFile(file, false)) + { + FatalErrorIn("ccm::reader(const fileName&)") + << "Cannot read file " << file + << exit(FatalError); + } + + // Reinitialize error state from the return value + globalState_->error = CCMIOOpenFile + ( + nullptr, + file.c_str(), + kCCMIORead, + &(globalState_->root) + ); + assertNoError("Error opening file for reading"); + + detectGeometry(); + detectSolution(); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::ccm::reader::~reader() +{ + close(); + deleteDemandDrivenData(options_); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +const Foam::ccm::reader::options& Foam::ccm::reader::option() const +{ + return *options_; +} + + +// ************************************************************************* // diff --git a/src/conversion/ccm/reader/ccmReader.H b/src/conversion/ccm/reader/ccmReader.H new file mode 100644 index 0000000000000000000000000000000000000000..aa15978dd35314388bf4de9c407fe4c41c19a710 --- /dev/null +++ b/src/conversion/ccm/reader/ccmReader.H @@ -0,0 +1,710 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::ccm::reader + +Description + Reads CCM files as written by PROSTAR/STARCCM + + - arbitrary polyhedral meshs + - writes interfaces (baffles) to constant/polymesh/interfaces + - experimental handling of monitoring (internal) boundaries + - does not handle cyclics. Use createPatch to recreate these + - does patch names only if they are in the problem description + - reads cell and face solution data + - reads Lagrangian data + + The Default_Boundary_Region (region 0) is a special region that serves + two purposes: + -# it contains all wall and baffle boundaries that have not otherwise + been assigned. + -# it holds the outer bounds of flow domains (fluid/porous/solid) + + The CCM node \c Meshes/FaceBasedTopology/Cells/Interfaces holds the mapping + of the corresponding mesh faces, which can be used to merge these internal + boundaries. + + If solid cells exist, there are three possible courses of action: + -# Remove all solid cells for subsequent flow calculations. + This is the default. + -# Treat solid cells like fluid cells, but convert the corresponding + Default_Boundary_Region to Default_Boundary_Solid for easier + identification. + This treatment is useful for visualization purposes. + -# Move solid cells to a separate mesh region. + This would be useful for conjugate heat transfer, but + is not implemented. + + \par Files + + The <tt>constant/remapping</tt> file is an \c IOdictionary that is + \c READ_IF_PRESENT and can be used to remap certain information. eg, + + \verbatim + // rename/combine cellTable entries + // newName ( listOldNames ); + cellTable + { + fluid ( inletRegion outletRegion ); + cat1 ( CAT1 "cat1_(Back|Front|Gamma)" ); + } + + // rename boundary regions + // newName oldName; + boundaryRegion + { + inlet_4 inlet_1; + inlet_5 inlet_2; + inlet_6 inlet_3; + } + \endverbatim + + The <tt>constant/boundaryRegion</tt> file is an \c IOMap<dictionary> + that is written. It contains the boundary type and names. eg, + + \verbatim + ( + 0 + { + BoundaryType wall; + Label Default_Boundary_Region; + } + 1 + { + BoundaryType inlet; + Label inlet_1; + } + ... + + 4 + { + BoundaryType pressure; + Label outlet; + } + ) + \endverbatim + + The <tt>constant/cellTable</tt> file is an \c IOMap<dictionary> that is + written. It contains the cellTable information. + eg, + + \verbatim + ( + 1 + { + Label inletRegion; + MaterialType fluid; + MaterialId 1; + } + 2 + { + Label cat1; + MaterialType fluid; + MaterialId 1; + PorosityId 1; + } + 3 + { + Label outletRegion; + MaterialType fluid; + MaterialId 1; + } + ) + \endverbatim + +Note + this class is still under development + - any/all of the class names and members may change + +SourceFiles + ccmReader.C + ccmReaderAux.C + ccmReaderMesh.C + ccmReaderSolution.C + +\*---------------------------------------------------------------------------*/ + +#ifndef ccmReader_H +#define ccmReader_H + +#include "ccmBase.H" +#include "STARCDCore.H" + +#include "labelList.H" +#include "ListOps.H" +#include "polyMesh.H" +#include "boundaryRegion.H" +#include "cellTable.H" +#include "ccmInterfaceDefinitions.H" +#include "ccmSolutionTable.H" + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace ccm +{ + +// * * * * * * * * * * * * * Forward Declarations * * * * * * * * * * * * * // + +class ccmID; +class ccmNODE; +class ccmGlobalState; +class reader; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +/*---------------------------------------------------------------------------*\ + Class ccm::reader Declaration +\*---------------------------------------------------------------------------*/ + +class reader +: + public base, + protected fileFormats::STARCDCore +{ +public: + // Forward Declarations + class options; + + +private: + + // Static Data + + //- cellTable integer options + static const char* cellTableOpti[]; + + //- cellTable string options + static const char* cellTableOptstr[]; + + + // Private data + + //- Reader options + const options* options_; + + + //- Enumeration defining the status of a ccmio node + enum nodeStatus + { + UNKNOWN, BAD, OKAY, READ + }; + + + //- status of the geometry (topology) information + nodeStatus geometryStatus_; + + //- status of the solution (field) information + nodeStatus solutionStatus_; + + // Persistent data + + //- ccm node: /InterfaceDefinitions + interfaceDefinitions interfaceDefinitions_; + + //- ccm node: ProblemDescriptions/boundaryRegion + boundaryRegion boundaryRegion_; + + //- ccm node: ProblemDescriptions/cellType + cellTable cellTable_; + + //- Number of points + label nPoints_; + + //- Number of internal faces + label nInternalFaces_; + + //- Number of faces + label nFaces_; + + //- Number of cells + label nCells_; + + //- Minimum mesh data + + //- Points + pointField points_; + + //- Faces + faceList faces_; + + //- Face-owner cells + labelList faceOwner_; + + //- Face-neighbour cells + labelList faceNeighbour_; + + // List of interface pairs (baffles) + List<labelPair> bafInterfaces_; + + //- List of interface pairs between mesh regions (domains) + List<labelPair> domInterfaces_; + + //- Face sets for monitoring + HashTable<labelList> monitoringSets_; + + + // Mesh Maps + + //- Map to original face id + labelList origFaceId_; + + //- Map to original cell id + labelList origCellId_; + + //- Cell table id for each cell + labelList cellTableId_; + + //- List of the original ccm boundary region number + labelList origBndId_; + + //- Patching and region info + labelList patchSizes_; + + //- Solution information + solutionTable solutionTable_; + + //- Field information + fieldTable fieldTable_; + + //- Field information + fieldTable lagrangianTable_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + reader(const reader&) = delete; + + //- Disallow default bitwise assignment + void operator=(const reader&) = delete; + + + //- Calculate patch starts from given index with current patch sizes + inline labelList patchStartList(label initial) const; + + //- Report mesh sizes to stdout + void printSizes() const; + + //- Simulate CCMIOGetEntityIndex for Nodes (not ids) + int ccmGetEntityIndex(ccmNODE node); + + //- Read string option from specified ccm node + // return empty string on failure + std::string ccmReadNodestr(const char* opt, ccmNODE node); + + //- Read string option from specified ccm node + // return empty string on failure + std::string ccmReadOptstr(const char* opt, ccmID node); + + //- Strip invalid characters, prefix leading digit with '_' + static word validateWord(const std::string&); + + //- Read map data and check error + void readMap(const ccmID& mapId, labelList& data); + + //- Determine if the geometry looks good + bool detectGeometry(); + + //- Get interfaces, cellTable and boundaryRegion information + void readProblemDescription(const ccmID& probNode); + + //- Get /InterfaceDefinitions, used by STARCCM to define in-place interfaces, etc + // only handle in-place (IN_PLACE) ones at the moment + void readInterfaceDefinitions(); + + //- Get boundaryRegion information + void readProblemDescription_boundaryRegion(const ccmID& probNode); + + //- Get cellTable information + void readProblemDescription_cellTable(const ccmID& probNode); + + //- Read the geometry without any sorting or renumbering + void readMeshTopology(const scalar scaleFactor=1.0); + + //- Read the vertices + labelList readVertices + ( + const ccmID& verticesNode, + const scalar scaleFactor = 1.0 + ); + + //- Read the cells + void readCells(const ccmID& topoNode); + + //- Read the interfaces + void readInterfaces(const ccmID& cellsNode); + + //- Read the monitoring + void readMonitoring(const ccmID& topoId); + + //- Move solid faces from Default_Boundary_Region -> Default_Boundary_Solid + void juggleSolids(); + + //- Remove unwanted fluid/porous/solid regions + void removeUnwanted(); + + //- Remove interfaces with face >= nFace + void validateInterface(List<labelPair>&); + + //- Renumber interface faces + void renumberInterfaces(const List<label>&); + + //- Remove interfaces between domains (fluid/porosity; fluid/solid, etc) + // reorganize baffle interfaces into [0-N/2; N/2-N] lists at the + // beginning of the corresponding patch + void cleanupInterfaces(); + + //- Merge the points and faces of in-place conformal interfaces + void mergeInplaceInterfaces(); + + //- Re-order mesh and ensure upper-triangular order + void reorderMesh(); + + //- Write interface (baffle) mapping + void writeInterfaces(const objectRegistry&) const; + + //- Write List<label> in constant/polyMesh + void writeMeshLabelList + ( + const objectRegistry& registry, + const word& propertyName, + const labelList& list, + IOstream::streamFormat fmt = IOstream::ASCII + ) const; + + // polyMesh Friend Functions + void addPatches(polyMesh&) const; + + //- Add faceZones based on monitoring boundary conditions + void addFaceZones(polyMesh&) const; + + //- Get information about all available solutions + bool detectSolution(); + + //- Get information about available fields + // assume that all fields are available for all solution intervals + void determineFieldInfo(const ccmID& fieldSetNode, fieldTable&); + + + // Static Members + + //- Get map of porous regions + static Map<word> selectPorous(const Map<dictionary>&); + + +public: + + // Static Members + + //- Warn about repeated name + static void warnDuplicates(const word& context, const wordList&); + + + // Constructors + + //- Open a file for reading + reader(const fileName&, const options& opts); + + + //- Destructor (closes file) + ~reader(); + + + // Member Functions + + // Access + + //- Reference to the reader options + const reader::options& option() const; + + + //- Construct the polyMesh from the read geometry + // provide optional remapping dictionary + autoPtr<polyMesh> mesh + ( + const objectRegistry& registry, + const fileName& remappingDictName = fileName::null + ); + + + // label nPoints() const { return nPoints_; } + // label nInternalFaces() const { return nInternalFaces_; } + // label nFaces() const { return nFaces_; } + // label nCells() const { return nCells_; } + + // const faceList& faces() const { return faces_; } + // const labelList& faceOwner() const { return faceOwner_; } + // const labelList& faceNeighbour() const { return faceNeighbour_; } + // const pointField& points() const { return points_; } + + + // Check + + //- Return true if file has geometry associated with it + bool hasGeometry(); + + //- Return true if file has solutions associated with it + bool hasSolution(); + + + // Edit + + //- Remap cellTable and boundaryRegion according to dictionary + bool remapMeshInfo + ( + const objectRegistry& registry, + const fileName& remappingDictName = fileName::null + ); + + + // Write + + //- Write the polyMesh + void writeMesh + ( + const polyMesh&, + IOstream::streamFormat fmt = IOstream::BINARY + ) const; + + //- Write cellTable, boundaryRegion and interface information + void writeAux(const objectRegistry&) const; + + //- Detect and read geometry if possible + bool readGeometry(const scalar scaleFactor = 1.0); + + //- Print general information about the mesh + void printInfo() const; + + //- Clear out some information after obtaining a polyMesh + void clearGeom(); + + //- Map to original cell Id + const labelList& origCellId() const + { + return origCellId_; + } + + //- Map to original face Id + const labelList& origFaceId() const + { + return origFaceId_; + } + + //- Return interface definitions map + const interfaceDefinitions& interfaceDefinitionsInfo() const + { + return interfaceDefinitions_; + } + + //- Return boundaryRegion table + const boundaryRegion& boundaryTableInfo() const + { + return boundaryRegion_; + } + + //- Return cell table + const cellTable& cellTableInfo() const + { + return cellTable_; + } + + //- Return a list of names corresponding to fluids + Map<word> fluids() const + { + return cellTable_.fluids(); + } + + //- Return a list of names corresponding to solids + Map<word> solids() const + { + return cellTable_.solids(); + } + + //- Return table of available solutions + const solutionTable& solutions() + { + detectSolution(); + return solutionTable_; + } + + //- Return table of available fields + const fieldTable& fields() + { + detectSolution(); + return fieldTable_; + } + + //- Return table of available lagrangian fields + const fieldTable& lagrangian() + { + detectSolution(); + return lagrangianTable_; + } + + //- Read solution and field combination + tmp<scalarField> readField + ( + const word& solutionName, + const word& fieldName, + const bool wallData = false + ); + +}; + + +/*---------------------------------------------------------------------------*\ + Class ccm::reader::options Declaration +\*---------------------------------------------------------------------------*/ + +class reader::options +{ + // Private data + + //- Keep fluid regions (default true) + bool keepFluid_; + + //- Keep porous regions (default true) + bool keepPorous_; + + //- Keep solid regions (default true) + bool keepSolid_; + + //- Merge in-place interfaces (default true) + bool mergeInterfaces_; + + //- Rename interface boundaries as InterfaceN_0, InterfaceN_1 (default true) + bool renameInterfaces_; + + //- Combine identically named boundaries (default false) + bool combineBoundaries_; + + //- Remove baffles by merging their respective faces (default false) + bool removeBaffles_; + + //- Use numbered names (eg, patch_0, zone_0) instead of human-readable + // names (default false) + bool useNumberedNames_; + + //- merge tolerance for points (default 0.05e-3) + scalar mergeTol_; + + //- Value to assign for undefined solutions (default: NaN) + scalar undefScalar_; + + +public: + + // Constructors + + //- Construct with the defaults + options(); + + + // Member Functions + + // Access + + //- Keep fluid regions (default true) + bool keepFluid() const; + + //- Keep porous regions (default true) + bool keepPorous() const; + + //- Keep solid regions (default true) + bool keepSolid() const; + + //- Some region (fluid, porous, solid) is kept. + bool keptSomeRegion() const; + + //- Merge in-place interfaces (default true) + bool mergeInterfaces() const; + + //- Rename interface boundaries as InterfaceN_0, InterfaceN_1 (default true) + bool renameInterfaces() const; + + //- Combine identically named boundaries (default false) + bool combineBoundaries() const; + + //- Remove baffles by merging their respective faces (default false) + bool removeBaffles() const; + + //- Use numbered names (eg, patch_0, zone_0) instead of human-readable + // names (default false) + bool useNumberedNames() const; + + //- Merge tolerance for points (default 0.05e-3) + scalar mergeTol() const; + + //- Value to assign for undefined solutions (default: NaN) + scalar undefScalar() const; + + + // Edit + + //- Keep fluid regions + void keepFluid(bool); + + //- Keep porous regions + void keepPorous(bool); + + //- Keep solid regions + void keepSolid(bool); + + //- Merge in-place interfaces + void mergeInterfaces(bool); + + //- Rename interface boundaries as InterfaceN_0, InterfaceN_1 + void renameInterfaces(bool); + + //- Combine identically named boundaries + void combineBoundaries(bool); + + //- Remove baffles by merging their respective faces + void removeBaffles(bool); + + //- Use numbered names (eg, patch_0, zone_0) instead of human-readable + void useNumberedNames(bool); + + //- Merge tolerance for points (default 0.05e-3) + void mergeTol(const scalar&); + + //- Value to assign for undefined solutions (default: NaN) + void undefScalar(const scalar&); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace ccm +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ccm/reader/ccmReaderAux.C b/src/conversion/ccm/reader/ccmReaderAux.C new file mode 100644 index 0000000000000000000000000000000000000000..f820dcb7f531871860e9232691cb518d8e121550 --- /dev/null +++ b/src/conversion/ccm/reader/ccmReaderAux.C @@ -0,0 +1,214 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Description + read/write auxiliary files for aiding STARCD/OPENFOAM interoperability + + - cellTable information + - boundaryRegion information + - interface information + +\*----------------------------------------------------------------------------*/ + +#include "OFstream.H" +#include "ccmReader.H" +#include "ccmInternal.H" // include last to avoid any strange interactions + + +// * * * * * * * * * * * * * * * Static Functions * * * * * * * * * * * * * // + +Foam::Map<Foam::word> Foam::ccm::reader::selectPorous +( + const Map<dictionary>& table +) +{ + Map<word> lookup; + + forAllConstIter(Map<dictionary>, table, iter) + { + if (iter().lookupOrDefault<label>("PorosityId", 0) != 0) + { + lookup.insert + ( + iter.key(), + iter().lookupOrDefault<word> + ( + "Label", + "cellTable_" + Foam::name(iter.key()) + ) + ); + } + } + + return lookup; +} + + +void Foam::ccm::reader::warnDuplicates +( + const word& context, + const wordList& lst +) +{ + HashTable<label> hashed(lst.size()); + bool duplicates = false; + + forAll(lst, elemI) + { + // Check duplicate name + HashTable<label>::iterator iter = hashed.find(lst[elemI]); + if (iter != hashed.end()) + { + (*iter)++; + duplicates = true; + } + else + { + hashed.insert(lst[elemI], 1); + } + } + + // Warn about duplicate names + if (duplicates) + { + Info << nl << "WARNING: " << context << " with identical names:"; + forAllConstIter(HashTable<label>, hashed, iter) + { + if (*iter > 1) + { + Info << " " << iter.key(); + } + } + Info << nl << endl; + } +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::ccm::reader::writeInterfaces +( + const objectRegistry& registry +) const +{ + // Write constant/polyMesh/interface + IOList<labelList> ioObj + ( + IOobject + ( + "interfaces", + "constant", + polyMesh::meshSubDir, + registry, + IOobject::NO_READ, + IOobject::AUTO_WRITE, + false + ) + ); + + ioObj.note() = "as yet unsupported interfaces (baffles)"; + + Info<< "Writing " << ioObj.name() << " to " << ioObj.objectPath() << endl; + + OFstream os(ioObj.objectPath()); + ioObj.writeHeader(os); + + os << bafInterfaces_; +} + + +// Write List<label> in constant/polyMesh +// - this is crucial for later conversion back to ccm/starcd +void Foam::ccm::reader::writeMeshLabelList +( + const objectRegistry& registry, + const word& propertyName, + const labelList& list, + IOstream::streamFormat fmt +) const +{ + // Write constant/polyMesh/propertyName + IOList<label> ioObj + ( + IOobject + ( + propertyName, + "constant", + polyMesh::meshSubDir, + registry, + IOobject::NO_READ, + IOobject::AUTO_WRITE, + false + ), + list + ); + + ioObj.note() = "persistent data for STARCD <-> OPENFOAM translation"; + Info<< "Writing " << ioObj.name() << " to " << ioObj.objectPath() << endl; + + // NOTE: + // The cellTableId is an integer and almost always < 1000, thus ASCII + // will be compacter than binary and makes external scripting easier + // + ioObj.writeObject + ( + fmt, + IOstream::currentVersion, + IOstream::UNCOMPRESSED + ); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::ccm::reader::writeAux +( + const objectRegistry& registry +) const +{ + cellTable_.writeDict(registry); + boundaryRegion_.writeDict(registry); + writeInterfaces(registry); + + // Write origCellId as List<label> + writeMeshLabelList + ( + registry, + "origCellId", + origCellId_, + IOstream::BINARY + ); + + // Write cellTableId as List<label> + // - this is crucial for later conversion back to ccm/starcd + writeMeshLabelList + ( + registry, + "cellTableId", + cellTableId_, + IOstream::ASCII + ); +} + + +// ************************************************************************* // diff --git a/src/conversion/ccm/reader/ccmReaderMesh.C b/src/conversion/ccm/reader/ccmReaderMesh.C new file mode 100644 index 0000000000000000000000000000000000000000..aa5058c3cefbdea6b79d7df8ace12d7e734e6b25 --- /dev/null +++ b/src/conversion/ccm/reader/ccmReaderMesh.C @@ -0,0 +1,2696 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*----------------------------------------------------------------------------*/ + +#include "ccmReader.H" + +#include "emptyPolyPatch.H" +#include "symmetryPolyPatch.H" +#include "wallPolyPatch.H" +#include "SortableList.H" +#include "IFstream.H" +#include "OFstream.H" +#include "IOdictionary.H" + +#include "ccmBoundaryInfo.H" +#include "PackedList.H" +#include "uindirectPrimitivePatch.H" +#include "SortableList.H" +#include "mergePoints1.H" +#include "ListOps1.H" + +#include "ccmInternal.H" // include last to avoid any strange interactions + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::labelList Foam::ccm::reader::patchStartList +( + label initial +) const +{ + labelList startLst(patchSizes_.size(), Zero); + + label patchFaceI = initial; + forAll(patchSizes_, patchI) + { + startLst[patchI] = patchFaceI; + patchFaceI += patchSizes_[patchI]; + } + + return startLst; +} + + +void Foam::ccm::reader::printSizes() const +{ + Info<<"nPoints:" << nPoints_ + << " nCells:" << nCells_ + << " nFaces:" << nFaces_ + << " nInternalFaces:" << nInternalFaces_ + << endl; +} + + +// Determine if the geometry looks good. +// We'll insist that everything be on the first ("default") state, +// and is on the same file, and has a problem description +// +// The detection reads the problem description as well +// +bool Foam::ccm::reader::detectGeometry() +{ + // Call once + if (geometryStatus_ != UNKNOWN) + { + return (geometryStatus_ == OKAY || geometryStatus_ == READ); + } + + // Explicitly restricted to 'default' state node + ccmID stateNode; + + // Get associated problem description + ccmID probNode; + + // Only check the first processor + ccmID processorNode; + int procI = 0; + + // Geometry needs vertices and topology + ccmID verticesNode, topoNode; + + if + ( + CCMIOGetState + ( + nullptr, + (globalState_->root), + "default", + &probNode, + &stateNode + ) + == kCCMIONoErr + + && CCMIONextEntity + ( + nullptr, + stateNode, + kCCMIOProcessor, + &procI, + &processorNode + ) + == kCCMIONoErr + + && CCMIOReadProcessor + ( + nullptr, + processorNode, + &verticesNode, + &topoNode, + nullptr, // Ignore initialField + nullptr // Ignore solutionNode + ) + == kCCMIONoErr + + && CCMIOIsFromSameFile((globalState_->root), verticesNode) + && CCMIOIsFromSameFile((globalState_->root), topoNode) + && CCMIOIsValidEntity(probNode) + ) + { + readProblemDescription(probNode); + geometryStatus_ = OKAY; + } + else + { + // Missing/incomplete geometry node and/or problem node + geometryStatus_ = BAD; + } + + return (geometryStatus_ == OKAY || geometryStatus_ == READ); +} + + +// read the geometry without any sorting +void Foam::ccm::reader::readMeshTopology +( + const scalar scaleFactor +) +{ + ccmID verticesNode, topoNode; + + // Use first ("default") state node + ccmID stateNode; + int stateI = 0; + + // Use the first processor to find the mesh nodes + ccmID processorNode; + int procI = 0; + + if + ( + CCMIONextEntity + ( + nullptr, + (globalState_->root), + kCCMIOState, + &stateI, + &stateNode + ) + == kCCMIONoErr + + && CCMIONextEntity + ( + nullptr, + stateNode, + kCCMIOProcessor, + &procI, + &processorNode + ) + == kCCMIONoErr + + && CCMIOReadProcessor + ( + nullptr, + processorNode, + &verticesNode, + &topoNode, + nullptr, // Ignore initialField + nullptr // Ignore solutionNode + ) + == kCCMIONoErr + ) + { + labelList origPointId = readVertices(verticesNode, scaleFactor); + readCells(topoNode); + readMonitoring(topoNode); + + // Renumber vertex labels (ccm -> Foam) + { + label maxId = max(origPointId); + labelList mapToFoam(invert(maxId+1, origPointId)); + + forAll(faces_, faceI) + { + inplaceRenumber(mapToFoam, faces_[faceI]); + } + } + origPointId.clear(); + + // Renumber owners/neighbours cell labels (ccm -> Foam) + { + label maxId = max(origCellId_); + labelList mapToFoam(invert(maxId+1, origCellId_)); + + inplaceRenumber(mapToFoam, faceOwner_); + inplaceRenumber(mapToFoam, faceNeighbour_); + } + + // Juggle solids into fluid as required + juggleSolids(); + + // Report sizes + printSizes(); + + // Remove unwanted fluid/porous/solid types + removeUnwanted(); + + // Collapse interfaces between domains (eg, fluid|porosity) + cleanupInterfaces(); + + // Use point merge to join conformal interfaces (STARCCM) + mergeInplaceInterfaces(); + } +} + + +// readVertices: +// 1) read the vertex data +// 2) read the map (which maps the index into the data array with the Id number) +// +// returns the original point Id +Foam::labelList Foam::ccm::reader::readVertices +( + const ccmID& verticesNode, + const scalar scaleFactor +) +{ + int dims = 1; + float scale = 1.0; + + CCMIOSize size = 0; + ccmID mapId; + +#ifdef DEBUG_CCMIOREAD + Info<< "readVertices()" << endl; +#endif + + // Determine dimensions and mapId + CCMIOEntitySize + ( + &(globalState_->error), + verticesNode, + &size, + nullptr + ); + + CCMIOReadVerticesd + ( + &(globalState_->error), + verticesNode, + &dims, + &scale, + &mapId, + nullptr, + kCCMIOStart, + kCCMIOEnd + ); + assertNoError("problem finding 'Vertices' node"); + + if (dims != 3) + { + FatalErrorIn("ccm::reader::readVertices") + << "can only handle 3-dimensional vertices" + << exit(FatalError); + } + + nPoints_ = size; + labelList origPointId(nPoints_); + + readMap + ( + mapId, + origPointId + ); + + // Temporary storage for the points - reading piecemeal is much slower + List<scalar> vrts(3*nPoints_); + + // The ccm data is double precision too + CCMIOReadVerticesd + ( + &(globalState_->error), + verticesNode, + nullptr, + nullptr, + nullptr, + vrts.begin(), + kCCMIOStart, + kCCMIOEnd + ); + assertNoError("problem reading 'Vertices' node"); + + // Convert to foam Points + points_.setSize(nPoints_); + + scalar effectiveScale = scale * scaleFactor; + forAll(points_, i) + { + points_[i].x() = effectiveScale * vrts[i*3]; + points_[i].y() = effectiveScale * vrts[i*3+1]; + points_[i].z() = effectiveScale * vrts[i*3+2]; + } + + vrts.clear(); + +#ifdef DEBUG_CCMIOREAD + Info<< "readVertices: " << nPoints_ << endl; +#endif + + return origPointId; +} + + +// readCells: +// - read faces, faceOwner and faceNeighbour +// - finally read interfaces +void Foam::ccm::reader::readCells +( + const ccmID& topoNode +) +{ + CCMIOSize size = 0; + ccmID cellsNode, mapId; + ccmID nodeId; + +#ifdef DEBUG_CCMIOREAD + Info<< "readCells()" << endl; +#endif + + // Determine dimensions and mapId information for 'Cells' + CCMIOGetEntity + ( + &(globalState_->error), + topoNode, + kCCMIOCells, + 0, + &cellsNode + ); + + CCMIOEntitySize + ( + &(globalState_->error), + cellsNode, + &size, + nullptr + ); + assertNoError("cannot get 'Cells' node"); + + nCells_ = size; + +#ifdef DEBUG_CCMIOREAD + Info<< "readCells: " << nCells_ << endl; +#endif + + // Store cell ids so that we know which cells are which + origCellId_.setSize(nCells_); + cellTableId_.setSize(nCells_); + + CCMIOReadCells + ( + &(globalState_->error), + cellsNode, + &mapId, + cellTableId_.begin(), + kCCMIOStart, + kCCMIOEnd + ); + assertNoError("Error reading 'Cells' node"); + + readMap + ( + mapId, + origCellId_ + ); + + // Determine dimensions and mapId information for 'InternalFaces' + CCMIOGetEntity + ( + &(globalState_->error), + topoNode, + kCCMIOInternalFaces, + 0, + &nodeId + ); + CCMIOEntitySize + ( + &(globalState_->error), + nodeId, + &size, + nullptr + ); + nInternalFaces_ = size; + + nFaces_ = nInternalFaces_; + + // First pass: + // + // Determine patch sizes before reading internal faces + // also determine the original boundary regions + + label nPatches = 0; + DynamicList<ccmBoundaryInfo> bndInfo; + + // Number of children in the parent node is more than number of patches, + // but is a good start for allocation + if + ( + CCMIOGetNumberOfChildren + ( + nullptr, + topoNode.node, + &nPatches + ) == kCCMIONoErr + ) + { + bndInfo.setCapacity(nPatches); + } + + for + ( + int index = 0; + CCMIONextEntity + ( + nullptr, + topoNode, + kCCMIOBoundaryFaces, + &index, + &nodeId + ) == kCCMIONoErr + && CCMIOEntitySize + ( + &(globalState_->error), + nodeId, + &size, + nullptr + ) == kCCMIONoErr; + /* nop */ + ) + { + ccmBoundaryInfo info; + info.size = size; + nFaces_ += size; + + CCMIOGetEntityIndex + ( + &(globalState_->error), + nodeId, + &(info.ccmIndex) + ); + + // Name directly from the node (eg, STARCCM) + info.setPatchName(ccmReadOptstr("Label", nodeId)); + + // Lookup the name, type from boundary region info: + Map<dictionary>::iterator dictIter = boundaryRegion_.find(info.ccmIndex); + if (dictIter != boundaryRegion_.end()) + { + word patchName(dictIter()["Label"]); + word patchType(dictIter()["BoundaryType"]); + + if (!patchName.empty()) + { + info.patchName = patchName; + } + + if (!patchType.empty()) + { + info.patchType = patchType; + } + + // Optional, but potentially useful information: + dictIter().add("BoundaryIndex", info.ccmIndex); + dictIter().add("size", info.size); + } + + bndInfo.append(info); + } + + // Redimension lists according to the overall sizes + faces_.setSize(nFaces_); + faceOwner_.setSize(nFaces_); + faceNeighbour_.setSize(nFaces_); + origFaceId_.setSize(nFaces_); + + + // May be too large, but is a good place start size + patchSizes_.setSize(bndInfo.size()); + origBndId_.setSize(bndInfo.size()); + patchSizes_ = 0; + origBndId_ = -1; + nPatches = 0; + + HashTable<label, std::string> hashedNames; + if (option().combineBoundaries()) + { + // Ensure all the interfaces are orderd up-front: + forAll(interfaceDefinitions_, interI) + { + const interfaceEntry& ifentry = interfaceDefinitions_[interI]; + + label info0Index = -1; + label info1Index = -1; + + forAll(bndInfo, infoI) + { + if (bndInfo[infoI].ccmIndex == ifentry.bnd0) + { + info0Index = infoI; + } + else if (bndInfo[infoI].ccmIndex == ifentry.bnd1) + { + info1Index = infoI; + } + } + + if (info0Index == info1Index || info0Index < 0 || info1Index < 0) + { + // this should never be able to happen + continue; + } + + ccmBoundaryInfo& info0 = bndInfo[info0Index]; + ccmBoundaryInfo& info1 = bndInfo[info1Index]; + + // Preserve interface order + info0.patchId = nPatches++; + info1.patchId = nPatches++; + + // full safety: + info0.patchName = ifentry.canonicalName0(); + info1.patchName = ifentry.canonicalName1(); + + hashedNames.insert(info0.patchName, info0Index); + hashedNames.insert(info1.patchName, info1Index); + } + } + + forAll(bndInfo, infoI) + { + ccmBoundaryInfo& info = bndInfo[infoI]; + + if (info.patchId != -1) + { + // Already inserted - eg, as interface + origBndId_[info.patchId] = info.ccmIndex; + } + else + { + if (option().combineBoundaries()) + { + // Check if patch name was already seen + HashTable<label, std::string>::const_iterator citer = hashedNames.find(info.patchName); + if (citer != hashedNames.end()) + { + info.patchId = bndInfo[citer()].patchId; + } + else + { + hashedNames.insert(info.patchName, infoI); + + info.patchId = nPatches++; + origBndId_[info.patchId] = info.ccmIndex; + } + } + else + { + info.patchId = nPatches++; + origBndId_[info.patchId] = info.ccmIndex; + } + } + + patchSizes_[info.patchId] += info.size; + } + + // Shrink to sizes actually used + patchSizes_.setSize(nPatches); + origBndId_.setSize(nPatches); + + // Boundary info indices flattened and sorted by patchId + + IndirectList<ccmBoundaryInfo> ccmLookupOrder(bndInfo, labelList()); + { + DynamicList<label> addr(bndInfo.size()); + for (int patchI = 0; patchI < nPatches; ++patchI) + { + forAll(bndInfo, infoI) + { + if (bndInfo[infoI].patchId == patchI) + { + addr.append(infoI); + } + } + } + + ccmLookupOrder.resetAddressing(addr.xfer()); + } + + if (option().combineBoundaries()) + { + Info<<"patches combined by name: "; + if (nPatches == bndInfo.size()) + { + Info<<"none" << endl; + } + else + { + Info<< bndInfo.size() << " into " << nPatches << endl; + } + // Info<< ccmLookupOrder << endl; + } + + + // + // Now we are ready to do the reading + // + CCMIOGetEntity + ( + &(globalState_->error), + topoNode, + kCCMIOInternalFaces, + 0, + &nodeId + ); + + // get allocation sizes + CCMIOReadFaces + ( + &(globalState_->error), + nodeId, + kCCMIOInternalFaces, + &mapId, + &size, + nullptr, + kCCMIOStart, + kCCMIOEnd + ); + + List<label> mapData(nInternalFaces_); + List<label> faceCells(2*nInternalFaces_); + List<label> ccmFaces(size); + + CCMIOReadFaces + ( + &(globalState_->error), + nodeId, + kCCMIOInternalFaces, + nullptr, + nullptr, + ccmFaces.begin(), + kCCMIOStart, + kCCMIOEnd + ); + + CCMIOReadFaceCells + ( + &(globalState_->error), + nodeId, + kCCMIOInternalFaces, + faceCells.begin(), + kCCMIOStart, + kCCMIOEnd + ); + assertNoError("Error reading internal faces"); + + readMap + ( + mapId, + mapData + ); + + // Copy into Foam list + // ccmFaces are organized as [nVert vrt1 .. vrtN] + unsigned int pos = 0; + for (label faceI = 0; faceI < nInternalFaces_; ++faceI) + { + origFaceId_[faceI] = mapData[faceI]; + faceOwner_[faceI] = faceCells[2*faceI]; + faceNeighbour_[faceI] = faceCells[2*faceI+1]; + face& f = faces_[faceI]; + + f.setSize(ccmFaces[pos++]); + forAll(f, fp) + { + f[fp] = ccmFaces[pos++]; + } + } + + // Read the boundary faces + // ~~~~~~~~~~~~~~~~~~~~~~~ + label patchFaceI = nInternalFaces_; + + forAll(ccmLookupOrder, lookupI) + { + const ccmBoundaryInfo& info = ccmLookupOrder[lookupI]; + const unsigned int patchSize = info.size; + + if + ( + CCMIOGetEntity + ( + &(globalState_->error), + topoNode, + kCCMIOBoundaryFaces, + info.ccmIndex, + &nodeId + ) == kCCMIONoErr + ) + { + CCMIOReadFaces + ( + &(globalState_->error), + nodeId, + kCCMIOBoundaryFaces, + &mapId, + &size, // size needed for the faces + nullptr, + kCCMIOStart, + kCCMIOEnd + ); + + mapData.setSize(patchSize); + faceCells.setSize(patchSize); + ccmFaces.setSize(size); + + readMap + ( + mapId, + mapData + ); + + CCMIOReadFaces + ( + &(globalState_->error), + nodeId, + kCCMIOBoundaryFaces, + nullptr, + nullptr, + ccmFaces.begin(), + kCCMIOStart, + kCCMIOEnd + ); + CCMIOReadFaceCells + ( + &(globalState_->error), + nodeId, + kCCMIOBoundaryFaces, + faceCells.begin(), + kCCMIOStart, + kCCMIOEnd + ); + assertNoError("Error reading boundary face cells - index " + ::Foam::name(info.ccmIndex)); + + // Copy into Foam list + // ccmFaces are organized as [nVert vrt1 .. vrtN] + unsigned int pos = 0; + for (unsigned int i = 0; i < patchSize; ++i, ++patchFaceI) + { + origFaceId_[patchFaceI] = mapData[i]; + faceOwner_[patchFaceI] = faceCells[i]; + faceNeighbour_[patchFaceI] = -1; + + face& f = faces_[patchFaceI]; + + f.setSize(ccmFaces[pos++]); + forAll(f, fp) + { + f[fp] = ccmFaces[pos++]; + } + } + } + else + { + assertNoError("Error reading boundary faces - index " + ::Foam::name(info.ccmIndex)); + } + } + + readInterfaces(cellsNode); +} + + +// Read any interfaces +// 1) interfaces between domains (fluid/solid, fluid/porosity) +// 2) PROSTAR baffles +// +void Foam::ccm::reader::readInterfaces +( + const ccmID& cellsNode +) +{ +#ifdef DEBUG_CCMIOREAD + Info<< "readInterfaces()" << endl; +#endif + + label nBaffleInterface = 0, nInterfaceTotal = 0; + CCMIOIndex size = 0, dims = 0; + + bafInterfaces_.clear(); + domInterfaces_.clear(); + + ccmID interfaceNode; + + if + ( + CCMIOGetEntity + ( + nullptr, + cellsNode, + kCCMIOInterfaces, + 0, + &interfaceNode + ) + == kCCMIONoErr + + && CCMIOGetOptInfo + ( + nullptr, + interfaceNode, + "FaceIds", + nullptr, + &size, + &dims, + nullptr + ) + == kCCMIONoErr + + && size > 0 && dims == 2 + ) + { + nInterfaceTotal = size; + } + else + { + return; + } + + // Get ProstarBaffles + // formatted as [ prostarId faceId1 faceId2 celltableId ] + if + ( + CCMIOGetOptInfo + ( + nullptr, + interfaceNode, + "ProstarBaffles", + nullptr, + &size, + nullptr, + nullptr + ) + == kCCMIONoErr + + && size > 0 + ) + { + // Be paranoid - force an integral value of 4 + nBaffleInterface = (size - size % 4) / 4; + } + + // Determine sizes + label nDomainInterface = nInterfaceTotal - nBaffleInterface; + + // Maximum dimension + List<int> mapData(max(2 * nInterfaceTotal, 4 * nBaffleInterface), -1); + + bafInterfaces_.setSize(nBaffleInterface); + domInterfaces_.setSize(nDomainInterface); + + // Face number mapping + label maxId = max(origFaceId_); + labelList toFoamFaces(invert(maxId+1, origFaceId_)); + + if (nBaffleInterface > 0) + { + mapData = -1; + + CCMIOReadOpt1i + ( + &(globalState_->error), + interfaceNode, + "ProstarBaffles", + mapData.begin(), + kCCMIOStart, + kCCMIOEnd + ); + assertNoError("problem reading interface 'ProstarBaffles'"); + + + // Copy/compress the desired entries (cannot use a SubList) + // Transform + // from [ prostarId faceId1 faceId2 celltableId ] + // to [ faceId1 faceId2 ] + for (label i=0; i < nBaffleInterface; ++i) + { + mapData[i*2] = mapData[i*4+1]; + mapData[i*2+1] = mapData[i*4+2]; + } + + for (label i=2*nBaffleInterface; i < 4*nBaffleInterface; ++i) + { + mapData[i] = -1; + } + + // Translate ccm faceId -> foam faceId + inplaceRenumber(toFoamFaces, mapData); + + forAll(bafInterfaces_, i) + { + bafInterfaces_[i][0] = mapData[i*2]; + bafInterfaces_[i][1] = mapData[i*2+1]; + } + } + + // Baffles are not domInterfaces, use hash to skip them + SubList<label> subMap(mapData, 2*nBaffleInterface); + labelHashSet hashedFace(subMap); + + mapData = -1; + + CCMIOReadOpt2i + ( + &(globalState_->error), + interfaceNode, + "FaceIds", + mapData.begin(), + kCCMIOStart, + kCCMIOEnd + ); + assertNoError("problem reading interface 'FaceIds'"); + + // Translate ccm faceId -> foam faceId + // newer version handles negatives indices + inplaceRenumber(toFoamFaces, mapData); + + nDomainInterface = 0; + for (label i=0; i < nInterfaceTotal; ++i) + { + label face0 = mapData[i*2]; + label face1 = mapData[i*2+1]; + + if + ( + !hashedFace.found(face0) + && !hashedFace.found(face1) + ) + { + domInterfaces_[nDomainInterface][0] = face0; + domInterfaces_[nDomainInterface][1] = face1; + ++nDomainInterface; + if (nDomainInterface >= domInterfaces_.size()) + { + break; + } + } + } + + // Truncate for extra safety + domInterfaces_.setSize(nDomainInterface); +} + + +// Read monitoring faces +// +void Foam::ccm::reader::readMonitoring +( + const ccmID& topoId +) +{ +#ifdef DEBUG_CCMIOREAD + Info<< "readMonitoring()" << endl; +#endif + +#ifdef WITH_MONITORING + CCMIONode topoNode, monitorParent; + CCMIONode monitorNode; + + // CCMIOID -> CCMIONODE + if + ( + CCMIOGetEntityNode + ( + nullptr, + topoId, + &topoNode + ) + == kCCMIONoErr + + // Get "/Meshes/FaceBasedTopology/MonitorBoundaryRegions" + && CCMIOGetNode + ( + nullptr, + topoNode, + "MonitorBoundaryRegions", + &monitorParent + ) + == kCCMIONoErr + ) + { + labelList toFoamFaces(invert(nFaces_+1, origFaceId_)); + + // Simulate CCMIONextEntity + for + ( + int index = 0; + CCMIOGetNextChildWithLabel + ( + nullptr, + monitorParent, + "boundaryFaces", + &index, + &monitorNode + ) == kCCMIONoErr; + /* nop */ + ) + { +#ifdef DEBUG_MONITORING + Info<< "index = " << index << endl; +#endif + + int nMonFaces = 0; + // Simulate EntitySize ? + CCMIOReadNodei + ( + nullptr, + monitorNode, + "NumFaces", + &nMonFaces + ); + + int ccmRegionId = ccmGetEntityIndex(monitorNode); + + ccmID mapId; + + int idVal; + CCMIOReadNodei + ( + nullptr, + monitorNode, + "MapId", + &idVal + ); + +#ifdef DEBUG_MONITORING + Info<< "monitoring mapId " << idVal + << " with nFaces = " << nMonFaces + << endl; +#endif + // Is it risky changing parents here? + CCMIOGetEntity + ( + nullptr, + (globalState_->root), + kCCMIOMap, + idVal, + &mapId + ); + + List<label> mapData(nMonFaces); + // mapData.setSize(nMonFaces); + // faceCells.setSize(nMonFaces); + + readMap + ( + mapId, + mapData + ); + +#ifdef DEBUG_MONITORING + Info<< "map: " << mapData << nl + << "toFoam: " << toFoamFaces + << endl; +#endif + + // Translate ccm faceId -> foam faceId + // newer version handles negatives indices + inplaceRenumber(toFoamFaces, mapData); + +#ifdef DEBUG_MONITORING + Info<< "map: " << mapData << nl + << "ccmRegionId: " << ccmRegionId << endl; +#endif + + Map<dictionary>::const_iterator + iter = boundaryRegion_.find(ccmRegionId); + + word zoneName; + if (iter != boundaryRegion_.end()) + { + iter().lookup("Label") >> zoneName; + } + else + { + zoneName = "monitoring_" + Foam::name(ccmRegionId); + } + + monitoringSets_.insert(zoneName, mapData); + + // CCMIONode subNode; + // + //- simulate ReadFaceCells with kCCMIOBoundaryFaces + // CCMIOGetNode(nullptr, childNode, "Cells", &subNode); + // CCMIORead1i(nullptr, subNode, faceCells.begin(), kCCMIOStart, kCCMIOEnd); + // + // Info << "cells: " << faceCells << endl; + } + } +#endif +} + + +// Move solid faces from Default_Boundary_Region -> Default_Boundary_Solid +void Foam::ccm::reader::juggleSolids() +{ + if (!option().keepSolid()) + { + return; + } + + // Find "Default_Boundary_Region" + label defaultBoundaryRegion = boundaryRegion_.findIndex + ( + defaultBoundaryName + ); + + // Find "Default_Boundary_Solid" + label defaultBoundarySolid = boundaryRegion_.findIndex + ( + defaultSolidBoundaryName + ); + + // Cannot do anything if Default_Boundary_Region does not exist + // or if Default_Boundary_Solid already exists + if + ( + defaultBoundaryRegion < 0 + || defaultBoundarySolid >= 0 + ) + { + return; + } + + // Identify solid cells + // ~~~~~~~~~~~~~~~~~~~~ + label nSolids = 0; + boolList solidCells(cellTableId_.size(), false); + { + Map<word> solidMap = cellTable_.solids(); + + forAll(cellTableId_, cellI) + { + if (solidMap.found(cellTableId_[cellI])) + { + solidCells[cellI] = true; + ++nSolids; + } + } + } + + if (!nSolids) + { + return; + } + + + // The corresponding Foam patch + const label patchIndex = findIndex(origBndId_, defaultBoundaryRegion); + const label nPatchFaces = patchSizes_[patchIndex]; + + labelList patchStarts(patchStartList(nInternalFaces_)); + label adjustPatch = 0; + for (label i = 0; i < nPatchFaces; ++i) + { + label faceI = patchStarts[patchIndex] + i; + label cellI = faceOwner_[faceI]; + + if (solidCells[cellI]) + { + ++adjustPatch; + } + } + + // No solid cells on the Default_Boundary_Region + if (!adjustPatch) + { + return; + } + + + // Insert Default_Boundary_Solid immediately after Default_Boundary_Region + // then we only need to adjust a single patch and can easily re-merge + // later + label nPatches = patchSizes_.size(); + patchStarts.setSize(nPatches+1, 0); + patchSizes_.setSize(nPatches+1, 0); + origBndId_.setSize(nPatches+1, 0); + + // make room for new entry + for (label i = nPatches; i > patchIndex; --i) + { + patchStarts[i] = patchStarts[i-1]; + patchSizes_[i] = patchSizes_[i-1]; + origBndId_[i] = origBndId_[i-1]; + } + + // Adjust start and sizes + patchSizes_[patchIndex] -= adjustPatch; + patchSizes_[patchIndex+1] = adjustPatch; + patchStarts[patchIndex+1] = patchStarts[patchIndex] + patchSizes_[patchIndex]; + + origBndId_[patchIndex+1] = boundaryRegion_.append + ( + dictionary + ( + IStringStream + ( + "BoundaryType wall;" + "Label " + word(defaultSolidBoundaryName) + ";" + )() + ) + ); + + label fluidFace = patchStarts[patchIndex]; + label solidFace = patchStarts[patchIndex+1]; + + labelList oldToNew(identity(nFaces_)); + for (label i = 0; i < nPatchFaces; ++i) + { + label faceI = patchStarts[patchIndex] + i; + label cellI = faceOwner_[faceI]; + + if (solidCells[cellI]) + { + oldToNew[faceI] = solidFace++; + } + else + { + oldToNew[faceI] = fluidFace++; + } + } + + // Re-order faces, owners/neighbours + inplaceReorder(oldToNew, faces_); + inplaceReorder(oldToNew, faceOwner_); + inplaceReorder(oldToNew, faceNeighbour_); + inplaceReorder(oldToNew, origFaceId_); + + renumberInterfaces(oldToNew); +} + + +// In CCM, separate mesh domains are used for fluid/porous/solid +// Thus the fluid/porous/solid cells correspond uniquely to a face owner +void Foam::ccm::reader::removeUnwanted() +{ + // Identify fluid/porous/solid cells for removal + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + label nRemove = 0; + boolList removeCells(cellTableId_.size(), false); + + { + Map<word> fluidMap = cellTable_.fluids(); + Map<word> porousMap = selectPorous(cellTable_); + Map<word> solidMap = cellTable_.solids(); + Map<word> removeMap; + + forAll(cellTableId_, cellI) + { + label tableId = cellTableId_[cellI]; + + if + ( + porousMap.found(tableId) + ? !option().keepPorous() + : fluidMap.found(tableId) + ? !option().keepFluid() + : solidMap.found(tableId) + ? !option().keepSolid() + : false + ) + { + removeCells[cellI] = true; + ++nRemove; + removeMap.set(tableId, cellTable_.name(tableId)); + } + } + + if (nRemove) + { + Map<word> keepMap; + + forAllConstIter(Map<dictionary>, cellTable_, iter) + { + const label tableId = iter.key(); + if (!removeMap.found(tableId)) + { + keepMap.set(tableId, cellTable_.name(tableId)); + } + } + + Info<<"remove "<< nRemove << " cells in " + << removeMap.size() << " unwanted cellZone(s)" << nl; + + forAllConstIter(Map<word>, removeMap, iter) + { + Info<< " zone " << iter.key() << " : "<< iter() << nl; + } + + Info<<"retain "<< (nCells_ - nRemove) << " cells in " + << keepMap.size() << " cellZone(s)" << nl; + + forAllConstIter(Map<word>, keepMap, iter) + { + Info<< " zone " << iter.key() << " : "<< iter() << nl; + } + } + } + + if (!nRemove) + { + return; + } + + // Remove all faces where the owner corresponds to a removed cell + // Adjust the nInternalFaces and patch sizes accordingly + label adjustInternal = 0; + labelList adjustPatchSize(patchSizes_.size(), 0); + + label newFaceI = 0; + label oldFaceI = nFaces_ - 1; + labelList oldToNew(nFaces_, -1); + for (label faceI = 0; faceI < nFaces_; ++faceI) + { + label cellI = faceOwner_[faceI]; + if (removeCells[cellI]) + { + if (faceI < nInternalFaces_) + { + ++adjustInternal; + } + else + { + // need to adjust the patch sizes + label beg = nInternalFaces_; + forAll(patchSizes_, patchI) + { + label end = beg + patchSizes_[patchI]; + + if (faceI >= beg && faceI < end) + { + ++adjustPatchSize[patchI]; + break; + } + + beg = end; + } + } + + // Put discarded faces at the end of the list + oldToNew[faceI] = oldFaceI--; + } + else + { + if (newFaceI != faceI) + { + faces_[newFaceI] = faces_[faceI]; + faceOwner_[newFaceI] = faceOwner_[faceI]; + faceNeighbour_[newFaceI] = faceNeighbour_[faceI]; + origFaceId_[newFaceI] = origFaceId_[faceI]; + } + + // New position for the face + oldToNew[faceI] = newFaceI++; + } + } + + nFaces_ = newFaceI; + + // Redimension + faces_.setSize(nFaces_); + faceOwner_.setSize(nFaces_); + faceNeighbour_.setSize(nFaces_); + origFaceId_.setSize(nFaces_); + + // Adjust internal faces and patch sizes + + nInternalFaces_ -= adjustInternal; + forAll(patchSizes_, patchI) + { + patchSizes_[patchI] -= adjustPatchSize[patchI]; + } + + renumberInterfaces(oldToNew); + + // Renumber cells + label nCell = 0; + oldToNew.setSize(nCells_, -1); + for (label cellI = 0; cellI < nCells_; ++cellI) + { + if (!removeCells[cellI]) + { + if (nCell != cellI) + { + origCellId_[nCell] = origCellId_[cellI]; + cellTableId_[nCell] = cellTableId_[cellI]; + } + oldToNew[cellI] = nCell; + ++nCell; + } + } + + inplaceRenumber(oldToNew, faceOwner_); + inplaceRenumber(oldToNew, faceNeighbour_); + + // Redimension + nCells_ = nCell; + origCellId_.setSize(nCells_); + cellTableId_.setSize(nCells_); + + + // Remove unused points - adjust points, faces accordingly + oldToNew.setSize(nPoints_); + oldToNew = -1; + + // Mark up all the used points + forAll(faces_, faceI) + { + const labelList& facePoints = faces_[faceI]; + + forAll(facePoints, ptI) + { + ++oldToNew[facePoints[ptI]]; + } + } + + label nPointUsed = 0; + forAll(oldToNew, ptI) + { + if (oldToNew[ptI] >= 0) + { + oldToNew[ptI] = nPointUsed; + if (ptI != nPointUsed) + { + points_[nPointUsed] = points_[ptI]; + } + ++nPointUsed; + } + } + + nPoints_ = nPointUsed; + points_.setSize(nPoints_); + + forAll(faces_, faceI) + { + inplaceRenumber(oldToNew, faces_[faceI]); + } + + // Report sizes + printSizes(); +} + + +void Foam::ccm::reader::validateInterface +( + List<labelPair>& lst +) +{ + label nElem = 0; + forAll(lst, elemI) + { + label face0 = lst[elemI][0]; + label face1 = lst[elemI][1]; + + if (face0 < nFaces_ && face1 < nFaces_) + { + if (nElem != elemI) + { + lst[nElem][0] = face0; + lst[nElem][1] = face1; + } + ++nElem; + } + } + lst.setSize(nElem); +} + + +void Foam::ccm::reader::renumberInterfaces +( + const labelList& oldToNew +) +{ + forAll(domInterfaces_, elemI) + { + domInterfaces_[elemI][0] = oldToNew[domInterfaces_[elemI][0]]; + domInterfaces_[elemI][1] = oldToNew[domInterfaces_[elemI][1]]; + } + + forAll(bafInterfaces_, elemI) + { + bafInterfaces_[elemI][0] = oldToNew[bafInterfaces_[elemI][0]]; + bafInterfaces_[elemI][1] = oldToNew[bafInterfaces_[elemI][1]]; + } + + validateInterface(domInterfaces_); + validateInterface(bafInterfaces_); +} + + +// +// 1) remove interfaces between domains (fluid/porosity; fluid/solid, etc) +// 2) reorganize baffle interfaces into [0-N/2; N/2-N] lists at the beginning +// of the corresponding patch +// +void Foam::ccm::reader::cleanupInterfaces() +{ + validateInterface(bafInterfaces_); + validateInterface(domInterfaces_); + + if (bafInterfaces_.size() <= 0 && domInterfaces_.size() <= 0) + { + Info<<"0 baffle interface pairs" << endl; + Info<<"0 domain interface pairs" << endl; + return; + } + +#ifdef DEBUG_BAFFLES + Info<< "baffle Interfaces " << bafInterfaces_ << nl + << "domain Interfaces " << domInterfaces_ << nl + << "nCells:" << nCells_ << nl + << "nFaces:" << nFaces_ << nl + << "patchSizes:" << patchSizes_ << nl + << "nInternalFaces:" << nInternalFaces_ << endl; + + forAll(domInterfaces_, elemI) + { + label face0 = domInterfaces_[elemI][0]; + label face1 = domInterfaces_[elemI][1]; + + Info<< "interface [" << elemI << "] = " + << face0 << " - " << face1 << " own/neigh = " + << faceOwner_[face0] << "/" << faceNeighbour_[face0] << " " + << faceOwner_[face1] << "/" << faceNeighbour_[face1] << endl; + } +#endif + + // Only reorder faces that need it + labelList oldToNew(nFaces_, -1); + + // - move side0 face from domInterfaces to join the internal faces + // - move the redundant side1 to the end of the list for later deletion + label begOfList = nInternalFaces_; + label endOfList = nFaces_ - 1; + + // The patch sizes (and the start) will definitely change + const labelList origPatchStarts(patchStartList(nInternalFaces_)); + labelList adjustPatchSize(patchSizes_.size(), 0); + labelList bafflePatchCount(patchSizes_.size(), 0); + + // The new dimensions after merging the domain interfaces: + nInternalFaces_ += domInterfaces_.size(); + nFaces_ -= domInterfaces_.size(); + + Info<< domInterfaces_.size() << " domain interface pairs"; + if (domInterfaces_.size()) + { + Info<<" to merge" << endl; + printSizes(); + } + else + { + Info<< endl; + } + + forAll(domInterfaces_, elemI) + { + label face0 = domInterfaces_[elemI][0]; + label face1 = domInterfaces_[elemI][1]; + + oldToNew[face0] = begOfList++; + oldToNew[face1] = endOfList--; // End of list for truncationx + + // face0 gets a new neighbour, face1 loses its owner + faceNeighbour_[face0] = faceOwner_[face1]; + faceOwner_[face1] = -1; + + // Need to adjust the patch sizes + forAll(patchSizes_, patchI) + { + label beg = origPatchStarts[patchI]; + label end = beg + patchSizes_[patchI]; + + if (face0 >= beg && face0 < end) + { + ++adjustPatchSize[patchI]; + } + if (face1 >= beg && face1 < end) + { + ++adjustPatchSize[patchI]; + } + } + } + + // Count the number of baffles per patch + forAll(bafInterfaces_, elemI) + { + label face0 = bafInterfaces_[elemI][0]; + label face1 = bafInterfaces_[elemI][1]; + + forAll(patchSizes_, patchI) + { + label beg = origPatchStarts[patchI]; + label end = beg + patchSizes_[patchI]; + + if (face0 >= beg && face0 < end) + { + ++bafflePatchCount[patchI]; + } + if (face1 >= beg && face1 < end) + { + ++bafflePatchCount[patchI]; + } + } + } + + + if (option().removeBaffles()) + { + // The new dimensions after merging the baffles: + nInternalFaces_ += bafInterfaces_.size(); + nFaces_ -= bafInterfaces_.size(); + } + + Info<< bafInterfaces_.size() << " baffle interface pairs"; + if (bafInterfaces_.size()) + { + if (option().removeBaffles()) + { + Info<< " to merge" << endl; + printSizes(); + } + else + { + Info<< " to be sorted" << endl; + } + } + else + { + Info<< endl; + } + + if (option().removeBaffles()) + { + forAll(bafInterfaces_, elemI) + { + label face0 = bafInterfaces_[elemI][0]; + label face1 = bafInterfaces_[elemI][1]; + + oldToNew[face0] = begOfList++; + oldToNew[face1] = endOfList--; // End of list for truncation + + // face0 gets a new neighbour, face1 loses its owner + faceNeighbour_[face0] = faceOwner_[face1]; + faceOwner_[face1] = -1; + } + + + // Boundary faces continue from the new nInternalFaces + label pos = nInternalFaces_; + forAll(patchSizes_, patchI) + { + label beg = origPatchStarts[patchI]; + label end = beg + patchSizes_[patchI]; + + // Fill in values for the remainder of the boundary patch + for (label faceI = beg; faceI < end; ++faceI) + { + if (oldToNew[faceI] < 0) + { + oldToNew[faceI] = pos; + ++pos; + } + } + } + + // Baffles have been resolved - remove last traces + bafInterfaces_.clear(); + } + else + { + // This check is probably unnecessary + forAll(bafflePatchCount, patchI) + { + if (bafflePatchCount[patchI] % 2) + { + Info<< "WARNING: patch " << patchI + << " has an uneven number of baffles (" + << bafflePatchCount[patchI] << ") expect strange results" + << endl; + } + } + + + // Reordered faces continue from the new nInternalFaces + label pos = nInternalFaces_; + forAll(patchSizes_, patchI) + { + const label beg = origPatchStarts[patchI]; + const label end = beg + patchSizes_[patchI]; + + const label nsize = bafflePatchCount[patchI]; + if (nsize > 0) + { + // Reorganize baffle interfaces into [0-N/2; N/2-N] lists + // at the beginning of the corresponding patch + const label nsizeby2 = (nsize - nsize % 2) / 2; + label nsorted = 0; + + // Renumber the normal (baffle) interfaces + forAll(bafInterfaces_, elemI) + { + const label face0 = bafInterfaces_[elemI][0]; + const label face1 = bafInterfaces_[elemI][1]; + + if + ( + (face0 >= beg && face0 < end) + || (face1 >= beg && face1 < end) + ) + { + oldToNew[face0] = pos + nsorted; + oldToNew[face1] = pos + nsorted + nsizeby2; + + // Mark destination of the faces, but cannot renumber yet + // use negative to potential overlap with other patch regions + bafInterfaces_[elemI][0] = -oldToNew[face0]; + bafInterfaces_[elemI][1] = -oldToNew[face1]; + + ++nsorted; + } + } + pos += 2*nsorted; + } + + // Fill in values for the remainder of the boundary patch + for (label faceI = beg; faceI < end; ++faceI) + { + if (oldToNew[faceI] < 0) + { + oldToNew[faceI] = pos; + ++pos; + } + } + } + + // Finalize new numbers for the normal (baffle) interfaces + forAll(bafInterfaces_, elemI) + { + bafInterfaces_[elemI][0] = abs(bafInterfaces_[elemI][0]); + bafInterfaces_[elemI][1] = abs(bafInterfaces_[elemI][1]); + } + } + +#ifdef DEBUG_BAFFLES + Info<< "remap with " << oldToNew << nl + << "owners:" << faceOwner_ << nl + << "neighbours:" << faceNeighbour_ << nl + << endl; +#endif + + // Re-order faces, owners/neighbours + inplaceReorder(oldToNew, faces_); + inplaceReorder(oldToNew, faceOwner_); + inplaceReorder(oldToNew, faceNeighbour_); + inplaceReorder(oldToNew, origFaceId_); + + if (monitoringSets_.size()) + { +#ifdef WITH_MONITORING + // Modify oldToNew mapping to account for monitoring faces that + // coincided with a domain interface + // + // TODO - should modify flip map as well + forAll(domInterfaces_, elemI) + { + label face0 = domInterfaces_[elemI][0]; + label face1 = domInterfaces_[elemI][1]; + oldToNew[face1] = oldToNew[face0]; + } + +// Info<< "nInternalFaces " << nInternalFaces_ << nl +// << "oldToNew (internal) " +// << SubList<label>(oldToNew, nInternalFaces_) +// << nl +// << "oldToNew (extern) " +// << SubList<label>(oldToNew, nFaces_ - nInternalFaces_, nInternalFaces_) +// << endl; + + forAllIter(HashTable<labelList>, monitoringSets_, iter) + { + inplaceRenumber(oldToNew, iter()); + } +#endif + } + + // We can finally drop this information now + domInterfaces_.clear(); + + // Truncate lists + faces_.setSize(nFaces_); + faceOwner_.setSize(nFaces_); + faceNeighbour_.setSize(nFaces_); + origFaceId_.setSize(nFaces_); + + // Remove empty patches: + + // Fix patch sizes: + oldToNew.setSize(patchSizes_.size()); + oldToNew = -1; + + label nPatches = 0; + forAll(patchSizes_, patchI) + { + patchSizes_[patchI] -= adjustPatchSize[patchI]; + if (option().removeBaffles()) + { + patchSizes_[patchI] -= bafflePatchCount[patchI]; + } + + if (patchSizes_[patchI]) + { + oldToNew[patchI] = nPatches++; + } + } + + inplaceReorder(oldToNew, patchSizes_); + inplaceReorder(oldToNew, origBndId_); + + patchSizes_.setSize(nPatches); + origBndId_.setSize(nPatches); + +#ifdef DEBUG_BAFFLES + Info<< "nCells:" << nCells_ << nl + << "nFaces:" << nFaces_ << nl + << "PatchSizes:" << patchSizes_ << nl + << "nInternalFaces:" << nInternalFaces_ << nl + << endl; +#endif +} + + +// +// Merge STARCCM in-place interfaces +// +void Foam::ccm::reader::mergeInplaceInterfaces() +{ + if (interfaceDefinitions_.empty()) + { + return; + } + if (!option().mergeInterfaces()) + { + Info<< interfaceDefinitions_.size() << " interface definitions" + << " - leaving unmerged" << endl; + return; + } + + // List of patch pairs that are interfaces + DynamicList<labelPair> interfacePatches(interfaceDefinitions_.size()); + + forAll(interfaceDefinitions_, interI) + { + const interfaceEntry& ifentry = interfaceDefinitions_[interI]; + + labelPair patchPair + ( + findIndex(origBndId_, ifentry.bnd0), + findIndex(origBndId_, ifentry.bnd1) + ); + + if (patchPair[0] == patchPair[1] || patchPair[0] < 0 || patchPair[1] < 0) + { + // This should not happen + Info<<"Warning : bad interface " << interI << " " << ifentry + <<" on patches " << patchPair << endl; + } + else if + ( + patchSizes_[patchPair[0]] != patchSizes_[patchPair[1]] + || patchSizes_[patchPair[0]] == 0 + || patchSizes_[patchPair[1]] == 0 + ) + { + Info<<"Warning : skip interface " << interI << " " << ifentry + <<" on patches " << patchPair << nl + <<" has zero or different number of faces: (" + << patchSizes_[patchPair[0]] << " " << patchSizes_[patchPair[0]] << ")" + << endl; + } + else + { + interfacePatches.append(patchPair); + } + } + + if (interfacePatches.empty()) + { + return; + } + + + // Local point mapping + labelList mergedPointMap; + + // Global remapping + labelList oldToNew(identity(points_.size())); + + const labelList origPatchStarts(patchStartList(nInternalFaces_)); + + label nMergedTotal = 0; + + // Markup points to merge + PackedBoolList whichPoints(points_.size()); + + Info<< "interface merge points (tol=" << option().mergeTol() << "):" << endl; + + DynamicList<label> interfacesToMerge(interfacePatches.size()); + forAll(interfacePatches, interI) + { + const label patch0 = interfacePatches[interI][0]; + const label patch1 = interfacePatches[interI][1]; + const label nPatch0Faces = patchSizes_[patch0]; + const label nPatch1Faces = patchSizes_[patch1]; + + // Markup points to merge + whichPoints.reset(); + for (label local0FaceI = 0; local0FaceI < nPatch0Faces; ++local0FaceI) + { + const face& f = faces_[origPatchStarts[patch0] + local0FaceI]; + + forAll(f, fp) + { + // Simultaneously account for previous point merges + whichPoints.set(oldToNew[f[fp]]); + } + } + for (label local1FaceI = 0; local1FaceI < nPatch1Faces; ++local1FaceI) + { + const face& f = faces_[origPatchStarts[patch1] + local1FaceI]; + + forAll(f, fp) + { + // Simultaneously account for previous point merges + whichPoints.set(oldToNew[f[fp]]); + } + } + + // The global addresses + labelList addr(whichPoints.used()); + + const UIndirectList<point> pointsToMerge(points_, addr); + + label nMerged = mergePoints + ( + true, + pointsToMerge, + option().mergeTol(), + false, + mergedPointMap + ); + + Info<< " patch " << patch0 << ", " << patch1 << ": " + << nMerged << " from " << pointsToMerge.size() << " points" + << endl; + + if (nMerged) + { + // Transcribe local to global addressing + forAll(mergedPointMap, lookupI) + { + oldToNew[addr[lookupI]] = addr[mergedPointMap[lookupI]]; + } + + interfacesToMerge.append(interI); + nMergedTotal += nMerged; + } + } + + + // + // Nothing to do + // + if (!nMergedTotal) + { + return; + } + + // Update point references to account for point merge: + forAll(faces_, faceI) + { + inplaceRenumber(oldToNew, faces_[faceI]); + } + + // Determine which points are actually in use: + oldToNew.setSize(nPoints_); + oldToNew = -1; + + // Mark up all the used points + forAll(faces_, faceI) + { + const labelList& facePoints = faces_[faceI]; + + forAll(facePoints, ptI) + { + ++oldToNew[facePoints[ptI]]; + } + } + + label nPointUsed = 0; + forAll(oldToNew, ptI) + { + if (oldToNew[ptI] >= 0) + { + oldToNew[ptI] = nPointUsed; + if (ptI != nPointUsed) + { + points_[nPointUsed] = points_[ptI]; + } + ++nPointUsed; + } + } + + // Info<< "merge " << nMergedTotal << " points from " + // << nPoints_ << " to " << nPointUsed << endl; + + nPoints_ = nPointUsed; + points_.setSize(nPoints_); + + forAll(faces_, faceI) + { + inplaceRenumber(oldToNew, faces_[faceI]); + } + + + // + // Merge the faces as well + // + Info<< "interface merge faces:" << endl; + + nMergedTotal = 0; + labelList adjustPatchSize(patchSizes_.size(), 0); + forAll(interfacesToMerge, mergeI) + { + const label patch0 = interfacePatches[interfacesToMerge[mergeI]][0]; + const label patch1 = interfacePatches[interfacesToMerge[mergeI]][1]; + + labelList faceAddr0(patchSizes_[patch0]); + labelList faceAddr1(patchSizes_[patch1]); + + forAll(faceAddr0, localFaceI) + { + faceAddr0[localFaceI] = origPatchStarts[patch0] + localFaceI; + } + forAll(faceAddr1, localFaceI) + { + faceAddr1[localFaceI] = origPatchStarts[patch1] + localFaceI; + } + + if (faceAddr0.size() != faceAddr1.size()) + { + // This should not occur, we avoided the same thing above + continue; + } + + // Improve comparision speed by sorting by distance + SortableList<scalar> pts0MagSqr + ( + magSqr + ( + uindirectPrimitivePatch + ( + UIndirectList<face> + ( + faces_, + faceAddr0 + ), + points_ + ).faceCentres() + ) + ); + SortableList<scalar> pts1MagSqr + ( + magSqr + ( + uindirectPrimitivePatch + ( + UIndirectList<face> + ( + faces_, + faceAddr1 + ), + points_ + ).faceCentres() + ) + ); + + label nMerged = 0; + + // Record which faces failed to merge - use slower ad hoc merging + labelHashSet failed0, failed1; + forAll(pts0MagSqr, sortI) + { + const label face0I = faceAddr0[pts0MagSqr.indices()[sortI]]; + const label face1I = faceAddr1[pts1MagSqr.indices()[sortI]]; + + // This is what we expect + if (face::compare(faces_[face0I], faces_[face1I])) + { + ++nMerged; + + // Moved from boundary patch to internal patch + ++adjustPatchSize[patch0]; + ++adjustPatchSize[patch1]; + + if (faceOwner_[face0I] < faceOwner_[face1I]) + { + // keep 0, discard 1 + faceNeighbour_[face0I] = faceOwner_[face1I]; + faceNeighbour_[face1I] = faceOwner_[face1I] = -1; + } + else + { + // keep 1, discard 0 + faceNeighbour_[face1I] = faceOwner_[face0I]; + faceNeighbour_[face0I] = faceOwner_[face0I] = -1; + } + } + else + { + failed0.set(face0I); + failed1.set(face1I); + } + } + + // Perhaps some sorting issues, recheck + if (failed0.size()) + { + // Note which one were successful + labelHashSet done(failed0.size()); + + forAllConstIter(labelHashSet, failed0, iter0) + { + const label face0I = iter0.key(); + + forAllConstIter(labelHashSet, failed1, iter1) + { + const label face1I = iter1.key(); + + // This is what we expect + if (face::compare(faces_[face0I], faces_[face1I])) + { + ++nMerged; + + // Moved from boundary patch to internal patch + ++adjustPatchSize[patch0]; + ++adjustPatchSize[patch1]; + + if (faceOwner_[face0I] < faceOwner_[face1I]) + { + // keep 0, discard 1 + faceNeighbour_[face0I] = faceOwner_[face1I]; + faceNeighbour_[face1I] = faceOwner_[face1I] = -1; + } + else + { + // keep 1, discard 0 + faceNeighbour_[face1I] = faceOwner_[face0I]; + faceNeighbour_[face0I] = faceOwner_[face0I] = -1; + } + + failed1.erase(face1I); // Never check again + done.set(face0I); // Mark as done + break; // Stop looking + } + } + } + + // Transfer to note how many were successful + failed0 = done; + } + + Info<< " patch " << patch0 << ", " << patch1 << ": " + << nMerged << " from " << faceAddr0.size() << " faces"; + + if (failed0.size()) + { + Info<< " (" << failed0.size() << " merged ad hoc)"; + } + Info<< endl; + + + nMergedTotal += nMerged; + } + + + // Nothing to do + if (!nMergedTotal) + { + return; + } + + // Info<< "merge " << nMergedTotal << " faces from " + // << nFaces_ << " to " << (nFaces_ - nMergedTotal) << endl; + + oldToNew.setSize(nFaces_); + oldToNew = -1; + + // Remaining external faces will be shifted here: + label extFaceI = nInternalFaces_ + nMergedTotal; + + // Start over + nInternalFaces_ = 0; + label nFaceUsed = 0; + for (label faceI = 0; faceI < nFaces_; ++faceI) + { + if (faceOwner_[faceI] != -1) + { + if (faceNeighbour_[faceI] != -1) + { + // Internal face + oldToNew[faceI] = nInternalFaces_; + ++nInternalFaces_; + ++nFaceUsed; + } + else + { + // External face + oldToNew[faceI] = extFaceI; + ++extFaceI; + ++nFaceUsed; + } + } + } + + if (nFaceUsed != extFaceI) + { + FatalErrorIn("ccm::reader::mergeInplaceInterfaces") + << "coding error: used " << nFaceUsed + << " faces, but expected to use " << extFaceI << " faces" + << exit(FatalError); + } + + // Re-order faces, owners/neighbours + inplaceReorder(oldToNew, faces_, true); + inplaceReorder(oldToNew, faceOwner_, true); + inplaceReorder(oldToNew, faceNeighbour_, true); + inplaceReorder(oldToNew, origFaceId_, true); + + nFaces_ = nFaceUsed; + + faces_.setSize(nFaces_); + faceOwner_.setSize(nFaces_); + faceNeighbour_.setSize(nFaces_); + origFaceId_.setSize(nFaces_); + + // Fix patch sizes: + oldToNew.setSize(patchSizes_.size()); + oldToNew = -1; + + label nPatches = 0; + forAll(patchSizes_, patchI) + { + patchSizes_[patchI] -= adjustPatchSize[patchI]; + if (patchSizes_[patchI]) + { + oldToNew[patchI] = nPatches++; + } + } + + inplaceReorder(oldToNew, patchSizes_); + inplaceReorder(oldToNew, origBndId_); + + patchSizes_.setSize(nPatches); + origBndId_.setSize(nPatches); + + // Report we are done + Info<< ".." << endl; +} + + +// +// Re-order mesh into Foam convention +// - owner < neighbour +// - face vertices such that normal points away from owner +// - order faces: upper-triangular for internal faces; +// boundary faces after internal faces +// +void Foam::ccm::reader::reorderMesh() +{ + // Set owner/neighbour so owner < neighbour + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + forAll(faceOwner_, faceI) + { + label nbr = faceNeighbour_[faceI]; + label own = faceOwner_[faceI]; + + if (nbr >= cellTableId_.size() || own >= cellTableId_.size()) + { + FatalErrorIn("ccm::reader::reorderMesh") + << "face:" << faceI + << " nbr:" << nbr + << " own:" << own + << " nCells:" << cellTableId_.size() + << exit(FatalError); + } + + if (nbr >= 0 && nbr < own) + { + faceOwner_[faceI] = faceNeighbour_[faceI]; + faceNeighbour_[faceI] = own; + faces_[faceI] = faces_[faceI].reverseFace(); + } + + // And check the face + const face& f = faces_[faceI]; + + forAll(f, fp) + { + if (f[fp] < 0 || f[fp] >= points_.size()) + { + FatalErrorIn("ccm::reader::reorderMesh") + << "face:" << faceI << " f:" << f + << abort(FatalError); + } + } + } + + // Do upper-triangular ordering + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + labelList oldToNew(faceOwner_.size(), -1); + + // Create cells (inverse of face-to-cell addressing) + cellList cellFaceAddr; + primitiveMesh::calcCells + ( + cellFaceAddr, + faceOwner_, + faceNeighbour_, + nCells_ + ); + + label newFaceI = 0; + forAll(cellFaceAddr, cellI) + { + const labelList& cFaces = cellFaceAddr[cellI]; + SortableList<label> nbr(cFaces.size(), -1); + + forAll(cFaces, i) + { + label faceI = cFaces[i]; + label nbrCellI = faceNeighbour_[faceI]; + + if (nbrCellI >= 0) + { + // Internal face. Get cell on other side + if (nbrCellI == cellI) + { + nbrCellI = faceOwner_[faceI]; + } + + // cellI is master + if (cellI < nbrCellI) + { + nbr[i] = nbrCellI; + } + } + } + + nbr.sort(); + + forAll(nbr, i) + { + if (nbr[i] >= 0) + { + oldToNew[cFaces[nbr.indices()[i]]] = newFaceI++; + } + } + } + + // Reorder faces accordingly + inplaceReorder(oldToNew, faces_); + inplaceReorder(oldToNew, faceOwner_); + inplaceReorder(oldToNew, faceNeighbour_); + inplaceReorder(oldToNew, origFaceId_); + + forAllIter(HashTable<labelList>, monitoringSets_, iter) + { + inplaceRenumber(oldToNew, iter()); + labelList &lst = iter(); + + // disallow monitoring on boundaries + label nElem = 0; + forAll(lst, i) + { + if (lst[i] >= 0 && lst[i] < nInternalFaces_) + { + if (nElem != i) + { + lst[nElem] = lst[i]; + } + nElem++; + } + } + + if (nElem) + { + lst.setSize(nElem); + } + else + { + Info << "remove monitor " << iter.key() << endl; + monitoringSets_.erase(iter); + } + } +} + + +// Attach patches +// +// - patchSizes_ : obvious +// - origBndId_ : lookup for patch name/type +// +void Foam::ccm::reader::addPatches +( + polyMesh& mesh +) const +{ + // Create patches + // use patch types to determine what Foam types to generate + List<polyPatch*> newPatches(origBndId_.size()); + + label meshFaceI = nInternalFaces_; + wordHashSet hashedNames(origBndId_.size()); + + // lookup patch names/types from the problem description + // provide some fallback vlues + forAll(newPatches, patchI) + { + word fallbackName("patch" + Foam::name(patchI)); + word patchName; + word patchType; + + Map<dictionary>::const_iterator + citer = boundaryRegion_.find(origBndId_[patchI]); + + if (citer != boundaryRegion_.end()) + { + citer().lookup("Label") >> patchName; + citer().lookup("BoundaryType") >> patchType; + } + else + { + patchName = fallbackName; + patchType = "patch"; + } + + // Avoid duplicate names + // - don't bother checking if the modified name is also a duplicate + if (hashedNames.found(patchName)) + { + Info<< "renamed patch " << patchName << " to "; + patchName = fallbackName + "_" + patchName; + Info<< patchName << endl; + } + hashedNames.insert(patchName); + + Info<< "patch " << patchI + << " (start: " << meshFaceI << " size: " << patchSizes_[patchI] + << ") name: " << patchName + << endl; + + if (patchType == "wall") + { + newPatches[patchI] = + new wallPolyPatch + ( + patchName, + patchSizes_[patchI], + meshFaceI, + patchI, + mesh.boundaryMesh(), + patchType + ); + } + else if (patchType == "symmetry") + { + newPatches[patchI] = + new symmetryPolyPatch + ( + patchName, + patchSizes_[patchI], + meshFaceI, + patchI, + mesh.boundaryMesh(), + patchType + ); + } + else if (patchType == "empty") + { + // Note: not ccm name, may have been introduced by us + newPatches[patchI] = + new emptyPolyPatch + ( + patchName, + patchSizes_[patchI], + meshFaceI, + patchI, + mesh.boundaryMesh(), + patchType + ); + } + else + { + // All other ccm types become straight polyPatch: + // 'inlet', 'outlet', 'pressure'. + newPatches[patchI] = + new polyPatch + ( + patchName, + patchSizes_[patchI], + meshFaceI, + patchI, + mesh.boundaryMesh(), + patchType + ); + } + + meshFaceI += patchSizes_[patchI]; + } + + if (meshFaceI != mesh.nFaces()) + { + FatalErrorIn("ccm::reader::addPatches(polyMesh& mesh)") + << "meshFaceI:" << meshFaceI << " nFaces:" << mesh.nFaces() + << abort(FatalError); + } + + mesh.addPatches(newPatches); +} + + + +// Attach faceZones based on the monitoring boundary conditions +void Foam::ccm::reader::addFaceZones +( + polyMesh& mesh +) const +{ + label nZone = monitoringSets_.size(); + mesh.faceZones().setSize(nZone); + + if (!nZone) + { + return; + } + + nZone = 0; + forAllConstIter(HashTable<labelList>, monitoringSets_, iter) + { + Info<< "faceZone " << nZone + << " (size: " << iter().size() << ") name: " + << iter.key() << endl; + + mesh.faceZones().set + ( + nZone, + new faceZone + ( + iter.key(), + iter(), + boolList(iter().size(), false), + nZone, + mesh.faceZones() + ) + ); + + nZone++; + } + + mesh.faceZones().writeOpt() = IOobject::AUTO_WRITE; + warnDuplicates("faceZones", mesh.faceZones().names()); +} + + +// Remove most of the ccm-specific information with the exception of information +// auxiliary to the normal polyMesh: +// (cellTableId_, origCellId_, origFaceId_, interfaces_, ...) +void Foam::ccm::reader::clearGeom() +{ + // allow re-reading the file + if (geometryStatus_ == OKAY || geometryStatus_ == READ) + { + geometryStatus_ = UNKNOWN; + } + + points_.clear(); + faces_.clear(); + faceOwner_.clear(); + faceNeighbour_.clear(); + + origBndId_.clear(); + patchSizes_.clear(); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +Foam::autoPtr<Foam::polyMesh> Foam::ccm::reader::mesh +( + const objectRegistry& registry, + const fileName& remappingDictName +) +{ + if (!readGeometry()) + { + return autoPtr<polyMesh>(); + } + + // merge cellTable and rename boundaryRegion + remapMeshInfo(registry, remappingDictName); + + // Construct polyMesh + // ~~~~~~~~~~~~~~~~~~ + autoPtr<polyMesh> mesh + ( + new polyMesh + ( + IOobject + ( + polyMesh::defaultRegion, + "constant", + registry + ), + xferMove(points_), + xferMove(faces_), + xferMove(faceOwner_), + xferMove(faceNeighbour_) + ) + ); + + addPatches(mesh()); + + // Attach cellZones based on the cellTable Id + // any other values can be extracted later from the cellTable dictionary + cellTable_.addCellZones(mesh(), cellTableId_); + warnDuplicates("cellZones", mesh().cellZones().names()); + + addFaceZones(mesh()); + + warnDuplicates("boundaries", mesh().boundaryMesh().names()); + clearGeom(); + + return mesh; +} + + +// ************************************************************************* // diff --git a/src/conversion/ccm/reader/ccmReaderOptions.C b/src/conversion/ccm/reader/ccmReaderOptions.C new file mode 100644 index 0000000000000000000000000000000000000000..c6bfe87d7dc6413818aeb0a5d3f50f7883073a66 --- /dev/null +++ b/src/conversion/ccm/reader/ccmReaderOptions.C @@ -0,0 +1,174 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*----------------------------------------------------------------------------*/ + +#include "ccmReader.H" + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::ccm::reader::options::options() +: + keepFluid_(true), + keepPorous_(true), + keepSolid_(true), + mergeInterfaces_(false), + renameInterfaces_(true), + combineBoundaries_(false), + removeBaffles_(false), + useNumberedNames_(false), + mergeTol_(0.05e-3), + undefScalar_(NAN) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::ccm::reader::options::keepFluid() const +{ + return keepFluid_; +} + + +bool Foam::ccm::reader::options::keepPorous() const +{ + return keepPorous_; +} + + +bool Foam::ccm::reader::options::keepSolid() const +{ + return keepSolid_; +} + + +bool Foam::ccm::reader::options::keptSomeRegion() const +{ + return keepFluid_ || keepPorous_ || !keepSolid_; +} + + +bool Foam::ccm::reader::options::mergeInterfaces() const +{ + return mergeInterfaces_; +} + + +bool Foam::ccm::reader::options::renameInterfaces() const +{ + return renameInterfaces_; +} + + +bool Foam::ccm::reader::options::combineBoundaries() const +{ + return combineBoundaries_; +} + + +bool Foam::ccm::reader::options::removeBaffles() const +{ + return removeBaffles_; +} + + +bool Foam::ccm::reader::options::useNumberedNames() const +{ + return useNumberedNames_; +} + + +Foam::scalar Foam::ccm::reader::options::mergeTol() const +{ + return mergeTol_; +} + + +Foam::scalar Foam::ccm::reader::options::undefScalar() const +{ + return undefScalar_; +} + + + +void Foam::ccm::reader::options::keepFluid(bool b) +{ + keepFluid_ = b; +} + + +void Foam::ccm::reader::options::keepPorous(bool b) +{ + keepPorous_ = b; +} + + +void Foam::ccm::reader::options::keepSolid(bool b) +{ + keepSolid_ = b; +} + + +void Foam::ccm::reader::options::mergeInterfaces(bool b) +{ + mergeInterfaces_ = b; +} + + +void Foam::ccm::reader::options::renameInterfaces(bool b) +{ + renameInterfaces_ = b; +} + + +void Foam::ccm::reader::options::combineBoundaries(bool b) +{ + combineBoundaries_ = b; +} + + +void Foam::ccm::reader::options::removeBaffles(bool b) +{ + removeBaffles_ = b; +} + + +void Foam::ccm::reader::options::useNumberedNames(bool b) +{ + useNumberedNames_ = b; +} + + +void Foam::ccm::reader::options::mergeTol(const scalar& val) +{ + mergeTol_ = val; +} + + +void Foam::ccm::reader::options::undefScalar(const scalar& val) +{ + undefScalar_ = val; +} + + +// ************************************************************************* // diff --git a/src/conversion/ccm/reader/ccmReaderSolution.C b/src/conversion/ccm/reader/ccmReaderSolution.C new file mode 100644 index 0000000000000000000000000000000000000000..04881011f355398f79489875fd0245249512daaa --- /dev/null +++ b/src/conversion/ccm/reader/ccmReaderSolution.C @@ -0,0 +1,643 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*----------------------------------------------------------------------------*/ + +#include "ccmReader.H" +#include "ccmInternal.H" // include last to avoid any strange interactions + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +// Get information about available fields. +// - assume that all fields are available for all solution intervals +// eg, +// /FieldSets/FieldSet-1/Phase-1/Fields/Velocity +// /FieldSets/FieldSet-1/Phase-1/Fields/Pressure +// ... +void Foam::ccm::reader::determineFieldInfo +( + const ccmID& fieldSetNode, + fieldTable& table +) +{ + char fullName[kCCMIOMaxStringLength + 1]; + char shortName[kCCMIOProstarShortNameLength+1]; + + // Loop through all phases + ccmID phaseNode; + int phaseI = 0; + + while + ( + CCMIONextEntity + ( + NULL, + fieldSetNode, + kCCMIOFieldPhase, + &phaseI, + &phaseNode + ) + == kCCMIONoErr + ) + { + CCMIODimensionality dims; + + // Examine each field in this fieldSet + ccmID fieldNode; + int fieldI = 0; + + // Get full/short names and dimension (scalar/vector/tensor). + // Use short name as unique identifier. + + while + ( + CCMIONextEntity + ( + NULL, + phaseNode, + kCCMIOField, + &fieldI, + &fieldNode + ) + == kCCMIONoErr + + && CCMIOReadField + ( + NULL, + fieldNode, + fullName, + shortName, + &dims, + NULL + ) + == kCCMIONoErr + ) + { + // The shortName *should* be a word, but some fields seem + // to have blanks! + { + char *ptr = shortName; + while (*ptr) + { + if (!word::valid(*ptr)) + { + *ptr = '_'; + } + ptr++; + } + } + + word fieldName(shortName); + + if (dims == kCCMIOScalar) + { + // Add to table as required + if (!table.found(fieldName)) + { + fieldEntry entry(fieldName, fullName); + + entry.units + ( + ccmReadOptstr("Units", fieldNode) + ); + + table.append(entry); + } + + fieldEntry& entry = table.find(fieldName)(); + + // Obtain sizes of data field + // - only process cell/face data + ccmID dataNode; + int dataI = 0; + + CCMIODataLocation dataLocation; + CCMIOIndex maxId; + + while + ( + CCMIONextEntity + ( + NULL, + fieldNode, + kCCMIOFieldData, + &dataI, + &dataNode + ) + == kCCMIONoErr + + && CCMIOEntitySize + ( + NULL, + dataNode, + NULL, + &maxId + ) + == kCCMIONoErr + + && CCMIOReadFieldDatad + ( + NULL, + dataNode, + NULL, + &dataLocation, + NULL, + kCCMIOStart, + kCCMIOEnd + ) + == kCCMIONoErr + ) + { + if (dataLocation == kCCMIOCell) + { + entry.maxCellId(maxId); + } + else if (dataLocation == kCCMIOFace) + { + entry.maxFaceId(maxId); + } + } + } + } + } +} + + +// Get information about all available solutions. +// - it is sufficient to examine the first processor +// +// The "States": +// Restart_1/Processor-1 +// -OR- +// Transient_1/Processor-1 +// ... +// Transient_N/Processor-1 +// +// point to the "FieldSets": +// FieldSet-1/RestartInfo +// +bool Foam::ccm::reader::detectSolution() +{ + // call once + if (solutionStatus_ != UNKNOWN) + { + return (solutionStatus_ == OKAY || solutionStatus_ == READ); + } + + // loop through all States + ccmID stateNode; + int stateI = 0; + while + ( + CCMIONextEntity + ( + NULL, + (globalState_->root), + kCCMIOState, + &stateI, + &stateNode + ) + == kCCMIONoErr + ) + { + // Loop through all processors/solutions + ccmID processorNode; + ccmID solutionNode; + int procI = 0; + + while + ( + CCMIONextEntity + ( + NULL, + stateNode, + kCCMIOProcessor, + &procI, + &processorNode + ) + == kCCMIONoErr + + && CCMIOReadProcessor + ( + NULL, + processorNode, + NULL, // Ignore verticesNode + NULL, // Ignore topologyNode + NULL, // Ignore initialField + &solutionNode + ) + == kCCMIONoErr + ) + { + // Restrict to solutions with RestartInfo on the first cpu + // (there is normally only one set of restart data) + ccmID restartNode; + int restartI = 0; + + char solutionName[kCCMIOMaxStringLength + 1]; + int iteration = 0; + float timeValue = 0; + + if + ( + CCMIONextEntity + ( + NULL, + solutionNode, + kCCMIORestart, + &restartI, + &restartNode + ) + == kCCMIONoErr + + && CCMIOEntityName + ( + NULL, + stateNode, + solutionName + ) + == kCCMIONoErr + + && CCMIOReadRestartInfo + ( + NULL, + restartNode, + NULL, // Ignore solverName + &iteration, + &timeValue, + NULL, // Ignore timeUnits + NULL // Ignore startAngle + ) + == kCCMIONoErr + ) + { + solutionTable_.append + ( + solutionEntry(solutionName, iteration, timeValue) + ); + } + + // Determine field information + determineFieldInfo(solutionNode, fieldTable_); + + // check Lagrangian data + ccmID lagrangianNode; + ccmID lagrangianSolutions; + int lagrangianI = 0; + + if + ( + CCMIONextEntity + ( + NULL, + processorNode, + kCCMIOLagrangianData, + &lagrangianI, + &lagrangianNode + ) + == kCCMIONoErr + + && CCMIOReadLagrangianData + ( + NULL, + lagrangianNode, + NULL, + &lagrangianSolutions + ) + == kCCMIONoErr + ) + { + determineFieldInfo(lagrangianSolutions, lagrangianTable_); + } + } + } + + if (solutionTable_.size() && fieldTable_.size()) + { + solutionStatus_ = OKAY; + } + else + { + solutionStatus_ = BAD; + } + + return (solutionStatus_ == OKAY || solutionStatus_ == READ); +} + +#define SOLID_STRESS_HACK + +// +// Read solution and field combination +// +Foam::tmp<Foam::scalarField> +Foam::ccm::reader::readField +( + const word& solutionName, + const word& fieldName, + const bool wallData +) +{ + // get State by name + ccmID stateNode; + ccmID solutionNode; + + if + ( + CCMIOGetState + ( + NULL, + (globalState_->root), + solutionName.c_str(), + NULL, + &stateNode + ) + != kCCMIONoErr + + || !fieldTable_.found(fieldName) + ) + { + return tmp<scalarField>(new Field<scalar>()); + } + + CCMIODataLocation requestedLocation = kCCMIOCell; + + fieldEntry& entry = fieldTable_.find(fieldName)(); + + label maxId = entry.maxCellId(); + + if (wallData) + { + maxId = entry.maxFaceId(); + requestedLocation = kCCMIOFace; + } + + // we can skip empty fields immediately + if (!maxId) + { + return tmp<scalarField>(new Field<scalar>()); + } + + char shortName[kCCMIOProstarShortNameLength+1]; + + List<label> mapData; + List<scalar> rawData; + + tmp<scalarField> tscalarData + ( + new scalarField(maxId + 1, option().undefScalar()) + ); + scalarField& scalarData = tscalarData.ref(); + + + CCMIODimensionality dims; + + // Loop across all processors + ccmID processorNode; + int procI = 0; + + while + ( + CCMIONextEntity + ( + NULL, + stateNode, + kCCMIOProcessor, + &procI, + &processorNode + ) + == kCCMIONoErr + + && CCMIOReadProcessor + ( + NULL, + processorNode, + NULL, // Ignore verticesNode + NULL, // Ignore topologyNode + NULL, // Ignore initialField + &solutionNode + ) + == kCCMIONoErr + ) + { + // loop through all phases + int phaseI = 0; + ccmID phaseNode; + + while + ( + CCMIONextEntity + ( + NULL, + solutionNode, + kCCMIOFieldPhase, + &phaseI, + &phaseNode + ) + == kCCMIONoErr + ) + { + // Get Field that matches the name + ccmID fieldNode; + int fieldI = 0; + + while + ( + CCMIONextEntity + ( + NULL, + phaseNode, + kCCMIOField, + &fieldI, + &fieldNode + ) + == kCCMIONoErr + ) + { + // Get full/short names and dimension (scalar/vector/tensor) + // use short name as unique identifier + CCMIOReadField + ( + &(globalState_->error), + fieldNode, + NULL, + shortName, + &dims, + NULL + ); + assertNoError + ( + "reading post data field: " + + string(shortName) + ); + + if (fieldName == shortName && dims == kCCMIOScalar) + { + // Obtain sizes of data field + ccmID dataNode; + ccmID mapId; + int dataI = 0; + while + ( + CCMIONextEntity + ( + NULL, + fieldNode, + kCCMIOFieldData, + &dataI, + &dataNode + ) + == kCCMIONoErr + ) + { + CCMIODataLocation dataLocation; + CCMIOSize n; + + // Only process cell/face data + if + ( + CCMIOEntitySize + ( + NULL, + dataNode, + &n, + NULL + ) + == kCCMIONoErr + + && CCMIOReadFieldDatad + ( + NULL, + dataNode, + &mapId, + &dataLocation, + NULL, + kCCMIOStart, + kCCMIOEnd + ) + == kCCMIONoErr + + && dataLocation == requestedLocation + ) + { + +#ifdef SOLID_STRESS_HACK + bool okayCombination = true; + + CCMIOSize len; + if + ( + CCMIOEntityDescription + ( + NULL, + dataNode, + &len, + NULL + ) + == kCCMIONoErr + ) + { + char* dataLabel = new char[len + 1]; + + if + ( + CCMIOEntityDescription + ( + NULL, + dataNode, + &len, + dataLabel + ) + == kCCMIONoErr + ) + { + if + ( + ( + strstr(fieldName.c_str(), "SIG") + || strstr(fieldName.c_str(), "EPS") + ) + && strstr(dataLabel, "So") == NULL + ) + { + okayCombination = false; + // skip non-solid + } + } + + delete[] dataLabel; + } + + if (!okayCombination) + { + continue; + } +#endif + + mapData.setSize(n); + rawData.setSize(n); + + readMap + ( + mapId, + mapData + ); + + CCMIOReadFieldDatad + ( + &(globalState_->error), + dataNode, + NULL, + NULL, + rawData.begin(), + kCCMIOStart, + kCCMIOEnd + ); + assertNoError + ( + "reading post data field: " + + string(shortName) + ); + + // transcribe to output list + forAll(mapData, i) + { + label cellId = mapData[i]; + scalarData[cellId] = rawData[i]; + } + + } + } + } + } + } + } + + // Overwrite possible junk in cell 0 (often used as /dev/null) + scalarData[0] = option().undefScalar(); + + return tscalarData; +} + + +// ************************************************************************* // diff --git a/src/conversion/ccm/reader/ccmSolutionTable.H b/src/conversion/ccm/reader/ccmSolutionTable.H new file mode 100644 index 0000000000000000000000000000000000000000..e223d1c7480cca60c7b476de073ce0b7e9ad0010 --- /dev/null +++ b/src/conversion/ccm/reader/ccmSolutionTable.H @@ -0,0 +1,452 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Description + Containers for holding ccm solution and field listings. + +\*---------------------------------------------------------------------------*/ +#ifndef ccmSolutionTable_H +#define ccmSolutionTable_H + +#include "SLList.H" +#include "stringListOps.H" +#include "Ostream.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace ccm +{ + +/*---------------------------------------------------------------------------*\ + Class ccm::namesList Declaration +\*---------------------------------------------------------------------------*/ + +//- A linked-list that is searchable by the 'name()' of the items +template<class T> +class namesList +: + public SLList<T> +{ +public: + typedef typename SLList<T>::const_iterator const_iterator; + typedef typename SLList<T>::iterator iterator; + + // Constructors + + //- Null construct + namesList() + {} + + + // Access + + //- Return true if a list element has a name that matches key + bool found(const word& key) const + { + for + ( + const_iterator iter = SLList<T>::begin(); + iter != SLList<T>::end(); + ++iter + ) + { + if (iter().name() == key) + { + return true; + } + } + + return false; + } + + + //- Find a list element has a name matching key + iterator find(const word& key) + { + for + ( + iterator iter = SLList<T>::begin(); + iter != SLList<T>::end(); + ++iter + ) + { + if (iter().name() == key) + { + return iter; + } + } + + return SLList<T>::end(); + } + + + //- Return a list of names matching whiteList and not matching blackList + List<word> findNames + ( + const UList<wordRe>& whiteLst, + const UList<wordRe>& blackLst = UList<wordRe>() + ) const + { + List<word> matched(SLList<T>::size()); + + label matchI = 0; + for + ( + const_iterator iter = SLList<T>::begin(); + iter != SLList<T>::end(); + ++iter + ) + { + const word& name = iter().name(); + + if + ( + findStrings(whiteLst, name) + && !findStrings(blackLst, name) + ) + { + matched[matchI++] = name; + } + } + matched.setSize(matchI); + + return matched; + } + +}; + + +/*---------------------------------------------------------------------------*\ + Class ccm::fieldEntry Declaration +\*---------------------------------------------------------------------------*/ + +//- A ccm field entry with short name, name, maxId and type +// shortName => ( fullName, maxId, type ); +class fieldEntry +{ + // Private Data + + //- The field name (PROSTAR short name) + word name_; + + //- The full field name + string fullName_; + + //- The field units + string units_; + + //- The max cell id for the field + label maxCellId_; + + //- The max face id for the field + label maxFaceId_; + +public: + + // Constructors + + //- Construct from components with optional units + fieldEntry + ( + const word& shortName, + const string& fullName, + const char* units = nullptr + ) + : + name_(shortName), + fullName_(fullName), + units_(), + maxCellId_(0), + maxFaceId_(0) + { + if (units && *units) + { + units_ = units; + } + } + + + // Access + + //- The field name (PROSTAR short name) + const word& name() const + { + return name_; + } + + //- The full field name + const string& fullName() const + { + return fullName_; + } + + //- The field units + const string& units() const + { + return units_; + } + + //- The max cell id for the field + label maxCellId() const + { + return maxCellId_; + } + + //- The max face id for the field + label maxFaceId() const + { + return maxFaceId_; + } + + + // Edit + + //- Set the field units + void units(const char* units) + { + if (units && *units) + { + units_ = units; + } + } + + //- Set the field units + void units(const std::string& units) + { + if (!units.empty()) + { + units_ = units; + } + } + + //- Set the max cell Id for the field + void maxCellId(const int newMax) + { + if (maxCellId_ < newMax) + { + maxCellId_ = newMax; + } + } + + + //- Set the max face Id for the field + void maxFaceId(const int newMax) + { + if (maxFaceId_ < newMax) + { + maxFaceId_ = newMax; + } + } + + + // IOstream Operators + + friend Ostream& operator<< + ( + Ostream& os, + const fieldEntry& entry + ) + { + os << entry.name_ << " => " << entry.fullName_ + << " [" << entry.units_.c_str() + << "] maxCell: " << entry.maxCellId_ + << " maxFace: " << entry.maxFaceId_; + + return os; + } + +}; + +/*---------------------------------------------------------------------------*\ + Class ccm::solutionEntry Declaration +\*---------------------------------------------------------------------------*/ + +//- A ccm solution entry with name, iteration and time +// stateName => ( iteration, time ); +class solutionEntry +{ + // Private Data + + //- The solution name + word name_; + + //- The solution iteration/timestep + label iter_; + + //- The solution time (sec) + scalar time_; + +public: + + // Constructors + + //- Construct from components + solutionEntry + ( + const word& name, + const label& iteration, + const scalar& timeValue = 0 + ) + : + name_(name), + iter_(iteration), + time_(timeValue) + {} + + // Access + + //- The solution name + const word& name() const + { + return name_; + } + + //- The solution iteration/timestep + label iteration() const + { + return iter_; + } + + //- The solution time (sec) + scalar timeValue() const + { + return time_; + } + + + // IOstream Operators + + friend Ostream& operator<< + ( + Ostream& os, + const solutionEntry& entry + ) + { + os << entry.name_ << " =>" + << " iter: " << entry.iter_ + << " time: " << entry.time_; + + return os; + } + +}; + + +/*---------------------------------------------------------------------------*\ + Class ccm::solutionTable Declaration +\*---------------------------------------------------------------------------*/ + +// Typedef: ccm::solutionTable +// A list of all the available solutions +typedef namesList<solutionEntry> solutionTable; + + +/*---------------------------------------------------------------------------*\ + Class ccm::fieldTable Declaration +\*---------------------------------------------------------------------------*/ + +//- A list of the available fields +class fieldTable +: + public namesList<fieldEntry> +{ +public: + + // Constructor + + //- Null construct + fieldTable() + : + namesList<fieldEntry>() + {} + + // Access + + //- The maximum cell Id referenced in the list + label maxCellId() const + { + label maxId = 0; + forAllConstIter(namesList<fieldEntry>, *this, iter) + { + label currMax = (iter()).maxCellId(); + + if (maxId < currMax) + { + maxId = currMax; + } + } + + return maxId; + } + + + //- The maximum face Id referenced in the list + label maxFaceId() const + { + label maxId = 0; + + forAllConstIter(namesList<fieldEntry>, *this, iter) + { + label currMax = (iter()).maxFaceId(); + + if (maxId < currMax) + { + maxId = currMax; + } + } + + return maxId; + } + + + // IOstream Operators + + friend Ostream& operator<< + ( + Ostream& os, + const fieldTable& tbl + ) + { + os << static_cast<const namesList<fieldEntry>& >(tbl) + << nl + << "maxCell: " << tbl.maxCellId() + << " maxFace: " << tbl.maxFaceId(); + + return os; + } + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace ccm +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ccm/remapping b/src/conversion/ccm/remapping new file mode 100644 index 0000000000000000000000000000000000000000..d2013ecfcb0691a8d0486724389fbbdbd33f398f --- /dev/null +++ b/src/conversion/ccm/remapping @@ -0,0 +1,96 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1612+ | +| \\ / A nd | Web: www.OpenFOAM.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + note "remapping for STARCD <-> OPENFOAM translation"; + object remapping; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// +// rename/combine cellTable entries +// target ( source names ) +// +cellTable +{ + fluid ( FLUID "cat[0-9]_?(In|Out)_?Layer" ); + cat1 ( CAT1 "cat1_?(Front|Back|Gamma)" ); + cat2 ( CAT2 "cat2_?(Front|Back|Gamma)" ); + cat3 ( CAT3 "cat3_?(Front|Back|Gamma)" ); + cat4 ( CAT4 "cat4_?(Front|Back|Gamma)" ); +} + + +// +// rename boundary regions +// newName <- oldName +// +boundaryRegion +{ + walls Default_Boundary_Region; + inlet1 inlet_1; + inlet2 inlet_2; + inlet3 inlet_3; + inlet4 inlet_4; + inlet5 inlet_5; + inlet6 inlet_6; + outlet1 outlet_1; + outlet2 outlet_2; + outlet3 outlet_3; + outlet4 outlet_4; + outlet5 outlet_5; + outlet6 outlet_6; +} + + +boundary +{ + empty symmetryPlane; +} + + +// +// map OPENFOAM field names to CCM fields +// +fields +{ + tracer0 + { + name CONC_001; + Label "tracer0"; + } + + tracer1 + { + name CONC_002; + Label "tracer1"; + } + + tracer2 + { + name CONC_003; + Label "tracer2"; + } + + divPhi + { + name CONC_004; + Label "divPhi"; + } + + Ma + { + name CONC_100; + Label "Mach"; + } +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/conversion/ccm/writer/ccmWriter.C b/src/conversion/ccm/writer/ccmWriter.C new file mode 100644 index 0000000000000000000000000000000000000000..c78a2fa068626d15cf77f154581529ff6546d631 --- /dev/null +++ b/src/conversion/ccm/writer/ccmWriter.C @@ -0,0 +1,389 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*----------------------------------------------------------------------------*/ + +#include "ccmWriter.H" +#include "cellModeller.H" +#include "demandDrivenData.H" +#include "ccmInternal.H" // include last to avoid any strange interactions + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +// name for the topology file reference +Foam::string Foam::ccm::writer::defaultMeshName = "meshExport"; + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +// Create a filled linear map with 'size' from 'start + 1' +void Foam::ccm::writer::addLinearMap +( + const string& mapName, + ccmID& mapId, + label size, + label start +) const +{ + if (globalState_->hasError() || size <= 0) + { + return; + } + + CCMIONewEntity + ( + &(globalState_->error), + (globalState_->root), + kCCMIOMap, + mapName.c_str(), + &mapId + ); + assertNoError("creating linearMap '" + mapName + "' node"); + + List<int> data(size); + forAll(data, i) + { + data[i] = start + 1 + i; + } + + CCMIOWriteMap + ( + &(globalState_->error), + mapId, + size, + (start + size), + data.begin(), + kCCMIOStart, + kCCMIOEnd + ); + assertNoError("writing linearMap '" + mapName + "' data"); +} + + +Foam::label Foam::ccm::writer::findDefaultBoundary() const +{ + return mesh_.boundaryMesh().findPatchID(defaultBoundaryName); +} + + +void Foam::ccm::writer::writeBoundaryRegion +( + const ccmID& probNode +) const +{ + // Create dictionary lookup for constant/boundaryRegion + dictionary typeDict; + + forAllConstIter(Map<dictionary>, boundaryRegion_, iter) + { + const dictionary& dict = iter(); + if + ( + dict.found("Label") + && dict.found("BoundaryType") + ) + { + word nameEntry, typeEntry; + + dict.lookup("Label") >> nameEntry; + dict.lookup("BoundaryType") >> typeEntry; + + if (!typeDict.found(nameEntry)) + { + typeDict.add(nameEntry, typeEntry); + } + } + } + + const polyBoundaryMesh& patches = mesh_.boundaryMesh(); + + label defaultId = findDefaultBoundary(); + + // Force write Default_Boundary_Region as BoundaryRegion-0 + { + ccmID nodeId; + CCMIONewIndexedEntity + ( + &(globalState_->error), + probNode, + kCCMIOBoundaryRegion, + 0, + nullptr, + &nodeId + ); + CCMIOWriteOptstr + ( + nullptr, + nodeId, + "Label", + defaultBoundaryName + ); + CCMIOWriteOptstr + ( + nullptr, + nodeId, + "BoundaryType", + "wall" + ); + } + + forAll(patches, patchI) + { + word patchName = patches[patchI].name(); + word patchType = patches[patchI].type(); + + label regionId = patchI; + if (regionId == defaultId) + { + continue; // Skip - already written + } + else if (defaultId == -1 || regionId < defaultId) + { + regionId++; + } + + // Use BoundaryType from constant/boundaryRegion + typeDict.readIfPresent(patchName, patchType); + + ccmID nodeId; + CCMIONewIndexedEntity + ( + &(globalState_->error), + probNode, + kCCMIOBoundaryRegion, + regionId, + nullptr, + &nodeId + ); + CCMIOWriteOptstr + ( + nullptr, + nodeId, + "Label", + patchName.c_str() + ); + CCMIOWriteOptstr + ( + nullptr, + nodeId, + "BoundaryType", + patchType.c_str() + ); + } +} + + +void Foam::ccm::writer::writeCellTable +( + const ccmID& probNode +) const +{ + if (!cellTable_.size()) + { + Info<< "No cellTable" << endl; + return; + } + + ccmID nodeId; + + forAllConstIter(Map<dictionary>, cellTable_, iter) + { + label intVal = iter.key(); + const dictionary& dict = iter(); + + CCMIONewIndexedEntity + ( + &(globalState_->error), + probNode, + kCCMIOCellType, + intVal, + nullptr, + &nodeId + ); + + wordList toc = dict.toc(); + forAll(toc, i) + { + word keyword = toc[i]; + int pos = keyword.find("Id"); + + // Tags containing 'Id' are integers + if (pos > 0) + { + dict.lookup(keyword) >> intVal; + CCMIOWriteOpti + ( + nullptr, + nodeId, + keyword.c_str(), + intVal + ); + } + else if (pos < 0) + { + word strVal; + dict.lookup(keyword) >> strVal; + + CCMIOWriteOptstr + ( + nullptr, + nodeId, + keyword.c_str(), + strVal.c_str() + ); + } + } + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +// Write out problem description +void Foam::ccm::writer::writeProblem +( + const ccmID& stateNode +) const +{ + ccmID probNode; + CCMIONewEntity + ( + &(globalState_->error), + (globalState_->root), + kCCMIOProblemDescription, + nullptr, + &probNode + ); + + writeCellTable(probNode); + writeBoundaryRegion(probNode); + + // let the state know about our problem + CCMIOWriteState + ( + &(globalState_->error), + stateNode, + probNode, + nullptr + ); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +// Construct for writing geometry +Foam::ccm::writer::writer +( + const fileName& file, + const polyMesh& mesh, + const bool backup +) +: + base(), + maps_(new ccmMaps), + mesh_(mesh), + // Mapping between OpenFOAM and PROSTAR primitives + prostarShapeLookup_ + ({ + { cellModeller::lookup("hex")->index(), STARCDCore::starcdHex }, + { cellModeller::lookup("prism")->index(), STARCDCore::starcdPrism }, + { cellModeller::lookup("tet")->index(), STARCDCore::starcdTet }, + { cellModeller::lookup("pyr")->index(), STARCDCore::starcdPyr } + }), + boundaryRegion_(mesh), + cellTable_(mesh) +{ + // Writing/re-writing existing files is too annoying - start anew + if (backup) + { + if (Foam::mvBak(file)) + { + Info<< "moved existing file -> " << fileName(file + ".bak*") << nl; + } + } + else if (exists(file, false)) + { + Foam::rm(file); + Info<< "removed existing file: " << file << nl; + } + + // Reinitialize error state from the return value + globalState_->error = CCMIOOpenFile + ( + nullptr, + file.c_str(), + kCCMIOWrite, + &(globalState_->root) + ); + assertNoError("Error opening file for writing"); + + // We always need the cell map + addLinearMap + ( + "cell Map", + maps_->cells, + mesh_.nCells() + ); + + // We often need the internalFaces map + addLinearMap + ( + "internalFaces Map", + maps_->internalFaces, + mesh_.nInternalFaces() + ); + + const polyBoundaryMesh& patches = mesh_.boundaryMesh(); + maps_->boundary.setSize(patches.size()); + + // We always need maps for the boundary regions + forAll(patches, patchI) + { + if (patches[patchI].size() > 0) + { + string mapName = "boundaryMap-" + Foam::name(patchI); + + addLinearMap + ( + mapName, + maps_->boundary[patchI], + patches[patchI].size(), + patches[patchI].start() + ); + } + } +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::ccm::writer::~writer() +{ + close(); + + deleteDemandDrivenData(maps_); +} + + +// ************************************************************************* // diff --git a/src/conversion/ccm/writer/ccmWriter.H b/src/conversion/ccm/writer/ccmWriter.H new file mode 100644 index 0000000000000000000000000000000000000000..a2d57148c9bb8633630cc79f4fbdd60ce08a2cb1 --- /dev/null +++ b/src/conversion/ccm/writer/ccmWriter.H @@ -0,0 +1,256 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::ccm::writer + +Description + Write OpenFOAM meshes and/or results to CCM format + + - partial support for interfaces + - no monitoring (internal) boundaries + - does not handle Lagrangian data + + \par Files + + The <tt>constant/boundaryRegion</tt> and <tt>constant/cellTable</tt> files, + which are described in ccmReader, are used to construct the CCM + \c ProblemDescription node. + + The <tt>constant/remapping</tt> file is an \c IOdictionary that is + \c READ_IF_PRESENT and can be used to remap certain information. + eg, + + \verbatim + // map OpenFOAM scalar fields to CCM output fields + fields + { + tracer0 + { + name CONC_001; + Label "tracer0"; + } + tracer1 + { + name CONC_002; + Label "tracer1"; + } + tracer2 + { + name CONC_003; + Label "tracer2"; + } + divPhi + { + name CONC_004; + Label "divPhi"; + } + // an example with units: + p + { + name P; + Label "Pressure"; + units "Pa"; + } + } + \endverbatim + +Note + This class is in development + - any/all of the class names and members may change + +SourceFiles + ccmWriter.C + ccmWriterMesh.C + ccmWriterSolution.C + +\*---------------------------------------------------------------------------*/ +#ifndef ccmWriter_H +#define ccmWriter_H + +#include "ccmBase.H" +#include "STARCDCore.H" + +#include "fvMesh.H" +#include "boundaryRegion.H" +#include "cellTable.H" +#include "IOobjectList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace ccm +{ + +// * * * * * * * * * * * * * Forward Declarations * * * * * * * * * * * * * // + +class ccmID; +class ccmMaps; +class ccmDimension; +class ccmGlobalState; + +/*---------------------------------------------------------------------------*\ + Class ccm::writer Declaration +\*---------------------------------------------------------------------------*/ + +class writer +: + public base, + protected fileFormats::STARCDCore +{ + // Private Data + + // Static Data + + //- The OpenFOAM -> CCM field mappings + static dictionary defaultNameMapping; + + + // Member Data + + //- MapIds for various components (cell, internalFaces, boundaries) + ccmMaps* maps_; + + //- mesh reference + const polyMesh& mesh_; + + //- Lookup between cellModel shape and PROSTAR shape + const Map<label> prostarShapeLookup_; + + //- ccm node: ProblemDescriptions/boundaryRegion + boundaryRegion boundaryRegion_; + + // ccm node: ProblemDescriptions/cellType + cellTable cellTable_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + writer(const writer&) = delete; + + //- Disallow default bitwise assignment + void operator=(const writer&) = delete; + + + //- create a filled linear map with 'size' from 'start + 1' + void addLinearMap + ( + const string& mapName, + ccmID& mapId, + label size, + label start = 0 + ) const; + + void writeBoundaryRegion(const ccmID& probNode) const; + + void writeCellTable(const ccmID& probNode) const; + + //- write out problem description + void writeProblem(const ccmID& stateNode) const; + + //- Return the PROSTAR face id for the given cell/face + label prostarCellFaceId(const label& cellId, const label& faceI) const; + + // write the faces, the number of vertices appears before each entry + void writeFaces + ( + const ccmID& nodeId, + const ccmID& mapId, + bool isBoundary, // boundary or internal faces + label size, + label start = 0 + ) const; + + void writeVertices(const ccmID& verticesNode) const; + + // - write internal faces with owner/neighbour + void writeInternalFaces(const ccmID& topoNode) const; + + // - write boundary faces with owner + void writeBoundaryFaces(const ccmID& topoNode) const; + + void writeCells(const ccmID& topoNode); + + void writeInterfaces(const ccmID& cellsNode) const; + + bool newFieldNode + ( + const ccmID& phaseNode, + const word& fieldName, + const dictionary& nameMapping, + const ccmDimension& ccmDim, + ccmID& fieldNode + ) const; + + + //- Return patch named 'Default_Boundary_Region' or -1 on error + label findDefaultBoundary() const; + +public: + + // Static data members + + //- The name for the topology file reference + static string defaultMeshName; + + + // Constructors + + //- Open a file for writing, with backup/overwrite existing file + writer(const fileName&, const polyMesh&, const bool backup=true); + + + //- Destructor (closes file) + ~writer(); + + + // Member Functions + + // Write + + //- Write the mesh + void writeGeometry(); + + //- Write the solutions + // provide optional remapping dictionary + void writeSolution + ( + const IOobjectList&, + const fileName& remappingDictName = fileName::null + ); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace ccm +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/ccm/writer/ccmWriterMesh.C b/src/conversion/ccm/writer/ccmWriterMesh.C new file mode 100644 index 0000000000000000000000000000000000000000..506e9fc1c9c419e4ce8527eb1de1675ddc388fce --- /dev/null +++ b/src/conversion/ccm/writer/ccmWriterMesh.C @@ -0,0 +1,831 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*----------------------------------------------------------------------------*/ + +#include "ccmWriter.H" +#include "ccmInternal.H" // include last to avoid any strange interactions + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::label Foam::ccm::writer::prostarCellFaceId +( + const label& cellId, + const label& faceI +) const +{ + const faceList& faces = mesh_.faces(); + const cellShape& shape = mesh_.cellShapes()[cellId]; + const labelList& cFaces = mesh_.cells()[cellId]; + + label cellFaceId = findIndex(cFaces, faceI); + label mapIndex = shape.model().index(); + + if (ccm::debug > 1) + { + Info<< " face[" << faceI << "]: " << faces[faceI] << nl + << " owner: " << cellId + << " cellFace: " << cellFaceId + << " cellFaces: " << cFaces + << " shape [index " << mapIndex << "] " << shape + << endl; + + Info << "cellFaces" << nl; + forAll(cFaces, cFaceI) + { + Info<< " face [" << cFaces[cFaceI] << "] = " + << faces[cFaces[cFaceI]] << nl; + } + + Info << "shapeFaces" << nl; + { + const faceList sFaces = shape.faces(); + forAll(sFaces, sFaceI) + { + Info<< " sFace[" << sFaceI << "] = " + << sFaces[sFaceI] << nl; + } + } + } + + // The face order returned by primitiveMesh::cells() is not + // necessarily the same as defined by + // primitiveMesh::cellShapes(). + // Thus do the lookup for registered primitive types. + // Finally, remap the cellModel face number to the ProstarFaceId + if (prostarShapeLookup_.found(mapIndex)) + { + const faceList sFaces = shape.faces(); + forAll(sFaces, sFaceI) + { + if (faces[faceI] == sFaces[sFaceI]) + { + cellFaceId = sFaceI; + + if (ccm::debug > 1) + { + Info << " FoamCellFace: " << sFaceI; + } + + break; + } + } + + mapIndex = prostarShapeLookup_[mapIndex]; + cellFaceId = STARCDCore::foamToStarFaceAddr[mapIndex][cellFaceId]; + + if (ccm::debug > 1) + { + Info<< " ProstarShape: " << mapIndex + << " ProstarFaceId: " << cellFaceId + 1 + << endl; + } + } + + // PROSTAR used 1-based indices + return cellFaceId + 1; +} + + +// write the faces, the number of vertices appears before each entry +void Foam::ccm::writer::writeFaces +( + const ccmID& nodeId, + const ccmID& mapId, + bool isBoundary, + label size, + label start +) const +{ + if (globalState_->hasError() || size <= 0) + { + return; + } + + CCMIOEntity nodeType; + if (isBoundary) + { + nodeType = kCCMIOBoundaryFaces; + } + else + { + nodeType = kCCMIOInternalFaces; + } + + const faceList& faces = mesh_.faces(); + const labelList& owner = mesh_.faceOwner(); + const labelList& neigh = mesh_.faceNeighbour(); + + // 1. write vertices to define faces + + // Determine allocation size + label streamSize = size; + for (label faceI = 0; faceI < size; ++faceI) + { + streamSize += faces[faceI + start].size(); + } + + // Build a vertex stream + List<int> ccmStream(streamSize); + streamSize = 0; + for (label faceI = 0; faceI < size; ++faceI) + { + const labelList& vrtList = faces[faceI + start]; + + ccmStream[streamSize++] = vrtList.size(); + forAll(vrtList, i) + { + ccmStream[streamSize++] = vrtList[i] + 1; + } + } + + if (ccm::debug) + { + Info<<"CCMIOWriteFaces() size:" << size << " streamSize:" << streamSize << endl; + } + + CCMIOWriteFaces + ( + &(globalState_->error), + nodeId, + nodeType, + mapId, + streamSize, + ccmStream.begin(), + kCCMIOStart, + kCCMIOEnd + ); + + if (globalState_->hasError()) + { + return; + } + + // 2. write face owner/neighbours + if (isBoundary) + { + streamSize = size; + if (ccmStream.size() < streamSize) + { + ccmStream.setSize(streamSize); + } + + for (int faceI = 0; faceI < size; ++faceI) + { + ccmStream[faceI] = owner[faceI + start] + 1; + } + } + else + { + // kCCMIOInternalFaces + streamSize = 2 * size; + if (ccmStream.size() < streamSize) + { + ccmStream.setSize(streamSize); + } + + for (int faceI = 0; faceI < size; ++faceI) + { + ccmStream[faceI*2] = owner[faceI + start] + 1; + ccmStream[faceI*2+1] = neigh[faceI + start] + 1; + } + } + + if (ccm::debug) + { + Info<<"CCMIOWriteFaceCells() size:" << size; + if (isBoundary) + { + Info<< " boundary"; + } + else + { + Info<<" internal"; + } + Info<<"Faces"<<endl; + } + + CCMIOWriteFaceCells + ( + &(globalState_->error), + nodeId, + nodeType, + mapId, + ccmStream.begin(), + kCCMIOStart, + kCCMIOEnd + ); + + // determine corresponding ProstarFaceId + if (isBoundary) + { + streamSize = size; + if (ccmStream.size() < streamSize) + { + ccmStream.setSize(streamSize); + } + + for (int faceIdx = 0; faceIdx < size; ++faceIdx) + { + label faceI = faceIdx + start; + // boundary face - owner only + ccmStream[faceIdx] = prostarCellFaceId(owner[faceI], faceI); + } + + CCMIOWriteOpt1i + ( + &(globalState_->error), + nodeId, + "ProstarFaceId", + size, + ccmStream.begin(), + kCCMIOStart, + kCCMIOEnd + ); + } + else + { + // kCCMIOInternalFaces + streamSize = 2 * size; + if (ccmStream.size() < streamSize) + { + ccmStream.setSize(streamSize); + } + + for (int faceIdx = 0; faceIdx < size; ++faceIdx) + { + label faceI = faceIdx + start; + ccmStream[faceIdx*2] = prostarCellFaceId(owner[faceI], faceI); + ccmStream[faceIdx*2+1] = prostarCellFaceId(neigh[faceI], faceI); + } + + CCMIOWriteOpt2i + ( + &(globalState_->error), + nodeId, + "ProstarFaceId", + size, + 2, + ccmStream.begin(), + kCCMIOStart, + kCCMIOEnd + ); + } +} + + +// writeVertices +// 1) write the vertex map (starting with 1) +// 2) write the vertex data +// +void Foam::ccm::writer::writeVertices +( + const ccmID& verticesNode +) const +{ + const pointField& pts = mesh_.points(); + + Info<< "writing points: " << pts.size() << endl; + + // 1. mapping data array index to the vertex Id (starting with 1) + ccmID vertexMap; + addLinearMap + ( + "vertex Map", + vertexMap, + pts.size() + ); + + // 2. write vertices - scale [m] -> [mm] for consistency with PROSTAR + // but is probably immaterial + const float scaling(0.001); // to recover meters + List<float> vrts(3*pts.size()); + forAll(pts, i) + { + vrts[3*i] = 1000.0 * pts[i].x(); + vrts[3*i+1] = 1000.0 * pts[i].y(); + vrts[3*i+2] = 1000.0 * pts[i].z(); + } + + CCMIOWriteVerticesf + ( + &(globalState_->error), + verticesNode, + 3, scaling, + vertexMap, + vrts.begin(), + kCCMIOStart, + kCCMIOEnd + ); + assertNoError("writing 'Vertices' node"); +} + + +// writeInternalFaces +// 1) write the face map (starting with 1) +// 2) write owner/neighbour +// +void Foam::ccm::writer::writeInternalFaces +( + const ccmID& topoNode +) const +{ + label nFaces = mesh_.nInternalFaces(); + + Info<< "writing internalFaces: " << nFaces << endl; + if (nFaces > 0) + { + ccmID nodeId; + CCMIONewEntity + ( + &(globalState_->error), + topoNode, + kCCMIOInternalFaces, + nullptr, + &nodeId + ); + assertNoError("creating internalFaces node"); + + writeFaces + ( + nodeId, + maps_->internalFaces, + false, + nFaces + ); + assertNoError("writing internalFaces"); + } +} + + +// writeBoundaryFaces: +// - write faces with owner +void Foam::ccm::writer::writeBoundaryFaces +( + const ccmID& topoNode +) const +{ + const polyBoundaryMesh& patches = mesh_.boundaryMesh(); + + // 4. write boundary faces + Info<< "writing boundaryFaces:" << flush; + + label defaultId = findDefaultBoundary(); + + // write Default_Boundary_Region as BoundaryFaces-0 + if (defaultId >= 0) + { + Info<< " " << patches[defaultId].size() << flush; + + ccmID nodeId; + CCMIONewIndexedEntity + ( + &(globalState_->error), + topoNode, + kCCMIOBoundaryFaces, + 0, + nullptr, + &nodeId + ); + assertNoError + ( + "creating boundaryFaces node patch: " + patches[defaultId].name() + ); + + writeFaces + ( + nodeId, + maps_->boundary[defaultId], + true, + patches[defaultId].size(), + patches[defaultId].start() + ); + assertNoError + ( + "writing boundaryFaces patch: " + patches[defaultId].name() + ); + } + + // + // write boundary faces - skip Default_Boundary_Region + // + forAll(patches, patchI) + { + label regionId = patchI; + if (regionId == defaultId) + { + continue; // skip - already written + } + else if (defaultId == -1 || regionId < defaultId) + { + regionId++; + } + + Info<< " " << patches[patchI].size() << flush; + + if (patches[patchI].size() > 0) + { + ccmID nodeId; + CCMIONewIndexedEntity + ( + &(globalState_->error), + topoNode, + kCCMIOBoundaryFaces, + regionId, + nullptr, + &nodeId + ); + assertNoError + ( + "creating boundaryFaces node patch: " + patches[patchI].name() + ); + + writeFaces + ( + nodeId, + maps_->boundary[patchI], + true, + patches[patchI].size(), + patches[patchI].start() + ); + assertNoError + ( + "writing boundaryFaces patch: " + patches[patchI].name() + ); + } + } + + Info<< endl; +} + + +// writeCells: +// - write faces with owner/neighbour +// - write interfaces +void Foam::ccm::writer::writeCells +( + const ccmID& topoNode +) +{ + Info<< "writing cells: " << mesh_.nCells() << endl; + + // 1. cellTableId + // - if possible, read from constant/polyMesh/cellTableId + // - otherwise use cellZone information + List<int> mapData(mesh_.nCells(), -1); + bool useCellZones = false; + + IOList<label> ioList + ( + IOobject + ( + "cellTableId", + "constant", + polyMesh::meshSubDir, + mesh_, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE, + false + ) + ); + + + if (ioList.headerOk()) + { + if (ioList.size() == mesh_.nCells()) + { + mapData.transfer(ioList); + } + else + { + WarningIn("ccm::writer::writeCells(polyMesh&)") + << ioList.objectPath() << endl + << " Has incorrect number of cells: " + << ioList.size() << " instead of " << mesh_.nCells() + << " - use cellZone information instead" + << endl; + + ioList.clear(); + useCellZones = true; + } + } + else + { + useCellZones = true; + } + + + if (useCellZones) + { + if (!cellTable_.size()) + { + Info<< "created cellTable from cellZones" << endl; + cellTable_ = mesh_; + } + + // track if there are unzoned cells + label nUnzoned = mesh_.nCells(); + + // get the cellZone <-> cellTable correspondence + Info<< "matching cellZones to cellTable" << endl; + + forAll(mesh_.cellZones(), zoneI) + { + const cellZone& cZone = mesh_.cellZones()[zoneI]; + if (cZone.size()) + { + nUnzoned -= cZone.size(); + + label tableId = cellTable_.findIndex(cZone.name()); + if (tableId < 0) + { + dictionary dict; + + dict.add("Label", cZone.name()); + dict.add("MaterialType", "fluid"); + tableId = cellTable_.append(dict); + } + + forAll(cZone, i) + { + mapData[cZone[i]] = tableId; + } + } + } + + if (nUnzoned) + { + dictionary dict; + + dict.add("Label", "__unzonedCells__"); + dict.add("MaterialType", "fluid"); + label tableId = cellTable_.append(dict); + + forAll(mapData, i) + { + if (mapData[i] < 0) + { + mapData[i] = tableId; + } + } + } + } + + // 2. mapping data array index to the cell Id (starting with 1) + ccmID cellsNode; + CCMIONewEntity + ( + &(globalState_->error), + topoNode, + kCCMIOCells, + nullptr, + &cellsNode + ); + assertNoError("creating 'Cells' node"); + + CCMIOWriteCells + ( + &(globalState_->error), + cellsNode, + maps_->cells, + mapData.begin(), + kCCMIOStart, kCCMIOEnd + ); + assertNoError("writing 'Cells' node"); + + // 3. add cell topology information, if possible + const cellShapeList& shapes = mesh_.cellShapes(); + forAll(shapes, cellI) + { + label mapIndex = shapes[cellI].model().index(); + + // A registered primitive type + if (prostarShapeLookup_.found(mapIndex)) + { + mapData[cellI] = prostarShapeLookup_[mapIndex]; + } + else + { + mapData[cellI] = STARCDCore::starcdPoly; // Treat as polyhedral + } + } + + CCMIOWriteOpt1i + ( + &(globalState_->error), + cellsNode, + "CellTopologyType", + mesh_.nCells(), + mapData.begin(), + kCCMIOStart, kCCMIOEnd + ); + + // 4. write interfaces + writeInterfaces(cellsNode); +} + + +// write interfaces +// 1) PROSTAR baffles +// +void Foam::ccm::writer::writeInterfaces +( + const ccmID& cellsNode +) const +{ + IOList<labelList> interfaces + ( + IOobject + ( + "interfaces", + "constant", + "polyMesh", + mesh_, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE, + false + ) + ); + + if (interfaces.headerOk() && interfaces.size() > 0) + { + List<int> mapData(2 * interfaces.size()); + + forAll(interfaces, i) + { + mapData[i*2] = interfaces[i][0]; + mapData[i*2+1] = interfaces[i][1]; + } + + ccmID nodeId; + if + ( + CCMIONewEntity + ( + &(globalState_->error), + cellsNode, + kCCMIOInterfaces, + 0, + &nodeId + ) + != kCCMIONoErr + + || CCMIOWriteOpt2i + ( + &(globalState_->error), + nodeId, + "FaceIds", + interfaces.size(), + 2, + mapData.begin(), kCCMIOStart, kCCMIOEnd + ) + != kCCMIONoErr + ) + { + assertNoError("writing interfaces 'FaceIds'"); + } + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::ccm::writer::writeGeometry() +{ + // use first ("default") state node + ccmID stateNode; + // int stateI = 0; + + // create "default" State + CCMIONewState + ( + &(globalState_->error), + (globalState_->root), + "default", + nullptr, + nullptr, + &stateNode + ); + assertNoError("could not create default state"); + + // use first processor - create a new one + ccmID processorNode; + int procI = 0; + + if + ( + CCMIONextEntity + ( + nullptr, + stateNode, + kCCMIOProcessor, + &procI, + &processorNode + ) + != kCCMIONoErr + ) + { + CCMIONewEntity + ( + &(globalState_->error), + stateNode, + kCCMIOProcessor, + nullptr, + &processorNode + ); + assertNoError("could not create processor node"); + } + + // remove old data (if it exists) + CCMIOClearProcessor + ( + nullptr, stateNode, processorNode, + true, // Clear vertices + true, // Clear topology + true, // Clear initial field + true, // Clear solution + true // Clear lagrangian + ); + +#if 0 + CCMIOWriteOptstr + ( + nullptr, + processorNode, + "CreatingProgram", + "ccm::writer" + ); +#endif + + // + // create vertices and topology nodes + // + ccmID verticesNode, topoNode; + if + ( + CCMIONewEntity + ( + &(globalState_->error), + (globalState_->root), + kCCMIOVertices, + nullptr, + &verticesNode + ) + == kCCMIONoErr + + && CCMIONewEntity + ( + &(globalState_->error), + (globalState_->root), + kCCMIOTopology, + nullptr, + &topoNode + ) + == kCCMIONoErr + ) + { + writeVertices(verticesNode); + writeInternalFaces(topoNode); + writeBoundaryFaces(topoNode); + writeCells(topoNode); + writeProblem(stateNode); + } + + // Now we have the mesh (vertices and topology), + // we can write out the processor information. + CCMIOWriteProcessor + ( + &(globalState_->error), + processorNode, + nullptr, &verticesNode, // no verticesFile, write verticesNode + nullptr, &topoNode, // no topologyFile, write topoNode + nullptr, nullptr, // initialField unchanged + nullptr, nullptr // no solutionFile, solution unchanged + ); + assertNoError("Error after writing geometry processor"); + +} + + +// ************************************************************************* // diff --git a/src/conversion/ccm/writer/ccmWriterSolution.C b/src/conversion/ccm/writer/ccmWriterSolution.C new file mode 100644 index 0000000000000000000000000000000000000000..c351ef76c86650be2bd3218bfb0d13e409ec4279 --- /dev/null +++ b/src/conversion/ccm/writer/ccmWriterSolution.C @@ -0,0 +1,814 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*----------------------------------------------------------------------------*/ + +#include "ccmWriter.H" +#include "dictionary.H" +#include "IFstream.H" +#include "IStringStream.H" +#include "volFields.H" +#include "surfaceFields.H" +#include "ccmInternal.H" // include last to avoid any strange interactions + + +// * * * * * * * * * * * * * * * Static Data Member * * * * * * * * * * * * // + +// names for known field types +Foam::dictionary Foam::ccm::writer::defaultNameMapping +( + IStringStream + ( + // volScalarField + "p { name P; Label \"Pressure\"; units \"Pa\"; }" + // "?? { name PTER; Label \"Thermo. Pressure\"; units \"Pa\"; }" + // "yPlus { name YPLU; Label \"YPLUS\"; }" + // "?? { name DIST; Label \"Normal Distance\"; units \"m\"; }" + // "?? { name H; Label \"Enthalpy\"; units \"J/kg\"; }" + "rho { name DENS; Label \"Density\"; units \"kg/m3\"; }" + "T { name T; Label \"Temperature\"; units \"K\"; }" + "k { name TE; Label \"Turb Kinetic Energy\"; units \"m2/s2\"; }" + "epsilon { name ED; Label \"Dissipation Rate\"; units \"m2/s3\"; }" + "mu { name LAMV; Label \"Molecular Viscosity\"; units \"Pa s\"; }" + "mut { name VIS; Label \"Turbulent Viscosity\"; units \"Pa s\"; }" + // volVectorField + "U { name ALL; Label \"Velocity\"; units \"m/s\"; }" + // U-components: + "_0U { name SU; Label \"Velocity Component U\"; units \"m/s\"; }" + "_1U { name SV; Label \"Velocity Component V\"; units \"m/s\"; }" + "_2U { name SW; Label \"Velocity Component W\"; units \"m/s\"; }" + // surfaceScalarField + "phi { name MassFlux; Label \"Mass Flux\"; units \"kg/s\"; }" + )() +); + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +bool Foam::ccm::writer::newFieldNode +( + const ccmID& phaseNode, + const word& fieldName, + const dictionary& nameMapping, + const ccmDimension& dims, + ccmID& fieldNode +) const +{ + if (!nameMapping.found(fieldName) || !nameMapping.isDict(fieldName)) + { + return false; + } + + const dictionary& dict = nameMapping.subDict(fieldName); + + word shortName; + if (!dict.readIfPresent("name", shortName)) + { + return false; + } + + string ccmLabel(fieldName); + dict.readIfPresent("Label", ccmLabel); + + CCMIONewField + ( + &(globalState_->error), + phaseNode, + ccmLabel.c_str(), + shortName.c_str(), + dims(), + &fieldNode + ); + + + string units; + if (dims() == kCCMIOScalar && dict.readIfPresent("units", units)) + { + CCMIOWriteOptstr + ( + &(globalState_->error), + fieldNode, + "Units", + units.c_str() + ); + } + + return true; + +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::ccm::writer::writeSolution +( + const IOobjectList& objects, + const fileName& remappingDictName +) +{ + const polyBoundaryMesh& patches = mesh_.boundaryMesh(); + + if (!isA<fvMesh>(mesh_)) + { + WarningIn("ccm::writer::writeSolution(const IOobjectList&, const fileName&)") + << "cannot write solutions with a polyMesh instead of a fvMesh" + << endl; + return; + } + + dictionary remapDict; + + if (remappingDictName.empty()) + { + remapDict = IOdictionary + ( + IOobject + ( + "remapping", + mesh_.time().constant(), + mesh_, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE, + false + ) + ); + } + else + { + // Specified (absolute/relative) name: treat like MUST_READ + remapDict = dictionary(IFstream(remappingDictName)()); + } + + + dictionary nameMapping(defaultNameMapping); + + // Merge without overwrite + if (remapDict.isDict("fields")) + { + nameMapping |= remapDict.subDict("fields"); + } + + + ccmID stateNode, processorNode, nodeId; + int procI = 0; + + // Create first ("default") state node + CCMIONewState + ( + &(globalState_->error), + (globalState_->root), + "default", + nullptr, + nullptr, + &stateNode + ); + assertNoError("could not create default state"); + + // Use first processor or create a new one + procI = 0; + if + ( + CCMIONextEntity + ( + nullptr, + stateNode, + kCCMIOProcessor, + &procI, + &processorNode + ) + != kCCMIONoErr + ) + { + CCMIONewEntity + ( + &(globalState_->error), + stateNode, + kCCMIOProcessor, + nullptr, + &processorNode + ); + assertNoError("could not create processor node"); + } + + // Remove old data (if it exists) + CCMIOClearProcessor + ( + nullptr, stateNode, processorNode, + true, // Clear vertices + true, // Clear topology + true, // Clear initial field + true, // Clear solution + true // Clear lagrangian + ); + + // + // Create vertices and topology nodes + // and references to vertices and topology files + // + { + ccmID verticesNode, topoNode; + CCMIONewEntity + ( + &(globalState_->error), + (globalState_->root), + kCCMIOVertices, + nullptr, + &verticesNode + ); + + CCMIONewEntity + ( + &(globalState_->error), + (globalState_->root), + kCCMIOTopology, + nullptr, + &topoNode + ); + + string topoFileName = defaultMeshName + ".ccmg"; + + CCMIOWriteProcessor + ( + &(globalState_->error), + processorNode, + topoFileName.c_str(), &verticesNode,// verticesFile, verticesNode + topoFileName.c_str(), &topoNode, // topologyFile, topologyNode + nullptr, nullptr, // initialField unchanged + nullptr, nullptr // no solutionFile, solution unchanged + ); + } + assertNoError("Error after writing geometry processor"); + + CCMIONewState + ( + &(globalState_->error), + (globalState_->root), + "Restart_1", + nullptr, + nullptr, + &stateNode + ); + assertNoError("could not create Restart_1 state"); + + // Use first processor or create a new one + procI = 0; + if + ( + CCMIONextEntity + ( + nullptr, + stateNode, + kCCMIOProcessor, + &procI, + &processorNode + ) + != kCCMIONoErr + ) + { + CCMIONewEntity + ( + &(globalState_->error), + stateNode, + kCCMIOProcessor, + nullptr, + &processorNode + ); + assertNoError("could not create 'Processor' node"); + } + + // Remove old data (if it exists) + CCMIOClearProcessor + ( + nullptr, stateNode, processorNode, + true, // Clear vertices + true, // Clear topology + true, // Clear initial field + true, // Clear solution + true // Clear lagrangian + ); + + // Write out some simple solution data + ccmID phaseNode, fieldSetNode; + + // Use first FieldSet + int fieldSetI = 0; + if + ( + CCMIONextEntity + ( + nullptr, + (globalState_->root), + kCCMIOFieldSet, + &fieldSetI, + &fieldSetNode + ) + != kCCMIONoErr + ) + { + CCMIONewEntity + ( + &(globalState_->error), + (globalState_->root), + kCCMIOFieldSet, + nullptr, + &fieldSetNode + ); + assertNoError("could not create FieldSet node"); + } + + // RestartInfo + { + ccmID restartInfoNode, restartDataNode; + CCMIONewEntity + ( + &(globalState_->error), + fieldSetNode, + kCCMIORestart, + nullptr, + &restartInfoNode + ); + assertNoError("could not create restartInfoNode node"); + + // Get time information + const Time& runTime = mesh_.time(); + label timeIndex = 0; + // scalar timeValue = runTime.timeName(); + 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.typeHeaderOk<IOdictionary>(true)) + { + IOdictionary timeObject + ( + IOobject + ( + "time", + runTime.timeName(), + "uniform", + runTime, + IOobject::MUST_READ, + IOobject::NO_WRITE, + false + ) + ); + + timeObject.lookup("index") >> timeIndex; + } + } + + CCMIOWriteRestartInfo + ( + &(globalState_->error), + restartInfoNode, + "ccm::writer", // solverName + timeIndex, // iteration + 0.0, // time + nullptr, // timeUnits: default (s) + 0.0 // startAngle: non-rotating mesh + ); + + // RestartData + CCMIONewEntity + ( + &(globalState_->error), + restartInfoNode, + kCCMIORestartData, + nullptr, + &restartDataNode + ); + assertNoError("could not create restartDataNode node"); + + // Minimal information required by PROSTAR + + CCMIOWriteOptf + ( + nullptr, + restartDataNode, + "SCALE", + 0.001 // [m] -> [mm]: PROSTAR is still a bit buggy here + ); + + + // Add Phase data + CCMIONewIndexedEntity + ( + &(globalState_->error), + restartDataNode, + kCCMIOFieldPhase, + 1, + nullptr, + &nodeId + ); + + // HACK: for calculating Mach number + // FIXME: use thermodynamicProperties /or/ thermophysicalProperties + CCMIOWriteOptf + ( + nullptr, + nodeId, + "Material Specific Heat", + 1007 + ); + + CCMIOWriteOptf + ( + nullptr, + nodeId, + "Material Molecular Weight", + 28.96 + ); + } + + CCMIONewIndexedEntity + ( + &(globalState_->error), + fieldSetNode, + kCCMIOFieldPhase, + 1, + "Phase_0001", + &phaseNode + ); + + + + forAllConstIter(IOobjectList, objects, iter) + { + word fieldName = (*iter()).name(); + bool variableGood = + ( + nameMapping.found(fieldName) + && (*iter()).typeHeaderOk<volScalarField>(false) + ); + + if (!variableGood) + { + // Only retain registered fields that are also readable + continue; + } + + word fieldType = (*iter()).headerClassName(); + + if (fieldType == volScalarField::typeName) + { + Info<< " " << fieldName << flush; + + volScalarField field + ( + IOobject + ( + fieldName, + mesh_.time().timeName(), + mesh_, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE + ), + refCast<const fvMesh>(mesh_) + ); + + ccmID fieldNode; + + // Info<< " call newFieldNode " << fieldName << flush; + + if + ( + !newFieldNode + ( + phaseNode, + fieldName, + nameMapping, + kCCMIOScalar, + fieldNode + ) + ) + { + continue; + } + + // Write cellData first + CCMIONewEntity + ( + &(globalState_->error), + fieldNode, + kCCMIOFieldData, + nullptr, + &nodeId + ); + + CCMIOWriteFieldDatad + ( + &(globalState_->error), + nodeId, + maps_->cells, + kCCMIOCell, + const_cast<scalar*> + ( + field.primitiveField().begin() + ), + kCCMIOStart, + kCCMIOEnd + ); + assertNoError("writing internalField " + fieldName); + + // Write boundaryData + forAll(patches, patchI) + { + CCMIONewEntity + ( + &(globalState_->error), + fieldNode, + kCCMIOFieldData, + nullptr, + &nodeId + ); + + CCMIOWriteFieldDatad + ( + &(globalState_->error), + nodeId, + maps_->boundary[patchI], + kCCMIOFace, + const_cast<scalar*> + ( + field.boundaryField()[patchI].begin() + ), + kCCMIOStart, + kCCMIOEnd + ); + } + + assertNoError("writing boundaryField " + fieldName); + } + else if (fieldType == volVectorField::typeName && fieldName == "U") + { + Info<< " " << fieldName << flush; + + volVectorField vfield + ( + IOobject + ( + fieldName, + mesh_.time().timeName(), + mesh_, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE + ), + refCast<const fvMesh>(mesh_) + ); + + + ccmID vectorNode; + newFieldNode + ( + phaseNode, + fieldName, + nameMapping, + kCCMIOVector, + vectorNode + ); + + for (direction cmpt=0; cmpt < pTraits<vector>::nComponents; ++cmpt) + { + word componentName("_" + Foam::name(cmpt) + fieldName); + volScalarField field(vfield.component(cmpt)); + + CCMIOComponent ccmComponent = kCCMIOVectorX; + switch(cmpt) { + case 0: + ccmComponent = kCCMIOVectorX; + break; + case 1: + ccmComponent = kCCMIOVectorY; + break; + case 2: + ccmComponent = kCCMIOVectorZ; + break; + } + + ccmID componentNode; + if + ( + !newFieldNode + ( + phaseNode, + componentName, + nameMapping, + kCCMIOScalar, + componentNode + ) + ) + { + continue; + } + + // Re-register with vector field + CCMIOWriteMultiDimensionalFieldData + ( + &(globalState_->error), + vectorNode, + ccmComponent, + componentNode + ); + + // Write cellData first + CCMIONewEntity + ( + &(globalState_->error), + componentNode, + kCCMIOFieldData, + nullptr, + &nodeId + ); + + CCMIOWriteFieldDatad + ( + &(globalState_->error), + nodeId, + maps_->cells, + kCCMIOCell, + const_cast<scalar*> + ( + field.primitiveField().begin() + ), + kCCMIOStart, kCCMIOEnd + ); + assertNoError + ( + "writing internalField " + fieldName + " " + componentName + ); + + + // Write boundaryData + forAll(patches, patchI) + { + CCMIONewEntity + ( + &(globalState_->error), + componentNode, + kCCMIOFieldData, + nullptr, + &nodeId + ); + + CCMIOWriteFieldDatad + ( + &(globalState_->error), + nodeId, + maps_->boundary[patchI], + kCCMIOFace, + const_cast<scalar*> + ( + field.boundaryField()[patchI].begin() + ), + kCCMIOStart, kCCMIOEnd + ); + } + + assertNoError + ( + "writing boundaryField " + fieldName + " " + componentName + ); + } + } + else if (fieldType == surfaceScalarField::typeName) + { +#if 0 + // Still have problems reading surface fields in PROSTAR + Info<< " " << fieldName << flush; + + surfaceScalarField field + ( + IOobject + ( + fieldName, + mesh_.time().timeName(), + mesh_, + IOobject::READ_IF_PRESENT, + IOobject::NO_WRITE + ), + refCast<const fvMesh>(mesh_) + ); + + ccmID fieldNode; + + // Info<< " call newFieldNode " << fieldName << flush; + + if + ( + !newFieldNode + ( + phaseNode, + fieldName, + nameMapping, + kCCMIOScalar, + fieldNode + ) + ) + { + continue; + } + + // Write cell faceData first + CCMIONewEntity + ( + &(globalState_->error), + fieldNode, + kCCMIOFieldData, + nullptr, + &nodeId + ); + + CCMIOWriteFieldDatad + ( + &(globalState_->error), + nodeId, + maps_->internalFaces, + kCCMIOFace, + const_cast<scalar*> + ( + field.primitiveField().begin() + ), + kCCMIOStart, + kCCMIOEnd + ); + assertNoError("writing internalField " + fieldName); + + // Write boundaryData + forAll(patches, patchI) + { + CCMIONewEntity + ( + &(globalState_->error), + fieldNode, + kCCMIOFieldData, + nullptr, + &nodeId + ); + + CCMIOWriteFieldDatad + ( + &(globalState_->error), + nodeId, + maps_->boundary[patchI], + kCCMIOFace, + field.boundaryField()[patchI].begin(), + kCCMIOStart, + kCCMIOEnd + ); + } + + assertNoError("writing boundaryField " + fieldName); +#endif + } + } + Info<< endl; + + assertNoError("Error before writing processor"); + + CCMIOWriteProcessor + ( + &(globalState_->error), + processorNode, + nullptr, nullptr, // vertices + nullptr, nullptr, // topology + nullptr, nullptr, // initial field + nullptr, &fieldSetNode + ); + assertNoError("Error after writing processor"); +} + + +// ************************************************************************* // diff --git a/src/conversion/common/reader/meshReader.C b/src/conversion/common/reader/meshReader.C index c7e2d67980f6a0419c5a8168a04d274b445aeebd..4a6356910cb76d13e11e8d34a6c0d8273068af13 100644 --- a/src/conversion/common/reader/meshReader.C +++ b/src/conversion/common/reader/meshReader.C @@ -213,7 +213,13 @@ Foam::meshReader::meshReader baffleFaces_(0), cellTableId_(0), cellTable_() -{} +{ + // Sanity + if (scaleFactor_ <= VSMALL) + { + scaleFactor_ = 1; + } +} // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // diff --git a/src/conversion/common/reader/meshReader.H b/src/conversion/common/reader/meshReader.H index 54d5876e96448902374c72fb9fe7b06076da3756..b53d0c1e4dfbcdd93da2f09f35b3e47f1b177a7c 100644 --- a/src/conversion/common/reader/meshReader.H +++ b/src/conversion/common/reader/meshReader.H @@ -275,7 +275,7 @@ public: // Constructors //- Construct from fileName - meshReader(const fileName&, const scalar scaleFactor = 1.0); + meshReader(const fileName&, const scalar scaling = 1.0); //- Destructor diff --git a/src/conversion/common/writer/meshWriter.C b/src/conversion/common/writer/meshWriter.C index 36d6426757254d8ab97ecf9da6d3bbfaeadcbb2c..760cccea7a23697c655ef3fed30b4a42bf9568d2 100644 --- a/src/conversion/common/writer/meshWriter.C +++ b/src/conversion/common/writer/meshWriter.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -68,15 +68,24 @@ lookup // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -Foam::meshWriter::meshWriter(const polyMesh& mesh, const scalar scaleFactor) +Foam::meshWriter::meshWriter +( + const polyMesh& mesh, + const scalar scaling +) : mesh_(mesh), - scaleFactor_(scaleFactor), - writeBoundary_(true), + scaleFactor_(scaling), boundaryRegion_(), cellTable_(), cellTableId_() -{} +{ + // Sanity + if (scaleFactor_ <= VSMALL) + { + scaleFactor_ = 1; + } +} // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // diff --git a/src/conversion/common/writer/meshWriter.H b/src/conversion/common/writer/meshWriter.H index 51f4c4014a911bd39d48b9da74d6796f5aa958a3..d17322fde0754480c3eb7a2a6864fba89b318d6f 100644 --- a/src/conversion/common/writer/meshWriter.H +++ b/src/conversion/common/writer/meshWriter.H @@ -98,9 +98,6 @@ protected: //- Scaling factor for points (eg, [m] -> [mm]) scalar scaleFactor_; - //- Write bnd file - bool writeBoundary_; - //- boundaryRegion persistent data saved as a dictionary boundaryRegion boundaryRegion_; @@ -125,13 +122,14 @@ public: //- Specify a default mesh name static string defaultMeshName; + // Constructors - //- Create a writer object + //- Create a writer object with given output scaling meshWriter ( const polyMesh&, - const scalar scaleFactor = 1.0 + const scalar scaling = 1.0 ); @@ -141,28 +139,13 @@ public: // Member Functions - // Edit - - //- Set points scaling - void scaleFactor(const scalar scaling) - { - scaleFactor_ = scaling; - } + // Write - //- Suppress writing boundary (bnd) file - void noBoundary() - { - writeBoundary_ = false; - } - - - // Write - - //- Write volume mesh. Subclass must supply this method - virtual bool write - ( - const fileName& timeName = fileName::null - ) const = 0; + //- Write volume mesh. Subclass must supply this method + virtual bool write + ( + const fileName& timeName = fileName::null + ) const = 0; }; diff --git a/src/conversion/fire/FIREMeshReader.C b/src/conversion/fire/FIREMeshReader.C new file mode 100644 index 0000000000000000000000000000000000000000..ef8576cf5f543665a282d97ecf9250a20cbf607c --- /dev/null +++ b/src/conversion/fire/FIREMeshReader.C @@ -0,0 +1,549 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "FIREMeshReader.H" +#include "wallPolyPatch.H" +#include "ListOps.H" +#include "IFstream.H" + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::word Foam::fileFormats::FIREMeshReader::validateWord +( + const std::string& str +) +{ + std::string::size_type ngood = 0; + bool prefix = false; + bool first = true; + + for + ( + std::string::const_iterator iter = str.begin(); + iter != str.end(); + ++iter + ) + { + if (word::valid(*iter)) + { + ++ngood; + if (first) + { + first = false; + + // start with a digit? need to prefix with '_' + if (isdigit(*iter)) + { + prefix = true; + } + } + } + } + + if (prefix) + { + ++ngood; + } + else if (ngood == str.size()) + { + return str; + } + + Foam::word out; + out.resize(ngood); + ngood = 0; + + Foam::word::iterator iter2 = out.begin(); + for + ( + std::string::const_iterator iter1 = str.begin(); + iter1 != str.end(); + ++iter1 + ) + { + register char c = *iter1; + + if (Foam::word::valid(c)) + { + if (prefix) + { + prefix = false; + *(iter2++) = '_'; + ++ngood; + } + *(iter2++) = c; + ++ngood; + } + } + + out.resize(ngood); + + return out; +} + + +void Foam::fileFormats::FIREMeshReader::readPoints +( + ISstream& is, + const scalar scaleFactor +) +{ + const label n = FIRECore::readPoints(is, points_); + // the above has FatalError if there are no points + + Info<< "Number of points = " << n << endl; + if (scaleFactor > 1.0 + SMALL || scaleFactor < 1.0 - SMALL) + { + points_ *= scaleFactor; + } +} + + +void Foam::fileFormats::FIREMeshReader::readFaces(ISstream& is) +{ + const label nFaces = getFireLabel(is); + Info<< "Number of faces = " << nFaces << endl; + meshFaces_.setSize(nFaces); + + if (nFaces > 0) + { + forAll(meshFaces_, faceI) + { + const label size = getFireLabel(is); + + face& f = meshFaces_[faceI]; + f.setSize(size); + forAll(f, fp) + { + f[fp] = getFireLabel(is); + } + + // flip in-place + f.flip(); + } + } + else + { + FatalErrorInFunction + << "no faces in file " << is.name() + << abort(FatalError); + } +} + + +void Foam::fileFormats::FIREMeshReader::readCells(ISstream& is) +{ + const label nCells = getFireLabel(is); + Info<< "Number of cells = " << nCells << endl; + + owner_.setSize(meshFaces_.size()); + neigh_.setSize(meshFaces_.size()); + + owner_ = -1; + neigh_ = -1; + + if (nCells > 0) + { + for (label cellI = 0; cellI < nCells; ++cellI) + { + const label nface = getFireLabel(is); + + for (label i = 0; i < nface; ++i) + { + const label faceI = getFireLabel(is); + + if (owner_[faceI] == -1) + { + owner_[faceI] = cellI; + } + else if (neigh_[faceI] == -1) + { + neigh_[faceI] = cellI; + } + else + { + Warning + << "bad cell connectivity for face " << faceI + << " on cell " << cellI + << endl; + } + } + } + } + else + { + FatalErrorInFunction + << "no cells in file " << is.name() + << abort(FatalError); + } + + cellTableId_.setSize(nCells); + cellTableId_ = -1; +} + + +void Foam::fileFormats::FIREMeshReader::readSelections(ISstream& is) +{ + const label nSelect = getFireLabel(is); + Info<< "Number of select = " << nSelect << endl; + + label nCellSelections = 0; + label nFaceSelections = 0; + + faceZoneId_.setSize(meshFaces_.size()); + faceZoneId_ = -1; + + DynamicList<word> faceNames(32); + + for (label selI = 0; selI < nSelect; ++selI) + { + std::string name = getFireString(is); + const label selType = getFireLabel(is); + const label count = getFireLabel(is); + + if (selType == FIRECore::cellSelection) + { + // index starting at 1 + const label selId = ++nCellSelections; + + cellTable_.setName(selId, validateWord(name)); + cellTable_.setMaterial(selId, "fluid"); + + for (label i = 0; i < count; ++i) + { + const label cellId = getFireLabel(is); + + cellTableId_[cellId] = selId; + } + } + else if (selType == FIRECore::faceSelection) + { + // index starting at 0 + const label selId = nFaceSelections++; + + faceNames.append(validateWord(name)); + + for (label i = 0; i < count; ++i) + { + const label faceId = getFireLabel(is); + + faceZoneId_[faceId] = selId; + } + } + else + { + // discard other selection types (eg, nodes) + for (label i = 0; i < count; ++i) + { + getFireLabel(is); + } + } + } + + Info<< nFaceSelections << " face selections" << endl; + Info<< nCellSelections << " cell selections" << endl; + + // add extra for missed boundary faces + faceNames.append("__MISSED_FACES__"); + faceNames_.transfer(faceNames); +} + + +void Foam::fileFormats::FIREMeshReader::reorganize() +{ + nInternalFaces_ = 0; + + // pass 1: + // count internal faces and also swap owner <-> neigh as required + forAll(meshFaces_, faceI) + { + if (neigh_[faceI] != -1) + { + ++nInternalFaces_; + + if (owner_[faceI] > neigh_[faceI]) + { + Swap(owner_[faceI], neigh_[faceI]); + } + } + } + + label posInternal = 0; + label posExternal = nInternalFaces_; + + labelList oldToNew(meshFaces_.size(), -1); + + // pass 2: + // mapping to ensure proper division of internal / external + forAll(meshFaces_, faceI) + { + if (neigh_[faceI] == -1) + { + oldToNew[faceI] = posExternal++; + } + else + { + oldToNew[faceI] = posInternal++; + } + } + + inplaceReorder(oldToNew, meshFaces_); + inplaceReorder(oldToNew, owner_); + inplaceReorder(oldToNew, neigh_); + inplaceReorder(oldToNew, faceZoneId_); + + // determine the patch sizes - faceNames_ already has extra place for missed faces + const label zoneMissed = faceNames_.size() - 1; + patchSizes_.setSize(faceNames_.size()); + patchSizes_ = 0; + + patchStarts_.setSize(patchSizes_.size()); + patchStarts_ = 0; + + for (label faceI = nInternalFaces_; faceI < meshFaces_.size(); ++faceI) + { + label zoneI = faceZoneId_[faceI]; + if (zoneI == -1) + { + ++patchSizes_[zoneMissed]; + } + else + { + ++patchSizes_[zoneI]; + } + } + + if (patchSizes_[zoneMissed]) + { + Info<<"collecting " << patchSizes_[zoneMissed] + << " missed boundary faces to final patch" << endl; + } + + oldToNew = -1; + + // calculate the patch starts + { + label pos = nInternalFaces_; + + forAll(patchStarts_, patchI) + { + patchStarts_[patchI] = pos; + pos += patchSizes_[patchI]; + } + + forAll(patchSizes_, patchI) + { + patchSizes_[patchI] = 0; + } + } + + // reordering + for (label faceI = nInternalFaces_; faceI < meshFaces_.size(); ++faceI) + { + label patchI = faceZoneId_[faceI]; + if (patchI == -1) + { + oldToNew[faceI] = patchStarts_[zoneMissed] + patchSizes_[zoneMissed]; + ++patchSizes_[zoneMissed]; + } + else + { + oldToNew[faceI] = patchStarts_[patchI] + patchSizes_[patchI]; + ++patchSizes_[patchI]; + } + } + + // discard old information + faceZoneId_.clear(); + + inplaceReorder(oldToNew, meshFaces_); + inplaceReorder(oldToNew, owner_); + inplaceReorder(oldToNew, neigh_); + + //--- neigh_.setSize(nInternalFaces_); + + // finally reduce to the number of patches actually used + patchNames_.setSize(patchSizes_.size()); + oldToNew = -1; + + label nPatches = 0; + forAll(patchSizes_, patchI) + { + if (patchSizes_[patchI]) + { + patchNames_[nPatches] = faceNames_[patchI]; + + oldToNew[patchI] = nPatches; + ++nPatches; + } + } + + inplaceReorder(oldToNew, patchStarts_); + inplaceReorder(oldToNew, patchSizes_); + + patchStarts_.setSize(nPatches); + patchSizes_.setSize(nPatches); + patchNames_.setSize(nPatches); +} + + +void Foam::fileFormats::FIREMeshReader::addPatches(polyMesh& mesh) const +{ + // create patches + List<polyPatch*> newPatches(patchSizes_.size()); + + label meshFaceI = nInternalFaces_; + + forAll(patchStarts_, patchI) + { + Info<< "patch " << patchI + << " (start: " << meshFaceI << " size: " << patchSizes_[patchI] + << ") name: " << patchNames_[patchI] + << endl; + + // don't know anything better - just make it a wall + newPatches[patchI] = new polyPatch + ( + patchNames_[patchI], + patchSizes_[patchI], + meshFaceI, + patchI, + mesh.boundaryMesh(), + word::null + ); + + meshFaceI += patchSizes_[patchI]; + } + + mesh.addPatches(newPatches); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +bool Foam::fileFormats::FIREMeshReader::readGeometry(const scalar scaleFactor) +{ + IOstream::streamFormat fmt = IOstream::ASCII; + + const word ext = geometryFile_.ext(); + bool supported = FIRECore::file3dExtensions.found(ext); + if (supported) + { + FIRECore::fileExt3d fireFileType = FIRECore::file3dExtensions[ext]; + if (fireFileType == FIRECore::POLY_ASCII) + { + fmt = IOstream::ASCII; + } + else if (fireFileType == FIRECore::POLY_BINARY) + { + fmt = IOstream::BINARY; + } + else + { + // compressed or something + supported = false; + } + } + + if (!supported) + { + FatalErrorInFunction + << "File-type '" << ext + << "' is not supported for reading as a FIRE mesh." << nl + << "If it is a compressed file, use gunzip first." + << abort(FatalError); + } + + IFstream is(geometryFile_, fmt, false); + + readPoints(is, scaleFactor); + readFaces(is); + readCells(is); + readSelections(is); + + return true; +} + +Foam::autoPtr<Foam::polyMesh> Foam::fileFormats::FIREMeshReader::mesh +( + const objectRegistry& registry +) +{ + readGeometry(scaleFactor_); + reorganize(); + + Info<< "Creating a polyMesh" << endl; + + autoPtr<polyMesh> mesh + ( + new polyMesh + ( + IOobject + ( + polyMesh::defaultRegion, + "constant", + registry + ), + xferMove(points_), + xferMove(meshFaces_), + xferMove(owner_), + xferMove(neigh_) + ) + ); + + // adding patches also checks the mesh + addPatches(mesh()); + + cellTable_.addCellZones(mesh(), cellTableId_); + + // addFaceZones(mesh()); + + return mesh; +} + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::fileFormats::FIREMeshReader::FIREMeshReader +( + const fileName& name, + const scalar scaleFactor +) +: + meshReader(name, scaleFactor), + owner_(0), + neigh_(0), + faceZoneId_(0), + faceNames_() +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::fileFormats::FIREMeshReader::~FIREMeshReader() +{} + + +// ************************************************************************* // diff --git a/src/conversion/fire/FIREMeshReader.H b/src/conversion/fire/FIREMeshReader.H new file mode 100644 index 0000000000000000000000000000000000000000..0c95cb5fa21eb39a0110168d8d4d90e0436478ac --- /dev/null +++ b/src/conversion/fire/FIREMeshReader.H @@ -0,0 +1,140 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::fileFormats::FIREMeshReader + +Description + Read AVL/FIRE fpma, fpmb files. + +Note + Does not handle compressed versions (fpmaz, fpmbz) of these files. + +SourceFiles + FIREMeshReader.C + +\*---------------------------------------------------------------------------*/ + +#ifndef FIREMeshReader_H +#define FIREMeshReader_H + +#include "meshReader.H" +#include "FIRECore.H" +#include "labelList.H" +#include "IFstream.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +// forward declarations +class polyMesh; + +namespace fileFormats +{ + +/*---------------------------------------------------------------------------*\ + Class fileFormats::FIREMeshReader Declaration +\*---------------------------------------------------------------------------*/ + +class FIREMeshReader +: + public meshReader, + public FIRECore +{ + +protected: + + // Protected Data + + labelList owner_; + labelList neigh_; + + labelList faceZoneId_; + wordList faceNames_; + + + // Protected Member Functions + + //- Disallow default bitwise copy construct + FIREMeshReader(const FIREMeshReader&) = delete; + + //- Disallow default bitwise assignment + void operator=(const FIREMeshReader&) = delete; + + + //- Validate word (eg, avoid leading digits) + static word validateWord(const std::string&); + + + //- Read the mesh from the file(s) + virtual bool readGeometry(const scalar scaleFactor = 1.0); + + //- Read points from file + void readPoints(ISstream&, const scalar scaleFactor = 1.0); + + //- Read points from file + void readFaces(ISstream&); + + //- Read cell connectivities from file + void readCells(ISstream&); + + //- Read cell/face selections from file + void readSelections(ISstream&); + + //- + void reorganize(); + + void addPatches(polyMesh&) const; + + +public: + + // Constructors + + //- Construct by reading file, optionally with scaling + FIREMeshReader(const fileName&, const scalar scaleFactor = 1.0); + + + //- Destructor + virtual ~FIREMeshReader(); + + + // Member Functions + + //- Create and return polyMesh + virtual autoPtr<polyMesh> mesh(const objectRegistry&); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace fileFormats +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/fire/FIREMeshWriter.C b/src/conversion/fire/FIREMeshWriter.C new file mode 100644 index 0000000000000000000000000000000000000000..29746005d077f069cf23f14214cfdd7c86d059c0 --- /dev/null +++ b/src/conversion/fire/FIREMeshWriter.C @@ -0,0 +1,364 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "FIREMeshWriter.H" +#include "Time.H" +#include "HashTable.H" +#include "OFstream.H" +#include "processorPolyPatch.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +bool Foam::fileFormats::FIREMeshWriter::binary = false; +bool Foam::fileFormats::FIREMeshWriter::compress = false; +bool Foam::fileFormats::FIREMeshWriter::prefixBoundary = true; + + +//! \cond fileScope +//- Output newline in ascii mode, no-op in binary mode +inline static void newline(Foam::OSstream& os) +{ + if (os.format() == Foam::IOstream::ASCII) + { + os << Foam::endl; + } +} + +//! \endcond + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + + +bool Foam::fileFormats::FIREMeshWriter::writeGeometry(OSstream& os) const +{ + const faceList& faces = mesh_.faces(); + const pointField& points = mesh_.points(); + const cellList& cells = mesh_.cells(); + + // Points + // ~~~~~~ + + // Set the precision of the points data to 10 + os.precision(10); + + Info<< "points: " << points.size() << endl; + putFireLabel(os, points.size()); + newline(os); + + forAll(points, ptI) + { + // scaling is normally 1 (ie, none) + putFirePoint(os, scaleFactor_ * points[ptI]); + } + newline(os); // readability + + + // Faces + // ~~~~~ + // OPENFOAM - faces normals are outward-facing. + // FIRE - faces normals are inward-facing. + + Info<< "faces: " << faces.size() << endl; + putFireLabel(os, faces.size()); + newline(os); + + forAll(faces, faceI) + { + // flip face + putFireLabels(os, faces[faceI].reverseFace()); + } + newline(os); // readability + + + // Cells + // ~~~~~ + + Info<< "cells: " << cells.size() << endl; + putFireLabel(os, cells.size()); + newline(os); + + forAll(cells, cellId) + { + putFireLabels(os, cells[cellId]); + } + newline(os); // readability + + return os.good(); +} + + +bool Foam::fileFormats::FIREMeshWriter::writeSelections(OSstream& os) const +{ + label nZones = 0; + label nPatches = 0; + + // remap name between patches and cell-zones conflicts! + + HashTable<word, label> patchNames; + HashTable<word, label> zoneNames; + + wordHashSet usedPatchNames; + wordHashSet usedZoneNames; + + // boundaries, skipping empty and processor patches + forAll(mesh_.boundaryMesh(), patchI) + { + const polyPatch& patch = mesh_.boundaryMesh()[patchI]; + if (patch.size() && !isA<processorPolyPatch>(patch)) + { + ++nPatches; + + const word oldName = patch.name(); + word newName; + if (prefixBoundary) + { + newName = "BND_" + oldName; + + if (usedPatchNames.found(newName)) + { + newName = "BND_patch" + ::Foam::name(patchI); + } + } + else + { + newName = oldName; + + if (usedPatchNames.found(newName)) + { + newName = "patch" + ::Foam::name(patchI); + } + } + + usedPatchNames.set(newName); + patchNames.set(patchI, newName); + } + } + + + // cellzones, skipping empty zones + forAll(mesh_.cellZones(), zoneI) + { + const cellZone& cZone = mesh_.cellZones()[zoneI]; + if (cZone.size()) + { + ++nZones; + + const word oldName = cZone.name(); + word newName = oldName; + + if (usedPatchNames.found(newName) || usedZoneNames.found(newName)) + { + newName = "CEL_zone" + ::Foam::name(zoneI); + } + + usedZoneNames.set(newName); + zoneNames.set(zoneI, newName); + } + } + + + // + // actually write things + // + + putFireLabel(os, (nZones + nPatches)); + newline(os); + + // do cell zones + forAll(mesh_.cellZones(), zoneI) + { + const cellZone& cZone = mesh_.cellZones()[zoneI]; + + if (cZone.size()) + { + Info<< "cellZone " << zoneI + << " (size: " << cZone.size() + << ") name: " << zoneNames[zoneI] << nl; + + putFireString(os, zoneNames[zoneI]); + putFireLabel(os, static_cast<int>(FIRECore::cellSelection)); + newline(os); + + putFireLabels(os, cZone); + newline(os); // readability + } + } + + // do boundaries, skipping empty and processor patches + forAll(mesh_.boundaryMesh(), patchI) + { + const polyPatch& patch = mesh_.boundaryMesh()[patchI]; + if (patch.size() && !isA<processorPolyPatch>(patch)) + { + Info<< "patch " << patchI + << " (start: " << patch.start() << " size: " << patch.size() + << ") name: " << patchNames[patchI] + << endl; + + putFireString(os, patchNames[patchI]); + putFireLabel(os, static_cast<int>(FIRECore::faceSelection)); + newline(os); + + putFireLabels(os, patch.size(), patch.start()); + newline(os); // readability + } + + newline(os); // readability + } + + return os.good(); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::fileFormats::FIREMeshWriter::FIREMeshWriter +( + const polyMesh& mesh, + const scalar scaleFactor +) +: + meshWriter(mesh, scaleFactor) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::fileFormats::FIREMeshWriter::~FIREMeshWriter() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::fileFormats::FIREMeshWriter::write(const fileName& meshName) const +{ + bool useBinary = binary; + bool useCompress = compress; + + fileName baseName(meshName); + if (baseName.empty()) + { + baseName = meshWriter::defaultMeshName; + + const Time& t = mesh_.time(); + + if + ( + t.timeName() != "0" + && t.timeName() != t.constant() + ) + { + baseName += "_" + t.timeName(); + } + } + else + { + const word ext = baseName.ext(); + + if (FIRECore::file3dExtensions.found(ext)) + { + FIRECore::fileExt3d fireFileType = FIRECore::file3dExtensions[ext]; + if (fireFileType == FIRECore::POLY_ASCII) + { + useBinary = false; + useCompress = false; + } + else if (fireFileType == FIRECore::POLY_BINARY) + { + useBinary = true; + useCompress = false; + } + else if (fireFileType == FIRECore::POLY_ASCII_COMPRESSED) + { + useBinary = false; + useCompress = true; + } + else if (fireFileType == FIRECore::POLY_BINARY_COMPRESSED) + { + useBinary = true; + useCompress = true; + } + } + + baseName = baseName.lessExt(); + } + + + // A slight hack. Cannot generate compressed files with the desired ending + // So create and rename later + const fileName filename = FIRECore::fireFileName + ( + baseName, + useBinary ? FIRECore::POLY_BINARY : FIRECore::POLY_ASCII + ); + + autoPtr<OFstream> osPtr + ( + new OFstream + ( + filename, + (useBinary ? IOstream::BINARY : IOstream::ASCII), + IOstream::currentVersion, + (useCompress ? IOstream::COMPRESSED : IOstream::UNCOMPRESSED) + ) + ); + + if (osPtr->good()) + { + Info<< "Writing output to "; + if (useCompress) + { + // output .fpmaz instead of .fpma + Info<< '"' << osPtr().name().c_str() << "z\"" << endl; + } + else + { + Info<< osPtr().name() << endl; + } + + writeGeometry(osPtr()); + writeSelections(osPtr()); + + osPtr.clear(); // implicitly close the file + + if (useCompress) + { + // rename .fpma.gz -> .fpmaz + // The '.gz' is automatically added by OFstream in compression mode + Foam::mv(filename + ".gz", filename + "z"); + } + } + else + { + Info<<"could not open file for writing " << filename << endl; + return false; + } + + return true; +} + + +// ************************************************************************* // diff --git a/src/conversion/fire/FIREMeshWriter.H b/src/conversion/fire/FIREMeshWriter.H new file mode 100644 index 0000000000000000000000000000000000000000..7d61a0461eb9a585787174f1d8cba60a1b308690 --- /dev/null +++ b/src/conversion/fire/FIREMeshWriter.H @@ -0,0 +1,130 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::fileFormats::FIREMeshWriter + +Description + Writes polyMesh in AVL/FIRE polyhedra format (fpma, fpmb) + + It is also possible to write compressed formats (fpmaz, fpmbz) + +Note + The fpma, fpmb formats are relatively poorly documented, but are manageable + to read and write. It is, however, not recommended to import them directly + into AVL/FIRE (the GUI) since it is generally not robust enough. + Instead use their file-convertor to reconvert them into their native format. + + In the AVL/FIRE polyhedra format, the faces normals point inwards, whereas + the OpenFOAM face normals always point outwards. + +SourceFiles + FIREMeshWriter.C + +\*---------------------------------------------------------------------------*/ + +#ifndef FIREMeshWriter_H +#define FIREMeshWriter_H + +#include "meshWriter.H" +#include "FIRECore.H" +#include "IOstream.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace fileFormats +{ + +/*---------------------------------------------------------------------------*\ + Class fileFormats::FIREMeshWriter Declaration +\*---------------------------------------------------------------------------*/ + +class FIREMeshWriter +: + public meshWriter, + public FIRECore +{ + // Private Member Functions + + //- Disallow default bitwise copy construct + FIREMeshWriter(const FIREMeshWriter&) = delete; + + //- Disallow default bitwise assignment + void operator=(const FIREMeshWriter&) = delete; + + //- Write points, faces, cells + bool writeGeometry(OSstream&) const; + + //- Write selections + bool writeSelections(OSstream&) const; + +public: + + // Static data members + + //- Write binary (default ascii) + static bool binary; + + //- Write with compression (default false) + static bool compress; + + //- Prefix patches with 'BND_' before writing (default true) + static bool prefixBoundary; + + + // Constructors + + //- Prepare for writing, optionally with scaling + FIREMeshWriter(const polyMesh&, const scalar scaleFactor = 1.0); + + + //- Destructor + virtual ~FIREMeshWriter(); + + + // Member Functions + + // Write + + //- Write volume mesh + virtual bool write + ( + const fileName& meshName = fileName::null + ) const; + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace fileFormats +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/fire/checkFireEdges.C b/src/conversion/fire/checkFireEdges.C new file mode 100644 index 0000000000000000000000000000000000000000..eb7c3bf9da11bc5bf539062a256357bf83b5852b --- /dev/null +++ b/src/conversion/fire/checkFireEdges.C @@ -0,0 +1,299 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "checkFireEdges.H" +#include "polyMesh.H" +#include "edge.H" +#include "HashSet.H" +#include "ListOps.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + //! \cond fileScope + //- Print face information for debugging purposes + static inline void printFace + ( + const face& f, + label faceI, + const edge& currEdge + ) + { + Info<< "face " << faceI << ':'; + forAll(f, fpI) + { + Info<< ' '; + if (f[fpI] == currEdge[0] || f[fpI] == currEdge[1]) + { + Info<< '_'; // highlight the node + } + Info<< f[fpI]; + } + Info<< endl; + } + //! \endcond +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +Foam::label Foam::checkFireEdges +( + const faceList& faces, + const labelListList& pointFaces, + const UList<point>& points +) +{ + label nFailedEdges = 0; + const bool fullCheck = true; + typedef HashSet<edge, Hash<edge>> edgeHashSet; + + Info<< "Checking edges according to AVL/FIRE on-the-fly methodology..." + << endl; + + labelHashSet strayPoints(100); + edgeHashSet failedEdges(100); + + forAll(faces, faceI) + { + const face& faceA = faces[faceI]; + + forAll(faceA, edgeI) + { + const edge currEdge = faceA.faceEdge(edgeI); + + // all faces attached to the first point + const labelList& otherFaceIds = pointFaces[currEdge[0]]; + + forAll(otherFaceIds, otherI) + { + const int otherFaceI = otherFaceIds[otherI]; + const face& faceB = faces[otherFaceI]; + + // only check once + if (otherFaceI <= faceI && !fullCheck) + { + continue; + } + + // get local edges on the second face + int other_p0 = -1; + int other_p1 = -1; + int size_m1 = faceB.size() - 1; + + forAll(faceB, ptI) + { + if (faceB[ptI] == currEdge[0]) + { + other_p0 = ptI; + } + + if (faceB[ptI] == currEdge[1]) + { + other_p1 = ptI; + } + } + + if + ( + // did not have both points - can skip + other_p0 == -1 + || other_p1 == -1 + // a normal edge + || abs(other_p0 - other_p1) == 1 + // handle wrapping + || (other_p0 == 0 && other_p1 == size_m1) + || (other_p1 == 0 && other_p0 == size_m1) + ) + { + continue; + } + + // find the "stray" point + int stray = -1; + if (abs(other_p0 - other_p1) == 2) + { + // a normal case + stray = (other_p0 + other_p1) / 2; + } + else if + ( + (other_p0 == 0 && other_p1+1 == size_m1) + || (other_p1 == 0 && other_p0+1 == size_m1) + ) + { + stray = size_m1; + } + + if (stray > 0) + { + strayPoints.set(faceB[stray]); + } + + failedEdges.set(currEdge); + + ++nFailedEdges; + + Info<< nl + << "Broken edge calculated between points " + << currEdge[0] << " " << currEdge[1] << endl; + + printFace(faceA, faceI, currEdge); + printFace(faceB, otherFaceI, currEdge); + } + } + } + + if (nFailedEdges) + { + Info<< endl; + } + Info<< "detected " << nFailedEdges << " edge failures"; + + // reduce to the actual number of edges + nFailedEdges = failedEdges.size(); + + // report the locations + if (nFailedEdges) + { + Info<< " over " << nFailedEdges << " edges" << endl; + + Info<< nl + << "edge points" << nl + << "~~~~~~~~~~~" << endl; + + + forAllConstIter(edgeHashSet, failedEdges, citer) + { + edge thisEdge = citer.key(); + if (thisEdge.start() > thisEdge.end()) + { + thisEdge.flip(); + } + + if (&points) + { + forAll(thisEdge, keyI) + { + const label ptI = thisEdge[keyI]; + Info<< "point " << ptI << ": " << points[ptI] << endl; + } + } + else + { + forAll(thisEdge, keyI) + { + const label ptI = thisEdge[keyI]; + Info<< "point " << ptI << endl; + } + } + Info<< endl; + } + + Info<< nl + << "stray points" << nl + << "~~~~~~~~~~~~" << endl; + + { + labelList keys = strayPoints.sortedToc(); + + if (&points) + { + forAll(keys, keyI) + { + const label ptI = keys[keyI]; + Info<< "stray " << ptI << ": " << points[ptI] << endl; + } + } + else + { + forAll(keys, keyI) + { + const label ptI = keys[keyI]; + Info<< "stray " << ptI << endl; + } + } + + } + Info<< endl; + } + else + { + Info<< endl; + } + + return nFailedEdges; +} + + +Foam::label Foam::checkFireEdges +( + const faceList& faces, + const UList<point>& points +) +{ + label nPoints = -1; + + if (&points) + { + nPoints = points.size(); + + } + else + { + // get the max point addressed + forAll(faces, faceI) + { + const face& f = faces[faceI]; + forAll(f, fp) + { + if (nPoints < f[fp]) + { + nPoints = f[fp]; + } + } + } + + ++nPoints; + } + + labelListList pointFaces(nPoints); + invertManyToMany(nPoints, faces, pointFaces); + + return checkFireEdges(faces, pointFaces, points); +} + + +Foam::label Foam::checkFireEdges +( + const polyMesh& mesh +) +{ + return checkFireEdges(mesh.faces(), mesh.pointFaces(), mesh.points()); +} + + +// ************************************************************************* // diff --git a/src/conversion/fire/checkFireEdges.H b/src/conversion/fire/checkFireEdges.H new file mode 100644 index 0000000000000000000000000000000000000000..0f0bffe2c884c4632707499e3000e1349abc0e57 --- /dev/null +++ b/src/conversion/fire/checkFireEdges.H @@ -0,0 +1,79 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Description + Checks the mesh for edge connectivity as expected by the AVL/FIRE + on-the-fly calculations. + Errors flagged here are not necessarily topological errors at all. + +SourceFiles + checkFireEdges.C + +\*---------------------------------------------------------------------------*/ + +#ifndef checkFireEdges_H +#define checkFireEdges_H + +#include "faceList.H" +#include "labelList.H" +#include "point.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +class polyMesh; + +//- check edge connectivity +label checkFireEdges +( + const faceList&, + const labelListList& pointFaces, + const UList<point>& = UList<point>::null() +); + + +//- check edge connectivity with pointFaces mapping calculated automatically +label checkFireEdges +( + const faceList&, + const UList<point>& = UList<point>::null() +); + + +//- check edge connectivity +label checkFireEdges(const polyMesh&); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/starcd/STARCDMeshReader.C b/src/conversion/starcd/STARCDMeshReader.C index e5ddc1bcb5827db70197294f53738e9acd18c9c0..0229eaa0d20b854e84bd92c82652e703c7945e62 100644 --- a/src/conversion/starcd/STARCDMeshReader.C +++ b/src/conversion/starcd/STARCDMeshReader.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -35,26 +35,9 @@ License // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // -const char* const Foam::fileFormats::STARCDMeshReader::defaultBoundaryName = - "Default_Boundary_Region"; - -const char* const Foam::fileFormats::STARCDMeshReader::defaultSolidBoundaryName = - "Default_Boundary_Solid"; - -bool Foam::fileFormats::STARCDMeshReader::keepSolids = false; - -const int Foam::fileFormats::STARCDMeshReader::starToFoamFaceAddr[4][6] = -{ - { 4, 5, 2, 3, 0, 1 }, // 11 = pro-STAR hex - { 0, 1, 4, -1, 2, 3 }, // 12 = pro-STAR prism - { 3, -1, 2, -1, 1, 0 }, // 13 = pro-STAR tetra - { 0, -1, 4, 2, 1, 3 } // 14 = pro-STAR pyramid -}; - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -void Foam::fileFormats::STARCDMeshReader::readToNewline(IFstream& is) +//! \cond fileScope +//- Read and discard to newline +static void readToNewline(Foam::IFstream& is) { char ch = '\n'; do @@ -63,34 +46,7 @@ void Foam::fileFormats::STARCDMeshReader::readToNewline(IFstream& is) } while ((is) && ch != '\n'); } - - -bool Foam::fileFormats::STARCDMeshReader::readHeader(IFstream& is, word fileSignature) -{ - if (!is.good()) - { - FatalErrorInFunction - << abort(FatalError); - } - - word header; - label majorVersion; - - is >> header; - is >> majorVersion; - - // skip the rest of the line - readToNewline(is); - - // add other checks ... - if (header != fileSignature) - { - Info<< "header mismatch " << fileSignature << " " << is.name() - << endl; - } - - return true; -} +//! \endcond // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // @@ -118,20 +74,19 @@ Body: <vertexId> <x> <y> <z> [newline] \*---------------------------------------------------------------------------*/ -void Foam::fileFormats::STARCDMeshReader::readPoints +Foam::label Foam::fileFormats::STARCDMeshReader::readPoints ( const fileName& inputName, const scalar scaleFactor ) { - const word fileSignature = "PROSTAR_VERTEX"; label nPoints = 0, maxId = 0; // Pass 1: // get # points and maximum vertex label { IFstream is(inputName); - readHeader(is, fileSignature); + readHeader(is, STARCDCore::HEADER_VRT); label lineLabel; scalar x, y, z; @@ -164,7 +119,7 @@ void Foam::fileFormats::STARCDMeshReader::readPoints if (nPoints > 0) { IFstream is(inputName); - readHeader(is, fileSignature); + readHeader(is, STARCDCore::HEADER_VRT); label lineLabel; @@ -200,6 +155,8 @@ void Foam::fileFormats::STARCDMeshReader::readPoints << "no points in file " << inputName << abort(FatalError); } + + return maxId; } @@ -245,7 +202,6 @@ Strictly speaking, we only need the cellModeller for adding boundaries. void Foam::fileFormats::STARCDMeshReader::readCells(const fileName& inputName) { - const word fileSignature = "PROSTAR_CELL"; label nFluids = 0, nSolids = 0, nBaffles = 0, nShells = 0; label maxId = 0; @@ -257,7 +213,7 @@ void Foam::fileFormats::STARCDMeshReader::readCells(const fileName& inputName) // also see if polyhedral cells were used { IFstream is(inputName); - readHeader(is, fileSignature); + readHeader(is, STARCDCore::HEADER_CEL); label lineLabel, shapeId, nLabels, cellTableId, typeId; @@ -279,7 +235,7 @@ void Foam::fileFormats::STARCDMeshReader::readCells(const fileName& inputName) nLabels -= 8; } - if (typeId == starcdFluidType) + if (typeId == STARCDCore::starcdFluidType) { nFluids++; maxId = max(maxId, starCellId); @@ -290,10 +246,10 @@ void Foam::fileFormats::STARCDMeshReader::readCells(const fileName& inputName) cellTable_.setMaterial(cellTableId, "fluid"); } } - else if (typeId == starcdSolidType) + else if (typeId == STARCDCore::starcdSolidType) { nSolids++; - if (keepSolids) + if (keepSolids_) { maxId = max(maxId, starCellId); } @@ -305,13 +261,13 @@ void Foam::fileFormats::STARCDMeshReader::readCells(const fileName& inputName) } } - else if (typeId == starcdBaffleType) + else if (typeId == STARCDCore::starcdBaffleType) { // baffles have no cellTable entry nBaffles++; maxId = max(maxId, starCellId); } - else if (typeId == starcdShellType) + else if (typeId == STARCDCore::starcdShellType) { nShells++; if (!cellTable_.found(cellTableId)) @@ -326,7 +282,7 @@ void Foam::fileFormats::STARCDMeshReader::readCells(const fileName& inputName) Info<< "Number of fluids = " << nFluids << nl << "Number of baffles = " << nBaffles << nl; - if (keepSolids) + if (keepSolids_) { Info<< "Number of solids = " << nSolids << nl; } @@ -338,7 +294,7 @@ void Foam::fileFormats::STARCDMeshReader::readCells(const fileName& inputName) label nCells; - if (keepSolids) + if (keepSolids_) { nCells = nFluids + nSolids; } @@ -374,7 +330,7 @@ void Foam::fileFormats::STARCDMeshReader::readCells(const fileName& inputName) else { IFstream is(inputName); - readHeader(is, fileSignature); + readHeader(is, STARCDCore::HEADER_CEL); labelList starLabels(64); label lineLabel, shapeId, nLabels, cellTableId, typeId; @@ -407,7 +363,11 @@ void Foam::fileFormats::STARCDMeshReader::readCells(const fileName& inputName) } // skip solid cells - if (typeId == starcdSolidType && !keepSolids) + if + ( + typeId == STARCDCore::starcdSolidType + && !keepSolids_ + ) { continue; } @@ -418,16 +378,16 @@ void Foam::fileFormats::STARCDMeshReader::readCells(const fileName& inputName) // fluid/solid cells switch (shapeId) { - case starcdHex: + case STARCDCore::starcdHex: curModelPtr = hexModel; break; - case starcdPrism: + case STARCDCore::starcdPrism: curModelPtr = prismModel; break; - case starcdTet: + case STARCDCore::starcdTet: curModelPtr = tetModel; break; - case starcdPyr: + case STARCDCore::starcdPyr: curModelPtr = pyrModel; break; } @@ -471,7 +431,7 @@ void Foam::fileFormats::STARCDMeshReader::readCells(const fileName& inputName) cellFaces_[celli] = cellShapes_[celli].faces(); celli++; } - else if (shapeId == starcdPoly) + else if (shapeId == STARCDCore::starcdPoly) { // polyhedral cell label nFaces = starLabels[0] - 1; @@ -548,7 +508,7 @@ void Foam::fileFormats::STARCDMeshReader::readCells(const fileName& inputName) cellFaces_[celli] = faces; celli++; } - else if (typeId == starcdBaffleType) + else if (typeId == STARCDCore::starcdBaffleType) { // baffles @@ -639,7 +599,6 @@ void Foam::fileFormats::STARCDMeshReader::readBoundary const fileName& inputName ) { - const word fileSignature = "PROSTAR_BOUNDARY"; label nPatches = 0, nFaces = 0, nBafflePatches = 0, maxId = 0; label lineLabel, starCellId, cellFaceId, starRegion, configNumber; word patchType; @@ -649,15 +608,17 @@ void Foam::fileFormats::STARCDMeshReader::readBoundary labelList origRegion(1000, label(0)); patchTypes_.setSize(1000); - // this is what we seem to need - // these MUST correspond to starToFoamFaceAddr // - Map<label> faceLookupIndex; - - faceLookupIndex.insert(hexModel->index(), 0); - faceLookupIndex.insert(prismModel->index(), 1); - faceLookupIndex.insert(tetModel->index(), 2); - faceLookupIndex.insert(pyrModel->index(), 3); + // Mapping between OpenFOAM and PROSTAR primitives + // - needed for face mapping + // + const Map<label> prostarShapeLookup = + { + { hexModel->index(), STARCDCore::starcdHex }, + { prismModel->index(), STARCDCore::starcdPrism }, + { tetModel->index(), STARCDCore::starcdTet }, + { pyrModel->index(), STARCDCore::starcdPyr } + }; // Pass 1: // collect @@ -675,7 +636,7 @@ void Foam::fileFormats::STARCDMeshReader::readBoundary if (is.good()) { - readHeader(is, fileSignature); + readHeader(is, STARCDCore::HEADER_BND); while ((is >> lineLabel).good()) { @@ -863,7 +824,7 @@ void Foam::fileFormats::STARCDMeshReader::readBoundary if (nPatches > 1 && mapToFoamCellId_.size() > 1) { IFstream is(inputName); - readHeader(is, fileSignature); + readHeader(is, STARCDCore::HEADER_BND); while ((is >> lineLabel).good()) { @@ -899,11 +860,11 @@ void Foam::fileFormats::STARCDMeshReader::readBoundary // restrict lookup to volume cells (no baffles) if (cellId < cellShapes_.size()) { - label index = cellShapes_[cellId].model().index(); - if (faceLookupIndex.found(index)) + label mapIndex = cellShapes_[cellId].model().index(); + if (prostarShapeLookup.found(mapIndex)) { - index = faceLookupIndex[index]; - cellFaceId = starToFoamFaceAddr[index][cellFaceId]; + mapIndex = prostarShapeLookup[mapIndex]; + cellFaceId = STARCDCore::starToFoamFaceAddr[mapIndex][cellFaceId]; } } else @@ -1046,10 +1007,20 @@ void Foam::fileFormats::STARCDMeshReader::cullPoints() bool Foam::fileFormats::STARCDMeshReader::readGeometry(const scalar scaleFactor) { - readPoints(geometryFile_ + ".vrt", scaleFactor); - readCells(geometryFile_ + ".cel"); + readPoints + ( + starFileName(geometryFile_, STARCDCore::VRT_FILE), + scaleFactor + ); + readCells + ( + starFileName(geometryFile_, STARCDCore::CEL_FILE) + ); cullPoints(); - readBoundary(geometryFile_ + ".bnd"); + readBoundary + ( + starFileName(geometryFile_, STARCDCore::BND_FILE) + ); return true; } @@ -1061,10 +1032,12 @@ Foam::fileFormats::STARCDMeshReader::STARCDMeshReader ( const fileName& prefix, const objectRegistry& registry, - const scalar scaleFactor + const scalar scaleFactor, + const bool keepSolids ) : meshReader(prefix, scaleFactor), + keepSolids_(keepSolids), cellShapes_(0), mapToFoamPointId_(0), mapToFoamCellId_(0) diff --git a/src/conversion/starcd/STARCDMeshReader.H b/src/conversion/starcd/STARCDMeshReader.H index 5025a5c11a2437c2e89cbb3d5a856e0b4b586fa6..9288002991546735fd32642f4d50ce03507ba7b7 100644 --- a/src/conversion/starcd/STARCDMeshReader.H +++ b/src/conversion/starcd/STARCDMeshReader.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -43,6 +43,7 @@ SourceFiles #define STARCDMeshReader_H #include "meshReader.H" +#include "STARCDCore.H" #include "boundaryRegion.H" #include "cellShape.H" #include "IFstream.H" @@ -61,18 +62,27 @@ namespace fileFormats class STARCDMeshReader : - public meshReader + public meshReader, + protected STARCDCore { + // Private data -protected: + //- Retain solid cell types + bool keepSolids_; - // Protected Data - static const char* const defaultBoundaryName; - static const char* const defaultSolidBoundaryName; + // Private member functions + + //- Disallow default bitwise copy construct + STARCDMeshReader(const STARCDMeshReader&) = delete; + + //- Disallow default bitwise assignment + void operator=(const STARCDMeshReader&) = delete; - //- Face addressing from pro-STAR faces -> OpenFOAM faces - static const int starToFoamFaceAddr[4][6]; + +protected: + + // Protected Data //- Cell shapes cellShapeList cellShapes_; @@ -92,8 +102,8 @@ protected: //- Read the mesh from the file(s) virtual bool readGeometry(const scalar scaleFactor = 1.0); - //- Read points from file - void readPoints(const fileName&, const scalar scaleFactor); + //- Read points from file, return the max prostar id used. + label readPoints(const fileName&, const scalar scaleFactor); //- Read cell connectivities from file virtual void readCells(const fileName&); @@ -107,57 +117,9 @@ protected: //- Read auxiliary data from constant/{boundaryRegion,cellTable} void readAux(const objectRegistry&); - //- Read and discard to newline - static void readToNewline(IFstream&); - - //- Read header - static bool readHeader(IFstream&, word fileSignature); - - -private: - - // Private member functions - - //- Disallow default bitwise copy construct - STARCDMeshReader(const STARCDMeshReader&) = delete; - - //- Disallow default bitwise assignment - void operator=(const STARCDMeshReader&) = delete; - - -protected: - - enum cellType - { - starcdFluidType = 1, - starcdSolidType = 2, - starcdBaffleType = 3, - starcdShellType = 4, - starcdLineType = 5, - starcdPointType = 6 - }; - - enum shapeType - { - starcdPoint = 1, - starcdLine = 2, - starcdShell = 3, - starcdHex = 11, - starcdPrism = 12, - starcdTet = 13, - starcdPyr = 14, - starcdPoly = 255 - }; - public: - // Static data - - //- Keep solids (default false) - static bool keepSolids; - - // Constructors //- Construct from case name @@ -165,12 +127,14 @@ public: ( const fileName& prefix, const objectRegistry&, - const scalar scaleFactor = 1.0 + const scalar scaleFactor = 1.0, + const bool keepSolids = false ); //- Destructor virtual ~STARCDMeshReader(); + }; diff --git a/src/conversion/starcd/STARCDMeshWriter.C b/src/conversion/starcd/STARCDMeshWriter.C index 3436fc5a76c33ecf269be571bd3f05b809443339..c4ccf80faa70a339cc053cd3ab6b9a3f67fca1b7 100644 --- a/src/conversion/starcd/STARCDMeshWriter.C +++ b/src/conversion/starcd/STARCDMeshWriter.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -29,20 +29,6 @@ License #include "SortableList.H" #include "OFstream.H" -// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // - -const char* Foam::fileFormats::STARCDMeshWriter::defaultBoundaryName = - "Default_Boundary_Region"; - -const Foam::label Foam::fileFormats::STARCDMeshWriter::foamToStarFaceAddr[4][6] = -{ - { 4, 5, 2, 3, 0, 1 }, // 11 = pro-STAR hex - { 0, 1, 4, 5, 2, -1 }, // 12 = pro-STAR prism - { 5, 4, 2, 0, -1, -1 }, // 13 = pro-STAR tetra - { 0, 4, 3, 5, 2, -1 } // 14 = pro-STAR pyramid -}; - - // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // Foam::label Foam::fileFormats::STARCDMeshWriter::findDefaultBoundary() const @@ -171,66 +157,37 @@ void Foam::fileFormats::STARCDMeshWriter::getCellTable() } -void Foam::fileFormats::STARCDMeshWriter::writeHeader(Ostream& os, const char* filetype) -{ - os << "PROSTAR_" << filetype << nl - << 4000 - << " " << 0 - << " " << 0 - << " " << 0 - << " " << 0 - << " " << 0 - << " " << 0 - << " " << 0 - << endl; -} - - -void Foam::fileFormats::STARCDMeshWriter::writePoints(const fileName& prefix) const -{ - OFstream os(prefix + ".vrt"); - writeHeader(os, "VERTEX"); - - // Set the precision of the points data to 10 - os.precision(10); - - // force decimal point for Fortran input - os.setf(std::ios::showpoint); - - const pointField& points = mesh_.points(); - - Info<< "Writing " << os.name() << " : " - << points.size() << " points" << endl; - - forAll(points, ptI) - { - // convert [m] -> [mm] - os - << ptI + 1 << " " - << scaleFactor_ * points[ptI].x() << " " - << scaleFactor_ * points[ptI].y() << " " - << scaleFactor_ * points[ptI].z() << nl; - } - os.flush(); - -} - - void Foam::fileFormats::STARCDMeshWriter::writeCells ( const fileName& prefix ) const { - OFstream os(prefix + ".cel"); - writeHeader(os, "CELL"); + OFstream os(starFileName(prefix, STARCDCore::CEL_FILE)); + writeHeader(os, STARCDCore::HEADER_CEL); // this is what we seem to need // map foam cellModeller index -> star shape Map<label> shapeLookupIndex; - shapeLookupIndex.insert(hexModel->index(), 11); - shapeLookupIndex.insert(prismModel->index(), 12); - shapeLookupIndex.insert(tetModel->index(), 13); - shapeLookupIndex.insert(pyrModel->index(), 14); + shapeLookupIndex.insert + ( + hexModel->index(), + STARCDCore::starcdHex + ); + shapeLookupIndex.insert + ( + prismModel->index(), + STARCDCore::starcdPrism + ); + shapeLookupIndex.insert + ( + tetModel->index(), + STARCDCore::starcdTet + ); + shapeLookupIndex.insert + ( + pyrModel->index(), + STARCDCore::starcdPyr + ); const cellShapeList& shapes = mesh_.cellShapes(); const cellList& cells = mesh_.cells(); @@ -242,30 +199,30 @@ void Foam::fileFormats::STARCDMeshWriter::writeCells forAll(cells, cellId) { - label tableId = cellTableId_[cellId]; - label materialType = 1; // 1(fluid) + const label tableId = cellTableId_[cellId]; + label materialType = STARCDCore::starcdFluidType; // 1(fluid) if (cellTable_.found(tableId)) { const dictionary& dict = cellTable_[tableId]; - if (dict.found("MaterialType")) - { - word matType; - dict.lookup("MaterialType") >> matType; - if (matType == "solid") - { - materialType = 2; - } + word matType; + if + ( + dict.readIfPresent("MaterialType", matType) + && matType == "solid" + ) + { + materialType = STARCDCore::starcdSolidType; // 2(solid) } } const cellShape& shape = shapes[cellId]; - label mapIndex = shape.model().index(); + const label mapIndex = shape.model().index(); // a registered primitive type if (shapeLookupIndex.found(mapIndex)) { - label shapeId = shapeLookupIndex[mapIndex]; + const label shapeId = shapeLookupIndex[mapIndex]; const labelList& vrtList = shapes[cellId]; os << cellId + 1 @@ -288,11 +245,11 @@ void Foam::fileFormats::STARCDMeshWriter::writeCells count++; } os << endl; - } else { - label shapeId = 255; // treat as general polyhedral + // treat as general polyhedral + const label shapeId = STARCDCore::starcdPoly; const labelList& cFaces = cells[cellId]; // create (beg,end) indices @@ -366,8 +323,8 @@ void Foam::fileFormats::STARCDMeshWriter::writeBoundary const fileName& prefix ) const { - OFstream os(prefix + ".bnd"); - writeHeader(os, "BOUNDARY"); + OFstream os(starFileName(prefix, STARCDCore::BND_FILE)); + writeHeader(os, STARCDCore::HEADER_BND); const cellShapeList& shapes = mesh_.cellShapes(); const cellList& cells = mesh_.cells(); @@ -375,20 +332,23 @@ void Foam::fileFormats::STARCDMeshWriter::writeBoundary const labelList& owner = mesh_.faceOwner(); const polyBoundaryMesh& patches = mesh_.boundaryMesh(); - // this is what we seem to need - // these MUST correspond to foamToStarFaceAddr // - Map<label> faceLookupIndex; - faceLookupIndex.insert(hexModel->index(), 0); - faceLookupIndex.insert(prismModel->index(), 1); - faceLookupIndex.insert(tetModel->index(), 2); - faceLookupIndex.insert(pyrModel->index(), 3); + // Mapping between OpenFOAM and PROSTAR primitives + // - needed for face mapping + // + const Map<label> prostarShapeLookup = + { + { hexModel->index(), STARCDCore::starcdHex }, + { prismModel->index(), STARCDCore::starcdPrism }, + { tetModel->index(), STARCDCore::starcdTet }, + { pyrModel->index(), STARCDCore::starcdPyr } + }; Info<< "Writing " << os.name() << " : " << (mesh_.nFaces() - patches[0].start()) << " boundaries" << endl; - label defaultId = findDefaultBoundary(); + const label defaultId = findDefaultBoundary(); // // write boundary faces - skip Default_Boundary_Region entirely @@ -435,8 +395,8 @@ void Foam::fileFormats::STARCDMeshWriter::writeBoundary label mapIndex = shape.model().index(); - // a registered primitive type - if (faceLookupIndex.found(mapIndex)) + // A registered primitive type + if (prostarShapeLookup.found(mapIndex)) { const faceList sFaces = shape.faces(); forAll(sFaces, sFacei) @@ -448,8 +408,8 @@ void Foam::fileFormats::STARCDMeshWriter::writeBoundary } } - mapIndex = faceLookupIndex[mapIndex]; - cellFaceId = foamToStarFaceAddr[mapIndex][cellFaceId]; + mapIndex = prostarShapeLookup[mapIndex]; + cellFaceId = STARCDCore::foamToStarFaceAddr[mapIndex][cellFaceId]; } // Info<< endl; @@ -473,10 +433,12 @@ void Foam::fileFormats::STARCDMeshWriter::writeBoundary Foam::fileFormats::STARCDMeshWriter::STARCDMeshWriter ( const polyMesh& mesh, - const scalar scaleFactor + const scalar scaleFactor, + const bool writeBndFile ) : - meshWriter(mesh, scaleFactor) + meshWriter(mesh, scaleFactor), + writeBoundary_(writeBndFile) { boundaryRegion_.readDict(mesh_); cellTable_.readDict(mesh_); @@ -492,15 +454,6 @@ Foam::fileFormats::STARCDMeshWriter::~STARCDMeshWriter() // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -void Foam::fileFormats::STARCDMeshWriter::rmFiles(const fileName& baseName) const -{ - rm(baseName + ".vrt"); - rm(baseName + ".cel"); - rm(baseName + ".bnd"); - rm(baseName + ".inp"); -} - - bool Foam::fileFormats::STARCDMeshWriter::write(const fileName& meshName) const { fileName baseName(meshName); @@ -519,10 +472,25 @@ bool Foam::fileFormats::STARCDMeshWriter::write(const fileName& meshName) const } } - rmFiles(baseName); - writePoints(baseName); + STARCDCore::removeFiles(baseName); + + // points + { + OFstream os + ( + starFileName(baseName, STARCDCore::VRT_FILE) + ); + + Info<< "Writing " << os.name() << " : " + << mesh_.nPoints() << " points" << endl; + + writePoints(os, mesh_.points(), scaleFactor_); + } + + // cells writeCells(baseName); + // boundaries if (writeBoundary_) { writeBoundary(baseName); diff --git a/src/conversion/starcd/STARCDMeshWriter.H b/src/conversion/starcd/STARCDMeshWriter.H index 9de8c60490d33ad19897f5a6fe7ced9b1f4cf9a9..2b33eaa20aca6ed4490a708f22de4e4c2aecabed 100644 --- a/src/conversion/starcd/STARCDMeshWriter.H +++ b/src/conversion/starcd/STARCDMeshWriter.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -39,6 +39,7 @@ SourceFiles #define STARCDMeshWriter_H #include "meshWriter.H" +#include "STARCDCore.H" #include "IOstream.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -55,27 +56,17 @@ namespace fileFormats class STARCDMeshWriter : - public meshWriter + public meshWriter, + protected STARCDCore { - // Private Data + // Private data - static const char* defaultBoundaryName; + //- Write boundary (bnd) file - default true + bool writeBoundary_; // Private Member Functions - //- Disallow default bitwise copy construct - STARCDMeshWriter(const STARCDMeshWriter&) = delete; - - //- Disallow default bitwise assignment - void operator=(const STARCDMeshWriter&) = delete; - - //- Pro-STAR 4+ header format - static void writeHeader(Ostream&, const char* filetype); - - //- Write points - void writePoints(const fileName& baseName) const; - //- Write cells void writeCells(const fileName& baseName) const; @@ -87,18 +78,24 @@ class STARCDMeshWriter label findDefaultBoundary() const; -public: + //- Disallow default bitwise copy construct + STARCDMeshWriter(const STARCDMeshWriter&) = delete; - // Static data members + //- Disallow default bitwise assignment + void operator=(const STARCDMeshWriter&) = delete; - //- Face addressing from OpenFOAM faces -> pro-STAR faces - static const label foamToStarFaceAddr[4][6]; +public: // Constructors //- Write mesh files in PROSTAR format - STARCDMeshWriter(const polyMesh&, const scalar scaleFactor = 1.0); + STARCDMeshWriter + ( + const polyMesh&, + const scalar scaleFactor = 1.0, + const bool writeBndFile = true + ); //- Destructor @@ -107,19 +104,13 @@ public: // Member Functions - // Edit - - //- Remove STAR-CD files for the baseName - void rmFiles(const fileName& baseName) const; - - - // Write + // Write - //- Write volume mesh - virtual bool write - ( - const fileName& meshName = fileName::null - ) const; + //- Write volume mesh + virtual bool write + ( + const fileName& meshName = fileName::null + ) const; }; diff --git a/src/conversion/vtk/output/foamVtkOutput.C b/src/conversion/vtk/output/foamVtkOutput.C new file mode 100644 index 0000000000000000000000000000000000000000..4ece681a85a8c8b8186ce328bfb528983c9c6205 --- /dev/null +++ b/src/conversion/vtk/output/foamVtkOutput.C @@ -0,0 +1,126 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "foamVtkOutput.H" +#include "foamVtkAsciiFormatter.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const Foam::word Foam::foamVtkOutput::legacy::EXT = "vtk"; + + +//! \cond fileScope +static inline std::ostream& legacyDataHeader +( + std::ostream& os, + const char* tag, + const Foam::label nItems, + const Foam::label nFields +) +{ + os << tag << ' ' << nItems << '\n' + << "FIELD attributes " << nFields << '\n'; + + return os; +} +//! \endcond + + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +Foam::label Foam::foamVtkOutput::writeVtmFile +( + std::ostream& os, + const UList<fileName>& files +) +{ + const word& content = "vtkMultiBlockDataSet"; + + foamVtkAsciiFormatter vtmFile(os); + + vtmFile + .xmlHeader() + .openTag("VTKFile") + ( "type", content ) + ( "version", "1.0" ) + ( "byte_order", foamVtkFormatter::byteOrder ) + ( "header_type", foamVtkFormatter::headerType ) + .closeTag(); + + vtmFile.tag(content); + + forAll(files, i) + { + vtmFile + .openTag("DataSet") + ( "index", i ) + ( "file", files[i] ) + .closeTag(true); + } + + vtmFile.endTag(content).endTag("VTKFile"); + + return files.size(); +} + + +std::ostream& Foam::foamVtkOutput::legacy::writeHeader +( + std::ostream& os, + const std::string& title, + const bool binary +) +{ + os << "# vtk DataFile Version 2.0" << nl + << title << nl + << (binary ? "BINARY" : "ASCII") << nl; + + return os; +} + + +std::ostream& Foam::foamVtkOutput::legacy::writeCellDataHeader +( + std::ostream& os, + const label nCells, + const label nFields +) +{ + return legacyDataHeader(os, "CELL_DATA", nCells, nFields); +} + + +std::ostream& Foam::foamVtkOutput::legacy::writePointDataHeader +( + std::ostream& os, + const label nPoints, + const label nFields +) +{ + return legacyDataHeader(os, "POINT_DATA", nPoints, nFields); +} + + +// ************************************************************************* // diff --git a/src/conversion/vtk/output/foamVtkOutput.H b/src/conversion/vtk/output/foamVtkOutput.H new file mode 100644 index 0000000000000000000000000000000000000000..ad7964bfff7b638f1ff8837088d125feb10506d5 --- /dev/null +++ b/src/conversion/vtk/output/foamVtkOutput.H @@ -0,0 +1,216 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + foamVtkOutput + +Description + A collection of functions for writing vtk file content. + +SourceFiles + foamVtkOutput.C + foamVtkOutputTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef foamVtkOutput_H +#define foamVtkOutput_H + +#include "floatScalar.H" +#include "volFields.H" +#include "foamVtkFormatter.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class foamVtkOutput Declaration +\*---------------------------------------------------------------------------*/ + +class foamVtkOutput +{ + // Private Member Functions + + //- Disallow construction + foamVtkOutput() = delete; + +public: + + // Forward declarations + class legacy; + + + // Static Members + + //- Write vtm datasets for specified files + static Foam::label writeVtmFile + ( + std::ostream& os, + const UList<fileName>& files + ); + + + //- Write a value component-wise. + template<class Type> + inline static void write(foamVtkFormatter&, const Type&); + + + //- Write a list of values. + // The output does not include the payload size. + template<class Type> + static void writeList + ( + foamVtkFormatter&, + const UList<Type>& + ); + + + //- Write a list of values via indirect addressing. + // The output does not include the payload size. + template<class Type> + static void writeList + ( + foamVtkFormatter&, + const UList<Type>&, + const UList<label>& addressing + ); + + + //- Write volField with cell values (including decomposed cells). + // The output includes the payload size and flush. + template<class Type> + static void writeField + ( + foamVtkFormatter&, + const GeometricField<Type, fvPatchField, volMesh>&, + const UList<label>& superCells + ); + +}; + + +/*---------------------------------------------------------------------------*\ + Class foamVtkOutput::legacy Declaration +\*---------------------------------------------------------------------------*/ + +//- Basic support for legacy files +class foamVtkOutput::legacy +{ + // Private Member Functions + + //- Disallow construction + legacy() = delete; + +public: + + // Static data members + + //- file extension for legacy files (vtk) + static const Foam::word EXT; + + + // Static Members + + //- Emit header for legacy file + static std::ostream& writeHeader + ( + std::ostream&, + const std::string& title, + const bool binary = false + ); + + + //- Emit header for legacy CELL_DATA + static std::ostream& writeCellDataHeader + ( + std::ostream& os, + const label nCells, + const label nFields + ); + + + //- Emit header for legacy POINT_DATA + static std::ostream& writePointDataHeader + ( + std::ostream& os, + const label nPoints, + const label nFields + ); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +//- Template specialization for label +template<> +inline void Foam::foamVtkOutput::write<label> +( + foamVtkFormatter& fmt, + const label& val +) +{ + fmt.write(val); +} + + +//- Template specialization for float +template<> +inline void Foam::foamVtkOutput::write<float> +( + foamVtkFormatter& fmt, + const float& val +) +{ + fmt.write(val); +} + + +//- Template specialization for double +template<> +inline void Foam::foamVtkOutput::write<double> +( + foamVtkFormatter& fmt, + const double& val +) +{ + fmt.write(val); +} + +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "foamVtkOutputTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/vtk/output/foamVtkOutputTemplates.C b/src/conversion/vtk/output/foamVtkOutputTemplates.C new file mode 100644 index 0000000000000000000000000000000000000000..03c2d56bd9d941d97e427b049914698fd179147a --- /dev/null +++ b/src/conversion/vtk/output/foamVtkOutputTemplates.C @@ -0,0 +1,94 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +template<class Type> +inline void Foam::foamVtkOutput::write +( + foamVtkFormatter& fmt, + const Type& val +) +{ + for (direction cmpt=0; cmpt < pTraits<Type>::nComponents; ++cmpt) + { + fmt.write(component(val, cmpt)); + } +} + + +template<class Type> +void Foam::foamVtkOutput::writeList +( + foamVtkFormatter& fmt, + const UList<Type>& lst +) +{ + forAll(lst, i) + { + write(fmt, lst[i]); + } +} + + +template<class Type> +void Foam::foamVtkOutput::writeList +( + foamVtkFormatter& fmt, + const UList<Type>& lst, + const UList<label>& addressing +) +{ + forAll(addressing, i) + { + write(fmt, lst[addressing[i]]); + } +} + + +template<class Type> +void Foam::foamVtkOutput::writeField +( + foamVtkFormatter& fmt, + const GeometricField<Type, fvPatchField, volMesh>& vf, + const UList<label>& superCells +) +{ + const uint64_t payLoad = + ( + (vf.size() + superCells.size()) + * pTraits<Type>::nComponents * sizeof(float) + ); + + fmt.writeSize(payLoad); + writeList(fmt, vf.internalField()); + writeList(fmt, vf, superCells); + + fmt.flush(); +} + + +// ************************************************************************* // diff --git a/src/conversion/vtk/part/foamVtkCells.C b/src/conversion/vtk/part/foamVtkCells.C new file mode 100644 index 0000000000000000000000000000000000000000..b4c7beacde9d7523af4cd59f61edac03fc6c2590 --- /dev/null +++ b/src/conversion/vtk/part/foamVtkCells.C @@ -0,0 +1,649 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "foamVtkCells.H" +#include "polyMesh.H" +#include "cellShape.H" +#include "cellModeller.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::foamVtkCells::correct() +{ + // Clear derived data + // clearGeom(); + + const cellModel& tet = *(cellModeller::lookup("tet")); + const cellModel& pyr = *(cellModeller::lookup("pyr")); + const cellModel& prism = *(cellModeller::lookup("prism")); + const cellModel& wedge = *(cellModeller::lookup("wedge")); + const cellModel& tetWedge = *(cellModeller::lookup("tetWedge")); + const cellModel& hex = *(cellModeller::lookup("hex")); + + const cellShapeList& cellShapes = mesh_.cellShapes(); + + // face owner is needed to determine the face orientation + const labelList& owner = mesh_.faceOwner(); + + // Unique vertex labels per polyhedral + HashSet<label> hashUniqId(2*256); + + // ======================= + // PASS 1: Determine sizes + + label nVertLabels = 0; + label nFaceLabels = 0; + label nAddPoints = 0; + label nAddCells = 0; + label nAddVerts = 0; + + forAll(cellShapes, cellI) + { + const cellShape& shape = cellShapes[cellI]; + const cellModel& model = shape.model(); + + if + ( + model == tet + || model == pyr + || model == prism + || model == hex + ) + { + // normal primitives + nVertLabels += shape.size(); + } + else if (model == tetWedge && decompose_.requested()) + { + // Treat as squeezed prism (VTK_WEDGE) + nVertLabels += 6; + } + else if (model == wedge && decompose_.requested()) + { + // Treat as squeezed hex + nVertLabels += 8; + } + else if (decompose_.requested()) + { + // Polyhedral: Decompose into tets + pyramids. + + // Count vertices in first decomposed cell + bool first = true; + + const cell& cFaces = mesh_.cells()[cellI]; + forAll(cFaces, cFaceI) + { + const face& f = mesh_.faces()[cFaces[cFaceI]]; + + // Face decomposed into triangles and quads + // Tri -> Tet, Quad -> Pyr + label nTria = 0, nQuad = 0; + f.nTrianglesQuads(mesh_.points(), nTria, nQuad); + + nAddCells += nTria + nQuad; + nAddVerts += (nTria * 4) + (nQuad * 5); + + if (first) + { + const label nvrt = (nQuad ? 5 : 4); + nAddCells--; + nAddVerts -= nvrt; + nVertLabels += nvrt; + + first = false; + } + } + + ++nAddPoints; + } + else + { + // Polyhedral: Not decomposed. + + const labelList& cFaces = mesh_.cells()[cellI]; + + // establish unique node ids used (only needed for XML) + hashUniqId.clear(); + + // determing sizing for face stream + // number of faces, size of each face, vertices per face + // [nFaces, nFace0Pts, id1, id2, ..., nFace1Pts, id1, id2, ...] + + forAll(cFaces, cFaceI) + { + const face& f = mesh_.faces()[cFaces[cFaceI]]; + nFaceLabels += f.size(); + + forAll(f, fp) + { + hashUniqId.insert(f[fp]); + } + } + + nVertLabels += hashUniqId.size(); + nFaceLabels += 1 + cFaces.size(); + } + } + + + // + // adjust/reserve sizes + // + + // Cell types (including added cells) in vtk numbering + cellTypes_.setSize(cellShapes.size() + nAddCells); + + // List of vertex labels in VTK ordering + vertLabels_.setSize(nVertLabels + nAddVerts); + + vertOffset_.setSize(cellShapes.size() + nAddCells); + + faceLabels_.clear(); + faceOffset_.clear(); + if (nFaceLabels) + { + faceLabels_.setSize(nFaceLabels); + + // only need nCells (without nAddCells) + // set to -1 (primitive) + faceOffset_.setSize(cellShapes.size(), -1); + } + + if (decompose_.requested()) + { + decompose_.addPointCellLabels_.setSize(nAddPoints); + decompose_.superCells_.setSize(nAddCells); + } + + + // ====================== + // PASS 2: Fill in arrays + + // Need this offset later, but only for decomposed polys + const label offsetAddVerts = nVertLabels; + + // Reset counters + nVertLabels = 0; + nFaceLabels = 0; + nAddPoints = 0; + nAddCells = 0; + nAddVerts = 0; + + forAll(cellShapes, cellI) + { + const cellShape& shape = cellShapes[cellI]; + const cellModel& model = shape.model(); + + if (model == tet) + { + cellTypes_[cellI] = foamVtkCore::VTK_TETRA; + forAll(shape, i) + { + vertLabels_[nVertLabels++] = shape[i]; + } + vertOffset_[cellI] = nVertLabels; + } + else if (model == pyr) + { + cellTypes_[cellI] = foamVtkCore::VTK_PYRAMID; + forAll(shape, i) + { + vertLabels_[nVertLabels++] = shape[i]; + } + vertOffset_[cellI] = nVertLabels; + } + else if (model == hex) + { + cellTypes_[cellI] = foamVtkCore::VTK_HEXAHEDRON; + forAll(shape, i) + { + vertLabels_[nVertLabels++] = shape[i]; + } + vertOffset_[cellI] = nVertLabels; + } + else if (model == prism) + { + cellTypes_[cellI] = foamVtkCore::VTK_WEDGE; + + // VTK_WEDGE triangles point outwards (swap 1<->2, 4<->5) + vertLabels_[nVertLabels++] = shape[0]; + vertLabels_[nVertLabels++] = shape[2]; + vertLabels_[nVertLabels++] = shape[1]; + vertLabels_[nVertLabels++] = shape[3]; + vertLabels_[nVertLabels++] = shape[5]; + vertLabels_[nVertLabels++] = shape[4]; + + vertOffset_[cellI] = nVertLabels; + } + else if (model == tetWedge && decompose_.requested()) + { + // Treat as squeezed prism (VTK_WEDGE) + cellTypes_[cellI] = foamVtkCore::VTK_WEDGE; + + vertLabels_[nVertLabels++] = shape[0]; + vertLabels_[nVertLabels++] = shape[2]; + vertLabels_[nVertLabels++] = shape[1]; + vertLabels_[nVertLabels++] = shape[3]; + vertLabels_[nVertLabels++] = shape[4]; + vertLabels_[nVertLabels++] = shape[3]; + + vertOffset_[cellI] = nVertLabels; + } + else if (model == wedge && decompose_.requested()) + { + // Treat as squeezed hex + cellTypes_[cellI] = foamVtkCore::VTK_HEXAHEDRON; + + vertLabels_[nVertLabels++] = shape[0]; + vertLabels_[nVertLabels++] = shape[1]; + vertLabels_[nVertLabels++] = shape[2]; + vertLabels_[nVertLabels++] = shape[2]; + vertLabels_[nVertLabels++] = shape[3]; + vertLabels_[nVertLabels++] = shape[4]; + vertLabels_[nVertLabels++] = shape[5]; + vertLabels_[nVertLabels++] = shape[6]; + + vertOffset_[cellI] = nVertLabels; + } + else if (decompose_.requested()) + { + // Polyhedral cell - decompose into tet/pyr. + + // Ensure we have the correct orientation for the base of the + // primitive cell shape. + // If the cell is face owner, the orientation needs to be flipped + // to avoid defining negative cells. + // VTK doesn't seem to care, but we'll do it anyhow for safety. + + // The new vertex from the cell-centre + const label newVertexLabel = mesh_.nPoints() + nAddPoints; + + // Mapping from additional point to cell + decompose_.addPointCellLabels_[nAddPoints++] = cellI; + + // Whether to insert cell in place of original or not. + bool first = true; + + const labelList& cFaces = mesh_.cells()[cellI]; + forAll(cFaces, cFaceI) + { + const face& f = mesh_.faces()[cFaces[cFaceI]]; + const bool isOwner = (owner[cFaces[cFaceI]] == cellI); + + // Count triangles/quads in decomposition + label nTria = 0; + label nQuad = 0; + f.nTrianglesQuads(mesh_.points(), nTria, nQuad); + + // Do actual decomposition + faceList faces3(nTria); + faceList faces4(nQuad); + nTria = 0, nQuad = 0; + f.trianglesQuads(mesh_.points(), nTria, nQuad, faces3, faces4); + + forAll(faces4, fci) + { + const face& quad = faces4[fci]; + + label celLoc; + label vrtLoc; + + if (first) + { + celLoc = cellI; + vrtLoc = nVertLabels; + nVertLabels += 5; + + vertOffset_[celLoc] = nVertLabels; + first = false; + } + else + { + celLoc = mesh_.nCells() + nAddCells; + vrtLoc = offsetAddVerts + nAddVerts; + nAddVerts += 5; + + vertOffset_[celLoc] = nAddVerts; + decompose_.superCells_[nAddCells++] = celLoc; + } + + cellTypes_[celLoc] = foamVtkCore::VTK_PYRAMID; + + // See note above about the orientation. + if (isOwner) + { + vertLabels_[vrtLoc++] = quad[3]; + vertLabels_[vrtLoc++] = quad[2]; + vertLabels_[vrtLoc++] = quad[1]; + vertLabels_[vrtLoc++] = quad[0]; + } + else + { + vertLabels_[vrtLoc++] = quad[0]; + vertLabels_[vrtLoc++] = quad[1]; + vertLabels_[vrtLoc++] = quad[2]; + vertLabels_[vrtLoc++] = quad[3]; + } + + vertLabels_[vrtLoc++] = newVertexLabel; + } + + forAll(faces3, fci) + { + const face& tria = faces3[fci]; + + label celLoc; + label vrtLoc; + + if (first) + { + celLoc = cellI; + vrtLoc = nVertLabels; + nVertLabels += 4; + + vertOffset_[celLoc] = nVertLabels; + first = false; + } + else + { + celLoc = mesh_.nCells() + nAddCells; + vrtLoc = offsetAddVerts + nAddVerts; + nAddVerts += 4; + + vertOffset_[celLoc] = nAddVerts; + decompose_.superCells_[nAddCells++] = celLoc; + } + + cellTypes_[celLoc] = foamVtkCore::VTK_TETRA; + + // See note above about the orientation. + if (isOwner) + { + vertLabels_[vrtLoc++] = tria[2]; + vertLabels_[vrtLoc++] = tria[1]; + vertLabels_[vrtLoc++] = tria[0]; + } + else + { + vertLabels_[vrtLoc++] = tria[0]; + vertLabels_[vrtLoc++] = tria[1]; + vertLabels_[vrtLoc++] = tria[2]; + } + vertLabels_[vrtLoc++] = newVertexLabel; + } + } + } + else + { + // Polyhedral cell - not decomposed + + hashUniqId.clear(); // unique node ids used (only needed for XML) + + // face-stream + // [nFaces, nFace0Pts, id1, id2, ..., nFace1Pts, id1, id2, ...] + + cellTypes_[cellI] = foamVtkCore::VTK_POLYHEDRON; + const labelList& cFaces = mesh_.cells()[cellI]; + + faceLabels_[nFaceLabels++] = cFaces.size(); + + forAll(cFaces, cFaceI) + { + const face& f = mesh_.faces()[cFaces[cFaceI]]; + const bool isOwner = (owner[cFaces[cFaceI]] == cellI); + + forAll(f, fp) + { + hashUniqId.insert(f[fp]); + } + + // number of labels for this face + faceLabels_[nFaceLabels++] = f.size(); + + if (isOwner) + { + forAll(f, fp) + { + faceLabels_[nFaceLabels++] = f[fp]; + } + } + else + { + // fairly immaterial if we reverse the list + // or use face::reverseFace() + forAllReverse(f, fp) + { + faceLabels_[nFaceLabels++] = f[fp]; + } + } + } + + faceOffset_[cellI] = nFaceLabels; + + const labelList uniq = hashUniqId.sortedToc(); + forAll(uniq, i) + { + vertLabels_[nVertLabels++] = uniq[i]; + } + + vertOffset_[cellI] = nVertLabels; + } + } + + // =========================================== + // PASS 3: Repair offsets for additional cells + +// Info<<"vertOffset: " << vertOffset_.size() << " VS. " << (mesh_.nCells()) << endl; +// Info<<"nAddCells: " << nAddCells << " VS. " << (mesh_.nCells()) << endl; + + if (nAddCells) + { + const label beg = mesh_.nCells(); + const label add = vertOffset_[beg-1]; + + for (label i = beg; i < vertOffset_.size(); ++i) + { + vertOffset_[i] += add; + } + } + + // Some basic programming/sanity checks + + if ((nVertLabels + nAddVerts) != vertOffset_[mesh_.nCells()-1 + nAddCells]) + { + WarningInFunction + << "predicted offsets (" << nVertLabels << " + " << nAddVerts << ") != " + << vertOffset_[mesh_.nCells()-1 + nAddCells] + << endl; + } + + if (offsetAddVerts != vertOffset_[mesh_.nCells()-1]) + { + WarningInFunction + << "predicted regular offset " << offsetAddVerts + << " != " << vertOffset_[mesh_.nCells()] + << endl; + } + + // nFaceLabels = 0; + // nAddPoints = 0; + // nAddCells = 0; + + // Pout<<"vertLabels: " << vertLabels_.size() << " vs. " << (nVertLabels + nAddVerts) << endl; + // Pout<<"faceLabels: " << faceLabels_.size() << " vs. " << nFaceLabels << endl; +#if 0 + if (decompose_.requested()) + { + Pout<< " Original cells:" << mesh_.nCells() + << " points:" << mesh_.nPoints() + << " Additional cells:" << decompose_.superCells_.size() + << " additional points:" << decompose_.addPointCellLabels_.size() + << nl << endl; + } +#endif +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::foamVtkCells::decomp::decomp(const bool decomposePoly) +: + addPointCellLabels_(), + superCells_(), + pointMap_(), + requested_(decomposePoly) +{} + + +Foam::foamVtkCells::foamVtkCells +( + const polyMesh& mesh, + const bool decomposePoly, + const bool lazy +) +: + mesh_(mesh), + cellTypes_(), + vertLabels_(), + vertOffset_(), + faceLabels_(), + faceOffset_(), + decompose_(decomposePoly), + needsUpdate_(true) +{ + if (!lazy) + { + correct(); + } +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::foamVtkCells::decomp::~decomp() +{} + + +Foam::foamVtkCells::~foamVtkCells() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + + +void Foam::foamVtkCells::decomp::clear() +{ + superCells_.clear(); + addPointCellLabels_.clear(); + pointMap_.clear(); +} + + +Foam::label Foam::foamVtkCells::nFieldPoints() const +{ + return mesh_.nPoints() + decompose_.addPointCellLabels_.size(); +} + + +Foam::label Foam::foamVtkCells::legacyCellPayLoad() const +{ + label payLoad = cellTypes_.size(); + + if (faceOffset_.size()) + { + // also has polys with face streams + + label begVert = 0; + label begFace = 0; + + forAll(faceOffset_, i) + { + label endFace = faceOffset_[i]; + label endVert = vertOffset_[i]; + + if (endFace > 0) + { + // poly with face stream + payLoad += endFace - begFace; + + begFace = endFace; + } + else + { + // primitive without face stream + payLoad += endVert - begVert; + } + begVert = endVert; + } + } + else if (vertOffset_.size()) + { + // primitives only, trivial + payLoad += vertOffset_[vertOffset_.size()-1]; + } + + return payLoad; +} + + +bool Foam::foamVtkCells::needsUpdate() const +{ + return needsUpdate_; +} + + +bool Foam::foamVtkCells::expire() +{ + // Clear any stored topologies + + // Clear derived data + // clearGeom(); + + // already marked as expired + if (needsUpdate_) + { + return false; + } + + needsUpdate_ = true; + return true; +} + + +bool Foam::foamVtkCells::update() +{ + if (!needsUpdate_) + { + return false; + } + + correct(); + + needsUpdate_ = false; + return true; +} + + +// ************************************************************************* // diff --git a/src/conversion/vtk/part/foamVtkCells.H b/src/conversion/vtk/part/foamVtkCells.H new file mode 100644 index 0000000000000000000000000000000000000000..692614a4b9b98e272062fb199751cde0c37980be --- /dev/null +++ b/src/conversion/vtk/part/foamVtkCells.H @@ -0,0 +1,350 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::foamVtkCells + +Description + The deep-copy description of an OpenFOAM volume mesh in data structures + corresponding to an VTK UnstructuredGrid, including the possiblity of + decomposing polyhedral cells into primitive cell types. + + Knowledge of the vtkUnstructuredGrid and the corresponding \c .vtu + xml file-format aids in understanding this class. + For flexibilty, support for the legacy vtk file-format is also provided. + + Primitive cell types are straighforward, polyhedral cells are represented + by a face stream: + \verbatim + [nFaces, nFace0Pts, id1, id2, ..., nFace1Pts, id1, id2, ...] + \endverbatim + + For the legacy format, the face stream is simply passed as vertex labels + (connectivity). + + For the xml format, the face stream is saved separately: + \verbatim + "connectivity" + == the unique vertex labels used by the cell (optionally sorted). + + "offsets": + == offset + sizeof(connectivity) + + "faces": + [nFaces, nFace0Pts, id1, id2, ..., nFace1Pts, id1, id2, ...] + + "faceoffsets": + == faceoffsets + sizeof(faces) + \endverbatim + + The storage of "connectivity" and "offsets" strongly resembles a + CompactListList, but the "offsets" point to the end of the respective + sub-lists. + +SourceFiles + foamVtkCells.C + +\*---------------------------------------------------------------------------*/ + +#ifndef foamVtkCells_H +#define foamVtkCells_H + +#include "foamVtkCore.H" +#include "DynamicList.H" +#include "SubList.H" +#include "labelList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declaration of classes +class polyMesh; + +/*---------------------------------------------------------------------------*\ + Class foamVtkCells Declaration +\*---------------------------------------------------------------------------*/ + +class foamVtkCells +: + public fileFormats::foamVtkCore +{ +public: + + //- Bookkeeping for polyhedral cell decomposition + class decomp + { + private: + friend foamVtkCells; + + // Private data + + //- Cell-centre labels for additional points of decomposed cells + DynamicList<label> addPointCellLabels_; + + //- Label of original cell for decomposed cells + DynamicList<label> superCells_; + + //- Point labels for subsetted meshes + DynamicList<label> pointMap_; + + //- Track if decomposition was requested + const bool requested_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + decomp(const decomp&) = delete; + + //- Disallow default bitwise assignment + void operator=(const decomp&) = delete; + + public: + + // Constructors + + //- Construct null + decomp(const bool decomposePoly = false); + + + //- Destructor + ~decomp(); + + + // Member Functions + + // Access + + //- Polyhedral decomposition requested + inline bool requested() const; + + //- Polyhedral decomposition used + inline bool used() const; + + //- Label of original cell for decomposed cells + inline const labelList& superCells() const; + + //- Cell-centre labels for additional points of decomposed cells + inline const labelList& addPointCellLabels() const; + + //- Point labels for subsetted meshes + inline const labelList& pointMap() const; + + + // Edit + + //- Clear + void clear(); + }; + + +private: + + // Private data + + //- Reference to underlying mesh or mesh sub-set + const polyMesh& mesh_; + + //- Cell types (including added cells) in vtk numbering + // Range is 1-255 + List<uint8_t> cellTypes_; + + //- Vertices per cell (including added cells) in vtk ordering + DynamicList<label> vertLabels_; + + //- Vertices per cell (including added cells) in vtk ordering + DynamicList<label> vertOffset_; + + //- Face lists per polyhedral cell + DynamicList<label> faceLabels_; + + //- Face label offsets + DynamicList<label> faceOffset_; + + //- Bookkeeping for polyhedral cell decomposition + decomp decompose_; + + //- Needs update + bool needsUpdate_; + + + + // Private Member Functions + + //- Create the geometry + void correct(); + + //- Disallow default bitwise copy construct + foamVtkCells(const foamVtkCells&) = delete; + + //- Disallow default bitwise assignment + void operator=(const foamVtkCells&) = delete; + + +public: + + // Constructors + + //- Construct from components. + // Optionally with polyhedral decomposition and/or lazy evaluation. + // A 'lazy' evaluation avoids fully creation within the constructor. + foamVtkCells + ( + const polyMesh&, + const bool decomposePoly = false, + const bool lazy = false + ); + + + //- Destructor + ~foamVtkCells(); + + + // Member Functions + + // Access + + //- Query the poly decompose flag. + inline bool decomposeRequested() const; + + //- Values for "connectivity" (XML) or basis for "CELLS" (legacy) + // In the legacy format, the size (offset) must be prefixed. + inline const labelList& vertLabels() const; + + //- Values for "offsets" (XML) + // or sizes to prefix for for "CELLS" (legacy) + inline const labelList& vertOffsets() const; + + //- Values for "types" (XML) and "CELL_TYPES" (legacy) + inline const List<uint8_t>& cellTypes() const; + + //- Values for "faces" (XML) + inline const labelList& faceLabels() const; + + //- Values for "faceoffsets" (XML) + inline const labelList& faceOffsets() const; + + //- Additional point addressing (from added point to original cell) + inline const labelList& addPointCellLabels() const; + + //- Additional cells mapping (from added cell to original cell) + inline const labelList& superCells() const; + + + //- Number of field cells + inline label nFieldCells() const; + + //- Number of field points + label nFieldPoints() const; + + //- The field size for legacy "CELLS". + // In the legacy format, the size (offset) must be prefixed. + label legacyCellPayLoad() const; + + + //- Does the mapping need an update? + bool needsUpdate() const; + + //- Mark as needing an update. + // May also free up unneeded data. + // Return false if it was already marked as expired. + bool expire(); + + //- Update the description (and decomposition) as required. + // Do nothing (and return false) if no update was required + bool update(); + + + //- The const_iterator for foamVtkCells + class const_iterator + { + friend class foamVtkCells; + + protected: + + // Protected Data + + //- Reference to parent list + const foamVtkCells& parent_; + + //- Element index + label index_; + + //- Begin of connectivity sub-list + mutable label begVert_; + + //- Begin of faces sub-list + mutable label begFace_; + + //- On-demand legacy pointer + mutable autoPtr<SubList<label>> legacy_; + + + // Constructors + + //- Construct begin/end iterator + inline const_iterator + ( + const foamVtkCells&, + bool isEnd = false + ); + + public: + + // Member operators + + //- On-demand legacy cell labels (primitive or faces) + inline const labelUList& legacyCell() const; + + //- Compare position + inline bool operator!=(const const_iterator&) const; + + //- Pre-increment iterator + inline const_iterator& operator++(); + }; + + + //- const_iterator set to the beginning + inline const_iterator begin() const; + + //- const_iterator set to beyond the end + inline const_iterator end() const; + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "foamVtkCellsI.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/conversion/vtk/part/foamVtkCellsI.H b/src/conversion/vtk/part/foamVtkCellsI.H new file mode 100644 index 0000000000000000000000000000000000000000..5973f5113e8de89c3630fa095c201fed966401ca --- /dev/null +++ b/src/conversion/vtk/part/foamVtkCellsI.H @@ -0,0 +1,239 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "foamVtkCells.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +inline bool Foam::foamVtkCells::decomp::requested() const +{ + return requested_; +} + + +inline bool Foam::foamVtkCells::decomp::used() const +{ + return !superCells_.empty(); +} + + +inline const Foam::labelList& +Foam::foamVtkCells::decomp::superCells() const +{ + return superCells_; +} + + +inline const Foam::labelList& +Foam::foamVtkCells::decomp::addPointCellLabels() const +{ + return addPointCellLabels_; +} + + +inline const Foam::labelList& +Foam::foamVtkCells::decomp::pointMap() const +{ + return pointMap_; +} + + +inline bool Foam::foamVtkCells::decomposeRequested() const +{ + return decompose_.requested(); +} + + +inline const Foam::labelList& +Foam::foamVtkCells::vertLabels() const +{ + return vertLabels_; +} + + +inline const Foam::labelList& +Foam::foamVtkCells::vertOffsets() const +{ + return vertOffset_; +} + + +inline const Foam::List<uint8_t>& +Foam::foamVtkCells::cellTypes() const +{ + return cellTypes_; +} + + +inline const Foam::labelList& +Foam::foamVtkCells::faceLabels() const +{ + return faceLabels_; +} + + +inline const Foam::labelList& +Foam::foamVtkCells::faceOffsets() const +{ + return faceOffset_; +} + + +inline const Foam::labelList& +Foam::foamVtkCells::addPointCellLabels() const +{ + return decompose_.addPointCellLabels(); +} + + +inline const Foam::labelList& +Foam::foamVtkCells::superCells() const +{ + return decompose_.superCells(); +} + + +inline Foam::label +Foam::foamVtkCells::nFieldCells() const +{ + return cellTypes_.size(); +} + + +inline Foam::foamVtkCells::const_iterator +Foam::foamVtkCells::begin() const +{ + return const_iterator(*this); +} + + +inline Foam::foamVtkCells::const_iterator +Foam::foamVtkCells::end() const +{ + return const_iterator(*this, true); +} + + +// * * * * * * * * * * * * * * * * Iterators * * * * * * * * * * * * * * * * // + +inline Foam::foamVtkCells::const_iterator::const_iterator +( + const foamVtkCells& cells, + bool isEnd +) +: + parent_(cells), + index_(0), + begVert_(0), + begFace_(0), + legacy_() +{ + if (isEnd) + { + index_ = parent_.vertOffsets().size(); + } +} + + +inline +Foam::foamVtkCells::const_iterator& +Foam::foamVtkCells::const_iterator::operator++() +{ + ++index_; + legacy_.clear(); + + return *this; +} + + +inline +const Foam::UList<Foam::label>& +Foam::foamVtkCells::const_iterator::legacyCell() const +{ + if + ( + legacy_.valid() + || index_ >= parent_.vertOffsets().size() + ) + { + return legacy_(); + } + + const label endVert = parent_.vertOffsets()[index_]; + + const label endFace = + ( + parent_.faceOffsets().size() + ? parent_.faceOffsets()[index_] + : -1 + ); + + if (endFace > 0) + { + // poly with face stream + + legacy_.reset + ( + new SubList<label> + ( + parent_.faceLabels(), + endFace - begFace_, + begFace_ + ) + ); + + begFace_ = endFace; + } + else + { + // primitive without face stream + legacy_.reset + ( + new SubList<label> + ( + parent_.vertLabels(), + endVert - begVert_, + begVert_ + ) + ); + } + + begVert_ = endVert; + + return legacy_(); +} + + +inline bool +Foam::foamVtkCells::const_iterator::operator!= +( + const const_iterator& rhs +) const +{ + return (index_ != rhs.index_); +} + + +// ************************************************************************* // diff --git a/src/dynamicMesh/Make/files b/src/dynamicMesh/Make/files index 215d35048d1e33999822dc8be39d9589a241d232..de8f61296cd77d4c7d1a774f90da81716deffefc 100644 --- a/src/dynamicMesh/Make/files +++ b/src/dynamicMesh/Make/files @@ -90,6 +90,7 @@ polyMeshAdder/polyMeshAdder.C fvMeshTools/fvMeshTools.C fvMeshSubset/fvMeshSubset.C +meshSubsetHelper/meshSubsetHelper.C motionSmoother/motionSmoother.C motionSmoother/motionSmootherAlgo.C diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/meshSubsetHelper.C b/src/dynamicMesh/meshSubsetHelper/meshSubsetHelper.C similarity index 88% rename from applications/utilities/postProcessing/dataConversion/foamToEnsight/meshSubsetHelper.C rename to src/dynamicMesh/meshSubsetHelper/meshSubsetHelper.C index 05bdc9420bb74411a78277f13d425798a14bcec9..0f3760654cb11e43358124b3f66d71f1799f9bbb 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/meshSubsetHelper.C +++ b/src/dynamicMesh/meshSubsetHelper/meshSubsetHelper.C @@ -28,21 +28,34 @@ License #include "cellSet.H" #include "cellZone.H" #include "Time.H" -#include "IOstreams.H" // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // +Foam::meshSubsetHelper::meshSubsetHelper +( + fvMesh& baseMesh +) +: + baseMesh_(baseMesh), + subsetter_(baseMesh), + type_(NONE), + name_() +{ + correct(); +} + + Foam::meshSubsetHelper::meshSubsetHelper ( fvMesh& baseMesh, - const word& name, - const bool isCellSet + const subsetType type, + const word& name ) : baseMesh_(baseMesh), subsetter_(baseMesh), - name_(name), - type_(name_.empty() ? 0 : isCellSet ? 1 : 2) + type_(name.empty() ? NONE : type), + name_(name) { correct(); } @@ -52,7 +65,7 @@ Foam::meshSubsetHelper::meshSubsetHelper void Foam::meshSubsetHelper::correct(bool verbose) { - if (type_ == 1) + if (type_ == SET) { if (verbose) { @@ -62,7 +75,7 @@ void Foam::meshSubsetHelper::correct(bool verbose) cellSet subset(baseMesh_, name_); subsetter_.setLargeCellSubset(subset); } - else if (type_ == 2) + else if (type_ == ZONE) { if (verbose) { diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/meshSubsetHelper.H b/src/dynamicMesh/meshSubsetHelper/meshSubsetHelper.H similarity index 86% rename from applications/utilities/postProcessing/dataConversion/foamToEnsight/meshSubsetHelper.H rename to src/dynamicMesh/meshSubsetHelper/meshSubsetHelper.H index 43112a5a18a80f250c9617a653ebe28585033bba..891e6d94a6ed625f6a4416203f7deebb9bdf80dc 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/meshSubsetHelper.H +++ b/src/dynamicMesh/meshSubsetHelper/meshSubsetHelper.H @@ -54,6 +54,17 @@ class Time; class meshSubsetHelper { +public: + + //- Internal book-keeping for subset type + enum subsetType + { + NONE, //<! Not a subset + SET, //<! Using a cellSet for the subset + ZONE //<! Using a cellZone for the subset + }; + + // Private data //- Reference to mesh @@ -62,12 +73,12 @@ class meshSubsetHelper //- Subsetting engine + sub-fvMesh fvMeshSubset subsetter_; + //- Subset type if any. + const subsetType type_; + //- Name of current cellSet/cellZone (or empty) const word name_; - //- Internal book-keeping. 0 = unused, 1 = set, 2 = zone - const int type_; - // Private Member Functions @@ -82,12 +93,15 @@ public: // Constructors + //- Construct from components + meshSubsetHelper(fvMesh& baseMesh); + //- Construct from components meshSubsetHelper ( fvMesh& baseMesh, - const word& name = word::null, - const bool isCellSet = false + const subsetType, + const word& name ); @@ -110,7 +124,7 @@ public: //- Check if running a sub-mesh is being used inline bool useSubMesh() const { - return type_; + return type_ != NONE; } //- Access either mesh or submesh @@ -146,7 +160,7 @@ public: Type, fvPatchField, volMesh - >::Internal& df + >::Internal& ); @@ -174,6 +188,11 @@ public: >::Internal& ) const; + + //- Map volume field (does in fact do very little interpolation; + // just copied from fvMeshSubset) + template<class GeoField> + tmp<GeoField> interpolate(const GeoField& fld) const; }; diff --git a/applications/utilities/postProcessing/dataConversion/foamToEnsight/meshSubsetHelperTemplates.C b/src/dynamicMesh/meshSubsetHelper/meshSubsetHelperTemplates.C similarity index 89% rename from applications/utilities/postProcessing/dataConversion/foamToEnsight/meshSubsetHelperTemplates.C rename to src/dynamicMesh/meshSubsetHelper/meshSubsetHelperTemplates.C index d588118d0f0fa6bcfdface68ea0013f9008645df..25a6d1301b7671324d1b63aacc9f0a5ecf0b98ff 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToEnsight/meshSubsetHelperTemplates.C +++ b/src/dynamicMesh/meshSubsetHelper/meshSubsetHelperTemplates.C @@ -116,4 +116,25 @@ Foam::meshSubsetHelper::interpolate } +template<class GeoField> +Foam::tmp<GeoField> +Foam::meshSubsetHelper::interpolate +( + const GeoField& fld +) const +{ + if (subsetter_.hasSubMesh()) + { + tmp<GeoField> subFld = subsetter_.interpolate(fld); + subFld.ref().checkOut(); + subFld.ref().rename(fld.name()); + return subFld; + } + else + { + return fld; + } +} + + // ************************************************************************* // diff --git a/src/edgeMesh/edgeMeshFormats/starcd/STARCDedgeFormat.C b/src/edgeMesh/edgeMeshFormats/starcd/STARCDedgeFormat.C index d58a67c562b0dfb2275384579f8ccc65055e6f26..9a002009a1c84f0bb88d4bf32134570edc983f5a 100644 --- a/src/edgeMesh/edgeMeshFormats/starcd/STARCDedgeFormat.C +++ b/src/edgeMesh/edgeMeshFormats/starcd/STARCDedgeFormat.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -37,7 +37,7 @@ inline void Foam::fileFormats::STARCDedgeFormat::writeLines const edgeList& edges ) { - writeHeader(os, "CELL"); + writeHeader(os, STARCDCore::HEADER_CEL); forAll(edges, edgeI) { @@ -45,10 +45,10 @@ inline void Foam::fileFormats::STARCDedgeFormat::writeLines const label cellId = edgeI + 1; os << cellId // includes 1 offset - << ' ' << starcdLineShape_ // 2(line) shape + << ' ' << starcdLine // 2(line) shape << ' ' << e.size() << ' ' << 401 // arbitrary value - << ' ' << starcdLineType_; // 5(line) + << ' ' << starcdLineType; // 5(line) os << nl << " " << cellId << " " << (e[0]+1) << " " << (e[1]+1) << nl; @@ -118,7 +118,7 @@ bool Foam::fileFormats::STARCDedgeFormat::read // read points from .vrt file readPoints ( - IFstream(baseName + ".vrt")(), + IFstream(starFileName(baseName, STARCDCore::VRT_FILE))(), storedPoints(), pointId ); @@ -137,7 +137,7 @@ bool Foam::fileFormats::STARCDedgeFormat::read // // read .cel file // ~~~~~~~~~~~~~~ - IFstream is(baseName + ".cel"); + IFstream is(starFileName(baseName, STARCDCore::CEL_FILE)); if (!is.good()) { FatalErrorInFunction @@ -145,7 +145,7 @@ bool Foam::fileFormats::STARCDedgeFormat::read << exit(FatalError); } - readHeader(is, "PROSTAR_CELL"); + readHeader(is, STARCDCore::HEADER_CEL); DynamicList<edge> dynEdges; @@ -173,7 +173,7 @@ bool Foam::fileFormats::STARCDedgeFormat::read vertexLabels.append(mapPointId[vrtId]); } - if (typeId == starcdLineType_) + if (typeId == starcdLineType) { if (vertexLabels.size() >= 2) { @@ -239,13 +239,21 @@ void Foam::fileFormats::STARCDedgeFormat::write fileName baseName = filename.lessExt(); - writePoints(OFstream(baseName + ".vrt")(), pointLst); - writeLines(OFstream(baseName + ".cel")(), edgeLst); + writePoints + ( + OFstream(starFileName(baseName, STARCDCore::VRT_FILE))(), + pointLst + ); + writeLines + ( + OFstream(starFileName(baseName, STARCDCore::CEL_FILE))(), + edgeLst + ); // write a simple .inp file writeCase ( - OFstream(baseName + ".inp")(), + OFstream(starFileName(baseName, STARCDCore::INP_FILE))(), pointLst, edgeLst.size() ); diff --git a/src/edgeMesh/edgeMeshFormats/starcd/STARCDedgeFormat.H b/src/edgeMesh/edgeMeshFormats/starcd/STARCDedgeFormat.H index bc5a0ec1bbc96f4aefc533901580a4755443e698..d4c2206ff6c31e0c3dc16144d8ed149168d5edb9 100644 --- a/src/edgeMesh/edgeMeshFormats/starcd/STARCDedgeFormat.H +++ b/src/edgeMesh/edgeMeshFormats/starcd/STARCDedgeFormat.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -62,30 +62,18 @@ namespace fileFormats class STARCDedgeFormat : public edgeMesh, - public STARCDCore + protected STARCDCore { - // Private Data - - //- STAR-CD identifier for line shapes (1d elements) - static const int starcdLineShape_ = 2; - - //- STAR-CD identifier for line type - static const int starcdLineType_ = 5; - - // Private Member Functions - static inline void writeLines - ( - Ostream&, - const edgeList& - ); + static inline void writeLines(Ostream&, const edgeList&); + //- Disallow default bitwise copy construct - STARCDedgeFormat(const STARCDedgeFormat&); + STARCDedgeFormat(const STARCDedgeFormat&) = delete; //- Disallow default bitwise assignment - void operator=(const STARCDedgeFormat&); + void operator=(const STARCDedgeFormat&) = delete; protected: diff --git a/src/fileFormats/Make/files b/src/fileFormats/Make/files index c972fde32e70d577dd7bc1f49fcdd51d1e61d8f0..8919e3392d620678737974d272ee3dd44f807754 100644 --- a/src/fileFormats/Make/files +++ b/src/fileFormats/Make/files @@ -7,10 +7,21 @@ ensight/part/ensightFaces.C ensight/read/ensightReadFile.C ensight/type/ensightPTraits.C -vtk/vtkUnstructuredReader.C nas/NASCore.C +fire/FIRECore.C starcd/STARCDCore.C +vtk/foamVtkCore.C +vtk/format/foamVtkAppendBase64Formatter.C +vtk/format/foamVtkAppendRawFormatter.C +vtk/format/foamVtkAsciiFormatter.C +vtk/format/foamVtkBase64Formatter.C +vtk/format/foamVtkLegacyFormatter.C +vtk/format/foamVtkFormatter.C +vtk/format/foamVtkOutputOptions.C +vtk/read/vtkUnstructuredReader.C +vtk/type/foamVtkPTraits.C + coordSet/coordSet.C setWriters = sampledSetWriters diff --git a/src/fileFormats/fire/FIRECore.C b/src/fileFormats/fire/FIRECore.C new file mode 100644 index 0000000000000000000000000000000000000000..ab576116348cdc4d698b2966e16b4b1a7b69b051 --- /dev/null +++ b/src/fileFormats/fire/FIRECore.C @@ -0,0 +1,370 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "FIRECore.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const Foam::NamedEnum<Foam::fileFormats::FIRECore::fileExt3d, 4> + Foam::fileFormats::FIRECore::file3dExtensions; + +namespace Foam +{ + template<> + const char* Foam::NamedEnum + < + Foam::fileFormats::FIRECore::fileExt3d, + 4 + >::names[] = + { + "fpma", + "fpmb", + "fpmaz", + "fpmbz" + }; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::fileFormats::FIRECore::FIRECore() +{} + + +// * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * * // + +Foam::label Foam::fileFormats::FIRECore::readPoints +( + ISstream& is, + pointField& points +) +{ + const label n = getFireLabel(is); + + if (n > 0) + { + points.setSize(n); + + // read the coordinates + forAll(points, pointI) + { + points[pointI] = getFirePoint(is); + } + } + else + { + FatalErrorInFunction + << "no points in file " << is.name() + << abort(FatalError); + } + + return n; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +Foam::fileName Foam::fileFormats::FIRECore::fireFileName +( + const fileName& base, + const enum fileExt3d ext +) +{ + return base + '.' + file3dExtensions[ext]; +} + + +Foam::label Foam::fileFormats::FIRECore::getFireLabel(ISstream& is) +{ + if (is.format() == IOstream::BINARY) + { + fireInt_t ivalue; + + is.stdStream().read + ( + reinterpret_cast<char *>(&ivalue), + sizeof(ivalue) + ); + + return ivalue; + } + else + { + return readLabel(is); + } +} + + +Foam::point Foam::fileFormats::FIRECore::getFirePoint(ISstream& is) +{ + point pt; + + if (is.format() == IOstream::BINARY) + { + fireReal_t coord[3]; + + is.stdStream().read + ( + reinterpret_cast<char *>(&coord), + sizeof(coord) + ); + + pt.x() = coord[0]; + pt.y() = coord[1]; + pt.z() = coord[2]; + } + else + { + pt.x() = readScalar(is); + pt.y() = readScalar(is); + pt.z() = readScalar(is); + } + + return pt; +} + + +std::string Foam::fileFormats::FIRECore::getFireString(ISstream& is) +{ + std::string str; + + if (is.format() == IOstream::BINARY) + { + long len; + + is.stdStream().read + ( + reinterpret_cast<char *>(&len), + sizeof(len) + ); + + str.resize(len); + + for (std::size_t pos = 0; pos < str.size(); ++pos) + { + is.stdStream().read(&(str[pos]), sizeof(char)); + } + } + else + { + const std::string whitespace(" \t\f\v\n\r"); + + string s; + + // use a low-level getline, but this means we must handle + // blank lines manually + while (s.empty()) + { + is.getLine(s); + if (!s.empty()) + { + // remove prefix whitespace + size_t pos = s.find_first_not_of(whitespace); + + if (pos != std::string::npos) + { + s.erase(0, pos); + + // remove suffix whitespace + pos = s.find_last_not_of(whitespace); + if (pos != std::string::npos) + { + s.erase(pos + 1); + } + } + + if (pos == std::string::npos) + { + s.clear(); + } + } + } + + str.swap(s); + } + + return str; +} + + +void Foam::fileFormats::FIRECore::putFireLabel +( + OSstream& os, + const label value +) +{ + if (os.format() == Foam::IOstream::BINARY) + { + fireInt_t ivalue(value); + + os.stdStream().write + ( + reinterpret_cast<char const *>(&ivalue), + sizeof(ivalue) + ); + } + else + { + os << value; + } +} + + +void Foam::fileFormats::FIRECore::putFireLabels +( + OSstream& os, + const labelUList& lst +) +{ + if (os.format() == IOstream::BINARY) + { + fireInt_t ivalue(lst.size()); + + os.stdStream().write + ( + reinterpret_cast<char const *>(&ivalue), + sizeof(ivalue) + ); + + forAll(lst, i) + { + ivalue = lst[i]; + + os.stdStream().write + ( + reinterpret_cast<char const *>(&ivalue), + sizeof(ivalue) + ); + } + } + else + { + os << ' ' << lst.size(); + forAll(lst, i) + { + os << ' ' << lst[i]; + } + os << '\n'; + } +} + + +void Foam::fileFormats::FIRECore::putFireLabels +( + OSstream& os, + const label count, + const label start +) +{ + if (os.format() == IOstream::BINARY) + { + fireInt_t ivalue(count); + + os.stdStream().write + ( + reinterpret_cast<char const *>(&ivalue), + sizeof(ivalue) + ); + + ivalue = start; + for (label i=0; i < count; ++i, ++ivalue) + { + os.stdStream().write + ( + reinterpret_cast<char const *>(&ivalue), + sizeof(ivalue) + ); + } + } + else + { + os << ' ' << count; + + label ivalue = start; + for (label i = 0; i < count; ++i, ++ivalue) + { + os << ' ' << ivalue; + } + os << '\n'; + } +} + + +void Foam::fileFormats::FIRECore::putFirePoint +( + OSstream& os, + const point& value +) +{ + if (os.format() == IOstream::BINARY) + { + fireReal_t fvalue[3]; + fvalue[0] = value.x(); + fvalue[1] = value.y(); + fvalue[2] = value.z(); + + os.stdStream().write + ( + reinterpret_cast<char const *>(&fvalue), + sizeof(fvalue) + ); + } + else + { + os << ' ' + << value.x() << ' ' + << value.y() << ' ' + << value.z() << '\n'; + } +} + + +void Foam::fileFormats::FIRECore::putFireString +( + OSstream& os, + const std::string& value +) +{ + if (os.format() == IOstream::BINARY) + { + long len(value.size()); + + os.stdStream().write + ( + reinterpret_cast<char const *>(&len), + sizeof(len) + ); + + os.stdStream().write(value.data(), len); + } + else + { + // output without surrounding quotes + os.stdStream() << value << '\n'; + } +} + + +// ************************************************************************* // diff --git a/src/fileFormats/fire/FIRECore.H b/src/fileFormats/fire/FIRECore.H new file mode 100644 index 0000000000000000000000000000000000000000..3f9c654cc1ea1acdf0b5027a140d2014a3e44859 --- /dev/null +++ b/src/fileFormats/fire/FIRECore.H @@ -0,0 +1,179 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::fileFormats::FIRECore + +Description + Core routines used when reading/writing AVL/FIRE files. + +SourceFiles + FIRECore.C + +\*---------------------------------------------------------------------------*/ + +#ifndef FIRECore_H +#define FIRECore_H + +#include "point.H" +#include "string.H" +#include "labelList.H" +#include "pointField.H" +#include "IOstreams.H" +#include "NamedEnum.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +// forward declarations +class polyMesh; + +namespace fileFormats +{ + +/*---------------------------------------------------------------------------*\ + Class fileFormats::FIRECore Declaration +\*---------------------------------------------------------------------------*/ + +class FIRECore +{ +public: + + // Public Data, Declarations + + //- Selection Types + enum selectionType + { + cellSelection = 2, + faceSelection = 3 + }; + + //- Shape-Type for FIRE (FLMA) files + enum shapeType + { + fireLine = 1, + fireTri = 2, + fireQuad = 3, + fireTet = 4, + fireHex = 5, + firePyr = 6, + firePrism = 8 + }; + + //- Enumeration defining the file extensions for 3D types + enum fileExt3d + { + POLY_ASCII, + POLY_BINARY, + POLY_ASCII_COMPRESSED, + POLY_BINARY_COMPRESSED + }; + + + //- Integer type (binary format) + typedef int32_t fireInt_t; + + //- Float type (binary format) + typedef double fireReal_t; + +protected: + + // Protected Data + + static const NamedEnum<fileExt3d, 4> file3dExtensions; + + + // Protected Member Functions + + //- Construct null + FIRECore(); + + + //- Read points. + // This is the first thing to do when reading FPMA,FPMB,FLMA files. + // Return the number of points read. + // + // The file format is as follows: + // \verbatim + // NUMBER_OF_VERTICES + // x0 y0 z0 x1 y1 z1 ... xN-1 yN-1 zN-1 + // \endverbatim + static label readPoints(ISstream&, pointField&); + +public: + + // Public Member Functions + + //- Resolve base file-name for the given file-type + static fileName fireFileName + ( + const fileName& baseName, + const enum fileExt3d + ); + + + //- Get an integer (ascii or binary) + static label getFireLabel(ISstream&); + + //- Get an point x/y/z (ascii or binary) + static point getFirePoint(ISstream&); + + //- Extract a string (ascii or binary) + static std::string getFireString(ISstream&); + + + //- Write an integer (ascii or binary) + static void putFireLabel(OSstream&, const label); + + //- Write multiple integers (ascii or binary) + static void putFireLabels(OSstream&, const labelUList&); + + //- Write an on-the-fly list of integers (ascii or binary) + static void putFireLabels + ( + OSstream&, + const label count, + const label start + ); + + + //- Write a point x/y/z (ascii or binary) + static void putFirePoint(OSstream&, const point&); + + //- Write a string (ascii or binary) + static void putFireString(OSstream&, const std::string&); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace fileFormats +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/fileFormats/fire/README b/src/fileFormats/fire/README new file mode 100644 index 0000000000000000000000000000000000000000..1cf217d220506c415045a070a582653de5786cc8 --- /dev/null +++ b/src/fileFormats/fire/README @@ -0,0 +1,124 @@ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + AVL/FIRE fpma/fpmb +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +fpma/fpmb are polyhedral formats (ASCII and BINARY). +The fpmaz/fpmbz are the same, but in compressed format. + +The fpma/fpmb format can exported directly from within the FIRE GUI. +However, it is not recommended to import them directly. +Instead use the utility fire_wm_convert_file, fire_wm_convert_mesh +(or equivalents) +are used to rewrite the fpma/fpmb into the internal FIRE format. + + +~~~~~~ +FORMAT +~~~~~~ + +NUMBER_OF_VERTICES +x0 y0 z0 x1 y1 z1 ... xN-1 yN-1 zN-1 + + +NUMBER_OF_FACES +face-stream0 +... +face-streamN-1 + + +NUMBER_OF_CELLS +cell-face-stream0 +.. +cell-face-streamN-1 + + +NUMBER_OF_SELECTIONS +selectionName[0] +selectionType[0] (2 = cells, 3 = faces) +numberOfIDs +id0 .. indN-1 +<blank-line> + + + +The face-stream: + nvert vert0 .. vertN + +The cell-face-stream: + nface faceId0 .. faceIdN + + +CAUTION: + The FIRE faces have inward-facing normals. + The OPENFOAM faces have outward-facing normals! + + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + AVL/FIRE flma +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The AVL/FIRE flma format is very simple, but can only be used for 1D/2D shapes +and for 3D primitive shapes. + +it is fairly easy to write and to parse. +For 3D polyhedra, the cell-types are non-obvious and not easily determined +- the fpma/fpmb format is preferred for that. + + +~~~~~~ +FORMAT +~~~~~~ +NUMBER_OF_VERTICES +x0 y0 z0 x1 y1 z1 ... xN-1 yN-1 zN-1 + +NUMBER_OF_CELLS +nv[0] +verts[0] +nv[N-1] +... +verts[N-1] +<blank-line> +NUMBER_OF_CELLS +type0 type1 ... type2 +<blank-line> +NUMBER_OF_SELECTIONS +selectionName[0] +selectionType[0] (2 = cells, 3 = faces) +numberOfIDs +id0 .. indN-1 +<blank-line> +... +selectionName[N-1] +selectionType[N-1] (2 = cells, 3 = faces) +numberOfIDs +id0 .. indN-1 +<blank-line> + + +-- NOTES (flma) -- +# vertex/cells are zero-based + + cell-types: + 1 = line + 2 = tri + 3 = quad + 4 = tet + 5 = hex + 6 = pyr + 8 = prism + + +---------------+---------------+ + | shape | face-order | + +---------------+---------------+ + + Tet(FIRE) | 0 1 2 3 | + + Tet(FOAM) | 3 2 0 1 | + +---------------+---------------+ + + Hex(FIRE) | 0 1 2 3 4 5 | + + Hex(FOAM) | 4 5 0 1 2 3 | + +---------------+---------------+ + + Pyr(FIRE) | 0 1 2 3 4 | + + Pyr(FOAM) | 0 4 3 2 1 | + +---------------+---------------+ + + Prism(FIRE) | 0 1 2 3 4 | + + Prism(FOAM) | 0 1 4 3 2 | + +---------------+---------------+ + diff --git a/src/fileFormats/starcd/STARCDCore.C b/src/fileFormats/starcd/STARCDCore.C index 5e1ef1fb08aba3ff745dda43e7e37ddf1aa9207e..612b9c30911fb2913314787a888cdcb0ee7ea1bf 100644 --- a/src/fileFormats/starcd/STARCDCore.C +++ b/src/fileFormats/starcd/STARCDCore.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -28,6 +28,72 @@ License #include "clock.H" #include "PackedBoolList.H" #include "IStringStream.H" +#include "OSspecific.H" + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const Foam::NamedEnum<Foam::fileFormats::STARCDCore::fileHeader, 3> + Foam::fileFormats::STARCDCore::fileHeaders_; + +const Foam::NamedEnum<Foam::fileFormats::STARCDCore::fileExt, 4> + Foam::fileFormats::STARCDCore::fileExtensions_; + +namespace Foam +{ + template<> + const char* Foam::NamedEnum + < + Foam::fileFormats::STARCDCore::fileHeader, + 3 + >::names[] = + { + "PROSTAR_CELL", + "PROSTAR_VERTEX", + "PROSTAR_BOUNDARY" + }; + + template<> + const char* Foam::NamedEnum + < + Foam::fileFormats::STARCDCore::fileExt, + 4 + >::names[] = + { + "cel", + "vrt", + "bnd", + "inp" + }; +} + + +const char* const Foam::fileFormats::STARCDCore::defaultBoundaryName = + "Default_Boundary_Region"; + +const char* const Foam::fileFormats::STARCDCore::defaultSolidBoundaryName = + "Default_Boundary_Solid"; + + +const Foam::Map<Foam::FixedList<int, 6>> +Foam::fileFormats::STARCDCore::foamToStarFaceAddr = +{ + { starcdHex, { 4, 5, 2, 3, 0, 1 } }, + { starcdPrism, { 0, 1, 4, 5, 2, -1 } }, + { starcdTet, { 5, 4, 2, 0, -1, -1 } }, + { starcdPyr, { 0, 4, 3, 5, 2, -1 } } +}; + + +const Foam::Map<Foam::FixedList<int, 6>> +Foam::fileFormats::STARCDCore::starToFoamFaceAddr = +{ + { starcdHex, { 4, 5, 2, 3, 0, 1 } }, + { starcdPrism, { 0, 1, 4, -1, 2, 3 } }, + { starcdTet, { 3, -1, 2, -1, 1, 0 } }, + { starcdPyr, { 0, -1, 4, 2, 1, 3 } } +}; + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // @@ -40,7 +106,7 @@ Foam::fileFormats::STARCDCore::STARCDCore() bool Foam::fileFormats::STARCDCore::readHeader ( IFstream& is, - const word& signature + const enum fileHeader header ) { if (!is.good()) @@ -49,22 +115,25 @@ bool Foam::fileFormats::STARCDCore::readHeader << abort(FatalError); } - word header; + word magic; label majorVersion; string line; is.getLine(line); - IStringStream(line)() >> header; + IStringStream(line)() >> magic; is.getLine(line); IStringStream(line)() >> majorVersion; // add other checks ... - if (header != signature) + if (magic != fileHeaders_[header]) { - Info<< "header mismatch " << signature << " " << is.name() + Info<< "header mismatch " << fileHeaders_[header] + << " " << is.name() << endl; + + return false; } return true; @@ -74,10 +143,10 @@ bool Foam::fileFormats::STARCDCore::readHeader void Foam::fileFormats::STARCDCore::writeHeader ( Ostream& os, - const word& filetype + const enum fileHeader header ) { - os << "PROSTAR_" << filetype << nl + os << fileHeaders_[header] << nl << 4000 << " " << 0 << " " << 0 @@ -92,13 +161,34 @@ void Foam::fileFormats::STARCDCore::writeHeader // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -bool Foam::fileFormats::STARCDCore::readPoints +Foam::fileName Foam::fileFormats::STARCDCore::starFileName +( + const fileName& base, + const enum fileExt ext +) +{ + return base + '.' + fileExtensions_[ext]; +} + + +void Foam::fileFormats::STARCDCore::removeFiles(const fileName& base) +{ + Foam::rm(starFileName(base, VRT_FILE)); + Foam::rm(starFileName(base, CEL_FILE)); + Foam::rm(starFileName(base, BND_FILE)); + Foam::rm(starFileName(base, INP_FILE)); +} + + +Foam::label Foam::fileFormats::STARCDCore::readPoints ( IFstream& is, pointField& points, labelList& ids ) { + label maxId = 0; + if (!is.good()) { FatalErrorInFunction @@ -106,8 +196,7 @@ bool Foam::fileFormats::STARCDCore::readPoints << exit(FatalError); } - readHeader(is, "PROSTAR_VERTEX"); - + readHeader(is, HEADER_VRT); // reuse memory if possible DynamicList<point> dynPoints(points.xfer()); @@ -116,31 +205,35 @@ bool Foam::fileFormats::STARCDCore::readPoints dynPoints.clear(); dynPointId.clear(); - label lineLabel; - while ((is >> lineLabel).good()) { + label lineLabel; scalar x, y, z; - is >> x >> y >> z; + while ((is >> lineLabel).good()) + { + maxId = max(maxId, lineLabel); + is >> x >> y >> z; - dynPoints.append(point(x, y, z)); - dynPointId.append(lineLabel); + dynPoints.append(point(x, y, z)); + dynPointId.append(lineLabel); + } } points.transfer(dynPoints); ids.transfer(dynPointId); - return true; + return maxId; } void Foam::fileFormats::STARCDCore::writePoints ( Ostream& os, - const pointField& pointLst + const pointField& points, + const double scaleFactor ) { - writeHeader(os, "VERTEX"); + writeHeader(os, HEADER_VRT); // Set the precision of the points data to 10 os.precision(10); @@ -148,18 +241,17 @@ void Foam::fileFormats::STARCDCore::writePoints // force decimal point for Fortran input os.setf(std::ios::showpoint); - forAll(pointLst, ptI) + forAll(points, ptI) { + // convert [m] -> [mm] etc os - << ptI + 1 << " " - << pointLst[ptI].x() << " " - << pointLst[ptI].y() << " " - << pointLst[ptI].z() << nl; + << ptI + 1 << ' ' + << scaleFactor * points[ptI].x() << ' ' + << scaleFactor * points[ptI].y() << ' ' + << scaleFactor * points[ptI].z() << '\n'; } os.flush(); } - - // ************************************************************************* // diff --git a/src/fileFormats/starcd/STARCDCore.H b/src/fileFormats/starcd/STARCDCore.H index 25920cdda26ebebb9a5e2cd3d141c0c1519d5e7d..cae3d1e7c0de7a8e7a6a3e6d305f49642f354cff 100644 --- a/src/fileFormats/starcd/STARCDCore.H +++ b/src/fileFormats/starcd/STARCDCore.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -36,7 +36,10 @@ SourceFiles #define STARCDCore_H #include "IFstream.H" +#include "NamedEnum.H" #include "pointField.H" +#include "Map.H" +#include "FixedList.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -52,20 +55,29 @@ namespace fileFormats class STARCDCore { -protected: - - // Protected Member Functions - - //- Read header - static bool readHeader(IFstream&, const word& fileSignature); +public: - //- Write header for fileType (CELL|VERTEX|BOUNDARY) - static void writeHeader(Ostream&, const word& fileType); + // Public Data, Declarations + //- Enumeration defining the file headers + enum fileHeader + { + HEADER_CEL, + HEADER_VRT, + HEADER_BND + }; -protected: + //- Enumeration defining the file extensions + enum fileExt + { + CEL_FILE, + VRT_FILE, + BND_FILE, + INP_FILE + }; - enum cellType + //- Basic material type for STARCD/PROSTAR files + enum matlType { starcdFluidType = 1, starcdSolidType = 2, @@ -75,6 +87,7 @@ protected: starcdPointType = 6 }; + //- Shape-Type for STARCD/PROSTAR files enum shapeType { starcdPoint = 1, @@ -88,11 +101,61 @@ protected: }; + //- The name for default (unassigned) boundaries + static const char* const defaultBoundaryName; + + //- The name we have chosen for default (unassigned) solid boundaries. + // Slightly distinguished from the regular default name. + static const char* const defaultSolidBoundaryName; + + +private: + + // Private Data + + static const NamedEnum<fileHeader, 3> fileHeaders_; + static const NamedEnum<fileExt, 4> fileExtensions_; + + +protected: + + // Protected Member Functions + + //- Face addressing from pro-STAR faces to OpenFOAM faces. + // For hex, prism, tet, pyr primitive shapes. + static const Map<FixedList<int, 6>> starToFoamFaceAddr; + + //- Face addressing from OpenFOAM faces to pro-STAR faces. + // For hex, prism, tet, pyr primitive shapes. + static const Map<FixedList<int, 6>> foamToStarFaceAddr; + + + // Constructors + + //- Construct null + STARCDCore(); + + //- Read header and check signature PROSTAR_(CELL|VERTEX|BOUNDARY) + static bool readHeader(IFstream&, const enum fileHeader); + + //- Write header for fileType (CELL|VERTEX|BOUNDARY) + static void writeHeader(Ostream&, const enum fileHeader); + + public: // Public Member Functions - //- Read points from a (.vrt) file + //- Resolve base file-name for the given file-type + static fileName starFileName(const fileName& baseName, const enum fileExt); + + + //- Remove existing PROSTAR files for the given base file-name + static void removeFiles(const fileName& baseName); + + + //- Read points from a (.vrt) file, return the max prostar id used. + // // The file format is as follows: // \verbatim // Line 1: @@ -104,16 +167,20 @@ public: // Body: // {vertexId} {x} {y} {z} newline // \endverbatim - static bool readPoints(IFstream&, pointField&, labelList& ids); - - //- Write header and points to (.vrt) file - static void writePoints(Ostream&, const pointField&); - - - // Constructors - - //- Construct null - STARCDCore(); + static label readPoints + ( + IFstream&, + pointField&, + labelList& ids + ); + + //- Write header and points to (.vrt) file, optionally with scaling + static void writePoints + ( + Ostream&, + const pointField&, + const scalar scaleFactor = 1.0 + ); }; diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/vtkMesh.C b/src/fileFormats/vtk/foamVtkCore.C similarity index 53% rename from applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/vtkMesh.C rename to src/fileFormats/vtk/foamVtkCore.C index d13a96df3d4753375cdbfc514c4f6571ca82fa2c..2450c02b7b2d0c1c7acc86c9a1c7f6395410bbc0 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK/vtkMesh.C +++ b/src/fileFormats/vtk/foamVtkCore.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -23,60 +23,32 @@ License \*---------------------------------------------------------------------------*/ -#include "vtkMesh.H" -#include "fvMeshSubset.H" -#include "Time.H" -#include "cellSet.H" - -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - -Foam::vtkMesh::vtkMesh -( - fvMesh& baseMesh, - const word& setName -) -: - baseMesh_(baseMesh), - subsetter_(baseMesh), - setName_(setName) -{ - if (setName.size()) - { - // Read cellSet using whole mesh - cellSet currentSet(baseMesh_, setName_); - - // Set current subset - subsetter_.setLargeCellSubset(currentSet); - } -} +#include "foamVtkCore.H" +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -Foam::polyMesh::readUpdateState Foam::vtkMesh::readUpdate() -{ - polyMesh::readUpdateState meshState = baseMesh_.readUpdate(); +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - if (meshState != polyMesh::UNCHANGED) - { - // Note: since fvMeshSubset has no movePoints() functionality, - // reconstruct the subset even if only movement. +Foam::fileFormats::foamVtkCore::foamVtkCore() +{} - topoPtr_.clear(); - if (setName_.size()) - { - Info<< "Subsetting mesh based on cellSet " << setName_ << endl; +// * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * * // - // Read cellSet using whole mesh - cellSet currentSet(baseMesh_, setName_); - subsetter_.setLargeCellSubset(currentSet); - } - } +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - return meshState; +/* +Foam::fileName Foam::fileFormats::foamVtkCore::vtkFileName +( + const fileName& base, + const enum fileExt ext +) +{ + return base + '.' + fileExtensions_[ext]; } +*/ // ************************************************************************* // diff --git a/src/fileFormats/vtk/foamVtkCore.H b/src/fileFormats/vtk/foamVtkCore.H new file mode 100644 index 0000000000000000000000000000000000000000..adcdc00871a5300fb0e5ddb4e12345473d40b1f8 --- /dev/null +++ b/src/fileFormats/vtk/foamVtkCore.H @@ -0,0 +1,109 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::foamVtkCore + +Description + Core routines for dealing with VTK files. + +SourceFiles + foamVtkCore.C + +\*---------------------------------------------------------------------------*/ + +#ifndef foamVtkCore_H +#define foamVtkCore_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace fileFormats +{ + +/*---------------------------------------------------------------------------*\ + Class fileFormats::foamVtkCore Declaration +\*---------------------------------------------------------------------------*/ + +class foamVtkCore +{ +public: + + // Public Data, Declarations + + //- The context when outputting a VTK file (XML or legacy). + enum OutputContext + { + INLINE, //<! Generate header and inline data + HEADER, //<! Generate header only + APPEND //<! Generate append-data + }; + + + //- Equivalent to enumeration in "vtkCellType.h" + enum vtkTypes + { + VTK_EMPTY_CELL = 0, + VTK_VERTEX = 1, + VTK_POLY_VERTEX = 2, + VTK_LINE = 3, + VTK_POLY_LINE = 4, + VTK_TRIANGLE = 5, + VTK_TRIANGLE_STRIP = 6, + VTK_POLYGON = 7, + VTK_PIXEL = 8, + VTK_QUAD = 9, + VTK_TETRA = 10, + VTK_VOXEL = 11, + VTK_HEXAHEDRON = 12, + VTK_WEDGE = 13, + VTK_PYRAMID = 14, + VTK_PENTAGONAL_PRISM = 15, + VTK_HEXAGONAL_PRISM = 16, + VTK_POLYHEDRON = 42 + }; + + +protected: + + // Constructors + + //- Construct null + foamVtkCore(); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace fileFormats + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkAppendBase64Formatter.C b/src/fileFormats/vtk/format/foamVtkAppendBase64Formatter.C new file mode 100644 index 0000000000000000000000000000000000000000..ee8b84200f0aaa5b8d333d2e577b44c2d5289be3 --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkAppendBase64Formatter.C @@ -0,0 +1,65 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "foamVtkAppendBase64Formatter.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const char* Foam::foamVtkAppendBase64Formatter::name_ = "append"; +const char* Foam::foamVtkAppendBase64Formatter::encoding_ = "base64"; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::foamVtkAppendBase64Formatter::foamVtkAppendBase64Formatter +( + std::ostream& os +) +: + foamVtkBase64Formatter(os) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::foamVtkAppendBase64Formatter::~foamVtkAppendBase64Formatter() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +const char* Foam::foamVtkAppendBase64Formatter::name() const +{ + return name_; +} + + +const char* Foam::foamVtkAppendBase64Formatter::encoding() const +{ + return encoding_; +} + + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkAppendBase64Formatter.H b/src/fileFormats/vtk/format/foamVtkAppendBase64Formatter.H new file mode 100644 index 0000000000000000000000000000000000000000..b7239ee7c66ffc637441b4504eb69a9a74f52a24 --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkAppendBase64Formatter.H @@ -0,0 +1,99 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + foamVtkAppendBase64Formatter + +Description + Appended base-64 encoded binary output. + Uses an output filter layer to write base-64 encoded content. + +SourceFiles + foamVtkAppendBase64Formatter.C + +\*---------------------------------------------------------------------------*/ + +#ifndef foamVtkAppendBase64Formatter_H +#define foamVtkAppendBase64Formatter_H + +#include "foamVtkBase64Formatter.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class foamVtkAppendBase64Formatter Declaration +\*---------------------------------------------------------------------------*/ + +class foamVtkAppendBase64Formatter +: + public foamVtkBase64Formatter +{ + // Private Data Members + + static const char* name_; + static const char* encoding_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + foamVtkAppendBase64Formatter(const foamVtkAppendBase64Formatter&) = delete; + + //- Disallow default bitwise assignment + void operator=(const foamVtkAppendBase64Formatter&) = delete; + + +public: + + // Constructors + + //- Construct and attach to an output stream + foamVtkAppendBase64Formatter(std::ostream&); + + + //- Destructor + virtual ~foamVtkAppendBase64Formatter(); + + + // Member Functions + + //- Output name for XML type ("append") + virtual const char* name() const; + + //- Name for the XML append encoding ("base64"). + virtual const char* encoding() const; + +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkAppendRawFormatter.C b/src/fileFormats/vtk/format/foamVtkAppendRawFormatter.C new file mode 100644 index 0000000000000000000000000000000000000000..9933970495ea2e8a920659bf6f61edd680933914 --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkAppendRawFormatter.C @@ -0,0 +1,112 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "foamVtkAppendRawFormatter.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const char* Foam::foamVtkAppendRawFormatter::name_ = "append"; +const char* Foam::foamVtkAppendRawFormatter::encoding_ = "raw"; + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +void Foam::foamVtkAppendRawFormatter::write +( + const char* s, + std::streamsize n +) +{ + os().write(s, n); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::foamVtkAppendRawFormatter::foamVtkAppendRawFormatter(std::ostream& os) +: + foamVtkFormatter(os) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::foamVtkAppendRawFormatter::~foamVtkAppendRawFormatter() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +const char* Foam::foamVtkAppendRawFormatter::name() const +{ + return name_; +} + + +const char* Foam::foamVtkAppendRawFormatter::encoding() const +{ + return encoding_; +} + + +void Foam::foamVtkAppendRawFormatter::writeSize(const uint64_t val) +{ + write(reinterpret_cast<const char*>(&val), sizeof(uint64_t)); +} + + +void Foam::foamVtkAppendRawFormatter::write(const uint8_t val) +{ + write(reinterpret_cast<const char*>(&val), sizeof(uint8_t)); +} + + +void Foam::foamVtkAppendRawFormatter::write(const label val) +{ + // std::cerr<<"label is:" << sizeof(val) << '\n'; + write(reinterpret_cast<const char*>(&val), sizeof(label)); +} + + +void Foam::foamVtkAppendRawFormatter::write(const float val) +{ + // std::cerr<<"float is:" << sizeof(val) << '\n'; + write(reinterpret_cast<const char*>(&val), sizeof(float)); +} + + +void Foam::foamVtkAppendRawFormatter::write(const double val) +{ + // std::cerr<<"write double as float:" << val << '\n'; + float copy(val); + write(copy); +} + + +void Foam::foamVtkAppendRawFormatter::flush() +{} + + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkAppendRawFormatter.H b/src/fileFormats/vtk/format/foamVtkAppendRawFormatter.H new file mode 100644 index 0000000000000000000000000000000000000000..abc3db09293f7baccc6c1796ef4ba3ffe40d2e1d --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkAppendRawFormatter.H @@ -0,0 +1,115 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + foamVtkAppendRawFormatter + +Description + Appended raw binary output. + +SourceFiles + foamVtkAppendRawFormatter.C + +\*---------------------------------------------------------------------------*/ + +#ifndef foamVtkAppendRawFormatter_H +#define foamVtkAppendRawFormatter_H + +#include "foamVtkFormatter.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class foamVtkAppendRawFormatter Declaration +\*---------------------------------------------------------------------------*/ + +class foamVtkAppendRawFormatter +: + public foamVtkFormatter +{ + // Private Data Members + + static const char* name_; + static const char* encoding_; + + // Private Member Functions + + //- Disallow default bitwise copy construct + foamVtkAppendRawFormatter(const foamVtkAppendRawFormatter&) = delete; + + //- Disallow default bitwise assignment + void operator=(const foamVtkAppendRawFormatter&) = delete; + + +protected: + + // Protected Member Functions + + //- Write + void write(const char* s, std::streamsize n); + + +public: + + // Constructors + + //- Construct and attach to an output stream + foamVtkAppendRawFormatter(std::ostream&); + + + //- Destructor + virtual ~foamVtkAppendRawFormatter(); + + + // Member Functions + + //- Output name for XML type ("append") + virtual const char* name() const; + + //- Output name for append encoding type ("raw") + virtual const char* encoding() const; + + + //- Write leading size for binary output + virtual void writeSize(const uint64_t); + + virtual void write(const uint8_t); + virtual void write(const label); + virtual void write(const float); + virtual void write(const double); + virtual void flush(); + +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkAsciiFormatter.C b/src/fileFormats/vtk/format/foamVtkAsciiFormatter.C new file mode 100644 index 0000000000000000000000000000000000000000..6a78f73f53cbf19db657bda92e828c282329d4ab --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkAsciiFormatter.C @@ -0,0 +1,136 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "foamVtkAsciiFormatter.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const char* Foam::foamVtkAsciiFormatter::name_ = "ascii"; + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +inline void Foam::foamVtkAsciiFormatter::next() +{ + if (pos_ == 6) + { + os()<< '\n'; + pos_ = 0; + } + else if (pos_) + { + os()<< ' '; + } + ++pos_; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::foamVtkAsciiFormatter::foamVtkAsciiFormatter(std::ostream& os) +: + foamVtkFormatter(os), + pos_(0) +{} + + +Foam::foamVtkAsciiFormatter::foamVtkAsciiFormatter +( + std::ostream& os, + unsigned precision +) +: + foamVtkFormatter(os), + pos_(0) +{ + os.precision(precision); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::foamVtkAsciiFormatter::~foamVtkAsciiFormatter() +{ + flush(); +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +const char* Foam::foamVtkAsciiFormatter::name() const +{ + return name_; +} + + +const char* Foam::foamVtkAsciiFormatter::encoding() const +{ + return name_; +} + + +void Foam::foamVtkAsciiFormatter::writeSize(const uint64_t) +{/*nop*/} + + +void Foam::foamVtkAsciiFormatter::write(const uint8_t val) +{ + next(); + os()<< int(val); +} + + +void Foam::foamVtkAsciiFormatter::write(const label val) +{ + next(); + os()<< val; +} + + +void Foam::foamVtkAsciiFormatter::write(const float val) +{ + next(); + os()<< val; +} + + +void Foam::foamVtkAsciiFormatter::write(const double val) +{ + next(); + os()<< float(val); +} + + +void Foam::foamVtkAsciiFormatter::flush() +{ + if (pos_) + { + os()<< '\n'; + } + pos_ = 0; +} + + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkAsciiFormatter.H b/src/fileFormats/vtk/format/foamVtkAsciiFormatter.H new file mode 100644 index 0000000000000000000000000000000000000000..009d776f89f1d85cf3cd5335e2feb5cde8695047 --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkAsciiFormatter.H @@ -0,0 +1,120 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + foamVtkAsciiFormatter + +Description + Inline ASCII binary output. + Adds spaces between entries and a newline every 6 items + (for consistency with what VTK itself outputs). + +SourceFiles + foamVtkAsciiFormatter.C + +\*---------------------------------------------------------------------------*/ + +#ifndef foamVtkAsciiFormatter_H +#define foamVtkAsciiFormatter_H + +#include "foamVtkFormatter.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class foamVtkAsciiFormatter Declaration +\*---------------------------------------------------------------------------*/ + +class foamVtkAsciiFormatter +: + public foamVtkFormatter +{ + // Private Data Members + + static const char* name_; + + //- Track the current output position + unsigned short pos_; + + + // Private Member Functions + + //- Advance to next position, adding space or newline as required + inline void next(); + + + //- Disallow default bitwise copy construct + foamVtkAsciiFormatter(const foamVtkAsciiFormatter&) = delete; + + //- Disallow default bitwise assignment + void operator=(const foamVtkAsciiFormatter&) = delete; + + +public: + + // Constructors + + //- Construct and attach to an output stream, use default precision + foamVtkAsciiFormatter(std::ostream&); + + //- Construct and attach to an output stream, use specified precision + foamVtkAsciiFormatter(std::ostream&, unsigned precision); + + + //- Destructor + virtual ~foamVtkAsciiFormatter(); + + + // Member Functions + + //- Name for the XML output type ("ascii") + // The legacy output type is an uppercase version of this. + virtual const char* name() const; + + //- Name for the XML append encoding - unused. + // Currently simply "ASCII", but this should not be relied upon. + virtual const char* encoding() const; + + + //- Write leading size - this is a no-op for ascii output + virtual void writeSize(const uint64_t); + + virtual void write(const uint8_t); + virtual void write(const label); + virtual void write(const float); + virtual void write(const double); + virtual void flush(); +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkBase64Formatter.C b/src/fileFormats/vtk/format/foamVtkBase64Formatter.C new file mode 100644 index 0000000000000000000000000000000000000000..a11d97bd49e573d318700e6e56f66802364daf51 --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkBase64Formatter.C @@ -0,0 +1,120 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "foamVtkBase64Formatter.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const char* Foam::foamVtkBase64Formatter::name_ = "binary"; +const char* Foam::foamVtkBase64Formatter::encoding_ = "base64"; + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +void Foam::foamVtkBase64Formatter::write +( + const char* s, + std::streamsize n +) +{ + base64Layer::write(s, n); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::foamVtkBase64Formatter::foamVtkBase64Formatter(std::ostream& os) +: + foamVtkFormatter(os), + base64Layer(os) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::foamVtkBase64Formatter::~foamVtkBase64Formatter() +{ + flush(); +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +const char* Foam::foamVtkBase64Formatter::name() const +{ + return name_; +} + + +const char* Foam::foamVtkBase64Formatter::encoding() const +{ + return encoding_; +} + + +void Foam::foamVtkBase64Formatter::writeSize(const uint64_t val) +{ + write(reinterpret_cast<const char*>(&val), sizeof(uint64_t)); +} + + +void Foam::foamVtkBase64Formatter::write(const uint8_t val) +{ + base64Layer::add(val); +} + + +void Foam::foamVtkBase64Formatter::write(const label val) +{ + // std::cerr<<"label is:" << sizeof(val) << '\n'; + write(reinterpret_cast<const char*>(&val), sizeof(label)); +} + + +void Foam::foamVtkBase64Formatter::write(const float val) +{ + // std::cerr<<"float is:" << sizeof(val) << '\n'; + write(reinterpret_cast<const char*>(&val), sizeof(float)); +} + + +void Foam::foamVtkBase64Formatter::write(const double val) +{ + // std::cerr<<"write double as float:" << val << '\n'; + float copy(val); + write(copy); +} + + +void Foam::foamVtkBase64Formatter::flush() +{ + if (base64Layer::close()) + { + os().put('\n'); + } +} + + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkBase64Formatter.H b/src/fileFormats/vtk/format/foamVtkBase64Formatter.H new file mode 100644 index 0000000000000000000000000000000000000000..f01bec3d9aa343159749834e47cc0f7ff14e62fe --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkBase64Formatter.H @@ -0,0 +1,116 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + foamVtkBase64Formatter + +Description + Inline base-64 encoded binary output. + Uses an output filter layer to write base-64 encoded content. + +\*---------------------------------------------------------------------------*/ + +#ifndef foamVtkBase64Formatter_H +#define foamVtkBase64Formatter_H + +#include "foamVtkFormatter.H" +#include "base64Layer.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class foamVtkBase64Formatter Declaration +\*---------------------------------------------------------------------------*/ + +class foamVtkBase64Formatter +: + public foamVtkFormatter, + private base64Layer +{ + // Private Data Members + + static const char* name_; + static const char* encoding_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + foamVtkBase64Formatter(const foamVtkBase64Formatter&) = delete; + + //- Disallow default bitwise assignment + void operator=(const foamVtkBase64Formatter&) = delete; + +protected: + + // Protected Member Functions + + //- Write + void write(const char* s, std::streamsize n); + + +public: + + // Constructors + + //- Construct and attach to an output stream + foamVtkBase64Formatter(std::ostream&); + + + //- Destructor + virtual ~foamVtkBase64Formatter(); + + + // Member Functions + + //- Name for the XML output type ("binary") + // The lowercase version of the Legacy output type. + virtual const char* name() const; + + //- Name for the XML append encoding. + virtual const char* encoding() const; + + + //- Write leading size for binary output + virtual void writeSize(const uint64_t); + + virtual void write(const uint8_t); + virtual void write(const label); + virtual void write(const float); + virtual void write(const double); + virtual void flush(); + +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkFormatter.C b/src/fileFormats/vtk/format/foamVtkFormatter.C new file mode 100644 index 0000000000000000000000000000000000000000..b204ad22795410165c657f553ea44b8b63b52cff --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkFormatter.C @@ -0,0 +1,315 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. +\*---------------------------------------------------------------------------*/ + +#include "foamVtkFormatter.H" +#include "foamVtkPTraits.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const char* const Foam::foamVtkFormatter::byteOrder + = Foam::foamVtkPTraits<endian>::typeName; + +const char* const Foam::foamVtkFormatter::headerType = + Foam::foamVtkPTraits<uint64_t>::typeName; + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::foamVtkFormatter::foamVtkFormatter(std::ostream& os) +: + os_(os), + xmlTags_(), + inTag_(false) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::foamVtkFormatter::~foamVtkFormatter() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +void Foam::foamVtkFormatter::indent() +{ + label n = xmlTags_.size() * 2; + while (n--) + { + os_ << ' '; + } +} + + +Foam::foamVtkFormatter& +Foam::foamVtkFormatter::xmlHeader() +{ + if (inTag_) + { + WarningInFunction + << "xml header, but already within a tag!" + << endl; + } + + os_ << "<?xml version='1.0'?>" << nl; + + return *this; +} + + +Foam::foamVtkFormatter& +Foam::foamVtkFormatter::comment(const std::string& text) +{ + if (inTag_) + { + WarningInFunction + << "adding xml comment inside a tag??" + << endl; + } + + indent(); + os_ << "<!-- " << text << " -->" << nl; + + return *this; +} + + +Foam::foamVtkFormatter& +Foam::foamVtkFormatter::openTag(const word& tag) +{ + if (inTag_) + { + WarningInFunction + << "open XML tag '" << tag << "', but already within a tag!" + << endl; + } + + indent(); + os_ << '<' << tag; + + xmlTags_.push(tag); + inTag_ = true; + + return *this; +} + + +Foam::foamVtkFormatter& +Foam::foamVtkFormatter::closeTag(bool isEmpty) +{ + if (!inTag_) + { + WarningInFunction + << "close XML tag, but not within a tag!" + << endl; + } + + if (isEmpty) + { + // eg, <tag ... /> + xmlTags_.pop(); + os_ << " /"; + } + os_ << '>' << nl; + + inTag_ = false; + + return *this; +} + + +Foam::foamVtkFormatter& +Foam::foamVtkFormatter::tag(const word& tag) +{ + openTag(tag); + closeTag(); + + return *this; +} + + + +Foam::foamVtkFormatter& +Foam::foamVtkFormatter::endTag(const word& tag) +{ + const word curr = xmlTags_.pop(); + indent(); + + if (inTag_) + { + WarningInFunction + << "adding XML endTag '" << curr + << "' but already in another tag!" + << endl; + } + + // verify inTag_ + if (!tag.empty() && tag != curr) + { + WarningInFunction + << "expected to end xml-tag '" << tag + << "' but found '" << curr << "' instead" + << endl; + } + + os_ << "</" << curr << '>' << nl; + + inTag_ = false; + + return *this; +} + + + +Foam::foamVtkFormatter& +Foam::foamVtkFormatter::xmlAttr +( + const word& k, + const std::string& v, + const char quote +) +{ + if (!inTag_) + { + WarningInFunction + << "xml attribute '" << k << "' but not within a tag!" + << endl; + } + + os_ << ' ' << k << '=' << quote << v.c_str() << quote; + + return *this; +} + + +Foam::foamVtkFormatter& +Foam::foamVtkFormatter::xmlAttr +( + const word& k, + const label v, + const char quote +) +{ + if (!inTag_) + { + WarningInFunction + << "xml attribute '" << k << "' but not within a tag!" + << endl; + } + + os_ << ' ' << k << '=' << quote << v << quote; + + return *this; +} + + +Foam::foamVtkFormatter& +Foam::foamVtkFormatter::xmlAttr +( + const word& k, + const uint64_t v, + const char quote +) +{ + if (!inTag_) + { + WarningInFunction + << "xml attribute '" << k << "' but not within a tag!" + << endl; + } + + os_ << ' ' << k << '=' << quote << v << quote; + + return *this; +} + + +Foam::foamVtkFormatter& +Foam::foamVtkFormatter::xmlAttr +( + const word& k, + const scalar v, + const char quote +) +{ + if (!inTag_) + { + WarningInFunction + << "xml attribute '" << k << "' but not within a tag!" + << endl; + } + + os_ << ' ' << k << '=' << quote << v << quote; + + return *this; +} + + +// * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * // + +Foam::foamVtkFormatter& +Foam::foamVtkFormatter::operator() +( + const word& k, + const std::string& v +) +{ + return xmlAttr(k, v); +} + + +Foam::foamVtkFormatter& +Foam::foamVtkFormatter::operator() +( + const word& k, + const label v +) +{ + return xmlAttr(k, v); +} + + +Foam::foamVtkFormatter& +Foam::foamVtkFormatter::operator() +( + const word& k, + const uint64_t v +) +{ + return xmlAttr(k, v); +} + + +Foam::foamVtkFormatter& +Foam::foamVtkFormatter::operator() +( + const word& k, + const scalar v +) +{ + return xmlAttr(k, v); +} + + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkFormatter.H b/src/fileFormats/vtk/format/foamVtkFormatter.H new file mode 100644 index 0000000000000000000000000000000000000000..4fe0cb997773461de2a049b087af731126b359ee --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkFormatter.H @@ -0,0 +1,233 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + foamVtkFormatter + +Description + Abstract class for a VTK output stream formatter. + + Includes very simple support for writing XML tags. + +SourceFiles + foamVtkFormatter.C + +\*---------------------------------------------------------------------------*/ + +#ifndef foamVtkFormatter_H +#define foamVtkFormatter_H + +#include "int.H" +#include "uint64.H" +#include "label.H" +#include "word.H" +#include "UList.H" +#include "LIFOStack.H" +#include "foamVtkPTraits.H" + +#include <iostream> + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class foamVtkFormatter Declaration +\*---------------------------------------------------------------------------*/ + +class foamVtkFormatter +{ + // Private Data + + //- The output stream for the formatter + std::ostream& os_; + + //- Stack of current XML tags + LIFOStack<word> xmlTags_; + + //- Tag open/closed/ended state + mutable bool inTag_; + + +protected: + + // Protected Member Functions + + //- Construct and attach to an output stream + foamVtkFormatter(std::ostream& os); + +public: + + // Static Data + + //- VTK name for the 'byte_order' attribute + static const char* const byteOrder; + + //- VTK name for the 'header_type' attribute (UInt64) + static const char* const headerType; + + + //- Destructor + virtual ~foamVtkFormatter(); + + + // Member Functions + + //- Access to the underlying output stream + inline std::ostream& os() + { + return os_; + } + + + //- Name for the XML output type. + // Possibly the lowercase version of the Legacy output type + virtual const char* name() const = 0; + + //- Name for the XML append encoding + virtual const char* encoding() const = 0; + + + //- Write leading size for binary output + virtual void writeSize(const uint64_t) = 0; + + virtual void write(const uint8_t) = 0; + virtual void write(const label) = 0; + virtual void write(const float) = 0; + virtual void write(const double) = 0; + virtual void flush() = 0; + + + // Member Functions + + //- Indent according to the currently nested XML tags + void indent(); + + //- Write XML header + foamVtkFormatter& xmlHeader(); + + //- Write XML comment (at the current indentation level) + foamVtkFormatter& comment(const std::string&); + + + //- Open XML tag + foamVtkFormatter& openTag(const word& tag); + + //- Close XML tag, optional as an empty container. + // Always adds a trailing newline. + foamVtkFormatter& closeTag(bool isEmpty = false); + + //- End XML tag, optional with sanity check + // Always adds a trailing newline. + foamVtkFormatter& endTag(const word& tag = word::null); + + //- Write XML tag without any attributes. Combines openTag/closeTag. + foamVtkFormatter& tag(const word& tag); + + + //- Open "DataArray" XML tag + template<class Type, int nComp=0> + foamVtkFormatter& openDataArray(const word& dataName); + + + //- Insert a single "PDataArray" XML entry tag. + // For some entries, the name is optional. + template<class Type, int nComp=0> + foamVtkFormatter& PDataArray(const word& dataName); + + + //- End "DataArray" XML tag + foamVtkFormatter& endDataArray() + { + return endTag("DataArray"); + } + + + + //- Write XML attribute + foamVtkFormatter& xmlAttr + ( + const word&, + const std::string&, + const char quote='\'' + ); + + //- Write XML attribute + foamVtkFormatter& xmlAttr + ( + const word&, + const label, + const char quote='\'' + ); + + //- Write XML attribute + foamVtkFormatter& xmlAttr + ( + const word&, + const uint64_t, + const char quote='\'' + ); + + //- Write XML attribute + foamVtkFormatter& xmlAttr + ( + const word&, + const scalar, + const char quote='\'' + ); + + + + // Member Operators + + //- Write XML attribute + foamVtkFormatter& operator()(const word&, const std::string&); + + //- Write XML attribute + foamVtkFormatter& operator()(const word&, const label); + + //- Write XML attribute + foamVtkFormatter& operator()(const word&, const uint64_t); + + //- Write XML attribute + foamVtkFormatter& operator()(const word&, const scalar); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "foamVtkFormatterTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkFormatterTemplates.C b/src/fileFormats/vtk/format/foamVtkFormatterTemplates.C new file mode 100644 index 0000000000000000000000000000000000000000..6e0830e2b1fab52f022a8ef6cfd81dbf15581d03 --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkFormatterTemplates.C @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. +\*---------------------------------------------------------------------------*/ + +#include "foamVtkPTraits.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template<class Type, int nComp> +Foam::foamVtkFormatter& Foam::foamVtkFormatter::openDataArray +( + const word& dataName +) +{ + openTag("DataArray"); + xmlAttr("type", foamVtkPTraits<Type>::typeName); + xmlAttr("Name", dataName); + if (nComp > 1) + { + xmlAttr("NumberOfComponents", nComp); + } + xmlAttr("format", name()); + + return *this; +} + + +template<class Type, int nComp> +Foam::foamVtkFormatter& Foam::foamVtkFormatter::PDataArray +( + const word& dataName +) +{ + openTag("PDataArray"); + xmlAttr("type", foamVtkPTraits<Type>::typeName); + if (dataName.size()) + { + xmlAttr("Name", dataName); + } + if (nComp > 1) + { + xmlAttr("NumberOfComponents", nComp); + } + + closeTag(true); + + return *this; +} + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkLegacyFormatter.C b/src/fileFormats/vtk/format/foamVtkLegacyFormatter.C new file mode 100644 index 0000000000000000000000000000000000000000..177249b306a84daf44531ffb39668beb836b9a0e --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkLegacyFormatter.C @@ -0,0 +1,139 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "foamVtkLegacyFormatter.H" +#include "endian.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const char* Foam::foamVtkLegacyFormatter::name_ = "BINARY"; + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +void Foam::foamVtkLegacyFormatter::write +( + const char* s, + std::streamsize n +) +{ + os().write(s, n); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::foamVtkLegacyFormatter::foamVtkLegacyFormatter(std::ostream& os) +: + foamVtkFormatter(os) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::foamVtkLegacyFormatter::~foamVtkLegacyFormatter() +{} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +const char* Foam::foamVtkLegacyFormatter::name() const +{ + return name_; +} + + +const char* Foam::foamVtkLegacyFormatter::encoding() const +{ + return name_; +} + + +void Foam::foamVtkLegacyFormatter::writeSize(const uint64_t) +{} + + +void Foam::foamVtkLegacyFormatter::write(const uint8_t val) +{ + // Can only handle integers + int copy(val); + write(copy); +} + + +void Foam::foamVtkLegacyFormatter::write(const label val) +{ + // std::cerr<<"label is:" << sizeof(val) << '\n'; + + // Not entirely correct: the legacy format only supports 32-bit integers. + // Either limit size for 64-bit label, or simply do not support for 64-bit. +#ifdef WM_LITTLE_ENDIAN +# if WM_LABEL_SIZE == 32 + uint32_t swapped = endian::swap32(val); + write(reinterpret_cast<const char*>(&swapped), sizeof(uint32_t)); +# elif WM_LABEL_SIZE == 64 + uint64_t swapped = endian::swap64(val); + write(reinterpret_cast<const char*>(&swapped), sizeof(uint64_t)); +#endif +#else + write(reinterpret_cast<const char*>(&val), sizeof(label)); +#endif +} + + +void Foam::foamVtkLegacyFormatter::write(const float val) +{ + // std::cerr<<"float is:" << sizeof(val) << '\n'; + +#ifdef WM_LITTLE_ENDIAN + // De-reference in two stages to avoid the warning + // dereferencing type-punned pointer will break strict-aliasing rules + // [-Wstrict-aliasing] + + const uint32_t* ptr = reinterpret_cast<const uint32_t*>(&val); + uint32_t swapped = endian::swap32(*ptr); + write(reinterpret_cast<const char*>(&swapped), sizeof(uint32_t)); +#else + write(reinterpret_cast<const char*>(&val), sizeof(float)); +#endif +} + + +void Foam::foamVtkLegacyFormatter::write(const double val) +{ + // Legacy cannot support Float64 anyhow. + // std::cerr<<"write double as float:" << val << '\n'; + float copy(val); + write(copy); +} + + +void Foam::foamVtkLegacyFormatter::flush() +{ + os()<< '\n'; +} + + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkLegacyFormatter.H b/src/fileFormats/vtk/format/foamVtkLegacyFormatter.H new file mode 100644 index 0000000000000000000000000000000000000000..fe2395add4d143085d854c987d040b6ed051caaa --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkLegacyFormatter.H @@ -0,0 +1,119 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + foamVtkLegacyFormatter + +Description + Binary output for the VTK legacy format, always written as big-endian. + + The legacy files are always written as big endian. + Since integers in the legacy format are limited to 32-bit, + this format should not be used for OpenFOAM with 64-bit label sizes. + +SourceFiles + foamVtkLegacyFormatter.C + +\*---------------------------------------------------------------------------*/ + +#ifndef foamVtkLegacyFormatter_H +#define foamVtkLegacyFormatter_H + +#include "foamVtkFormatter.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class foamVtkLegacyFormatter Declaration +\*---------------------------------------------------------------------------*/ + +class foamVtkLegacyFormatter +: + public foamVtkFormatter +{ + // Private Data Members + + static const char* name_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + foamVtkLegacyFormatter(const foamVtkLegacyFormatter&) = delete; + + //- Disallow default bitwise assignment + void operator=(const foamVtkLegacyFormatter&) = delete; + + +protected: + + // Protected Member Functions + + //- Write + void write(const char* s, std::streamsize n); + + +public: + + // Constructors + + //- Construct and attach to an output stream + foamVtkLegacyFormatter(std::ostream&); + + + //- Destructor + virtual ~foamVtkLegacyFormatter(); + + + // Member Functions + + //- Name for the Legacy output type ("BINARY") + virtual const char* name() const; + + //- Name for the XML append encoding (unused) + // Currently simply "BINARY", but this should not be relied upon. + virtual const char* encoding() const; + + + //- Write leading size - a no-op for legacy binary output + virtual void writeSize(const uint64_t); + + virtual void write(const uint8_t); + virtual void write(const label); + virtual void write(const float); + virtual void write(const double); + virtual void flush(); +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkOutputOptions.C b/src/fileFormats/vtk/format/foamVtkOutputOptions.C new file mode 100644 index 0000000000000000000000000000000000000000..816cbe90b906762658ce94dac8db39f39c9d7e86 --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkOutputOptions.C @@ -0,0 +1,240 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "foamVtkOutputOptions.H" + +#include "foamVtkAppendBase64Formatter.H" +#include "foamVtkAppendRawFormatter.H" +#include "foamVtkAsciiFormatter.H" +#include "foamVtkBase64Formatter.H" +#include "foamVtkLegacyFormatter.H" + +#include "IOstream.H" + + +// * * * * * * * * * * * * * * Constructor * * * * * * * * * * * * * // + +Foam::foamVtkOutputOptions::foamVtkOutputOptions() +: + type_(ASCII), + style_(NONE), + precision_(IOstream::defaultPrecision()) +{} + + +// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * // + +Foam::autoPtr<Foam::foamVtkFormatter> +Foam::foamVtkOutputOptions::newFormatter +( + std::ostream& os +) const +{ + switch (type_) + { + case (LEGACY | BINARY): + return autoPtr<foamVtkFormatter> + ( + new foamVtkLegacyFormatter(os) + ); + + case BASE64: // xml insitu + return autoPtr<foamVtkFormatter> + ( + new foamVtkBase64Formatter(os) + ); + + case (APPEND | BASE64): + return autoPtr<foamVtkFormatter> + ( + new foamVtkAppendBase64Formatter(os) + ); + + case (APPEND | BINARY): + return autoPtr<foamVtkFormatter> + ( + new foamVtkAppendRawFormatter(os) + ); + + default: // ASCII (legacy or xml) must always work + return autoPtr<foamVtkFormatter> + ( + new foamVtkAsciiFormatter(os, precision_) + ); + } +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +void Foam::foamVtkOutputOptions::ascii(bool b) +{ + if (b) + { + // Force ASCII: + + if (type_ & APPEND) + { + // Append: ascii = base64 (vs raw binary) + type_ = (APPEND | BASE64); + } + else if (type_ & LEGACY) + { + // Legacy: ascii = ascii + type_ = (LEGACY | ASCII); + } + else + { + // XML: ascii = ascii + type_ = ASCII; + } + } + else + { + // Non-ASCII: + + if (type_ & APPEND) + { + // Append: binary == (raw) binary + type_ = APPEND | BINARY; + } + else if (type_ & LEGACY) + { + // Legacy: binary = binary + type_ = LEGACY | BINARY; + } + else + { + // XML: binary == (inline) binary == base64 + type_ = BASE64; + } + } +} + + +void Foam::foamVtkOutputOptions::append(bool b) +{ + if (b) + { + if (!(type_ & APPEND)) + { + // XML: base64 -> raw binary, ascii -> base64 + // Legacy: binary -> raw binary, ascii -> base64 + type_ = APPEND | ((type_ & (BASE64 | BINARY)) ? BINARY : BASE64); + } + } + else if (type_ & APPEND) + { + // Only revert back to inline XML base64 versions + // ASCII needs another step. + + type_ = BASE64; + } +} + + +void Foam::foamVtkOutputOptions::legacy(bool b) +{ + if (b) + { + if (type_ & APPEND) + { + // Append: base64 -> ascii, binary -> binary + type_ = (LEGACY | ((type_ & BINARY) ? BINARY : ASCII)); + } + else if (type_ & LEGACY) + { + // no-op + } + else + { + // XML: ascii -> ascii, base64 -> binary + type_ = (LEGACY | ((type_ & BASE64) ? BINARY : ASCII)); + } + } + else if (type_ & LEGACY) + { + // Legacy: ascii -> xml ascii, binary -> xml base64 + type_ = (type_ & BINARY) ? BASE64 : ASCII; + } +} + + +void Foam::foamVtkOutputOptions::precision(unsigned val) const +{ + precision_ = val; +} + + +Foam::Ostream& +Foam::foamVtkOutputOptions::info(Ostream& os) const +{ + os << "type: " << type_; + + switch (type_) + { + case (LEGACY | ASCII): + os << " legacy ascii"; + break; + + case (LEGACY | BINARY): + os << " legacy binary"; + break; + + case BASE64: + os << " xml insitu base64"; + break; + + case (APPEND | BASE64): + os << " xml-append base64"; + break; + + case (APPEND | BINARY): + os << " xml-append binary"; + break; + + case ASCII: + os << " xml insitu ascii"; + break; + + case BINARY: + os << " xml insitu binary - WRONG"; + break; + + default: + os << " unknown"; + break; + } + + if (legacy()) os << " legacy"; + if (xml()) os << " xml"; + if (append()) os << " append"; + if (ascii()) os << " ascii"; + + return os; +} + + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkOutputOptions.H b/src/fileFormats/vtk/format/foamVtkOutputOptions.H new file mode 100644 index 0000000000000000000000000000000000000000..43a3ee0918e89350419ab3fda802fb18fb8c3acc --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkOutputOptions.H @@ -0,0 +1,156 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + foamVtkOutputOptions + +Description + Encapsulate combinations of output format options. + +SourceFiles + foamVtkOutputOptions.C + +\*---------------------------------------------------------------------------*/ + +#ifndef foamVtkOutputOptions_H +#define foamVtkOutputOptions_H + +#include "autoPtr.H" +#include "foamVtkFormatter.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +class Ostream; + +/*---------------------------------------------------------------------------*\ + Class foamVtkOutputOptions Declaration +\*---------------------------------------------------------------------------*/ + +class foamVtkOutputOptions +{ + // Private data + + //- The supported output/format types + enum foamVtkOptionTypes + { + ASCII = 0x0000, //!< ASCII formatting for data + BINARY = 0x0001, //!< Raw binary formatting for data + BASE64 = 0x0002, //!< Base64 encoding for data + LEGACY = 0x0100, //!< Legacy vtk file format + APPEND = 0x0200 //!< XML append format + }; + + //- The output style tuning + enum foamVtkStyleOptions + { + NONE = 0x0000, //!< Normal + HEADER = 0x0001 //!< Emit xml header + }; + + + //- The output format type + unsigned short type_; + + //- The output style tuning + unsigned short style_; + + + //- ASCII write precision + mutable unsigned precision_; + + +public: + + // Constructors + + //- Construct null - XML insitu ASCII format with default precision + foamVtkOutputOptions(); + + + // Selectors + + //- Return new data formatter based on the writer options + autoPtr<foamVtkFormatter> newFormatter(std::ostream&) const; + + + // Member Functions + + // Access + + //- True if writer uses legacy file format + inline bool legacy() const; + + //- True if writer uses XML file format (non-legacy) + inline bool xml() const; + + //- True if output format uses an append mode + inline bool append() const; + + //- True if output format does not use an append mode + inline bool insitu() const; + + //- True if output format is ASCII + inline bool ascii() const; + + + // Edit + + //- Toggle ASCII mode on/off. + // In append mode, this switches between base64 and raw binary. + // In XML mode, this switches between ASCII and base64. + // In legacy mode, this switches between ASCII and binary. + void ascii(bool); + + //- Toggle append mode on/off. + void append(bool); + + //- Toggle legacy mode on/off. + void legacy(bool); + + //- Set the write precision to be used for new ASCII formatters + void precision(unsigned val) const; + + + // Other + + //- Report information about the options + Ostream& info(Ostream&) const; + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "foamVtkOutputOptionsI.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/format/foamVtkOutputOptionsI.H b/src/fileFormats/vtk/format/foamVtkOutputOptionsI.H new file mode 100644 index 0000000000000000000000000000000000000000..0205f2f98ec87c5dba88223afb604310eb13407b --- /dev/null +++ b/src/fileFormats/vtk/format/foamVtkOutputOptionsI.H @@ -0,0 +1,56 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +inline bool Foam::foamVtkOutputOptions::legacy() const +{ + return (type_ & LEGACY); +} + + +inline bool Foam::foamVtkOutputOptions::xml() const +{ + return !legacy(); +} + + +inline bool Foam::foamVtkOutputOptions::append() const +{ + return (type_ & APPEND); +} + + +inline bool Foam::foamVtkOutputOptions::insitu() const +{ + return !(type_ & APPEND); +} + + +inline bool Foam::foamVtkOutputOptions::ascii() const +{ + return !(type_ & (BINARY | BASE64)); +} + + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/vtkUnstructuredReader.C b/src/fileFormats/vtk/read/vtkUnstructuredReader.C similarity index 98% rename from src/fileFormats/vtk/vtkUnstructuredReader.C rename to src/fileFormats/vtk/read/vtkUnstructuredReader.C index 3edf53ee3d813f550a473f0da708ac73d0eba925..d834f4d5ebab183b171a2053f929833d1cec1106 100644 --- a/src/fileFormats/vtk/vtkUnstructuredReader.C +++ b/src/fileFormats/vtk/read/vtkUnstructuredReader.C @@ -136,7 +136,7 @@ void Foam::vtkUnstructuredReader::extractCells { switch (cellTypes[i]) { - case VTK_VERTEX: + case foamVtkCore::VTK_VERTEX: { warnUnhandledType(inFile, cellTypes[i], warningGiven); label nRead = cellVertData[dataIndex++]; @@ -152,7 +152,7 @@ void Foam::vtkUnstructuredReader::extractCells } break; - case VTK_POLY_VERTEX: + case foamVtkCore::VTK_POLY_VERTEX: { warnUnhandledType(inFile, cellTypes[i], warningGiven); label nRead = cellVertData[dataIndex++]; @@ -160,7 +160,7 @@ void Foam::vtkUnstructuredReader::extractCells } break; - case VTK_LINE: + case foamVtkCore::VTK_LINE: { //warnUnhandledType(inFile, cellTypes[i], warningGiven); label nRead = cellVertData[dataIndex++]; @@ -180,7 +180,7 @@ void Foam::vtkUnstructuredReader::extractCells } break; - case VTK_POLY_LINE: + case foamVtkCore::VTK_POLY_LINE: { //warnUnhandledType(inFile, cellTypes[i], warningGiven); label nRead = cellVertData[dataIndex++]; @@ -194,7 +194,7 @@ void Foam::vtkUnstructuredReader::extractCells } break; - case VTK_TRIANGLE: + case foamVtkCore::VTK_TRIANGLE: { faceMap_[facei] = i; face& f = faces_[facei++]; @@ -214,7 +214,7 @@ void Foam::vtkUnstructuredReader::extractCells } break; - case VTK_QUAD: + case foamVtkCore::VTK_QUAD: { faceMap_[facei] = i; face& f = faces_[facei++]; @@ -235,7 +235,7 @@ void Foam::vtkUnstructuredReader::extractCells } break; - case VTK_POLYGON: + case foamVtkCore::VTK_POLYGON: { faceMap_[facei] = i; face& f = faces_[facei++]; @@ -248,7 +248,7 @@ void Foam::vtkUnstructuredReader::extractCells } break; - case VTK_TETRA: + case foamVtkCore::VTK_TETRA: { label nRead = cellVertData[dataIndex++]; if (nRead != 4) @@ -268,7 +268,7 @@ void Foam::vtkUnstructuredReader::extractCells } break; - case VTK_PYRAMID: + case foamVtkCore::VTK_PYRAMID: { label nRead = cellVertData[dataIndex++]; if (nRead != 5) @@ -289,7 +289,7 @@ void Foam::vtkUnstructuredReader::extractCells } break; - case VTK_WEDGE: + case foamVtkCore::VTK_WEDGE: { label nRead = cellVertData[dataIndex++]; if (nRead != 6) @@ -311,7 +311,7 @@ void Foam::vtkUnstructuredReader::extractCells } break; - case VTK_HEXAHEDRON: + case foamVtkCore::VTK_HEXAHEDRON: { label nRead = cellVertData[dataIndex++]; if (nRead != 8) diff --git a/src/fileFormats/vtk/vtkUnstructuredReader.H b/src/fileFormats/vtk/read/vtkUnstructuredReader.H similarity index 90% rename from src/fileFormats/vtk/vtkUnstructuredReader.H rename to src/fileFormats/vtk/read/vtkUnstructuredReader.H index db2391bc3bc92705af4461eeff8b6ad025783032..77bd71b4aac8f6ebcbaf9b90e1e1023871bae610 100644 --- a/src/fileFormats/vtk/vtkUnstructuredReader.H +++ b/src/fileFormats/vtk/read/vtkUnstructuredReader.H @@ -25,8 +25,8 @@ Class Foam::vtkUnstructuredReader Description - Reader for vtk unstructured_grid legacy files. Supports single CELLS, POINTS - etc. entry only. + Reader for vtk UNSTRUCTURED_GRID legacy files. + Supports single CELLS, POINTS etc. entry only. - all integer types (int, unsigned_int, long etc.) become Foam::label - all real types (float, double) become Foam::scalar @@ -47,6 +47,7 @@ SourceFiles #ifndef vtkUnstructuredReader_H #define vtkUnstructuredReader_H +#include "foamVtkCore.H" #include "objectRegistry.H" #include "cellShapeList.H" #include "HashSet.H" @@ -62,6 +63,8 @@ namespace Foam \*---------------------------------------------------------------------------*/ class vtkUnstructuredReader +: + public fileFormats::foamVtkCore { public: @@ -108,29 +111,6 @@ public: static const NamedEnum<parseMode, 5> parseModeNames; - //- Enumeration defining the cell types - enum vtkTypes - { - VTK_EMPTY_CELL = 0, - VTK_VERTEX = 1, - VTK_POLY_VERTEX = 2, - VTK_LINE = 3, - VTK_POLY_LINE = 4, - VTK_TRIANGLE = 5, - VTK_TRIANGLE_STRIP = 6, - VTK_POLYGON = 7, - VTK_PIXEL = 8, - VTK_QUAD = 9, - VTK_TETRA = 10, - VTK_VOXEL = 11, - VTK_HEXAHEDRON = 12, - VTK_WEDGE = 13, - VTK_PYRAMID = 14, - VTK_PENTAGONAL_PRISM = 15, - VTK_HEXAGONAL_PRISM = 16, - }; - - private: //- Header diff --git a/src/fileFormats/vtk/vtkUnstructuredReaderTemplates.C b/src/fileFormats/vtk/read/vtkUnstructuredReaderTemplates.C similarity index 98% rename from src/fileFormats/vtk/vtkUnstructuredReaderTemplates.C rename to src/fileFormats/vtk/read/vtkUnstructuredReaderTemplates.C index eb1e5f5273eeea792e32ee14aac739ade81a8026..86f6f6d89544c0a8f28e3f14aee6fe20ee127287 100644 --- a/src/fileFormats/vtk/vtkUnstructuredReaderTemplates.C +++ b/src/fileFormats/vtk/read/vtkUnstructuredReaderTemplates.C @@ -56,7 +56,7 @@ void Foam::vtkUnstructuredReader::printFieldStats { wordList fieldNames(obj.names(Type::typeName)); - if (fieldNames.size() > 0) + if (fieldNames.size()) { Info<< "Read " << fieldNames.size() << " " << Type::typeName << " fields:" << endl; diff --git a/src/fileFormats/vtk/type/foamVtkPTraits.C b/src/fileFormats/vtk/type/foamVtkPTraits.C new file mode 100644 index 0000000000000000000000000000000000000000..91bf1f3a33b647663c9077245b8252efa4d0c76a --- /dev/null +++ b/src/fileFormats/vtk/type/foamVtkPTraits.C @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "foamVtkPTraits.H" +#include "endian.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +template<> +const char* const +Foam::foamVtkPTraits<uint8_t>::typeName = "UInt8"; + +template<> +const char * const +Foam::foamVtkPTraits<int32_t>::typeName = "Int32"; + +template<> +const char * const +Foam::foamVtkPTraits<uint32_t>::typeName = "UInt32"; + +template<> +const char * const +Foam::foamVtkPTraits<int64_t>::typeName = "Int64"; + +template<> +const char * const +Foam::foamVtkPTraits<uint64_t>::typeName = "UInt64"; + +template<> +const char * const +Foam::foamVtkPTraits<float>::typeName = "Float32"; + +template<> +const char * const +Foam::foamVtkPTraits<double>::typeName = "Float64"; + +#ifdef WM_LITTLE_ENDIAN +template<> +const char* const +Foam::foamVtkPTraits<::Foam::endian>::typeName = "LittleEndian"; +#else +template<> +const char* const +Foam::foamVtkPTraits<::Foam::endian>::typeName = "BigEndian"; +#endif + + +// ************************************************************************* // diff --git a/src/fileFormats/vtk/type/foamVtkPTraits.H b/src/fileFormats/vtk/type/foamVtkPTraits.H new file mode 100644 index 0000000000000000000000000000000000000000..ea95c0820d1f61f8190336f0c7dd092013ffd98d --- /dev/null +++ b/src/fileFormats/vtk/type/foamVtkPTraits.H @@ -0,0 +1,93 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::foamVtkPTraits + +Description + Names for VTK primitive types. + +\*---------------------------------------------------------------------------*/ + +#ifndef foamVtkPTraits_H +#define foamVtkPTraits_H + +#include <cstdint> + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declarations +class endian; + +/*---------------------------------------------------------------------------*\ + Class foamVtkPTraits Declaration +\*---------------------------------------------------------------------------*/ + +template<class PrimitiveType> +class foamVtkPTraits +{ +public: + + // Static data members + + static const char* const typeName; +}; + + +template<> +const char* const foamVtkPTraits<uint8_t>::typeName; // = UInt8 + +template<> +const char* const foamVtkPTraits<int32_t>::typeName; // = Int32 + +template<> +const char* const foamVtkPTraits<int32_t>::typeName; // = UInt32 + +template<> +const char* const foamVtkPTraits<int32_t>::typeName; // = Int64 + +template<> +const char* const foamVtkPTraits<int64_t>::typeName; // = UInt64 + +template<> +const char* const foamVtkPTraits<float>::typeName; // = Float32 + +template<> +const char* const foamVtkPTraits<double>::typeName; // = Float64 + +template<> +const char* const foamVtkPTraits<::Foam::endian>::typeName; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/surfMesh/Make/files b/src/surfMesh/Make/files index 5e19af861366c32dac7299078654198d27636264..f7beae2f7c0dcd154712c4ad53c80ff23b53d95c 100644 --- a/src/surfMesh/Make/files +++ b/src/surfMesh/Make/files @@ -24,6 +24,7 @@ $(surfaceFormats)/surfaceFormatsCore.C $(surfaceFormats)/ac3d/AC3DsurfaceFormatCore.C $(surfaceFormats)/ac3d/AC3DsurfaceFormatRunTime.C +$(surfaceFormats)/fire/FLMAsurfaceFormatRunTime.C $(surfaceFormats)/gts/GTSsurfaceFormatRunTime.C $(surfaceFormats)/nas/NASsurfaceFormatRunTime.C $(surfaceFormats)/obj/OBJsurfaceFormatRunTime.C diff --git a/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.C b/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.C new file mode 100644 index 0000000000000000000000000000000000000000..4cbfb60d561c486b225e6d90d819cc72451bb768 --- /dev/null +++ b/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.C @@ -0,0 +1,390 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "FLMAsurfaceFormat.H" + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +//! \cond fileScope +//- Output newline in ascii mode, no-op in binary mode +inline static void newline(Foam::OSstream& os) +{ + if (os.format() == Foam::IOstream::ASCII) + { + os << Foam::endl; + } +} + + +template<class Face> +inline static int countFaces(const Face& f) +{ + int n = (f.size() - 2); // number triangles can be determined directly + return n == 2 ? 1 : n; // quads don't need triangulation +} + +//! \endcond + + +template<class Face> +inline void Foam::fileFormats::FLMAsurfaceFormat<Face>::writeShell +( + OSstream& os, + const Face& f +) +{ + if (os.format() == IOstream::BINARY) + { + if (f.size() == 3 || f.size() == 4) + { + putFireLabel(os, f.size()); + forAll(f, fp) + { + putFireLabel(os, f[fp]); + } + } + else + { + // simple triangulation about f[0]. + // better triangulation should have been done before + for (label fp1 = 1; fp1 < f.size() - 1; ++fp1) + { + label fp2 = f.fcIndex(fp1); + + putFireLabel(os, 3); + putFireLabel(os, f[0]); + putFireLabel(os, f[fp1]); + putFireLabel(os, f[fp2]); + } + } + } + else + { + // ASCII + if (f.size() == 3 || f.size() == 4) + { + os << ' ' << f.size(); + forAll(f, fp) + { + os << ' ' << f[fp]; + } + os << nl; + } + else + { + for (label fp1 = 1; fp1 < f.size() - 1; ++fp1) + { + label fp2 = f.fcIndex(fp1); + os << ' ' << 3 << ' ' + << f[0] << ' ' << f[fp1] << ' ' << f[fp2] + << nl; + } + } + } +} + + +template<class Face> +inline void Foam::fileFormats::FLMAsurfaceFormat<Face>::writeType +( + OSstream& os, + const Face& f +) +{ + if (os.format() == IOstream::BINARY) + { + if (f.size() == 4) + { + putFireLabel(os, fireQuad); + } + else + { + const label n = countFaces(f); + for (label i=0; i < n; ++i) + { + putFireLabel(os, fireTri); + } + } + } + else + { + // ASCII + if (f.size() == 4) + { + os << ' ' << fireQuad; + } + else + { + const label n = countFaces(f); + for (label i=0; i < n; ++i) + { + os << ' ' << fireTri; + } + } + } +} + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +template<class Face> +void Foam::fileFormats::FLMAsurfaceFormat<Face>::write +( + OSstream& os, + const MeshedSurfaceProxy<Face>& surf +) +{ + if (!os.good()) + { + FatalErrorIn + ( + "fileFormats::FLMAsurfaceFormat::write" + "(OSstream&, const MeshedSurfaceProxy<Face>&)" + ) + << "bad output state " + << exit(FatalError); + } + + const pointField& pointLst = surf.points(); + const List<Face>& faceLst = surf.surfFaces(); + const List<label>& faceMap = surf.faceMap(); + + // for no zones, suppress the group name + const List<surfZone>& zones = + ( + surf.surfZones().empty() + ? surfaceFormatsCore::oneZone(faceLst, word::null) + : surf.surfZones() + ); + + const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1); + + + // determine the number of faces by counting the + // tri/quads/triangulated) faces in each zone + label nFaces = 0; + List<label> zoneCount(zones.size()); + + { + label faceIndex = 0; + forAll(zones, zoneI) + { + const surfZone& zone = zones[zoneI]; + + label selCount = 0; + if (useFaceMap) + { + forAll(zone, localFaceI) + { + selCount += countFaces(faceLst[faceMap[faceIndex++]]); + } + } + else + { + forAll(zone, localFaceI) + { + selCount += countFaces(faceLst[faceIndex++]); + } + } + + zoneCount[zoneI] = selCount; + nFaces += selCount; + } + } + + + // Points + // ~~~~~~ + + // Set the precision of the points data to 10 + os.precision(10); + + Info<< "points: " << pointLst.size() << endl; + putFireLabel(os, pointLst.size()); + newline(os); + + forAll(pointLst, ptI) + { + // scaling is normally 1 + putFirePoint(os, pointLst[ptI]); + } + newline(os); // readability + + // Faces indices + { + Info<< "faces: " << nFaces << endl; + putFireLabel(os, nFaces); + newline(os); + + label faceIndex = 0; + forAll(zones, zoneI) + { + const surfZone& zone = zones[zoneI]; + + if (useFaceMap) + { + forAll(zone, localFaceI) + { + writeShell(os, faceLst[faceMap[faceIndex++]]); + } + } + else + { + forAll(zone, localFaceI) + { + writeShell(os, faceLst[faceIndex++]); + } + } + } + newline(os); + newline(os); // readability + } + + + // Face types + { + putFireLabel(os, nFaces); + newline(os); + + label faceIndex = 0; + forAll(zones, zoneI) + { + const surfZone& zone = zones[zoneI]; + + if (useFaceMap) + { + forAll(zone, localFaceI) + { + writeType(os, faceLst[faceMap[faceIndex++]]); + } + } + else + { + forAll(zone, localFaceI) + { + writeType(os, faceLst[faceIndex++]); + } + } + } + newline(os); + newline(os); // readability + } + + // Selections (cell) + { + putFireLabel(os, zones.size()); + newline(os); + + label faceIndex = 0; + forAll(zones, zoneI) + { + const surfZone& zone = zones[zoneI]; + const label selCount = zoneCount[zoneI]; + + putFireString(os, zone.name()); + putFireLabel(os, static_cast<int>(FIRECore::cellSelection)); + newline(os); + + putFireLabels(os, selCount, faceIndex); + faceIndex += selCount; + + newline(os); // readability + } + } +} + + +template<class Face> +void Foam::fileFormats::FLMAsurfaceFormat<Face>::write +( + const fileName& filename, + const MeshedSurfaceProxy<Face>& surf, + bool compress +) +{ + autoPtr<OFstream> osPtr + ( + compress + ? new OFstream + ( + filename, + IOstream::ASCII, + IOstream::currentVersion, + IOstream::COMPRESSED + ) + : new OFstream(filename) + ); + + if (osPtr->good()) + { + FLMAsurfaceFormat<Face>::write(osPtr(), surf); + osPtr.clear(); // implicitly close the file + + if (compress) + { + // rename .flmaz.gz -> .flmaz + // The '.gz' is automatically added by OFstream in compression mode + Foam::mv(filename + ".gz", filename); + } + } + else + { + FatalErrorIn + ( + "fileFormats::FLMAsurfaceFormat::write" + "(const fileName&, const MeshedSurfaceProxy<Face>&)" + ) + << "Cannot open file for writing " << filename + << exit(FatalError); + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template<class Face> +void Foam::fileFormats::FLMAsurfaceFormat<Face>::write +( + const fileName& filename, + const MeshedSurfaceProxy<Face>& surf +) +{ + write(filename, surf, false); +} + + +template<class Face> +void Foam::fileFormats::FLMAZsurfaceFormat<Face>::write +( + const fileName& filename, + const MeshedSurfaceProxy<Face>& surf +) +{ + FLMAsurfaceFormat<Face>::write(filename, surf, true); +} + + +// ************************************************************************* // diff --git a/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.H b/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.H new file mode 100644 index 0000000000000000000000000000000000000000..1af5a3f3972ac8aa1493013dde6dfb28829af47f --- /dev/null +++ b/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormat.H @@ -0,0 +1,189 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::fileFormats::FLMAsurfaceFormat + +Description + Provide a means of writing AVL/FIRE FLMA format. + +SourceFiles + FLMAsurfaceFormat.C + +\*---------------------------------------------------------------------------*/ + +#ifndef FLMAsurfaceFormat_H +#define FLMAsurfaceFormat_H + +#include "MeshedSurface.H" +#include "MeshedSurfaceProxy.H" +#include "FIRECore.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace fileFormats +{ + +/*---------------------------------------------------------------------------*\ + Class FLMAsurfaceFormat Declaration +\*---------------------------------------------------------------------------*/ + +template<class Face> +class FLMAsurfaceFormat +: + public MeshedSurface<Face>, + public FIRECore +{ + // Private Member Functions + + static inline void writeShell(OSstream&, const Face&); + static inline void writeType(OSstream&, const Face&); + + //- Disallow default bitwise copy construct + FLMAsurfaceFormat(const FLMAsurfaceFormat<Face>&) = delete; + + //- Disallow default bitwise assignment + void operator=(const FLMAsurfaceFormat<Face>&) = delete; + + +protected: + + // Protected Member Functions + + //- Write surface mesh components by proxy + static void write + ( + OSstream&, + const MeshedSurfaceProxy<Face>& + ); + + + //- Write surface mesh components by proxy with/without compression + static void write + ( + const fileName&, + const MeshedSurfaceProxy<Face>&, + bool compress + ); + + +public: + + // Constructors + + //- Construct null + FLMAsurfaceFormat() + {} + + + //- Destructor + virtual ~FLMAsurfaceFormat() + {} + + + // Member Functions + + //- Write surface mesh components by proxy + static void write + ( + const fileName&, + const MeshedSurfaceProxy<Face>& + ); + + //- Write flma file + virtual void write(const fileName& name) const + { + write(name, MeshedSurfaceProxy<Face>(*this)); + } + +}; + + +/*---------------------------------------------------------------------------*\ + Class FLMAZsurfaceFormat Declaration +\*---------------------------------------------------------------------------*/ + +template<class Face> +class FLMAZsurfaceFormat +: + public FLMAsurfaceFormat<Face> +{ + // Private Member Functions + + //- Disallow default bitwise copy construct + FLMAZsurfaceFormat(const FLMAZsurfaceFormat<Face>&) = delete; + + //- Disallow default bitwise assignment + void operator=(const FLMAZsurfaceFormat<Face>&) = delete; + + +public: + + // Constructors + + //- Construct null + FLMAZsurfaceFormat() + {} + + + //- Destructor + virtual ~FLMAZsurfaceFormat() + {} + + + // Member Functions + + //- Write surface mesh components by proxy + static void write + ( + const fileName&, + const MeshedSurfaceProxy<Face>& + ); + + //- Write flmaz file + virtual void write(const fileName& name) const + { + write(name, MeshedSurfaceProxy<Face>(*this)); + } + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace fileFormats +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository +# include "FLMAsurfaceFormat.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormatRunTime.C b/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormatRunTime.C new file mode 100644 index 0000000000000000000000000000000000000000..a4b00b40f0ccdb24606a2f380bb4aff92fbe379e --- /dev/null +++ b/src/surfMesh/surfaceFormats/fire/FLMAsurfaceFormatRunTime.C @@ -0,0 +1,82 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "FLMAsurfaceFormat.H" + +#include "addToRunTimeSelectionTable.H" +#include "addToMemberFunctionSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace fileFormats +{ + +// write MeshedSurfaceProxy +addNamedTemplatedToMemberFunctionSelectionTable +( + MeshedSurfaceProxy, + FLMAsurfaceFormat, + face, + write, + fileExtension, + flma +); +addNamedTemplatedToMemberFunctionSelectionTable +( + MeshedSurfaceProxy, + FLMAsurfaceFormat, + triFace, + write, + fileExtension, + flma +); + + +// write MeshedSurfaceProxy (comnpressed versions of above) +addNamedTemplatedToMemberFunctionSelectionTable +( + MeshedSurfaceProxy, + FLMAZsurfaceFormat, + face, + write, + fileExtension, + flmaz +); +addNamedTemplatedToMemberFunctionSelectionTable +( + MeshedSurfaceProxy, + FLMAZsurfaceFormat, + triFace, + write, + fileExtension, + flmaz +); + +} +} + +// ************************************************************************* // diff --git a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C index c4ef94cb383e040490dd58c0b91f8231a2fe2b91..219448967cfb40b8c481d016e8ecf62452ff4318 100644 --- a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C +++ b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.C @@ -38,10 +38,10 @@ inline void Foam::fileFormats::STARCDsurfaceFormat<Face>::writeShell ) { os << cellId // includes 1 offset - << ' ' << starcdShellShape_ // 3(shell) shape + << ' ' << starcdShell // 3(shell) shape << ' ' << f.size() << ' ' << cellTableId - << ' ' << starcdShellType_; // 4(shell) + << ' ' << starcdShellType; // 4(shell) // primitives have <= 8 vertices, but prevent overrun anyhow // indent following lines for ease of reading @@ -85,15 +85,10 @@ bool Foam::fileFormats::STARCDsurfaceFormat<Face>::read fileName baseName = filename.lessExt(); // read cellTable names (if possible) - Map<word> cellTableLookup; - - { - IFstream is(baseName + ".inp"); - if (is.good()) - { - cellTableLookup = readInpCellTable(is); - } - } + Map<word> cellTableLookup = readInpCellTable + ( + IFstream(starFileName(baseName, STARCDCore::INP_FILE))() + ); // STAR-CD index of points @@ -102,7 +97,7 @@ bool Foam::fileFormats::STARCDsurfaceFormat<Face>::read // read points from .vrt file readPoints ( - IFstream(baseName + ".vrt")(), + IFstream(starFileName(baseName, STARCDCore::VRT_FILE))(), this->storedPoints(), pointId ); @@ -115,10 +110,10 @@ bool Foam::fileFormats::STARCDsurfaceFormat<Face>::read } pointId.clear(); - // + // read .cel file // ~~~~~~~~~~~~~~ - IFstream is(baseName + ".cel"); + IFstream is(starFileName(baseName, STARCDCore::CEL_FILE)); if (!is.good()) { FatalErrorInFunction @@ -126,7 +121,7 @@ bool Foam::fileFormats::STARCDsurfaceFormat<Face>::read << exit(FatalError); } - readHeader(is, "PROSTAR_CELL"); + readHeader(is, STARCDCore::HEADER_CEL); DynamicList<Face> dynFaces; DynamicList<label> dynZones; @@ -162,7 +157,7 @@ bool Foam::fileFormats::STARCDsurfaceFormat<Face>::read vertexLabels.append(mapPointId[vrtId]); } - if (typeId == starcdShellType_) + if (typeId == starcdShellType) { // Convert groupID into zoneID Map<label>::const_iterator fnd = lookup.find(cellTableId); @@ -262,9 +257,13 @@ void Foam::fileFormats::STARCDsurfaceFormat<Face>::write fileName baseName = filename.lessExt(); - writePoints(OFstream(baseName + ".vrt")(), pointLst); - OFstream os(baseName + ".cel"); - writeHeader(os, "CELL"); + writePoints + ( + OFstream(starFileName(baseName, STARCDCore::VRT_FILE))(), + pointLst + ); + OFstream os(starFileName(baseName, STARCDCore::CEL_FILE)); + writeHeader(os, STARCDCore::HEADER_CEL); label faceIndex = 0; forAll(zones, zoneI) @@ -292,7 +291,7 @@ void Foam::fileFormats::STARCDsurfaceFormat<Face>::write // write simple .inp file writeCase ( - OFstream(baseName + ".inp")(), + OFstream(starFileName(baseName, STARCDCore::INP_FILE))(), pointLst, faceLst.size(), zones diff --git a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.H b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.H index 8e4c7e09413afe588229743af16744939d523f66..8d21f2cd870514f4fbd43fd1547206bcf786aa65 100644 --- a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.H +++ b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormat.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -63,15 +63,6 @@ class STARCDsurfaceFormat public MeshedSurface<Face>, public STARCDsurfaceFormatCore { - // Private Data - - //- STAR-CD identifier for shell shapes (2d elements) - static const int starcdShellShape_ = 3; - - //- STAR-CD identifier for shell type (shells vs. baffles) - static const int starcdShellType_ = 4; - - // Private Member Functions static inline void writeShell @@ -83,10 +74,10 @@ class STARCDsurfaceFormat ); //- Disallow default bitwise copy construct - STARCDsurfaceFormat(const STARCDsurfaceFormat<Face>&); + STARCDsurfaceFormat(const STARCDsurfaceFormat<Face>&) = delete; //- Disallow default bitwise assignment - void operator=(const STARCDsurfaceFormat<Face>&); + void operator=(const STARCDsurfaceFormat<Face>&) = delete; public: diff --git a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormatCore.C b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormatCore.C index c73db97ddb5c625a6a02b6843dd9d72f93ab823d..8200a5b58be44a9e66b7d1c07e0dcf00bbf1fac6 100644 --- a/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormatCore.C +++ b/src/surfMesh/surfaceFormats/starcd/STARCDsurfaceFormatCore.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -42,6 +42,11 @@ Foam::fileFormats::STARCDsurfaceFormatCore::readInpCellTable { Map<word> lookup; + if (!is.good()) + { + return lookup; + } + regExp ctnameRE ( " *CTNA[^ ]*" // keyword - min 4 chars