diff --git a/applications/solvers/additiveFoam/additiveFoam.C b/applications/solvers/additiveFoam/additiveFoam.C index 5000591..b1afc92 100644 --- a/applications/solvers/additiveFoam/additiveFoam.C +++ b/applications/solvers/additiveFoam/additiveFoam.C @@ -42,6 +42,8 @@ Description #include "movingHeatSourceModel.H" #include "foamToExaCA/foamToExaCA.H" +#include "interface/interfacePoints.H" + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // int main(int argc, char *argv[]) @@ -67,12 +69,16 @@ int main(int argc, char *argv[]) movingHeatSourceModel sources(mesh); + DynamicList> interfaceData; + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Info<< "\nStarting time loop\n" << endl; while (runTime.run()) { + volScalarField R("R", mag(fvc::ddt(T))); + #include "updateProperties.H" #include "readTimeControls.H" @@ -94,6 +100,8 @@ int main(int argc, char *argv[]) } #include "thermo/TEqn.H" + + #include "interface/interface.H" ExaCA.update(); @@ -104,6 +112,8 @@ int main(int argc, char *argv[]) << nl << endl; } + #include "interface/interfaceWrite.H" + ExaCA.write(); return 0; diff --git a/applications/solvers/additiveFoam/interface/interface.H b/applications/solvers/additiveFoam/interface/interface.H new file mode 100644 index 0000000..f30460d --- /dev/null +++ b/applications/solvers/additiveFoam/interface/interface.H @@ -0,0 +1,28 @@ +// write out interface dimensions +Info<< "interface span " << "(" << Tliq.value() << "): " + << interfacePoints(T, Tliq.value()) << endl; + +Info<< "interface span " << "(" << Tsol.value() << "): " + << interfacePoints(T, Tsol.value()) << endl; + +// write out the maximum temperature +Info<< "maximum temperature: " << gMax(T.internalField()) << endl; + +volScalarField G("G", mag(fvc::grad(T))); + +forAll(mesh.cells(), celli) +{ + if ( (T[celli] <= Tliq.value()) && (T.oldTime()[celli] > Tliq.value()) ) + { + const point pt = mesh.C()[celli]; + + interfaceData.append( + { + pt[0], + pt[1], + pt[2], + R[celli] / G[celli], + G[celli] + }); + } +} diff --git a/applications/solvers/additiveFoam/interface/interfacePoints.H b/applications/solvers/additiveFoam/interface/interfacePoints.H new file mode 100644 index 0000000..7bb42da --- /dev/null +++ b/applications/solvers/additiveFoam/interface/interfacePoints.H @@ -0,0 +1,81 @@ +vector interfacePoints(const volScalarField& field, const scalar& iso) +{ + const fvMesh& mesh = field.mesh(); + + // set local reference to mesh data + const labelUList& owner = mesh.owner(); + const labelUList& neighbour = mesh.neighbour(); + + const volVectorField& cc = mesh.C(); + + DynamicList positions(mesh.nFaces()); + + // check internal faces + for(label facei=0; facei < mesh.nInternalFaces(); facei++) + { + const label own = owner[facei]; + const label nei = neighbour[facei]; + + scalar minFace = min(field[own], field[nei]); + scalar maxFace = max(field[own], field[nei]); + + if ((minFace < iso) && (maxFace >= iso)) + { + vector d = cc[nei] - cc[own]; + vector p = cc[own] + d*(iso - field[own])/(field[nei] - field[own]); + positions.append(p); + } + } + + // check boundary faces + const volScalarField::Boundary& fieldBf = field.boundaryField(); + + forAll(fieldBf, patchi) + { + const fvPatchScalarField& fieldPf = fieldBf[patchi]; + + const labelUList& faceCells = fieldPf.patch().faceCells(); + + if (fieldPf.coupled()) + { + // processor boundary : interpolate across face + const vectorField ccn(cc.boundaryField()[patchi].patchNeighbourField()); + const scalarField fn(fieldPf.patchNeighbourField()); + + forAll(faceCells, facei) + { + label own = faceCells[facei]; + + scalar minFace = min(field[own], fn[facei]); + scalar maxFace = max(field[own], fn[facei]); + + if ((minFace < iso) && (maxFace >= iso)) + { + vector d = ccn[facei] - cc[own]; + vector p = cc[own] + d*(iso - field[own])/(fn[facei] - field[own]); + positions.append(p); + } + } + } + else + { + // physical boundary : take face centre in liquid + const vectorField fc(mesh.boundaryMesh()[patchi].faceCentres()); + const scalarField pif(fieldPf.patchInternalField()); + + forAll(fc, i) + { + if (pif[i] >= iso) + { + positions.append(fc[i]); + } + } + } + } + + positions.shrink(); + + boundBox isoBb(positions); + + return returnReduce(isoBb.span(), maxOp()); +} diff --git a/applications/solvers/additiveFoam/interface/interfaceWrite.H b/applications/solvers/additiveFoam/interface/interfaceWrite.H new file mode 100644 index 0000000..021d095 --- /dev/null +++ b/applications/solvers/additiveFoam/interface/interfaceWrite.H @@ -0,0 +1,22 @@ +const fileName interfacePath +( + runTime.rootPath()/runTime.globalCaseName()/"solidificationData" +); + +mkDir(interfacePath); + +OFstream os +( + interfacePath + "/" + "data_" + Foam::name(Pstream::myProcNo()) + ".csv" +); + +for(int i=0; i < interfaceData.size(); i++) +{ + int n = interfaceData[i].size()-1; + + for(int j=0; j < n; j++) + { + os << interfaceData[i][j] << ","; + } + os << interfaceData[i][n] << endl; +} diff --git a/applications/solvers/additiveFoam/movingHeatSource/Make/files b/applications/solvers/additiveFoam/movingHeatSource/Make/files index 044edf5..fda4be0 100644 --- a/applications/solvers/additiveFoam/movingHeatSource/Make/files +++ b/applications/solvers/additiveFoam/movingHeatSource/Make/files @@ -11,6 +11,7 @@ heatSourceModels/heatSourceModel/heatSourceModel.C heatSourceModels/heatSourceModel/heatSourceModelNew.C heatSourceModels/superGaussian/superGaussian.C heatSourceModels/modifiedSuperGaussian/modifiedSuperGaussian.C +heatSourceModels/nLight/nLight.C movingHeatSourceModel/movingHeatSourceModel.C diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.C index 02a7d04..a9dad5d 100644 --- a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.C +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/heatSourceModel/heatSourceModel.C @@ -239,7 +239,7 @@ Foam::heatSourceModel::qDot() ); volScalarField& qDot_ = tqDot.ref(); - // sample gaussian distribution at desired resolution + // sample distribution at desired resolution const scalar power_ = movingBeam_->power(); if (power_ > small) @@ -247,7 +247,7 @@ Foam::heatSourceModel::qDot() const vector position_ = movingBeam_->position(); // udpate the absorbed power and heat source normalization term - const scalar aspectRatio = + const scalar aspectRatio = dimensions_.z() / min(dimensions_.x(), dimensions_.y()); dimensionedScalar absorbedPower @@ -275,7 +275,7 @@ Foam::heatSourceModel::qDot() ); const pointField& points = mesh_.points(); - + treeBoundBox beamBb ( position_ - 1.5*dimensions_, diff --git a/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/nLight/nLight.C b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/nLight/nLight.C new file mode 100644 index 0000000..686c0d7 --- /dev/null +++ b/applications/solvers/additiveFoam/movingHeatSource/heatSourceModels/nLight/nLight.C @@ -0,0 +1,247 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 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 "nLight.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace heatSourceModels +{ + defineTypeNameAndDebug(nLight, 0); + addToRunTimeSelectionTable(heatSourceModel, nLight, dictionary); +} +} + +using Foam::constant::mathematical::pi; + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::heatSourceModels::nLight::nLight +( + const word& sourceName, + const dictionary& dict, + const fvMesh& mesh +) +: + heatSourceModel(typeName, sourceName, dict, mesh), + mesh_(mesh), + spotCoeffs_(heatSourceModelCoeffs_.optionalSubDict("spotCoeffs")), + ringCoeffs_(heatSourceModelCoeffs_.optionalSubDict("ringCoeffs")) +{ + // Select parameters from specified mode + mode_ = heatSourceModelCoeffs_.lookup