diff --git a/src/sampling/Make/files b/src/sampling/Make/files index 649f05523d..118a48cab4 100644 --- a/src/sampling/Make/files +++ b/src/sampling/Make/files @@ -55,6 +55,7 @@ $(surfWriters)/surfaceWriter.C $(surfWriters)/dx/dxSurfaceWriter.C $(surfWriters)/ensight/ensightSurfaceWriter.C $(surfWriters)/foamFile/foamFileSurfaceWriter.C +$(surfWriters)/nastran/nastranSurfaceWriter.C $(surfWriters)/proxy/proxySurfaceWriter.C $(surfWriters)/raw/rawSurfaceWriter.C $(surfWriters)/starcd/starcdSurfaceWriter.C diff --git a/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriter.C b/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriter.C new file mode 100644 index 0000000000..3a67a8dd23 --- /dev/null +++ b/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriter.C @@ -0,0 +1,372 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2012 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "nastranSurfaceWriter.H" +#include "IOmanip.H" +#include "Tuple2.H" +#include "makeSurfaceWriterMethods.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + makeSurfaceWriterType(nastranSurfaceWriter); + addToRunTimeSelectionTable(surfaceWriter, nastranSurfaceWriter, wordDict); + + // create write methods + defineSurfaceWriterWriteFields(nastranSurfaceWriter); + + template<> + const char* NamedEnum::names[] = + { + "short", + "long", + "free" + }; + + const NamedEnum + nastranSurfaceWriter::writeFormatNames_; +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::nastranSurfaceWriter::formatOS(OFstream& os) const +{ + os.setf(ios_base::scientific); + + // capitalise the E marker + os.setf(ios_base::uppercase); + + label prec = 0; + label offset = 7; + switch (writeFormat_) + { + case (wfShort): + case (wfFree): + { + prec = 8 - offset; + break; + } + case (wfLong): + { + prec = 16 - offset; + break; + } + default: + { + } + } + + os.precision(prec); +} + + +void Foam::nastranSurfaceWriter::writeCoord +( + const point& p, + label& nPoint, + label& continuation, + Ostream& os +) const +{ + // Fixed short/long formats: + // 1 GRID + // 2 ID : point ID + // 3 CP : co-ordinate system ID (blank) + // 4 X1 : point x cp-ordinate + // 5 X2 : point x cp-ordinate + // 6 X3 : point x cp-ordinate + // 7 CD : co-ordinate system for displacements (blank) + // 8 PS : single point constraints (blank) + // 9 SEID : super-element ID + + switch (writeFormat_) + { + case wfShort: + { + os << setw(8) << "GRID" + << setw(8) << ++nPoint + << " " + << setw(8) << p.x() + << setw(8) << p.y() + << setw(8) << p.z() + << nl; + + break; + } + case wfLong: + { + os << setw(8) << "GRID*" + << setw(16) << ++nPoint + << " " + << setw(16) << p.x() + << setw(16) << p.y() + << setw(8) << ++continuation + << nl + << setw(8) << continuation + << setw(16) << p.z() + << nl; + + break; + } + case wfFree: + { + os << "GRID" + << ',' << ++nPoint + << ',' + << ',' << p.x() + << ',' << p.y() + << ',' << p.z() + << nl; + + break; + } + default: + { + FatalErrorIn + ( + "void Foam::nastranSurfaceWriter::writeCoord" + "(" + "Ostream&, " + "const point&" + ") const" + ) << "Unknown writeFormat enumeration" << abort(FatalError); + } + } +} + +void Foam::nastranSurfaceWriter::writeFace +( + const word& faceType, + const labelList& facePts, + label& nFace, + Ostream& os +) const +{ + // Only valid surface elements are CTRIA3 and CQUAD4 + + // Fixed short/long formats: + // 1 CQUAD4 + // 2 EID : element ID + // 3 PID : property element ID; default = EID (blank) + // 4 G1 : grid point index + // 5 G2 : grid point index + // 6 G3 : grid point index + // 7 G4 : grid point index + // 8 onwards - not used + + // For CTRIA3 elements, cols 7 onwards are not used + + switch (writeFormat_) + { + case wfShort: + case wfLong: + { + os << setw(8) << faceType + << setw(8) << ++nFace + << " "; + + forAll(facePts, i) + { + os << setw(8) << facePts[i]; + } + + os << nl; + + break; + } + case wfFree: + { + os << faceType << ',' + << ++nFace << ','; + + forAll(facePts, i) + { + os << ',' << facePts[i]; + } + + os << nl; + + break; + } + default: + { + FatalErrorIn + ( + "void Foam::nastranSurfaceWriter::writeFace" + "(" + "const word&" + "const labelList&" + "label&" + "Ostream&, " + ") const" + ) << "Unknown writeFormat enumeration" << abort(FatalError); + } + } + +} + + +void Foam::nastranSurfaceWriter::writeGeometry +( + const pointField& points, + const faceList& faces, + List >& decomposedFaces, + Ostream& os +) const +{ + // write points + + os << "$" << nl + << "$ Points" << nl + << "$" << nl; + + label nPoint = 0; + label continuation = 0; + + forAll(points, pointI) + { + writeCoord(points[pointI], nPoint, continuation, os); + } + + + // write faces + + os << "$" << nl + << "$ Faces" << nl + << "$" << nl; + + label nFace = 0; + + forAll(faces, faceI) + { + const face& f = faces[faceI]; + + if (f.size() == 3) + { + writeFace("CTRIA3", faces[faceI], nFace, os); + decomposedFaces[faceI].append(faces[faceI]); + } + else if (f.size() == 4) + { + writeFace("CQUAD4", faces[faceI], nFace, os); + decomposedFaces[faceI].append(faces[faceI]); + } + else + { + // decompose poly face into tris + label nTri = 0; + faceList triFaces; + f.triangles(points, nTri, triFaces); + + forAll(triFaces, triI) + { + writeFace("CTRIA3", triFaces[triI], nFace, os); + decomposedFaces[faceI].append(triFaces[triI]); + } + } + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::nastranSurfaceWriter::nastranSurfaceWriter() +: + surfaceWriter(), + writeFormat_(wfShort), + fieldMap_() +{} + + +Foam::nastranSurfaceWriter::nastranSurfaceWriter(const dictionary& options) +: + surfaceWriter(), + writeFormat_(wfShort), + fieldMap_() +{ + if (options.found("format")) + { + writeFormat_ = writeFormatNames_.read(options.lookup("format")); + } + + List > fieldSet(options.lookup("fields")); + + forAll(fieldSet, i) + { + fieldMap_.insert(fieldSet[i].first(), fieldSet[i].second()); + } +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::nastranSurfaceWriter::~nastranSurfaceWriter() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::nastranSurfaceWriter::write +( + const fileName& outputDir, + const fileName& surfaceName, + const pointField& points, + const faceList& faces, + const bool verbose +) const +{ + if (!isDir(outputDir)) + { + mkDir(outputDir); + } + + OFstream os(outputDir/surfaceName + ".dat"); + formatOS(os); + + if (verbose) + { + Info<< "Writing nastran file to " << os.name() << endl; + } + + os << "TITLE=OpeNFOAM " << surfaceName.c_str() << " mesh" << nl + << "$" << nl + << "BEGIN BULK" << nl; + + List > decomposedFaces(faces.size()); + + writeGeometry(points, faces, decomposedFaces, os); + + if (!isDir(outputDir)) + { + mkDir(outputDir); + } + + os << "ENDDATA" << endl; +} + + +// ************************************************************************* // diff --git a/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriter.H b/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriter.H new file mode 100644 index 0000000000..3667173d65 --- /dev/null +++ b/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriter.H @@ -0,0 +1,260 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2012 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Class + Foam::nastranSurfaceWriter + +Description + A surface writer for the Nastran file format - both surface mesh and fields + +SourceFiles + nastranSurfaceWriter.C + nastranSurfaceWriterTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef nastranSurfaceWriter_H +#define nastranSurfaceWriter_H + +#include "surfaceWriter.H" +#include "NamedEnum.H" +#include "OFstream.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class nastranSurfaceWriter Declaration +\*---------------------------------------------------------------------------*/ + +class nastranSurfaceWriter +: + public surfaceWriter +{ +public: + + enum writeFormat + { + wfShort, + wfLong, + wfFree + }; + + static const NamedEnum writeFormatNames_; + + +private: + + // Private data + + //- Write option + writeFormat writeFormat_; + + //- Map of OpenFOAM field name vs nastran field name + HashTable fieldMap_; + + + // Private Member Functions + + //- Initialise the output stream format params + void formatOS(OFstream& os) const; + + //- Write a co-ordinate + void writeCoord + ( + const point& p, + label& nPoint, + label& continuation, + Ostream& os + ) const; + + //- Write a face element (CTRIA3 or CQUAD4) + void writeFace + ( + const word& faceType, + const labelList& facePts, + label& nFace, + Ostream& os + ) const; + + //- Main driver to write the surface mesh geometry + void writeGeometry + ( + const pointField& points, + const faceList& faces, + List >& decomposedFaces, + Ostream& os + ) const; + + //- Write a face-based value + template + void writeFaceValue + ( + const word& nasFieldName, + const Type& value, + const label EID, + Ostream& os + ) const; + + //- Templated write operation + template + void writeTemplate + ( + const fileName& outputDir, + const fileName& surfaceName, + const pointField& points, + const faceList& faces, + const word& fieldName, + const Field& values, + const bool isNodeValues, + const bool verbose + ) const; + + +public: + + //- Runtime type information + TypeName("nastran"); + + + // Constructors + + //- Construct null + nastranSurfaceWriter(); + + //- Construct with some output options + nastranSurfaceWriter(const dictionary& options); + + + //- Destructor + virtual ~nastranSurfaceWriter(); + + + // Member Functions + + //- True if the surface format supports geometry in a separate file. + // False if geometry and field must be in a single file + virtual bool separateGeometry() + { + return false; + } + + //- Write single surface geometry to file. + virtual void write + ( + const fileName& outputDir, + const fileName& surfaceName, + const pointField& points, + const faceList& faces, + const bool verbose = false + ) const; + + //- Write scalarField for a single surface to file. + // One value per face or vertex (isNodeValues = true) + virtual void write + ( + const fileName& outputDir, + const fileName& surfaceName, + const pointField& points, + const faceList& faces, + const word& fieldName, + const Field& values, + const bool isNodeValues, + const bool verbose = false + ) const; + + //- Write vectorField for a single surface to file. + // One value per face or vertex (isNodeValues = true) + virtual void write + ( + const fileName& outputDir, + const fileName& surfaceName, + const pointField& points, + const faceList& faces, + const word& fieldName, + const Field& values, + const bool isNodeValues, + const bool verbose = false + ) const; + + //- Write sphericalTensorField for a single surface to file. + // One value per face or vertex (isNodeValues = true) + virtual void write + ( + const fileName& outputDir, + const fileName& surfaceName, + const pointField& points, + const faceList& faces, + const word& fieldName, + const Field& values, + const bool isNodeValues, + const bool verbose = false + ) const; + + //- Write symmTensorField for a single surface to file. + // One value per face or vertex (isNodeValues = true) + virtual void write + ( + const fileName& outputDir, + const fileName& surfaceName, + const pointField& points, + const faceList& faces, + const word& fieldName, + const Field& values, + const bool isNodeValues, + const bool verbose = false + ) const; + + //- Write tensorField for a single surface to file. + // One value per face or vertex (isNodeValues = true) + virtual void write + ( + const fileName& outputDir, + const fileName& surfaceName, + const pointField& points, + const faceList& faces, + const word& fieldName, + const Field& values, + const bool isNodeValues, + const bool verbose = false + ) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "nastranSurfaceWriterTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriterTemplates.C b/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriterTemplates.C new file mode 100644 index 0000000000..a393a5968b --- /dev/null +++ b/src/sampling/sampledSurface/writers/nastran/nastranSurfaceWriterTemplates.C @@ -0,0 +1,201 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2012 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "OFstream.H" +#include "IOmanip.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +template +void Foam::nastranSurfaceWriter::writeFaceValue +( + const word& nasFieldName, + const Type& value, + const label EID, + Ostream& os +) const +{ + // Fixed short/long formats: + // 1 Nastran distributed load type, e.g. PLOAD4 + // 2 SID : load set ID + // 3 EID : element ID + // 4 onwards: load values + + label SID = 0; + + label w = 16; + switch (writeFormat_) + { + case wfShort: + { + w = 8; + } + case wfLong: + { + os << setw(8) << nasFieldName + << setw(8) << SID + << setw(8) << EID; + + for (direction dirI = 0; dirI < pTraits::nComponents; dirI++) + { + os << setw(w) << component(value, dirI); + } + + break; + } + case wfFree: + { + os << nasFieldName << ',' + << SID << ',' + << EID; + + for (direction dirI = 0; dirI < pTraits::nComponents; dirI++) + { + os << ',' << component(value, dirI); + } + + break; + } + default: + { + } + } + + os << nl; +} + + +template +void Foam::nastranSurfaceWriter::writeTemplate +( + const fileName& outputDir, + const fileName& surfaceName, + const pointField& points, + const faceList& faces, + const word& fieldName, + const Field& values, + const bool isNodeValues, + const bool verbose +) const +{ + if (!fieldMap_.found(fieldName)) + { + WarningIn + ( + "void Foam::nastranSurfaceWriter::writeTemplate" + "(" + "const fileName&, " + "const fileName&, " + "const pointField&, " + "const faceList&, " + "const word&, " + "const Field&, " + "const bool, " + "const bool" + ") const" + ) + << "No mapping found between field " << fieldName + << " and corresponding Nastran field. Available types are:" + << fieldMap_ + << exit(FatalError); + + return; + } + + const word& nasFieldName(fieldMap_[fieldName]); + + if (!isDir(outputDir/fieldName)) + { + mkDir(outputDir/fieldName); + } + + // const scalar timeValue = Foam::name(this->mesh().time().timeValue()); + const scalar timeValue = 0.0; + + OFstream os(outputDir/fieldName/surfaceName + ".dat"); + formatOS(os); + + if (verbose) + { + Info<< "Writing nastran file to " << os.name() << endl; + } + + os << "TITLE=OpenFOAM " << surfaceName.c_str() << " " << fieldName + << " data" << nl + << "$" << nl + << "TIME " << timeValue << nl + << "$" << nl + << "BEGIN BULK" << nl; + + List > decomposedFaces(faces.size()); + + writeGeometry(points, faces, decomposedFaces, os); + + + os << "$" << nl + << "$ Field data" << nl + << "$" << nl; + + if (isNodeValues) + { + label n = 0; + + forAll(decomposedFaces, i) + { + const DynamicList& dFaces = decomposedFaces[i]; + forAll(dFaces, faceI) + { + Type v = pTraits::zero; + const face& f = dFaces[faceI]; + + forAll(f, fptI) + { + v += values[f[fptI]]; + } + + writeFaceValue(nasFieldName, v, ++n, os); + } + } + } + else + { + label n = 0; + + forAll(decomposedFaces, i) + { + const DynamicList& dFaces = decomposedFaces[i]; + + forAll(dFaces, faceI) + { + writeFaceValue(nasFieldName, values[faceI], ++n, os); + } + } + } + + os << "ENDDATA" << endl; +} + + +// ************************************************************************* //