BUG: Have sensible value for refValue.
[OpenFOAM-1.6.x.git] / src / turbulenceModels / compressible / RAS / derivedFvPatchFields / turbulentTemperatureCoupledBaffleMixed / turbulentTemperatureCoupledBaffleMixedFvPatchScalarField.C
blob494a1e3257342bcca3647b3256b636ed8468e236
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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 \*---------------------------------------------------------------------------*/
27 #include "turbulentTemperatureCoupledBaffleMixedFvPatchScalarField.H"
28 #include "addToRunTimeSelectionTable.H"
29 #include "fvPatchFieldMapper.H"
30 #include "volFields.H"
31 #include "directMappedPatchBase.H"
32 #include "regionProperties.H"
33 #include "basicThermo.H"
34 #include "RASModel.H"
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
38 namespace Foam
40 namespace compressible
43 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
45 bool turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::interfaceOwner
47     const polyMesh& nbrRegion,
48     const polyPatch& nbrPatch
49 ) const
51     const fvMesh& myRegion = patch().boundaryMesh().mesh();
53     if (nbrRegion.name() == myRegion.name())
54     {
55         return patch().index() < nbrPatch.index();
56     }
57     else
58     {
59         const regionProperties& props =
60             myRegion.objectRegistry::parent().lookupObject<regionProperties>
61             (
62                 "regionProperties"
63             );
65         label myIndex = findIndex(props.fluidRegionNames(), myRegion.name());
66         if (myIndex == -1)
67         {
68             label i = findIndex(props.solidRegionNames(), myRegion.name());
70             if (i == -1)
71             {
72                 FatalErrorIn
73                 (
74                     "turbulentTemperatureCoupledBaffleMixedFvPatchScalarField"
75                     "::interfaceOwner(const polyMesh&"
76                     ", const polyPatch&)const"
77                 )   << "Cannot find region " << myRegion.name()
78                     << " neither in fluids " << props.fluidRegionNames()
79                     << " nor in solids " << props.solidRegionNames()
80                     << exit(FatalError);
81             }
82             myIndex = props.fluidRegionNames().size() + i;
83         }
84         label nbrIndex = findIndex
85         (
86             props.fluidRegionNames(),
87             nbrRegion.name()
88         );
89         if (nbrIndex == -1)
90         {
91             label i = findIndex(props.solidRegionNames(), nbrRegion.name());
93             if (i == -1)
94             {
95                 FatalErrorIn
96                 (
97                     "coupleManager::interfaceOwner"
98                     "(const polyMesh&, const polyPatch&) const"
99                 )   << "Cannot find region " << nbrRegion.name()
100                     << " neither in fluids " << props.fluidRegionNames()
101                     << " nor in solids " << props.solidRegionNames()
102                     << exit(FatalError);
103             }
104             nbrIndex = props.fluidRegionNames().size() + i;
105         }
106         return myIndex < nbrIndex;
107     }
111 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
113 turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::
114 turbulentTemperatureCoupledBaffleMixedFvPatchScalarField
116     const fvPatch& p,
117     const DimensionedField<scalar, volMesh>& iF
120     mixedFvPatchScalarField(p, iF),
121     neighbourFieldName_("undefined-neighbourFieldName"),
122     KName_("undefined-K")
124     this->refValue() = 0.0;
125     this->refGrad() = 0.0;
126     this->valueFraction() = 1.0;
127     this->fixesValue_ = true;
131 turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::
132 turbulentTemperatureCoupledBaffleMixedFvPatchScalarField
134     const turbulentTemperatureCoupledBaffleMixedFvPatchScalarField& ptf,
135     const fvPatch& p,
136     const DimensionedField<scalar, volMesh>& iF,
137     const fvPatchFieldMapper& mapper
140     mixedFvPatchScalarField(ptf, p, iF, mapper),
141     neighbourFieldName_(ptf.neighbourFieldName_),
142     KName_(ptf.KName_),
143     fixesValue_(ptf.fixesValue_)
147 turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::
148 turbulentTemperatureCoupledBaffleMixedFvPatchScalarField
150     const fvPatch& p,
151     const DimensionedField<scalar, volMesh>& iF,
152     const dictionary& dict
155     mixedFvPatchScalarField(p, iF),
156     neighbourFieldName_(dict.lookup("neighbourFieldName")),
157     KName_(dict.lookup("K"))
159     if (!isA<directMappedPatchBase>(this->patch().patch()))
160     {
161         FatalErrorIn
162         (
163             "turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::"
164             "turbulentTemperatureCoupledBaffleMixedFvPatchScalarField\n"
165             "(\n"
166             "    const fvPatch& p,\n"
167             "    const DimensionedField<scalar, volMesh>& iF,\n"
168             "    const dictionary& dict\n"
169             ")\n"
170         )   << "\n    patch type '" << p.type()
171             << "' not type '" << directMappedPatchBase::typeName << "'"
172             << "\n    for patch " << p.name()
173             << " of field " << dimensionedInternalField().name()
174             << " in file " << dimensionedInternalField().objectPath()
175             << exit(FatalError);
176     }
178     fvPatchScalarField::operator=(scalarField("value", dict, p.size()));
180     if (dict.found("refValue"))
181     {
182         // Full restart
183         refValue() = scalarField("refValue", dict, p.size());
184         refGrad() = scalarField("refGradient", dict, p.size());
185         valueFraction() = scalarField("valueFraction", dict, p.size());
186         fixesValue_ = readBool(dict.lookup("fixesValue"));
187     }
188     else
189     {
190         // Start from user entered data. Assume fixedValue.
191         refValue() = *this;
192         refGrad() = 0.0;
193         valueFraction() = 1.0;
194         fixesValue_ = true;
195     }
199 turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::
200 turbulentTemperatureCoupledBaffleMixedFvPatchScalarField
202     const turbulentTemperatureCoupledBaffleMixedFvPatchScalarField& wtcsf,
203     const DimensionedField<scalar, volMesh>& iF
206     mixedFvPatchScalarField(wtcsf, iF),
207     neighbourFieldName_(wtcsf.neighbourFieldName_),
208     KName_(wtcsf.KName_),
209     fixesValue_(wtcsf.fixesValue_)
213 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
215 tmp<scalarField>
216 turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::K() const
218     const fvMesh& mesh = patch().boundaryMesh().mesh();
220     if (KName_ == "none")
221     {
222         const compressible::RASModel& model =
223             db().lookupObject<compressible::RASModel>("RASProperties");
225         tmp<volScalarField> talpha = model.alphaEff();
227         const basicThermo& thermo =
228             db().lookupObject<basicThermo>("thermophysicalProperties");
230         return
231             talpha().boundaryField()[patch().index()]
232            *thermo.Cp()().boundaryField()[patch().index()];
233     }
234     else if (mesh.objectRegistry::foundObject<volScalarField>(KName_))
235     {
236         return patch().lookupPatchField<volScalarField, scalar>(KName_);
237     }
238     else if (mesh.objectRegistry::foundObject<volSymmTensorField>(KName_))
239     {
240         const symmTensorField& KWall =
241             patch().lookupPatchField<volSymmTensorField, scalar>(KName_);
243         vectorField n = patch().nf();
245         return n & KWall & n;
246     }
247     else
248     {
249         FatalErrorIn
250         (
251             "turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::K()"
252             " const"
253         )   << "Did not find field " << KName_
254             << " on mesh " << mesh.name() << " patch " << patch().name()
255             << endl
256             << "Please set 'K' to 'none', a valid volScalarField"
257             << " or a valid volSymmTensorField." << exit(FatalError);
259         return scalarField(0);
260     }
264 void turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::updateCoeffs()
266     if (updated())
267     {
268         return;
269     }
271     // Get the coupling information from the directMappedPatchBase
272     const directMappedPatchBase& mpp = refCast<const directMappedPatchBase>
273     (
274         patch().patch()
275     );
276     const polyMesh& nbrMesh = mpp.sampleMesh();
277     const fvPatch& nbrPatch = refCast<const fvMesh>
278     (
279         nbrMesh
280     ).boundary()[mpp.samplePolyPatch().index()];
282     // Force recalculation of mapping and schedule
283     const mapDistribute& distMap = mpp.map();
284     (void)distMap.schedule();
286     tmp<scalarField> intFld = patchInternalField();
288     if (interfaceOwner(nbrMesh, nbrPatch.patch()))
289     {
290         // Note: other side information could be cached - it only needs
291         // to be updated the first time round the iteration (i.e. when
292         // switching regions) but unfortunately we don't have this information.
295         // Calculate the temperature by harmonic averaging
296         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
298         const turbulentTemperatureCoupledBaffleMixedFvPatchScalarField&
299         nbrField =
300         refCast
301         <
302             const turbulentTemperatureCoupledBaffleMixedFvPatchScalarField
303         >
304         (
305             nbrPatch.lookupPatchField<volScalarField, scalar>
306             (
307                 neighbourFieldName_
308             )
309         );
311         // Swap to obtain full local values of neighbour internal field
312         scalarField nbrIntFld = nbrField.patchInternalField();
313         mapDistribute::distribute
314         (
315             Pstream::defaultCommsType,
316             distMap.schedule(),
317             distMap.constructSize(),
318             distMap.subMap(),           // what to send
319             distMap.constructMap(),     // what to receive
320             nbrIntFld
321         );
323         // Swap to obtain full local values of neighbour K*delta
324         scalarField nbrKDelta = nbrField.K()*nbrPatch.deltaCoeffs();
325         mapDistribute::distribute
326         (
327             Pstream::defaultCommsType,
328             distMap.schedule(),
329             distMap.constructSize(),
330             distMap.subMap(),           // what to send
331             distMap.constructMap(),     // what to receive
332             nbrKDelta
333         );
335         tmp<scalarField> myKDelta = K()*patch().deltaCoeffs();
337         // Calculate common wall temperature. Reuse *this to store common value.
338         scalarField Twall
339         (
340             (myKDelta()*intFld() + nbrKDelta*nbrIntFld)
341           / (myKDelta() + nbrKDelta)
342         );
343         // Assign to me
344         fvPatchScalarField::operator=(Twall);
345         // Distribute back and assign to neighbour
346         mapDistribute::distribute
347         (
348             Pstream::defaultCommsType,
349             distMap.schedule(),
350             nbrField.size(),
351             distMap.constructMap(),     // reverse : what to send
352             distMap.subMap(),
353             Twall
354         );
355         const_cast<turbulentTemperatureCoupledBaffleMixedFvPatchScalarField&>
356         (
357             nbrField
358         ).fvPatchScalarField::operator=(Twall);
359     }
362     // Switch between fixed value (of harmonic avg) or gradient
363     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
365     label nFixed = 0;
367     // Like snGrad but bypass switching on refValue/refGrad.
368     tmp<scalarField> normalGradient = (*this-intFld())*patch().deltaCoeffs();
370     if (debug)
371     {
372         scalar Q = gSum(K()*patch().magSf()*normalGradient());
374         Info<< patch().boundaryMesh().mesh().name() << ':'
375             << patch().name() << ':'
376             << this->dimensionedInternalField().name() << " -> "
377             << nbrMesh.name() << ':'
378             << nbrPatch.name() << ':'
379             << this->dimensionedInternalField().name() << " :"
380             << " heatFlux:" << Q
381             << " walltemperature "
382             << " min:" << gMin(*this)
383             << " max:" << gMax(*this)
384             << " avg:" << gAverage(*this)
385             << endl;
386     }
388     forAll(*this, i)
389     {
390         // if outgoing flux use fixed value.
391         if (normalGradient()[i] < 0.0)
392         {
393             this->refValue()[i] = operator[](i);
394             this->refGrad()[i] = 0.0;   // not used by me
395             this->valueFraction()[i] = 1.0;
396             nFixed++;
397         }
398         else
399         {
400             // Fixed gradient. Make sure to have valid refValue (even though
401             // I am not using it - other boundary conditions might)
402             this->refValue()[i] = operator[](i);
403             this->refGrad()[i] = normalGradient()[i];
404             this->valueFraction()[i] = 0.0;
405         }
406     }
408     reduce(nFixed, sumOp<label>());
410     fixesValue_ = (nFixed > 0);
412     if (debug)
413     {
414         label nTotSize = returnReduce(this->size(), sumOp<label>());
416         Info<< patch().boundaryMesh().mesh().name() << ':'
417             << patch().name() << ':'
418             << this->dimensionedInternalField().name() << " -> "
419             << nbrMesh.name() << ':'
420             << nbrPatch.name() << ':'
421             << this->dimensionedInternalField().name() << " :"
422             << " patch:" << patch().name()
423             << " out of:" << nTotSize
424             << " fixedBC:" << nFixed
425             << " gradient:" << nTotSize-nFixed << endl;
426     }
428     mixedFvPatchScalarField::updateCoeffs();
432 void turbulentTemperatureCoupledBaffleMixedFvPatchScalarField::write
434     Ostream& os
435 ) const
437     mixedFvPatchScalarField::write(os);
438     os.writeKeyword("neighbourFieldName")<< neighbourFieldName_
439         << token::END_STATEMENT << nl;
440     os.writeKeyword("K") << KName_ << token::END_STATEMENT << nl;
441     os.writeKeyword("fixesValue") << fixesValue_ << token::END_STATEMENT << nl;
445 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
447 makePatchTypeField
449     fvPatchScalarField,
450     turbulentTemperatureCoupledBaffleMixedFvPatchScalarField
454 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
456 } // End namespace compressible
457 } // End namespace Foam
460 // ************************************************************************* //