diff --git a/applications/utilities/mesh/conversion/fireToFoam/Make/files b/applications/utilities/mesh/conversion/fireToFoam/Make/files
new file mode 100644
index 0000000000..a8734855d0
--- /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 0000000000..e3af2fe661
--- /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 0000000000..0f7c32c701
--- /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 .
+
+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 \
+ 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 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 0000000000..0cc67f4f55
--- /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 0000000000..e3af2fe661
--- /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 0000000000..87ddd4dff9
--- /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 .
+
+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 \
+ 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 0000000000..11b8993f28
--- /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(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/src/conversion/Make/files b/src/conversion/Make/files
index 19af831aeb..0266423e35 100644
--- a/src/conversion/Make/files
+++ b/src/conversion/Make/files
@@ -15,6 +15,10 @@ 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
diff --git a/src/conversion/fire/FIREMeshReader.C b/src/conversion/fire/FIREMeshReader.C
new file mode 100644
index 0000000000..ef8576cf5f
--- /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 .
+
+\*---------------------------------------------------------------------------*/
+
+#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 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 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::fileFormats::FIREMeshReader::mesh
+(
+ const objectRegistry& registry
+)
+{
+ readGeometry(scaleFactor_);
+ reorganize();
+
+ Info<< "Creating a polyMesh" << endl;
+
+ autoPtr 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 0000000000..0c95cb5fa2
--- /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 .
+
+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 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 0000000000..29746005d0
--- /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 .
+
+\*---------------------------------------------------------------------------*/
+
+#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 patchNames;
+ HashTable 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(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(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(patch))
+ {
+ Info<< "patch " << patchI
+ << " (start: " << patch.start() << " size: " << patch.size()
+ << ") name: " << patchNames[patchI]
+ << endl;
+
+ putFireString(os, patchNames[patchI]);
+ putFireLabel(os, static_cast(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 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 0000000000..7d61a0461e
--- /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 .
+
+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 0000000000..eb7c3bf9da
--- /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 .
+
+\*---------------------------------------------------------------------------*/
+
+#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& points
+)
+{
+ label nFailedEdges = 0;
+ const bool fullCheck = true;
+ typedef HashSet> 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& 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 0000000000..0f0bffe2c8
--- /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 .
+
+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& = UList::null()
+);
+
+
+//- check edge connectivity with pointFaces mapping calculated automatically
+label checkFireEdges
+(
+ const faceList&,
+ const UList& = UList::null()
+);
+
+
+//- check edge connectivity
+label checkFireEdges(const polyMesh&);
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fileFormats/Make/files b/src/fileFormats/Make/files
index c972fde32e..4be2605bd8 100644
--- a/src/fileFormats/Make/files
+++ b/src/fileFormats/Make/files
@@ -7,10 +7,12 @@ 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/vtkUnstructuredReader.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 0000000000..ab57611634
--- /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 .
+
+\*---------------------------------------------------------------------------*/
+
+#include "FIRECore.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+const Foam::NamedEnum
+ 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(&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(&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(&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(&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(&ivalue),
+ sizeof(ivalue)
+ );
+
+ forAll(lst, i)
+ {
+ ivalue = lst[i];
+
+ os.stdStream().write
+ (
+ reinterpret_cast(&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(&ivalue),
+ sizeof(ivalue)
+ );
+
+ ivalue = start;
+ for (label i=0; i < count; ++i, ++ivalue)
+ {
+ os.stdStream().write
+ (
+ reinterpret_cast(&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(&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(&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 0000000000..3f9c654cc1
--- /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 .
+
+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 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 0000000000..1cf217d220
--- /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
+
+
+
+
+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]
+
+NUMBER_OF_CELLS
+type0 type1 ... type2
+
+NUMBER_OF_SELECTIONS
+selectionName[0]
+selectionType[0] (2 = cells, 3 = faces)
+numberOfIDs
+id0 .. indN-1
+
+...
+selectionName[N-1]
+selectionType[N-1] (2 = cells, 3 = faces)
+numberOfIDs
+id0 .. indN-1
+
+
+
+-- 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/surfMesh/Make/files b/src/surfMesh/Make/files
index 5e19af8613..f7beae2f7c 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 0000000000..4cbfb60d56
--- /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 .
+
+\*---------------------------------------------------------------------------*/
+
+#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
+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
+inline void Foam::fileFormats::FLMAsurfaceFormat::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
+inline void Foam::fileFormats::FLMAsurfaceFormat::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
+void Foam::fileFormats::FLMAsurfaceFormat::write
+(
+ OSstream& os,
+ const MeshedSurfaceProxy& surf
+)
+{
+ if (!os.good())
+ {
+ FatalErrorIn
+ (
+ "fileFormats::FLMAsurfaceFormat::write"
+ "(OSstream&, const MeshedSurfaceProxy&)"
+ )
+ << "bad output state "
+ << exit(FatalError);
+ }
+
+ const pointField& pointLst = surf.points();
+ const List& faceLst = surf.surfFaces();
+ const List