openfoam/applications/utilities/postProcessing/lagrangian/steadyParticleTracks/steadyParticleTracksTemplates.C
Mark Olesen c3e14ffdd5 ENH: refactor coordSet writers (#2347)
- the very old 'writer' class was fully stateless and always templated
  on an particular output type.

  This is now replaced with a 'coordSetWriter' with similar concepts
  as previously introduced for surface writers (#1206).

  - writers change from being a generic state-less set of routines to
    more properly conforming to the normal notion of a writer.

  - Parallel data is done *outside* of the writers, since they are used
    in a wide variety of contexts and the caller is currently still in
    a better position for deciding how to combine parallel data.

ENH: update sampleSets to sample on per-field basis (#2347)

- sample/write a field in a single step.

- support for 'sampleOnExecute' to obtain values at execution
  intervals without writing.

- support 'sets' input as a dictionary entry (as well as a list),
  which is similar to the changes for sampled-surface and permits use
  of changeDictionary to modify content.

- globalIndex for gather to reduce parallel communication, less code

- qualify the sampleSet results (properties) with the name of the set.
  The sample results were previously without a qualifier, which meant
  that only the last property value was actually saved (previous ones
  overwritten).

  For example,
  ```
    sample1
    {
        scalar
        {
            average(line,T) 349.96521;
            min(line,T)     349.9544281;
            max(line,T)     350;
            average(cells,T) 349.9854619;
            min(cells,T)    349.6589286;
            max(cells,T)    350.4967271;
            average(line,epsilon) 0.04947733869;
            min(line,epsilon) 0.04449639927;
            max(line,epsilon) 0.06452856475;
        }
        label
        {
            size(line,T)    79;
            size(cells,T)   1720;
            size(line,epsilon) 79;
        }
    }
  ```

ENH: update particleTracks application

- use globalIndex to manage original parcel addressing and
  for gathering. Simplify code by introducing a helper class,
  storing intermediate fields in hash tables instead of
  separate lists.

ADDITIONAL NOTES:

- the regionSizeDistribution largely retains separate writers since
  the utility of placing sum/dev/count for all fields into a single file
  is questionable.

- the streamline writing remains a "soft" upgrade, which means that
  scalar and vector fields are still collected a priori and not
  on-the-fly.  This is due to how the streamline infrastructure is
  currently handled (should be upgraded in the future).
2022-03-10 19:41:22 +01:00

134 lines
3.7 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "steadyParticleTracksTemplates.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
Foam::tmp<Foam::IOField<Type>> Foam::readParticleField
(
const word& fieldName,
const IOobjectList& cloudObjects
)
{
const IOobject* io = cloudObjects.cfindObject<IOField<Type>>(fieldName);
if (io)
{
return tmp<IOField<Type>>::New(*io);
}
FatalErrorInFunction
<< "Cloud field name " << fieldName
<< " not found or the incorrect type"
<< abort(FatalError);
return nullptr;
}
template<class Type>
void Foam::writeVTK(OFstream& os, const Type& value)
{
os << component(value, 0);
for (label d=1; d < pTraits<Type>::nComponents; ++d)
{
os << ' ' << component(value, d);
}
}
template<class Type>
void Foam::writeVTKField
(
OFstream& os,
const IOField<Type>& field,
const List<labelList>& addr
)
{
const label step = max(1, floor(8/pTraits<Type>::nComponents));
Info<< " writing field " << field.name() << endl;
os << nl << field.name() << ' '
<< int(pTraits<Type>::nComponents) << ' '
<< field.size() << " float" << nl;
///label offset = 0;
for (const labelList& ids : addr)
{
List<Type> data(UIndirectList<Type>(field, ids));
label nData = data.size() - 1;
forAll(data, i)
{
writeVTK<Type>(os, data[i]);
if (((i + 1) % step == 0) || (i == nData))
{
os << nl;
}
else
{
os << ' ';
}
}
/// offset += ids.size();
}
}
template<class Type>
void Foam::processFields
(
OFstream& os,
const List<labelList>& addr,
const IOobjectList& cloudObjects
)
{
for (const word& fldName : cloudObjects.sortedNames<IOField<Type>>())
{
const IOobject* io = cloudObjects.cfindObject<IOField<Type>>(fldName);
if (!io)
{
FatalErrorInFunction
<< "Could not read field:" << fldName
<< " type:" << IOField<Type>::typeName
<< abort(FatalError);
}
else
{
Info<< " reading field " << fldName << endl;
IOField<Type> field(*io);
writeVTKField<Type>(os, field, addr);
}
}
}
// ************************************************************************* //