From 14a39405c22873036e5c11c8028c9d1a03173666 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Wed, 17 Oct 2018 17:37:23 +0200 Subject: [PATCH] ENH: simple dataCloud function object (issue #1044) - writes positions and a single field (eg, diameter) in plain ASCII files, suitable for importing in a spreadsheet or manipulation with scripting tools. - code integrated from https://develop.openfoam.com/Community/OpenFOAM-addOns --- src/functionObjects/lagrangian/Make/files | 1 + .../lagrangian/dataCloud/dataCloud.C | 227 ++++++++++++++++++ .../lagrangian/dataCloud/dataCloud.H | 180 ++++++++++++++ .../lagrangian/dataCloud/dataCloudTemplates.C | 130 ++++++++++ .../simplifiedSiwek/system/controlDict | 1 + .../simplifiedSiwek/system/dataCloud | 13 + 6 files changed, 552 insertions(+) create mode 100644 src/functionObjects/lagrangian/dataCloud/dataCloud.C create mode 100644 src/functionObjects/lagrangian/dataCloud/dataCloud.H create mode 100644 src/functionObjects/lagrangian/dataCloud/dataCloudTemplates.C create mode 100644 tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/dataCloud diff --git a/src/functionObjects/lagrangian/Make/files b/src/functionObjects/lagrangian/Make/files index 921ca2d707f..c7feb02e33f 100644 --- a/src/functionObjects/lagrangian/Make/files +++ b/src/functionObjects/lagrangian/Make/files @@ -1,3 +1,4 @@ +dataCloud/dataCloud.C cloudInfo/cloudInfo.C icoUncoupledKinematicCloud/icoUncoupledKinematicCloud.C dsmcFields/dsmcFields.C diff --git a/src/functionObjects/lagrangian/dataCloud/dataCloud.C b/src/functionObjects/lagrangian/dataCloud/dataCloud.C new file mode 100644 index 00000000000..53267ab0251 --- /dev/null +++ b/src/functionObjects/lagrangian/dataCloud/dataCloud.C @@ -0,0 +1,227 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 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 "dataCloud.H" +#include "Cloud.H" +#include "dictionary.H" +#include "fvMesh.H" +#include "pointList.H" +#include "OFstream.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionObjects +{ + defineTypeNameAndDebug(dataCloud, 0); + addToRunTimeSelectionTable(functionObject, dataCloud, dictionary); +} +} + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +bool Foam::functionObjects::dataCloud::writeCloud +( + const fileName& outputName, + const word& cloudName +) +{ + const auto* objPtr = mesh_.findObject<cloud>(cloudName); + if (!objPtr) + { + return false; + } + + objectRegistry obrTmp + ( + IOobject + ( + "tmp::dataCloud::" + cloudName, + mesh_.time().constant(), + mesh_, + IOobject::NO_READ, + IOobject::NO_WRITE, + false + ) + ); + + objPtr->writeObjects(obrTmp); + + const auto* pointsPtr = obrTmp.findObject<vectorField>("position"); + + if (!pointsPtr) + { + // This should be impossible + return false; + } + + // Total number of parcels on all processes + label nTotParcels = pointsPtr->size(); + reduce(nTotParcels, sumOp<label>()); + + if (!nTotParcels) + { + return false; + } + + + if (Pstream::master()) + { + mkDir(outputName.path()); + } + + return + ( + writeField<label>(outputName, obrTmp) + || writeField<scalar>(outputName, obrTmp) + || writeField<vector>(outputName, obrTmp) + ); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::functionObjects::dataCloud::dataCloud +( + const word& name, + const Time& runTime, + const dictionary& dict +) +: + fvMeshFunctionObject(name, runTime, dict), + selectClouds_(), + fieldName_(), + directory_() +{ + read(dict); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::functionObjects::dataCloud::read(const dictionary& dict) +{ + fvMeshFunctionObject::read(dict); + + const int padWidth = dict.lookupOrDefault<int>("width", 8); + + // Appropriate printf format - Enforce min/max sanity limits + if (padWidth < 1 || padWidth > 31) + { + printf_.clear(); + } + else + { + printf_ = "%0" + std::to_string(padWidth) + "d"; + } + + + selectClouds_.clear(); + dict.readIfPresent("clouds", selectClouds_); + + if (selectClouds_.empty()) + { + selectClouds_.resize(1); + selectClouds_.first() = + dict.lookupOrDefault<word>("cloud", cloud::defaultName); + } + + dict.readEntry("field", fieldName_); + + // Output directory + + directory_.clear(); + dict.readIfPresent("directory", directory_); + + if (directory_.size()) + { + // User-defined output directory + directory_.expand(); + if (!directory_.isAbsolute()) + { + directory_ = time_.globalPath()/directory_; + } + } + else + { + // Standard postProcessing/ naming + directory_ = time_.globalPath()/functionObject::outputPrefix/name(); + } + directory_.clean(); + + return true; +} + + +bool Foam::functionObjects::dataCloud::execute() +{ + return true; +} + + +bool Foam::functionObjects::dataCloud::write() +{ + const wordList cloudNames(mesh_.sortedNames<cloud>(selectClouds_)); + + if (cloudNames.empty()) + { + return true; // skip - not available + } + + const word timeDesc = "_" + + ( + printf_.empty() + ? Foam::name(time_.timeIndex()) + : word::printf(printf_, time_.timeIndex()) + ); + + Log << name() << " output Time: " << time_.timeName() << nl; + + // Each cloud separately + for (const word& cloudName : cloudNames) + { + // Legacy is not to be supported + + const fileName outputName + ( + directory_/cloudName + timeDesc + ".dat" + ); + + // writeCloud() includes mkDir (on master) + + if (writeCloud(outputName, cloudName)) + { + Log << " cloud : " + << outputName.relative(time_.globalPath()) << endl; + } + } + + return true; +} + + +// ************************************************************************* // diff --git a/src/functionObjects/lagrangian/dataCloud/dataCloud.H b/src/functionObjects/lagrangian/dataCloud/dataCloud.H new file mode 100644 index 00000000000..a1ef28b587f --- /dev/null +++ b/src/functionObjects/lagrangian/dataCloud/dataCloud.H @@ -0,0 +1,180 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 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::functionObjects::dataCloud + +Group + grpLagrangianFunctionObjects + +Description + This functionObject writes a cloud position and in ASCII. + + Example of function object specification: + \verbatim + cloudWrite1 + { + type dataCloud; + libs ("liblagrangianFunctionObjects.so"); + writeControl writeTime; + writeInterval 1; + cloud myCloud; + field d; + } + \endverbatim + +Usage + \table + Property | Description | Required | Default + type | Type name: dataCloud | yes | + cloud | | no | defaultCloud + clouds | wordRe list of clouds | no | + field | Name of the field | yes | + directory | The output directory name | no | postProcessing/NAME + width | Padding width for file name | no | 8 + \endtable + +See also + Foam::functionObjects::vtkCloud + +SourceFiles + dataCloud.C + dataCloudTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef functionObjects_dataCloud_H +#define functionObjects_dataCloud_H + +#include "fvMeshFunctionObject.H" +#include "vectorField.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace functionObjects +{ + +/*---------------------------------------------------------------------------*\ + Class dataCloud Declaration +\*---------------------------------------------------------------------------*/ + +class dataCloud +: + public fvMeshFunctionObject +{ + // Private data + + //- The printf format for zero-padding names + string printf_; + + //- Requested names of clouds to process + wordRes selectClouds_; + + //- Subset of cloud fields to process + word fieldName_; + + //- Output directory + fileName directory_; + + + // Private Member Functions + + template<class Type> + static void writeField + ( + Ostream& os, + const vectorField& points, + const Field<Type>& field + ); + + //- Write to disk + bool writeCloud(const fileName& outputName, const word& cloudName); + + //- Write from objectRegistry entry + template<class Type> + bool writeField + ( + const fileName& outputName, + const objectRegistry& obrTmp + ) const; + + + //- No copy construct + dataCloud(const dataCloud&) = delete; + + //- No copy assignment + void operator=(const dataCloud&) = delete; + + +public: + + //- Runtime type information + TypeName("dataCloud"); + + + // Constructors + + //- Construct from Time and dictionary + dataCloud + ( + const word& name, + const Time& runTime, + const dictionary& dict + ); + + + //- Destructor + virtual ~dataCloud() = default; + + + // Member Functions + + //- Read the dataCloud specification + virtual bool read(const dictionary& dict); + + //- Execute, currently does nothing + virtual bool execute(); + + //- Write fields + virtual bool write(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace functionObjects +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "dataCloudTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/functionObjects/lagrangian/dataCloud/dataCloudTemplates.C b/src/functionObjects/lagrangian/dataCloud/dataCloudTemplates.C new file mode 100644 index 00000000000..c51033e9e56 --- /dev/null +++ b/src/functionObjects/lagrangian/dataCloud/dataCloudTemplates.C @@ -0,0 +1,130 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 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 "IOField.H" +#include "OFstream.H" +#include "pointField.H" +#include "vectorField.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +template<class Type> +void Foam::functionObjects::dataCloud::writeField +( + Ostream& os, + const vectorField& points, + const Field<Type>& field +) +{ + const label len = field.size(); + + for (label pointi=0; pointi<len; ++pointi) + { + const point& pt = points[pointi]; + const Type& val = field[pointi]; + + os << pt.x() << ' ' << pt.y() << ' ' << pt.z(); + + for (direction cmpt=0; cmpt < pTraits<Type>::nComponents; ++cmpt) + { + os << ' ' << component(val, cmpt); + } + os << nl; + } +} + + +template<class Type> +bool Foam::functionObjects::dataCloud::writeField +( + const fileName& outputName, + const objectRegistry& obrTmp +) const +{ + // Fields are not always on all processors (eg, multi-component parcels). + // Thus need to resolve between all processors. + + const auto* fldPtr = obrTmp.findObject<IOField<Type>>(fieldName_); + + if (!returnReduce((fldPtr != nullptr), orOp<bool>())) + { + return false; + } + + const auto* pointsPtr = obrTmp.findObject<vectorField>("position"); + + if (!pointsPtr) + { + // This should be impossible + return false; + } + + if (Pstream::master()) + { + OFstream os(outputName); + + os << "# x y z " << fieldName_ << nl; + + // Master + if (fldPtr) + { + writeField(os, *pointsPtr, *fldPtr); + } + + // Slaves - recv + for (int slave=1; slave<Pstream::nProcs(); ++slave) + { + IPstream fromSlave(Pstream::commsTypes::blocking, slave); + vectorField points(fromSlave); + Field<Type> fld(fromSlave); + + writeField(os, points, fld); + } + } + else + { + // Slaves + + OPstream toMaster(Pstream::commsTypes::blocking, Pstream::masterNo()); + + if (fldPtr) + { + toMaster + << *pointsPtr + << *fldPtr; + } + else + { + toMaster + << vectorField() + << Field<Type>(); + } + } + + return true; +} + + +// ************************************************************************* // diff --git a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/controlDict b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/controlDict index 20916ea29a8..a2f5fcfc88e 100644 --- a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/controlDict +++ b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/controlDict @@ -54,6 +54,7 @@ maxDeltaT 1; functions { #include "vtkCloud" + // #include "dataCloud" #include "runTimePostProcessing" } diff --git a/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/dataCloud b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/dataCloud new file mode 100644 index 00000000000..127d1ccf071 --- /dev/null +++ b/tutorials/lagrangian/coalChemistryFoam/simplifiedSiwek/system/dataCloud @@ -0,0 +1,13 @@ +// -*- C++ -*- +// Minimal example of using the dataCloud function object. +dataCloud +{ + type dataCloud; + libs ("liblagrangianFunctionObjects.so"); + log true; + + cloud coalCloud1; + field d; +} + +// ************************************************************************* // -- GitLab