/*---------------------------------------------------------------------------*\ ========= | \\ / 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) 2022-2024 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 . Application setFields Group grpPreProcessingUtilities Description Set values on a selected set of cells/patch-faces via a dictionary. \*---------------------------------------------------------------------------*/ #include "argList.H" #include "timeSelector.H" #include "Time.H" #include "fvMesh.H" #include "faMesh.H" #include "topoSetSource.H" #include "cellSet.H" #include "faceSet.H" #include "volFields.H" #include "areaFields.H" #include "coupledFvPatch.H" #include "coupledFaPatch.H" using namespace Foam; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // //- Simple tuple of field type and name (read from stream) class fieldDescription { word type_; word name_; public: const word& type() const noexcept { return type_; } const word& name() const noexcept { return name_; } explicit fieldDescription(Istream& is) { is >> type_; is >> name_; // Eg, read as "volScalarFieldValue", but change to "volScalarField" if (type_.ends_with("Value")) { type_.erase(type_.size()-5); } } }; // Consume unused field information template bool consumeUnusedType(const fieldDescription& fieldDesc, Istream& is) { typedef GeometricField fieldType1; typedef GeometricField fieldType2; //? typedef GeometricField fieldType3; //? typedef GeometricField fieldType4; if ( fieldDesc.type() == fieldType1::typeName || fieldDesc.type() == fieldType2::typeName ) { (void) pTraits(is); return true; } return false; } // Consume unused field information static bool consumeUnused(const fieldDescription& fieldDesc, Istream& is) { return ( consumeUnusedType(fieldDesc, is) || consumeUnusedType(fieldDesc, is) || consumeUnusedType(fieldDesc, is) || consumeUnusedType(fieldDesc, is) || consumeUnusedType(fieldDesc, is) ); } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // Setting volume fields template bool setCellFieldType ( const fieldDescription& fieldDesc, const fvMesh& mesh, const labelList& selectedCells, Istream& is ) { typedef GeometricField fieldType; if (fieldDesc.type() != fieldType::typeName) { return false; } // Get value from stream const Type fieldValue = pTraits(is); // Check the current time directory IOobject fieldHeader ( fieldDesc.name(), mesh.thisDb().time().timeName(), mesh.thisDb(), IOobject::MUST_READ ); bool found = fieldHeader.typeHeaderOk(true); if (!found) { // Fallback to "constant" directory fieldHeader = IOobject ( fieldDesc.name(), mesh.thisDb().time().constant(), mesh.thisDb(), IOobject::MUST_READ ); found = fieldHeader.typeHeaderOk(true); } // Field exists if (found) { Info<< " - set internal values of " << fieldHeader.headerClassName() << ": " << fieldDesc.name() << " = " << fieldValue << endl; fieldType field(fieldHeader, mesh, false); if (isNull(selectedCells) || selectedCells.size() == field.size()) { field.primitiveFieldRef() = fieldValue; } else { for (const label celli : selectedCells) { field[celli] = fieldValue; } } // Make boundary fields consistent - treat like zeroGradient for (auto& pfld : field.boundaryFieldRef()) { pfld = pfld.patchInternalField(); } // Handle any e.g. halo-swaps field.boundaryFieldRef().template evaluateCoupled(); if (!field.write()) { FatalErrorInFunction << "Failed writing field " << field.name() << endl; } } else { Warning << "Field " << fieldDesc.name() << " not found" << endl; } return true; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // Setting finite-area face fields template bool setAreaFieldType ( const fieldDescription& fieldDesc, const faMesh& mesh, const labelList& selectedFaces, Istream& is ) { typedef GeometricField fieldType; if (fieldDesc.type() != fieldType::typeName) { return false; } // Get value from stream const Type fieldValue = pTraits(is); // Check the current time directory IOobject fieldHeader ( fieldDesc.name(), mesh.thisDb().time().timeName(), mesh.thisDb(), IOobject::MUST_READ ); bool found = fieldHeader.typeHeaderOk(true); if (!found) { // Fallback to "constant" directory fieldHeader = IOobject ( fieldDesc.name(), mesh.thisDb().time().constant(), mesh.thisDb(), IOobject::MUST_READ ); found = fieldHeader.typeHeaderOk(true); } // Field exists if (found) { Info<< " - set internal values of " << fieldHeader.headerClassName() << ": " << fieldDesc.name() << " = " << fieldValue << endl; fieldType field(fieldHeader, mesh); if (isNull(selectedFaces) || selectedFaces.size() == field.size()) { field.primitiveFieldRef() = fieldValue; } else { for (const label facei : selectedFaces) { field[facei] = fieldValue; } } // Handle any e.g. halo-swaps field.boundaryFieldRef().template evaluateCoupled(); if (!field.write()) { FatalErrorInFunction << "Failed writing field " << field.name() << endl; } } else { Warning << "Field " << fieldDesc.name() << " not found" << endl; } return true; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // Setting volume boundary fields template bool setFaceFieldType ( const fieldDescription& fieldDesc, const fvMesh& mesh, const labelList& selectedFaces, Istream& is ) { typedef GeometricField fieldType; if (fieldDesc.type() != fieldType::typeName) { return false; } // Get value from stream const Type fieldValue = pTraits(is); // Check the current time directory IOobject fieldHeader ( fieldDesc.name(), mesh.thisDb().time().timeName(), mesh.thisDb(), IOobject::MUST_READ ); bool found = fieldHeader.typeHeaderOk(true); if (!found) { // Fallback to "constant" directory fieldHeader = IOobject ( fieldDesc.name(), mesh.thisDb().time().constant(), mesh.thisDb(), IOobject::MUST_READ ); found = fieldHeader.typeHeaderOk(true); } // Field exists if (found) { Info<< " - set boundary values of " << fieldHeader.headerClassName() << ": " << fieldDesc.name() << " = " << fieldValue << endl; fieldType field(fieldHeader, mesh); // Create flat list of selected faces and their value. Field allBoundaryValues(mesh.nBoundaryFaces()); forAll(field.boundaryField(), patchi) { SubField ( allBoundaryValues, field.boundaryField()[patchi].size(), field.boundaryField()[patchi].patch().start() - mesh.nInternalFaces() ) = field.boundaryField()[patchi]; } // Override unsigned hasWarned = 0; labelList nChanged ( returnReduce(field.boundaryField().size(), maxOp