diff --git a/.gitignore b/.gitignore index b9ec77d5..1f4be394 100644 --- a/.gitignore +++ b/.gitignore @@ -148,12 +148,19 @@ moose/include/base/Precompiled.h.gch # clang .clangd +# direnv +.envrc + # OpenFOAM mesh object files test/**/*.obj # downloaded mesh tarballs test/tests/**/*.tar.gz +# OpenFOAM build files +test/OpenFOAM/**/lnInclude +test/OpenFOAM/**/linux* + framework/contrib/exodiff/exodiff # Mac garbage diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c24d3f5f..fdb7c938 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,3 +31,4 @@ repos: hooks: - id: remove-crlf - id: forbid-tabs + exclude: '.*\.mk$' diff --git a/Makefile b/Makefile index 5211c653..c809995e 100644 --- a/Makefile +++ b/Makefile @@ -60,3 +60,8 @@ include $(FRAMEWORK_DIR)/app.mk ############################################################################### # Additional special case targets should be added here + +# Add foam modules +# TODO: Reorganise build: consider single mk for all OpenFOAM modules +# as they are written. +include test/OpenFOAM/foam_modules.mk diff --git a/include/actions/AddFoamVariableAction.h b/include/actions/AddFoamVariableAction.h new file mode 100644 index 00000000..a87dd449 --- /dev/null +++ b/include/actions/AddFoamVariableAction.h @@ -0,0 +1,12 @@ +#include "InputParameters.h" +#include "MooseObjectAction.h" + +class AddFoamVariableAction : public MooseObjectAction +{ +public: + static InputParameters validParams(); + + AddFoamVariableAction(const InputParameters & parameters); + + virtual void act() override; +}; diff --git a/include/problems/FoamProblem.h b/include/problems/FoamProblem.h index b83590e4..be4d72b3 100644 --- a/include/problems/FoamProblem.h +++ b/include/problems/FoamProblem.h @@ -2,12 +2,14 @@ #include "FoamMesh.h" #include "FoamSolver.h" +#include "FoamVariableField.h" #include #include #include #include #include +#include class FoamProblem : public ExternalProblem { @@ -18,7 +20,7 @@ class FoamProblem : public ExternalProblem virtual void syncSolutions(Direction /* dir */) override; virtual bool converged(const unsigned int /* nl_sys_num */) override { return true; } virtual void addExternalVariables() override {}; - + virtual void initialSetup() override; using ExternalProblem::mesh; virtual FoamMesh const & mesh() const override { return *_foam_mesh; } virtual FoamMesh & mesh() override { return *_foam_mesh; } @@ -42,6 +44,10 @@ class FoamProblem : public ExternalProblem Hippo::FoamSolver & solver() { return _solver; } protected: + // check FoamVariables and print summarising table + void verifyFoamVariables(); + FoamMesh * _foam_mesh = nullptr; Hippo::FoamSolver _solver; + std::vector _foam_variables; }; diff --git a/include/variables/FoamFunctionObject.h b/include/variables/FoamFunctionObject.h new file mode 100644 index 00000000..7421659f --- /dev/null +++ b/include/variables/FoamFunctionObject.h @@ -0,0 +1,27 @@ +#pragma once + +#include "FoamVariableField.h" +#include "functionObject.H" + +#include + +// Class for mirroring functionObjects +class FoamFunctionObject : public FoamVariableField +{ +public: + explicit FoamFunctionObject(const InputParameters & params); + + // function that executes functionObject and transfers variable from + // OpenFOAM variable to MOOSE + virtual void transferVariable(); + + // Destroys functionObject pointer + ~FoamFunctionObject() { delete _shadow_fo; }; + +private: + // function to construct the functionObject + Foam::functionObject * _getFunctionObject(Foam::dictionary fo_dict); + + // The function object pointer + Foam::functionObject * _shadow_fo; +}; diff --git a/include/variables/FoamVariableField.h b/include/variables/FoamVariableField.h new file mode 100644 index 00000000..d0234da3 --- /dev/null +++ b/include/variables/FoamVariableField.h @@ -0,0 +1,32 @@ +#pragma once + +#include "Moose.h" +#include "MooseTypes.h" +#include "FoamMesh.h" + +class FoamVariableField : public MooseObject +{ +public: + static InputParameters validParams(); + + explicit FoamVariableField(const InputParameters & params); + + // transfer variable from OpenFOAM field to MOOSE variable + virtual void transferVariable(); + + // returns the name of the foam variable this object shadows + std::string foamVariable() const { return _foam_variable; }; + +protected: + // variable name or functionObject to be shadowed + std::string _foam_variable; + + // moose variable that shadows the OpenFOAM variable + MooseVariableFieldBase & _moose_var; + + // Create Auxilliary variable + MooseVariableFieldBase & createMooseVariable(std::string name, const InputParameters & params); + + // Pointer to the FoamMesh object + FoamMesh * _mesh; +}; diff --git a/src/actions/AddFoamVariableAction.C b/src/actions/AddFoamVariableAction.C new file mode 100644 index 00000000..0d66e33e --- /dev/null +++ b/src/actions/AddFoamVariableAction.C @@ -0,0 +1,34 @@ +#include "AddFoamVariableAction.h" +#include "FoamProblem.h" +#include "FoamVariableField.h" +#include "InputParameters.h" +#include "MooseObjectAction.h" +#include "Registry.h" + +registerMooseAction("hippoApp", AddFoamVariableAction, "add_foam_variable"); + +InputParameters +AddFoamVariableAction::validParams() +{ + auto params = MooseObjectAction::validParams(); + params.addClassDescription("Adds a FoamVariable that shadows an OpenFOAM scalar field."); + return params; +} + +AddFoamVariableAction::AddFoamVariableAction(const InputParameters & parameters) + : MooseObjectAction(parameters) +{ +} + +void +AddFoamVariableAction::act() +{ + if (_current_task == "add_foam_variable") + { + auto * foam_problem = dynamic_cast(_problem.get()); + if (!foam_problem) + mooseError("FoamVariables block must be used with FoamProblem"); + + foam_problem->addObject(_type, _name, _moose_object_pars, false); + } +} diff --git a/src/base/hippoApp.C b/src/base/hippoApp.C index 565416d9..4efceaaf 100644 --- a/src/base/hippoApp.C +++ b/src/base/hippoApp.C @@ -32,6 +32,11 @@ hippoApp::registerAll(Factory & f, ActionFactory & af, Syntax & syntax) Registry::registerActionsTo(af, {"hippoApp"}); /* register custom execute flags, action syntax, etc. here */ + + // Add input file syntax for the [FoamVariables] block + registerSyntaxTask("AddFoamVariableAction", "FoamVariables/*", "add_foam_variable"); + registerMooseObjectTask("add_foam_variable", FoamVariable, false); + addTaskDependency("add_external_aux_variables", "add_foam_variable"); } void diff --git a/src/problems/FoamProblem.C b/src/problems/FoamProblem.C index bcad5938..973bb1bc 100644 --- a/src/problems/FoamProblem.C +++ b/src/problems/FoamProblem.C @@ -6,6 +6,9 @@ #include #include #include +#include "FoamVariableField.h" +#include "InputParameters.h" +#include "VariadicTable.h" #include #include #include @@ -60,7 +63,11 @@ FoamProblem::validParams() FoamProblem::FoamProblem(InputParameters const & params) : ExternalProblem(params), _foam_mesh(dynamic_cast(&this->ExternalProblem::mesh())), - _solver(Foam::solver::New("fluid", _foam_mesh->fvMesh()).ptr()) + _solver(Foam::solver::New(_foam_mesh->fvMesh().time().controlDict().lookupOrDefault( + "solver", "fluid"), + _foam_mesh->fvMesh()) + .ptr()), + _foam_variables() { assert(_foam_mesh); @@ -117,6 +124,18 @@ FoamProblem::externalSolve() } } +void +FoamProblem::initialSetup() +{ + ExternalProblem::initialSetup(); + + // Get FoamVariables create by the action AddFoamVariableAction + TheWarehouse::Query query = theWarehouse().query().condition("FoamVariable"); + query.queryInto(_foam_variables); + + verifyFoamVariables(); +} + void FoamProblem::syncSolutions(Direction dir) { @@ -143,6 +162,12 @@ FoamProblem::syncSolutions(Direction dir) { syncFromOpenFoam(); } + + // Loop of shadowed variables and perform transfer + for (auto & var : _foam_variables) + { + var->transferVariable(); + } } else if (dir == ExternalProblem::Direction::TO_EXTERNAL_APP) { @@ -331,3 +356,19 @@ FoamProblem::getConstantMonomialVariableFromParameters(const std::string & param } return var; } + +void +FoamProblem::verifyFoamVariables() +{ + // Create table summarising FoamVariables + VariadicTable vt({ + "FoamVariable name", + "Type", + "Foam variable", + }); + for (auto & var : _foam_variables) + { + vt.addRow(var->name(), var->type(), var->foamVariable()); + } + vt.print(_console); +} diff --git a/src/variables/FoamFunctionObject.C b/src/variables/FoamFunctionObject.C new file mode 100644 index 00000000..0cf4d55d --- /dev/null +++ b/src/variables/FoamFunctionObject.C @@ -0,0 +1,58 @@ +#include "FoamVariableField.h" +#include "FoamFunctionObject.h" +#include "InputParameters.h" +#include "Registry.h" +#include "SystemBase.h" +#include "dictionary.H" +#include "functionObject.H" +// #include "wallHeatFlux.h" +#include + +registerMooseObject("hippoApp", FoamFunctionObject); + +FoamFunctionObject::FoamFunctionObject(const InputParameters & params) : FoamVariableField(params) +{ + auto & mesh = _mesh->fvMesh(); + + // construct input Foam dictionary for the functionObject + auto fo_dict = mesh.time().controlDict().lookupOrDefault(_foam_variable, Foam::dictionary()); + + // create patch names where functionObject applies + // TODO: when volumetric mirror is implemented some of this may need to be + // put in the _getFunctionObject function. + std::vector patch_ids{_mesh->getSubdomainList()}; + Foam::wordList patch_names; + for (auto id : patch_ids) + patch_names.append(mesh.boundaryMesh()[id].name()); + + fo_dict.set("patches", patch_names); + fo_dict.set("writeToFile", false); + + // construct functionObject and execute + _shadow_fo = _getFunctionObject(fo_dict); + _shadow_fo->execute(); +} + +Foam::functionObject * +FoamFunctionObject::_getFunctionObject(Foam::dictionary fo_dict) +{ + // Create polymorphic pointer to each type of valid functionObject + if (_foam_variable == "wallHeatFlux") + { + Foam::functionObjects::wallHeatFlux * whf_func = + new Foam::functionObjects::wallHeatFlux("wallHeatFlux", _mesh->fvMesh().time(), fo_dict); + return static_cast(whf_func); + } + else + { + mooseError("Only wallHeatFlux functionObject is currently supported"); + } +} + +void +FoamFunctionObject::transferVariable() +{ + // execute functionObject before transfer + _shadow_fo->execute(); + FoamVariableField::transferVariable(); +} diff --git a/src/variables/FoamVariableField.C b/src/variables/FoamVariableField.C new file mode 100644 index 00000000..1f0a6437 --- /dev/null +++ b/src/variables/FoamVariableField.C @@ -0,0 +1,92 @@ +#include "FoamVariableField.h" +#include "FoamProblem.h" +#include "InputParameters.h" +#include "MooseObject.h" +#include "MooseTypes.h" +#include "MooseVariableFieldBase.h" +#include "MooseVariableFieldBase.h" + +registerMooseObject("hippoApp", FoamVariableField); + +InputParameters +FoamVariableField::validParams() +{ + auto params = MooseObject::validParams(); + + params.addRequiredParam("foam_variable", + "OpenFOAM variable or functionObject to be shadowed"); + + params.registerBase("FoamVariable"); + params.registerSystemAttributeName("FoamVariable"); + return params; +} + +MooseVariableFieldBase & +FoamVariableField::createMooseVariable(std::string name, const InputParameters & params) +{ + // TODO: Add other parameters from variable instantiations such as Boundary restrictions + auto & problem = getMooseApp().feProblem(); + + auto var_params = _factory.getValidParams("MooseVariable"); + + // The MOOSE variable has to be constant monomial + var_params.set("order") = "CONSTANT"; + var_params.set("family") = "MONOMIAL"; + + // Create the Aux variable + problem.addAuxVariable("MooseVariable", name, var_params); + + THREAD_ID tid = parameters().get("_tid"); + + // return reference to moose variable + return problem.getVariable(tid, name, Moose::VarKindType::VAR_AUXILIARY); +} + +FoamVariableField::FoamVariableField(const InputParameters & params) + : MooseObject(params), + _foam_variable(params.get("foam_variable")), + _moose_var(createMooseVariable(name(), params)) +{ + auto * problem = dynamic_cast(&getMooseApp().feProblem()); + if (!problem) + mooseError("This Variable can only be used with FoamProblem"); + + _mesh = &problem->mesh(); +} + +void +FoamVariableField::transferVariable() +{ + // TODO: some recent changes to FoamMesh can improve this + // TODO: may be useful to create a base class for getting data to and from MOOSE/OpenFOAM + + auto subdomains = _mesh->getSubdomainList(); + auto & foam_mesh = _mesh->fvMesh(); + std::vector patch_counts(subdomains.size() + 1, 0); + std::vector data; + + // loop over subdomains and construct vector with boundary values + for (auto i = 0U; i < subdomains.size(); ++i) + { + auto patch_id = subdomains[i]; + auto & var = foam_mesh.boundary()[patch_id].lookupPatchField( + _foam_variable); + std::copy(var.begin(), var.end(), std::back_inserter(data)); + patch_counts[i] = var.size(); + } + + // assign values to each element + std::exclusive_scan(patch_counts.begin(), patch_counts.end(), patch_counts.begin(), 0); + for (auto i = 0U; i < subdomains.size(); ++i) + { + for (auto elem = patch_counts[i]; elem < patch_counts[i + 1]; ++elem) + { + auto elem_ptr = _mesh->getElemPtr(elem + _mesh->rank_element_offset); + assert(elem_ptr); + auto dof_t = elem_ptr->dof_number(_moose_var.sys().number(), _moose_var.number(), 0); + _moose_var.sys().solution().set(dof_t, data[elem]); + } + } + + _moose_var.sys().solution().close(); +} diff --git a/test/OpenFOAM/foam_modules.mk b/test/OpenFOAM/foam_modules.mk new file mode 100644 index 00000000..401c4c31 --- /dev/null +++ b/test/OpenFOAM/foam_modules.mk @@ -0,0 +1,7 @@ +# Build custom OpenFOAM source files: this should be improved in future +all: build_foam_tests + +MAKE=wmake +build_foam_tests: + $(info Building Hippo's OpenFOAM test modules) + @$(MAKE) -j $(MOOSE_JOBS) test/OpenFOAM/modules/transferTestSolver/ 1>/dev/null diff --git a/test/OpenFOAM/modules/transferTestSolver/Make/files b/test/OpenFOAM/modules/transferTestSolver/Make/files new file mode 100644 index 00000000..4d6d664f --- /dev/null +++ b/test/OpenFOAM/modules/transferTestSolver/Make/files @@ -0,0 +1,3 @@ +SOURCE += transferTestSolver.C + +LIB = $(FOAM_USER_LIBBIN)/libtransferTestSolver diff --git a/test/OpenFOAM/modules/transferTestSolver/Make/options b/test/OpenFOAM/modules/transferTestSolver/Make/options new file mode 100644 index 00000000..cc845ca8 --- /dev/null +++ b/test/OpenFOAM/modules/transferTestSolver/Make/options @@ -0,0 +1,20 @@ +EXE_INC = \ + -I$(LIB_SRC)/physicalProperties/lnInclude \ + -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \ + -I$(LIB_SRC)/thermophysicalModels/solidThermo/lnInclude \ + -I$(LIB_SRC)/ThermophysicalTransportModels/thermophysicalTransportModel/lnInclude \ + -I$(LIB_SRC)/ThermophysicalTransportModels/solid/lnInclude \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude \ + -I$(LIB_SRC)/sampling/lnInclude + +LIB_LIBS = \ + -lsolidThermo \ + -lsolidThermophysicalTransportModels \ + -lcoupledThermophysicalTransportModels \ + -lspecie \ + -lfiniteVolume \ + -lmeshTools \ + -lsampling \ + -lfvModels \ + -lfvConstraints diff --git a/test/OpenFOAM/modules/transferTestSolver/transferTestSolver.C b/test/OpenFOAM/modules/transferTestSolver/transferTestSolver.C new file mode 100644 index 00000000..80adcbae --- /dev/null +++ b/test/OpenFOAM/modules/transferTestSolver/transferTestSolver.C @@ -0,0 +1,178 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Copyright (C) 2022-2024 OpenFOAM Foundation + \\/ 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 . + +\*---------------------------------------------------------------------------*/ + +#include "dimensionSets.H" +#include "fvMesh.H" +#include "transferTestSolver.H" +#include "fvMeshMover.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace solvers +{ +defineTypeNameAndDebug(transferTestSolver, 0); +addToRunTimeSelectionTable(solver, transferTestSolver, fvMesh); +} +} + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * // + +bool +Foam::solvers::transferTestSolver::dependenciesModified() const +{ + return runTime.controlDict().modified(); +} + +bool +Foam::solvers::transferTestSolver::read() +{ + solver::read(); + + maxDeltaT_ = runTime.controlDict().found("maxDeltaT") + ? runTime.controlDict().lookup("maxDeltaT", runTime.userUnits()) + : vGreat; + + return true; +} + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // +// Solver based on solid.C module +Foam::solvers::transferTestSolver::transferTestSolver(fvMesh & mesh, autoPtr thermoPtr) + : solver(mesh), + + thermoPtr_(thermoPtr), + thermo_(thermoPtr_()), + + T_(IOobject("T", mesh.time().name(), mesh, IOobject::NO_READ, IOobject::AUTO_WRITE), mesh), + + thermophysicalTransport(solidThermophysicalTransportModel::New(thermo_)), + thermo(thermo_), + T(T_) +{ + thermo.validate("solid", "h", "e"); +} + +Foam::solvers::transferTestSolver::transferTestSolver(fvMesh & mesh) + : transferTestSolver(mesh, solidThermo::New(mesh)) +{ + // Read the controls + read(); +} + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::solvers::transferTestSolver::~transferTestSolver() {} + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +Foam::scalar +Foam::solvers::transferTestSolver::maxDeltaT() const +{ + return min(fvModels().maxDeltaT(), maxDeltaT_); +} + +void +Foam::solvers::transferTestSolver::preSolve() +{ + fvModels().preUpdateMesh(); + + // Update the mesh for topology change, mesh to mesh mapping + mesh_.update(); +} + +void +Foam::solvers::transferTestSolver::moveMesh() +{ + if (pimple.firstIter() || pimple.moveMeshOuterCorrectors()) + { + if (!mesh_.mover().solidBody()) + { + FatalErrorInFunction << "Region " << name() << " of type " << type() + << " does not support non-solid body mesh motion" << exit(FatalError); + } + + mesh_.move(); + } +} + +void +Foam::solvers::transferTestSolver::motionCorrector() +{ +} + +void +Foam::solvers::transferTestSolver::prePredictor() +{ +} + +void +Foam::solvers::transferTestSolver::momentumPredictor() +{ +} + +void +Foam::solvers::transferTestSolver::thermophysicalPredictor() +{ + // To set temperature for testing, internal energy must be set. The + // thermo_.correct() call calculates Temperature. + + // Get e and Cv + volScalarField & e = thermo_.he(); + const volScalarField & Cv = thermo_.Cv(); + + // Set e to Cv*(xy + yz + xz)t which gives a non-uniform be first order value of wall heat flux at + // all boundaries. + dimensioned t( + "t", T_.dimensions() / (dimLength * dimLength), mesh_.time().userTimeValue()); + auto & coords = mesh_.C(); + e = Cv * (dimensionedScalar(T.dimensions(), 0.01) + + (coords.component(0) * coords.component(1) + coords.component(1) * coords.component(2) + + coords.component(2) * coords.component(0)) * + t); + + thermo_.correct(); +} + +void +Foam::solvers::transferTestSolver::pressureCorrector() +{ +} + +void +Foam::solvers::transferTestSolver::postCorrector() +{ +} + +void +Foam::solvers::transferTestSolver::postSolve() +{ +} + +// ************************************************************************* // diff --git a/test/OpenFOAM/modules/transferTestSolver/transferTestSolver.H b/test/OpenFOAM/modules/transferTestSolver/transferTestSolver.H new file mode 100644 index 00000000..f15ecd66 --- /dev/null +++ b/test/OpenFOAM/modules/transferTestSolver/transferTestSolver.H @@ -0,0 +1,147 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Copyright (C) 2022-2023 OpenFOAM Foundation + \\/ 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 . + +Class + Foam::solvers::transferTestSolver + +Description + Solver module for to test transfers between OpenFOAM and MOOSE. Based on Solid + solver + +SourceFiles + transferTestSolver.C + +\*---------------------------------------------------------------------------*/ + +#pragma once + +#include "solver.H" +#include "solidThermophysicalTransportModel.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace solvers +{ + +/*---------------------------------------------------------------------------*\ + Class transferTestSolver Declaration +\*---------------------------------------------------------------------------*/ + +class transferTestSolver : public solver +{ + +protected: + // Control parameters + scalar maxDeltaT_; + + // Thermophysical properties + autoPtr thermoPtr_; + + solidThermo & thermo_; + + volScalarField T_; + + autoPtr thermophysicalTransport; + + // Protected Member Functions + + //- Return true if the solver's dependencies have been modified + virtual bool dependenciesModified() const; + + //- Read controls + virtual bool read(); + +public: + // Public Data + // reference to thermophysical properties + const solidThermo & thermo; + + //- Reference to the temperature field + const volScalarField & T; + + //- Runtime type information + TypeName("transferTestSolver"); + + // Constructors + + //- Construct from region mesh + transferTestSolver(fvMesh & mesh, autoPtr thermoPtr); + + transferTestSolver(fvMesh & mesh); + + //- Disallow default bitwise copy construction + transferTestSolver(const transferTestSolver &) = delete; + + //- Destructor + virtual ~transferTestSolver(); + + // Member Functions + + //- Return the current maximum time-step for stable solution + virtual scalar maxDeltaT() const; + + //- Called at the start of the time-step, before the PIMPLE loop + virtual void preSolve(); + + //- Called at the start of the PIMPLE loop to move the mesh + virtual void moveMesh(); + + //- Corrections that follow mesh motion + virtual void motionCorrector(); + + //- Called at the beginning of the PIMPLE loop + virtual void prePredictor(); + + //- Construct and optionally solve the momentum equation + virtual void momentumPredictor(); + + //- Construct and solve the energy equation, + // convert to temperature + // and update thermophysical and transport properties + virtual void thermophysicalPredictor(); + + //- Construct and solve the pressure equation in the PISO loop + virtual void pressureCorrector(); + + //- Correct the thermophysical transport modelling + virtual void postCorrector(); + + //- Called after the PIMPLE loop at the end of the time-step + virtual void postSolve(); + + // Member Operators + + //- Disallow default bitwise assignment + void operator=(const transferTestSolver &) = delete; +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace solvers +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// ************************************************************************* // diff --git a/test/python/read_hippo_data.py b/test/python/read_hippo_data.py index 8c586b23..d3a8b5e7 100644 --- a/test/python/read_hippo_data.py +++ b/test/python/read_hippo_data.py @@ -4,6 +4,10 @@ import numpy as np import pyvista as pv +def get_exodus_times(exo_file): + reader: pv.ExodusIIReader = pv.get_reader(exo_file) + return reader.time_values + def read_moose_exodus_data(exo_file, time, variable, diff --git a/test/tests/actions/foam_variable/foam/0/T b/test/tests/actions/foam_variable/foam/0/T new file mode 100644 index 00000000..f8312bb2 --- /dev/null +++ b/test/tests/actions/foam_variable/foam/0/T @@ -0,0 +1,56 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 10 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + location "0"; + object T; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +internalField uniform 0.1; + +boundaryField +{ + left + { + type calculated; + value uniform 0.; + } + right + { + type calculated; + value uniform 0.; + } + top + { + type calculated; + value uniform 0.; + } + bottom + { + type calculated; + value uniform 0.; + } + back + { + type calculated; + value uniform 0.; + } + front + { + type calculated; + value uniform 0.; + } +} + + +// ************************************************************************* // diff --git a/test/tests/actions/foam_variable/foam/constant/physicalProperties b/test/tests/actions/foam_variable/foam/constant/physicalProperties new file mode 100644 index 00000000..96a14c15 --- /dev/null +++ b/test/tests/actions/foam_variable/foam/constant/physicalProperties @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 10 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object physicalProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +thermoType +{ + type heSolidThermo; + mixture pureMixture; + transport constIsoSolid; + thermo eConst; + equationOfState rhoConst; + specie specie; + energy sensibleInternalEnergy; +} + +mixture +{ + specie + { + molWeight 1; + } + thermodynamics + { + Cv 1; // Specific heat capacity [J/(kg·K)] + Hf 1; // Heat of formation [J/kg] + Tref 0; + } + transport + { + kappa 1; // Thermal conductivity [W/(m·K)] + } + equationOfState + { + rho 1; // Density [kg/m^3] + } +} + + +// ************************************************************************* // diff --git a/test/tests/actions/foam_variable/foam/system/blockMeshDict b/test/tests/actions/foam_variable/foam/system/blockMeshDict new file mode 100644 index 00000000..face9ea6 --- /dev/null +++ b/test/tests/actions/foam_variable/foam/system/blockMeshDict @@ -0,0 +1,85 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +vertices +( + ( 0.0 0.0 0.0 ) + ( 10.0 0.0 0.0 ) + ( 10.0 1.0 0.0 ) + ( 0.0 1.0 0.0 ) + + ( 0.0 0.0 1.0) + ( 10.0 0.0 1.0) + ( 10.0 1.0 1.0) + ( 0.0 1.0 1.0) +); + +blocks +( + hex (0 1 2 3 4 5 6 7) (50 1 1) simpleGrading (25 1 1) +); + +boundary +( + + // interface + left + { + type wall; + faces + ( + (4 7 3 0) + ); + } + + right + { + type wall; + faces + ( + (6 5 1 2) + ); + } + + top + { + type wall; + faces + ( + (2 3 7 6) + ); + } + + front + { + type wall; + faces + ( + (3 2 1 0) + ); + } + + bottom + { + type wall; + faces + ( + (0 1 5 4) + ); + } + + back + { + type wall; + faces + ( + (4 5 6 7) + ); + } + +); diff --git a/test/tests/actions/foam_variable/foam/system/controlDict b/test/tests/actions/foam_variable/foam/system/controlDict new file mode 100644 index 00000000..0383dd23 --- /dev/null +++ b/test/tests/actions/foam_variable/foam/system/controlDict @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 10 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solver transferTestSolver; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 0.32; + +deltaT 0.01; + +writeControl timeStep; + +writeInterval 1; + +writeFormat ascii; + +writePrecision 20; + +writeCompression off; + +timeFormat general; + +timePrecision 20; + +runTimeModifiable true; + +// ************************************************************************* // diff --git a/test/tests/actions/foam_variable/foam/system/fvSchemes b/test/tests/actions/foam_variable/foam/system/fvSchemes new file mode 100644 index 00000000..787f3b83 --- /dev/null +++ b/test/tests/actions/foam_variable/foam/system/fvSchemes @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 12 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + default none; + + div(phi,U) Gauss linear; + div(phi,K) Gauss linear; + div(phi,h) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} + +// ************************************************************************* // diff --git a/test/tests/actions/foam_variable/foam/system/fvSolution b/test/tests/actions/foam_variable/foam/system/fvSolution new file mode 100644 index 00000000..61143b21 --- /dev/null +++ b/test/tests/actions/foam_variable/foam/system/fvSolution @@ -0,0 +1,61 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 12 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + rho + { + solver diagonal; + } + + rhoFinal + { + $rho; + } + + + "(U|h|p_rgh)" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-8; + relTol 1e-8; + } + + "(U|h|p_rgh)Final" + { + $U; + tolerance 1e-8; + relTol 1e-8; + } +} + +PIMPLE +{ + momentumPredictor yes; + pRefCell 0; + pRefValue 0; +} + +relaxationFactors +{ + equations + { + h 1; + U 1; + } +} + +// ************************************************************************* // diff --git a/test/tests/actions/foam_variable/main.i b/test/tests/actions/foam_variable/main.i new file mode 100644 index 00000000..ab7e7313 --- /dev/null +++ b/test/tests/actions/foam_variable/main.i @@ -0,0 +1,38 @@ +[Mesh] + type = FoamMesh + case = 'foam' + foam_patch = 'left right bottom top back front' +[] + +[Variables] + [dummy] + family = MONOMIAL + order = CONSTANT + initial_condition = 999 + [] +[] + +[FoamVariables] + [T_shadow] + type = FoamVariableField + foam_variable = 'T' + [] +[] +[Problem] + type = FoamProblem + # Take the boundary temperature from OpenFOAM and set it on the MOOSE mesh. +[] + +[Executioner] + type = Transient + end_time = 0.32 + [TimeSteppers] + [foam] + type = FoamControlledTimeStepper + [] + [] +[] + +[Outputs] + exodus = true +[] diff --git a/test/tests/actions/foam_variable/tests b/test/tests/actions/foam_variable/tests new file mode 100644 index 00000000..1046656a --- /dev/null +++ b/test/tests/actions/foam_variable/tests @@ -0,0 +1,22 @@ +[Tests] + [transfer_test] + [setup] + type = RunCommand + command = 'bash -c "foamCleanCase -case foam && blockMesh -case foam"' + [] + [run] + type = RunApp + input = main.i + prereq = transfer_test/setup + allow_warnings = true + [] + [err_problem] + type = RunException + input = main.i + prereq = transfer_test/setup + expect_err = "FoamVariables block must be used with FoamProblem" + cli_args = "Problem/type=FEProblem" + allow_warnings = true + [] + [] +[] diff --git a/test/tests/variables/foam_variable/foam/0/T b/test/tests/variables/foam_variable/foam/0/T new file mode 100644 index 00000000..f8312bb2 --- /dev/null +++ b/test/tests/variables/foam_variable/foam/0/T @@ -0,0 +1,56 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 10 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class volScalarField; + location "0"; + object T; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +internalField uniform 0.1; + +boundaryField +{ + left + { + type calculated; + value uniform 0.; + } + right + { + type calculated; + value uniform 0.; + } + top + { + type calculated; + value uniform 0.; + } + bottom + { + type calculated; + value uniform 0.; + } + back + { + type calculated; + value uniform 0.; + } + front + { + type calculated; + value uniform 0.; + } +} + + +// ************************************************************************* // diff --git a/test/tests/variables/foam_variable/foam/constant/physicalProperties b/test/tests/variables/foam_variable/foam/constant/physicalProperties new file mode 100644 index 00000000..96a14c15 --- /dev/null +++ b/test/tests/variables/foam_variable/foam/constant/physicalProperties @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 10 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + location "constant"; + object physicalProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +thermoType +{ + type heSolidThermo; + mixture pureMixture; + transport constIsoSolid; + thermo eConst; + equationOfState rhoConst; + specie specie; + energy sensibleInternalEnergy; +} + +mixture +{ + specie + { + molWeight 1; + } + thermodynamics + { + Cv 1; // Specific heat capacity [J/(kg·K)] + Hf 1; // Heat of formation [J/kg] + Tref 0; + } + transport + { + kappa 1; // Thermal conductivity [W/(m·K)] + } + equationOfState + { + rho 1; // Density [kg/m^3] + } +} + + +// ************************************************************************* // diff --git a/test/tests/variables/foam_variable/foam/system/blockMeshDict b/test/tests/variables/foam_variable/foam/system/blockMeshDict new file mode 100644 index 00000000..face9ea6 --- /dev/null +++ b/test/tests/variables/foam_variable/foam/system/blockMeshDict @@ -0,0 +1,85 @@ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} + +vertices +( + ( 0.0 0.0 0.0 ) + ( 10.0 0.0 0.0 ) + ( 10.0 1.0 0.0 ) + ( 0.0 1.0 0.0 ) + + ( 0.0 0.0 1.0) + ( 10.0 0.0 1.0) + ( 10.0 1.0 1.0) + ( 0.0 1.0 1.0) +); + +blocks +( + hex (0 1 2 3 4 5 6 7) (50 1 1) simpleGrading (25 1 1) +); + +boundary +( + + // interface + left + { + type wall; + faces + ( + (4 7 3 0) + ); + } + + right + { + type wall; + faces + ( + (6 5 1 2) + ); + } + + top + { + type wall; + faces + ( + (2 3 7 6) + ); + } + + front + { + type wall; + faces + ( + (3 2 1 0) + ); + } + + bottom + { + type wall; + faces + ( + (0 1 5 4) + ); + } + + back + { + type wall; + faces + ( + (4 5 6 7) + ); + } + +); diff --git a/test/tests/variables/foam_variable/foam/system/controlDict b/test/tests/variables/foam_variable/foam/system/controlDict new file mode 100644 index 00000000..0383dd23 --- /dev/null +++ b/test/tests/variables/foam_variable/foam/system/controlDict @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 10 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solver transferTestSolver; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 0.32; + +deltaT 0.01; + +writeControl timeStep; + +writeInterval 1; + +writeFormat ascii; + +writePrecision 20; + +writeCompression off; + +timeFormat general; + +timePrecision 20; + +runTimeModifiable true; + +// ************************************************************************* // diff --git a/test/tests/variables/foam_variable/foam/system/fvSchemes b/test/tests/variables/foam_variable/foam/system/fvSchemes new file mode 100644 index 00000000..787f3b83 --- /dev/null +++ b/test/tests/variables/foam_variable/foam/system/fvSchemes @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 12 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + default none; + + div(phi,U) Gauss linear; + div(phi,K) Gauss linear; + div(phi,h) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} + +// ************************************************************************* // diff --git a/test/tests/variables/foam_variable/foam/system/fvSolution b/test/tests/variables/foam_variable/foam/system/fvSolution new file mode 100644 index 00000000..61143b21 --- /dev/null +++ b/test/tests/variables/foam_variable/foam/system/fvSolution @@ -0,0 +1,61 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 12 + \\/ M anipulation | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + format ascii; + class dictionary; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + rho + { + solver diagonal; + } + + rhoFinal + { + $rho; + } + + + "(U|h|p_rgh)" + { + solver PBiCGStab; + preconditioner DILU; + tolerance 1e-8; + relTol 1e-8; + } + + "(U|h|p_rgh)Final" + { + $U; + tolerance 1e-8; + relTol 1e-8; + } +} + +PIMPLE +{ + momentumPredictor yes; + pRefCell 0; + pRefValue 0; +} + +relaxationFactors +{ + equations + { + h 1; + U 1; + } +} + +// ************************************************************************* // diff --git a/test/tests/variables/foam_variable/main.i b/test/tests/variables/foam_variable/main.i new file mode 100644 index 00000000..dd300e45 --- /dev/null +++ b/test/tests/variables/foam_variable/main.i @@ -0,0 +1,47 @@ +[Mesh] + type = FoamMesh + case = 'foam' + foam_patch = 'left right bottom top back front' +[] + +[Variables] + [dummy] + family = MONOMIAL + order = CONSTANT + initial_condition = 999 + [] +[] + +[FoamVariables] + [T_shadow] + type = FoamVariableField + foam_variable = 'T' + [] + [e_shadow] + type = FoamVariableField + foam_variable = 'e' + [] + [whf_shadow] + type = FoamFunctionObject + foam_variable = 'wallHeatFlux' + [] +[] + +[Problem] + type = FoamProblem + # Take the boundary temperature from OpenFOAM and set it on the MOOSE mesh. +[] + +[Executioner] + type = Transient + end_time = 0.32 + [TimeSteppers] + [foam] + type = FoamControlledTimeStepper + [] + [] +[] + +[Outputs] + exodus = true +[] diff --git a/test/tests/variables/foam_variable/test.py b/test/tests/variables/foam_variable/test.py new file mode 100644 index 00000000..0155c86e --- /dev/null +++ b/test/tests/variables/foam_variable/test.py @@ -0,0 +1,50 @@ +"""Tests for shadowing scalar variables and function objects using MOOSE +""" + +import unittest + +import numpy as np + +from read_hippo_data import read_moose_exodus_data, get_exodus_times #pylint: disable=E0401 + +class TestFoamVariableTransfer(unittest.TestCase): + """Test class for shadowing scalar fields in Hippo.""" + def test_variable_transfer(self): + """Test case for shadowing a volScalarField.""" + + times = get_exodus_times("main_out.e")[1:] + for time in times: + coords, temp = read_moose_exodus_data('main_out.e', + time, + variable="T_shadow") + + temp_ref = 0.01 + (coords['x']*coords['y'] + coords['z']*coords['y'] + + coords['z']*coords['x'])*time + temp_diff_max = np.argmax(abs(temp-temp_ref)) + assert np.allclose(temp_ref, temp, rtol=1e-7, atol=1e-12),\ + (f"Max diff ({time}): {abs(temp-temp_ref).max()} " + f"{temp[temp_diff_max]} {temp_ref[temp_diff_max]}") + + def test_wall_heat_flux_transfer(self): + """Test case for shadowing the output of the wallHeatFlux functionObject.""" + times = get_exodus_times("main_out.e")[1:] + for time in times: + coords, whf = read_moose_exodus_data('main_out.e', + time, + variable="whf_shadow") + + sum_ = 0 + whf_ref = np.zeros_like(whf) + for comp in ('x', 'y', 'z'): + low = coords[comp](coords[comp].max()-1e-6) + sum_ += np.sum(low) + np.sum(high) + c = ('y', 'z') if comp == 'x' else ('z', 'x') if comp == 'y' else ('x', 'y') + whf_ref[low] = -time*(coords[c[0]][low] + coords[c[1]][low]) + whf_ref[high] = time*(coords[c[0]][high] + coords[c[1]][high]) + + assert sum_ == whf.size, f"{sum_} {whf.size}" + + whf_diff_max = np.argmax(abs(whf-whf_ref)) + assert np.allclose(whf_ref, whf, rtol=1e-7, atol=1e-12),\ + f"Max diff ({time}): {abs(whf-whf_ref)[whf_diff_max]} {whf[whf_diff_max]}" diff --git a/test/tests/variables/foam_variable/tests b/test/tests/variables/foam_variable/tests new file mode 100644 index 00000000..9ff41bcf --- /dev/null +++ b/test/tests/variables/foam_variable/tests @@ -0,0 +1,19 @@ +[Tests] + [transfer_test] + [setup] + type = RunCommand + command = 'bash -c "foamCleanCase -case foam && blockMesh -case foam"' + [] + [run] + type = RunApp + input = main.i + prereq = transfer_test/setup + allow_warnings = true + [] + [verify] + type = PythonUnitTest + input = test.py + prereq = transfer_test/run + [] + [] +[]