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..8e99cba1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,79 @@ +# 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 tabulated-profile inspection and automatic D4Sigma calculation. +- 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 depth distribution. +- 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 transient 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`. +- The former projected Gaussian, nLight AFX, and tabulated heat-source models + are now profiles selected by `projectedHeatSource`. Their shared axial model + is selected as the `exponential` projection. +- `superGaussian` remains a volumetric `heatSourceModel` and can also be + selected as the planar `profile` of a `projectedHeatSource`. Volumetric + `dimensions` have three components; profile `dimensions` have two. +- The tabulated profile derives its D4Sigma metrics from the beam-profile + table. No user-supplied lateral dimensions are required. +- The `A` and `B` projected-depth coefficients are now named `nSlope` and + `nIntercept` in `exponentialCoeffs`. +- 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 [![OpenFOAM-14](https://img.shields.io/badge/OpenFOAM-14-blue.svg)](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/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..a24fddf7 100644 --- a/applications/solvers/additiveFoam/movingHeatSource/Make/files +++ b/applications/solvers/additiveFoam/movingHeatSource/Make/files @@ -9,11 +9,17 @@ movingBeam/movingBeam.C heatSourceModels/heatSourceModel/heatSourceModel.C heatSourceModels/heatSourceModel/heatSourceModelNew.C +heatSourceModels/projectedHeatSource/profiles/heatSourceProfile/heatSourceProfile.C +heatSourceModels/projectedHeatSource/profiles/heatSourceProfile/heatSourceProfileNew.C +heatSourceModels/projectedHeatSource/profiles/superGaussian/superGaussianProfile.C +heatSourceModels/projectedHeatSource/profiles/nLightAFX/nLightAFXProfile.C +heatSourceModels/projectedHeatSource/profiles/tabulated/tabulatedProfile.C +heatSourceModels/projectedHeatSource/projections/heatSourceProjection/heatSourceProjection.C +heatSourceModels/projectedHeatSource/projections/heatSourceProjection/heatSourceProjectionNew.C +heatSourceModels/projectedHeatSource/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/projectedHeatSource/projectedHeatSource.C refinementModels/refinementModel/refinementModel.C refinementModels/refinementModel/refinementModelNew.C diff --git a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.C b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.C index 9d83eb56..3d620268 100644 --- a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.C +++ b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.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. @@ -75,9 +75,11 @@ Foam::absorptionModels::Kelly::Kelly Foam::scalar Foam::absorptionModels::Kelly::eta ( - const scalar& aspectRatio + scalar aspectRatio ) const { + aspectRatio = max(aspectRatio, small); + if (aspectRatio > aspectRatioSwitch_) { const scalar theta = Foam::atan(1.0 / aspectRatio); @@ -97,8 +99,14 @@ Foam::absorptionModels::Kelly::eta G = 0.5 / (1.0 + aspectRatio); } - return (eta0_ * (1.0 + (1.0 - eta0_)*(G - F)) - / (1.0 - (1.0 - eta0_)*(1.0 - G))).value(); + return max + ( + etaMin_.value(), + ( + eta0_*(1.0 + (1.0 - eta0_)*(G - F)) + /(1.0 - (1.0 - eta0_)*(1.0 - G)) + ).value() + ); } else { diff --git a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.H b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.H index 34ee0e49..3fb0f3ea 100644 --- a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.H +++ b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/Kelly/KellyAbsorption.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. @@ -71,7 +71,7 @@ class Kelly //- Fresnel absorption of the liquid metal dimensionedScalar eta0_; - //- Effective absorption in the conduction regime + //- Minimum effective absorption dimensionedScalar etaMin_; //- Aspect ratio above which the Kelly multiple-reflection model is used @@ -103,7 +103,7 @@ public: //- Return the absorption as a scalar field virtual scalar eta ( - const scalar& aspectRatio + scalar aspectRatio ) const; //- Read the absorption properties diff --git a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModel.H b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModel.H index c3f3fb36..ac17d606 100644 --- a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModel.H +++ b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/absorptionModel/absorptionModel.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. @@ -88,7 +88,7 @@ public: //- Runtime type information TypeName("absorptionModel"); - //- Default heatSourceProperties dictionary name + //- Default heatSourceDict dictionary name static const word heatSourceDictName; // Declare run-time constructor selection table @@ -140,7 +140,7 @@ public: //- Return const-access to the absorption virtual scalar eta ( - const scalar& aspectRatio + scalar aspectRatio ) const = 0; //- Read the absorption properties diff --git a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/constant/constantAbsorption.H b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/constant/constantAbsorption.H index 88f388ec..2ecba8f4 100644 --- a/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/constant/constantAbsorption.H +++ b/applications/solvers/additiveFoam/movingHeatSource/absorptionModels/constant/constantAbsorption.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. @@ -85,7 +85,7 @@ public: //- Return the absorption as a scalar field virtual scalar eta ( - const scalar& aspectRatio + scalar aspectRatio ) const { return eta_.value(); diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.C index aed14633..1a031e45 100644 --- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.C +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.C @@ -90,6 +90,16 @@ Foam::heatSourceModel::heatSourceModel sourceDict_(heatSourceDict_.optionalSubDict(sourceName_)), heatSourceModelCoeffs_(sourceDict_.optionalSubDict(type + "Coeffs")), mesh_(mesh), + transient_(false), + isoValue_(great), + D4Sigma_(0), + minimumDepth_(0), + depth_(0), + isoDepth_(0), + nPoints_(vector::one), + tolerance_(1.0e-3), + sourceBb_(point::zero, point::zero), + V0_("V0", dimVolume, 0), absorptionModel_(nullptr), movingBeam_(nullptr) { @@ -99,27 +109,17 @@ Foam::heatSourceModel::heatSourceModel 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_) - ) + if (transient_) { - isoValue_ = thermoPath(mesh_).liquidus(); - } - else - { - heatSourceModelCoeffs_.readIfPresent("isoValue", isoValue_); + isoValue_ = + heatSourceModelCoeffs_.lookupOrDefault + ( + "isoValue", + thermoPath(mesh_).liquidus() + ); } nPoints_ = @@ -128,28 +128,31 @@ Foam::heatSourceModel::heatSourceModel "nPoints", vector::one ); + + tolerance_ = + heatSourceModelCoeffs_.lookupOrDefault + ( + "tolerance", + 1.0e-3 + ); } // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // -void Foam::heatSourceModel::updateDimensions() +void Foam::heatSourceModel::updateDepth() { - if (!transient_ ) + if (!transient_) { - Info << "maxDepth: " << dimensions_.z() << endl; + isoDepth_ = 0; + depth_ = minimumDepth_; + Info << "depth: " << depth_ << endl; return; } - const vector position_ = movingBeam_->position(); - - const scalar searchRadius - ( - max(staticDimensions_.x(), staticDimensions_.y()) - ); + const vector position = movingBeam_->position(); - // find maximum isotherm depth within supplied beam radius - // depth is defined as the z-distance from the heat source centre + // Find the maximum isotherm depth within the planar source bounds const volScalarField& T = mesh_.lookupObject("T"); const labelUList& owner = mesh_.owner(); @@ -157,7 +160,7 @@ void Foam::heatSourceModel::updateDimensions() const volVectorField& cc = mesh_.C(); - scalar maxDepth = staticDimensions_.z(); + scalar isoDepth = 0; // isocontour location evaluated linearly across faces for (label facei=0; facei < mesh_.nInternalFaces(); facei++) @@ -171,15 +174,21 @@ void Foam::heatSourceModel::updateDimensions() 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()); + const vector p = + cc[own] + + d*(isoValue_ - T[own])/(T[nei] - T[own]) + - position; - if (pxy <= searchRadius) + if + ( + p.x() >= sourceBb_.min().x() + && p.x() <= sourceBb_.max().x() + && p.y() >= sourceBb_.min().y() + && p.y() <= sourceBb_.max().y() + && p.z() <= 0 + ) { - maxDepth = max(p.z(), maxDepth); + isoDepth = max(-p.z(), isoDepth); } } } @@ -211,28 +220,35 @@ void Foam::heatSourceModel::updateDimensions() 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) + const vector p = + cc[own] + + d*(isoValue_ - T[own])/(Tn[facei] - T[own]) + - position; + + if + ( + p.x() >= sourceBb_.min().x() + && p.x() <= sourceBb_.max().x() + && p.y() >= sourceBb_.min().y() + && p.y() <= sourceBb_.max().y() + && p.z() <= 0 + ) { - maxDepth = max(p.z(), maxDepth); + isoDepth = max(-p.z(), isoDepth); } } } } } - reduce(maxDepth, maxOp()); + reduce(isoDepth, maxOp()); + + isoDepth_ = isoDepth; - dimensions_ = - vector(staticDimensions_.x(), staticDimensions_.y(), maxDepth); + depth_ = max(minimumDepth_, isoDepth_); - Info << "maxDepth: " << dimensions_.z() << endl; + Info<< "isoDepth: " << isoDepth_ + << ", depth: " << depth_ << endl; } Foam::tmpFoam::heatSourceModel::qDot() @@ -255,22 +271,20 @@ Foam::tmpFoam::heatSourceModel::qDot() ); 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 scalar a = + (transient_ ? isoDepth_ : depth_)/(0.5*D4Sigma_); const dimensionedScalar absorbedPower ( "etaP", dimPower, - absorptionModel_->eta(aspectRatio)*power_ + absorptionModel_->eta(a)*power_ ); dimensionedScalar volume = V0(); @@ -290,14 +304,14 @@ Foam::tmpFoam::heatSourceModel::qDot() dimensionedScalar("Zero", dimless, 0.0) ); - const pointField& points = mesh_.points(); - - treeBoundBox beamBb + treeBoundBox currentSourceBb ( - position_ - 1.5*dimensions_, - position_ + 1.5*dimensions_ + position_ + sourceBb_.min(), + position_ + sourceBb_.max() ); + const pointField& points = mesh_.points(); + hexMatcher hex; forAll(mesh_.cells(), celli) @@ -312,22 +326,31 @@ Foam::tmpFoam::heatSourceModel::qDot() cellBb.max() = max(cellBb.max(), points[vertices[i]]); } - if (cellBb.overlaps(beamBb)) + if (cellBb.overlaps(currentSourceBb)) { if (hex.isA(mesh_, celli)) { - vector dx_ = cmptDivide(dimensions_, vector(nPoints_)); + vector dx_ = + cmptDivide + ( + sourceBb_.span(), + vector(nPoints_) + ); labelVector nCellPoints = max ( - cmptDivide(cellBb.span() + small*vector::one, dx_), + cmptDivide + ( + cellBb.span() + small*vector::one, + dx_ + ), vector::one ); dx_ = cmptDivide(cellBb.span(), vector(nCellPoints)); - scalar dVi = dx_.x() * dx_.y() * dx_.z(); + scalar dVi = dx_.x()*dx_.y()*dx_.z(); scalar wi = 0.0; @@ -347,23 +370,27 @@ Foam::tmpFoam::heatSourceModel::qDot() ) ); - treeBoundBox ptBb(pt - 0.5*dx_, pt + 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)) + if (currentSourceBb.overlaps(ptBb)) { - wi += weight(pt - position_) * dVi; + wi += weight(pt - position_)*dVi; } } } } - weights[celli] = wi / mesh_.V()[celli]; + weights[celli] = wi/mesh_.V()[celli]; } else { // cell is not hexahedral, evaluate at centre - point d = cmptMag(mesh_.cellCentres()[celli] - position_); + point d = mesh_.cellCentres()[celli] - position_; weights[celli] = weight(d); } @@ -372,7 +399,7 @@ Foam::tmpFoam::heatSourceModel::qDot() // stabilize numerical integration errors within 95% of applied power dimensionedScalar sumWeights = fvc::domainIntegrate(weights); - scalar residual = (sumWeights / volume).value(); + scalar residual = (sumWeights/volume).value(); if (mag(1 - residual) < 0.05) { @@ -390,7 +417,41 @@ bool Foam::heatSourceModel::read() { if (regIOobject::read()) { - heatSourceModelCoeffs_ = optionalSubDict(type() + "Coeffs"); + sourceDict_ = optionalSubDict(sourceName_); + + heatSourceModelCoeffs_ = + sourceDict_.optionalSubDict(type() + "Coeffs"); + + transient_ = + heatSourceModelCoeffs_.lookupOrDefault + ( + "transient", + false + ); + + if (transient_) + { + isoValue_ = + heatSourceModelCoeffs_.lookupOrDefault + ( + "isoValue", + thermoPath(mesh_).liquidus() + ); + } + + nPoints_ = + heatSourceModelCoeffs_.lookupOrDefault + ( + "nPoints", + vector::one + ); + + tolerance_ = + heatSourceModelCoeffs_.lookupOrDefault + ( + "tolerance", + 1.0e-3 + ); return true; } diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.H index e74d3d9a..b5101c17 100644 --- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.H +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.H @@ -27,7 +27,9 @@ Class Foam::heatSourceModels::heatSourceModel Description - Abstract base class for heatSource models + Abstract base class for heatSource models. The optional tolerance + coefficient controls the maximum fraction of analytical source power + outside the integration bounds and defaults to 1e-3. SourceFiles heatSourceModel.C @@ -42,6 +44,7 @@ SourceFiles #include "movingBeam.H" #include "absorptionModel.H" #include "labelVector.H" +#include "boundBox.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -67,6 +70,12 @@ class heatSourceModel protected: + // Protected Member Functions + + //- Update the transient heat source depth + void updateDepth(); + + // Protected data //- Name of heat source @@ -87,18 +96,33 @@ protected: //- Flag for transient or static heat source dimensions Switch transient_; - //- Isotherm depth tracked in transient heat source model + //- Temperature isovalue used to calculate the transient source depth scalar isoValue_; - //- Dimensions of the heat source (dynamic) - vector dimensions_; + //- Area-equivalent second-moment beam diameter + scalar D4Sigma_; + + //- Minimum heat source depth + scalar minimumDepth_; + + //- Current heat source depth + scalar depth_; - //- Dimensions of the heat source (static) - vector staticDimensions_; + //- Calculated isotherm depth, zero when no isotherm is detected + scalar isoDepth_; - //- Number of points along heat source dimensions resolved by sampling + //- Number of points across the source bounds resolved by sampling labelVector nPoints_; + //- Maximum fraction of analytical power outside the source bounds + scalar tolerance_; + + //- Source bounds relative to the beam position + boundBox sourceBb_; + + //- Analytical normalization volume + dimensionedScalar V0_; + //- AutoPtrs to absorption model and moving beam instances autoPtr absorptionModel_; autoPtr movingBeam_; @@ -108,7 +132,7 @@ public: //- Runtime type information TypeName("heatSourceModel"); - //- Default heatSourceProperties dictionary name + //- Default heatSourceDict dictionary name static const word heatSourceDictName; // Declare run-time constructor selection table @@ -187,29 +211,32 @@ public: return isoValue_; } - //- Return vector of current heat source dimensions - inline vector dimensions() const + //- Return the area-equivalent second-moment beam diameter + inline scalar D4Sigma() const { - return dimensions_; + return D4Sigma_; } - //- Return vector of original heat source dimensions - inline vector staticDimensions() const + //- Return the source bounds relative to the beam position + inline const boundBox& sourceBb() const { - return staticDimensions_; + return sourceBb_; } - //- Update the transient heat source dimensions - void updateDimensions(); + //- Update the heat source state + virtual void update() = 0; //- Return the volumetric heating field virtual tmp qDot(); //- Return the weight of the heat source distribution at a given point - virtual scalar weight(const vector& d) = 0; + virtual scalar weight(const vector& r) const = 0; //- Return the normalization volume for the integrated distribution - virtual dimensionedScalar V0() = 0; + inline const dimensionedScalar& V0() const + { + return V0_; + } //- Read the heat source dictionary virtual bool read() = 0; diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/modifiedSuperGaussian/modifiedSuperGaussian.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/modifiedSuperGaussian/modifiedSuperGaussian.C index 95b2d750..5a32ff7d 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. @@ -26,6 +26,7 @@ License \*---------------------------------------------------------------------------*/ #include "modifiedSuperGaussian.H" +#include "superGaussianProfile.H" #include "addToRunTimeSelectionTable.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -56,69 +57,119 @@ Foam::heatSourceModels::modifiedSuperGaussian::modifiedSuperGaussian ) : heatSourceModel(typeName, sourceName, dict, mesh), - mesh_(mesh) + dimensions_(vector::zero), + k_(1), + m_(1), + s_(vector::zero) { + dimensions_ = heatSourceModelCoeffs_.lookup("dimensions"); k_ = heatSourceModelCoeffs_.lookup("k"); m_ = heatSourceModelCoeffs_.lookup("m"); + + minimumDepth_ = dimensions_.z(); + depth_ = minimumDepth_; + + D4Sigma_ = + heatSourceProfiles::superGaussianProfile::D4Sigma + ( + dimensions_.x(), + dimensions_.y(), + k_ + ); + + updateSource(); } // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // -inline Foam::scalar -Foam::heatSourceModels::modifiedSuperGaussian::weight(const vector& d) +void Foam::heatSourceModels::modifiedSuperGaussian::updateSource() { - scalar a = Foam::pow(2.0, 1.0/k_); - - vector s = cmptDivide(dimensions_, vector(a, a, 1.0)); + dimensions_.z() = depth_; + + s_ = dimensions_/Foam::pow(2.0, 1.0/k_); + s_.z() = dimensions_.z(); + + const scalar fMax = + Foam::pow + ( + invIncGammaRatio_P(2.0/k_, 1.0 - tolerance_), + 1.0/k_ + ); + + sourceBb_ = + boundBox + ( + point(-fMax*s_.x(), -fMax*s_.y(), -s_.z()), + point(fMax*s_.x(), fMax*s_.y(), 0) + ); + + V0_ = + dimensionedScalar + ( + "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_) + ); +} - 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); +void Foam::heatSourceModels::modifiedSuperGaussian::update() +{ + updateDepth(); + updateSource(); +} - scalar x = Foam::pow(magSqr(cmptDivide(di, s)), k_/2.0); - return Foam::exp(-x); - } - else +inline Foam::scalar +Foam::heatSourceModels::modifiedSuperGaussian::weight(const vector& r) const +{ + if ((r.z() > 0) || (r.z() <= -s_.z())) { - return 0.0; + return 0; } -} - -inline Foam::dimensionedScalar -Foam::heatSourceModels::modifiedSuperGaussian::V0() -{ - const scalar a = Foam::pow(2.0, 1.0/k_); - - const vector s = cmptDivide(dimensions_, vector(a, a, 1.0)); - - const dimensionedScalar V0 - ( - "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_) - ); - return V0; + const scalar g = + Foam::pow + ( + 1.0 - Foam::pow(-r.z()/s_.z(), m_), + 1.0/m_ + ); + + const scalar f = + Foam::pow + ( + Foam::sqr(r.x()/(s_.x()*g)) + + Foam::sqr(r.y()/(s_.y()*g)), + k_/2.0 + ); + + return Foam::exp(-f); } bool Foam::heatSourceModels::modifiedSuperGaussian::read() { if (heatSourceModel::read()) { - heatSourceModelCoeffs_ = optionalSubDict(type() + "Coeffs"); - - //- Mandatory entries + heatSourceModelCoeffs_.lookup("dimensions") >> dimensions_; heatSourceModelCoeffs_.lookup("k") >> k_; heatSourceModelCoeffs_.lookup("m") >> m_; + minimumDepth_ = dimensions_.z(); + depth_ = max(minimumDepth_, isoDepth_); + + D4Sigma_ = + heatSourceProfiles::superGaussianProfile::D4Sigma + ( + dimensions_.x(), + dimensions_.y(), + k_ + ); + + updateSource(); + return true; } else diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/modifiedSuperGaussian/modifiedSuperGaussian.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/modifiedSuperGaussian/modifiedSuperGaussian.H index 6cff6f9b..ebdee6c7 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,7 +27,8 @@ Class Foam::heatSourceModels::modifiedSuperGaussian Description - modifiedSuperGaussian model. + One-sided modified super-Gaussian heat source model applied in the + negative z direction from the beam plane. Reference: \verbatim @@ -60,8 +61,8 @@ class modifiedSuperGaussian { // Private Data - //- Pointer to mesh information - const fvMesh& mesh_; + //- Heat source dimensions + vector dimensions_; //- Distribution shape coefficient of modifiedSuperGaussian distribution scalar k_; @@ -69,6 +70,15 @@ class modifiedSuperGaussian //- Geometric shape coefficient of modifiedSuperGaussian distribution scalar m_; + //- Scaled heat source dimensions + vector s_; + + + // Private Member Functions + + //- Update the source dimensions, bounds and normalization + void updateSource(); + public: //- Runtime type information @@ -93,11 +103,11 @@ public: // Member Functions - inline virtual scalar weight(const vector& d); + virtual void update(); - inline virtual dimensionedScalar V0(); + inline virtual scalar weight(const vector& r) const; - //- Read the heatSourceProperties dictionary + //- Read the heatSourceDict dictionary virtual bool read(); }; 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/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/projectedHeatSource/profiles/heatSourceProfile/heatSourceProfile.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/heatSourceProfile/heatSourceProfile.C new file mode 100644 index 00000000..6e64d25d --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/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/projectedHeatSource/profiles/heatSourceProfile/heatSourceProfile.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/heatSourceProfile/heatSourceProfile.H new file mode 100644 index 00000000..a62921e4 --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/heatSourceProfile/heatSourceProfile.H @@ -0,0 +1,117 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 "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 the planar profile integral + virtual scalar integral() const = 0; + + //- Return the area-equivalent second-moment diameter + virtual scalar D4Sigma() const = 0; + + //- Return the planar profile bounds + virtual const boundBox& profileBb() 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/projectedHeatSource/profiles/heatSourceProfile/heatSourceProfileNew.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/heatSourceProfile/heatSourceProfileNew.C new file mode 100644 index 00000000..46b4a44f --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/heatSourceProfile/heatSourceProfileNew.C @@ -0,0 +1,56 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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("profile")); + + 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/projectedHeatSource/profiles/nLightAFX/nLightAFXProfile.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/nLightAFX/nLightAFXProfile.C new file mode 100644 index 00000000..379bdafe --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/nLightAFX/nLightAFXProfile.C @@ -0,0 +1,196 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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(nLightAFXProfile, 0); + addToRunTimeSelectionTable + ( + heatSourceProfile, + nLightAFXProfile, + dictionary + ); +} +} + +using Foam::constant::mathematical::pi; + + +Foam::heatSourceProfiles::nLightAFXProfile::nLightAFXProfile +( + const dictionary& dict, + const fvMesh&, + const scalar epsilon +) +: + alpha_(0), + r0_(0), + sigma0_(0), + r1_(0), + sigma1_(0), + J0_(0), + J1_(0), + integral_(0), + D4Sigma_(0), + profileBb_(point::zero, point::zero) +{ + const dictionary& coeffs = dict.subDict(typeName + "Coeffs"); + + alpha_ = coeffs.lookup("alpha"); + + r0_ = coeffs.lookup("r0"); + sigma0_ = coeffs.lookup("sigma0"); + + r1_ = coeffs.lookup("r1"); + sigma1_ = coeffs.lookup("sigma1"); + + J0_ = J(0, r0_, sigma0_); + J1_ = J(0, r1_, sigma1_); + + integral_ = 2.0*pi*J0_; + + const scalar r2 = + (1.0 - alpha_)*K(r0_, sigma0_)/J0_ + + alpha_*K(r1_, sigma1_)/J1_; + + D4Sigma_ = 4.0*Foam::sqrt(0.5*r2); + + 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; + } + + profileBb_ = + boundBox + ( + point(-rMax, -rMax, 0), + point(rMax, rMax, 0) + ); +} + + +inline Foam::scalar Foam::heatSourceProfiles::nLightAFXProfile::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::nLightAFXProfile::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::nLightAFXProfile::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::nLightAFXProfile::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/projectedHeatSource/profiles/nLightAFX/nLightAFXProfile.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/nLightAFX/nLightAFXProfile.H new file mode 100644 index 00000000..a36269ee --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/nLightAFX/nLightAFXProfile.H @@ -0,0 +1,155 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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::nLightAFXProfile + +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 nLightAFXProfile +: + 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_; + + //- Planar integral + scalar integral_; + + //- Area-equivalent second-moment diameter + scalar D4Sigma_; + + //- Planar profile bounds + boundBox profileBb_; + + + // 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 + + nLightAFXProfile + ( + const dictionary& dict, + const fvMesh& mesh, + const scalar tolerance + ); + + //- Destructor + virtual ~nLightAFXProfile() + {} + + // Member Functions + + inline virtual scalar weight + ( + const scalar x, + const scalar y + ) const; + + inline virtual scalar integral() const + { + return integral_; + } + + inline virtual scalar D4Sigma() const + { + return D4Sigma_; + } + + inline virtual const boundBox& profileBb() const + { + return profileBb_; + } + +}; + +} // End namespace heatSourceProfiles +} // End namespace Foam + +#endif + +// ************************************************************************* // diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/superGaussian/superGaussianProfile.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/superGaussian/superGaussianProfile.C new file mode 100644 index 00000000..0a49d688 --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/superGaussian/superGaussianProfile.C @@ -0,0 +1,122 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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(superGaussianProfile, 0); + addToRunTimeSelectionTable + ( + heatSourceProfile, + superGaussianProfile, + dictionary + ); +} +} + +using Foam::constant::mathematical::pi; + +Foam::heatSourceProfiles::superGaussianProfile::superGaussianProfile +( + const dictionary& dict, + const fvMesh&, + const scalar tolerance +) +: + dimensions_(vector2D::zero), + k_(1), + s_(vector2D::zero), + integral_(0), + D4Sigma_(0), + profileBb_(point::zero, point::zero) +{ + const dictionary& coeffs = dict.subDict(typeName + "Coeffs"); + + dimensions_ = coeffs.lookup("dimensions"); + k_ = coeffs.lookup("k"); + + s_ = dimensions_/Foam::pow(2.0, 1.0/k_); + + integral_ = + pi*s_.x()*s_.y()*Foam::tgamma(1.0 + 2.0/k_); + + D4Sigma_ = D4Sigma(dimensions_.x(), dimensions_.y(), k_); + + const scalar fMax = + Foam::pow + ( + invIncGammaRatio_P(2.0/k_, 1.0 - tolerance), + 1.0/k_ + ); + + profileBb_ = + boundBox + ( + point(-fMax*s_.x(), -fMax*s_.y(), 0), + point(fMax*s_.x(), fMax*s_.y(), 0) + ); +} + + +Foam::scalar Foam::heatSourceProfiles::superGaussianProfile::D4Sigma +( + const scalar x, + const scalar y, + const scalar k +) +{ + const scalar s = Foam::sqrt(x*y)/Foam::pow(2.0, 1.0/k); + const scalar variance = + 0.5*Foam::tgamma(4.0/k)/Foam::tgamma(2.0/k); + + return 4.0*s*Foam::sqrt(variance); +} + + +Foam::scalar Foam::heatSourceProfiles::superGaussianProfile::weight +( + const scalar x, + const scalar y +) const +{ + return + Foam::exp + ( + -Foam::pow + ( + Foam::sqr(x/s_.x()) + Foam::sqr(y/s_.y()), + k_/2.0 + ) + ); +} + +// ************************************************************************* // diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/superGaussian/superGaussianProfile.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/superGaussian/superGaussianProfile.H new file mode 100644 index 00000000..13ba0c7b --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/superGaussian/superGaussianProfile.H @@ -0,0 +1,129 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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::superGaussianProfile + +Description + Planar super-Gaussian heat source profile. + +SourceFiles + superGaussianProfile.C + +\*---------------------------------------------------------------------------*/ + +#ifndef superGaussianProfile_H +#define superGaussianProfile_H + +#include "heatSourceProfile.H" +#include "vector2D.H" + +namespace Foam +{ +namespace heatSourceProfiles +{ + +class superGaussianProfile +: + public heatSourceProfile +{ + // Private Data + + //- Heat source dimensions + vector2D dimensions_; + + //- Shape coefficient + scalar k_; + + //- Scaled heat source dimensions + vector2D s_; + + //- Planar integral + scalar integral_; + + //- Area-equivalent second-moment diameter + scalar D4Sigma_; + + //- Planar profile bounds + boundBox profileBb_; + +public: + + //- Runtime type information + TypeName("superGaussian"); + + + // Constructors + + superGaussianProfile + ( + const dictionary& dict, + const fvMesh& mesh, + const scalar tolerance + ); + + //- Destructor + virtual ~superGaussianProfile() + {} + + // Member Functions + + //- Return the area-equivalent second-moment diameter + static scalar D4Sigma + ( + const scalar x, + const scalar y, + const scalar k + ); + + virtual scalar weight + ( + const scalar x, + const scalar y + ) const; + + inline virtual scalar integral() const + { + return integral_; + } + + inline virtual scalar D4Sigma() const + { + return D4Sigma_; + } + + inline virtual const boundBox& profileBb() const + { + return profileBb_; + } + +}; + +} // End namespace heatSourceProfiles +} // End namespace Foam + +#endif + +// ************************************************************************* // diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/tabulated/tabulatedProfile.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/tabulated/tabulatedProfile.C new file mode 100644 index 00000000..cc62652f --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/tabulated/tabulatedProfile.C @@ -0,0 +1,216 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 +{ + defineTypeNameAndDebug(tabulatedProfile, 0); + addToRunTimeSelectionTable + ( + heatSourceProfile, + tabulatedProfile, + dictionary + ); +} + +// * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::tabulatedProfile::tabulatedProfile() +: + nx_(0), + ny_(0), + x0_(0), + y0_(0), + dx_(0), + dy_(0), + x1_(0), + y1_(0), + invDx_(0), + invDy_(0), + values_(0), + integral_(0), + centroidX_(0), + centroidY_(0), + D4SigmaMajor_(0), + D4SigmaMinor_(0), + D4Sigma_(0), + azimuth_(0), + profileBb_(point::zero, point::zero) +{} + +Foam::tabulatedProfile::tabulatedProfile(const fileName& profileFile) +: + tabulatedProfile() +{ + read(profileFile); +} + + +Foam::tabulatedProfile::tabulatedProfile +( + const dictionary& dict, + const fvMesh& mesh, + const scalar +) +: + tabulatedProfile() +{ + const dictionary& coeffs = dict.subDict(typeName + "Coeffs"); + + const fileName fName(coeffs.lookup("file")); + + const fileName tableFile + ( + mesh.time().rootPath() + /mesh.time().globalCaseName() + /mesh.time().constant() + /fName + ); + + read(tableFile); + + Info<< "Tabulated profile: integral=" << integral_ + << ", centroid=(" << centroidX_ << ' ' << centroidY_ << ") m" + << ", D4Sigma/major/minor=" << D4Sigma_ << '/' + << D4SigmaMajor_ << '/' << D4SigmaMinor_ << " m" + << ", azimuth=" << azimuth_ << " rad" << endl; +} + +// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * // + +void Foam::tabulatedProfile::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 small + ? 0.5*Foam::atan2(2.0*covariance, varianceX - varianceY) + : 0.0; +} + +// * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::tabulatedProfile::read(const fileName& profileFile) +{ + IFstream is(profileFile); + + if (!is.good()) + { + FatalErrorInFunction + << "Cannot open tabulated profile " << profileFile + << exit(FatalError); + } + + is >> nx_ >> ny_; + is >> x0_ >> y0_; + is >> dx_ >> dy_; + + 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]; + } + + integrate(); + + profileBb_ = + boundBox + ( + point(x0_, y0_, 0), + point(x1_, y1_, 0) + ); +} + +// ************************************************************************* // diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/tabulated/tabulatedProfile.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/tabulated/tabulatedProfile.H new file mode 100644 index 00000000..5788913f --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/profiles/tabulated/tabulatedProfile.H @@ -0,0 +1,224 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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::tabulatedProfile + +Description + Uniform two-dimensional profile 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 +{ + +class tabulatedProfile +: + 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_; + + scalar integral_; + scalar centroidX_; + scalar centroidY_; + scalar D4SigmaMajor_; + scalar D4SigmaMinor_; + scalar D4Sigma_; + scalar azimuth_; + + boundBox profileBb_; + + // Private Member Functions + + void integrate(); + + +public: + //- Runtime type information + TypeName("tabulated"); + + // Constructors + + tabulatedProfile(); + + explicit tabulatedProfile(const fileName& profileFile); + + tabulatedProfile + ( + 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 scalar integral() const + { + return integral_; + } + + inline scalar centroidX() const + { + return centroidX_; + } + + inline scalar centroidY() const + { + return centroidY_; + } + + inline scalar D4SigmaMajor() const + { + return D4SigmaMajor_; + } + + inline scalar D4SigmaMinor() const + { + return D4SigmaMinor_; + } + + //- Area-equivalent D4Sigma diameter + //- sqrt(D4SigmaMajor()*D4SigmaMinor()) + inline virtual scalar D4Sigma() const + { + return D4Sigma_; + } + + inline scalar azimuth() const + { + return azimuth_; + } + + inline virtual const boundBox& profileBb() const + { + return profileBb_; + } + +}; + +} // End namespace Foam + +#endif + +// ************************************************************************* // diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projectedHeatSource.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projectedHeatSource.C new file mode 100644 index 00000000..8e1f88c1 --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projectedHeatSource.C @@ -0,0 +1,149 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 "projectedHeatSource.H" +#include "addToRunTimeSelectionTable.H" + +namespace Foam +{ +namespace heatSourceModels +{ + defineTypeNameAndDebug(projectedHeatSource, 0); + addToRunTimeSelectionTable + ( + heatSourceModel, + projectedHeatSource, + dictionary + ); +} +} + +Foam::heatSourceModels::projectedHeatSource::projectedHeatSource +( + const word& sourceName, + const dictionary& dict, + const fvMesh& mesh +) +: + heatSourceModel(typeName, sourceName, dict, mesh), + profile_(nullptr), + projection_(nullptr), + componentTolerance_ + ( + // (1 - componentTolerance)^2 = 1 - tolerance + tolerance_/(1.0 + Foam::sqrt(1.0 - tolerance_)) + ) +{ + profile_ = heatSourceProfile::New + ( + heatSourceModelCoeffs_, + mesh_, + componentTolerance_ + ); + + projection_ = heatSourceProjection::New(heatSourceModelCoeffs_); + + minimumDepth_ = heatSourceModelCoeffs_.lookup("minimumDepth"); + + depth_ = minimumDepth_; + D4Sigma_ = profile_->D4Sigma(); + sourceBb_ = profile_->profileBb(); + + updateSource(); + + Info<< "D4Sigma: " << D4Sigma_ << " m" << endl; +} + +void Foam::heatSourceModels::projectedHeatSource::updateSource() +{ + projection_->update + ( + depth_, + depth_/(0.5*D4Sigma_), + componentTolerance_ + ); + + sourceBb_.min().z() = projection_->zMin(); + sourceBb_.max().z() = 0; + + V0_ = + dimensionedScalar + ( + "V0", + dimVolume, + profile_->integral()*projection_->integral() + ); +} + +void Foam::heatSourceModels::projectedHeatSource::update() +{ + updateDepth(); + updateSource(); +} + +inline Foam::scalar +Foam::heatSourceModels::projectedHeatSource::weight(const vector& r) const +{ + const scalar p = projection_->weight(r.z()); + + return p > 0 ? p*profile_->weight(r.x(), r.y()) : 0; +} + +bool Foam::heatSourceModels::projectedHeatSource::read() +{ + if (heatSourceModel::read()) + { + // (1 - componentTolerance)^2 = 1 - tolerance + componentTolerance_ = + tolerance_/(1.0 + Foam::sqrt(1.0 - tolerance_)); + + profile_ = heatSourceProfile::New + ( + heatSourceModelCoeffs_, + mesh_, + componentTolerance_ + ); + + projection_ = heatSourceProjection::New(heatSourceModelCoeffs_); + + minimumDepth_ = heatSourceModelCoeffs_.lookup("minimumDepth"); + + depth_ = max(minimumDepth_, isoDepth_); + D4Sigma_ = profile_->D4Sigma(); + sourceBb_ = profile_->profileBb(); + + updateSource(); + + return true; + } + else + { + return false; + } +} + +// ************************************************************************* // diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedGaussian/projectedGaussian.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projectedHeatSource.H similarity index 59% rename from applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedGaussian/projectedGaussian.H rename to applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projectedHeatSource.H index d6106887..6c6723a9 100644 --- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedGaussian/projectedGaussian.H +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projectedHeatSource.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,82 @@ License along with OpenFOAM. If not, see . Class - Foam::heatSourceModels::projectedGaussian + Foam::heatSourceModels::projectedHeatSource Description - projectedGaussian heat source model for additive manufacting + Separable heat source constructed from a planar profile and a one-sided + axial projection. SourceFiles - projectedGaussian.C + projectedHeatSource.C \*---------------------------------------------------------------------------*/ -#ifndef projectedGaussian_H -#define projectedGaussian_H +#ifndef projectedHeatSource_H +#define projectedHeatSource_H #include "heatSourceModel.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +#include "heatSourceProfile.H" +#include "heatSourceProjection.H" namespace Foam { namespace heatSourceModels { -/*---------------------------------------------------------------------------*\ - Class projectedGaussian -\*---------------------------------------------------------------------------*/ - -class projectedGaussian +class projectedHeatSource : public heatSourceModel { // Private Data - //- Pointer to mesh information - const fvMesh& mesh_; + //- Planar heat source profile + autoPtr profile_; + + //- Axial heat source projection + autoPtr projection_; + + //- Maximum power fraction outside each separable component bound + scalar componentTolerance_; - //- weights for axial decay of 2D gaussian distribution in the form: - //- n = Alog2(x) + B - scalar A_; - scalar B_; - scalar k_; + // Private Member Functions + + //- Update the projection, source bounds and normalization + void updateSource(); public: //- Runtime type information - TypeName("projectedGaussian"); + TypeName("projectedHeatSource"); // Constructors - //- Construct from components - projectedGaussian + projectedHeatSource ( const word& sourceName, const dictionary& dict, const fvMesh& mesh ); - //- Destructor - virtual ~projectedGaussian() + virtual ~projectedHeatSource() {} - // Member Functions - inline virtual scalar weight(const vector& d); + virtual void update(); - inline virtual dimensionedScalar V0(); + inline virtual scalar weight(const vector& r) const; - //- Read the heatSourceProperties dictionary + //- Read the heatSourceDict dictionary virtual bool read(); }; - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - } // End namespace heatSourceModels } // End namespace Foam -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - #endif // ************************************************************************* // diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projections/exponential/exponential.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projections/exponential/exponential.C new file mode 100644 index 00000000..aa68825e --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projections/exponential/exponential.C @@ -0,0 +1,113 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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), + d_(0), + k_(1), + integral_(0), + zMin_(0) +{ + const dictionary& coeffs = dict.subDict(typeName + "Coeffs"); + + nSlope_ = coeffs.lookup("nSlope"); + nIntercept_ = coeffs.lookup("nIntercept"); +} + + +void Foam::heatSourceProjections::exponential::update +( + const scalar depth, + const scalar aspectRatio, + const scalar tolerance +) +{ + d_ = depth; + + const scalar n = + min + ( + max + ( + nSlope_*std::log2(aspectRatio) + nIntercept_, + 0.0 + ), + 9.0 + ); + + k_ = Foam::pow(2.0, n); + + integral_ = + d_*Foam::tgamma(1.0/k_) + /(k_*Foam::pow(3.0, 1.0/k_)); + + zMin_ = + -d_ + *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/d_, k_)); +} + +// ************************************************************************* // diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projections/exponential/exponential.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projections/exponential/exponential.H new file mode 100644 index 00000000..d913bd12 --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projections/exponential/exponential.H @@ -0,0 +1,113 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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::heatSourceProjections::exponential + +Description + One-sided generalized exponential projection applied in the negative z + direction from the beam plane. + +SourceFiles + exponential.C + +\*---------------------------------------------------------------------------*/ + +#ifndef exponential_H +#define exponential_H + +#include "heatSourceProjection.H" + +namespace Foam +{ +namespace heatSourceProjections +{ + +class exponential +: + public heatSourceProjection +{ + // Private Data + + //- nSlope in n = nSlope*log2(a) + nIntercept + scalar nSlope_; + + //- nIntercept in n = nSlope*log2(a) + nIntercept + scalar nIntercept_; + + //- Projection depth + scalar d_; + + //- Axial decay exponent + scalar k_; + + //- Projection integral + scalar integral_; + + //- Lower projection bound + scalar zMin_; + +public: + + //- Runtime type information + TypeName("exponential"); + + + // Constructors + + explicit exponential(const dictionary& dict); + + //- Destructor + virtual ~exponential() + {} + + // Member Functions + + virtual void update + ( + const scalar depth, + const scalar aspectRatio, + const scalar tolerance + ); + + inline virtual scalar weight(const scalar z) const; + + inline virtual scalar integral() const + { + return integral_; + } + + inline virtual scalar zMin() const + { + return zMin_; + } +}; + +} // End namespace heatSourceProjections +} // End namespace Foam + +#endif + +// ************************************************************************* // diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projections/heatSourceProjection/heatSourceProjection.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projections/heatSourceProjection/heatSourceProjection.C new file mode 100644 index 00000000..0fdfa0f1 --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/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/projectedHeatSource/projections/heatSourceProjection/heatSourceProjection.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projections/heatSourceProjection/heatSourceProjection.H new file mode 100644 index 00000000..2be30b2c --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/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/projectedHeatSource/projections/heatSourceProjection/heatSourceProjectionNew.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projections/heatSourceProjection/heatSourceProjectionNew.C new file mode 100644 index 00000000..2035f743 --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/projectedHeatSource/projections/heatSourceProjection/heatSourceProjectionNew.C @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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("projection")); + + 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/superGaussian/superGaussian.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/superGaussian/superGaussian.C index 822e1781..fea69b28 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. @@ -26,6 +26,7 @@ License \*---------------------------------------------------------------------------*/ #include "superGaussian.H" +#include "superGaussianProfile.H" #include "addToRunTimeSelectionTable.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -51,48 +52,99 @@ Foam::heatSourceModels::superGaussian::superGaussian ) : heatSourceModel(typeName, sourceName, dict, mesh), - mesh_(mesh) + dimensions_(vector::zero), + k_(1), + s_(vector::zero) { + dimensions_ = heatSourceModelCoeffs_.lookup("dimensions"); k_ = heatSourceModelCoeffs_.lookup("k"); + + minimumDepth_ = dimensions_.z(); + depth_ = minimumDepth_; + + D4Sigma_ = + heatSourceProfiles::superGaussianProfile::D4Sigma + ( + dimensions_.x(), + dimensions_.y(), + k_ + ); + + updateSource(); } // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // -inline Foam::scalar -Foam::heatSourceModels::superGaussian::weight(const vector& d) +void Foam::heatSourceModels::superGaussian::updateSource() { - vector s = dimensions_ / Foam::pow(2.0, 1.0/k_); + dimensions_.z() = depth_; + + s_ = dimensions_/Foam::pow(2.0, 1.0/k_); + + const scalar fMax = + Foam::pow + ( + invIncGammaRatio_P(3.0/k_, 1.0 - tolerance_), + 1.0/k_ + ); + + sourceBb_ = + boundBox + ( + point(-fMax*s_.x(), -fMax*s_.y(), -fMax*s_.z()), + point(fMax*s_.x(), fMax*s_.y(), 0) + ); + + V0_ = + dimensionedScalar + ( + "V0", + dimVolume, + (2.0/3.0)*s_.x()*s_.y()*s_.z()*pi + *Foam::tgamma(1.0 + 3.0/k_) + ); +} - scalar x = Foam::pow(magSqr(cmptDivide(d, s)), k_/2.0); - return Foam::exp(-x); +void Foam::heatSourceModels::superGaussian::update() +{ + updateDepth(); + updateSource(); } -inline Foam::dimensionedScalar -Foam::heatSourceModels::superGaussian::V0() -{ - vector s = dimensions_ / Foam::pow(2.0, 1.0/k_); - const dimensionedScalar V0 - ( - "V0", - dimVolume, - (2.0 / 3.0)*s.x()*s.y()*s.z()*pi*Foam::tgamma(1.0 + 3.0/k_) - ); +inline Foam::scalar +Foam::heatSourceModels::superGaussian::weight(const vector& r) const +{ + if (r.z() > 0) + { + return 0; + } - return V0; + return Foam::exp(-Foam::pow(magSqr(cmptDivide(r, s_)), k_/2.0)); } bool Foam::heatSourceModels::superGaussian::read() { if (heatSourceModel::read()) { - heatSourceModelCoeffs_ = optionalSubDict(type() + "Coeffs"); - - //- Mandatory entries + heatSourceModelCoeffs_.lookup("dimensions") >> dimensions_; heatSourceModelCoeffs_.lookup("k") >> k_; + minimumDepth_ = dimensions_.z(); + depth_ = max(minimumDepth_, isoDepth_); + + D4Sigma_ = + heatSourceProfiles::superGaussianProfile::D4Sigma + ( + dimensions_.x(), + dimensions_.y(), + k_ + ); + + updateSource(); + return true; } else diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/superGaussian/superGaussian.H b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/superGaussian/superGaussian.H index 1532552a..34db7280 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 super-Gaussian heat source model applied in the negative z + direction from the beam plane. SourceFiles superGaussian.C @@ -56,12 +57,21 @@ class superGaussian { // Private Data - //- Pointer to mesh information - const fvMesh& mesh_; + //- Heat source dimensions + vector dimensions_; //- Shape coefficient of supergaussian distribution scalar k_; + //- Scaled heat source dimensions + vector s_; + + + // Private Member Functions + + //- Update the source dimensions, bounds and normalization + void updateSource(); + public: //- Runtime type information @@ -86,11 +96,11 @@ public: // Member Functions - inline virtual scalar weight(const vector& d); + virtual void update(); - inline virtual dimensionedScalar V0(); + inline virtual scalar weight(const vector& r) const; - //- Read the heatSourceProperties dictionary + //- Read the heatSourceDict dictionary virtual bool read(); }; 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/movingHeatSourceModel/movingHeatSourceModel.C b/applications/solvers/additiveFoam/movingHeatSource/movingHeatSourceModel/movingHeatSourceModel.C index 05b8c23d..52739f50 100644 --- a/applications/solvers/additiveFoam/movingHeatSource/movingHeatSourceModel/movingHeatSourceModel.C +++ b/applications/solvers/additiveFoam/movingHeatSource/movingHeatSourceModel/movingHeatSourceModel.C @@ -109,12 +109,15 @@ void Foam::movingHeatSourceModel::update() { 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(); @@ -130,8 +133,6 @@ 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)); @@ -141,11 +142,10 @@ void Foam::movingHeatSourceModel::update() sources_[i].beam().move(pathTime); qDoti += dt*sources_[i].qDot(); - - sumWeights += dt; } - qDoti /= sumWeights; + // Preserve the active fraction of a time step ending after the path + qDoti /= deltaT; qDot_ += qDoti; } diff --git a/applications/solvers/additiveFoam/movingHeatSource/refinementModels/noRefinementModel/noRefinementModel.H b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/noRefinementModel/noRefinementModel.H index f95af438..d7b8385d 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 \*---------------------------------------------------------------------------*/ @@ -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..e503dd9f 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 . \*---------------------------------------------------------------------------*/ diff --git a/applications/solvers/additiveFoam/movingHeatSource/refinementModels/refinementModel/refinementModel.H b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/refinementModel/refinementModel.H index 842f923b..f068a8fa 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 @@ -270,7 +270,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/targetCellLoad/targetCellLoad.C b/applications/solvers/additiveFoam/movingHeatSource/refinementModels/targetCellLoad/targetCellLoad.C index 083f9cbc..83ef8650 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 . \*---------------------------------------------------------------------------*/ @@ -218,17 +218,8 @@ Foam::refinementModels::targetCellLoad::targetCellLoad // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // -bool Foam::refinementModels::targetCellLoad::update() +void Foam::refinementModels::targetCellLoad::update() { - label nCellsTotal = mesh_.nCells(); - reduce(nCellsTotal, sumOp