00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "advectiveFvPatchField.H"
00027 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00028 #include <finiteVolume/fvPatchFieldMapper.H>
00029 #include <finiteVolume/volFields.H>
00030 #include <finiteVolume/EulerDdtScheme.H>
00031 #include <finiteVolume/CrankNicholsonDdtScheme.H>
00032 #include <finiteVolume/backwardDdtScheme.H>
00033
00034
00035
00036 namespace Foam
00037 {
00038
00039
00040
00041 template<class Type>
00042 advectiveFvPatchField<Type>::advectiveFvPatchField
00043 (
00044 const fvPatch& p,
00045 const DimensionedField<Type, volMesh>& iF
00046 )
00047 :
00048 mixedFvPatchField<Type>(p, iF),
00049 phiName_("phi"),
00050 rhoName_("rho"),
00051 fieldInf_(pTraits<Type>::zero),
00052 lInf_(0.0)
00053 {
00054 this->refValue() = pTraits<Type>::zero;
00055 this->refGrad() = pTraits<Type>::zero;
00056 this->valueFraction() = 0.0;
00057 }
00058
00059
00060 template<class Type>
00061 advectiveFvPatchField<Type>::advectiveFvPatchField
00062 (
00063 const advectiveFvPatchField& ptf,
00064 const fvPatch& p,
00065 const DimensionedField<Type, volMesh>& iF,
00066 const fvPatchFieldMapper& mapper
00067 )
00068 :
00069 mixedFvPatchField<Type>(ptf, p, iF, mapper),
00070 phiName_(ptf.phiName_),
00071 rhoName_(ptf.rhoName_),
00072 fieldInf_(ptf.fieldInf_),
00073 lInf_(ptf.lInf_)
00074 {}
00075
00076
00077 template<class Type>
00078 advectiveFvPatchField<Type>::advectiveFvPatchField
00079 (
00080 const fvPatch& p,
00081 const DimensionedField<Type, volMesh>& iF,
00082 const dictionary& dict
00083 )
00084 :
00085 mixedFvPatchField<Type>(p, iF),
00086 phiName_(dict.lookupOrDefault<word>("phi", "phi")),
00087 rhoName_(dict.lookupOrDefault<word>("rho", "rho")),
00088 fieldInf_(pTraits<Type>::zero),
00089 lInf_(0.0)
00090 {
00091 if (dict.found("value"))
00092 {
00093 fvPatchField<Type>::operator=
00094 (
00095 Field<Type>("value", dict, p.size())
00096 );
00097 }
00098 else
00099 {
00100 fvPatchField<Type>::operator=(this->patchInternalField());
00101 }
00102
00103 this->refValue() = *this;
00104 this->refGrad() = pTraits<Type>::zero;
00105 this->valueFraction() = 0.0;
00106
00107 if (dict.readIfPresent("lInf", lInf_))
00108 {
00109 dict.lookup("fieldInf") >> fieldInf_;
00110
00111 if (lInf_ < 0.0)
00112 {
00113 FatalIOErrorIn
00114 (
00115 "advectiveFvPatchField<Type>::"
00116 "advectiveFvPatchField"
00117 "(const fvPatch&, const Field<Type>&, const dictionary&)",
00118 dict
00119 ) << "unphysical lInf specified (lInf < 0)\n"
00120 << " on patch " << this->patch().name()
00121 << " of field " << this->dimensionedInternalField().name()
00122 << " in file " << this->dimensionedInternalField().objectPath()
00123 << exit(FatalIOError);
00124 }
00125 }
00126 }
00127
00128
00129 template<class Type>
00130 advectiveFvPatchField<Type>::advectiveFvPatchField
00131 (
00132 const advectiveFvPatchField& ptpsf
00133 )
00134 :
00135 mixedFvPatchField<Type>(ptpsf),
00136 phiName_(ptpsf.phiName_),
00137 rhoName_(ptpsf.rhoName_),
00138 fieldInf_(ptpsf.fieldInf_),
00139 lInf_(ptpsf.lInf_)
00140 {}
00141
00142
00143 template<class Type>
00144 advectiveFvPatchField<Type>::advectiveFvPatchField
00145 (
00146 const advectiveFvPatchField& ptpsf,
00147 const DimensionedField<Type, volMesh>& iF
00148 )
00149 :
00150 mixedFvPatchField<Type>(ptpsf, iF),
00151 phiName_(ptpsf.phiName_),
00152 rhoName_(ptpsf.rhoName_),
00153 fieldInf_(ptpsf.fieldInf_),
00154 lInf_(ptpsf.lInf_)
00155 {}
00156
00157
00158
00159
00160 template<class Type>
00161 tmp<scalarField> advectiveFvPatchField<Type>::advectionSpeed() const
00162 {
00163 const surfaceScalarField& phi =
00164 this->db().objectRegistry::lookupObject<surfaceScalarField>(phiName_);
00165
00166 fvsPatchField<scalar> phip = this->patch().lookupPatchField
00167 (
00168 phiName_,
00169 reinterpret_cast<const surfaceScalarField*>(0),
00170 reinterpret_cast<const scalar*>(0)
00171 );
00172
00173 if (phi.dimensions() == dimDensity*dimVelocity*dimArea)
00174 {
00175 const fvPatchScalarField& rhop = this->patch().lookupPatchField
00176 (
00177 rhoName_,
00178 reinterpret_cast<const volScalarField*>(0),
00179 reinterpret_cast<const scalar*>(0)
00180 );
00181
00182 return phip/(rhop*this->patch().magSf());
00183 }
00184 else
00185 {
00186 return phip/this->patch().magSf();
00187 }
00188 }
00189
00190
00191 template<class Type>
00192 void advectiveFvPatchField<Type>::updateCoeffs()
00193 {
00194 if (this->updated())
00195 {
00196 return;
00197 }
00198
00199 word ddtScheme
00200 (
00201 this->dimensionedInternalField().mesh()
00202 .ddtScheme(this->dimensionedInternalField().name())
00203 );
00204 scalar deltaT = this->db().time().deltaT().value();
00205
00206 const GeometricField<Type, fvPatchField, volMesh>& field =
00207 this->db().objectRegistry::
lookupObject<GeometricField<Type, fvPatchField, volMesh> >
00208 (
00209 this->dimensionedInternalField().name()
00210 );
00211
00212
00213
00214 scalarField w = Foam::max(advectionSpeed(), scalar(0));
00215
00216
00217 scalarField alpha = w*deltaT*this->patch().deltaCoeffs();
00218
00219 label patchi = this->patch().index();
00220
00221
00222
00223 if (lInf_ > SMALL)
00224 {
00225
00226 scalarField k = w*deltaT/lInf_;
00227
00228 if
00229 (
00230 ddtScheme == fv::EulerDdtScheme<scalar>::typeName
00231 || ddtScheme == fv::CrankNicholsonDdtScheme<scalar>::typeName
00232 )
00233 {
00234 this->refValue() =
00235 (
00236 field.oldTime().boundaryField()[patchi] + k*fieldInf_
00237 )/(1.0 + k);
00238
00239 this->valueFraction() = (1.0 + k)/(1.0 + alpha + k);
00240 }
00241 else if (ddtScheme == fv::backwardDdtScheme<scalar>::typeName)
00242 {
00243 this->refValue() =
00244 (
00245 2.0*field.oldTime().boundaryField()[patchi]
00246 - 0.5*field.oldTime().oldTime().boundaryField()[patchi]
00247 + k*fieldInf_
00248 )/(1.5 + k);
00249
00250 this->valueFraction() = (1.5 + k)/(1.5 + alpha + k);
00251 }
00252 else
00253 {
00254 FatalErrorIn
00255 (
00256 "advectiveFvPatchField<Type>::updateCoeffs()"
00257 ) << " Unsupported temporal differencing scheme : "
00258 << ddtScheme
00259 << "\n on patch " << this->patch().name()
00260 << " of field " << this->dimensionedInternalField().name()
00261 << " in file " << this->dimensionedInternalField().objectPath()
00262 << exit(FatalError);
00263 }
00264 }
00265 else
00266 {
00267 if
00268 (
00269 ddtScheme == fv::EulerDdtScheme<scalar>::typeName
00270 || ddtScheme == fv::CrankNicholsonDdtScheme<scalar>::typeName
00271 )
00272 {
00273 this->refValue() = field.oldTime().boundaryField()[patchi];
00274
00275 this->valueFraction() = 1.0/(1.0 + alpha);
00276 }
00277 else if (ddtScheme == fv::backwardDdtScheme<scalar>::typeName)
00278 {
00279 this->refValue() =
00280 (
00281 2.0*field.oldTime().boundaryField()[patchi]
00282 - 0.5*field.oldTime().oldTime().boundaryField()[patchi]
00283 )/1.5;
00284
00285 this->valueFraction() = 1.5/(1.5 + alpha);
00286 }
00287 else
00288 {
00289 FatalErrorIn
00290 (
00291 "advectiveFvPatchField<Type>::updateCoeffs()"
00292 ) << " Unsupported temporal differencing scheme : "
00293 << ddtScheme
00294 << "\n on patch " << this->patch().name()
00295 << " of field " << this->dimensionedInternalField().name()
00296 << " in file " << this->dimensionedInternalField().objectPath()
00297 << exit(FatalError);
00298 }
00299 }
00300
00301 mixedFvPatchField<Type>::updateCoeffs();
00302 }
00303
00304
00305 template<class Type>
00306 void advectiveFvPatchField<Type>::write(Ostream& os) const
00307 {
00308 fvPatchField<Type>::write(os);
00309
00310 if (phiName_ != "phi")
00311 {
00312 os.writeKeyword("phi") << phiName_ << token::END_STATEMENT << nl;
00313 }
00314 if (rhoName_ != "rho")
00315 {
00316 os.writeKeyword("rho") << rhoName_ << token::END_STATEMENT << nl;
00317 }
00318
00319 if (lInf_ > SMALL)
00320 {
00321 os.writeKeyword("fieldInf") << fieldInf_
00322 << token::END_STATEMENT << nl;
00323 os.writeKeyword("lInf") << lInf_
00324 << token::END_STATEMENT << nl;
00325 }
00326
00327 this->writeEntry("value", os);
00328 }
00329
00330
00331
00332
00333 }
00334
00335
00336