diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
index 85a97343..cf98addc 100644
--- a/.github/workflows/CI.yml
+++ b/.github/workflows/CI.yml
@@ -42,4 +42,4 @@ jobs:
cd userCase
blockMesh
decomposePar
- mpirun -n 6 --oversubscribe --allow-run-as-root additiveFoam -parallel
+ mpirun -n 8 --oversubscribe --allow-run-as-root additiveFoam -parallel
diff --git a/Allwmake b/Allwmake
index 830f8594..c00f9c61 100755
--- a/Allwmake
+++ b/Allwmake
@@ -10,7 +10,7 @@ cd ${0%/*} || exit 1 # Run from this directory
#------------------------------------------------------------------------------
# AdditiveFOAM build information
-GIT_DESCRIBE=$(git describe --tags --always 2>/dev/null) \
+GIT_DESCRIBE=$(git describe --tags --always --dirty 2>/dev/null) \
|| GIT_DESCRIBE="undefined"
GIT_SHA1=$(git rev-parse HEAD 2>/dev/null) \
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ab881938..1c5ef7f4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,91 @@
+# Release 2.0.0
+
+## Features
+
+- Ported AdditiveFOAM to OpenFOAM-14.
+- Added dynamic refinement models and reusable material and heat-source
+ configuration files.
+- Added a general projected heat source with super-Gaussian, nLight AFX, and
+ tabulated planar profiles and an exponential axial projection.
+- Added conversion of PRIMES beam measurements with `primesToAdditiveFoam`.
+- Added general planar-profile moment metrics, tabulated-profile inspection,
+ and automatic `D4Sigma` calculation.
+- Added rotated elliptical analytic profiles, `e2` and `secondMoment` radius
+ definitions, and selectable area-equivalent, major, or minor `D4Sigma`
+ reference widths.
+- Added model-specific heat-source bounds that retain at least
+ `1-tolerance` of the analytical source power.
+- Added support-based heat-source quadrature.
+- Added an adaptive Bayesian workflow with deterministic posterior quadrature
+ for calibrating the projected heat-source axial closure.
+- Expanded the AMB2018, multi-beam, multi-layer, nLight AFX, and tabulated
+ tutorials.
+
+## Bug fixes
+
+- Made all heat sources one-sided, consistent with their analytic
+ normalization.
+- Synchronized heat-source depth, shape parameters, normalization, and bounds
+ once before beam subcycling.
+- Preserved the active-power fraction when a solver time step crosses the end
+ of a scan path.
+- Restricted isotherm source-depth measurements to the planar source support
+ below the beam plane and removed a modified super-Gaussian endpoint
+ singularity.
+- Added calculation-ROI reconstruction, coordinate-preserving support cropping,
+ and beam-statistics reporting to `primesToAdditiveFoam`.
+- Preserved an explicitly configured Kelly `aspectRatioSwitch` value and
+ applied `etaMin` as a lower bound on the Kelly absorption curve.
+
+## Upgrade notes
+
+- AdditiveFOAM 2.0 requires OpenFOAM-14. Source the OpenFOAM-14 environment
+ before sourcing `etc/bashrc` and rebuild AdditiveFOAM with `./Allwmake`.
+- Sources now use nested `absorption`, `heatSource`, `profile`, `projection`,
+ and `refinement` dictionaries with a `model` entry instead of `*Coeffs`
+ dictionaries.
+- The former projected Gaussian, nLight AFX, and tabulated heat-source models
+ are profiles selected by the `projected` model. Their shared axial model is
+ selected in the `projection` dictionary.
+- `superGaussian` remains a volumetric model and is also a planar profile.
+ `radius` is two-dimensional and `depth` is a separate scalar.
+- The tabulated profile derives its D4Sigma metrics from the beam-profile
+ table. No user-supplied lateral dimensions are required.
+- Profile metrics expose `D4Sigma` as `(major minor)`. Reference dimensions
+ select the scalar width and constant or isotherm depth used by aspect-ratio
+ closures.
+- Aspect-ratio closures use a `D4Sigma` width reference, with selectable
+ `areaEquivalent`, `major`, or `minor` component, and a `constant` or
+ `isotherm` depth reference.
+- The `A` and `B` projected-depth coefficients are named `nSlope` and
+ `nIntercept` in the `projection` dictionary.
+- Python 3.10 through 3.12 and the packages in `requirements.txt` are required
+ only for the calibration and plotting utilities.
+
+## Full Changelog
+
+For a complete list of changes, see the [full changelog](https://github.com/ORNL/AdditiveFOAM/compare/1.2.0...2.0.0).
+
+
+# Release 1.2.0
+
+## Features
+
+- Added the projected Gaussian heat-source model.
+- Added melt-pool-dimension and solidification-data function objects.
+- Added optional implicit temperature limiting through the PIMPLE dictionary.
+- Added multi-layer scan-path support and updated the ExaCA tutorials.
+- Added the top-level build script for solvers and utilities.
+
+## Bug Fixes
+
+- Corrected thermophysical file handling for cases launched with `-case`.
+
+## Full Changelog
+
+For a complete list of changes, see the [full changelog](https://github.com/ORNL/AdditiveFOAM/compare/1.1.0...1.2.0).
+
+
# Release 1.1
## Features
diff --git a/LICENSE b/LICENSE
index f2f3c772..df2c378d 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,7 @@
GNU GENERAL PUBLIC LICENSE
Copyright (C) 2011-2017 OpenFOAM Foundation
- Copyright (C) 2023 Oak Ridge National Laboratory
+ Copyright (C) 2023-2026 Oak Ridge National Laboratory
You may use, distribute and copy AdditiveFOAM under the terms
of GNU General Public License version 3, which is displayed below, or
diff --git a/README.md b/README.md
index 2d0272c6..ccbbdc90 100644
--- a/README.md
+++ b/README.md
@@ -11,8 +11,10 @@ The documentation for `AdditiveFOAM` is hosted on [GitHub Pages](https://ornl.gi
### Repository Features
| Link | Description |
|-----------------------------------------------------------|------------------------------------------|
-| [solver](applications/solvers/additiveFoam) | Development version of the solver |
+| [solver](applications/solvers/additiveFoam) | AdditiveFOAM solver source |
| [tutorials](tutorials) | Tutorial cases |
+| [calibration utility](bin/calibrateHeatSource) | Heat-source calibration command |
+| [calibration tutorial](tutorials/heatSourceCalibration) | Projected heat-source calibration workflow |
## Installation
[](https://github.com/OpenFOAM/OpenFOAM-14)
@@ -42,8 +44,28 @@ script from the repository root:
./Allwmake
```
-For regular use, source both environments in each new shell or add them to your
-shell startup file:
+The Python utilities require Python 3.10 through 3.12. To use a dedicated
+virtual environment, create it and install the pinned dependencies from the
+repository root:
+
+```sh
+python3 -m venv .venv
+. .venv/bin/activate
+python -m pip install -r requirements.txt
+python -m pip check
+calibrateHeatSource --help
+```
+
+To use an existing Python environment instead, activate that environment and
+install the same requirements into it:
+
+```sh
+python -m pip install -r /path/to/AdditiveFOAM/requirements.txt
+python -m pip check
+```
+
+The AdditiveFOAM environment does not create or activate a Python environment.
+Source the OpenFOAM and AdditiveFOAM environments in each new shell:
```sh
source /path/to/OpenFOAM-14/etc/bashrc
diff --git a/applications/solvers/additiveFoam/additiveFoam.C b/applications/solvers/additiveFoam/additiveFoam.C
index fadbc53f..cfd09367 100644
--- a/applications/solvers/additiveFoam/additiveFoam.C
+++ b/applications/solvers/additiveFoam/additiveFoam.C
@@ -42,6 +42,12 @@ Description
#include "fvmDiv.H"
#include "fvmDdt.H"
+#include "fvcDdt.H"
+#include "fvcFlux.H"
+#include "fvcLaplacian.H"
+#include "fvcMeshPhi.H"
+#include "fvcReconstruct.H"
+#include "fvcSnGrad.H"
#include "fvcSurfaceIntegrate.H"
#include "fvcVolumeIntegrate.H"
#include "fvmLaplacian.H"
@@ -56,7 +62,7 @@ Description
#include "CrankNicolsonDdtScheme.H"
#include "additiveFoamInfo.H"
-#include "movingHeatSourceModel.H"
+#include "movingHeatSources.H"
#include "thermoPath.H"
#include "interpolateXY.H"
@@ -82,7 +88,7 @@ int main(int argc, char *argv[])
// Initialize time-stepping controls
scalar DiNum = 0.0;
scalar alphaCoNum = 0.0;
- movingHeatSourceModel sources(mesh);
+ movingHeatSources sources(mesh);
Info<< "\nStarting time loop\n" << endl;
diff --git a/applications/solvers/additiveFoam/derivedFvPatchFields/marangoni/marangoniFvPatchVectorField.H b/applications/solvers/additiveFoam/derivedFvPatchFields/marangoni/marangoniFvPatchVectorField.H
index c0315233..71c5ea32 100644
--- a/applications/solvers/additiveFoam/derivedFvPatchFields/marangoni/marangoniFvPatchVectorField.H
+++ b/applications/solvers/additiveFoam/derivedFvPatchFields/marangoni/marangoniFvPatchVectorField.H
@@ -36,8 +36,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
-#ifndef BC_H
-#define BC_H
+#ifndef marangoniFvPatchVectorField_H
+#define marangoniFvPatchVectorField_H
#include "fvPatchFields.H"
#include "transformFvPatchFields.H"
diff --git a/applications/solvers/additiveFoam/derivedFvPatchFields/mixedTemperature/mixedTemperatureFvPatchScalarField.C b/applications/solvers/additiveFoam/derivedFvPatchFields/mixedTemperature/mixedTemperatureFvPatchScalarField.C
index 6a4975ca..a196f1e1 100644
--- a/applications/solvers/additiveFoam/derivedFvPatchFields/mixedTemperature/mixedTemperatureFvPatchScalarField.C
+++ b/applications/solvers/additiveFoam/derivedFvPatchFields/mixedTemperature/mixedTemperatureFvPatchScalarField.C
@@ -78,7 +78,10 @@ mixedTemperatureFvPatchScalarField
valueFraction() = 0.0;
refValue() = scalarField("Tinf", dict, p.size());
- fvPatchScalarField::operator=(refValue());
+ fvPatchScalarField::operator=
+ (
+ scalarField("value", iF.dimensions(), dict, p.size())
+ );
}
diff --git a/applications/solvers/additiveFoam/derivedFvPatchFields/mixedTemperature/mixedTemperatureFvPatchScalarField.H b/applications/solvers/additiveFoam/derivedFvPatchFields/mixedTemperature/mixedTemperatureFvPatchScalarField.H
index 6e5329f0..bd9a8a91 100644
--- a/applications/solvers/additiveFoam/derivedFvPatchFields/mixedTemperature/mixedTemperatureFvPatchScalarField.H
+++ b/applications/solvers/additiveFoam/derivedFvPatchFields/mixedTemperature/mixedTemperatureFvPatchScalarField.H
@@ -47,6 +47,7 @@ Usage
h | Uniform convection coeff | yes |
emissivity | Uniform surface emissivity | no | transportProperties
Tinf | Ambient temperature | yes |
+ value | Initial patch temperature | yes |
\endtable
Example of the boundary condition specification:
@@ -55,6 +56,8 @@ Usage
{
type mixedTemperature;
h 10.0;
+ Tinf uniform 300;
+ value uniform 300;
}
\endverbatim
@@ -63,8 +66,8 @@ SourceFiles
\*---------------------------------------------------------------------------*/
-#ifndef BC_H
-#define BC_H
+#ifndef mixedTemperatureFvPatchScalarField_H
+#define mixedTemperatureFvPatchScalarField_H
#include "mixedFvPatchFields.H"
#include "Function1.H"
diff --git a/applications/solvers/additiveFoam/functionObjects/meltPoolDimensions/meltPoolDimensions.C b/applications/solvers/additiveFoam/functionObjects/meltPoolDimensions/meltPoolDimensions.C
index 855062ec..2dc768ca 100644
--- a/applications/solvers/additiveFoam/functionObjects/meltPoolDimensions/meltPoolDimensions.C
+++ b/applications/solvers/additiveFoam/functionObjects/meltPoolDimensions/meltPoolDimensions.C
@@ -5,7 +5,7 @@
\\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2023 Oak Ridge National Laboratory
+ Copyright (C) 2023-2026 Oak Ridge National Laboratory
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -247,7 +247,7 @@ bool Foam::functionObjects::meltPoolDimensions::execute()
// physical boundary : take face point if above iso value
const vectorField& Cf = mesh_.Cf().boundaryField()[patchi];
- const scalarField& pif(TPf.patchInternalField());
+ const scalarField pif(TPf.patchInternalField());
forAll(faceCells, facei)
{
diff --git a/applications/solvers/additiveFoam/moveMesh.H b/applications/solvers/additiveFoam/moveMesh.H
index 4df8d27a..42ccbc04 100644
--- a/applications/solvers/additiveFoam/moveMesh.H
+++ b/applications/solvers/additiveFoam/moveMesh.H
@@ -28,6 +28,7 @@ if (pimple.firstPimpleIter() || pimple.moveMeshOuterCorrectors())
);
// Make the flux relative to the mesh motion
+ MRF.makeRelative(phi);
fvc::makeRelative(phi, U);
}
diff --git a/applications/solvers/additiveFoam/movingHeatSource/Make/files b/applications/solvers/additiveFoam/movingHeatSource/Make/files
index de7b98fe..0f3b7fcb 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/Make/files
+++ b/applications/solvers/additiveFoam/movingHeatSource/Make/files
@@ -7,13 +7,23 @@ pathVector/pathVector.C
movingBeam/movingBeam.C
+heatSourceModels/profileMetrics/profileMetrics.C
heatSourceModels/heatSourceModel/heatSourceModel.C
heatSourceModels/heatSourceModel/heatSourceModelNew.C
+heatSourceModels/projected/profiles/heatSourceProfile/heatSourceProfile.C
+heatSourceModels/projected/profiles/heatSourceProfile/heatSourceProfileNew.C
+heatSourceModels/projected/profiles/superGaussian/superGaussianProfile.C
+heatSourceModels/projected/profiles/nLightAFX/nLightAFXProfile.C
+heatSourceModels/projected/profiles/tabulated/tabulatedProfile.C
+heatSourceModels/projected/projections/heatSourceProjection/heatSourceProjection.C
+heatSourceModels/projected/projections/heatSourceProjection/heatSourceProjectionNew.C
+heatSourceModels/projected/projections/exponential/exponential.C
heatSourceModels/superGaussian/superGaussian.C
heatSourceModels/modifiedSuperGaussian/modifiedSuperGaussian.C
-heatSourceModels/projectedGaussian/projectedGaussian.C
-heatSourceModels/nLightAFX/nLightAFX.C
-heatSourceModels/tabulated/tabulated.C
+heatSourceModels/projected/projected.C
+
+movingHeatSources/referenceDimensions.C
+movingHeatSources/movingHeatSource.C
refinementModels/refinementModel/refinementModel.C
refinementModels/refinementModel/refinementModelNew.C
@@ -22,6 +32,6 @@ refinementModels/timeStep/timeStep.C
refinementModels/targetCellLoad/targetCellLoad.C
refinementModels/uniformTimeIntervals/uniformTimeIntervals.C
-movingHeatSourceModel/movingHeatSourceModel.C
+movingHeatSources/movingHeatSources.C
LIB = $(FOAM_USER_LIBBIN)/libmovingBeamModels
diff --git a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.C b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.C
index 9d83eb56..d17b7286 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.C
+++ b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.C
@@ -1,11 +1,9 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
- \\ / O peration | Website: https://openfoam.org
- \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2026 Oak Ridge National Laboratory
\\/ M anipulation |
--------------------------------------------------------------------------------
- Copyright (C) 2023 Oak Ridge National Laboratory
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -22,14 +20,11 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
-
\*---------------------------------------------------------------------------*/
#include "KellyAbsorption.H"
#include "addToRunTimeSelectionTable.H"
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
-
namespace Foam
{
namespace absorptionModels
@@ -39,96 +34,64 @@ namespace absorptionModels
}
}
-// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
-
Foam::absorptionModels::Kelly::Kelly
(
- const word& sourceName,
const dictionary& dict,
- const fvMesh& mesh
+ const fvMesh&
)
:
- absorptionModel(typeName, sourceName, dict, mesh),
- geometry_(absorptionModelCoeffs_.lookup("geometry")),
- eta0_("eta0", dimless, absorptionModelCoeffs_),
- etaMin_("etaMin", dimless, absorptionModelCoeffs_),
+ geometry_(dict.lookup("geometry")),
+ eta0_("eta0", dimless, dict),
+ etaMin_("etaMin", dimless, dict),
aspectRatioSwitch_
(
- absorptionModelCoeffs_.lookupOrDefault
- (
- "aspectRatioSwitch",
- 1.0
- )
+ dict.lookupOrDefault("aspectRatioSwitch", 1.0)
)
{
- if ((geometry_ != "cone") && (geometry_ != "cylinder"))
+ if (geometry_ != "cone" && geometry_ != "cylinder")
{
- FatalErrorInFunction
- << "Kelly absorption model geometry type " << geometry_
- << " not recognized. Choose either cylinder or cone."
- << abort(FatalError);
+ FatalIOErrorInFunction(dict)
+ << "Kelly geometry must be cone or cylinder, found " << geometry_
+ << exit(FatalIOError);
}
}
-// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
-
-Foam::scalar
-Foam::absorptionModels::Kelly::eta
+Foam::scalar Foam::absorptionModels::Kelly::eta
(
- const scalar& aspectRatio
+ const scalar aspectRatio
) const
{
- if (aspectRatio > aspectRatioSwitch_)
+ if (aspectRatio <= aspectRatioSwitch_)
{
- const scalar theta = Foam::atan(1.0 / aspectRatio);
-
- scalar F = 0.0;
- scalar G = 0.0;
+ return etaMin_.value();
+ }
- if (geometry_ == "cone")
- {
- F = 0.25 * (3.0 * Foam::sin(theta) - Foam::sin(3.0 * theta));
- G = 1.0 / (1.0 + Foam::sqrt(1.0 + pow(aspectRatio, 2)));
- }
+ const scalar theta = Foam::atan(1.0/aspectRatio);
- else if (geometry_ == "cylinder")
- {
- F = 0.5 * (1.0 - Foam::cos(2.0 * theta));
- G = 0.5 / (1.0 + aspectRatio);
- }
+ scalar F = 0;
+ scalar G = 0;
- return (eta0_ * (1.0 + (1.0 - eta0_)*(G - F))
- / (1.0 - (1.0 - eta0_)*(1.0 - G))).value();
- }
- else
+ if (geometry_ == "cone")
{
- return etaMin_.value();
+ F = 0.25*(3.0*Foam::sin(theta) - Foam::sin(3.0*theta));
+ G = 1.0/(1.0 + Foam::sqrt(1.0 + sqr(aspectRatio)));
}
-};
-bool Foam::absorptionModels::Kelly::read()
-{
- if (absorptionModel::read())
+ if (geometry_ == "cylinder")
{
- absorptionModelCoeffs_ = optionalSubDict(type() + "Coeffs");
+ F = 0.5*(1.0 - Foam::cos(2.0*theta));
+ G = 0.5/(1.0 + aspectRatio);
+ }
- //- Mandatory entries
- absorptionModelCoeffs_.lookup("geometry") >> geometry_;
- absorptionModelCoeffs_.lookup("eta0") >> eta0_;
- absorptionModelCoeffs_.lookup("etaMin") >> etaMin_;
- aspectRatioSwitch_ =
- absorptionModelCoeffs_.lookupOrDefault
+ return
+ max
+ (
+ etaMin_.value(),
(
- "aspectRatioSwitch",
- 1.0
- );
-
- return true;
- }
- else
- {
- return false;
- }
+ eta0_*(1.0 + (1.0 - eta0_)*(G - F))
+ / (1.0 - (1.0 - eta0_)*(1.0 - G))
+ ).value()
+ );
}
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.H b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.H
index 34ee0e49..fc09c292 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.H
+++ b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.H
@@ -1,11 +1,9 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
- \\ / O peration | Website: https://openfoam.org
- \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2026 Oak Ridge National Laboratory
\\/ M anipulation |
--------------------------------------------------------------------------------
- Copyright (C) 2023 Oak Ridge National Laboratory
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -22,25 +20,6 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
-
-Class
- Foam::absorptionModel::Kelly
-
-Description
- Kelly absorption model for the optical absorption due to multiple internal
- reflections in simple geometric shapes (e.g. cone and cylinder).
-
- Reference:
- \verbatim
- F. J. Kelly,
- "An Equation for the Local Thermal Emissivity at the
- Vertex of a Diffuse Conical or V-Groove Cavity",
- Applied Optics, Vol. 5, No. 6, June 1966.
- \endverbatim
-
-SourceFiles
- KellyAbsorption.C
-
\*---------------------------------------------------------------------------*/
#ifndef KellyAbsorption_H
@@ -48,76 +27,38 @@ SourceFiles
#include "absorptionModel.H"
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
namespace Foam
{
namespace absorptionModels
{
-/*---------------------------------------------------------------------------*\
- Class Kelly
-\*---------------------------------------------------------------------------*/
-
class Kelly
:
public absorptionModel
{
- // Private Data
+ word geometry_;
- //- Conical or cylindrical
- word geometry_;
+ dimensionedScalar eta0_;
- //- Fresnel absorption of the liquid metal
- dimensionedScalar eta0_;
+ dimensionedScalar etaMin_;
- //- Effective absorption in the conduction regime
- dimensionedScalar etaMin_;
-
- //- Aspect ratio above which the Kelly multiple-reflection model is used
- scalar aspectRatioSwitch_;
+ scalar aspectRatioSwitch_;
public:
- //- Runtime type information
TypeName("Kelly");
+ Kelly(const dictionary& dict, const fvMesh& mesh);
- // Constructors
-
- //- Construct from components
- Kelly
- (
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
- );
-
-
- //- Destructor
virtual ~Kelly()
{}
- // Member Functions
-
- //- Return the absorption as a scalar field
- virtual scalar eta
- (
- const scalar& aspectRatio
- ) const;
-
- //- Read the absorption properties
- virtual bool read();
+ virtual scalar eta(const scalar aspectRatio) const;
};
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
} // End namespace absorptionModels
} // End namespace Foam
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
#endif
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModel.C b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModel.C
index 2e2bed52..f67dca2b 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModel.C
+++ b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModel.C
@@ -1,11 +1,9 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
- \\ / O peration | Website: https://openfoam.org
- \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2026 Oak Ridge National Laboratory
\\/ M anipulation |
--------------------------------------------------------------------------------
- Copyright (C) 2023 Oak Ridge National Laboratory
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -22,88 +20,14 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
-
\*---------------------------------------------------------------------------*/
#include "absorptionModel.H"
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
-
namespace Foam
{
defineTypeNameAndDebug(absorptionModel, 0);
defineRunTimeSelectionTable(absorptionModel, dictionary);
}
-const Foam::word Foam::absorptionModel::heatSourceDictName
-(
- "heatSourceDict"
-);
-
-// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
-
-Foam::IOobject Foam::absorptionModel::createIOobject
-(
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
-) const
-{
- typeIOobject io
- (
- dict.name(),
- mesh.time().name(),
- mesh,
- IOobject::MUST_READ,
- IOobject::NO_WRITE
- );
-
- if (io.headerOk())
- {
- io.readOpt() = IOobject::MUST_READ_IF_MODIFIED;
- return io;
- }
- else
- {
- io.readOpt() = IOobject::NO_READ;
- return io;
- }
-}
-
-// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
-
-Foam::absorptionModel::absorptionModel
-(
- const word& type,
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
-)
-:
- IOdictionary(createIOobject(sourceName, dict, mesh)),
- sourceName_(sourceName),
- heatSourceDict_(dict),
- mesh_(mesh),
-
- beamDict_(heatSourceDict_.optionalSubDict(sourceName_)),
- absorptionModelCoeffs_(beamDict_.optionalSubDict(type + "Coeffs"))
-{}
-
-
-// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
-
-bool Foam::absorptionModel::read()
-{
- if (regIOobject::read())
- {
- absorptionModelCoeffs_ = optionalSubDict(type() + "Coeffs");
-
- return true;
- }
- else
- {
- return false;
- }
-}
-
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModel.H b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModel.H
index c3f3fb36..a9b40b4b 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModel.H
+++ b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModel.H
@@ -1,11 +1,9 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
- \\ / O peration | Website: https://openfoam.org
- \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2026 Oak Ridge National Laboratory
\\/ M anipulation |
--------------------------------------------------------------------------------
- Copyright (C) 2023 Oak Ridge National Laboratory
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -22,143 +20,55 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
-
-Class
- Foam::absorptionModel
-
-Description
- Abstract base class for absorption models
-
-SourceFiles
- absorptionModel.C
-
\*---------------------------------------------------------------------------*/
#ifndef absorptionModel_H
#define absorptionModel_H
+#include "autoPtr.H"
#include "dictionary.H"
-#include "volFields.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+#include "fvMesh.H"
+#include "runTimeSelectionTables.H"
namespace Foam
{
-/*---------------------------------------------------------------------------*\
- Class absorptionModel Declaration
-\*---------------------------------------------------------------------------*/
-
class absorptionModel
-:
- public IOdictionary
{
- // Private member functions
-
- //- Construct the base IO object
- IOobject createIOobject
- (
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
- ) const;
-
-protected:
-
- // Protected data
-
- //- Name of beam
- const word& sourceName_;
-
- //- Main heat source dictionary
- const dictionary& heatSourceDict_;
-
- //- Pointer to mesh info
- const fvMesh& mesh_;
-
- //- Individual beam dictionary
- dictionary beamDict_;
-
- //- Absorption model coefficient dictionary
- dictionary absorptionModelCoeffs_;
-
-
public:
- //- Runtime type information
TypeName("absorptionModel");
- //- Default heatSourceProperties dictionary name
- static const word heatSourceDictName;
-
- // Declare run-time constructor selection table
declareRunTimeSelectionTable
(
autoPtr,
absorptionModel,
dictionary,
- (
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
- ),
- (sourceName, dict, mesh)
+ (const dictionary& dict, const fvMesh& mesh),
+ (dict, mesh)
);
- // Constructors
-
- //- Construct
- absorptionModel
- (
- const word& type,
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
- );
-
- //- Disallow default bitwise copy construction
- absorptionModel(const absorptionModel&);
-
- // Selectors
+ absorptionModel()
+ {}
- //- Return a reference to the selected absorption model
- static autoPtr New
- (
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
- );
+ absorptionModel(const absorptionModel&) = delete;
+ static autoPtr New
+ (
+ const dictionary& dict,
+ const fvMesh& mesh
+ );
- //- Destructor
virtual ~absorptionModel()
{}
+ virtual scalar eta(const scalar aspectRatio) const = 0;
- // Member Functions
-
- //- Return const-access to the absorption
- virtual scalar eta
- (
- const scalar& aspectRatio
- ) const = 0;
-
- //- Read the absorption properties
- virtual bool read();
-
- // Member Operators
-
- //- Disallow default bitwise assignment
- void operator=(const absorptionModel&) = delete;
+ void operator=(const absorptionModel&) = delete;
};
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
} // End namespace Foam
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
#endif
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModelNew.C b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModelNew.C
index 39fae8ef..57caaff8 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModelNew.C
+++ b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModelNew.C
@@ -1,11 +1,9 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
- \\ / O peration | Website: https://openfoam.org
- \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2026 Oak Ridge National Laboratory
\\/ M anipulation |
--------------------------------------------------------------------------------
- Copyright (C) 2023 Oak Ridge National Laboratory
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -22,46 +20,35 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
-
\*---------------------------------------------------------------------------*/
#include "absorptionModel.H"
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
Foam::autoPtr Foam::absorptionModel::New
(
- const word& sourceName,
const dictionary& dict,
const fvMesh& mesh
)
{
- //- Initialize modelType to a non-model word
- word modelType("unselected");
-
- //- Get model type from source subdict
- dictionary sourceDict(dict.optionalSubDict(sourceName));
- sourceDict.lookup("absorptionModel") >> modelType;
+ const word modelType(dict.lookup("model"));
Info<< "Selecting absorption model " << modelType << endl;
- //- Look up model type from runtime selection table and throw error
- // if it doesn't exist
- dictionaryConstructorTable::iterator cstrIter =
- dictionaryConstructorTablePtr_->find(modelType);
+ const auto cstrIter = dictionaryConstructorTablePtr_->find(modelType);
if (cstrIter == dictionaryConstructorTablePtr_->end())
{
- FatalErrorInFunction
- << "Unknown " << absorptionModel::typeName<< " type "
- << modelType << nl << nl
- << "Valid absorptionModels are : " << endl
+ FatalIOErrorInFunction(dict)
+ << "Unknown absorption model " << modelType << nl << nl
+ << "Valid models are:" << endl
<< dictionaryConstructorTablePtr_->sortedToc()
- << exit(FatalError);
+ << exit(FatalIOError);
}
- return autoPtr(cstrIter()(sourceName, dict, mesh));
+ return autoPtr
+ (
+ cstrIter()(dict, mesh)
+ );
}
-
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/constant/constantAbsorption.C b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/constant/constantAbsorption.C
index 8903608f..4621364d 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/constant/constantAbsorption.C
+++ b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/constant/constantAbsorption.C
@@ -1,11 +1,9 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
- \\ / O peration | Website: https://openfoam.org
- \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2026 Oak Ridge National Laboratory
\\/ M anipulation |
--------------------------------------------------------------------------------
- Copyright (C) 2023 Oak Ridge National Laboratory
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -22,14 +20,11 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
-
\*---------------------------------------------------------------------------*/
#include "constantAbsorption.H"
#include "addToRunTimeSelectionTable.H"
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
-
namespace Foam
{
namespace absorptionModels
@@ -39,36 +34,13 @@ namespace absorptionModels
}
}
-// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
-
Foam::absorptionModels::constant::constant
(
- const word& sourceName,
const dictionary& dict,
- const fvMesh& mesh
+ const fvMesh&
)
:
- absorptionModel(typeName, sourceName, dict, mesh),
- eta_("eta", dimless, absorptionModelCoeffs_)
+ eta_("eta", dimless, dict)
{}
-// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
-
-bool Foam::absorptionModels::constant::read()
-{
- if (absorptionModel::read())
- {
- absorptionModelCoeffs_ = optionalSubDict(type() + "Coeffs");
-
- //- Mandatory entries
- absorptionModelCoeffs_.lookup("eta") >> eta_;
-
- return true;
- }
- else
- {
- return false;
- }
-}
-
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/constant/constantAbsorption.H b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/constant/constantAbsorption.H
index 88f388ec..0aaf43bb 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/constant/constantAbsorption.H
+++ b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/constant/constantAbsorption.H
@@ -1,11 +1,9 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
- \\ / O peration | Website: https://openfoam.org
- \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2026 Oak Ridge National Laboratory
\\/ M anipulation |
--------------------------------------------------------------------------------
- Copyright (C) 2023 Oak Ridge National Laboratory
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -22,16 +20,6 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
-
-Class
- Foam::absorptionModels::constant
-
-Description
- constant absorption model.
-
-SourceFiles
- constantAbsorption.C
-
\*---------------------------------------------------------------------------*/
#ifndef constantAbsorption_H
@@ -39,70 +27,35 @@ SourceFiles
#include "absorptionModel.H"
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
namespace Foam
{
namespace absorptionModels
{
-/*---------------------------------------------------------------------------*\
- Class constant
-\*---------------------------------------------------------------------------*/
-
class constant
:
public absorptionModel
{
- // Private Data
-
- //- Constant absorption scalar
- dimensionedScalar eta_;
+ dimensionedScalar eta_;
public:
- //- Runtime type information
TypeName("constant");
+ constant(const dictionary& dict, const fvMesh& mesh);
- // Constructors
-
- //- Construct from components
- constant
- (
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
- );
-
-
- //- Destructor
virtual ~constant()
{}
- // Member Functions
-
- //- Return the absorption as a scalar field
- virtual scalar eta
- (
- const scalar& aspectRatio
- ) const
- {
- return eta_.value();
- };
-
- //- Read the absorption properties
- virtual bool read();
+ inline virtual scalar eta(const scalar) const
+ {
+ return eta_.value();
+ }
};
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
} // End namespace absorptionModels
} // End namespace Foam
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
#endif
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.C
index aed14633..dff2d184 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.C
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.C
@@ -22,16 +22,9 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
-
\*---------------------------------------------------------------------------*/
#include "heatSourceModel.H"
-#include "labelVector.H"
-#include "hexMatcher.H"
-#include "treeBoundBox.H"
-#include "thermoPath.H"
-
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
@@ -39,365 +32,17 @@ namespace Foam
defineRunTimeSelectionTable(heatSourceModel, dictionary);
}
-const Foam::word Foam::heatSourceModel::heatSourceDictName
-(
- "heatSourceDict"
-);
-
-// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
-
-Foam::IOobject Foam::heatSourceModel::createIOobject
-(
- const dictionary& dict,
- const fvMesh& mesh
-) const
-{
- typeIOobject io
- (
- dict.name(),
- mesh.time().constant(),
- mesh,
- IOobject::MUST_READ,
- IOobject::NO_WRITE
- );
-
- if (io.headerOk())
- {
- io.readOpt() = IOobject::MUST_READ_IF_MODIFIED;
- return io;
- }
- else
- {
- io.readOpt() = IOobject::NO_READ;
- return io;
- }
-}
-
-// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
-
Foam::heatSourceModel::heatSourceModel
(
- const word& type,
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
+ const dictionary& dict
)
:
- IOdictionary(createIOobject(dict, mesh)),
-
- sourceName_(sourceName),
- heatSourceDict_(dict),
- sourceDict_(heatSourceDict_.optionalSubDict(sourceName_)),
- heatSourceModelCoeffs_(sourceDict_.optionalSubDict(type + "Coeffs")),
- mesh_(mesh),
- absorptionModel_(nullptr),
- movingBeam_(nullptr)
-{
- absorptionModel_ =
- absorptionModel::New(sourceName_, heatSourceDict_, mesh_);
-
- movingBeam_ =
- movingBeam::New(sourceName_, heatSourceDict_, mesh_.time());
-
- dimensions_ =
- heatSourceModelCoeffs_.lookup("dimensions");
-
- staticDimensions_ = dimensions_;
-
- transient_ =
- heatSourceModelCoeffs_.lookupOrDefault("transient", false);
-
- isoValue_ = great;
-
- if
- (
- transient_
- && !heatSourceModelCoeffs_.readIfPresent("isoValue", isoValue_)
- )
- {
- isoValue_ = thermoPath(mesh_).liquidus();
- }
- else
- {
- heatSourceModelCoeffs_.readIfPresent("isoValue", isoValue_);
- }
-
- nPoints_ =
- heatSourceModelCoeffs_.lookupOrDefault
- (
- "nPoints",
- vector::one
- );
-}
-
-
-// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
-
-void Foam::heatSourceModel::updateDimensions()
-{
- if (!transient_ )
- {
- Info << "maxDepth: " << dimensions_.z() << endl;
- return;
- }
-
- const vector position_ = movingBeam_->position();
-
- const scalar searchRadius
- (
- max(staticDimensions_.x(), staticDimensions_.y())
- );
-
- // find maximum isotherm depth within supplied beam radius
- // depth is defined as the z-distance from the heat source centre
- const volScalarField& T = mesh_.lookupObject("T");
-
- const labelUList& owner = mesh_.owner();
- const labelUList& neighbour = mesh_.neighbour();
-
- const volVectorField& cc = mesh_.C();
-
- scalar maxDepth = staticDimensions_.z();
-
- // isocontour location evaluated linearly across faces
- for (label facei=0; facei < mesh_.nInternalFaces(); facei++)
- {
- const label own = owner[facei];
- const label nei = neighbour[facei];
-
- scalar minFace = min(T[own], T[nei]);
- scalar maxFace = max(T[own], T[nei]);
-
- if ((minFace < isoValue_) && (maxFace >= isoValue_))
- {
- vector d = cc[nei] - cc[own];
- vector p = cc[own] + d*(isoValue_ - T[own])/(T[nei] - T[own]);
-
- p = cmptMag(p - position_);
-
- scalar pxy = Foam::sqrt(p.x()*p.x() + p.y()*p.y());
-
- if (pxy <= searchRadius)
- {
- maxDepth = max(p.z(), maxDepth);
- }
- }
- }
-
- // isocontour location evaluated linearly across processor faces
- const volScalarField::Boundary& TBf = T.boundaryField();
-
- forAll(TBf, patchi)
- {
- const fvPatchScalarField& TPf = TBf[patchi];
-
- const labelUList& faceCells = TPf.patch().faceCells();
-
- if (TPf.coupled())
- {
- const vectorField ccn
- (
- cc.boundaryField()[patchi].patchNeighbourField()
- );
- const scalarField Tn(TPf.patchNeighbourField());
-
- forAll(faceCells, facei)
- {
- label own = faceCells[facei];
-
- scalar minFace = min(T[own], Tn[facei]);
- scalar maxFace = max(T[own], Tn[facei]);
-
- if ((minFace < isoValue_) && (maxFace >= isoValue_))
- {
- vector d = ccn[facei] - cc[own];
- vector p =
- cc[own] + d*(isoValue_ - T[own])/(Tn[facei] - T[own]);
-
- p = cmptMag(p - position_);
-
- scalar pxy = Foam::sqrt(p.x()*p.x() + p.y()*p.y());
-
- if (pxy <= searchRadius)
- {
- maxDepth = max(p.z(), maxDepth);
- }
- }
- }
- }
- }
-
- reduce(maxDepth, maxOp());
-
- dimensions_ =
- vector(staticDimensions_.x(), staticDimensions_.y(), maxDepth);
-
- Info << "maxDepth: " << dimensions_.z() << endl;
-}
-
-Foam::tmpFoam::heatSourceModel::qDot()
-{
- tmp tqDot
- (
- new volScalarField
- (
- IOobject
- (
- "qDot_",
- mesh_.time().name(),
- mesh_,
- IOobject::NO_READ,
- IOobject::NO_WRITE
- ),
- mesh_,
- dimensionedScalar("Zero", dimPower/dimVolume, 0.0)
- )
- );
- volScalarField& qDot_ = tqDot.ref();
-
- // sample gaussian distribution at desired resolution
- const scalar power_ = movingBeam_->power();
-
- if (power_ > small)
- {
- const vector position_ = movingBeam_->position();
-
- // udpate the absorbed power and heat source normalization term
- const scalar aspectRatio =
- dimensions_.z() / min(dimensions_.x(), dimensions_.y());
-
- const dimensionedScalar absorbedPower
- (
- "etaP",
- dimPower,
- absorptionModel_->eta(aspectRatio)*power_
- );
-
- dimensionedScalar volume = V0();
-
- // integrate the heat source in each overlapping cell
- volScalarField weights
- (
- IOobject
- (
- "weights",
- mesh_.time().name(),
- mesh_,
- IOobject::NO_READ,
- IOobject::NO_WRITE
- ),
- mesh_,
- dimensionedScalar("Zero", dimless, 0.0)
- );
-
- const pointField& points = mesh_.points();
-
- treeBoundBox beamBb
- (
- position_ - 1.5*dimensions_,
- position_ + 1.5*dimensions_
- );
-
- hexMatcher hex;
-
- forAll(mesh_.cells(), celli)
- {
- treeBoundBox cellBb(point::max, point::min);
-
- const labelList& vertices = mesh_.cellPoints()[celli];
-
- forAll(vertices, i)
- {
- cellBb.min() = min(cellBb.min(), points[vertices[i]]);
- cellBb.max() = max(cellBb.max(), points[vertices[i]]);
- }
-
- if (cellBb.overlaps(beamBb))
- {
- if (hex.isA(mesh_, celli))
- {
- vector dx_ = cmptDivide(dimensions_, vector(nPoints_));
-
- labelVector nCellPoints =
- max
- (
- cmptDivide(cellBb.span() + small*vector::one, dx_),
- vector::one
- );
-
- dx_ = cmptDivide(cellBb.span(), vector(nCellPoints));
-
- scalar dVi = dx_.x() * dx_.y() * dx_.z();
-
- scalar wi = 0.0;
-
- for (label k=0; k < nCellPoints.z(); ++k)
- {
- for (label j=0; j < nCellPoints.y(); ++j)
- {
- for (label i=0; i < nCellPoints.x(); ++i)
- {
- const point pt
- (
- cellBb.max()
- - cmptMultiply
- (
- vector(i + 0.5, j + 0.5, k + 0.5),
- dx_
- )
- );
-
- treeBoundBox ptBb(pt - 0.5*dx_, pt + 0.5*dx_);
-
- // calculate weight for point in beam bound box
- if (beamBb.overlaps(ptBb))
- {
- wi += weight(pt - position_) * dVi;
- }
- }
- }
- }
-
- weights[celli] = wi / mesh_.V()[celli];
- }
- else
- {
- // cell is not hexahedral, evaluate at centre
- point d = cmptMag(mesh_.cellCentres()[celli] - position_);
-
- weights[celli] = weight(d);
- }
- }
- }
-
- // stabilize numerical integration errors within 95% of applied power
- dimensionedScalar sumWeights = fvc::domainIntegrate(weights);
- scalar residual = (sumWeights / volume).value();
-
- if (mag(1 - residual) < 0.05)
- {
- volume = sumWeights;
- }
-
- qDot_ = absorbedPower * weights / volume;
- }
-
- return tqDot;
-}
-
-
-bool Foam::heatSourceModel::read()
-{
- if (regIOobject::read())
- {
- heatSourceModelCoeffs_ = optionalSubDict(type() + "Coeffs");
-
- return true;
- }
- else
- {
- return false;
- }
-}
+ nPoints_(dict.lookupOrDefault("nPoints", vector::one)),
+ tolerance_(dict.lookupOrDefault("tolerance", 1.0e-3)),
+ depth_(dict.lookup("depth")),
+ sourceDepth_(depth_),
+ bounds_(point::zero, point::zero),
+ V0_("V0", dimVolume, 0)
+{}
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.H
index e74d3d9a..ff3f2287 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.H
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.H
@@ -24,210 +24,112 @@ License
along with OpenFOAM. If not, see .
Class
- Foam::heatSourceModels::heatSourceModel
+ Foam::heatSourceModel
Description
- Abstract base class for heatSource models
+ Common interface for volumetric heat-source distributions. Profile metrics
+ always describe the intensity footprint in the beam plane at z=0.
SourceFiles
heatSourceModel.C
+ heatSourceModelNew.C
\*---------------------------------------------------------------------------*/
#ifndef heatSourceModel_H
#define heatSourceModel_H
+#include "autoPtr.H"
+#include "profileMetrics.H"
+#include "boundBox.H"
#include "dictionary.H"
-#include "volFields.H"
-#include "movingBeam.H"
-#include "absorptionModel.H"
+#include "fvMesh.H"
#include "labelVector.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+#include "runTimeSelectionTables.H"
namespace Foam
{
-/*---------------------------------------------------------------------------*\
- Class heatSourceModel Declaration
-\*---------------------------------------------------------------------------*/
-
class heatSourceModel
-:
- public IOdictionary
{
- // Private member functions
-
- //- Construct the base IO object
- IOobject createIOobject
- (
- const dictionary& dict,
- const fvMesh& mesh
- ) const;
-
protected:
- // Protected data
-
- //- Name of heat source
- const word& sourceName_;
+ labelVector nPoints_;
- //- Main heat source dictionary
- const dictionary& heatSourceDict_;
+ scalar tolerance_;
- //- Sub-dict for individual heat source
- dictionary sourceDict_;
+ scalar depth_;
- //- Heat source model coefficient sub-dict
- dictionary heatSourceModelCoeffs_;
+ scalar sourceDepth_;
- //- Pointer to mesh info
- const fvMesh& mesh_;
+ boundBox bounds_;
- //- Flag for transient or static heat source dimensions
- Switch transient_;
+ dimensionedScalar V0_;
- //- Isotherm depth tracked in transient heat source model
- scalar isoValue_;
-
- //- Dimensions of the heat source (dynamic)
- vector dimensions_;
-
- //- Dimensions of the heat source (static)
- vector staticDimensions_;
-
- //- Number of points along heat source dimensions resolved by sampling
- labelVector nPoints_;
-
- //- AutoPtrs to absorption model and moving beam instances
- autoPtr absorptionModel_;
- autoPtr movingBeam_;
+ heatSourceModel(const dictionary& dict);
public:
- //- Runtime type information
TypeName("heatSourceModel");
- //- Default heatSourceProperties dictionary name
- static const word heatSourceDictName;
-
- // Declare run-time constructor selection table
declareRunTimeSelectionTable
(
autoPtr,
heatSourceModel,
dictionary,
(
- const word& sourceName,
const dictionary& dict,
const fvMesh& mesh
),
- (sourceName, dict, mesh)
+ (dict, mesh)
);
+ heatSourceModel(const heatSourceModel&) = delete;
- // Constructors
-
- //- Construct for mixture
- heatSourceModel
- (
- const word& type,
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
- );
-
- //- Disallow default bitwise copy construction
- heatSourceModel(const heatSourceModel&);
-
- // Selectors
-
- //- Return a reference to the selected heatSource model
- static autoPtr New
- (
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
- );
+ static autoPtr New
+ (
+ const dictionary& dict,
+ const fvMesh& mesh
+ );
- //- Destructor
virtual ~heatSourceModel()
{}
+ virtual void update
+ (
+ const scalar depth,
+ const scalar aspectRatio
+ ) = 0;
- // Member Functions
-
- //- Return access to the movingBeam instance
- inline movingBeam& beam()
- {
- return movingBeam_();
- }
-
- //- Return const access to the movingBeam instance
- inline const movingBeam& beam() const
- {
- return movingBeam_();
- }
-
- //- Return the heat source name
- inline const word& sourceName() const
- {
- return sourceName_;
- }
-
- //- Return boolean of heat source type
- inline Switch transient() const
- {
- return transient_;
- }
-
- //- Return scalar of the isovalue
- inline scalar isoValue() const
- {
- return isoValue_;
- }
-
- //- Return vector of current heat source dimensions
- inline vector dimensions() const
- {
- return dimensions_;
- }
-
- //- Return vector of original heat source dimensions
- inline vector staticDimensions() const
- {
- return staticDimensions_;
- }
-
- //- Update the transient heat source dimensions
- void updateDimensions();
-
- //- Return the volumetric heating field
- virtual tmp qDot();
+ virtual scalar weight(const vector& r) const = 0;
- //- Return the weight of the heat source distribution at a given point
- virtual scalar weight(const vector& d) = 0;
+ virtual const profileMetrics& metrics() const = 0;
- //- Return the normalization volume for the integrated distribution
- virtual dimensionedScalar V0() = 0;
+ inline scalar depth() const
+ {
+ return depth_;
+ }
- //- Read the heat source dictionary
- virtual bool read() = 0;
+ inline const labelVector& nPoints() const
+ {
+ return nPoints_;
+ }
+ inline const boundBox& bounds() const
+ {
+ return bounds_;
+ }
- // Member Operators
+ inline const dimensionedScalar& V0() const
+ {
+ return V0_;
+ }
- //- Disallow default bitwise assignment
- void operator=(const heatSourceModel&) = delete;
+ void operator=(const heatSourceModel&) = delete;
};
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
} // End namespace Foam
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
#endif
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModelNew.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModelNew.C
index c5c5accf..ec9b38b9 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModelNew.C
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModelNew.C
@@ -22,46 +22,32 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
-
\*---------------------------------------------------------------------------*/
#include "heatSourceModel.H"
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
Foam::autoPtr Foam::heatSourceModel::New
(
- const word& sourceName,
const dictionary& dict,
const fvMesh& mesh
)
{
- //- Initialize modelType to a non-model word
- word modelType("unselected");
+ const word modelType(dict.lookup("model"));
- //- Get model type from source subdict
- dictionary sourceDict(dict.optionalSubDict(sourceName));
- sourceDict.lookup("heatSourceModel") >> modelType;
+ Info<< "Selecting heat source model " << modelType << endl;
- Info<< "Selecting heatSource model " << modelType << endl;
-
- //- Look up model type from runtime selection table and throw error
- // if it doesn't exist
- dictionaryConstructorTable::iterator cstrIter =
- dictionaryConstructorTablePtr_->find(modelType);
+ const auto cstrIter = dictionaryConstructorTablePtr_->find(modelType);
if (cstrIter == dictionaryConstructorTablePtr_->end())
{
- FatalErrorInFunction
- << "Unknown " << heatSourceModel::typeName<< " type "
- << modelType << nl << nl
- << "Valid heatSourceModels are : " << endl
+ FatalIOErrorInFunction(dict)
+ << "Unknown heat source model " << modelType << nl << nl
+ << "Valid models are:" << endl
<< dictionaryConstructorTablePtr_->sortedToc()
- << exit(FatalError);
+ << exit(FatalIOError);
}
- return autoPtr(cstrIter()(sourceName, dict, mesh));
+ return autoPtr(cstrIter()(dict, mesh));
}
-
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/modifiedSuperGaussian/modifiedSuperGaussian.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/modifiedSuperGaussian/modifiedSuperGaussian.C
index 95b2d750..3452e11a 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/modifiedSuperGaussian/modifiedSuperGaussian.C
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/modifiedSuperGaussian/modifiedSuperGaussian.C
@@ -5,7 +5,7 @@
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2023 Oak Ridge National Laboratory
+ Copyright (C) 2023-2026 Oak Ridge National Laboratory
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -22,13 +22,12 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
-
\*---------------------------------------------------------------------------*/
#include "modifiedSuperGaussian.H"
+#include "superGaussianProfile.H"
#include "addToRunTimeSelectionTable.H"
-
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+#include "mathematicalConstants.H"
namespace Foam
{
@@ -46,86 +45,131 @@ namespace heatSourceModels
using Foam::constant::mathematical::pi;
-// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
-
Foam::heatSourceModels::modifiedSuperGaussian::modifiedSuperGaussian
(
- const word& sourceName,
const dictionary& dict,
const fvMesh& mesh
)
:
- heatSourceModel(typeName, sourceName, dict, mesh),
- mesh_(mesh)
-{
- k_ = heatSourceModelCoeffs_.lookup("k");
- m_ = heatSourceModelCoeffs_.lookup("m");
-}
-
-
-// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
-
-inline Foam::scalar
-Foam::heatSourceModels::modifiedSuperGaussian::weight(const vector& d)
-{
- scalar a = Foam::pow(2.0, 1.0/k_);
-
- vector s = cmptDivide(dimensions_, vector(a, a, 1.0));
-
- const scalar z = mag(d.z());
-
- if (z < s.z())
- {
- s *= Foam::pow(1.0 - Foam::pow(z / s.z(), m_), 1.0/m_);
-
- vector di = vector(d.x(), d.y(), 0.0);
-
- scalar x = Foam::pow(magSqr(cmptDivide(di, s)), k_/2.0);
-
- return Foam::exp(-x);
- }
- else
- {
- return 0.0;
- }
-}
-
-inline Foam::dimensionedScalar
-Foam::heatSourceModels::modifiedSuperGaussian::V0()
+ heatSourceModel(dict),
+ radius_(dict.lookup("radius")),
+ k_(dict.lookup("k")),
+ m_(dict.lookup("m")),
+ coefficient_
+ (
+ heatSourceProfiles::superGaussian::coefficient(dict, k_)
+ ),
+ cosTheta_(0),
+ sinTheta_(0),
+ metrics_()
{
- const scalar a = Foam::pow(2.0, 1.0/k_);
-
- const vector s = cmptDivide(dimensions_, vector(a, a, 1.0));
-
- const dimensionedScalar V0
+ const scalar variance =
+ 0.5*Foam::tgamma(4.0/k_)/Foam::tgamma(2.0/k_);
+
+ const scalar azimuth =
+ dict.lookupOrDefault("azimuth", 0)*pi/180.0;
+ cosTheta_ = Foam::cos(azimuth);
+ sinTheta_ = Foam::sin(azimuth);
+ const scalar sx2 = sqr(radius_.x())/coefficient_;
+ const scalar sy2 = sqr(radius_.y())/coefficient_;
+
+ const scalar integral =
+ pi*radius_.x()*radius_.y()/coefficient_
+ *Foam::tgamma(1.0 + 2.0/k_);
+ const scalar varianceX =
+ sqr(cosTheta_)*sx2*variance
+ + sqr(sinTheta_)*sy2*variance;
+ const scalar varianceY =
+ sqr(sinTheta_)*sx2*variance
+ + sqr(cosTheta_)*sy2*variance;
+ const scalar covariance =
+ cosTheta_*sinTheta_*(sx2 - sy2)*variance;
+
+ metrics_.reset
(
- "V0",
- dimVolume,
- s.x()*s.y()*s.z()*pi*Foam::tgamma(1.0 + 2.0/k_)
- * Foam::tgamma(1.0 + 1.0/m_)*Foam::tgamma(1.0 + 2.0/m_)
- / Foam::tgamma(1.0 + 3.0/m_)
+ integral,
+ 0,
+ 0,
+ integral*varianceX,
+ integral*varianceY,
+ integral*covariance
);
- return V0;
+ update(depth_, 0);
}
-bool Foam::heatSourceModels::modifiedSuperGaussian::read()
+
+void Foam::heatSourceModels::modifiedSuperGaussian::update
+(
+ const scalar depth,
+ const scalar
+)
{
- if (heatSourceModel::read())
- {
- heatSourceModelCoeffs_ = optionalSubDict(type() + "Coeffs");
+ sourceDepth_ = depth;
+
+ const scalar fMax =
+ Foam::pow
+ (
+ invIncGammaRatio_P(2.0/k_, 1.0 - tolerance_),
+ 1.0/k_
+ );
+ const scalar xMax =
+ fMax/Foam::sqrt(coefficient_)
+ *Foam::sqrt
+ (
+ sqr(radius_.x()*cosTheta_)
+ + sqr(radius_.y()*sinTheta_)
+ );
+ const scalar yMax =
+ fMax/Foam::sqrt(coefficient_)
+ *Foam::sqrt
+ (
+ sqr(radius_.x()*sinTheta_)
+ + sqr(radius_.y()*cosTheta_)
+ );
+
+ bounds_ =
+ boundBox
+ (
+ point(-xMax, -yMax, -sourceDepth_),
+ point(xMax, yMax, 0)
+ );
+
+ V0_ =
+ dimensionedScalar
+ (
+ "V0",
+ dimVolume,
+ metrics_.integral()*sourceDepth_
+ *Foam::tgamma(1.0 + 1.0/m_)*Foam::tgamma(1.0 + 2.0/m_)
+ /Foam::tgamma(1.0 + 3.0/m_)
+ );
+}
- //- Mandatory entries
- heatSourceModelCoeffs_.lookup("k") >> k_;
- heatSourceModelCoeffs_.lookup("m") >> m_;
- return true;
- }
- else
+Foam::scalar Foam::heatSourceModels::modifiedSuperGaussian::weight
+(
+ const vector& r
+) const
+{
+ if (r.z() > 0 || r.z() <= -sourceDepth_)
{
- return false;
+ return 0;
}
-}
+ const scalar g =
+ Foam::pow
+ (
+ 1.0 - Foam::pow(-r.z()/sourceDepth_, m_),
+ 1.0/m_
+ );
+ const scalar x = cosTheta_*r.x() + sinTheta_*r.y();
+ const scalar y = -sinTheta_*r.x() + cosTheta_*r.y();
+ const scalar radiusSqr =
+ coefficient_
+ *(sqr(x/radius_.x()) + sqr(y/radius_.y()));
+
+ return Foam::exp(-Foam::pow(radiusSqr/sqr(g), k_/2.0));
+}
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/modifiedSuperGaussian/modifiedSuperGaussian.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/modifiedSuperGaussian/modifiedSuperGaussian.H
index 6cff6f9b..8c56ae9e 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/modifiedSuperGaussian/modifiedSuperGaussian.H
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/modifiedSuperGaussian/modifiedSuperGaussian.H
@@ -5,7 +5,7 @@
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2023 Oak Ridge National Laboratory
+ Copyright (C) 2023-2026 Oak Ridge National Laboratory
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -27,11 +27,7 @@ Class
Foam::heatSourceModels::modifiedSuperGaussian
Description
- modifiedSuperGaussian model.
-
- Reference:
- \verbatim
- \endverbatim
+ One-sided modified super-Gaussian heat source with finite depth.
SourceFiles
modifiedSuperGaussian.C
@@ -43,72 +39,53 @@ SourceFiles
#include "heatSourceModel.H"
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
namespace Foam
{
namespace heatSourceModels
{
-/*---------------------------------------------------------------------------*\
- Class modifiedSuperGaussian
-\*---------------------------------------------------------------------------*/
-
class modifiedSuperGaussian
:
public heatSourceModel
{
- // Private Data
-
- //- Pointer to mesh information
- const fvMesh& mesh_;
-
- //- Distribution shape coefficient of modifiedSuperGaussian distribution
- scalar k_;
-
- //- Geometric shape coefficient of modifiedSuperGaussian distribution
- scalar m_;
+ vector2D radius_;
+ scalar k_;
+ scalar m_;
+ scalar coefficient_;
+ scalar cosTheta_;
+ scalar sinTheta_;
+ profileMetrics metrics_;
public:
- //- Runtime type information
TypeName("modifiedSuperGaussian");
+ modifiedSuperGaussian
+ (
+ const dictionary& dict,
+ const fvMesh& mesh
+ );
- // Constructors
-
- //- Construct from components
- modifiedSuperGaussian
- (
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
- );
-
-
- //- Destructor
virtual ~modifiedSuperGaussian()
{}
+ virtual void update
+ (
+ const scalar depth,
+ const scalar aspectRatio
+ );
- // Member Functions
-
- inline virtual scalar weight(const vector& d);
+ virtual scalar weight(const vector& r) const;
- inline virtual dimensionedScalar V0();
-
- //- Read the heatSourceProperties dictionary
- virtual bool read();
+ inline virtual const profileMetrics& metrics() const
+ {
+ return metrics_;
+ }
};
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
} // End namespace heatSourceModels
} // End namespace Foam
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
#endif
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/nLightAFX/nLightAFX.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/nLightAFX/nLightAFX.C
deleted file mode 100644
index d1155341..00000000
--- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/nLightAFX/nLightAFX.C
+++ /dev/null
@@ -1,210 +0,0 @@
-/*---------------------------------------------------------------------------*\
- ========= |
- \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
- \\ / O peration | Website: https://openfoam.org
- \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
- \\/ M anipulation |
--------------------------------------------------------------------------------
- Copyright (C) 2023-2026 Oak Ridge National Laboratory
--------------------------------------------------------------------------------
-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 "nLightAFX.H"
-#include "addToRunTimeSelectionTable.H"
-
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
-
-namespace Foam
-{
-namespace heatSourceModels
-{
- defineTypeNameAndDebug(nLightAFX, 0);
- addToRunTimeSelectionTable(heatSourceModel, nLightAFX, dictionary);
-}
-}
-
-using Foam::constant::mathematical::pi;
-
-// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
-
-Foam::heatSourceModels::nLightAFX::nLightAFX
-(
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
-)
-:
- heatSourceModel(typeName, sourceName, dict, mesh),
- mesh_(mesh)
-{
- const dictionary innerDict
- (
- heatSourceModelCoeffs_.optionalSubDict("inner")
- );
-
- const dictionary outerDict
- (
- heatSourceModelCoeffs_.optionalSubDict("outer")
- );
-
- alpha_ = heatSourceModelCoeffs_.lookup("alpha");
-
- r0_ = innerDict.lookup("radius");
- sigma0_ = innerDict.lookup("sigma");
- A0_ = innerDict.lookup("A");
- B0_ = innerDict.lookup("B");
-
- r1_ = outerDict.lookup("radius");
- sigma1_ = outerDict.lookup("sigma");
- A1_ = outerDict.lookup("A");
- B1_ = outerDict.lookup("B");
-
- const scalar d = dimensions_.z();
-
- const scalar x =
- max
- (
- d/min(staticDimensions_.x(), staticDimensions_.y()),
- 0.001
- );
-
- const scalar p0 = min(max(A0_*std::log2(x) + B0_, 0.0), 9.0);
- const scalar p1 = min(max(A1_*std::log2(x) + B1_, 0.0), 9.0);
-
- n0_ = Foam::pow(2.0, p0);
- n1_ = Foam::pow(2.0, p1);
-
- a0_ = ai(r0_, sigma0_, d, n0_);
- a1_ = ai(r1_, sigma1_, d, n1_);
-}
-
-
-// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
-
-inline Foam::scalar
-Foam::heatSourceModels::nLightAFX::weight(const vector& x)
-{
- const scalar z = Foam::mag(x.z());
-
- const scalar r = Foam::sqrt(x.x()*x.x() + x.y()*x.y());
-
- const scalar d = dimensions_.z();
-
- const scalar x0 =
- std::exp(-0.5*Foam::sqr((r - r0_)/sigma0_))
- + std::exp(-0.5*Foam::sqr((r + r0_)/sigma0_));
-
- const scalar x1 =
- std::exp(-0.5*Foam::sqr((r - r1_)/sigma1_))
- + std::exp(-0.5*Foam::sqr((r + r1_)/sigma1_));
-
- const scalar s0 =
- std::exp(-3.0*Foam::pow(mag(z/d), n0_));
-
- const scalar s1 =
- std::exp(-3.0*Foam::pow(mag(z/d), n1_));
-
- return ((1.0 - alpha_)*x0*s0*a1_) + (alpha_*x1*s1*a0_);
-}
-
-
-inline Foam::scalar
-Foam::heatSourceModels::nLightAFX::ai
-(
- scalar x,
- scalar s,
- scalar d,
- scalar n
-)
-{
- const scalar t1 =
- 2.0*pi*s*d*Foam::tgamma(1.0/n)
- / (n*Foam::pow(3.0, 1.0/n));
-
- const scalar t2 =
- 2.0*s*std::exp(-0.5*Foam::sqr(x/s))
- + Foam::sqrt(2.0*pi)*x*Foam::erf(x/(Foam::sqrt(2.0)*s));
-
- return t1*t2;
-}
-
-
-inline Foam::dimensionedScalar
-Foam::heatSourceModels::nLightAFX::V0()
-{
- const scalar d = dimensions_.z();
-
- const scalar x =
- max
- (
- d/min(staticDimensions_.x(), staticDimensions_.y()),
- 0.001
- );
-
- const scalar p0 = min(max(A0_*std::log2(x) + B0_, 0.0), 9.0);
- const scalar p1 = min(max(A1_*std::log2(x) + B1_, 0.0), 9.0);
-
- n0_ = Foam::pow(2.0, p0);
- n1_ = Foam::pow(2.0, p1);
-
- a0_ = ai(r0_, sigma0_, d, n0_);
- a1_ = ai(r1_, sigma1_, d, n1_);
-
- return dimensionedScalar("V0", dimVolume, a0_*a1_);
-}
-
-
-bool Foam::heatSourceModels::nLightAFX::read()
-{
- if (heatSourceModel::read())
- {
- heatSourceModelCoeffs_ = optionalSubDict(type() + "Coeffs");
-
- const dictionary innerDict
- (
- heatSourceModelCoeffs_.optionalSubDict("inner")
- );
-
- const dictionary outerDict
- (
- heatSourceModelCoeffs_.optionalSubDict("outer")
- );
-
- heatSourceModelCoeffs_.lookup("alpha") >> alpha_;
-
- innerDict.lookup("radius") >> r0_;
- innerDict.lookup("sigma") >> sigma0_;
- innerDict.lookup("A") >> A0_;
- innerDict.lookup("B") >> B0_;
-
- outerDict.lookup("radius") >> r1_;
- outerDict.lookup("sigma") >> sigma1_;
- outerDict.lookup("A") >> A1_;
- outerDict.lookup("B") >> B1_;
-
- return true;
- }
- else
- {
- return false;
- }
-}
-
-
-// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/nLightAFX/nLightAFX.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/nLightAFX/nLightAFX.H
deleted file mode 100644
index bd18c90c..00000000
--- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/nLightAFX/nLightAFX.H
+++ /dev/null
@@ -1,145 +0,0 @@
-/*---------------------------------------------------------------------------*\
- ========= |
- \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
- \\ / O peration | Website: https://openfoam.org
- \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
- \\/ M anipulation |
--------------------------------------------------------------------------------
- Copyright (C) 2023-2026 Oak Ridge National Laboratory
--------------------------------------------------------------------------------
-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::heatSourceModels::nLightAFX
-
-Description
- nLight AFX heat source model for additive manufacturing
-
-SourceFiles
- nLightAFX.C
-
-\*---------------------------------------------------------------------------*/
-
-#ifndef nLightAFX_H
-#define nLightAFX_H
-
-#include "heatSourceModel.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-namespace Foam
-{
-namespace heatSourceModels
-{
-
-/*---------------------------------------------------------------------------*\
- Class nLightAFX
-\*---------------------------------------------------------------------------*/
-
-class nLightAFX
-:
- public heatSourceModel
-{
- // Private Data
-
- //- Pointer to mesh information
- const fvMesh& mesh_;
-
- //- Fraction of power applied to the outer component
- scalar alpha_;
-
- //- Radius of the inner Gaussian ring
- scalar r0_;
-
- //- Radius of the outer Gaussian ring
- scalar r1_;
-
- //- Standard deviation of the inner Gaussian ring
- scalar sigma0_;
-
- //- Standard deviation of the outer Gaussian ring
- scalar sigma1_;
-
- //- Inner axial decay coefficient in the form n = Alog2(x) + B
- scalar A0_;
-
- //- Inner axial decay coefficient in the form n = Alog2(x) + B
- scalar B0_;
-
- //- Outer axial decay coefficient in the form n = Alog2(x) + B
- scalar A1_;
-
- //- Outer axial decay coefficient in the form n = Alog2(x) + B
- scalar B1_;
-
- //- Inner axial decay exponent
- scalar n0_;
-
- //- Outer axial decay exponent
- scalar n1_;
-
- //- Inner normalization factor
- scalar a0_;
-
- //- Outer normalization factor
- scalar a1_;
-
-public:
-
- //- Runtime type information
- TypeName("nLightAFX");
-
-
- // Constructors
-
- //- Construct from components
- nLightAFX
- (
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
- );
-
-
- //- Destructor
- virtual ~nLightAFX()
- {}
-
-
- // Member Functions
-
- inline virtual scalar weight(const vector& d);
-
- inline scalar ai(scalar x, scalar s, scalar d, scalar n);
-
- inline virtual dimensionedScalar V0();
-
- //- Read the heatSourceProperties dictionary
- virtual bool read();
-};
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace heatSourceModels
-} // End namespace Foam
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-#endif
-
-// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/profileMetrics/profileMetrics.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/profileMetrics/profileMetrics.C
new file mode 100644
index 00000000..1c7a4bf1
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/profileMetrics/profileMetrics.C
@@ -0,0 +1,97 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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 "profileMetrics.H"
+
+Foam::profileMetrics::profileMetrics()
+:
+ integral_(0),
+ centroid_(vector2D::zero),
+ covariance_(symmTensor2D::zero),
+ D4Sigma_(vector2D::zero),
+ azimuth_(0)
+{}
+
+
+void Foam::profileMetrics::reset
+(
+ const scalar M00,
+ const scalar M10,
+ const scalar M01,
+ const scalar M20,
+ const scalar M02,
+ const scalar M11
+)
+{
+ if (!(M00 > 0))
+ {
+ FatalErrorInFunction
+ << "Profile integral must be positive, found " << M00
+ << exit(FatalError);
+ }
+
+ integral_ = M00;
+
+ centroid_.x() = M10/M00;
+
+ centroid_.y() = M01/M00;
+
+ scalar varianceX = M20/M00 - sqr(centroid_.x());
+
+ scalar varianceY = M02/M00 - sqr(centroid_.y());
+
+ const scalar covariance = M11/M00 - centroid_.x()*centroid_.y();
+
+ varianceX = max(varianceX, 0.0);
+
+ varianceY = max(varianceY, 0.0);
+
+ covariance_ = symmTensor2D(varianceX, covariance, varianceY);
+
+ const scalar meanVariance = 0.5*(varianceX + varianceY);
+
+ const scalar delta =
+ Foam::sqrt(0.25*sqr(varianceX - varianceY) + sqr(covariance));
+
+ const scalar majorVariance = meanVariance + delta;
+
+ scalar minorVariance = meanVariance - delta;
+
+ minorVariance = max(minorVariance, 0.0);
+
+ D4Sigma_.x() = 4.0*Foam::sqrt(majorVariance);
+
+ D4Sigma_.y() = 4.0*Foam::sqrt(minorVariance);
+
+ const scalar circularTolerance = rootSmall*max(meanVariance, VSMALL);
+
+ azimuth_ =
+ delta > circularTolerance
+ ? 0.5*Foam::atan2(2.0*covariance, varianceX - varianceY)
+ : 0.0;
+}
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/profileMetrics/profileMetrics.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/profileMetrics/profileMetrics.H
new file mode 100644
index 00000000..4a704b29
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/profileMetrics/profileMetrics.H
@@ -0,0 +1,104 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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::profileMetrics
+
+Description
+ Integral and second-moment metrics of an intensity distribution in the
+ beam plane. D4Sigma is ordered (major, minor).
+
+SourceFiles
+ profileMetrics.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef profileMetrics_H
+#define profileMetrics_H
+
+#include "scalar.H"
+#include "symmTensor2D.H"
+#include "vector2D.H"
+
+namespace Foam
+{
+
+class profileMetrics
+{
+ scalar integral_;
+
+ vector2D centroid_;
+
+ symmTensor2D covariance_;
+
+ vector2D D4Sigma_;
+
+ scalar azimuth_;
+
+public:
+
+ profileMetrics();
+
+ void reset
+ (
+ const scalar M00,
+ const scalar M10,
+ const scalar M01,
+ const scalar M20,
+ const scalar M02,
+ const scalar M11
+ );
+
+ inline scalar integral() const
+ {
+ return integral_;
+ }
+
+ inline const vector2D& centroid() const
+ {
+ return centroid_;
+ }
+
+ inline const symmTensor2D& covariance() const
+ {
+ return covariance_;
+ }
+
+ inline const vector2D& D4Sigma() const
+ {
+ return D4Sigma_;
+ }
+
+ inline scalar azimuth() const
+ {
+ return azimuth_;
+ }
+};
+
+} // End namespace Foam
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/heatSourceProfile/heatSourceProfile.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/heatSourceProfile/heatSourceProfile.C
new file mode 100644
index 00000000..6e64d25d
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/heatSourceProfile/heatSourceProfile.C
@@ -0,0 +1,36 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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 "heatSourceProfile.H"
+
+namespace Foam
+{
+ defineTypeNameAndDebug(heatSourceProfile, 0);
+ defineRunTimeSelectionTable(heatSourceProfile, dictionary);
+}
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/heatSourceProfile/heatSourceProfile.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/heatSourceProfile/heatSourceProfile.H
new file mode 100644
index 00000000..3bb61f93
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/heatSourceProfile/heatSourceProfile.H
@@ -0,0 +1,115 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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::heatSourceProfile
+
+Description
+ Abstract base class for planar heat source profiles.
+
+SourceFiles
+ heatSourceProfile.C
+ heatSourceProfileNew.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef heatSourceProfile_H
+#define heatSourceProfile_H
+
+#include "autoPtr.H"
+#include "boundBox.H"
+#include "dictionary.H"
+#include "profileMetrics.H"
+#include "runTimeSelectionTables.H"
+
+namespace Foam
+{
+
+class fvMesh;
+
+class heatSourceProfile
+{
+public:
+
+ //- Runtime type information
+ TypeName("heatSourceProfile");
+
+ // Declare run-time constructor selection table
+ declareRunTimeSelectionTable
+ (
+ autoPtr,
+ heatSourceProfile,
+ dictionary,
+ (
+ const dictionary& dict,
+ const fvMesh& mesh,
+ const scalar tolerance
+ ),
+ (dict, mesh, tolerance)
+ );
+
+ // Constructors
+
+ heatSourceProfile()
+ {}
+
+ //- Disallow default bitwise copy construction
+ heatSourceProfile(const heatSourceProfile&);
+
+ // Selectors
+
+ static autoPtr New
+ (
+ const dictionary& dict,
+ const fvMesh& mesh,
+ const scalar tolerance
+ );
+
+ //- Destructor
+ virtual ~heatSourceProfile()
+ {}
+
+ // Member Functions
+
+ //- Return the profile weight
+ virtual scalar weight(const scalar x, const scalar y) const = 0;
+
+ //- Return metrics of the intensity profile in the beam plane
+ virtual const profileMetrics& metrics() const = 0;
+
+ //- Return the planar profile bounds
+ virtual const boundBox& bounds() const = 0;
+
+ // Member Operators
+
+ //- Disallow default bitwise assignment
+ void operator=(const heatSourceProfile&) = delete;
+};
+
+} // End namespace Foam
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/heatSourceProfile/heatSourceProfileNew.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/heatSourceProfile/heatSourceProfileNew.C
new file mode 100644
index 00000000..678bb609
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/heatSourceProfile/heatSourceProfileNew.C
@@ -0,0 +1,59 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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 "heatSourceProfile.H"
+
+Foam::autoPtr Foam::heatSourceProfile::New
+(
+ const dictionary& dict,
+ const fvMesh& mesh,
+ const scalar tolerance
+)
+{
+ const word profileType(dict.lookup("model"));
+
+ Info<< "Selecting heatSourceProfile " << profileType << endl;
+
+ const auto cstrIter = dictionaryConstructorTablePtr_->find(profileType);
+
+ if (cstrIter == dictionaryConstructorTablePtr_->end())
+ {
+ FatalErrorInFunction
+ << "Unknown " << heatSourceProfile::typeName << " type "
+ << profileType << nl << nl
+ << "Valid heatSourceProfiles are:" << endl
+ << dictionaryConstructorTablePtr_->sortedToc()
+ << exit(FatalError);
+ }
+
+ return autoPtr
+ (
+ cstrIter()(dict, mesh, tolerance)
+ );
+}
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/nLightAFX/nLightAFXProfile.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/nLightAFX/nLightAFXProfile.C
new file mode 100644
index 00000000..ba6db1a1
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/nLightAFX/nLightAFXProfile.C
@@ -0,0 +1,201 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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 "nLightAFXProfile.H"
+#include "addToRunTimeSelectionTable.H"
+#include "mathematicalConstants.H"
+
+namespace Foam
+{
+namespace heatSourceProfiles
+{
+ defineTypeNameAndDebug(nLightAFX, 0);
+ addToRunTimeSelectionTable
+ (
+ heatSourceProfile,
+ nLightAFX,
+ dictionary
+ );
+}
+}
+
+using Foam::constant::mathematical::pi;
+
+
+Foam::heatSourceProfiles::nLightAFX::nLightAFX
+(
+ const dictionary& dict,
+ const fvMesh&,
+ const scalar epsilon
+)
+:
+ alpha_(0),
+ r0_(0),
+ sigma0_(0),
+ r1_(0),
+ sigma1_(0),
+ J0_(0),
+ J1_(0),
+ metrics_(),
+ bounds_(point::zero, point::zero)
+{
+ alpha_ = dict.lookup("alpha");
+
+ r0_ = dict.lookup("r0");
+ sigma0_ = dict.lookup("sigma0");
+
+ r1_ = dict.lookup("r1");
+ sigma1_ = dict.lookup("sigma1");
+
+ J0_ = J(0, r0_, sigma0_);
+ J1_ = J(0, r1_, sigma1_);
+
+ const scalar integral = 2.0*pi*J0_;
+
+ const scalar r2 =
+ (1.0 - alpha_)*K(r0_, sigma0_)/J0_
+ + alpha_*K(r1_, sigma1_)/J1_;
+
+ metrics_.reset
+ (
+ integral,
+ 0,
+ 0,
+ 0.5*integral*r2,
+ 0.5*integral*r2,
+ 0
+ );
+
+ scalar rMax =
+ max
+ (
+ cutoff(r0_, sigma0_, J0_, epsilon),
+ cutoff(r1_, sigma1_, J1_, epsilon)
+ );
+
+ scalar rMin = 0;
+
+ // Bisect to radial tolerance
+ const label nIter = ceil(std::log2(1/small));
+
+ for (label i=0; i1e-8; ++i)
+ {
+ const scalar R = 0.5*(rMin + rMax);
+
+ const scalar epsilonR =
+ (1.0 - alpha_)*J(R, r0_, sigma0_)/J0_
+ + alpha_*J(R, r1_, sigma1_)/J1_;
+
+ (epsilonR > epsilon ? rMin : rMax) = R;
+ }
+
+ bounds_ =
+ boundBox
+ (
+ point(-rMax, -rMax, 0),
+ point(rMax, rMax, 0)
+ );
+}
+
+
+inline Foam::scalar Foam::heatSourceProfiles::nLightAFX::J
+(
+ const scalar R,
+ const scalar r,
+ const scalar sigma
+) const
+{
+ return
+ Foam::sqr(sigma)
+ *(
+ std::exp(-0.5 * Foam::sqr((R - r) / sigma))
+ + std::exp(-0.5 * Foam::sqr((R + r) / sigma))
+ )
+ + r*sigma*Foam::sqrt(0.5*pi)
+ *(
+ Foam::erfc((R - r)/(Foam::sqrt(2.0)*sigma))
+ - Foam::erfc((R + r)/(Foam::sqrt(2.0)*sigma))
+ );
+}
+
+
+inline Foam::scalar Foam::heatSourceProfiles::nLightAFX::K
+(
+ const scalar r,
+ const scalar sigma
+) const
+{
+ const scalar f = std::exp(-0.5*Foam::sqr(r/sigma));
+ const scalar e = Foam::erf(r/(Foam::sqrt(2.0)*sigma));
+
+ return
+ 2.0*Foam::sqr(sigma)
+ *(Foam::sqr(r) + 2.0*Foam::sqr(sigma))*f
+ + r*sigma*Foam::sqrt(2.0*pi)
+ *(Foam::sqr(r) + 3.0*Foam::sqr(sigma))*e;
+}
+
+
+inline Foam::scalar Foam::heatSourceProfiles::nLightAFX::cutoff
+(
+ const scalar r,
+ const scalar sigma,
+ const scalar J0,
+ const scalar epsilon
+) const
+{
+ // J(r + sigma*u) <= C*exp(-u^2/2)
+ const scalar C =
+ 2.0*Foam::sqr(sigma)
+ + r*sigma*Foam::sqrt(0.5*pi);
+
+ const scalar u2 = 2.0*max(std::log(C/(epsilon*J0)), 0.0);
+
+ return r + sigma*Foam::sqrt(u2);
+}
+
+
+inline Foam::scalar Foam::heatSourceProfiles::nLightAFX::weight
+(
+ const scalar x,
+ const scalar y
+) const
+{
+ const scalar r = Foam::sqrt(x*x + y*y);
+
+ const scalar I0 =
+ std::exp(-0.5*Foam::sqr((r - r0_)/sigma0_))
+ + std::exp(-0.5*Foam::sqr((r + r0_)/sigma0_));
+
+ const scalar I1 =
+ std::exp(-0.5*Foam::sqr((r - r1_)/sigma1_))
+ + std::exp(-0.5*Foam::sqr((r + r1_)/sigma1_));
+
+ return (1.0 - alpha_)*I0 + alpha_*I1*J0_/J1_;
+}
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/nLightAFX/nLightAFXProfile.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/nLightAFX/nLightAFXProfile.H
new file mode 100644
index 00000000..32740bcf
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/nLightAFX/nLightAFXProfile.H
@@ -0,0 +1,147 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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::heatSourceProfiles::nLightAFX
+
+Description
+ Two-component nLight AFX planar heat source profile.
+
+SourceFiles
+ nLightAFXProfile.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef nLightAFXProfile_H
+#define nLightAFXProfile_H
+
+#include "heatSourceProfile.H"
+
+namespace Foam
+{
+namespace heatSourceProfiles
+{
+
+class nLightAFX
+:
+ public heatSourceProfile
+{
+ // Private Data
+
+ //- Fraction of power applied to Gaussian component 1
+ scalar alpha_;
+
+ //- Radius of Gaussian component 0
+ scalar r0_;
+
+ //- Standard deviation of Gaussian component 0
+ scalar sigma0_;
+
+ //- Radius of Gaussian component 1
+ scalar r1_;
+
+ //- Standard deviation of Gaussian component 1
+ scalar sigma1_;
+
+ //- J_0(0)
+ scalar J0_;
+
+ //- J_1(0)
+ scalar J1_;
+
+ //- Exact planar moments and derived beam metrics
+ profileMetrics metrics_;
+
+ //- Planar profile bounds
+ boundBox bounds_;
+
+
+ // Private Member Functions
+
+ //- Return J(R) = integral_R^infinity I(r)*r dr
+ inline scalar J
+ (
+ const scalar R,
+ const scalar r,
+ const scalar sigma
+ ) const;
+
+ //- Return K = integral_0^infinity I(r)*r^3 dr
+ inline scalar K(const scalar r, const scalar sigma) const;
+
+ //- Guaranteed upper bound where J(R)/J(0) <= epsilon
+ inline scalar cutoff
+ (
+ const scalar r,
+ const scalar sigma,
+ const scalar J0,
+ const scalar epsilon
+ ) const;
+
+public:
+
+ //- Runtime type information
+ TypeName("nLightAFX");
+
+
+ // Constructors
+
+ nLightAFX
+ (
+ const dictionary& dict,
+ const fvMesh& mesh,
+ const scalar tolerance
+ );
+
+ //- Destructor
+ virtual ~nLightAFX()
+ {}
+
+ // Member Functions
+
+ inline virtual scalar weight
+ (
+ const scalar x,
+ const scalar y
+ ) const;
+
+ inline virtual const profileMetrics& metrics() const
+ {
+ return metrics_;
+ }
+
+ inline virtual const boundBox& bounds() const
+ {
+ return bounds_;
+ }
+
+};
+
+} // End namespace heatSourceProfiles
+} // End namespace Foam
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/superGaussian/superGaussianProfile.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/superGaussian/superGaussianProfile.C
new file mode 100644
index 00000000..f4e11ee9
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/superGaussian/superGaussianProfile.C
@@ -0,0 +1,161 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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 "superGaussianProfile.H"
+#include "addToRunTimeSelectionTable.H"
+#include "mathematicalConstants.H"
+
+namespace Foam
+{
+namespace heatSourceProfiles
+{
+ defineTypeNameAndDebug(superGaussian, 0);
+ addToRunTimeSelectionTable
+ (
+ heatSourceProfile,
+ superGaussian,
+ dictionary
+ );
+}
+}
+
+using Foam::constant::mathematical::pi;
+
+Foam::scalar
+Foam::heatSourceProfiles::superGaussian::coefficient
+(
+ const dictionary& dict,
+ const scalar k
+)
+{
+ const word definition(dict.lookupOrDefault("definition", "e2"));
+
+ if (definition == "e2")
+ {
+ return Foam::pow(2.0, 2.0/k);
+ }
+ if (definition == "secondMoment")
+ {
+ return
+ 2.0*Foam::tgamma(4.0/k)/Foam::tgamma(2.0/k);
+ }
+
+ FatalIOErrorInFunction(dict)
+ << "definition must be e2 or secondMoment, found " << definition
+ << exit(FatalIOError);
+
+ return 0;
+}
+
+
+Foam::heatSourceProfiles::superGaussian::superGaussian
+(
+ const dictionary& dict,
+ const fvMesh&,
+ const scalar tolerance
+)
+:
+ radius_(dict.lookup("radius")),
+ k_(dict.lookup("k")),
+ coefficient_(coefficient(dict, k_)),
+ cosTheta_(0),
+ sinTheta_(0),
+ metrics_(),
+ bounds_(point::zero, point::zero)
+{
+ const scalar variance =
+ 0.5*Foam::tgamma(4.0/k_)/Foam::tgamma(2.0/k_);
+ const scalar azimuth =
+ dict.lookupOrDefault("azimuth", 0)*pi/180.0;
+ cosTheta_ = Foam::cos(azimuth);
+ sinTheta_ = Foam::sin(azimuth);
+ const scalar sx2 = sqr(radius_.x())/coefficient_;
+ const scalar sy2 = sqr(radius_.y())/coefficient_;
+
+ const scalar integral =
+ pi*radius_.x()*radius_.y()/coefficient_
+ *Foam::tgamma(1.0 + 2.0/k_);
+ const scalar varianceX =
+ sqr(cosTheta_)*sx2*variance
+ + sqr(sinTheta_)*sy2*variance;
+ const scalar varianceY =
+ sqr(sinTheta_)*sx2*variance
+ + sqr(cosTheta_)*sy2*variance;
+ const scalar covariance =
+ cosTheta_*sinTheta_*(sx2 - sy2)*variance;
+
+ metrics_.reset
+ (
+ integral,
+ 0,
+ 0,
+ integral*varianceX,
+ integral*varianceY,
+ integral*covariance
+ );
+
+ const scalar fMax =
+ Foam::pow
+ (
+ invIncGammaRatio_P(2.0/k_, 1.0 - tolerance),
+ 1.0/k_
+ );
+ const scalar xMax =
+ fMax/Foam::sqrt(coefficient_)
+ *Foam::sqrt
+ (
+ sqr(radius_.x()*cosTheta_)
+ + sqr(radius_.y()*sinTheta_)
+ );
+ const scalar yMax =
+ fMax/Foam::sqrt(coefficient_)
+ *Foam::sqrt
+ (
+ sqr(radius_.x()*sinTheta_)
+ + sqr(radius_.y()*cosTheta_)
+ );
+
+ bounds_ =
+ boundBox(point(-xMax, -yMax, 0), point(xMax, yMax, 0));
+}
+
+
+Foam::scalar Foam::heatSourceProfiles::superGaussian::weight
+(
+ const scalar x,
+ const scalar y
+) const
+{
+ const scalar xr = cosTheta_*x + sinTheta_*y;
+ const scalar yr = -sinTheta_*x + cosTheta_*y;
+ const scalar radiusSqr =
+ coefficient_
+ *(sqr(xr/radius_.x()) + sqr(yr/radius_.y()));
+
+ return Foam::exp(-Foam::pow(radiusSqr, k_/2.0));
+}
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/superGaussian/superGaussianProfile.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/superGaussian/superGaussianProfile.H
new file mode 100644
index 00000000..1f93bcdb
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/superGaussian/superGaussianProfile.H
@@ -0,0 +1,98 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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::heatSourceProfiles::superGaussian
+
+Description
+ Planar elliptical super-Gaussian intensity profile. radius contains the
+ local x/y radii and need not be ordered. definition is e2 or secondMoment.
+
+SourceFiles
+ superGaussianProfile.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef superGaussianProfile_H
+#define superGaussianProfile_H
+
+#include "heatSourceProfile.H"
+
+namespace Foam
+{
+namespace heatSourceProfiles
+{
+
+class superGaussian
+:
+ public heatSourceProfile
+{
+ vector2D radius_;
+ scalar k_;
+ scalar coefficient_;
+ scalar cosTheta_;
+ scalar sinTheta_;
+ profileMetrics metrics_;
+ boundBox bounds_;
+
+public:
+
+ TypeName("superGaussian");
+
+ superGaussian
+ (
+ const dictionary& dict,
+ const fvMesh& mesh,
+ const scalar tolerance
+ );
+
+ static scalar coefficient
+ (
+ const dictionary& dict,
+ const scalar k
+ );
+
+ virtual ~superGaussian()
+ {}
+
+ virtual scalar weight(const scalar x, const scalar y) const;
+
+ inline virtual const profileMetrics& metrics() const
+ {
+ return metrics_;
+ }
+
+ inline virtual const boundBox& bounds() const
+ {
+ return bounds_;
+ }
+};
+
+} // End namespace heatSourceProfiles
+} // End namespace Foam
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/tabulated/tabulatedProfile.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/tabulated/tabulatedProfile.C
new file mode 100644
index 00000000..2170372c
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/tabulated/tabulatedProfile.C
@@ -0,0 +1,209 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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 "tabulatedProfile.H"
+#include "addToRunTimeSelectionTable.H"
+#include "fvMesh.H"
+#include "IFstream.H"
+
+namespace Foam
+{
+namespace heatSourceProfiles
+{
+ defineTypeNameAndDebug(tabulated, 0);
+ addToRunTimeSelectionTable
+ (
+ heatSourceProfile,
+ tabulated,
+ dictionary
+ );
+}
+}
+
+// * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::heatSourceProfiles::tabulated::tabulated()
+:
+ nx_(0),
+ ny_(0),
+ x0_(0),
+ y0_(0),
+ dx_(0),
+ dy_(0),
+ x1_(0),
+ y1_(0),
+ invDx_(0),
+ invDy_(0),
+ values_(0),
+ metrics_(),
+ bounds_(point::zero, point::zero)
+{}
+
+Foam::heatSourceProfiles::tabulated::tabulated(const fileName& profileFile)
+:
+ tabulated()
+{
+ read(profileFile);
+}
+
+
+Foam::heatSourceProfiles::tabulated::tabulated
+(
+ const dictionary& dict,
+ const fvMesh& mesh,
+ const scalar
+)
+:
+ tabulated()
+{
+ const fileName fName(dict.lookup("file"));
+
+ const fileName tableFile
+ (
+ mesh.time().rootPath()
+ /mesh.time().globalCaseName()
+ /mesh.time().constant()
+ /fName
+ );
+
+ read(tableFile);
+
+ Info<< "Tabulated profile: integral=" << metrics_.integral()
+ << ", centroid=" << metrics_.centroid() << " m"
+ << ", D4Sigma (major minor)=" << metrics_.D4Sigma() << " m"
+ << ", azimuth=" << metrics_.azimuth() << " rad" << endl;
+}
+
+// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * //
+
+void Foam::heatSourceProfiles::tabulated::integrate()
+{
+ // Raw moments M_pq = integral x^p*y^q*I(x,y) dx dy
+ scalar M00 = 0;
+ scalar M10 = 0;
+ scalar M01 = 0;
+ scalar M20 = 0;
+ scalar M02 = 0;
+ scalar M11 = 0;
+
+ for (label j=0; j> nx_ >> ny_;
+ is >> x0_ >> y0_;
+ is >> dx_ >> dy_;
+
+ if (nx_ < 2 || ny_ < 2 || dx_ <= 0 || dy_ <= 0)
+ {
+ FatalErrorInFunction
+ << "Tabulated profile requires nx, ny >= 2 and positive spacing; "
+ << "found nx=" << nx_ << ", ny=" << ny_ << ", dx=" << dx_
+ << ", dy=" << dy_ << exit(FatalError);
+ }
+
+ x1_ = x0_ + (nx_ - 1)*dx_;
+ y1_ = y0_ + (ny_ - 1)*dy_;
+ invDx_ = 1.0/dx_;
+ invDy_ = 1.0/dy_;
+
+ values_.setSize(nx_*ny_);
+
+ forAll(values_, i)
+ {
+ is >> values_[i];
+
+ if (!is.good() || values_[i] < 0)
+ {
+ FatalErrorInFunction
+ << "Tabulated profile values must be present and nonnegative; "
+ << "invalid value at index " << i << " in " << profileFile
+ << exit(FatalError);
+ }
+ }
+
+ integrate();
+
+ bounds_ =
+ boundBox
+ (
+ point(x0_, y0_, 0),
+ point(x1_, y1_, 0)
+ );
+}
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/tabulated/tabulatedProfile.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/tabulated/tabulatedProfile.H
new file mode 100644
index 00000000..3b51f93d
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/profiles/tabulated/tabulatedProfile.H
@@ -0,0 +1,189 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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::heatSourceProfiles::tabulated
+
+Description
+ Tabulated profile on a uniform two-dimensional grid, with exact integral
+ and second moments of its bilinear interpolant.
+
+SourceFiles
+ tabulatedProfile.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef tabulatedProfile_H
+#define tabulatedProfile_H
+
+#include "fileName.H"
+#include "heatSourceProfile.H"
+#include "scalarField.H"
+
+namespace Foam
+{
+namespace heatSourceProfiles
+{
+
+class tabulated
+:
+ public heatSourceProfile
+{
+ // Private Data
+
+ label nx_;
+ label ny_;
+
+ scalar x0_;
+ scalar y0_;
+ scalar dx_;
+ scalar dy_;
+ scalar x1_;
+ scalar y1_;
+ scalar invDx_;
+ scalar invDy_;
+
+ scalarField values_;
+
+ profileMetrics metrics_;
+
+ boundBox bounds_;
+
+ // Private Member Functions
+
+ void integrate();
+
+
+public:
+ //- Runtime type information
+ TypeName("tabulated");
+
+ // Constructors
+
+ tabulated();
+
+ explicit tabulated(const fileName& profileFile);
+
+ tabulated
+ (
+ const dictionary& dict,
+ const fvMesh& mesh,
+ const scalar tolerance
+ );
+
+ // Member Functions
+
+ void read(const fileName& profileFile);
+
+ inline virtual scalar weight
+ (
+ const scalar x,
+ const scalar y
+ ) const
+ {
+ return interpolate(x, y);
+ }
+
+ inline scalar interpolate(const scalar x, const scalar y) const
+ {
+ const scalar xp = (x - x0_)*invDx_;
+ const scalar yp = (y - y0_)*invDy_;
+
+ if (xp < 0 || xp > nx_ - 1 || yp < 0 || yp > ny_ - 1)
+ {
+ return 0;
+ }
+
+ const label i = min(label(xp), nx_ - 2);
+ const label j = min(label(yp), ny_ - 2);
+ const scalar tx = xp - i;
+ const scalar ty = yp - j;
+ const label index = i + nx_*j;
+
+ return
+ (1.0 - tx)*(1.0 - ty)*values_[index]
+ + tx*(1.0 - ty)*values_[index + 1]
+ + (1.0 - tx)*ty*values_[index + nx_]
+ + tx*ty*values_[index + nx_ + 1];
+ }
+
+ inline label nx() const
+ {
+ return nx_;
+ }
+
+ inline label ny() const
+ {
+ return ny_;
+ }
+
+ inline scalar x0() const
+ {
+ return x0_;
+ }
+
+ inline scalar y0() const
+ {
+ return y0_;
+ }
+
+ inline scalar x1() const
+ {
+ return x1_;
+ }
+
+ inline scalar y1() const
+ {
+ return y1_;
+ }
+
+ inline scalar dx() const
+ {
+ return dx_;
+ }
+
+ inline scalar dy() const
+ {
+ return dy_;
+ }
+
+ inline virtual const profileMetrics& metrics() const
+ {
+ return metrics_;
+ }
+
+ inline virtual const boundBox& bounds() const
+ {
+ return bounds_;
+ }
+
+};
+
+} // End namespace heatSourceProfiles
+} // End namespace Foam
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projected.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projected.C
new file mode 100644
index 00000000..bdf04f1f
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projected.C
@@ -0,0 +1,112 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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 "projected.H"
+#include "addToRunTimeSelectionTable.H"
+
+namespace Foam
+{
+namespace heatSourceModels
+{
+ defineTypeNameAndDebug(projected, 0);
+ addToRunTimeSelectionTable
+ (
+ heatSourceModel,
+ projected,
+ dictionary
+ );
+}
+}
+
+Foam::heatSourceModels::projected::projected
+(
+ const dictionary& dict,
+ const fvMesh& mesh
+)
+:
+ heatSourceModel(dict),
+ profile_
+ (
+ heatSourceProfile::New
+ (
+ dict.subDict("profile"),
+ mesh,
+ tolerance_/(1.0 + Foam::sqrt(1.0 - tolerance_))
+ )
+ ),
+ projection_(heatSourceProjection::New(dict.subDict("projection"))),
+ componentTolerance_
+ (
+ tolerance_/(1.0 + Foam::sqrt(1.0 - tolerance_))
+ )
+{
+ bounds_ = profile_->bounds();
+
+ Info<< "Beam-plane D4Sigma (major minor)="
+ << metrics().D4Sigma() << " m, azimuth="
+ << metrics().azimuth() << " rad" << endl;
+}
+
+
+void Foam::heatSourceModels::projected::update
+(
+ const scalar depth,
+ const scalar aspectRatio
+)
+{
+ sourceDepth_ = depth;
+
+ projection_->update
+ (
+ sourceDepth_,
+ aspectRatio,
+ componentTolerance_
+ );
+
+ bounds_.min().z() = projection_->zMin();
+ bounds_.max().z() = 0;
+
+ V0_ =
+ dimensionedScalar
+ (
+ "V0",
+ dimVolume,
+ metrics().integral()*projection_->integral()
+ );
+}
+
+
+Foam::scalar Foam::heatSourceModels::projected::weight
+(
+ const vector& r
+) const
+{
+ return
+ projection_->weight(r.z())
+ *profile_->weight(r.x(), r.y());
+}
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projected.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projected.H
new file mode 100644
index 00000000..68e4130f
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projected.H
@@ -0,0 +1,92 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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::heatSourceModels::projected
+
+Description
+ Separable heat source constructed from a planar beam profile and a
+ one-sided axial projection.
+
+SourceFiles
+ projected.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef projected_H
+#define projected_H
+
+#include "heatSourceModel.H"
+#include "heatSourceProfile.H"
+#include "heatSourceProjection.H"
+
+namespace Foam
+{
+namespace heatSourceModels
+{
+
+class projected
+:
+ public heatSourceModel
+{
+ autoPtr profile_;
+
+ autoPtr projection_;
+
+ scalar componentTolerance_;
+
+public:
+
+ TypeName("projected");
+
+ projected
+ (
+ const dictionary& dict,
+ const fvMesh& mesh
+ );
+
+ virtual ~projected()
+ {}
+
+ virtual void update
+ (
+ const scalar depth,
+ const scalar aspectRatio
+ );
+
+ virtual scalar weight(const vector& r) const;
+
+ inline virtual const profileMetrics& metrics() const
+ {
+ return profile_->metrics();
+ }
+};
+
+} // End namespace heatSourceModels
+} // End namespace Foam
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/exponential/exponential.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/exponential/exponential.C
new file mode 100644
index 00000000..f6dd6a42
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/exponential/exponential.C
@@ -0,0 +1,112 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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 "exponential.H"
+#include "addToRunTimeSelectionTable.H"
+
+namespace Foam
+{
+namespace heatSourceProjections
+{
+ defineTypeNameAndDebug(exponential, 0);
+ addToRunTimeSelectionTable
+ (
+ heatSourceProjection,
+ exponential,
+ dictionary
+ );
+}
+}
+
+Foam::heatSourceProjections::exponential::exponential
+(
+ const dictionary& dict
+)
+:
+ nSlope_(0),
+ nIntercept_(0),
+ depth_(0),
+ k_(1),
+ integral_(0),
+ zMin_(0)
+{
+ nSlope_ = dict.lookup("nSlope");
+ nIntercept_ = dict.lookup("nIntercept");
+
+}
+
+
+void Foam::heatSourceProjections::exponential::update
+(
+ const scalar depth,
+ const scalar aspectRatio,
+ const scalar tolerance
+)
+{
+ depth_ = depth;
+
+ const scalar n =
+ min
+ (
+ max
+ (
+ nSlope_*std::log2(max(aspectRatio, VSMALL)) + nIntercept_,
+ 0.0
+ ),
+ 9.0
+ );
+
+ k_ = Foam::pow(2.0, n);
+
+ integral_ =
+ depth_*Foam::tgamma(1.0/k_)
+ /(k_*Foam::pow(3.0, 1.0/k_));
+
+ zMin_ =
+ -depth_
+ *Foam::pow
+ (
+ invIncGammaRatio_P(1.0/k_, 1.0 - tolerance)/3.0,
+ 1.0/k_
+ );
+}
+
+
+inline Foam::scalar Foam::heatSourceProjections::exponential::weight
+(
+ const scalar z
+) const
+{
+ if (z > 0)
+ {
+ return 0;
+ }
+
+ return Foam::exp(-3.0*Foam::pow(-z/depth_, k_));
+}
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedGaussian/projectedGaussian.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/exponential/exponential.H
similarity index 52%
rename from applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedGaussian/projectedGaussian.H
rename to applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/exponential/exponential.H
index d6106887..38a9e830 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedGaussian/projectedGaussian.H
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/exponential/exponential.H
@@ -5,7 +5,7 @@
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2023-2026 Oak Ridge National Laboratory
+ Copyright (C) 2026 Oak Ridge National Laboratory
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -24,88 +24,90 @@ License
along with OpenFOAM. If not, see .
Class
- Foam::heatSourceModels::projectedGaussian
+ Foam::heatSourceProjections::exponential
Description
- projectedGaussian heat source model for additive manufacting
+ One-sided generalized exponential projection applied in the negative z
+ direction from the beam plane.
SourceFiles
- projectedGaussian.C
+ exponential.C
\*---------------------------------------------------------------------------*/
-#ifndef projectedGaussian_H
-#define projectedGaussian_H
+#ifndef exponential_H
+#define exponential_H
-#include "heatSourceModel.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+#include "heatSourceProjection.H"
namespace Foam
{
-namespace heatSourceModels
+namespace heatSourceProjections
{
-/*---------------------------------------------------------------------------*\
- Class projectedGaussian
-\*---------------------------------------------------------------------------*/
-
-class projectedGaussian
+class exponential
:
- public heatSourceModel
+ public heatSourceProjection
{
// Private Data
- //- Pointer to mesh information
- const fvMesh& mesh_;
+ //- nSlope in n = nSlope*log2(a) + nIntercept
+ scalar nSlope_;
+
+ //- nIntercept in n = nSlope*log2(a) + nIntercept
+ scalar nIntercept_;
- //- weights for axial decay of 2D gaussian distribution in the form:
- //- n = Alog2(x) + B
- scalar A_;
- scalar B_;
+ //- Projection depth
+ scalar depth_;
+ //- Axial decay exponent
scalar k_;
+ //- Projection integral
+ scalar integral_;
+
+ //- Lower projection bound
+ scalar zMin_;
+
public:
//- Runtime type information
- TypeName("projectedGaussian");
+ TypeName("exponential");
// Constructors
- //- Construct from components
- projectedGaussian
- (
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
- );
-
+ explicit exponential(const dictionary& dict);
//- Destructor
- virtual ~projectedGaussian()
+ virtual ~exponential()
{}
-
// Member Functions
- inline virtual scalar weight(const vector& d);
-
- inline virtual dimensionedScalar V0();
+ virtual void update
+ (
+ const scalar depth,
+ const scalar aspectRatio,
+ const scalar tolerance
+ );
- //- Read the heatSourceProperties dictionary
- virtual bool read();
-};
+ inline virtual scalar weight(const scalar z) const;
+ inline virtual scalar integral() const
+ {
+ return integral_;
+ }
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+ inline virtual scalar zMin() const
+ {
+ return zMin_;
+ }
+};
-} // End namespace heatSourceModels
+} // End namespace heatSourceProjections
} // End namespace Foam
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
#endif
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/heatSourceProjection/heatSourceProjection.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/heatSourceProjection/heatSourceProjection.C
new file mode 100644
index 00000000..0fdfa0f1
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/heatSourceProjection/heatSourceProjection.C
@@ -0,0 +1,36 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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 "heatSourceProjection.H"
+
+namespace Foam
+{
+ defineTypeNameAndDebug(heatSourceProjection, 0);
+ defineRunTimeSelectionTable(heatSourceProjection, dictionary);
+}
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/heatSourceProjection/heatSourceProjection.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/heatSourceProjection/heatSourceProjection.H
new file mode 100644
index 00000000..2be30b2c
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/heatSourceProjection/heatSourceProjection.H
@@ -0,0 +1,110 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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::heatSourceProjection
+
+Description
+ Abstract base class for one-dimensional heat source projections.
+
+SourceFiles
+ heatSourceProjection.C
+ heatSourceProjectionNew.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef heatSourceProjection_H
+#define heatSourceProjection_H
+
+#include "autoPtr.H"
+#include "dictionary.H"
+#include "runTimeSelectionTables.H"
+
+namespace Foam
+{
+
+class heatSourceProjection
+{
+public:
+
+ //- Runtime type information
+ TypeName("heatSourceProjection");
+
+ // Declare run-time constructor selection table
+ declareRunTimeSelectionTable
+ (
+ autoPtr,
+ heatSourceProjection,
+ dictionary,
+ (const dictionary& dict),
+ (dict)
+ );
+
+ // Constructors
+
+ heatSourceProjection()
+ {}
+
+ //- Disallow default bitwise copy construction
+ heatSourceProjection(const heatSourceProjection&);
+
+ // Selectors
+
+ static autoPtr New(const dictionary& dict);
+
+ //- Destructor
+ virtual ~heatSourceProjection()
+ {}
+
+ // Member Functions
+
+ //- Update the projection state
+ virtual void update
+ (
+ const scalar depth,
+ const scalar aspectRatio,
+ const scalar tolerance
+ ) = 0;
+
+ //- Return the projection weight
+ virtual scalar weight(const scalar z) const = 0;
+
+ //- Return the projection integral
+ virtual scalar integral() const = 0;
+
+ //- Return the lower projection bound
+ virtual scalar zMin() const = 0;
+
+ // Member Operators
+
+ //- Disallow default bitwise assignment
+ void operator=(const heatSourceProjection&) = delete;
+};
+
+} // End namespace Foam
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/heatSourceProjection/heatSourceProjectionNew.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/heatSourceProjection/heatSourceProjectionNew.C
new file mode 100644
index 00000000..609a1529
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projected/projections/heatSourceProjection/heatSourceProjectionNew.C
@@ -0,0 +1,57 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2026 Oak Ridge National Laboratory
+-------------------------------------------------------------------------------
+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 "heatSourceProjection.H"
+
+Foam::autoPtr Foam::heatSourceProjection::New
+(
+ const dictionary& dict
+)
+{
+ const word projectionType(dict.lookup("model"));
+
+ Info<< "Selecting heatSourceProjection " << projectionType << endl;
+
+ const auto cstrIter = dictionaryConstructorTablePtr_->find(projectionType);
+
+ if (cstrIter == dictionaryConstructorTablePtr_->end())
+ {
+ FatalErrorInFunction
+ << "Unknown " << heatSourceProjection::typeName << " type "
+ << projectionType << nl << nl
+ << "Valid heatSourceProjections are:" << endl
+ << dictionaryConstructorTablePtr_->sortedToc()
+ << exit(FatalError);
+ }
+
+ return autoPtr
+ (
+ cstrIter()(dict)
+ );
+}
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedGaussian/projectedGaussian.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedGaussian/projectedGaussian.C
deleted file mode 100644
index 62a40899..00000000
--- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedGaussian/projectedGaussian.C
+++ /dev/null
@@ -1,139 +0,0 @@
-/*---------------------------------------------------------------------------*\
- ========= |
- \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
- \\ / O peration | Website: https://openfoam.org
- \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
- \\/ M anipulation |
--------------------------------------------------------------------------------
- Copyright (C) 2023-2026 Oak Ridge National Laboratory
--------------------------------------------------------------------------------
-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 "projectedGaussian.H"
-#include "addToRunTimeSelectionTable.H"
-
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
-
-namespace Foam
-{
-namespace heatSourceModels
-{
- defineTypeNameAndDebug(projectedGaussian, 0);
- addToRunTimeSelectionTable(heatSourceModel, projectedGaussian, dictionary);
-}
-}
-
-using Foam::constant::mathematical::pi;
-
-// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
-
-Foam::heatSourceModels::projectedGaussian::projectedGaussian
-(
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
-)
-:
- heatSourceModel(typeName, sourceName, dict, mesh),
- mesh_(mesh)
-{
- A_ = heatSourceModelCoeffs_.lookup("A");
- B_ = heatSourceModelCoeffs_.lookup("B");
-
- // set initial shape function
- const scalar x_ =
- max
- (
- dimensions_.z()
- / min(staticDimensions_.x(), staticDimensions_.y()),
- 0.001
- );
- const scalar n_ = min(max(A_*std::log2(x_) + B_, 0.0), 9.0);
- k_ = std::pow(2.0, n_);
-}
-
-
-// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
-
-inline Foam::scalar
-Foam::heatSourceModels::projectedGaussian::weight(const vector& d)
-{
- const scalar f_ =
- std::exp
- (
- -2.0
- * (
- Foam::sqr(d.x() / dimensions_.x())
- + Foam::sqr(d.y() / dimensions_.y())
- )
- );
-
- const scalar s_ =
- std::exp(-3.0 * std::pow(mag(mag(d.z()) / dimensions_.z()), k_));
-
- return f_ * s_;
-}
-
-inline Foam::dimensionedScalar
-Foam::heatSourceModels::projectedGaussian::V0()
-{
- const scalar x_ =
- max
- (
- dimensions_.z()
- / min(staticDimensions_.x(), staticDimensions_.y()),
- 0.001
- );
-
- const scalar n_ = min(max(A_*std::log2(x_) + B_, 0.0), 9.0);
-
- k_ = std::pow(2.0, n_);
-
- const dimensionedScalar V0
- (
- "V0",
- dimVolume,
- 0.5 * pi * dimensions_.x() * dimensions_.y() * dimensions_.z()
- * Foam::tgamma(1.0 / k_)
- / ( k_ * std::pow(3.0, 1.0 / k_) )
- );
-
- return V0;
-}
-
-bool Foam::heatSourceModels::projectedGaussian::read()
-{
- if (heatSourceModel::read())
- {
- heatSourceModelCoeffs_ = optionalSubDict(type() + "Coeffs");
-
- //- Mandatory entries
- heatSourceModelCoeffs_.lookup("A") >> A_;
- heatSourceModelCoeffs_.lookup("B") >> B_;
-
- return true;
- }
- else
- {
- return false;
- }
-}
-
-
-// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/superGaussian/superGaussian.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/superGaussian/superGaussian.C
index 822e1781..99d00dd8 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/superGaussian/superGaussian.C
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/superGaussian/superGaussian.C
@@ -5,7 +5,7 @@
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2023 Oak Ridge National Laboratory
+ Copyright (C) 2023-2026 Oak Ridge National Laboratory
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -22,13 +22,12 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
-
\*---------------------------------------------------------------------------*/
#include "superGaussian.H"
+#include "superGaussianProfile.H"
#include "addToRunTimeSelectionTable.H"
-
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+#include "mathematicalConstants.H"
namespace Foam
{
@@ -41,65 +40,140 @@ namespace heatSourceModels
using Foam::constant::mathematical::pi;
-// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
-
Foam::heatSourceModels::superGaussian::superGaussian
(
- const word& sourceName,
const dictionary& dict,
const fvMesh& mesh
)
:
- heatSourceModel(typeName, sourceName, dict, mesh),
- mesh_(mesh)
+ heatSourceModel(dict),
+ radius_(dict.lookup("radius")),
+ k_(dict.lookup("k")),
+ coefficient_
+ (
+ heatSourceProfiles::superGaussian::coefficient(dict, k_)
+ ),
+ cosTheta_(0),
+ sinTheta_(0),
+ metrics_()
{
- k_ = heatSourceModelCoeffs_.lookup("k");
-}
+ const scalar variance =
+ 0.5*Foam::tgamma(4.0/k_)/Foam::tgamma(2.0/k_);
+ const scalar azimuth =
+ dict.lookupOrDefault("azimuth", 0)*pi/180.0;
-// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
+ cosTheta_ = Foam::cos(azimuth);
-inline Foam::scalar
-Foam::heatSourceModels::superGaussian::weight(const vector& d)
-{
- vector s = dimensions_ / Foam::pow(2.0, 1.0/k_);
+ sinTheta_ = Foam::sin(azimuth);
- scalar x = Foam::pow(magSqr(cmptDivide(d, s)), k_/2.0);
+ const scalar sx2 = sqr(radius_.x())/coefficient_;
- return Foam::exp(-x);
-}
+ const scalar sy2 = sqr(radius_.y())/coefficient_;
-inline Foam::dimensionedScalar
-Foam::heatSourceModels::superGaussian::V0()
-{
- vector s = dimensions_ / Foam::pow(2.0, 1.0/k_);
+ const scalar integral =
+ pi*radius_.x()*radius_.y()/coefficient_
+ *Foam::tgamma(1.0 + 2.0/k_);
+
+ const scalar varianceX =
+ sqr(cosTheta_)*sx2*variance
+ + sqr(sinTheta_)*sy2*variance;
+
+ const scalar varianceY =
+ sqr(sinTheta_)*sx2*variance
+ + sqr(cosTheta_)*sy2*variance;
- const dimensionedScalar V0
+ const scalar covariance =
+ cosTheta_*sinTheta_*(sx2 - sy2)*variance;
+
+ metrics_.reset
(
- "V0",
- dimVolume,
- (2.0 / 3.0)*s.x()*s.y()*s.z()*pi*Foam::tgamma(1.0 + 3.0/k_)
+ integral,
+ 0,
+ 0,
+ integral*varianceX,
+ integral*varianceY,
+ integral*covariance
);
- return V0;
+ update(depth_, 0);
}
-bool Foam::heatSourceModels::superGaussian::read()
+
+void Foam::heatSourceModels::superGaussian::update
+(
+ const scalar depth,
+ const scalar
+)
{
- if (heatSourceModel::read())
- {
- heatSourceModelCoeffs_ = optionalSubDict(type() + "Coeffs");
+ sourceDepth_ = depth;
+
+ const scalar fMax =
+ Foam::pow
+ (
+ invIncGammaRatio_P(3.0/k_, 1.0 - tolerance_),
+ 1.0/k_
+ );
+
+ const scalar xMax =
+ fMax/Foam::sqrt(coefficient_)
+ *Foam::sqrt
+ (
+ sqr(radius_.x()*cosTheta_)
+ + sqr(radius_.y()*sinTheta_)
+ );
+
+ const scalar yMax =
+ fMax/Foam::sqrt(coefficient_)
+ *Foam::sqrt
+ (
+ sqr(radius_.x()*sinTheta_)
+ + sqr(radius_.y()*cosTheta_)
+ );
+
+ const scalar zMax = fMax*sourceDepth_/Foam::pow(2.0, 1.0/k_);
+
+ bounds_ =
+ boundBox
+ (
+ point(-xMax, -yMax, -zMax),
+ point(xMax, yMax, 0)
+ );
+
+ V0_ =
+ dimensionedScalar
+ (
+ "V0",
+ dimVolume,
+ (2.0/3.0)*pi*radius_.x()*radius_.y()*sourceDepth_
+ /(coefficient_*Foam::pow(2.0, 1.0/k_))
+ *Foam::tgamma(1.0 + 3.0/k_)
+ );
+}
- //- Mandatory entries
- heatSourceModelCoeffs_.lookup("k") >> k_;
- return true;
- }
- else
+Foam::scalar Foam::heatSourceModels::superGaussian::weight
+(
+ const vector& r
+) const
+{
+ if (r.z() > 0)
{
- return false;
+ return 0;
}
-}
+ const scalar x = cosTheta_*r.x() + sinTheta_*r.y();
+
+ const scalar y = -sinTheta_*r.x() + cosTheta_*r.y();
+
+ const scalar radiusSqr =
+ sqr(x/radius_.x()) + sqr(y/radius_.y());
+
+ const scalar f =
+ coefficient_*radiusSqr
+ + Foam::pow(2.0, 2.0/k_)*sqr(r.z()/sourceDepth_);
+
+ return Foam::exp(-Foam::pow(f, k_/2.0));
+}
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/superGaussian/superGaussian.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/superGaussian/superGaussian.H
index 1532552a..3090eb57 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/superGaussian/superGaussian.H
+++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/superGaussian/superGaussian.H
@@ -5,7 +5,7 @@
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
- Copyright (C) 2023 Oak Ridge National Laboratory
+ Copyright (C) 2023-2026 Oak Ridge National Laboratory
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@@ -27,7 +27,8 @@ Class
Foam::heatSourceModels::superGaussian
Description
- superGaussian heat source model for additive manufacting
+ One-sided volumetric super-Gaussian heat source. definition applies to
+ radius; depth always specifies the axial depth.
SourceFiles
superGaussian.C
@@ -39,69 +40,57 @@ SourceFiles
#include "heatSourceModel.H"
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
namespace Foam
{
namespace heatSourceModels
{
-/*---------------------------------------------------------------------------*\
- Class superGaussian
-\*---------------------------------------------------------------------------*/
-
class superGaussian
:
public heatSourceModel
{
- // Private Data
+ vector2D radius_;
- //- Pointer to mesh information
- const fvMesh& mesh_;
+ scalar k_;
- //- Shape coefficient of supergaussian distribution
- scalar k_;
+ scalar coefficient_;
-public:
+ scalar cosTheta_;
- //- Runtime type information
- TypeName("superGaussian");
+ scalar sinTheta_;
+ profileMetrics metrics_;
- // Constructors
+public:
- //- Construct from components
- superGaussian
- (
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
- );
+ TypeName("superGaussian");
+ superGaussian
+ (
+ const dictionary& dict,
+ const fvMesh& mesh
+ );
- //- Destructor
virtual ~superGaussian()
{}
+ virtual void update
+ (
+ const scalar depth,
+ const scalar aspectRatio
+ );
- // Member Functions
-
- inline virtual scalar weight(const vector& d);
-
- inline virtual dimensionedScalar V0();
+ virtual scalar weight(const vector& r) const;
- //- Read the heatSourceProperties dictionary
- virtual bool read();
+ inline virtual const profileMetrics& metrics() const
+ {
+ return metrics_;
+ }
};
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
} // End namespace heatSourceModels
} // End namespace Foam
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
#endif
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/tabulated/tabulated.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/tabulated/tabulated.C
deleted file mode 100644
index 92717465..00000000
--- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/tabulated/tabulated.C
+++ /dev/null
@@ -1,243 +0,0 @@
-/*---------------------------------------------------------------------------*\
- ========= |
- \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
- \\ / O peration | Website: https://openfoam.org
- \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
- \\/ M anipulation |
--------------------------------------------------------------------------------
- Copyright (C) 2023-2026 Oak Ridge National Laboratory
--------------------------------------------------------------------------------
-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 "tabulated.H"
-#include "addToRunTimeSelectionTable.H"
-#include "IFstream.H"
-
-// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
-
-namespace Foam
-{
-namespace heatSourceModels
-{
- defineTypeNameAndDebug(tabulated, 0);
- addToRunTimeSelectionTable(heatSourceModel, tabulated, dictionary);
-}
-}
-
-// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
-
-Foam::heatSourceModels::tabulated::tabulated
-(
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
-)
-:
- heatSourceModel(typeName, sourceName, dict, mesh),
- mesh_(mesh),
- A_(Zero),
- B_(Zero),
- k_(Zero),
- x0_(Zero),
- y0_(Zero),
- dx_(Zero),
- dy_(Zero),
- invDx_(Zero),
- invDy_(Zero),
- nx_(Zero),
- ny_(Zero),
- f_(0),
- Axy_(Zero)
-{
- A_ = heatSourceModelCoeffs_.lookup("A");
- B_ = heatSourceModelCoeffs_.lookup("B");
-
- const fileName fName(heatSourceModelCoeffs_.lookup("file"));
-
- const fileName tableFile
- (
- mesh_.time().rootPath()
- /mesh_.time().globalCaseName()
- /mesh_.time().constant()
- /fName
- );
-
- readTable(tableFile);
- integrateTable();
-
- const scalar x =
- max
- (
- dimensions_.z()/min(staticDimensions_.x(), staticDimensions_.y()),
- 0.001
- );
-
- const scalar n = min(max(A_*std::log2(x) + B_, 0.0), 9.0);
-
- k_ = std::pow(2.0, n);
-}
-
-
-// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
-
-void Foam::heatSourceModels::tabulated::readTable(const fileName& tableFile)
-{
- IFstream is(tableFile);
-
- if (!is.good())
- {
- FatalIOErrorInFunction(heatSourceModelCoeffs_)
- << "Cannot find tabulated heat source file " << tableFile
- << exit(FatalIOError);
- }
-
- is >> nx_ >> ny_;
- is >> x0_ >> y0_;
- is >> dx_ >> dy_;
-
- invDx_ = 1.0/dx_;
- invDy_ = 1.0/dy_;
-
- f_.setSize(nx_*ny_);
-
- forAll(f_, i)
- {
- is >> f_[i];
- }
-}
-
-
-void Foam::heatSourceModels::tabulated::integrateTable()
-{
- Axy_ = Zero;
-
- for (label j=0; j nx_ - 1 || yp < 0.0 || yp > ny_ - 1)
- {
- return 0.0;
- }
-
- label i = label(xp);
- label j = label(yp);
-
- i = min(i, nx_ - 2);
- j = min(j, ny_ - 2);
-
- const scalar tx = xp - i;
- const scalar ty = yp - j;
-
- const label id = i + nx_*j;
-
- const scalar f =
- (1.0 - tx)*(1.0 - ty)*f_[id]
- + tx*(1.0 - ty)*f_[id + 1]
- + (1.0 - tx)*ty*f_[id + nx_]
- + tx*ty*f_[id + nx_ + 1];
-
- const scalar s =
- std::exp(-3.0*std::pow(mag(d.z()/dimensions_.z()), k_));
-
- return f*s;
-}
-
-
-inline Foam::dimensionedScalar
-Foam::heatSourceModels::tabulated::V0()
-{
- const scalar x =
- max
- (
- dimensions_.z()/min(staticDimensions_.x(), staticDimensions_.y()),
- 0.001
- );
-
- const scalar n = min(max(A_*std::log2(x) + B_, 0.0), 9.0);
-
- k_ = std::pow(2.0, n);
-
- const dimensionedScalar V0
- (
- "V0",
- dimVolume,
- Axy_*dimensions_.z()*Foam::tgamma(1.0/k_)
- / (k_*std::pow(3.0, 1.0/k_))
- );
-
- return V0;
-}
-
-
-bool Foam::heatSourceModels::tabulated::read()
-{
- if (heatSourceModel::read())
- {
- heatSourceModelCoeffs_ = optionalSubDict(type() + "Coeffs");
-
- heatSourceModelCoeffs_.lookup("A") >> A_;
- heatSourceModelCoeffs_.lookup("B") >> B_;
-
- const fileName fName(heatSourceModelCoeffs_.lookup("file"));
-
- const fileName tableFile
- (
- mesh_.time().rootPath()
- /mesh_.time().globalCaseName()
- /mesh_.time().constant()
- /fName
- );
-
- readTable(tableFile);
- integrateTable();
-
- return true;
- }
- else
- {
- return false;
- }
-}
-
-
-// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/tabulated/tabulated.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/tabulated/tabulated.H
deleted file mode 100644
index 4239c3cd..00000000
--- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/tabulated/tabulated.H
+++ /dev/null
@@ -1,153 +0,0 @@
-/*---------------------------------------------------------------------------*\
- ========= |
- \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
- \\ / O peration | Website: https://openfoam.org
- \\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
- \\/ M anipulation |
--------------------------------------------------------------------------------
- Copyright (C) 2023-2026 Oak Ridge National Laboratory
--------------------------------------------------------------------------------
-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::heatSourceModels::tabulated
-
-Description
- Tabulated 2D heat source model with a projected axial distribution
-
-SourceFiles
- tabulated.C
-
-\*---------------------------------------------------------------------------*/
-
-#ifndef tabulated_H
-#define tabulated_H
-
-#include "heatSourceModel.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-namespace Foam
-{
-namespace heatSourceModels
-{
-
-/*---------------------------------------------------------------------------*\
- Class tabulated
-\*---------------------------------------------------------------------------*/
-
-class tabulated
-:
- public heatSourceModel
-{
- // Private Data
-
- //- Pointer to mesh information
- const fvMesh& mesh_;
-
- //- Axial decay coefficient in the form n = Alog2(x) + B
- scalar A_;
-
- //- Axial decay coefficient in the form n = Alog2(x) + B
- scalar B_;
-
- //- Axial decay exponent
- scalar k_;
-
- //- Minimum x coordinate of the table
- scalar x0_;
-
- //- Minimum y coordinate of the table
- scalar y0_;
-
- //- Uniform x spacing
- scalar dx_;
-
- //- Uniform y spacing
- scalar dy_;
-
- //- Inverse uniform x spacing
- scalar invDx_;
-
- //- Inverse uniform y spacing
- scalar invDy_;
-
- //- Number of x points
- label nx_;
-
- //- Number of y points
- label ny_;
-
- //- Tabulated planar intensity, stored as i + nx*j
- scalarField f_;
-
- //- Integrated planar distribution
- scalar Axy_;
-
-
- // Private Member Functions
-
- //- Read tabulated planar distribution
- void readTable(const fileName& tableFile);
-
- //- Integrate tabulated planar distribution
- void integrateTable();
-
-
-public:
-
- //- Runtime type information
- TypeName("tabulated");
-
-
- // Constructors
-
- //- Construct from components
- tabulated
- (
- const word& sourceName,
- const dictionary& dict,
- const fvMesh& mesh
- );
-
-
- //- Destructor
- virtual ~tabulated()
- {}
-
-
- // Member Functions
-
- inline virtual scalar weight(const vector& d);
-
- inline virtual dimensionedScalar V0();
-
- //- Read the heatSourceProperties dictionary
- virtual bool read();
-};
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-} // End namespace heatSourceModels
-} // End namespace Foam
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
-#endif
-
-// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/movingBeam/movingBeam.C b/applications/solvers/additiveFoam/movingHeatSource/movingBeam/movingBeam.C
index aeaba037..464bb153 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/movingBeam/movingBeam.C
+++ b/applications/solvers/additiveFoam/movingHeatSource/movingBeam/movingBeam.C
@@ -26,6 +26,7 @@ License
\*---------------------------------------------------------------------------*/
#include "movingBeam.H"
+#include
#include
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@@ -35,22 +36,17 @@ const Foam::scalar Foam::movingBeam::eps = 1e-10;
namespace Foam
{
defineTypeNameAndDebug(movingBeam, 0);
- defineRunTimeSelectionTable(movingBeam, dictionary);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::movingBeam::movingBeam
(
- const word& sourceName,
- const dictionary& dict,
+ const dictionary& sourceDict,
const Time& runTime
)
:
- sourceName_(sourceName),
- dict_(dict),
runTime_(runTime),
- beamDict_(dict_.optionalSubDict(sourceName_)),
path_(0),
index_(0),
position_(Zero),
@@ -60,16 +56,16 @@ Foam::movingBeam::movingBeam
hitPathIntervals_(true)
{
//- Get beam parameters
- deltaT_ = beamDict_.lookupOrDefault("deltaT", GREAT);
+ deltaT_ = sourceDict.lookupOrDefault("deltaT", GREAT);
- hitPathIntervals_ = beamDict_.lookupOrDefault
+ hitPathIntervals_ = sourceDict.lookupOrDefault
(
"hitPathIntervals",
true
);
//- Read scan path file
- readPath();
+ readPath(sourceDict.lookup("path"));
//- Initialize path index
if (path_.size())
@@ -99,27 +95,28 @@ Foam::movingBeam::movingBeam
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
-void Foam::movingBeam::readPath()
+void Foam::movingBeam::readPath(const fileName& pathName)
{
- const word pName_(beamDict_.lookup("pathName"));
-
- const fileName pFile_
+ const fileName pathFile
(
- runTime_.rootPath()/runTime_.globalCaseName()/runTime_.constant()/pName_
+ runTime_.rootPath()
+ /runTime_.globalCaseName()
+ /runTime_.constant()
+ /pathName
);
- std::ifstream is(pFile_);
+ std::ifstream is(pathFile);
if (!is.good())
{
FatalErrorInFunction
- << "Cannot find file " << pFile_
+ << "Cannot find file " << pathFile
<< nl
<< exit(FatalError);
}
else
{
- Info << "Reading scan path from: " << pFile_ << endl;
+ Info << "Reading scan path from: " << pathFile << endl;
}
std::string line;
diff --git a/applications/solvers/additiveFoam/movingHeatSource/movingBeam/movingBeam.H b/applications/solvers/additiveFoam/movingHeatSource/movingBeam/movingBeam.H
index 2a558a1d..804ff959 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/movingBeam/movingBeam.H
+++ b/applications/solvers/additiveFoam/movingHeatSource/movingBeam/movingBeam.H
@@ -24,14 +24,13 @@ License
along with OpenFOAM. If not, see .
Class
- Foam::movingBeams
+ Foam::movingBeam
Description
Class for individual moving beam heat sources
SourceFiles
movingBeam.C
- calculateQDot.C
\*---------------------------------------------------------------------------*/
@@ -40,13 +39,10 @@ SourceFiles
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-#include
-#include "fvc.H"
-#include "pathVector.H"
-#include "HashTable.H"
-#include "absorptionModel.H"
+#include "dictionary.H"
#include "DynamicList.H"
-#include "meshSearch.H"
+#include "pathVector.H"
+#include "Time.H"
namespace Foam
{
@@ -61,18 +57,9 @@ private:
// Private data
- //- Name of beam
- const word& sourceName_;
-
- //- Main moving heat source dictionary
- const dictionary& dict_;
-
//- Run time information
const Time& runTime_;
- //- Individual beam sub-dict
- const dictionary& beamDict_;
-
//- List of beam pathVectors
DynamicList path_;
@@ -104,49 +91,18 @@ public:
//- Runtime type information
TypeName("movingBeam");
- // Declare run-time constructor selection table
- declareRunTimeSelectionTable
- (
- autoPtr,
- movingBeam,
- dictionary,
- (
- const word& sourceName,
- const dictionary& dict,
- const Time& runTime
- ),
- (sourceName, dict, runTime)
- );
-
// Constructors
// Construct from time and dictionary
movingBeam
(
- const word& sourceName,
- const dictionary& dict,
+ const dictionary& sourceDict,
const Time& runTime
);
//- Disallow default bitwise copy construction
movingBeam(const movingBeam&);
- // Selectors
-
- //- Return a reference to the selected phaseChange model
- static autoPtr New
- (
- const word& sourceName,
- const dictionary& dict,
- const Time& runTime
- )
- {
- return autoPtr
- (
- new movingBeam(sourceName, dict, runTime)
- );
- }
-
//- Destructor
virtual ~movingBeam()
{}
@@ -196,7 +152,7 @@ public:
void move(const scalar time);
//- Read the path file
- void readPath();
+ void readPath(const fileName& pathName);
};
diff --git a/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/movingHeatSource.C b/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/movingHeatSource.C
new file mode 100644
index 00000000..7c30a118
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/movingHeatSource.C
@@ -0,0 +1,210 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2026 Oak Ridge National Laboratory
+ \\/ 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 "movingHeatSource.H"
+#include "fvc.H"
+#include "hexMatcher.H"
+#include "treeBoundBox.H"
+
+Foam::movingHeatSource::movingHeatSource
+(
+ const word& name,
+ const dictionary& sourceDict,
+ const fvMesh& mesh
+)
+:
+ name_(name),
+ mesh_(mesh),
+ beam_(sourceDict, mesh_.time()),
+ absorption_(absorptionModel::New(sourceDict.subDict("absorption"), mesh_)),
+ heatSource_
+ (
+ heatSourceModel::New
+ (
+ sourceDict.subDict("heatSource"),
+ mesh_
+ )
+ ),
+ references_(sourceDict, mesh_)
+{
+ update();
+}
+
+
+void Foam::movingHeatSource::update()
+{
+ references_.update
+ (
+ heatSource_->metrics(),
+ heatSource_->depth(),
+ beam_.position(),
+ heatSource_->bounds()
+ );
+
+ const scalar referenceDepth = references_.depth();
+ const scalar sourceDepth = max(heatSource_->depth(), referenceDepth);
+ heatSource_->update(sourceDepth, references_.aspectRatio());
+
+ if (references_.isothermDepth())
+ {
+ Info<< "referenceDepth: " << referenceDepth
+ << ", depth: " << sourceDepth << endl;
+ }
+}
+
+Foam::tmp Foam::movingHeatSource::qDot() const
+{
+ tmp tqDot
+ (
+ new volScalarField
+ (
+ IOobject
+ (
+ "qDot_" + name_,
+ mesh_.time().name(),
+ mesh_,
+ IOobject::NO_READ,
+ IOobject::NO_WRITE
+ ),
+ mesh_,
+ dimensionedScalar("zero", dimPower/dimVolume, 0)
+ )
+ );
+ volScalarField& qDot = tqDot.ref();
+
+ if (beam_.power() <= small)
+ {
+ return tqDot;
+ }
+
+ const vector position = beam_.position();
+ const boundBox& bounds = heatSource_->bounds();
+ const labelVector& nPoints = heatSource_->nPoints();
+ const dimensionedScalar absorbedPower
+ (
+ "etaP",
+ dimPower,
+ absorption_->eta(references_.aspectRatio())*beam_.power()
+ );
+ dimensionedScalar volume(heatSource_->V0());
+
+ volScalarField weights
+ (
+ IOobject
+ (
+ "weights_" + name_,
+ mesh_.time().name(),
+ mesh_,
+ IOobject::NO_READ,
+ IOobject::NO_WRITE
+ ),
+ mesh_,
+ dimensionedScalar("zero", dimless, 0)
+ );
+
+ const treeBoundBox currentBounds
+ (
+ position + bounds.min(),
+ position + bounds.max()
+ );
+ const pointField& points = mesh_.points();
+ hexMatcher hex;
+
+ forAll(mesh_.cells(), celli)
+ {
+ treeBoundBox cellBounds(point::max, point::min);
+ const labelList& vertices = mesh_.cellPoints()[celli];
+
+ forAll(vertices, i)
+ {
+ cellBounds.min() = min(cellBounds.min(), points[vertices[i]]);
+ cellBounds.max() = max(cellBounds.max(), points[vertices[i]]);
+ }
+
+ if (!cellBounds.overlaps(currentBounds))
+ {
+ continue;
+ }
+
+ if (!hex.isA(mesh_, celli))
+ {
+ weights[celli] =
+ heatSource_->weight(mesh_.cellCentres()[celli] - position);
+ continue;
+ }
+
+ vector dx = cmptDivide(bounds.span(), vector(nPoints));
+ const labelVector nSamples
+ (
+ max
+ (
+ cmptDivide(cellBounds.span() + small*vector::one, dx),
+ vector::one
+ )
+ );
+ dx = cmptDivide(cellBounds.span(), vector(nSamples));
+ const scalar dVi = dx.x()*dx.y()*dx.z();
+ scalar wi = 0;
+
+ for (label k=0; kweight(pt - position)*dVi;
+ }
+ }
+ }
+ }
+
+ weights[celli] = wi/mesh_.V()[celli];
+ }
+
+ const dimensionedScalar sumWeights = fvc::domainIntegrate(weights);
+ const scalar residual = (sumWeights/volume).value();
+
+ if (mag(1.0 - residual) < 0.05)
+ {
+ volume = sumWeights;
+ }
+
+ qDot = absorbedPower*weights/volume;
+ return tqDot;
+}
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/movingHeatSource.H b/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/movingHeatSource.H
new file mode 100644
index 00000000..782d78ab
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/movingHeatSource.H
@@ -0,0 +1,87 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2026 Oak Ridge National Laboratory
+ \\/ 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 .
+\*---------------------------------------------------------------------------*/
+
+#ifndef movingHeatSource_H
+#define movingHeatSource_H
+
+#include "absorptionModel.H"
+#include "heatSourceModel.H"
+#include "movingBeam.H"
+#include "referenceDimensions.H"
+#include "volFields.H"
+
+namespace Foam
+{
+
+class movingHeatSource
+{
+ word name_;
+ const fvMesh& mesh_;
+ movingBeam beam_;
+ autoPtr absorption_;
+ autoPtr heatSource_;
+ referenceDimensions references_;
+public:
+
+ movingHeatSource
+ (
+ const word& name,
+ const dictionary& sourceDict,
+ const fvMesh& mesh
+ );
+
+ movingHeatSource(const movingHeatSource&) = delete;
+
+ inline const word& name() const
+ {
+ return name_;
+ }
+
+ inline movingBeam& beam()
+ {
+ return beam_;
+ }
+
+ inline const movingBeam& beam() const
+ {
+ return beam_;
+ }
+
+ inline const heatSourceModel& heatSource() const
+ {
+ return heatSource_();
+ }
+
+ void update();
+
+ tmp qDot() const;
+
+ void operator=(const movingHeatSource&) = delete;
+};
+
+} // End namespace Foam
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/movingHeatSourceModel/movingHeatSourceModel.C b/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/movingHeatSources.C
similarity index 68%
rename from applications/solvers/additiveFoam/movingHeatSource/movingHeatSourceModel/movingHeatSourceModel.C
rename to applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/movingHeatSources.C
index 05b8c23d..c45623f9 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/movingHeatSourceModel/movingHeatSourceModel.C
+++ b/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/movingHeatSources.C
@@ -25,13 +25,11 @@ License
\*---------------------------------------------------------------------------*/
-#include "movingHeatSourceModel.H"
-#include "DynamicList.H"
-#include "OFstream.H"
+#include "movingHeatSources.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
-Foam::movingHeatSourceModel::movingHeatSourceModel
+Foam::movingHeatSources::movingHeatSources
(
const fvMesh& mesh
)
@@ -44,11 +42,10 @@ Foam::movingHeatSourceModel::movingHeatSourceModel
"heatSourceDict",
mesh_.time().constant(),
mesh_,
- IOobject::MUST_READ,
+ IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
),
- sourceNames_(dict_.lookup("sources")),
qDot_
(
IOobject
@@ -62,37 +59,45 @@ Foam::movingHeatSourceModel::movingHeatSourceModel
mesh_,
dimensionedScalar(dimPower/dimVolume, 0.0)
),
- refinementModel_(nullptr)
+ refinement_(nullptr)
{
- sources_.resize(sourceNames_.size());
+ readSources();
+}
+
+
+void Foam::movingHeatSources::readSources()
+{
+ const dictionary& sourcesDict = dict_.subDict("sources");
+ const wordList names(sourcesDict.toc());
+ sources_.clear();
+ sources_.resize(names.size());
- //- Create new instance of movingBeam for each beam
forAll(sources_, i)
{
- Info << "Adding heatSourceModel for " << sourceNames_[i] << endl;
+ Info << "Adding moving heat source " << names[i] << endl;
sources_.set
(
i,
- heatSourceModel::New
+ new movingHeatSource
(
- sourceNames_[i],
- dict_,
+ names[i],
+ sourcesDict.subDict(names[i]),
mesh_
- ).ptr()
+ )
);
}
- refinementModel_ = refinementModel::New(sources_, dict_, mesh_);
+ refinement_ = refinementModel::New(sources_, dict_, mesh_);
}
// * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * * //
-Foam::movingHeatSourceModel::~movingHeatSourceModel()
+Foam::movingHeatSources::~movingHeatSources()
{}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
-void Foam::movingHeatSourceModel::adjustDeltaT(scalar& deltaT)
+void Foam::movingHeatSources::adjustDeltaT(scalar& deltaT)
{
forAll(sources_, i)
{
@@ -100,29 +105,35 @@ void Foam::movingHeatSourceModel::adjustDeltaT(scalar& deltaT)
}
}
-void Foam::movingHeatSourceModel::update()
+void Foam::movingHeatSources::update()
{
- //- Subcycle each moving heat source in time and combine into a single field
+ if (dict_.readIfModified())
+ {
+ readSources();
+ }
+
qDot_ = dimensionedScalar("Zero", qDot_.dimensions(), 0.0);
forAll(sources_, i)
{
if (sources_[i].beam().activePath())
{
- sources_[i].updateDimensions();
+ sources_[i].update();
- // integrate volumetric heat source over desired time step
scalar pathTime = mesh_.time().value();
- const scalar nextTime = pathTime + mesh_.time().deltaTValue();
+ const scalar deltaT = mesh_.time().deltaTValue();
+
+ const scalar nextTime =
+ min(pathTime + deltaT, sources_[i].beam().endTime());
- const scalar beam_dt = sources_[i].beam().deltaT();
+ const scalar beamDeltaT = sources_[i].beam().deltaT();
- volScalarField qDoti
+ volScalarField sourceQDot
(
IOobject
(
- "qDoti",
+ "sourceQDot",
mesh_.time().name(),
mesh_
),
@@ -130,30 +141,26 @@ void Foam::movingHeatSourceModel::update()
dimensionedScalar("Zero", qDot_.dimensions(), 0.0)
);
- scalar sumWeights = 0.0;
-
while ((nextTime - pathTime) > small)
{
- scalar dt = min(beam_dt, max(0, nextTime - pathTime));
+ scalar dt = min(beamDeltaT, max(0, nextTime - pathTime));
pathTime += dt;
sources_[i].beam().move(pathTime);
- qDoti += dt*sources_[i].qDot();
-
- sumWeights += dt;
+ sourceQDot += dt*sources_[i].qDot();
}
- qDoti /= sumWeights;
+ sourceQDot /= deltaT;
- qDot_ += qDoti;
+ qDot_ += sourceQDot;
}
}
qDot_.correctBoundaryConditions();
- refinementModel_->update();
+ refinement_->update();
}
// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/movingHeatSourceModel/movingHeatSourceModel.H b/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/movingHeatSources.H
similarity index 83%
rename from applications/solvers/additiveFoam/movingHeatSource/movingHeatSourceModel/movingHeatSourceModel.H
rename to applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/movingHeatSources.H
index 2e5e5b67..7f479857 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/movingHeatSourceModel/movingHeatSourceModel.H
+++ b/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/movingHeatSources.H
@@ -24,34 +24,32 @@ License
along with OpenFOAM. If not, see .
Class
- Foam::movingHeatSourceModel
+ Foam::movingHeatSources
Description
- Class for multiple moving beam heat sources
+ Aggregate of moving heat sources.
SourceFiles
- movingHeatSourceModel.C
- calculateQDot.C
+ movingHeatSources.C
\*---------------------------------------------------------------------------*/
-#ifndef movingHeatSourceModel_H
-#define movingHeatSourceModel_H
+#ifndef movingHeatSources_H
+#define movingHeatSources_H
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-#include "heatSourceModel.H"
-#include "movingBeam.H"
+#include "movingHeatSource.H"
#include "refinementModel.H"
namespace Foam
{
/*---------------------------------------------------------------------------*\
- Class movingHeatSourceModel Declaration
+ Class movingHeatSources Declaration
\*---------------------------------------------------------------------------*/
-class movingHeatSourceModel
+class movingHeatSources
{
private:
@@ -63,30 +61,30 @@ private:
//- Main movingHeatSourceDict
IOdictionary dict_;
- //- List of individual heat sources
- wordList sourceNames_;
-
//- Total volumetric power of all beams
volScalarField qDot_;
//- Pointer list to each beam instance
- PtrList sources_;
+ PtrList sources_;
//- Pointer to refinement model
- autoPtr refinementModel_;
+ autoPtr refinement_;
+
+ //- Construct sources and refinement model from the dictionary
+ void readSources();
public:
// Constructors
// Construct from time and dictionary
- movingHeatSourceModel
+ movingHeatSources
(
const fvMesh& mesh
);
//- Destructor
- ~movingHeatSourceModel();
+ ~movingHeatSources();
// Member Functions
diff --git a/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/referenceDimensions.C b/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/referenceDimensions.C
new file mode 100644
index 00000000..8adf3350
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/referenceDimensions.C
@@ -0,0 +1,213 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2026 Oak Ridge National Laboratory
+ \\/ 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 "referenceDimensions.H"
+#include "PstreamReduceOps.H"
+#include "thermoPath.H"
+#include "volFields.H"
+
+Foam::referenceDimensions::referenceDimensions
+(
+ const dictionary& dict,
+ const fvMesh& mesh
+)
+:
+ mesh_(mesh),
+ widthReference_
+ (
+ dict.lookupOrDefault("widthReference", "D4Sigma")
+ ),
+ depthReference_
+ (
+ dict.lookupOrDefault("depthReference", "constant")
+ ),
+ component_(areaEquivalent),
+ isotherm_(0),
+ width_(0),
+ depth_(0)
+{
+ if (widthReference_ != "D4Sigma")
+ {
+ FatalIOErrorInFunction(dict)
+ << "widthReference must be D4Sigma, found "
+ << widthReference_ << exit(FatalIOError);
+ }
+
+ const word D4Sigma
+ (
+ dict.lookupOrDefault("D4Sigma", "areaEquivalent")
+ );
+
+ if (D4Sigma == "major")
+ {
+ component_ = major;
+ }
+ else if (D4Sigma == "minor")
+ {
+ component_ = minor;
+ }
+ else if (D4Sigma != "areaEquivalent")
+ {
+ FatalIOErrorInFunction(dict)
+ << "D4Sigma must be areaEquivalent, major, or minor, found "
+ << D4Sigma << exit(FatalIOError);
+ }
+
+ if (depthReference_ == "isotherm")
+ {
+ isotherm_ =
+ dict.lookupOrDefault
+ (
+ "isotherm",
+ thermoPath(mesh_).liquidus()
+ );
+ }
+ else if (depthReference_ != "constant")
+ {
+ FatalIOErrorInFunction(dict)
+ << "depthReference must be constant or isotherm, found "
+ << depthReference_ << exit(FatalIOError);
+ }
+}
+
+
+void Foam::referenceDimensions::update
+(
+ const profileMetrics& metrics,
+ const scalar depth,
+ const vector& position,
+ const boundBox& bounds
+)
+{
+ const vector2D& D4Sigma = metrics.D4Sigma();
+
+ if (component_ == major)
+ {
+ width_ = D4Sigma.x();
+ }
+ else if (component_ == minor)
+ {
+ width_ = D4Sigma.y();
+ }
+ else
+ {
+ width_ = Foam::sqrt(D4Sigma.x()*D4Sigma.y());
+ }
+
+ if (depthReference_ == "constant")
+ {
+ depth_ = depth;
+ return;
+ }
+
+ const volScalarField& T = mesh_.lookupObject("T");
+ const labelUList& owner = mesh_.owner();
+ const labelUList& neighbour = mesh_.neighbour();
+ const volVectorField& cc = mesh_.C();
+ depth_ = 0;
+
+ for (label facei=0; facei= isotherm_
+ )
+ {
+ const vector p =
+ cc[own]
+ + (cc[nei] - cc[own])
+ *(isotherm_ - T[own])/(T[nei] - T[own])
+ - position;
+
+ if
+ (
+ p.x() >= bounds.min().x()
+ && p.x() <= bounds.max().x()
+ && p.y() >= bounds.min().y()
+ && p.y() <= bounds.max().y()
+ && p.z() <= 0
+ )
+ {
+ depth_ = max(depth_, -p.z());
+ }
+ }
+ }
+
+ const volScalarField::Boundary& TBf = T.boundaryField();
+
+ forAll(TBf, patchi)
+ {
+ const fvPatchScalarField& TPf = TBf[patchi];
+
+ if (!TPf.coupled())
+ {
+ continue;
+ }
+
+ const labelUList& faceCells = TPf.patch().faceCells();
+ const vectorField ccn
+ (
+ cc.boundaryField()[patchi].patchNeighbourField()
+ );
+ const scalarField Tn(TPf.patchNeighbourField());
+
+ forAll(faceCells, facei)
+ {
+ const label own = faceCells[facei];
+
+ if
+ (
+ min(T[own], Tn[facei]) < isotherm_
+ && max(T[own], Tn[facei]) >= isotherm_
+ )
+ {
+ const vector p =
+ cc[own]
+ + (ccn[facei] - cc[own])
+ *(isotherm_ - T[own])/(Tn[facei] - T[own])
+ - position;
+
+ if
+ (
+ p.x() >= bounds.min().x()
+ && p.x() <= bounds.max().x()
+ && p.y() >= bounds.min().y()
+ && p.y() <= bounds.max().y()
+ && p.z() <= 0
+ )
+ {
+ depth_ = max(depth_, -p.z());
+ }
+ }
+ }
+ }
+
+ reduce(depth_, maxOp());
+}
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/referenceDimensions.H b/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/referenceDimensions.H
new file mode 100644
index 00000000..70f7bf52
--- /dev/null
+++ b/applications/solvers/additiveFoam/movingHeatSource/movingHeatSources/referenceDimensions.H
@@ -0,0 +1,96 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2026 Oak Ridge National Laboratory
+ \\/ 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 .
+\*---------------------------------------------------------------------------*/
+
+#ifndef referenceDimensions_H
+#define referenceDimensions_H
+
+#include "boundBox.H"
+#include "dictionary.H"
+#include "fvMesh.H"
+#include "profileMetrics.H"
+
+namespace Foam
+{
+
+class referenceDimensions
+{
+ enum D4SigmaComponent
+ {
+ areaEquivalent,
+ major,
+ minor
+ };
+
+ const fvMesh& mesh_;
+
+ word widthReference_;
+
+ word depthReference_;
+
+ D4SigmaComponent component_;
+
+ scalar isotherm_;
+
+ scalar width_;
+
+ scalar depth_;
+
+public:
+
+ referenceDimensions(const dictionary& dict, const fvMesh& mesh);
+
+ void update
+ (
+ const profileMetrics& metrics,
+ const scalar depth,
+ const vector& position,
+ const boundBox& bounds
+ );
+
+ inline scalar width() const
+ {
+ return width_;
+ }
+
+ inline scalar depth() const
+ {
+ return depth_;
+ }
+
+ inline scalar aspectRatio() const
+ {
+ return 2.0*depth_/width_;
+ }
+
+ inline bool isothermDepth() const
+ {
+ return depthReference_ == "isotherm";
+ }
+};
+
+} // End namespace Foam
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/refinementModels/noRefinementModel/noRefinementModel.C b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/noRefinementModel/noRefinementModel.C
index 9a9403c3..e385050f 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/refinementModels/noRefinementModel/noRefinementModel.C
+++ b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/noRefinementModel/noRefinementModel.C
@@ -43,7 +43,7 @@ namespace refinementModels
Foam::refinementModels::noRefinementModel::noRefinementModel
(
- const PtrList& sources,
+ const PtrList& sources,
const dictionary& dict,
const fvMesh& mesh
)
diff --git a/applications/solvers/additiveFoam/movingHeatSource/refinementModels/noRefinementModel/noRefinementModel.H b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/noRefinementModel/noRefinementModel.H
index f95af438..686d56a2 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/refinementModels/noRefinementModel/noRefinementModel.H
+++ b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/noRefinementModel/noRefinementModel.H
@@ -24,13 +24,13 @@ License
along with OpenFOAM. If not, see .
Class
- Foam::refinementModel::none
+ Foam::refinementModels::noRefinementModel
Description
No refinement.
SourceFiles
- none.C
+ noRefinementModel.C
\*---------------------------------------------------------------------------*/
@@ -66,7 +66,7 @@ public:
//- Default empty constructor
noRefinementModel
(
- const PtrList& sources,
+ const PtrList& sources,
const dictionary& dict,
const fvMesh& mesh
);
@@ -79,11 +79,9 @@ public:
// Member Functions
- //- Return true
- virtual bool update()
- {
- return true;
- }
+ //- Do nothing
+ virtual void update()
+ {}
//- Return true
virtual bool read()
@@ -95,7 +93,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-} // End namespace refinementModel
+} // End namespace refinementModels
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/applications/solvers/additiveFoam/movingHeatSource/refinementModels/refinementModel/refinementModel.C b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/refinementModel/refinementModel.C
index 9dc7f4bf..5dfd4233 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/refinementModels/refinementModel/refinementModel.C
+++ b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/refinementModel/refinementModel.C
@@ -20,7 +20,7 @@ License
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
- You should have received a copy of the the GNU General Public License
+ You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
\*---------------------------------------------------------------------------*/
@@ -36,11 +36,6 @@ namespace Foam
defineRunTimeSelectionTable(refinementModel, dictionary);
}
-const Foam::word Foam::refinementModel::refinementModelDictName
-(
- "refinementModelDict"
-);
-
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::IOobject Foam::refinementModel::createIOobject
@@ -100,7 +95,7 @@ void Foam::refinementModel::readSourceBuffers()
forAll(sources_, sourcei)
{
- buffersDict.lookup(sources_[sourcei].sourceName())
+ buffersDict.lookup(sources_[sourcei].name())
>> sourceBuffers_[sourcei];
}
}
@@ -432,7 +427,7 @@ Foam::scalar Foam::refinementModel::minimumScanPathRefineVolume
Foam::refinementModel::refinementModel
(
- const PtrList& sources,
+ const PtrList& sources,
const dictionary& dict,
const fvMesh& mesh
)
@@ -441,8 +436,7 @@ Foam::refinementModel::refinementModel
sources_(sources),
mesh_(mesh),
- heatSourceDict_(dict),
- refinementDict_(heatSourceDict_.optionalSubDict("refinementModel")),
+ refinementDict_(dict.optionalSubDict("refinement")),
maxRefinementLevel_(0),
refinementTemperature_(GREAT),
sourceBuffers_(sources.size(), vector::zero),
@@ -466,7 +460,7 @@ Foam::refinementModel::refinementModel
Foam::refinementModel::refinementModel
(
const word& type,
- const PtrList& sources,
+ const PtrList& sources,
const dictionary& dict,
const fvMesh& mesh
)
@@ -475,8 +469,7 @@ Foam::refinementModel::refinementModel
sources_(sources),
mesh_(mesh),
- heatSourceDict_(dict),
- refinementDict_(heatSourceDict_.subDict("refinementModel")),
+ refinementDict_(dict.subDict("refinement")),
maxRefinementLevel_(readMaxRefinementLevel()),
refinementTemperature_
(
@@ -513,7 +506,7 @@ Foam::refinementModel::refinementModel
forAll(sources_, sourcei)
{
Info << "refinementModel: Refinement buffer for "
- << sources_[sourcei].sourceName() << " "
+ << sources_[sourcei].name() << " "
<< sourceBuffers_[sourcei] << endl;
}
}
@@ -763,7 +756,7 @@ bool Foam::refinementModel::read()
{
if (regIOobject::read())
{
- refinementDict_ = optionalSubDict("refinementModel");
+ refinementDict_ = optionalSubDict("refinement");
maxRefinementLevel_ = readMaxRefinementLevel();
diff --git a/applications/solvers/additiveFoam/movingHeatSource/refinementModels/refinementModel/refinementModel.H b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/refinementModel/refinementModel.H
index 842f923b..1ebead1a 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/refinementModels/refinementModel/refinementModel.H
+++ b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/refinementModel/refinementModel.H
@@ -20,7 +20,7 @@ License
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
- You should have received a copy of the the GNU General Public License
+ You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
Class
@@ -30,7 +30,7 @@ Description
Base class for models that populate the refinementField used by the
OpenFOAM dynamic mesh refiner.
- If no refinementModel dictionary is present in heatSourceDict, the
+ If no refinement dictionary is present in heatSourceDict, the
no-refinement model is selected and no AdditiveFOAM refinement controls
are required.
@@ -52,7 +52,7 @@ SourceFiles
#include "volFields.H"
#include "movingBeam.H"
#include "treeBoundBox.H"
-#include "heatSourceModel.H"
+#include "movingHeatSource.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -124,15 +124,12 @@ protected:
// Protected Data
//- PtrList to heatSourceModels
- const PtrList& sources_;
+ const PtrList& sources_;
//- Pointer to mesh information
const fvMesh& mesh_;
- //- Main heat source dictionary
- const dictionary& heatSourceDict_;
-
- //- Sub-dictionary for refinementModel entries
+ //- Refinement controls
dictionary refinementDict_;
//- Maximum dynamic-mesh refinement level
@@ -180,9 +177,6 @@ public:
//- Runtime type information
TypeName("refinementModel");
- //- Default refinement model dictionary name
- static const word refinementModelDictName;
-
// Declare run-time constructor selection table
declareRunTimeSelectionTable
(
@@ -190,7 +184,7 @@ public:
refinementModel,
dictionary,
(
- const PtrList& sources,
+ const PtrList& sources,
const dictionary& dict,
const fvMesh& mesh
),
@@ -203,7 +197,7 @@ public:
//- Construct inactive refinement model
refinementModel
(
- const PtrList& sources,
+ const PtrList& sources,
const dictionary& dict,
const fvMesh& mesh
);
@@ -212,7 +206,7 @@ public:
refinementModel
(
const word& type,
- const PtrList& sources,
+ const PtrList& sources,
const dictionary& dict,
const fvMesh& mesh
);
@@ -226,7 +220,7 @@ public:
//- Return a reference to the selected refinement model
static autoPtr New
(
- const PtrList& sources,
+ const PtrList& sources,
const dictionary& dict,
const fvMesh& mesh
);
@@ -270,7 +264,7 @@ public:
}
//- Update refinementField
- virtual bool update() = 0;
+ virtual void update() = 0;
//- Read the heat source dictionary
virtual bool read() = 0;
diff --git a/applications/solvers/additiveFoam/movingHeatSource/refinementModels/refinementModel/refinementModelNew.C b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/refinementModel/refinementModelNew.C
index 0c848e8c..cf97ceb8 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/refinementModels/refinementModel/refinementModelNew.C
+++ b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/refinementModel/refinementModelNew.C
@@ -31,22 +31,22 @@ License
Foam::autoPtr Foam::refinementModel::New
(
- const PtrList& sources,
+ const PtrList& sources,
const dictionary& dict,
const fvMesh& mesh
)
{
word modelType("none");
- if (dict.found("refinementModel"))
+ if (dict.found("refinement"))
{
const dictionary& refinementModelDict =
- dict.subDict("refinementModel");
+ dict.subDict("refinement");
modelType =
refinementModelDict.lookupOrDefault
(
- "refinementModel",
+ "model",
"none"
);
}
diff --git a/applications/solvers/additiveFoam/movingHeatSource/refinementModels/targetCellLoad/targetCellLoad.C b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/targetCellLoad/targetCellLoad.C
index 083f9cbc..9a6b1ee5 100644
--- a/applications/solvers/additiveFoam/movingHeatSource/refinementModels/targetCellLoad/targetCellLoad.C
+++ b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/targetCellLoad/targetCellLoad.C
@@ -20,7 +20,7 @@ License
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
- You should have received a copy of the the GNU General Public License
+ You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
\*---------------------------------------------------------------------------*/
@@ -47,39 +47,47 @@ namespace refinementModels
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
-void Foam::refinementModels::targetCellLoad::readCoeffs()
+void Foam::refinementModels::targetCellLoad::readControls()
{
targetCellsPerProc_ =
- coeffs_.lookupOrDefault