initial commit for version 1.6.x patch release
[OpenFOAM-1.6.x.git] / applications / solvers / heatTransfer / chtMultiRegionFoam / derivedFvPatchFields / solidWallMixedTemperatureCoupled / solidWallMixedTemperatureCoupledFvPatchScalarField.C
blob5bec5673108e4cd0c0684e041b6443f769c0ff55
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 "solidWallMixedTemperatureCoupledFvPatchScalarField.H"
28 #include "addToRunTimeSelectionTable.H"
29 #include "fvPatchFieldMapper.H"
30 #include "volFields.H"
31 #include "directMappedPatchBase.H"
32 #include "regionProperties.H"
34 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
36 bool Foam::solidWallMixedTemperatureCoupledFvPatchScalarField::interfaceOwner
38     const polyMesh& nbrRegion
39 ) const
41     const fvMesh& myRegion = patch().boundaryMesh().mesh();
43     const regionProperties& props =
44         myRegion.objectRegistry::parent().lookupObject<regionProperties>
45         (
46             "regionProperties"
47         );
49     label myIndex = findIndex(props.fluidRegionNames(), myRegion.name());
50     if (myIndex == -1)
51     {
52         label i = findIndex(props.solidRegionNames(), myRegion.name());
54         if (i == -1)
55         {
56             FatalErrorIn
57             (
58                 "solidWallMixedTemperatureCoupledFvPatchScalarField"
59                 "::interfaceOwner(const polyMesh&) const"
60             )   << "Cannot find region " << myRegion.name()
61                 << " neither in fluids " << props.fluidRegionNames()
62                 << " nor in solids " << props.solidRegionNames()
63                 << exit(FatalError);
64         }
65         myIndex = props.fluidRegionNames().size() + i;
66     }
67     label nbrIndex = findIndex(props.fluidRegionNames(), nbrRegion.name());
68     if (nbrIndex == -1)
69     {
70         label i = findIndex(props.solidRegionNames(), nbrRegion.name());
72         if (i == -1)
73         {
74             FatalErrorIn("coupleManager::interfaceOwner(const polyMesh&) const")
75                 << "Cannot find region " << nbrRegion.name()
76                 << " neither in fluids " << props.fluidRegionNames()
77                 << " nor in solids " << props.solidRegionNames()
78                 << exit(FatalError);
79         }
80         nbrIndex = props.fluidRegionNames().size() + i;
81     }
83     return myIndex < nbrIndex;
87 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
89 Foam::solidWallMixedTemperatureCoupledFvPatchScalarField::
90 solidWallMixedTemperatureCoupledFvPatchScalarField
92     const fvPatch& p,
93     const DimensionedField<scalar, volMesh>& iF
96     mixedFvPatchScalarField(p, iF),
97     neighbourFieldName_("undefined-neighbourFieldName"),
98     KName_("undefined-K")
100     this->refValue() = 0.0;
101     this->refGrad() = 0.0;
102     this->valueFraction() = 1.0;
103     this->fixesValue_ = true;
107 Foam::solidWallMixedTemperatureCoupledFvPatchScalarField::
108 solidWallMixedTemperatureCoupledFvPatchScalarField
110     const solidWallMixedTemperatureCoupledFvPatchScalarField& ptf,
111     const fvPatch& p,
112     const DimensionedField<scalar, volMesh>& iF,
113     const fvPatchFieldMapper& mapper
116     mixedFvPatchScalarField(ptf, p, iF, mapper),
117     neighbourFieldName_(ptf.neighbourFieldName_),
118     KName_(ptf.KName_),
119     fixesValue_(ptf.fixesValue_)
123 Foam::solidWallMixedTemperatureCoupledFvPatchScalarField::
124 solidWallMixedTemperatureCoupledFvPatchScalarField
126     const fvPatch& p,
127     const DimensionedField<scalar, volMesh>& iF,
128     const dictionary& dict
131     mixedFvPatchScalarField(p, iF),
132     neighbourFieldName_(dict.lookup("neighbourFieldName")),
133     KName_(dict.lookup("K"))
135     if (!isA<directMappedPatchBase>(this->patch().patch()))
136     {
137         FatalErrorIn
138         (
139             "solidWallMixedTemperatureCoupledFvPatchScalarField::"
140             "solidWallMixedTemperatureCoupledFvPatchScalarField\n"
141             "(\n"
142             "    const fvPatch& p,\n"
143             "    const DimensionedField<scalar, volMesh>& iF,\n"
144             "    const dictionary& dict\n"
145             ")\n"
146         )   << "\n    patch type '" << p.type()
147             << "' not type '" << directMappedPatchBase::typeName << "'"
148             << "\n    for patch " << p.name()
149             << " of field " << dimensionedInternalField().name()
150             << " in file " << dimensionedInternalField().objectPath()
151             << exit(FatalError);
152     }
154     fvPatchScalarField::operator=(scalarField("value", dict, p.size()));
156     if (dict.found("refValue"))
157     {
158         // Full restart
159         refValue() = scalarField("refValue", dict, p.size());
160         refGrad() = scalarField("refGradient", dict, p.size());
161         valueFraction() = scalarField("valueFraction", dict, p.size());
162         fixesValue_ = readBool(dict.lookup("fixesValue"));
163     }
164     else
165     {
166         // Start from user entered data. Assume fixedValue.
167         refValue() = *this;
168         refGrad() = 0.0;
169         valueFraction() = 1.0;
170         fixesValue_ = true;
171     }
175 Foam::solidWallMixedTemperatureCoupledFvPatchScalarField::
176 solidWallMixedTemperatureCoupledFvPatchScalarField
178     const solidWallMixedTemperatureCoupledFvPatchScalarField& wtcsf,
179     const DimensionedField<scalar, volMesh>& iF
182     mixedFvPatchScalarField(wtcsf, iF),
183     neighbourFieldName_(wtcsf.neighbourFieldName_),
184     KName_(wtcsf.KName_),
185     fixesValue_(wtcsf.fixesValue_)
189 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
191 const Foam::fvPatchScalarField&
192 Foam::solidWallMixedTemperatureCoupledFvPatchScalarField::K() const
194     return this->patch().lookupPatchField<volScalarField, scalar>(KName_);
198 void Foam::solidWallMixedTemperatureCoupledFvPatchScalarField::updateCoeffs()
200     if (updated())
201     {
202         return;
203     }
205     // Get the coupling information from the directMappedPatchBase
206     const directMappedPatchBase& mpp = refCast<const directMappedPatchBase>
207     (
208         patch().patch()
209     );
210     const polyMesh& nbrMesh = mpp.sampleMesh();
212     tmp<scalarField> intFld = patchInternalField();
214     if (interfaceOwner(nbrMesh))
215     {
216         // Note: other side information could be cached - it only needs
217         // to be updated the first time round the iteration (i.e. when
218         // switching regions) but unfortunately we don't have this information.
220         const mapDistribute& distMap = mpp.map();
221         const fvPatch& nbrPatch = refCast<const fvMesh>
222         (
223             nbrMesh
224         ).boundary()[mpp.samplePolyPatch().index()];
227         // Calculate the temperature by harmonic averaging
228         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
230         const solidWallMixedTemperatureCoupledFvPatchScalarField& nbrField =
231         refCast<const solidWallMixedTemperatureCoupledFvPatchScalarField>
232         (
233             nbrPatch.lookupPatchField<volScalarField, scalar>
234             (
235                 neighbourFieldName_
236             )
237         );
239         // Swap to obtain full local values of neighbour internal field
240         scalarField nbrIntFld = nbrField.patchInternalField();
241         mapDistribute::distribute
242         (
243             Pstream::defaultCommsType,
244             distMap.schedule(),
245             distMap.constructSize(),
246             distMap.subMap(),           // what to send
247             distMap.constructMap(),     // what to receive
248             nbrIntFld
249         );
251         // Swap to obtain full local values of neighbour K*delta
252         scalarField nbrKDelta = nbrField.K()*nbrPatch.deltaCoeffs();
253         mapDistribute::distribute
254         (
255             Pstream::defaultCommsType,
256             distMap.schedule(),
257             distMap.constructSize(),
258             distMap.subMap(),           // what to send
259             distMap.constructMap(),     // what to receive
260             nbrKDelta
261         );
264         tmp<scalarField> myKDelta = K()*patch().deltaCoeffs();
266         // Calculate common wall temperature. Reuse *this to store common value.
267         scalarField Twall
268         (
269             (myKDelta()*intFld() + nbrKDelta*nbrIntFld)
270           / (myKDelta() + nbrKDelta)
271         );
272         // Assign to me
273         fvPatchScalarField::operator=(Twall);
274         // Distribute back and assign to neighbour
275         mapDistribute::distribute
276         (
277             Pstream::defaultCommsType,
278             distMap.schedule(),
279             nbrField.size(),
280             distMap.constructMap(),     // reverse : what to send
281             distMap.subMap(),
282             Twall
283         );
284         const_cast<solidWallMixedTemperatureCoupledFvPatchScalarField&>
285         (
286             nbrField
287         ).fvPatchScalarField::operator=(Twall);
288     }
291     // Switch between fixed value (of harmonic avg) or gradient
292     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
294     label nFixed = 0;
296     // Like snGrad but bypass switching on refValue/refGrad.
297     tmp<scalarField> normalGradient = (*this-intFld())*patch().deltaCoeffs();
299     if (debug)
300     {
301         scalar Q = gSum(K()*patch().magSf()*normalGradient());
303         Info<< "solidWallMixedTemperatureCoupledFvPatchScalarField::"
304             << "updateCoeffs() :"
305             << " patch:" << patch().name()
306             << " heatFlux:" << Q
307             << " walltemperature "
308             << " min:" << gMin(*this)
309             << " max:" << gMax(*this)
310             << " avg:" << gAverage(*this)
311             << endl;
312     }
314     forAll(*this, i)
315     {
316         // if outgoing flux use fixed value.
317         if (normalGradient()[i] < 0.0)
318         {
319             this->refValue()[i] = operator[](i);
320             this->refGrad()[i] = 0.0;   // not used
321             this->valueFraction()[i] = 1.0;
322             nFixed++;
323         }
324         else
325         {
326             this->refValue()[i] = 0.0;  // not used
327             this->refGrad()[i] = normalGradient()[i];
328             this->valueFraction()[i] = 0.0;
329         }
330     }
332     reduce(nFixed, sumOp<label>());
334     fixesValue_ = (nFixed > 0);
336     if (debug)
337     {
338         label nTotSize = returnReduce(this->size(), sumOp<label>());
340         Info<< "solidWallMixedTemperatureCoupledFvPatchScalarField::"
341             << "updateCoeffs() :"
342             << " patch:" << patch().name()
343             << " out of:" << nTotSize
344             << " fixedBC:" << nFixed
345             << " gradient:" << nTotSize-nFixed << endl;
346     }
348     mixedFvPatchScalarField::updateCoeffs();
352 void Foam::solidWallMixedTemperatureCoupledFvPatchScalarField::write
354     Ostream& os
355 ) const
357     mixedFvPatchScalarField::write(os);
358     os.writeKeyword("neighbourFieldName")<< neighbourFieldName_
359         << token::END_STATEMENT << nl;
360     os.writeKeyword("K") << KName_ << token::END_STATEMENT << nl;
361     os.writeKeyword("fixesValue") << fixesValue_ << token::END_STATEMENT << nl;
365 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
367 namespace Foam
370 makePatchTypeField
372     fvPatchScalarField,
373     solidWallMixedTemperatureCoupledFvPatchScalarField
376 } // End namespace Foam
378 // ************************************************************************* //