1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2008-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
28 #include "addToRunTimeSelectionTable.H"
31 #include "absorptionEmissionModel.H"
32 #include "scatterModel.H"
33 #include "mathematicalConstants.H"
34 #include "radiationConstants.H"
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 defineTypeNameAndDebug(fvDOM, 0);
44 addToRunTimeSelectionTable
54 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
56 Foam::radiation::fvDOM::fvDOM(const volScalarField& T)
58 radiationModel(typeName, T),
64 mesh_.time().timeName(),
70 dimensionedScalar("G", dimMass/pow3(dimTime), 0.0)
77 mesh_.time().timeName(),
83 dimensionedScalar("Qr", dimMass/pow3(dimTime), 0.0)
90 mesh_.time().timeName(),
96 dimensionedScalar("a", dimless/dimLength, 0.0)
103 mesh_.time().timeName(),
109 dimensionedScalar("a", dimless/dimLength, 0.0)
116 mesh_.time().timeName(),
122 dimensionedScalar("E", dimMass/dimLength/pow3(dimTime), 0.0)
124 nTheta_(readLabel(coeffs_.lookup("nTheta"))),
125 nPhi_(readLabel(coeffs_.lookup("nPhi"))),
127 nLambda_(absorptionEmission_->nBands()),
129 blackBody_(nLambda_, T),
131 convergence_(coeffs_.lookupOrDefault<scalar>("convergence", 0.0)),
132 maxIter_(coeffs_.lookupOrDefault<label>("maxIter", 50))
134 if (mesh_.nSolutionD() == 3) //3D
136 nRay_ = 4*nPhi_*nTheta_;
137 IRay_.setSize(nRay_);
138 scalar deltaPhi = mathematicalConstant::pi/(2.0*nPhi_);
139 scalar deltaTheta = mathematicalConstant::pi/nTheta_;
141 for (label n = 1; n <= nTheta_; n++)
143 for (label m = 1; m <= 4*nPhi_; m++)
145 scalar thetai = (2.0*n - 1.0)*deltaTheta/2.0;
146 scalar phii = (2.0*m - 1.0)*deltaPhi/2.0;
150 new radiativeIntensityRay
169 if (mesh_.nSolutionD() == 2) //2D (X & Y)
171 scalar thetai = mathematicalConstant::pi/2.0;
172 scalar deltaTheta = mathematicalConstant::pi;
174 IRay_.setSize(nRay_);
175 scalar deltaPhi = mathematicalConstant::pi/(2.0*nPhi_);
177 for (label m = 1; m <= 4*nPhi_; m++)
179 scalar phii = (2.0*m - 1.0)*deltaPhi/2.0;
183 new radiativeIntensityRay
201 scalar thetai = mathematicalConstant::pi/2.0;
202 scalar deltaTheta = mathematicalConstant::pi;
204 IRay_.setSize(nRay_);
205 scalar deltaPhi = mathematicalConstant::pi;
207 for (label m = 1; m <= 2; m++)
209 scalar phii = (2.0*m - 1.0)*deltaPhi/2.0;
213 new radiativeIntensityRay
233 // Construct absorption field for each wavelength
234 forAll(aLambda_, lambdaI)
243 "aLambda_" + Foam::name(lambdaI) ,
244 mesh_.time().timeName(),
254 Info<< "fvDOM : Allocated " << IRay_.size()
255 << " rays with average orientation:" << nl;
258 Info<< '\t' << IRay_[i].I().name()
259 << '\t' << IRay_[i].dAve() << nl;
265 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
267 Foam::radiation::fvDOM::~fvDOM()
271 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
273 bool Foam::radiation::fvDOM::read()
275 if (radiationModel::read())
277 // Only reading solution parameters - not changing ray geometry
279 coeffs_.readIfPresent("convergence", convergence_);
280 coeffs_.readIfPresent("maxIter", maxIter_);
291 void Foam::radiation::fvDOM::calculate()
293 absorptionEmission_->correct(a_, aLambda_);
295 updateBlackBodyEmission();
297 scalar maxResidual = 0.0;
305 scalar maxBandResidual = IRay_[rayI].correct();
306 maxResidual = max(maxBandResidual, maxResidual);
309 Info << "Radiation solver iter: " << radIter << endl;
311 } while(maxResidual > convergence_ && radIter < maxIter_);
317 Foam::tmp<Foam::volScalarField> Foam::radiation::fvDOM::Rp() const
319 return tmp<volScalarField>
326 mesh_.time().timeName(),
332 4.0*a_*radiation::sigmaSB //absorptionEmission_->a()
338 Foam::tmp<Foam::DimensionedField<Foam::scalar, Foam::volMesh> >
339 Foam::radiation::fvDOM::Ru() const
342 const DimensionedField<scalar, volMesh>& G =
343 G_.dimensionedInternalField();
344 const DimensionedField<scalar, volMesh> E =
345 absorptionEmission_->ECont()().dimensionedInternalField();
346 const DimensionedField<scalar, volMesh> a =
347 a_.dimensionedInternalField(); //absorptionEmission_->aCont()()
353 void Foam::radiation::fvDOM::updateBlackBodyEmission()
355 for (label j=0; j < nLambda_; j++)
357 blackBody_.correct(j, absorptionEmission_->bands(j));
362 void Foam::radiation::fvDOM::updateG()
364 G_ = dimensionedScalar("zero",dimMass/pow3(dimTime), 0.0);
365 Qr_ = dimensionedScalar("zero",dimMass/pow3(dimTime), 0.0);
369 IRay_[rayI].addIntensity();
370 G_ += IRay_[rayI].I()*IRay_[rayI].omega();
371 //Qr_ += IRay_[rayI].Qr();
372 Qr_.boundaryField() += IRay_[rayI].Qr().boundaryField();
377 void Foam::radiation::fvDOM::setRayIdLambdaId
384 // assuming name is in the form: CHARS_rayId_lambdaId
385 size_type i1 = name.find_first_of("_");
386 size_type i2 = name.find_last_of("_");
388 rayId = readLabel(IStringStream(name.substr(i1+1, i2-1))());
389 lambdaId = readLabel(IStringStream(name.substr(i2+1, name.size()-1))());
393 // ************************************************************************* //