Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • Community/feature-adiosWrite
1 result
Select Git revision
Show changes
Commits on Source (5)
Showing
with 330 additions and 2827 deletions
#!/bin/sh
cd ${0%/*} || exit 1 # run from this directory
cd ${0%/*} || exit 1 # Run from this directory
targetType=libso
. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments
......@@ -12,6 +12,4 @@ targetType=libso
src/hasAdios || exit 1
src/Allwmake $targetType $*
# [ -d applications ] && applications/Allwmake $targetType $*
#------------------------------------------------------------------------------
......@@ -15,13 +15,13 @@ ThirdParty
Until this is fully integrated into OpenFOAM, the user should compile
ADIOS using the ThirdParty `makeADIOS` script with the preferred ADIOS version.
Subsequently, set `ADIOS_ARCH_PATH` accordingly. Eg,
Subsequently, set `ADIOS1_ARCH_PATH` accordingly. Eg,
adios_version=ADIOS-1.11.0
export ADIOS_ARCH_PATH=$WM_THIRD_PARTY_DIR/platforms/$WM_ARCH$WM_COMPILER/$adios_version
export ADIOS1_ARCH_PATH=$WM_THIRD_PARTY_DIR/platforms/$WM_ARCH$WM_COMPILER/$adios_version
And optionally add it to the PATH
PATH=$ADIOS_ARCH_PATH/bin:$PATH
PATH=$ADIOS1_ARCH_PATH/bin:$PATH
---
* Cold restart
* Not all Lagrangian types are yet supported
......@@ -12,13 +12,13 @@
---
2016-12-20
2019-04-10
---
* Storage directory: "adiosData/"
* Each "ofbp" (OpenFOAM binary packed) adios file is restricted to a
* Each "bp" (OpenFOAM binary packed) adios file is restricted to a
***single*** time-step/iteration.
This makes for simple and efficient handling.
......@@ -46,7 +46,8 @@ All entries are considered mandatory.
|---------|-----------------------------|--------
| _any_ | /constant/... | _reserved_
| _any_ | /system/... | _reserved_
| string | /openfoam/version | "plus-e40d8870f95a"
| int | /openfoam/api | 1906
| string | /openfoam/patch | "190401"
| string | /openfoam/endian | "LSB"
| int | /openfoam/label | 32
| int | /openfoam/scalar | 64
......@@ -61,15 +62,6 @@ of the `/openfoam/regions` attribute. No particular sort order is
specified for the region names.
These additional attributes provide assistance when reading the data files.
These entries are advisable.
| type | name | example
|---------|-----------------------------|--------
| string | /openfoam/baseline/plus | 1612
| string | /openfoam/platform | "linux64Gcc"
### General Variables
Coordinated data for all mesh, fields and cloud information.
......@@ -95,8 +87,8 @@ values are available directly from the meta-data.
| double | /time/value | time-value
| double | /time/deltaT | current time-step value
| double | /time/deltaT0 | previous time-step value
| double[]| /time/faces | time-value of mesh topology (per region)
| double[]| /time/points | time-value of mesh points (per region)
| double | /time/faces | time-value of mesh topology (per region)
| double | /time/points | time-value of mesh points (per region)
The order of the `/time/faces` and `/time/points` attributes must
correspond exactly to the ordering used by the `/openfoam/regions` attribute.
......@@ -175,7 +167,7 @@ also true.
| int | \<regionName\>/polyMesh/nInternalFaces | per processor
#### Localized Variables
#### Local Variables
| type | name | comment
|---------|---------------------------------------|-------------
......@@ -190,14 +182,14 @@ also true.
### Fields
#### Localized Variables
#### Local Variables
| type | name | comment
|---------|--------------------------------------|-------------
| double | \<regionName\>/field/p | internalField - primitive field content
| byte | \<regionName\>/field/p/boundaryField | as per OPENFOAM binary file content
| double | \<regionName\>/field/U | primitive field content
| byte | \<regionName\>/field/U/boundaryField | internalField - primitive field content
| double | \<regionName\>/field/p | internalField - primitive field content
| byte | \<regionName\>/field/p/boundaryField | as per OPENFOAM binary file content
| | ...
......@@ -205,10 +197,10 @@ also true.
| type | name | example
|---------|-------------------------------------|-------------
| string | \<regionName\>/field/p/class | "volScalarField"
| string[]| \<regionName\>/field/p/patch-types | { "zeroGradient", "zeroGradient", "empty" }
| string | \<regionName\>/field/U/class | "volVectorField"
| string[]| \<regionName\>/field/U/patch-types | {"fixedValue", "fixedValue", "empty"}
| string | \<regionName\>/field/p/class | "volScalarField"
| string[]| \<regionName\>/field/p/patch-types | { "zeroGradient", "zeroGradient", "empty" }
| | ...
......@@ -217,9 +209,7 @@ also true.
These entries are only available when the region also has any active
cloud information. A missing value of `nClouds` is equivalent to `nClouds=0`.
For efficiency, the parcel contents are stored directly as a binary
*blob*. The meaning of the binary content can be reconstructed
from its list of names and types.
The cloud contents are written as their IOFields.
#### Region Cloud Attributes
......@@ -233,18 +223,8 @@ from its list of names and types.
| type | name | comment
|---------|--------------------------------|-------------
| byte | \<regionName\>/cloud/\<cloudName\> | cloud binary content
| int | \<regionName\>/cloud/\<cloudName\>/nParcels | per processor
| int | \<regionName\>/cloud/\<cloudName\>/sizes | parcels sizes for variable-sized content
| double | \<regionName\>/cloud/\<cloudName\>/position | cloud x,y,z positions
The cloud attribute `min-size` corresponds to the fixed parcel length
known _a priori_ (eg, via the respective parcel `sizeofFields` value.
The cloud attribute `max-size` corresponds to the
maximum parcel length at a given time-step. If the `max-size` is not
equal to the `min-size`, the cloud type has variable-sized content and
the `sizes` variable is necessary for decoding the parcel content
manually.
#### Cloud Attributes
......@@ -252,28 +232,6 @@ manually.
|---------|--------------------------------|-------------
| string | \<regionName\>/cloud/\<cloudName\>/class | "Cloud\<basicKinematicCollidingParcel\>"
| int | \<regionName\>/cloud/\<cloudName\>/nParcels | total count (sum of corresponding variable)
| int | \<regionName\>/cloud/\<cloudName\>/min-size | 238 (bytes)
| int | \<regionName\>/cloud/\<cloudName\>/max-size | 380 (bytes)
| string[]| \<regionName\>/cloud/\<cloudName\>/names | {"position", "cellI", "faceI", "stepFraction", "tetFaceI", "tetPtI", "origProc", "origId", "active", "typeId", "nParticle", "d", "dTarget", "U", "rho", "age", "tTurb", "UTurb", "f", "angularMomentum", "torque", "*"}
| string[]| \<regionName\>/cloud/\<cloudName\>/types | {"vector", "label", "label", "scalar", "label", "label", "label", "label", "label", "label", "scalar", "scalar", "scalar", "vector", "scalar", "scalar", "scalar", "vector", "vector", "vector", "vector", "*"}
| int[] | \<regionName\>/cloud/\<cloudName\>/offset | {1, 25, 29, 33, 41, 45, 49, 53, 59, 63, 67, 75, 83, 91, 115, 123, 131, 139, 165, 189, 213, 238}
| int[] | \<regionName\>/cloud/\<cloudName\>/byte-size | {24, 4, 4, 8, 4, 4, 4, 4, 4, 4, 8, 8, 8, 24, 8, 8, 8, 24, 24, 24, 24, 0}
The following pseudocode illustrates a possible means of traversing
the parcel content:
get cloud attributes
if max-size != min-size
read "sizes" variable
read cloud binary stream
offset = 1 # leading '('
for each parcel
nbytes = sizes ? sizes[parcel] : min-size
encoded = stream[offset, offset + nbytes]
offset += nbytes
decode parcel content
---
#!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory
# Parse arguments for library compilation
. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments
. $WM_PROJECT_DIR/wmake/scripts/have_adios2
# -----------------------------------------------------------------------------
adiosFoam/Allwmake
functionObjects/Allwmake
if have_adios2
then
adiosFoam/Allwmake
functionObjects/Allwmake
else
hint_adios2
fi
# -----------------------------------------------------------------------------
#!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory
. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments
. $WM_PROJECT_DIR/wmake/scripts/have_adios2
if ../hasAdios
# -----------------------------------------------------------------------------
if have_adios2
then
wmake libso
else
......
adiosTypes.C
adiosTime.C
adiosFoam.C
adiosCore.C
adiosCoreWrite.C
adiosCoreWriteAttr.C
adiosCoreWriteVar.C
adiosCoreWriteMesh.C
adiosCoreWriteField.C
core/adiosCore.C
adiosReader.C
adiosReaderCloudInfo.C
adiosReaderField.C
adiosReaderVarInfo.C
read/adiosReader.C
read/adiosReaderCloud.C
read/adiosReaderField.C
lagrangian/ParcelEncoding.C
lagrangian/ParcelEncodingFragment.C
write/adiosCoreWrite.C
write/adiosCoreWriteAttr.C
write/adiosCoreWriteVar.C
write/adiosCoreWriteMesh.C
write/adiosCoreWriteField.C
write/adiosCoreWriteCloud.C
streams/OCompactStream.C
time/adiosTime.C
LIB = $(FOAM_USER_LIBBIN)/libadiosFoam
/* sinclude $(GENERAL_RULES)/ADIOS */
sinclude $(GENERAL_RULES)/mplib$(WM_MPLIB)
sinclude $(RULES)/mplib$(WM_MPLIB)
/* Obtain compile/link flags via adios_config */
ADIOS_INC := $(shell $(ADIOS_ARCH_PATH)/bin/adios_config -c)
ADIOS_LIBS := $(shell $(ADIOS_ARCH_PATH)/bin/adios_config -l)
sinclude $(GENERAL_RULES)/ADIOS2
EXE_INC = \
-DFOAM_PLATFORM="$(WM_ARCH)$(WM_COMPILER)" \
$(PFLAGS) $(PINC) $(ADIOS_INC) \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
$(PFLAGS) $(PINC) $(ADIOS_FLAGS) \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/finiteArea/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude
LIB_LIBS = \
$(PLIBS) $(ADIOS_LIBS) \
-llagrangian \
-lmeshTools -lfiniteVolume
-lmeshTools \
-lfiniteVolume \
-lfiniteArea \
-llagrangian
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 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::adiosCore
Description
Core routines for reading/writing ADIOS files for OpenFOAM.
SourceFiles
adiosCore.C
\*---------------------------------------------------------------------------*/
#ifndef adiosCore_H
#define adiosCore_H
#include "adiosTypes.H"
#include "word.H"
#include "instantList.H"
#include "IOstreams.H"
#include "Enum.H"
#include "CStringList.H"
#include "DynamicCharList.H"
#include "IBufStream.H"
#include "OBufStream.H"
#include "OCountStream.H"
#include "OCompactStringStream.H"
#include "OCompactBufStream.H"
#include "OCompactCountStream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declarations
class adiosCore;
/*---------------------------------------------------------------------------*\
Class adiosCore Declaration
\*---------------------------------------------------------------------------*/
class adiosCore
{
public:
//- Adios read methods. Values as per adios_read.h
enum readType
{
READ_BP = 0, //!< ADIOS_READ_METHOD_BP (=0)
READ_BP_AGGREGATE = 1 //!< ADIOS_READ_METHOD_BP_AGGREGATE (=1)
};
// Static data
static const Enum<readType> readMethodNames;
private:
// Static data
//- Reference counting for handling mpi init/finalize in serial
static unsigned refCount_;
// Private data
//- Group name within ADIOS files
word name_;
// Private Member Functions
//- Global initializations.
// Eg, Manual MPI_Init for serial runs (ADIOS always requires mpi).
static void global_init();
//- Cleanup global initializations.
// Eg, Manual MPI_Finalize for serial runs.
static void global_finalize();
protected:
// Protected data
//- Directory name for ADIOS files
static const word dataDirectory;
//- File extension for ADIOS files
static const word fileExt;
//- Buffer for reading/writing (streamed) content to/from ADIOS files
static DynamicCharList transfer_;
public:
//- OpenFOAM global attributes within ADIOS file
static const string foamAttribute;
//- OpenFOAM time attributes within ADIOS file
static const string timeAttribute;
// static const IOstream::streamFormat strFormat = IOstream::ASCII;
static const IOstream::streamFormat strFormat = IOstream::BINARY;
typedef OCompactStringStream OutputStringStreamer;
typedef OCompactBufStream OutputBufStreamer;
typedef OCompactCountStream OutputCounter;
// typedef OStringStream OStringStreamer;
// typedef OBufStream OutputBufStreamer;
// typedef OCountStream OutputCounter;
// Constructors
//- Construct for given ADIOS group name
adiosCore(const word& groupName);
//- Destructor
virtual ~adiosCore();
// Member Functions
//- Return name of the ADIOS group
const word& name() const
{
return name_;
}
//- Search a given directory for ADIOS time files
static instantList findTimes
(
const fileName& directory = dataDirectory,
const word& constantName = "constant"
);
//- Path name for a region
inline static const word& regionPath
(
const word& regionName
)
{
return regionName;
}
//- Path name for fields
inline static fileName fieldPath
(
const word& regionName,
const fileName& var = fileName::null
)
{
return regionPath(regionName) / "field" / var;
}
//- Path name for meshes
inline static fileName meshPath
(
const word& regionName,
const fileName& var = fileName::null
)
{
return regionPath(regionName) / "polyMesh" / var;
}
//- Path name for clouds
inline static fileName cloudPath
(
const word& regionName,
const word& cloudName = word::null
)
{
return regionPath(regionName) / "cloud" / cloudName;
}
//- Buffer for reading/writing (streamed) content to/from ADIOS files.
// Also used when reading/writing dissimilar content.
inline static DynamicCharList& transferBuffer()
{
return transfer_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
#endif
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2015 Norbert Podhorszki
-------------------------------------------------------------------------------
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 "adiosCoreWrite.H"
#include "adiosTime.H"
#include "foamVersion.H"
#include "endian.H"
#include "OSspecific.H"
// some internal pre-processor stringifications
#undef STRINGIFY
#undef TO_STRING
#define STRINGIFY(x) #x
#define TO_STRING(x) STRINGIFY(x)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::adiosCoreWrite::putAttribute
(
const std::string& attrName,
const std::string& varName,
const std::string& value
)
{
adios_define_attribute
(
groupID_,
attrName.c_str(),
varName.c_str(),
adios_string,
value.c_str(),
nullptr
);
}
void Foam::adiosCoreWrite::putIntAttribute
(
const std::string& attrName,
const std::string& varName,
const int value
)
{
int intval = value;
adios_define_attribute_byvalue
(
groupID_,
attrName.c_str(),
varName.c_str(),
adios_integer,
1,
&intval
);
}
void Foam::adiosCoreWrite::putScalarAttribute
(
const std::string& attrName,
const std::string& varName,
const double value
)
{
double fltval = value;
adios_define_attribute_byvalue
(
groupID_,
attrName.c_str(),
varName.c_str(),
adios_double,
1,
&fltval
);
}
bool Foam::adiosCoreWrite::putListAttribute
(
const std::string& attrName,
const std::string& varName,
const UList<int>& list
)
{
if (list.empty())
{
return false;
}
adios_define_attribute_byvalue
(
groupID_,
attrName.c_str(),
varName.c_str(),
adiosTraits<int>::adiosType,
list.size(),
list.cdata()
);
return true;
}
bool Foam::adiosCoreWrite::putListAttribute
(
const std::string& attrName,
const std::string& varName,
const UList<double>& list
)
{
if (list.empty())
{
return false;
}
adios_define_attribute_byvalue
(
groupID_,
attrName.c_str(),
varName.c_str(),
adiosTraits<double>::adiosType,
list.size(),
list.cdata()
);
return true;
}
bool Foam::adiosCoreWrite::putListAttribute
(
const std::string& attrName,
const std::string& varName,
const CStringList& cstrings
)
{
if (cstrings.size())
{
adios_define_attribute_byvalue
(
groupID_,
attrName.c_str(),
varName.c_str(),
adios_string_array,
cstrings.size(),
cstrings.strings()
);
return true;
}
return false;
}
bool Foam::adiosCoreWrite::putListAttribute
(
const std::string& attrName,
const std::string& varName,
const UList<word>& list
)
{
CStringList cstrings;
if (!list.empty())
{
cstrings.reset(list);
}
return putListAttribute(attrName, varName, cstrings);
}
bool Foam::adiosCoreWrite::putListAttribute
(
const std::string& attrName,
const std::string& varName,
const UList<string>& list
)
{
CStringList cstrings;
if (!list.empty())
{
cstrings.reset(list);
}
return putListAttribute(attrName, varName, cstrings);
}
bool Foam::adiosCoreWrite::putDimensionsAttribute
(
const std::string& varName,
const dimensionSet& dims
)
{
scalarList units(dimensionSet::nDimensions);
forAll(units, i)
{
units[i] = dims[i];
}
return putListAttribute("dimensions", varName, units);
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "adiosCoreWrite.H"
#include "volFields.H"
#include "nullObject.H"
#include "IOstreams.H"
#include "pointFields.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
int64_t Foam::adiosCoreWrite::writeFieldObject
(
const regIOobject& obj,
const bool testOnly
)
{
int64_t varid = -1;
const word& fieldType = obj.type();
// Point fields
if (fieldType == pointScalarField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const pointScalarField&>(obj)
);
}
else if (fieldType == pointVectorField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const pointVectorField&>(obj)
);
}
else if (fieldType == pointSphericalTensorField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const pointSphericalTensorField&>(obj)
);
}
else if (fieldType == pointSymmTensorField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const pointSymmTensorField&>(obj)
);
}
else if (fieldType == pointTensorField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const pointTensorField&>(obj)
);
}
// Surface fields
else if (fieldType == surfaceScalarField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const surfaceScalarField&>(obj)
);
}
else if (fieldType == surfaceVectorField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const surfaceVectorField&>(obj)
);
}
else if (fieldType == surfaceSphericalTensorField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const surfaceSphericalTensorField&>(obj)
);
}
else if (fieldType == surfaceSymmTensorField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const surfaceSymmTensorField&>(obj)
);
}
else if (fieldType == surfaceTensorField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const surfaceTensorField&>(obj)
);
}
// Volume fields
else if (fieldType == volScalarField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const volScalarField&>(obj)
);
}
else if (fieldType == volVectorField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const volVectorField&>(obj)
);
}
else if (fieldType == volSphericalTensorField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const volSphericalTensorField&>(obj)
);
}
else if (fieldType == volSymmTensorField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const volSymmTensorField&>(obj)
);
}
else if (fieldType == volTensorField::typeName)
{
varid = testOnly ? 1 : writeGeometricField
(
static_cast<const volTensorField&>(obj)
);
}
// Internal volume fields
else if (fieldType == volScalarField::Internal::typeName)
{
varid = testOnly ? 1 : writeInternalField
(
static_cast<const volScalarField::Internal&>(obj)
);
}
else if (fieldType == volVectorField::Internal::typeName)
{
varid = testOnly ? 1 : writeInternalField
(
static_cast<const volVectorField::Internal&>(obj)
);
}
else if (fieldType == volSphericalTensorField::Internal::typeName)
{
varid = testOnly ? 1 : writeInternalField
(
static_cast<const volSphericalTensorField::Internal&>(obj)
);
}
else if (fieldType == volSymmTensorField::Internal::typeName)
{
varid = testOnly ? 1 : writeInternalField
(
static_cast<const volSymmTensorField::Internal&>(obj)
);
}
else if (fieldType == volTensorField::Internal::typeName)
{
varid = testOnly ? 1 : writeInternalField
(
static_cast<const volTensorField::Internal&>(obj)
);
}
return varid;
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2015 Norbert Podhorszki
-------------------------------------------------------------------------------
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 "adiosCoreWrite.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
int64_t Foam::adiosCoreWrite::defineGenericVariable
(
const std::string& name,
enum ADIOS_DATATYPES type,
const std::string& local,
const std::string& global,
const std::string& offsets
)
{
int64_t varid = adios_define_var
(
groupID_,
name.c_str(), // name
nullptr, // path (deprecated)
type, // data-type
local.c_str(), // local dimensions
global.c_str(), // global dimensions
offsets.c_str() // local offsets
);
vars_.insert(name, varid);
return varid;
}
void Foam::adiosCoreWrite::writeGenericVariable
(
const int64_t varid,
const void* value
)
{
if (fileID_)
{
adios_write_byid(fileID_, varid, value);
}
else
{
WarningInFunction
<< "Attempting to write adios variable "
<< "without an open adios file"
<< endl;
}
}
void Foam::adiosCoreWrite::writeGenericVariable
(
const std::string& name,
const void* value
)
{
// could also check that variable has been defined
// vars_.found(name);
if (fileID_)
{
adios_write(fileID_, name.c_str(), value);
}
else
{
WarningInFunction
<< "Attempting to write adios variable "
<< name << " without an open adios file"
<< endl;
}
}
int64_t Foam::adiosCoreWrite::putLabelVariable
(
const std::string& name,
const label value
)
{
int64_t varid = adios_define_var
(
groupID_,
name.c_str(), // name
nullptr, // path (deprecated)
adiosTraits<label>::adiosType, // data-type
"1", // local dimensions
Foam::name(Pstream::nProcs()).c_str(), // global 1D array of this info
Foam::name(Pstream::myProcNo()).c_str() // offsets of this process into array
);
vars_.insert(name, varid);
if (fileID_)
{
adios_write_byid(fileID_, varid, &value);
}
else
{
WarningInFunction
<< "Attempting to write adios variable \""
<< name << "\" without an open adios file"
<< endl;
}
return varid;
}
int64_t Foam::adiosCoreWrite::defineStreamVariable
(
const std::string& name,
size_t count
)
{
// Use unsigned byte for raw storage
int64_t varid = adios_define_var
(
groupID_,
name.c_str(), // name
nullptr, // path (deprecated)
adios_unsigned_byte, // data-type
Foam::name(count).c_str(), // local dimensions
nullptr, // global dimensions
nullptr // local offsets
);
vars_.insert(name, varid);
return varid;
}
// ************************************************************************* //
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -23,106 +23,19 @@ License
\*---------------------------------------------------------------------------*/
#include "adiosCore.H"
#include "adios.h"
#include "adios_types.h"
#include "fileNameList.H"
#include "IStringStream.H"
#include "token.H"
#include "scalar.H"
#include "adiosFoam.H"
#include "OSspecific.H"
#include "Pstream.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const Foam::Enum<Foam::adiosCore::readType> Foam::adiosCore::readMethodNames
{
{ readType::READ_BP, "BP"},
{ readType::READ_BP_AGGREGATE, "BP_AGGREGATE" },
};
const Foam::word
Foam::adiosCore::dataDirectory("adiosData");
const Foam::word
Foam::adiosCore::fileExt("ofbp");
const Foam::string
Foam::adiosCore::foamAttribute = "/openfoam";
const Foam::string
Foam::adiosCore::timeAttribute = "/time";
unsigned Foam::adiosCore::refCount_ = 0;
Foam::DynamicCharList Foam::adiosCore::transfer_;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::adiosCore::global_init()
{
if (refCount_ == 0) // first one in
{
if (!Pstream::parRun())
{
// NULL args are OK for openmpi, mpich-2
MPI_Init(nullptr, nullptr);
}
// Runtime assertions (verify assumed sizes) - or emit a fatal error
adiosTraits<label>::ok();
adiosTraits<scalar>::ok();
}
++refCount_;
}
void Foam::adiosCore::global_finalize()
{
if (refCount_ == 1) // last one out
{
// Cleanup our own MPI_Init()
if (!Pstream::parRun())
{
MPI_Finalize();
}
transfer_.clearStorage();
}
--refCount_;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::adiosCore::adiosCore
(
const word& name
)
:
name_(name)
{
global_init();
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::adiosCore::~adiosCore()
{
global_finalize();
}
const Foam::word Foam::adiosFoam::defaultDirectory("adiosData");
const Foam::string Foam::adiosFoam::foamAttribute("/openfoam");
const Foam::string Foam::adiosFoam::timeAttribute("/time");
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
Foam::instantList Foam::adiosCore::findTimes
Foam::instantList Foam::adiosFoam::findTimes
(
const fileName& directory,
const word& constantName
......@@ -137,12 +50,12 @@ Foam::instantList Foam::adiosCore::findTimes
// Check for "constant" - not yet useful
bool haveConstant = false;
for (const auto& dirEntry : dirEntries)
for (const fileName& dirEntry : dirEntries)
{
if (dirEntry.ext() == fileExt && dirEntry.lessExt() == constantName)
if (dirEntry.hasExt("bp") && dirEntry.lessExt() == constantName)
{
Times[nTimes].value() = 0;
Times[nTimes].name() = dataDirectory/dirEntry;
Times[nTimes].name() = word(dirEntry);
++nTimes;
haveConstant = true;
break;
......@@ -150,17 +63,17 @@ Foam::instantList Foam::adiosCore::findTimes
}
// Read and parse all the entries in the directory
for (const auto& dirEntry : dirEntries)
for (const fileName& dirEntry : dirEntries)
{
if (dirEntry.ext() == fileExt)
if (dirEntry.hasExt("bp"))
{
IStringStream timeStream(dirEntry.lessExt());
token timeToken(timeStream);
scalar val;
const word dirValue(dirEntry.lessExt());
if (timeToken.isNumber() && timeStream.eof())
if (readScalar(dirValue, val))
{
Times[nTimes].value() = timeToken.number();
Times[nTimes].name() = dataDirectory/dirEntry;
Times[nTimes].value() = val;
Times[nTimes].name() = word(dirEntry);
++nTimes;
}
}
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2016-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -21,93 +21,112 @@ License
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::OCompactStream
Namespace
Foam::adiosFoam
Description
A generic output stream using an output with reduced spacing.
Core routines and definitions for OpenFOAM ADIOS files.
SourceFiles
OCompactStream.C
adiosFoam.C
\*---------------------------------------------------------------------------*/
#ifndef OCompactStream_H
#define OCompactStream_H
#ifndef adiosFoam_H
#define adiosFoam_H
#include "OSstream.H"
#include "fileName.H"
#include <iostream>
#include "instantList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace adiosFoam
{
/*---------------------------------------------------------------------------*\
Class OCompactStream Declaration
Namespace adiosFoam Declaration
\*---------------------------------------------------------------------------*/
class OCompactStream
:
public OSstream
{
// Private Member Functions
//- Disallow default bitwise copy construct
OCompactStream(const OCompactStream&) = delete;
//- The default directory name for ADIOS files ("adiosData")
extern const word defaultDirectory;
//- Disallow default bitwise assignment
void operator=(const OCompactStream&) = delete;
//- OpenFOAM global attributes within ADIOS file ("/openfoam")
extern const string foamAttribute;
public:
//- OpenFOAM time attributes within ADIOS file ("/time")
extern const string timeAttribute;
// Constructors
//- Set stream status
OCompactStream
(
ostream& os,
const string& name,
streamFormat format=ASCII,
versionNumber version=currentVersion,
compressionType compression=UNCOMPRESSED
);
//- Search a given directory for ADIOS time files
instantList findTimes
(
const fileName& directory,
const word& constantName = "constant"
);
// Member functions
//- Path name for a region
inline const word& regionPath
(
const word& regionName
)
{
return regionName;
}
// Write functions
//- Add indentation characters
virtual void indent();
//- Extract region name from a variable name (somewhat fragile)
inline word regionOf
(
const fileName& varName
)
{
const auto i = varName.find('/');
//- Write the keyword followed by an appropriate indentation
virtual Ostream& writeKeyword(const keyType&);
return varName.substr(0, i);
}
//- Write begin block group with the given name
virtual Ostream& beginBlock(const word&);
//- Write begin block group without a name
virtual Ostream& beginBlock();
//- Path name for fields
inline fileName fieldPath
(
const word& regionName,
const fileName& var = fileName::null
)
{
return regionPath(regionName) / "field" / var;
}
//- Write end block group
virtual Ostream& endBlock();
//- Path name for meshes
inline fileName meshPath
(
const word& regionName,
const fileName& var = fileName::null
)
{
return regionPath(regionName) / "polyMesh" / var;
}
// Stream state functions
//- Add newline and flush stream
virtual void endl();
//- Path name for clouds
inline fileName cloudPath
(
const word& regionName,
const word& cloudName = word::null
)
{
return regionPath(regionName) / "cloud" / cloudName;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace adiosFoam
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 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 "adiosReader.H"
#include "adiosCore.H"
#include "dictionary.H"
#include "IOstreams.H"
#include "Pstream.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::adiosReader::scan(bool verbose)
{
maxLen = 0;
variables.clear();
attributes.clear();
regionNames_.clear();
cloudNames_.clear();
if (!file)
{
if (verbose)
{
Info<< "adios-file not open" << endl;
}
return;
}
if (verbose)
{
Info<< "adios-file has " << file->nvars << " variables and "
<< file->nattrs << " attributes" << endl;
}
// attributes:
// hash as (name => lookup index)
for (int i=0; i < file->nattrs; ++i)
{
const char* name = file->attr_namelist[i];
attributes.insert(name, i);
if (verbose)
{
Info<< "attribute: " << name << endl;
}
}
// variable:
// hash as (name => nbytes on this process)
for (int i=0; i < file->nvars; ++i)
{
VarInfo vinfo(file, file->var_namelist[i]);
variables.insert(vinfo.name(), vinfo);
maxLen = Foam::max(maxLen, vinfo.sizeOf());
if (verbose)
{
vinfo.info(Pout) << endl;
}
}
// mandatory: /openfoam/nRegions - but can also just rely on region names
// mandatory: /openfoam/regions
regionNames_ = getStringListAttribute<word>
(
adiosCore::foamAttribute/"regions"
);
// optional: regionName/nClouds, regionName/clouds
for (const word& regName : regionNames_)
{
wordList names;
if
(
readStringListAttributeIfPresent(regName/"clouds", names)
&& !names.empty()
)
{
cloudNames_.insert(regName, names);
}
}
if (verbose)
{
Info<< "max-length: " << maxLen << endl;
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::adiosReader::adiosReader()
:
file(0),
selection(0),
maxLen(0),
regionNames_(),
cloudNames_()
{}
Foam::adiosReader::adiosReader(const fileName& bpFile, MPI_Comm comm)
:
file(0),
selection(0),
maxLen(0),
regionNames_(),
cloudNames_()
{
open(bpFile, comm);
}
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::adiosReader::~adiosReader()
{
close();
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
bool Foam::adiosReader::open(const fileName& bpFile, MPI_Comm comm)
{
// close anything already open
close();
file = adios_read_open_file
(
bpFile.c_str(),
ADIOS_READ_METHOD_BP,
comm
);
if (file)
{
select(adios_selection_writeblock(Pstream::myProcNo()));
// scan(false);
scan(true);
// Info<< "found num-vars: " << file->nvars << endl;
}
else
{
return false;
}
return isGood();
}
void Foam::adiosReader::select(ADIOS_SELECTION *sel)
{
if (selection)
{
adios_selection_delete(selection);
}
selection = sel;
}
void Foam::adiosReader::close()
{
if (selection)
{
adios_selection_delete(selection);
selection = 0;
}
if (file)
{
adios_read_close(file);
file = 0;
}
attributes.clear();
variables.clear();
regionNames_.clear();
cloudNames_.clear();
maxLen = 0;
}
bool Foam::adiosReader::isGood() const
{
return file;
}
Foam::HashTable<Foam::adiosReader::fieldInfo>
Foam::adiosReader::getFieldInfo(const word& regName) const
{
const string startsWith = adiosCore::fieldPath(regName);
HashTable<fieldInfo> table;
forAllConstIter(VarContainer, variables, iter)
{
const fileName& varName = iter.key();
const VarInfo& varInfo = iter();
if
(
varName.count('/') == 2 && varName.path() == startsWith
// Ignore "_0" fields, they are addressed separately
&& !varName.endsWith("_0")
)
{
// matches regName/field/xxx, but not regName/field/xxx_0
table.insert
(
varName.name(),
fieldInfo
(
varName,
varInfo.sizeOf(),
getStringAttribute(varName/"class")
)
);
}
}
// Info<<"Table ";
// forAllConstIter(HashTable<fieldInfo>, table, iter)
// {
// iter().info(Info);
// }
return table;
}
Foam::HashTable<Foam::adiosReader::cloudInfo>
Foam::adiosReader::getCloudInfo(const word& regName) const
{
const string startsWith = adiosCore::cloudPath(regName);
HashTable<cloudInfo> table;
forAllConstIter(VarContainer, variables, iter)
{
const fileName& varName = iter.key();
const VarInfo& varInfo = iter();
if (varName.count('/') == 2 && varName.path() == startsWith)
{
// matches regName/cloud/xxx
table.insert(varName.name(), cloudInfo(varInfo, *this));
}
}
return table;
}
bool Foam::adiosReader::readIntAttributeIfPresent
(
const string& name,
label& value
) const
{
enum ADIOS_DATATYPES type = adios_unknown;
int size = 0;
void *data = 0;
bool ok =
(
hasAttribute(name)
&& 0 ==
adios_get_attr_byid
(
file,
attributes[name],
&type,
&size,
&data
)
);
if (ok)
{
if (type == adios_integer || type == adios_unsigned_integer)
{
// we don't distinguish between signed/unsigned
// mostly just use signed anyhow
size /= sizeof(int);
ok = (size == 1);
if (ok)
{
value = *(reinterpret_cast<int*>(data));
}
}
else
{
size = -1;
ok = false;
}
if (data)
{
free(data);
}
if (size < 0)
{
FatalErrorInFunction
<< "incorrect type for attribute: " << name << nl
<< " expecting int/unsigned, found "
<< adios_type_to_string(type) << exit(FatalIOError);
}
else if (!ok)
{
FatalErrorInFunction
<< "wrong number of elements for attribute: " << name << nl
<< " expecting 1 int/unsigned, found " << size
<< exit(FatalIOError);
}
}
return ok;
}
bool Foam::adiosReader::readScalarAttributeIfPresent
(
const string& name,
double& value
) const
{
enum ADIOS_DATATYPES type = adios_unknown;
int size = 0;
void *data = 0;
bool ok =
(
hasAttribute(name)
&& 0 ==
adios_get_attr_byid
(
file,
attributes[name],
&type,
&size,
&data
)
);
if (ok)
{
if (type == adios_double)
{
size /= sizeof(double);
ok = (size == 1);
if (ok)
{
value = *(reinterpret_cast<double*>(data));
}
}
else
{
size = -1;
ok = false;
}
if (data)
{
free(data);
}
if (size < 0)
{
FatalErrorInFunction
<< "incorrect type for attribute: " << name << nl
<< " expecting double, found "
<< adios_type_to_string(type) << exit(FatalIOError);
}
else if (!ok)
{
FatalErrorInFunction
<< "wrong number of elements for attribute: " << name << nl
<< " expecting 1 double, found " << size
<< exit(FatalIOError);
}
}
return ok;
}
bool Foam::adiosReader::readIntListAttributeIfPresent
(
const string& name,
List<label>& lst
) const
{
enum ADIOS_DATATYPES type = adios_unknown;
int size = 0;
void *data = 0;
bool ok =
(
hasAttribute(name)
&& 0 ==
adios_get_attr_byid
(
file,
attributes[name],
&type,
&size,
&data
)
);
if (ok)
{
if (type == adios_integer || adios_unsigned_integer)
{
// we don't distinguish between signed/unsigned
// mostly just use signed anyhow
size /= sizeof(int);
ok = (size > 0);
if (ok)
{
int *ptr = reinterpret_cast<int*>(data);
lst.setSize(size);
for (int i=0; i < size; ++i)
{
lst[i] = ptr[i];
}
}
}
else
{
size = -1;
ok = false;
}
if (data)
{
free(data);
}
if (size < 0)
{
FatalErrorInFunction
<< "incorrect type for attribute: " << name << nl
<< " expecting int/unsigned, found "
<< adios_type_to_string(type) << exit(FatalIOError);
}
else if (!ok)
{
FatalErrorInFunction
<< "too few elements for attribute: " << name << nl
<< " expecting multiple int/unsigned values, found 0"
<< exit(FatalIOError);
}
}
return ok;
}
bool Foam::adiosReader::readScalarListAttributeIfPresent
(
const string& name,
List<double>& lst
) const
{
enum ADIOS_DATATYPES type = adios_unknown;
int size = 0;
void *data = 0;
bool ok =
(
hasAttribute(name)
&& 0 ==
adios_get_attr_byid
(
file,
attributes[name],
&type,
&size,
&data
)
);
if (ok)
{
if (type == adios_double)
{
size /= sizeof(double);
ok = (size > 0);
if (ok)
{
double *ptr = reinterpret_cast<double*>(data);
lst.setSize(size);
for (int i=0; i < size; ++i)
{
lst[i] = ptr[i];
}
}
}
else
{
size = -1;
ok = false;
}
if (data)
{
free(data);
}
if (size < 0)
{
FatalErrorInFunction
<< "incorrect type for attribute: " << name << nl
<< " expecting double, found "
<< adios_type_to_string(type) << exit(FatalIOError);
}
else if (!ok)
{
FatalErrorInFunction
<< "too few elements for attribute: " << name << nl
<< " expecting multiple double values, found 0"
<< exit(FatalIOError);
}
}
return ok;
}
bool Foam::adiosReader::readStringAttributeIfPresent
(
const string& name,
string& value
) const
{
enum ADIOS_DATATYPES type = adios_unknown;
int size = 0;
void *data = 0;
bool ok =
(
hasAttribute(name)
&& 0 ==
adios_get_attr_byid
(
file,
attributes[name],
&type,
&size,
&data
)
);
if (ok)
{
if (type == adios_string)
{
value = reinterpret_cast<char*>(data);
}
else
{
ok = false;
}
if (data)
{
free(data);
}
if (!ok)
{
FatalErrorInFunction
<< "incorrect type for attribute: " << name << nl
<< " expecting string, found "
<< adios_type_to_string(type)
<< exit(FatalIOError);
}
}
return ok;
}
bool Foam::adiosReader::readIntVariableIfPresent
(
const string& name,
label& value
) const
{
bool ok = hasVariable(name);
int err = 0;
int data = 0;
if (ok)
{
const VarInfo& vinfo = variables[name];
int size = vinfo.nElem();
if
(
vinfo.dataType() == adios_integer
|| vinfo.dataType() == adios_unsigned_integer
)
{
// we don't distinguish between signed/unsigned
// mostly just use signed anyhow
ok = (size == 1);
if (ok)
{
err = adios_schedule_read
(
file,
selection,
name.c_str(),
0, 1,
&data
);
if (!err)
{
err = adios_perform_reads(file, 1); // blocking
}
if (!err)
{
value = data;
}
else
{
FatalErrorInFunction
<< "error reading adios variable: " << name << nl
<< exit(FatalIOError);
}
}
}
else
{
size = -1;
ok = false;
}
if (size < 0)
{
FatalErrorInFunction
<< "incorrect type for variable: " << name << nl
<< " expecting int/unsigned, found "
<< adios_type_to_string(vinfo.dataType()) << exit(FatalIOError);
}
else if (!ok)
{
FatalErrorInFunction
<< "too many elements for variable: " << name << nl
<< " expecting 1 int/unsigned, found " << size
<< exit(FatalIOError);
}
}
return ok;
}
bool Foam::adiosReader::readScalarVariableIfPresent
(
const string& name,
scalar& value
) const
{
bool ok = hasVariable(name);
int err = 0;
if (ok)
{
const VarInfo& vinfo = variables[name];
int size = vinfo.nElem();
if (vinfo.dataType() == adios_real)
{
ok = (size == 1);
if (ok)
{
float data = 0;
err = adios_schedule_read
(
file,
selection,
name.c_str(),
0, 1,
&data
);
if (!err)
{
err = adios_perform_reads(file, 1); // blocking
}
if (!err)
{
value = data;
}
else
{
FatalErrorInFunction
<< "error reading adios variable: " << name << nl
<< exit(FatalIOError);
}
}
}
else if (vinfo.dataType() == adios_double)
{
ok = (size == 1);
if (ok)
{
double data = 0;
err = adios_schedule_read
(
file,
selection,
name.c_str(),
0, 1,
&data
);
if (!err)
{
err = adios_perform_reads(file, 1); // blocking
}
if (!err)
{
value = data;
}
else
{
FatalErrorInFunction
<< "error reading adios variable: " << name << nl
<< exit(FatalIOError);
}
}
}
else
{
size = -1;
ok = false;
}
if (size < 0)
{
FatalErrorInFunction
<< "incorrect type for variable: " << name << nl
<< " expecting float/double, found "
<< adios_type_to_string(vinfo.dataType()) << exit(FatalIOError);
}
else if (!ok)
{
FatalErrorInFunction
<< "too many elements for variable: " << name << nl
<< " expecting 1 float/double, found " << size
<< exit(FatalIOError);
}
}
return ok;
}
bool Foam::adiosReader::getVariable
(
const string& name,
void* data
) const
{
bool ok = hasVariable(name);
if (ok)
{
int err = adios_schedule_read
(
file,
selection,
name.c_str(),
0, 1,
data
);
if (!err)
{
err = adios_perform_reads(file, 1); // blocking
}
if (err)
{
FatalErrorInFunction
<< "Error reading adios variable " << name
<< adios_errmsg() << endl;
}
ok = !err;
}
else
{
FatalErrorInFunction
<< "missing adios variable: " << name
<< exit(FatalIOError);
}
return ok;
}
size_t Foam::adiosReader::getBuffered
(
const string& name
) const
{
return getBuffered(name, adiosCore::transferBuffer());
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "adiosReader.H"
#include "emptyFvPatchField.H"
#include "pointFields.H"
#include "volFields.H"
#include "surfaceFields.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::label Foam::adiosReader::readFieldObject
(
regIOobject& obj,
const fieldInfo& src
) const
{
const word& fieldType = obj.type();
const word& srcType = src.type();
if (fieldType != srcType)
{
// probably fatal:
Info<<"WARNING mismatch on field " << src
<< " (expected: " << fieldType
<< " but had " << srcType << ")\n";
return -1;
}
Info<<"Read " << obj.name() << " (type " << fieldType << ") from file\n";
// Point fields
if (fieldType == pointScalarField::typeName)
{
return readGeometricField
(
static_cast<pointScalarField&>(obj),
src
);
}
else if (fieldType == pointVectorField::typeName)
{
return readGeometricField
(
static_cast<pointVectorField&>(obj),
src
);
}
else if (fieldType == pointSphericalTensorField::typeName)
{
return readGeometricField
(
static_cast<pointSphericalTensorField&>(obj),
src
);
}
else if (fieldType == pointSymmTensorField::typeName)
{
return readGeometricField
(
static_cast<pointSymmTensorField&>(obj),
src
);
}
else if (fieldType == pointTensorField::typeName)
{
return readGeometricField
(
static_cast<pointTensorField&>(obj),
src
);
}
// Surface fields
else if (fieldType == surfaceScalarField::typeName)
{
return readGeometricField
(
static_cast<surfaceScalarField&>(obj),
src
);
}
else if (fieldType == surfaceVectorField::typeName)
{
return readGeometricField
(
static_cast<surfaceVectorField&>(obj),
src
);
}
else if (fieldType == surfaceSphericalTensorField::typeName)
{
return readGeometricField
(
static_cast<surfaceSphericalTensorField&>(obj),
src
);
}
else if (fieldType == surfaceSymmTensorField::typeName)
{
return readGeometricField
(
static_cast<surfaceSymmTensorField&>(obj),
src
);
}
else if (fieldType == surfaceTensorField::typeName)
{
return readGeometricField
(
static_cast<surfaceTensorField&>(obj),
src
);
}
// Volume fields
else if (fieldType == volScalarField::typeName)
{
return readGeometricField
(
static_cast<volScalarField&>(obj),
src
);
}
else if (fieldType == volVectorField::typeName)
{
return readGeometricField
(
static_cast<volVectorField&>(obj),
src
);
}
else if (fieldType == volSphericalTensorField::typeName)
{
return readGeometricField
(
static_cast<volSphericalTensorField&>(obj),
src
);
}
else if (fieldType == volSymmTensorField::typeName)
{
return readGeometricField
(
static_cast<volSymmTensorField&>(obj),
src
);
}
else if (fieldType == volTensorField::typeName)
{
return readGeometricField
(
static_cast<volTensorField&>(obj),
src
);
}
// Internal volume fields
else if (fieldType == volScalarField::Internal::typeName)
{
return readField
(
static_cast<volScalarField::Internal&>(obj),
src
);
}
else if (fieldType == volVectorField::Internal::typeName)
{
return readField
(
static_cast<volVectorField::Internal&>(obj),
src
);
}
else if (fieldType == volSphericalTensorField::Internal::typeName)
{
return readField
(
static_cast<volSphericalTensorField::Internal&>(obj),
src
);
}
else if (fieldType == volSymmTensorField::Internal::typeName)
{
return readField
(
static_cast<volSymmTensorField::Internal&>(obj),
src
);
}
else if (fieldType == volTensorField::Internal::typeName)
{
return readField
(
static_cast<volTensorField::Internal&>(obj),
src
);
}
return -1;
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 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 "adiosCore.H"
#include "adiosReader.H"
#include "error.H"
#include "CStringList.H"
#include "adios.h"
#include "adios_read.h"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type, class SourceType>
Foam::label Foam::adiosReader::copyList
(
UList<Type>& dst,
const fileName& varName
) const
{
DynamicCharList& buffer = adiosCore::transferBuffer();
label sizeRead = -1;
if (hasVariable(varName))
{
size_t nread = getBuffered(varName, buffer);
sizeRead = (nread / sizeof(SourceType) / pTraits<Type>::nComponents);
// TODO? check sizes
UList<SourceType> src
(
reinterpret_cast<SourceType*>(buffer.data()),
sizeRead
);
// Component-wise copy
label srcindex = 0;
for (Type& dstItem : dst)
{
for (direction cmpt = 0; cmpt < pTraits<Type>::nComponents; ++cmpt)
{
setComponent(dstItem, cmpt) = src[srcindex++];
}
}
}
// Fatal
if (sizeRead < 0)
{
FatalErrorInFunction
<< "missing adios variable: " << varName << endl
<< exit(FatalIOError);
}
return sizeRead;
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * * //
template<class StringType>
bool Foam::adiosReader::readStringListAttributeIfPresent
(
const string& name,
List<StringType>& lst
) const
{
enum ADIOS_DATATYPES type = adios_unknown;
int size = 0;
void *data = 0;
bool ok =
(
hasAttribute(name)
&& 0 ==
adios_get_attr_byid
(
file,
attributes[name],
&type,
&size,
&data
)
);
if (ok)
{
if (type == adios_string_array)
{
lst = CStringList::asList<StringType>
(
(size / sizeof(char*)), // argc
reinterpret_cast<char**>(data) // argv
);
}
else
{
ok = false;
}
if (data)
{
free(data);
}
if (!ok)
{
FatalErrorInFunction
<< "string-list attribute has wrong type: " << name << nl
<< " expecting char*[], found "
<< adios_type_to_string(type)
<< exit(FatalIOError);
}
}
return ok;
}
template<class bufferT>
size_t Foam::adiosReader::getBuffered
(
const string& name,
DynamicList<bufferT>& buffer
) const
{
size_t nbytes = 0;
if (hasVariable(name))
{
const VarInfo& vinfo = variables[name];
nbytes = vinfo.sizeOf();
const size_t sizeT = sizeof(bufferT);
const size_t target = (nbytes / sizeT) + (nbytes % sizeT);
buffer.reserve(nbytes / sizeT + nbytes % sizeT);
if (getVariable(name, buffer.data()))
{
buffer.setSize(target);
}
else
{
buffer.setSize(0);
nbytes = 0;
}
}
if (!nbytes)
{
FatalErrorInFunction
<< "missing adios variable: " << name
<< exit(FatalIOError);
}
return nbytes;
}
template<class Type, template<class> class PatchField, class GeoMesh>
Foam::label Foam::adiosReader::readGeometricField
(
GeometricField<Type, PatchField, GeoMesh>& field,
const fileName& varName
) const
{
label sizeRead = readField(field.ref(), varName);
Info<<"read " << varName << " was " << sizeRead << endl;
size_t nread = 0;
const fileName boundaryFieldName = varName/"boundaryField";
if (hasVariable(boundaryFieldName))
{
// Read data from file - fatal error if this fails!
nread = getBuffered(boundaryFieldName);
// Info<<"retrieve: " << boundaryFieldName << " with "
// << nread << " bytes" << endl;
if (nread)
{
// read fields via dictionary
IBufStream is
(
adiosCore::transferBuffer(),
nread,
adiosCore::strFormat
);
dictionary dict(is);
Pout<<"dictionary: " << field.name() << " with "
<< dict.toc() << endl;
field.boundaryFieldRef().readField(field, dict);
}
}
// Could/should also check nread (boundaryField)
const fileName field0Name = varName + "_0";
if (field.nOldTimes() > 1 && hasVariable(field0Name))
{
Info<<"should load " << field.oldTime().name()
<< " from " << field0Name
<< " since we have " << field.nOldTimes() << endl;
#if 0
// This needs more work to avoid creating time references for the
// "_0" field too. Probably have to bypass the standard mechanism
// and do the transfer directly and update the eventNo afterwards.
readGeometricField
(
field.oldTime(),
field0Name
);
#endif
}
return sizeRead;
}
template<class Type, class GeoMesh>
Foam::label Foam::adiosReader::readField
(
DimensionedField<Type, GeoMesh>& field,
const fileName& varName
) const
{
label sizeRead = -1;
const enum ADIOS_DATATYPES targetType =
adiosTraits<typename pTraits<Type>::cmptType>::adiosType;
Field<Type>& dst = field.field();
if (hasVariable(varName))
{
const adiosReader::VarInfo& vinfo = getVariableInfo(varName);
const enum ADIOS_DATATYPES sourceType = vinfo.dataType();
if (targetType == sourceType)
{
if (getVariable(varName, dst.data()))
{
// Assume the best. Need to verify later!
sizeRead = field.size();
}
}
else if (targetType == adios_real)
{
if (sourceType == adios_double)
{
sizeRead = copyList<Type, double>(dst, varName);
}
}
else if (targetType == adios_double)
{
if (sourceType == adios_real)
{
sizeRead = copyList<Type, float>(dst, varName);
}
}
else if (targetType == adios_integer)
{
if (sourceType == adios_long)
{
sizeRead = copyList<Type, long>(dst, varName);
}
}
else if (targetType == adios_long)
{
if (sourceType == adios_integer)
{
sizeRead = copyList<Type, int>(dst, varName);
}
}
else
{
// Fatal
}
}
if (sizeRead < 0)
{
FatalErrorInFunction
<< "missing adios variable: " << varName << endl
<< exit(FatalIOError);
}
return sizeRead;
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 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 "adiosReader.H"
#include "IOstreams.H"
#include "Pstream.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
bool Foam::adiosReader::VarInfo::readInfo
(
ADIOS_FILE *file,
bool verbose
)
{
nElem_ = 0; // the number of elements (flattened dimensions)
nBytes_ = 0;
if (file)
{
// TODO? restrict sizing to current processor!
ADIOS_VARINFO *vinfo = adios_inq_var(file, name_.c_str());
if (!vinfo)
{
WarningInFunction
<< "Error reading variable information " << name_
<< " from adios file: "
<< adios_errmsg() << endl;
return false;
}
if (vinfo->type == adios_string)
{
WarningInFunction
<< "Reading sizes for adios_string variables incomplete: "
<< name_ << endl;
// free ADIOS_VARINFO and any ADIOS_VARBLOCK(s)
adios_free_varinfo(vinfo);
return false;
}
// could also assert (vinfo->nstep == 1)
// since that is what we expect and support
varid_ = vinfo->varid;
type_ = vinfo->type;
if (vinfo->ndim > 0)
{
const int ndim = vinfo->ndim;
const int nblocks = vinfo->sum_nblocks;
// get block-decomposition
int err = adios_inq_var_blockinfo(file, vinfo);
if (err)
{
WarningInFunction
<< "Error reading blockinfo for dataset " << name_
<< " from adios file: "
<< adios_errmsg() << endl;
}
else
{
ADIOS_VARBLOCK *bp = vinfo->blockinfo;
for (int blockI=0; blockI < nblocks; ++blockI)
{
if (Foam::label(bp->process_id) == Pstream::myProcNo())
{
int count = 1;
for (int dimI=0; dimI < ndim; ++dimI)
{
count *= bp->count[dimI];
}
nElem_ += count;
#if 0
OStringStream os1;
OStringStream os2;
os1 << bp->count[0];
os2 << vinfo->dims[0];
for (int dimI=1; dimI < vinfo->ndim; ++dimI)
{
os1 << ',' << bp->count[dimI];
os2 << ',' << vinfo->dims[dimI];
}
if (vinfo->global)
{
Pout<< name_
<< " [" << bp->process_id
<< "] block[" << blockI << "]"
<< " nElem: " << nElem_
<< " dims: " << os1.str().c_str()
<< " global: " << os2.str().c_str()
<< " start: " << *(bp->start)
<< " time-index:" << bp->time_index << endl;
}
else
{
Pout<< name_
<< " [" << bp->process_id
<< "] block[" << blockI << "]"
<< " nElem: " << nElem_
<< " dims: " << os1.str().c_str()
<< " time-index:" << bp->time_index << endl;
}
#endif
}
++bp;
}
}
if (!nElem_)
{
WarningInFunction
<< "No corresponding information for dataset " << name_
<< " from adios file" << endl;
}
}
else
{
#if 0
Pout<< " variable=" << name_ << " is scalar" << endl;
#endif
nElem_ = 1; // scalar value
}
nBytes_ = nElem_ * adios_type_size(type_, nullptr);
if (verbose)
{
Pout<< " variable=" << name_
<< " nElem=" << nElem_
<< " nBytes=" << nBytes_
<< " type=" << adios_type_to_string(type_)
<< endl;
}
// free ADIOS_VARINFO and any ADIOS_VARBLOCK(s)
adios_free_varinfo(vinfo);
}
return nBytes_ > 0;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::adiosReader::VarInfo::VarInfo
(
const char* varName
)
:
name_(varName),
varid_(0),
type_(adios_unknown),
nElem_(0),
nBytes_(0)
{}
Foam::adiosReader::VarInfo::VarInfo
(
const string& varName
)
:
name_(varName),
varid_(0),
type_(adios_unknown),
nElem_(0),
nBytes_(0)
{}
Foam::adiosReader::VarInfo::VarInfo
(
ADIOS_FILE *file,
const char* varName,
bool verbose
)
:
name_(varName),
varid_(0),
type_(adios_unknown),
nElem_(0),
nBytes_(0)
{
readInfo(file, verbose);
}
Foam::adiosReader::VarInfo::VarInfo
(
ADIOS_FILE *file,
const string& varName,
bool verbose
)
:
name_(varName),
varid_(0),
type_(adios_unknown),
nElem_(0),
nBytes_(0)
{
readInfo(file, verbose);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::adiosReader::VarInfo::~VarInfo()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::Ostream& Foam::adiosReader::VarInfo::info(Ostream& os) const
{
os.beginBlock();
os.writeEntry("name", name_);
os.writeEntry("varid", varid_);
os.writeEntry("adiosType", label(type_));
os.writeEntry("count", nElem_);
os.writeEntry("sizeof", nBytes_);
os.endBlock();
return os;
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
InClass
Foam::adiosTraits
Description
Specializations.
\*---------------------------------------------------------------------------*/
#include "adiosTraits.H"
#include "label.H"
#include "scalar.H"
#include "vector.H"
#include "adios_types.h"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Template specialization for adiosTraits\<int\>
template<>
class adiosTraits<int>
{
int p_;
public:
//- ADIOS type
static const enum ADIOS_DATATYPES adiosType;
//- Size of ADIOS type
static const size_t adiosSize;
//- Verify ADIOS type-size
static bool ok();
// Constructors
//- Construct from primitive
explicit adiosTraits(const int&);
// Member Functions
//- Access to the primitive value
operator int() const
{
return p_;
}
//- Access to the primitive value
operator int&()
{
return p_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Template specialization for adiosTraits\<long\>
template<>
class adiosTraits<long>
{
long p_;
public:
//- Component type
// typedef label cmptType;
//- ADIOS type
static const enum ADIOS_DATATYPES adiosType;
//- Size of ADIOS type
static const size_t adiosSize;
//- Verify ADIOS type-size
static bool ok();
// Constructors
//- Construct from primitive
explicit adiosTraits(const long&);
// Member Functions
//- Access to the primitive value
operator long() const
{
return p_;
}
//- Access to the primitive value
operator long&()
{
return p_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Template specialization for adiosTraits\<float\>
template<>
class adiosTraits<float>
{
float p_;
public:
//- Component type
// typedef scalar cmptType;
//- ADIOS type
static const enum ADIOS_DATATYPES adiosType;
//- Size of ADIOS type
static const size_t adiosSize;
//- Verify ADIOS type-size
static bool ok();
// Constructors
//- Construct from primitive
explicit adiosTraits(const float&);
// Member Functions
//- Access to the primitive value
operator float() const
{
return p_;
}
//- Access to the primitive value
operator float&()
{
return p_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Template specialization for adiosTraits\<double\>
template<>
class adiosTraits<double>
{
double p_;
public:
//- ADIOS type
static const enum ADIOS_DATATYPES adiosType;
//- Size of ADIOS type
static const size_t adiosSize;
//- Verify ADIOS type-size
static bool ok();
// Constructors
//- Construct from primitive
explicit adiosTraits(const double&);
// Member Functions
//- Access to the primitive value
operator double() const
{
return p_;
}
//- Access to the primitive value
operator double&()
{
return p_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2016-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -23,26 +23,51 @@ License
\*---------------------------------------------------------------------------*/
#include "adiosCore.H"
#include "Pstream.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
int Foam::adiosFoam::adiosCore::debug(0);
unsigned Foam::adiosFoam::adiosCore::refCount_ = 0;
Foam::DynamicList<char> Foam::adiosFoam::adiosCore::transfer_;
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class CloudType>
Foam::ParcelEncoding::ParcelEncoding
(
const CloudType& cld
)
:
Container(),
types_(),
names_(),
length_(0)
Foam::adiosFoam::adiosCore::adiosCore()
{
// Info<< "inputTypes: " << CloudType::particleType::propertyTypes() << endl;
// Info<< "inputNames: " << CloudType::particleType::propertyList() << endl;
if (refCount_ == 0)
{
// First one in
transfer_.reserve(4096);
// Initialize MPI as required - needed for ADIOS
UPstream::initNull();
}
++refCount_;
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::adiosFoam::adiosCore::~adiosCore()
{
if (refCount_ == 1)
{
// Last one out
// Cleanup transfer buffer
transfer_.clearStorage();
setTypes(IStringStream(CloudType::particleType::propertyTypes())());
setNames(IStringStream(CloudType::particleType::propertyList())());
// OpenFOAM will cleanup and finalize MPI
}
makeSummary();
--refCount_;
}
......