/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021-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 .
\*---------------------------------------------------------------------------*/
#include "fvExpressionField.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "pointMesh.H"
#include "pointFields.H"
#include "volumeExprDriver.H"
#include "calculatedFvPatchField.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace functionObjects
{
defineTypeNameAndDebug(fvExpressionField, 0);
addToRunTimeSelectionTable(functionObject, fvExpressionField, dictionary);
}
}
const Foam::Enum
<
Foam::functionObjects::fvExpressionField::actionType
>
Foam::functionObjects::fvExpressionField::actionNames_
({
{ actionType::opNone, "none" },
{ actionType::opNew, "new" },
{ actionType::opModify, "modify" },
});
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
word fieldGeoType(const expressions::FieldAssociation geoType)
{
switch (geoType)
{
case expressions::FieldAssociation::POINT_DATA : return "points"; break;
case expressions::FieldAssociation::FACE_DATA : return "faces"; break;
case expressions::FieldAssociation::VOLUME_DATA : return "cells"; break;
default: break;
}
return "unknown";
}
template
static void doCorrectBoundaryConditions
(
bool correctBCs,
VolumeField& field
)
{
if (correctBCs)
{
// Info<< "Correcting boundary conditions: " << field.name() << nl;
field.correctBoundaryConditions();
// Ensure that calculated patches are updated
for (auto& pf : field.boundaryFieldRef())
{
if (isA>(pf))
{
pf = pf.patchInternalField();
}
}
}
}
template
void doCorrectBoundaryConditions
(
bool correctBCs,
PointField& field
)
{
if (correctBCs)
{
// Info<< "Correcting boundary conditions: " << field.name() << nl;
field.correctBoundaryConditions();
}
}
template
void doCorrectBoundaryConditions
(
bool correctBCs,
SurfaceField& field
)
{}
} // End namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template
bool Foam::functionObjects::fvExpressionField::loadAndStore(const IOobject& io)
{
if (FieldType::typeName == io.headerClassName())
{
// Store field on mesh database
Log << " Reading " << io.name()
<< " (" << FieldType::typeName << ')' << endl;
mesh_.objectRegistry::store(new FieldType(io, mesh_));
return true;
}
return false;
}
template
bool Foam::functionObjects::fvExpressionField::loadField(const IOobject& io)
{
return
(
loadAndStore>(io)
/// || loadAndStore>(io)
|| loadAndStore>(io)
);
}
Foam::label Foam::functionObjects::fvExpressionField::loadFields
(
const UList& fieldSet_
)
{
label nLoaded = 0;
for (const word& fieldName : fieldSet_)
{
// Already loaded?
const auto* ptr = mesh_.cfindObject(fieldName);
if (ptr)
{
++nLoaded;
DebugInfo
<< "readFields : "
<< ptr->name() << " (" << ptr->type()
<< ") already in database" << endl;
continue;
}
// Load field as necessary
IOobject io
(
fieldName,
mesh_.time().timeName(),
mesh_,
IOobject::MUST_READ,
IOobject::NO_WRITE
);
const bool ok =
(
io.typeHeaderOk(false) // Preload header info
&& !io.headerClassName().empty() // Extra safety
&&
(
loadField(io)
|| loadField(io)
|| loadField(io)
|| loadField(io)
|| loadField(io)
)
);
if (ok)
{
++nLoaded;
}
else
{
DebugInfo
<< "readFields : failed to load " << fieldName << endl;
}
}
return nLoaded;
}
template
bool Foam::functionObjects::fvExpressionField::setField
(
GeoField& output,
const GeoField& evaluated,
const boolField& fieldMask
)
{
label numValuesChanged = 0;
// Internal field
if (fieldMask.empty())
{
// No field-mask - set all
numValuesChanged = output.size();
output.primitiveFieldRef() = evaluated;
}
else
{
auto& internal = output.primitiveFieldRef();
forAll(internal, idx)
{
if (fieldMask[idx])
{
internal[idx] = evaluated[idx];
++numValuesChanged;
}
}
}
// Boundary fields
forAll(evaluated.boundaryField(), patchi)
{
auto& pf = output.boundaryFieldRef()[patchi];
if (pf.patch().coupled())
{
pf == evaluated.boundaryField()[patchi];
}
}
doCorrectBoundaryConditions(true, output);
if (action_ == actionType::opModify && log)
{
const label numTotal = returnReduce(output.size(), sumOp