FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

CrankNicholsonDdtScheme.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "CrankNicholsonDdtScheme.H"
00027 #include <finiteVolume/surfaceInterpolate.H>
00028 #include <finiteVolume/fvcDiv.H>
00029 #include <finiteVolume/fvMatrices.H>
00030 
00031 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00032 
00033 namespace Foam
00034 {
00035 
00036 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00037 
00038 namespace fv
00039 {
00040 
00041 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00042 
00043 template<class Type>
00044 template<class GeoField>
00045 CrankNicholsonDdtScheme<Type>::DDt0Field<GeoField>::DDt0Field
00046 (
00047     const IOobject& io,
00048     const fvMesh& mesh
00049 )
00050 :
00051     GeoField(io, mesh),
00052     startTimeIndex_(-2) // This field is for a restart and thus correct so set
00053                         // the start time-index to corespond to a previous run
00054 {
00055     // Set the time-index to the beginning of the run to ensure the field
00056     // is updated during the first time-step
00057     this->timeIndex() = mesh.time().startTimeIndex();
00058 }
00059 
00060 
00061 template<class Type>
00062 template<class GeoField>
00063 CrankNicholsonDdtScheme<Type>::DDt0Field<GeoField>::DDt0Field
00064 (
00065     const IOobject& io,
00066     const fvMesh& mesh,
00067     const dimensioned<typename GeoField::value_type>& dimType
00068 )
00069 :
00070     GeoField(io, mesh, dimType),
00071     startTimeIndex_(mesh.time().timeIndex())
00072 {}
00073 
00074 
00075 template<class Type>
00076 template<class GeoField>
00077 label CrankNicholsonDdtScheme<Type>::DDt0Field<GeoField>::
00078 startTimeIndex() const
00079 {
00080     return startTimeIndex_;
00081 }
00082 
00083 
00084 template<class Type>
00085 template<class GeoField>
00086 GeoField& CrankNicholsonDdtScheme<Type>::DDt0Field<GeoField>::
00087 operator()()
00088 {
00089     return *this;
00090 }
00091 
00092 
00093 template<class Type>
00094 template<class GeoField>
00095 void CrankNicholsonDdtScheme<Type>::DDt0Field<GeoField>::
00096 operator=(const GeoField& gf)
00097 {
00098     GeoField::operator=(gf);
00099 }
00100 
00101 
00102 template<class Type>
00103 template<class GeoField>
00104 CrankNicholsonDdtScheme<Type>::DDt0Field<GeoField>&
00105 CrankNicholsonDdtScheme<Type>::ddt0_
00106 (
00107     const word& name,
00108     const dimensionSet& dims
00109 )
00110 {
00111     if (!mesh().objectRegistry::foundObject<GeoField>(name))
00112     {
00113         const Time& runTime = mesh().time();
00114         word startTimeName = runTime.timeName(runTime.startTime().value());
00115 
00116         if
00117         (
00118             (
00119                 runTime.timeIndex() == runTime.startTimeIndex()
00120              || runTime.timeIndex() == runTime.startTimeIndex() + 1
00121             )
00122          && IOobject
00123             (
00124                 name,
00125                 startTimeName,
00126                 mesh()
00127             ).headerOk()
00128         )
00129         {
00130             regIOobject::store
00131             (
00132                 new DDt0Field<GeoField>
00133                 (
00134                     IOobject
00135                     (
00136                         name,
00137                         startTimeName,
00138                         mesh(),
00139                         IOobject::MUST_READ,
00140                         IOobject::AUTO_WRITE
00141                     ),
00142                     mesh()
00143                 )
00144             );
00145         }
00146         else
00147         {
00148             regIOobject::store
00149             (
00150                 new DDt0Field<GeoField>
00151                 (
00152                     IOobject
00153                     (
00154                         name,
00155                         mesh().time().timeName(),
00156                         mesh(),
00157                         IOobject::NO_READ,
00158                         IOobject::AUTO_WRITE
00159                     ),
00160                     mesh(),
00161                     dimensioned<typename GeoField::value_type>
00162                     (
00163                         "0",
00164                         dims/dimTime,
00165                         pTraits<typename GeoField::value_type>::zero
00166                     )
00167                 )
00168             );
00169         }
00170     }
00171 
00172     DDt0Field<GeoField>& ddt0 = static_cast<DDt0Field<GeoField>&>
00173     (
00174         const_cast<GeoField&>
00175         (
00176             mesh().objectRegistry::lookupObject<GeoField>(name)
00177         )
00178     );
00179 
00180     return ddt0;
00181 }
00182 
00183 
00184 template<class Type>
00185 template<class GeoField>
00186 bool CrankNicholsonDdtScheme<Type>::evaluate
00187 (
00188     const DDt0Field<GeoField>& ddt0
00189 ) const
00190 {
00191     return ddt0.timeIndex() != mesh().time().timeIndex();
00192 }
00193 
00194 template<class Type>
00195 template<class GeoField>
00196 scalar CrankNicholsonDdtScheme<Type>::coef_
00197 (
00198     const DDt0Field<GeoField>& ddt0
00199 ) const
00200 {
00201     if (mesh().time().timeIndex() - ddt0.startTimeIndex() > 0)
00202     {
00203         return 1.0 + ocCoeff_;
00204     }
00205     else
00206     {
00207         return 1.0;
00208     }
00209 }
00210 
00211 
00212 template<class Type>
00213 template<class GeoField>
00214 scalar CrankNicholsonDdtScheme<Type>::coef0_
00215 (
00216     const DDt0Field<GeoField>& ddt0
00217 ) const
00218 {
00219     if (mesh().time().timeIndex() - ddt0.startTimeIndex() > 1)
00220     {
00221         return 1.0 + ocCoeff_;
00222     }
00223     else
00224     {
00225         return 1.0;
00226     }
00227 }
00228 
00229 
00230 template<class Type>
00231 template<class GeoField>
00232 dimensionedScalar CrankNicholsonDdtScheme<Type>::rDtCoef_
00233 (
00234     const DDt0Field<GeoField>& ddt0
00235 ) const
00236 {
00237     return coef_(ddt0)/mesh().time().deltaT();
00238 }
00239 
00240 
00241 template<class Type>
00242 template<class GeoField>
00243 dimensionedScalar CrankNicholsonDdtScheme<Type>::rDtCoef0_
00244 (
00245     const DDt0Field<GeoField>& ddt0
00246 ) const
00247 {
00248     return coef0_(ddt0)/mesh().time().deltaT0();
00249 }
00250 
00251 
00252 template<class Type>
00253 template<class GeoField>
00254 tmp<GeoField> CrankNicholsonDdtScheme<Type>::offCentre_
00255 (
00256     const GeoField& ddt0
00257 ) const
00258 {
00259     if (ocCoeff_ < 1.0)
00260     {
00261         return ocCoeff_*ddt0;
00262     }
00263     else
00264     {
00265         return ddt0;
00266     }
00267 }
00268 
00269 
00270 template<class Type>
00271 const FieldField<fvPatchField, Type>& ff
00272 (
00273     const FieldField<fvPatchField, Type>& bf
00274 )
00275 {
00276     return bf;
00277 }
00278 
00279 
00280 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00281 
00282 template<class Type>
00283 tmp<GeometricField<Type, fvPatchField, volMesh> >
00284 CrankNicholsonDdtScheme<Type>::fvcDdt
00285 (
00286     const dimensioned<Type>& dt
00287 )
00288 {
00289     DDt0Field<GeometricField<Type, fvPatchField, volMesh> >& ddt0 =
00290         ddt0_<GeometricField<Type, fvPatchField, volMesh> >
00291         (
00292             "ddt0(" + dt.name() + ')',
00293             dt.dimensions()
00294         );
00295 
00296     IOobject ddtIOobject
00297     (
00298         "ddt(" + dt.name() + ')',
00299         mesh().time().timeName(),
00300         mesh()
00301     );
00302 
00303     tmp<GeometricField<Type, fvPatchField, volMesh> > tdtdt
00304     (
00305         new GeometricField<Type, fvPatchField, volMesh>
00306         (
00307             ddtIOobject,
00308             mesh(),
00309             dimensioned<Type>
00310             (
00311                 "0",
00312                 dt.dimensions()/dimTime,
00313                 pTraits<Type>::zero
00314             )
00315         )
00316     );
00317 
00318     dimensionedScalar rDtCoef = rDtCoef_(ddt0);
00319 
00320     if (mesh().moving())
00321     {
00322         if (evaluate(ddt0))
00323         {
00324             dimensionedScalar rDtCoef0 = rDtCoef0_(ddt0);
00325 
00326             ddt0.dimensionedInternalField() =
00327             (
00328                 (rDtCoef0*dt)*(mesh().V0() - mesh().V00())
00329               - mesh().V00()*offCentre_(ddt0.dimensionedInternalField())
00330             )/mesh().V0();
00331         }
00332 
00333         tdtdt().dimensionedInternalField() =
00334         (
00335             (rDtCoef*dt)*(mesh().V() - mesh().V0())
00336           - mesh().V0()*offCentre_(ddt0.dimensionedInternalField())
00337         )/mesh().V();
00338     }
00339 
00340     return tdtdt;
00341 }
00342 
00343 
00344 template<class Type>
00345 tmp<GeometricField<Type, fvPatchField, volMesh> >
00346 CrankNicholsonDdtScheme<Type>::fvcDdt
00347 (
00348     const GeometricField<Type, fvPatchField, volMesh>& vf
00349 )
00350 {
00351     DDt0Field<GeometricField<Type, fvPatchField, volMesh> >& ddt0 =
00352         ddt0_<GeometricField<Type, fvPatchField, volMesh> >
00353         (
00354             "ddt0(" + vf.name() + ')',
00355             vf.dimensions()
00356         );
00357 
00358     IOobject ddtIOobject
00359     (
00360         "ddt(" + vf.name() + ')',
00361         mesh().time().timeName(),
00362         mesh()
00363     );
00364 
00365     dimensionedScalar rDtCoef = rDtCoef_(ddt0);
00366 
00367     if (mesh().moving())
00368     {
00369         if (evaluate(ddt0))
00370         {
00371             scalar rDtCoef0 = rDtCoef0_(ddt0).value();
00372 
00373             ddt0.internalField() =
00374             (
00375                 rDtCoef0*
00376                 (
00377                     mesh().V0()*vf.oldTime().internalField()
00378                   - mesh().V00()*vf.oldTime().oldTime().internalField()
00379                 ) - mesh().V00()*offCentre_(ddt0.internalField())
00380             )/mesh().V0();
00381 
00382             ddt0.boundaryField() =
00383             (
00384                 rDtCoef0*
00385                 (
00386                     vf.oldTime().boundaryField()
00387                   - vf.oldTime().oldTime().boundaryField()
00388                 ) - offCentre_(ff(ddt0.boundaryField()))
00389             );
00390         }
00391 
00392         return tmp<GeometricField<Type, fvPatchField, volMesh> >
00393         (
00394             new GeometricField<Type, fvPatchField, volMesh>
00395             (
00396                 ddtIOobject,
00397                 mesh(),
00398                 rDtCoef.dimensions()*vf.dimensions(),
00399                 (
00400                     rDtCoef.value()*
00401                     (
00402                         mesh().V()*vf.internalField()
00403                       - mesh().V0()*vf.oldTime().internalField()
00404                     ) - mesh().V0()*offCentre_(ddt0.internalField())
00405                 )/mesh().V(),
00406                 rDtCoef.value()*
00407                 (
00408                     vf.boundaryField() - vf.oldTime().boundaryField()
00409                 ) - offCentre_(ff(ddt0.boundaryField()))
00410             )
00411         );
00412     }
00413     else
00414     {
00415         if (evaluate(ddt0))
00416         {
00417             ddt0 = rDtCoef0_(ddt0)*(vf.oldTime() - vf.oldTime().oldTime())
00418                  - offCentre_(ddt0());
00419         }
00420 
00421         return tmp<GeometricField<Type, fvPatchField, volMesh> >
00422         (
00423             new GeometricField<Type, fvPatchField, volMesh>
00424             (
00425                 ddtIOobject,
00426                 rDtCoef*(vf - vf.oldTime()) - offCentre_(ddt0())
00427             )
00428         );
00429     }
00430 }
00431 
00432 
00433 template<class Type>
00434 tmp<GeometricField<Type, fvPatchField, volMesh> >
00435 CrankNicholsonDdtScheme<Type>::fvcDdt
00436 (
00437     const dimensionedScalar& rho,
00438     const GeometricField<Type, fvPatchField, volMesh>& vf
00439 )
00440 {
00441     DDt0Field<GeometricField<Type, fvPatchField, volMesh> >& ddt0 =
00442         ddt0_<GeometricField<Type, fvPatchField, volMesh> >
00443         (
00444             "ddt0(" + rho.name() + ',' + vf.name() + ')',
00445             rho.dimensions()*vf.dimensions()
00446         );
00447 
00448     IOobject ddtIOobject
00449     (
00450         "ddt(" + rho.name() + ',' + vf.name() + ')',
00451         mesh().time().timeName(),
00452         mesh()
00453     );
00454 
00455     dimensionedScalar rDtCoef = rDtCoef_(ddt0);
00456 
00457     if (mesh().moving())
00458     {
00459         if (evaluate(ddt0))
00460         {
00461             scalar rDtCoef0 = rDtCoef0_(ddt0).value();
00462 
00463             ddt0.internalField() =
00464             (
00465                 rDtCoef0*rho.value()*
00466                 (
00467                     mesh().V0()*vf.oldTime().internalField()
00468                   - mesh().V00()*vf.oldTime().oldTime().internalField()
00469                 ) - mesh().V00()*offCentre_(ddt0.internalField())
00470             )/mesh().V0();
00471 
00472             ddt0.boundaryField() =
00473             (
00474                 rDtCoef0*rho.value()*
00475                 (
00476                     vf.oldTime().boundaryField()
00477                   - vf.oldTime().oldTime().boundaryField()
00478                 ) - offCentre_(ff(ddt0.boundaryField()))
00479             );
00480         }
00481 
00482         return tmp<GeometricField<Type, fvPatchField, volMesh> >
00483         (
00484             new GeometricField<Type, fvPatchField, volMesh>
00485             (
00486                 ddtIOobject,
00487                 mesh(),
00488                 rDtCoef.dimensions()*rho.dimensions()*vf.dimensions(),
00489                 (
00490                     rDtCoef.value()*rho.value()*
00491                     (
00492                         mesh().V()*vf.internalField()
00493                       - mesh().V0()*vf.oldTime().internalField()
00494                     ) - mesh().V0()*offCentre_(ddt0.internalField())
00495                 )/mesh().V(),
00496                 rDtCoef.value()*rho.value()*
00497                 (
00498                     vf.boundaryField() - vf.oldTime().boundaryField()
00499                 ) - offCentre_(ff(ddt0.boundaryField()))
00500             )
00501         );
00502     }
00503     else
00504     {
00505         if (evaluate(ddt0))
00506         {
00507             ddt0 = rDtCoef0_(ddt0)*rho*(vf.oldTime() - vf.oldTime().oldTime())
00508                  - offCentre_(ddt0());
00509         }
00510 
00511         return tmp<GeometricField<Type, fvPatchField, volMesh> >
00512         (
00513             new GeometricField<Type, fvPatchField, volMesh>
00514             (
00515                 ddtIOobject,
00516                 rDtCoef*rho*(vf - vf.oldTime()) - offCentre_(ddt0())
00517             )
00518         );
00519     }
00520 }
00521 
00522 
00523 template<class Type>
00524 tmp<GeometricField<Type, fvPatchField, volMesh> >
00525 CrankNicholsonDdtScheme<Type>::fvcDdt
00526 (
00527     const volScalarField& rho,
00528     const GeometricField<Type, fvPatchField, volMesh>& vf
00529 )
00530 {
00531     DDt0Field<GeometricField<Type, fvPatchField, volMesh> >& ddt0 =
00532         ddt0_<GeometricField<Type, fvPatchField, volMesh> >
00533         (
00534             "ddt0(" + rho.name() + ',' + vf.name() + ')',
00535             rho.dimensions()*vf.dimensions()
00536         );
00537 
00538     IOobject ddtIOobject
00539     (
00540         "ddt(" + rho.name() + ',' + vf.name() + ')',
00541         mesh().time().timeName(),
00542         mesh()
00543     );
00544 
00545     dimensionedScalar rDtCoef = rDtCoef_(ddt0);
00546 
00547     if (mesh().moving())
00548     {
00549         if (evaluate(ddt0))
00550         {
00551             scalar rDtCoef0 = rDtCoef0_(ddt0).value();
00552 
00553             ddt0.internalField() =
00554             (
00555                 rDtCoef0*
00556                 (
00557                     mesh().V0()*rho.oldTime().internalField()
00558                    *vf.oldTime().internalField()
00559                   - mesh().V00()*rho.oldTime().oldTime().internalField()
00560                    *vf.oldTime().oldTime().internalField()
00561                 ) - mesh().V00()*offCentre_(ddt0.internalField())
00562             )/mesh().V0();
00563 
00564             ddt0.boundaryField() =
00565             (
00566                 rDtCoef0*
00567                 (
00568                     rho.oldTime().boundaryField()
00569                    *vf.oldTime().boundaryField()
00570                   - rho.oldTime().oldTime().boundaryField()
00571                    *vf.oldTime().oldTime().boundaryField()
00572                 ) - offCentre_(ff(ddt0.boundaryField()))
00573             );
00574         }
00575 
00576         return tmp<GeometricField<Type, fvPatchField, volMesh> >
00577         (
00578             new GeometricField<Type, fvPatchField, volMesh>
00579             (
00580                 ddtIOobject,
00581                 mesh(),
00582                 rDtCoef.dimensions()*rho.dimensions()*vf.dimensions(),
00583                 (
00584                     rDtCoef.value()*
00585                     (
00586                         mesh().V()*rho.internalField()*vf.internalField()
00587                       - mesh().V0()*rho.oldTime().internalField()
00588                        *vf.oldTime().internalField()
00589                     ) - mesh().V00()*offCentre_(ddt0.internalField())
00590                 )/mesh().V(),
00591                 rDtCoef.value()*
00592                 (
00593                     rho.boundaryField()*vf.boundaryField()
00594                   - rho.oldTime().boundaryField()*vf.oldTime().boundaryField()
00595                 ) - offCentre_(ff(ddt0.boundaryField()))
00596             )
00597         );
00598     }
00599     else
00600     {
00601         if (evaluate(ddt0))
00602         {
00603             ddt0 = rDtCoef0_(ddt0)*
00604             (
00605                 rho.oldTime()*vf.oldTime()
00606               - rho.oldTime().oldTime()*vf.oldTime().oldTime()
00607             ) - offCentre_(ddt0());
00608         }
00609 
00610         return tmp<GeometricField<Type, fvPatchField, volMesh> >
00611         (
00612             new GeometricField<Type, fvPatchField, volMesh>
00613             (
00614                 ddtIOobject,
00615                 rDtCoef*(rho*vf - rho.oldTime()*vf.oldTime())
00616               - offCentre_(ddt0())
00617             )
00618         );
00619     }
00620 }
00621 
00622 
00623 template<class Type>
00624 tmp<fvMatrix<Type> >
00625 CrankNicholsonDdtScheme<Type>::fvmDdt
00626 (
00627     GeometricField<Type, fvPatchField, volMesh>& vf
00628 )
00629 {
00630     DDt0Field<GeometricField<Type, fvPatchField, volMesh> >& ddt0 =
00631         ddt0_<GeometricField<Type, fvPatchField, volMesh> >
00632         (
00633             "ddt0(" + vf.name() + ')',
00634             vf.dimensions()
00635         );
00636 
00637     tmp<fvMatrix<Type> > tfvm
00638     (
00639         new fvMatrix<Type>
00640         (
00641             vf,
00642             vf.dimensions()*dimVol/dimTime
00643         )
00644     );
00645 
00646     fvMatrix<Type>& fvm = tfvm();
00647 
00648     scalar rDtCoef = rDtCoef_(ddt0).value();
00649 
00650     fvm.diag() = rDtCoef*mesh().V();
00651 
00652     vf.oldTime().oldTime();
00653 
00654     if (mesh().moving())
00655     {
00656         if (evaluate(ddt0))
00657         {
00658             scalar rDtCoef0 = rDtCoef0_(ddt0).value();
00659 
00660             ddt0.internalField() =
00661             (
00662                 rDtCoef0*
00663                 (
00664                     mesh().V0()*vf.oldTime().internalField()
00665                   - mesh().V00()*vf.oldTime().oldTime().internalField()
00666                 )
00667               - mesh().V00()*offCentre_(ddt0.internalField())
00668             )/mesh().V0();
00669 
00670             ddt0.boundaryField() =
00671             (
00672                 rDtCoef0*
00673                 (
00674                     vf.oldTime().boundaryField()
00675                   - vf.oldTime().oldTime().boundaryField()
00676                 )
00677               - offCentre_(ff(ddt0.boundaryField()))
00678             );
00679         }
00680 
00681         fvm.source() =
00682         (
00683             rDtCoef*vf.oldTime().internalField()
00684           + offCentre_(ddt0.internalField())
00685         )*mesh().V0();
00686     }
00687     else
00688     {
00689         if (evaluate(ddt0))
00690         {
00691             ddt0 = rDtCoef0_(ddt0)*(vf.oldTime() - vf.oldTime().oldTime())
00692                  - offCentre_(ddt0());
00693         }
00694 
00695         fvm.source() =
00696         (
00697             rDtCoef*vf.oldTime().internalField()
00698           + offCentre_(ddt0.internalField())
00699         )*mesh().V();
00700     }
00701 
00702     return tfvm;
00703 }
00704 
00705 
00706 template<class Type>
00707 tmp<fvMatrix<Type> >
00708 CrankNicholsonDdtScheme<Type>::fvmDdt
00709 (
00710     const dimensionedScalar& rho,
00711     GeometricField<Type, fvPatchField, volMesh>& vf
00712 )
00713 {
00714     DDt0Field<GeometricField<Type, fvPatchField, volMesh> >& ddt0 =
00715         ddt0_<GeometricField<Type, fvPatchField, volMesh> >
00716         (
00717             "ddt0(" + rho.name() + ',' + vf.name() + ')',
00718             rho.dimensions()*vf.dimensions()
00719         );
00720 
00721     tmp<fvMatrix<Type> > tfvm
00722     (
00723         new fvMatrix<Type>
00724         (
00725             vf,
00726             rho.dimensions()*vf.dimensions()*dimVol/dimTime
00727         )
00728     );
00729     fvMatrix<Type>& fvm = tfvm();
00730 
00731     scalar rDtCoef = rDtCoef_(ddt0).value();
00732     fvm.diag() = rDtCoef*rho.value()*mesh().V();
00733 
00734     vf.oldTime().oldTime();
00735 
00736     if (mesh().moving())
00737     {
00738         if (evaluate(ddt0))
00739         {
00740             scalar rDtCoef0 = rDtCoef0_(ddt0).value();
00741 
00742             ddt0.internalField() =
00743             (
00744                 rDtCoef0*rho.value()*
00745                 (
00746                     mesh().V0()*vf.oldTime().internalField()
00747                   - mesh().V00()*vf.oldTime().oldTime().internalField()
00748                 )
00749               - mesh().V00()*offCentre_(ddt0.internalField())
00750             )/mesh().V0();
00751 
00752             ddt0.boundaryField() =
00753             (
00754                 rDtCoef0*rho.value()*
00755                 (
00756                     vf.oldTime().boundaryField()
00757                   - vf.oldTime().oldTime().boundaryField()
00758                 )
00759               - offCentre_(ff(ddt0.boundaryField()))
00760             );
00761         }
00762 
00763         fvm.source() =
00764         (
00765             rDtCoef*rho.value()*vf.oldTime().internalField()
00766           + offCentre_(ddt0.internalField())
00767         )*mesh().V0();
00768     }
00769     else
00770     {
00771         if (evaluate(ddt0))
00772         {
00773             ddt0 = rDtCoef0_(ddt0)*rho*(vf.oldTime() - vf.oldTime().oldTime())
00774                  - offCentre_(ddt0());
00775         }
00776 
00777         fvm.source() =
00778         (
00779             rDtCoef*rho.value()*vf.oldTime().internalField()
00780           + offCentre_(ddt0.internalField())
00781         )*mesh().V();
00782     }
00783 
00784     return tfvm;
00785 }
00786 
00787 
00788 template<class Type>
00789 tmp<fvMatrix<Type> >
00790 CrankNicholsonDdtScheme<Type>::fvmDdt
00791 (
00792     const volScalarField& rho,
00793     GeometricField<Type, fvPatchField, volMesh>& vf
00794 )
00795 {
00796     DDt0Field<GeometricField<Type, fvPatchField, volMesh> >& ddt0 =
00797         ddt0_<GeometricField<Type, fvPatchField, volMesh> >
00798         (
00799             "ddt0(" + rho.name() + ',' + vf.name() + ')',
00800             rho.dimensions()*vf.dimensions()
00801         );
00802 
00803     tmp<fvMatrix<Type> > tfvm
00804     (
00805         new fvMatrix<Type>
00806         (
00807             vf,
00808             rho.dimensions()*vf.dimensions()*dimVol/dimTime
00809         )
00810     );
00811     fvMatrix<Type>& fvm = tfvm();
00812 
00813     scalar rDtCoef = rDtCoef_(ddt0).value();
00814     fvm.diag() = rDtCoef*rho.internalField()*mesh().V();
00815 
00816     vf.oldTime().oldTime();
00817     rho.oldTime().oldTime();
00818 
00819     if (mesh().moving())
00820     {
00821         if (evaluate(ddt0))
00822         {
00823             scalar rDtCoef0 = rDtCoef0_(ddt0).value();
00824 
00825             ddt0.internalField() =
00826             (
00827                 rDtCoef0*
00828                 (
00829                     mesh().V0()*rho.oldTime().internalField()
00830                    *vf.oldTime().internalField()
00831                   - mesh().V00()*rho.oldTime().oldTime().internalField()
00832                    *vf.oldTime().oldTime().internalField()
00833                 )
00834               - mesh().V00()*offCentre_(ddt0.internalField())
00835             )/mesh().V0();
00836 
00837             ddt0.boundaryField() =
00838             (
00839                 rDtCoef0*
00840                 (
00841                     rho.oldTime().boundaryField()
00842                    *vf.oldTime().boundaryField()
00843                   - rho.oldTime().oldTime().boundaryField()
00844                    *vf.oldTime().oldTime().boundaryField()
00845                 )
00846               - offCentre_(ff(ddt0.boundaryField()))
00847             );
00848         }
00849 
00850         fvm.source() =
00851         (
00852             rDtCoef*rho.internalField()*vf.oldTime().internalField()
00853           + offCentre_(ddt0.internalField())
00854         )*mesh().V0();
00855     }
00856     else
00857     {
00858         if (evaluate(ddt0))
00859         {
00860             ddt0 = rDtCoef0_(ddt0)*
00861             (
00862                 rho.oldTime()*vf.oldTime()
00863               - rho.oldTime().oldTime()*vf.oldTime().oldTime()
00864             ) - offCentre_(ddt0());
00865         }
00866 
00867         fvm.source() =
00868         (
00869             rDtCoef*rho.oldTime().internalField()*vf.oldTime().internalField()
00870           + offCentre_(ddt0.internalField())
00871         )*mesh().V();
00872     }
00873 
00874     return tfvm;
00875 }
00876 
00877 
00878 
00879 template<class Type>
00880 tmp<typename CrankNicholsonDdtScheme<Type>::fluxFieldType>
00881 CrankNicholsonDdtScheme<Type>::fvcDdtPhiCorr
00882 (
00883     const volScalarField& rA,
00884     const GeometricField<Type, fvPatchField, volMesh>& U,
00885     const fluxFieldType& phi
00886 )
00887 {
00888     DDt0Field<GeometricField<Type, fvPatchField, volMesh> >& dUdt0 =
00889         ddt0_<GeometricField<Type, fvPatchField, volMesh> >
00890         (
00891             "ddt0(" + U.name() + ')',
00892             U.dimensions()
00893         );
00894 
00895     DDt0Field<fluxFieldType>& dphidt0 =
00896         ddt0_<fluxFieldType>
00897         (
00898             "ddt0(" + phi.name() + ')',
00899             phi.dimensions()
00900         );
00901 
00902     IOobject ddtIOobject
00903     (
00904         "ddtPhiCorr(" + rA.name() + ',' + U.name() + ',' + phi.name() + ')',
00905         mesh().time().timeName(),
00906         mesh()
00907     );
00908 
00909     dimensionedScalar rDtCoef = rDtCoef_(dUdt0);
00910 
00911     if (mesh().moving())
00912     {
00913         return tmp<fluxFieldType>
00914         (
00915             new fluxFieldType
00916             (
00917                 ddtIOobject,
00918                 mesh(),
00919                 dimensioned<typename flux<Type>::type>
00920                 (
00921                     "0",
00922                     rDtCoef.dimensions()*rA.dimensions()*phi.dimensions(),
00923                     pTraits<typename flux<Type>::type>::zero
00924                 )
00925             )
00926         );
00927     }
00928     else
00929     {
00930         if (evaluate(dUdt0))
00931         {
00932             dUdt0 =
00933                 rDtCoef0_(dUdt0)*(U.oldTime() - U.oldTime().oldTime())
00934               - offCentre_(dUdt0());
00935         }
00936 
00937         if (evaluate(dphidt0))
00938         {
00939             dphidt0 =
00940                 rDtCoef0_(dphidt0)*(phi.oldTime() - phi.oldTime().oldTime())
00941               - offCentre_(dphidt0());
00942         }
00943 
00944         return tmp<fluxFieldType>
00945         (
00946             new fluxFieldType
00947             (
00948                 ddtIOobject,
00949                 this->fvcDdtPhiCoeff(U.oldTime(), phi.oldTime())
00950                *fvc::interpolate(rA)
00951                *(
00952                     (rDtCoef*phi.oldTime() + offCentre_(dphidt0()))
00953                   - (
00954                         fvc::interpolate
00955                         (
00956                             (rDtCoef*U.oldTime() + offCentre_(dUdt0()))
00957                         ) & mesh().Sf()
00958                     )
00959                 )
00960             )
00961         );
00962     }
00963 }
00964 
00965 
00966 template<class Type>
00967 tmp<typename CrankNicholsonDdtScheme<Type>::fluxFieldType>
00968 CrankNicholsonDdtScheme<Type>::fvcDdtPhiCorr
00969 (
00970     const volScalarField& rA,
00971     const volScalarField& rho,
00972     const GeometricField<Type, fvPatchField, volMesh>& U,
00973     const fluxFieldType& phi
00974 )
00975 {
00976     DDt0Field<GeometricField<Type, fvPatchField, volMesh> >& dUdt0 =
00977         ddt0_<GeometricField<Type, fvPatchField, volMesh> >
00978         (
00979             "ddt0(" + U.name() + ')',
00980             U.dimensions()
00981         );
00982 
00983     DDt0Field<fluxFieldType>& dphidt0 =
00984         ddt0_<fluxFieldType>
00985         (
00986             "ddt0(" + phi.name() + ')',
00987             U.dimensions()*dimArea
00988         );
00989 
00990     IOobject ddtIOobject
00991     (
00992         "ddtPhiCorr("
00993       + rA.name() + ',' + rho.name() + ',' + U.name() + ',' + phi.name() + ')',
00994         mesh().time().timeName(),
00995         mesh()
00996     );
00997 
00998     dimensionedScalar rDtCoef = rDtCoef_(dUdt0);
00999 
01000     if (mesh().moving())
01001     {
01002         return tmp<fluxFieldType>
01003         (
01004             new fluxFieldType
01005             (
01006                 ddtIOobject,
01007                 mesh(),
01008                 dimensioned<typename flux<Type>::type>
01009                 (
01010                     "0",
01011                     rA.dimensions()*rho.dimensions()*phi.dimensions()/dimTime,
01012                     pTraits<typename flux<Type>::type>::zero
01013                 )
01014             )
01015         );
01016     }
01017     else
01018     {
01019         if
01020         (
01021             U.dimensions() == dimVelocity
01022          && phi.dimensions() == dimVelocity*dimArea
01023         )
01024         {
01025             if (evaluate(dUdt0))
01026             {
01027                 dUdt0 = rDtCoef0_(dUdt0)*
01028                 (
01029                     U.oldTime() - U.oldTime().oldTime()
01030                 ) - offCentre_(dUdt0());
01031             }
01032 
01033             if (evaluate(dphidt0))
01034             {
01035                 dphidt0 = rDtCoef0_(dphidt0)*
01036                 (
01037                     phi.oldTime()
01038                   - fvc::interpolate(rho.oldTime().oldTime()/rho.oldTime())
01039                    *phi.oldTime().oldTime()
01040                 ) - offCentre_(dphidt0());
01041             }
01042 
01043             return tmp<fluxFieldType>
01044             (
01045                 new fluxFieldType
01046                 (
01047                     ddtIOobject,
01048                     this->fvcDdtPhiCoeff(U.oldTime(), phi.oldTime())*
01049                     (
01050                         fvc::interpolate(rA*rho.oldTime())
01051                        *(rDtCoef*phi.oldTime() + offCentre_(dphidt0()))
01052                       - (
01053                             fvc::interpolate
01054                             (
01055                                 rA*rho.oldTime()
01056                                *(rDtCoef*U.oldTime() + offCentre_(dUdt0()))
01057                             ) & mesh().Sf()
01058                         )
01059                     )
01060                 )
01061             );
01062         }
01063         else if
01064         (
01065             U.dimensions() == dimVelocity
01066          && phi.dimensions() == rho.dimensions()*dimVelocity*dimArea
01067         )
01068         {
01069             if (evaluate(dUdt0))
01070             {
01071                 dUdt0 = rDtCoef0_(dUdt0)*
01072                 (
01073                     U.oldTime() - U.oldTime().oldTime()
01074                 ) - offCentre_(dUdt0());
01075             }
01076 
01077             if (evaluate(dphidt0))
01078             {
01079                 dphidt0 = rDtCoef0_(dphidt0)*
01080                 (
01081                     phi.oldTime()
01082                    /fvc::interpolate(rho.oldTime())
01083                   - phi.oldTime().oldTime()
01084                    /fvc::interpolate(rho.oldTime().oldTime())
01085                 ) - offCentre_(dphidt0());
01086             }
01087 
01088             return tmp<fluxFieldType>
01089             (
01090                 new fluxFieldType
01091                 (
01092                     ddtIOobject,
01093                     this->fvcDdtPhiCoeff
01094                     (
01095                         U.oldTime(),
01096                         phi.oldTime()/fvc::interpolate(rho.oldTime())
01097                     )
01098                    *(
01099                         fvc::interpolate(rA*rho.oldTime())
01100                        *(
01101                            rDtCoef*phi.oldTime()/fvc::interpolate(rho.oldTime())
01102                          + offCentre_(dphidt0())
01103                         )
01104                       - (
01105                             fvc::interpolate
01106                             (
01107                                 rA*rho.oldTime()
01108                                *(rDtCoef*U.oldTime() + offCentre_(dUdt0()))
01109                             ) & mesh().Sf()
01110                         )
01111                     )
01112                 )
01113             );
01114         }
01115         else if
01116         (
01117             U.dimensions() == rho.dimensions()*dimVelocity
01118          && phi.dimensions() == rho.dimensions()*dimVelocity*dimArea
01119         )
01120         {
01121             if (evaluate(dUdt0))
01122             {
01123                 dUdt0 = rDtCoef0_(dUdt0)*
01124                 (
01125                     U.oldTime() - U.oldTime().oldTime()
01126                 ) - offCentre_(dUdt0());
01127             }
01128 
01129             if (evaluate(dphidt0))
01130             {
01131                 dphidt0 = rDtCoef0_(dphidt0)*
01132                 (
01133                     phi.oldTime() - phi.oldTime().oldTime()
01134                 ) - offCentre_(dphidt0());
01135             }
01136 
01137             return tmp<fluxFieldType>
01138             (
01139                 new fluxFieldType
01140                 (
01141                     ddtIOobject,
01142                     this->fvcDdtPhiCoeff
01143                     (
01144                         rho.oldTime(),
01145                         U.oldTime(),
01146                         phi.oldTime()
01147                     )
01148                    *(
01149                         fvc::interpolate(rA)
01150                        *(rDtCoef*phi.oldTime() + offCentre_(dphidt0()))
01151                       - (
01152                             fvc::interpolate
01153                             (
01154                                 rA*(rDtCoef*U.oldTime() + offCentre_(dUdt0()))
01155                             ) & mesh().Sf()
01156                         )
01157                     )
01158                 )
01159             );
01160         }
01161         else
01162         {
01163             FatalErrorIn
01164             (
01165                 "CrankNicholsonDdtScheme<Type>::fvcDdtPhiCorr"
01166             )   << "dimensions of phi are not correct"
01167                 << abort(FatalError);
01168 
01169             return fluxFieldType::null();
01170         }
01171     }
01172 }
01173 
01174 
01175 template<class Type>
01176 tmp<surfaceScalarField> CrankNicholsonDdtScheme<Type>::meshPhi
01177 (
01178     const GeometricField<Type, fvPatchField, volMesh>& vf
01179 )
01180 {
01181     DDt0Field<surfaceScalarField>& meshPhi0 = ddt0_<surfaceScalarField>
01182     (
01183         "meshPhiCN_0",
01184         dimVolume
01185     );
01186 
01187     if (evaluate(meshPhi0))
01188     {
01189         meshPhi0 =
01190             coef0_(meshPhi0)*mesh().phi().oldTime() - offCentre_(meshPhi0());
01191     }
01192 
01193     return coef_(meshPhi0)*mesh().phi() - offCentre_(meshPhi0());
01194 }
01195 
01196 
01197 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
01198 
01199 } // End namespace fv
01200 
01201 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
01202 
01203 } // End namespace Foam
01204 
01205 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines