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

supersonicFreestreamFvPatchVectorField.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 "supersonicFreestreamFvPatchVectorField.H"
00027 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00028 #include <finiteVolume/fvPatchFieldMapper.H>
00029 #include <finiteVolume/volFields.H>
00030 
00031 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00032 
00033 namespace Foam
00034 {
00035 
00036 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00037 
00038 supersonicFreestreamFvPatchVectorField::supersonicFreestreamFvPatchVectorField
00039 (
00040     const fvPatch& p,
00041     const DimensionedField<vector, volMesh>& iF
00042 )
00043 :
00044     mixedFvPatchVectorField(p, iF),
00045     UInf_(vector::zero),
00046     pInf_(0),
00047     TInf_(0),
00048     gamma_(0)
00049 {
00050     refValue() = patchInternalField();
00051     refGrad() = vector::zero;
00052     valueFraction() = 1;
00053 }
00054 
00055 
00056 supersonicFreestreamFvPatchVectorField::supersonicFreestreamFvPatchVectorField
00057 (
00058     const supersonicFreestreamFvPatchVectorField& ptf,
00059     const fvPatch& p,
00060     const DimensionedField<vector, volMesh>& iF,
00061     const fvPatchFieldMapper& mapper
00062 )
00063 :
00064     mixedFvPatchVectorField(ptf, p, iF, mapper),
00065     UInf_(ptf.UInf_),
00066     pInf_(ptf.pInf_),
00067     TInf_(ptf.TInf_),
00068     gamma_(ptf.gamma_)
00069 {}
00070 
00071 
00072 supersonicFreestreamFvPatchVectorField::supersonicFreestreamFvPatchVectorField
00073 (
00074     const fvPatch& p,
00075     const DimensionedField<vector, volMesh>& iF,
00076     const dictionary& dict
00077 )
00078 :
00079     mixedFvPatchVectorField(p, iF),
00080     UInf_(dict.lookup("UInf")),
00081     pInf_(readScalar(dict.lookup("pInf"))),
00082     TInf_(readScalar(dict.lookup("TInf"))),
00083     gamma_(readScalar(dict.lookup("gamma")))
00084 {
00085     if (dict.found("value"))
00086     {
00087         fvPatchField<vector>::operator=
00088         (
00089             vectorField("value", dict, p.size())
00090         );
00091     }
00092     else
00093     {
00094         fvPatchField<vector>::operator=(patchInternalField());
00095     }
00096 
00097     refValue() = *this;
00098     refGrad() = vector::zero;
00099     valueFraction() = 1;
00100 
00101     if (pInf_ < SMALL)
00102     {
00103         FatalIOErrorIn
00104         (
00105             "supersonicFreestreamFvPatchVectorField::"
00106             "supersonicFreestreamFvPatchVectorField"
00107             "(const fvPatch&, const vectorField&, const dictionary&)",
00108             dict
00109         )   << "    unphysical pInf specified (pInf <= 0.0)"
00110             << "\n    on patch " << this->patch().name()
00111             << " of field " << this->dimensionedInternalField().name()
00112             << " in file " << this->dimensionedInternalField().objectPath()
00113             << exit(FatalIOError);
00114     }
00115 }
00116 
00117 
00118 supersonicFreestreamFvPatchVectorField::supersonicFreestreamFvPatchVectorField
00119 (
00120     const supersonicFreestreamFvPatchVectorField& sfspvf
00121 )
00122 :
00123     mixedFvPatchVectorField(sfspvf),
00124     UInf_(sfspvf.UInf_),
00125     pInf_(sfspvf.pInf_),
00126     TInf_(sfspvf.TInf_),
00127     gamma_(sfspvf.gamma_)
00128 {}
00129 
00130 
00131 supersonicFreestreamFvPatchVectorField::supersonicFreestreamFvPatchVectorField
00132 (
00133     const supersonicFreestreamFvPatchVectorField& sfspvf,
00134     const DimensionedField<vector, volMesh>& iF
00135 )
00136 :
00137     mixedFvPatchVectorField(sfspvf, iF),
00138     UInf_(sfspvf.UInf_),
00139     pInf_(sfspvf.pInf_),
00140     TInf_(sfspvf.TInf_),
00141     gamma_(sfspvf.gamma_)
00142 {}
00143 
00144 
00145 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00146 
00147 void supersonicFreestreamFvPatchVectorField::updateCoeffs()
00148 {
00149     if (!size() || updated())
00150     {
00151         return;
00152     }
00153 
00154     const fvPatchField<scalar>& pT =
00155         patch().lookupPatchField<volScalarField, scalar>("T");
00156 
00157     const fvPatchField<scalar>& pp =
00158         patch().lookupPatchField<volScalarField, scalar>("p");
00159 
00160     const fvPatchField<scalar>& ppsi =
00161         patch().lookupPatchField<volScalarField, scalar>("psi");
00162 
00163     // Need R of the free-stream flow.  Assume R is independent of location
00164     // along patch so use face 0
00165     scalar R = 1.0/(ppsi[0]*pT[0]);
00166 
00167     scalar MachInf = mag(UInf_)/sqrt(gamma_*R*TInf_);
00168 
00169     if (MachInf < 1.0)
00170     {
00171         FatalErrorIn
00172         (
00173             "supersonicFreestreamFvPatchVectorField::updateCoeffs()"
00174         )   << "    MachInf < 1.0, free stream must be supersonic"
00175             << "\n    on patch " << this->patch().name()
00176             << " of field " << this->dimensionedInternalField().name()
00177             << " in file " << this->dimensionedInternalField().objectPath()
00178             << exit(FatalError);
00179     }
00180 
00181     vectorField& Up = refValue();
00182     valueFraction() = 1;
00183 
00184     // get the near patch internal cell values
00185     vectorField U = patchInternalField();
00186 
00187 
00188     // Find the component of U normal to the free-stream flow and in the
00189     // plane of the free-stream flow and the patch normal
00190 
00191     // Direction of the free-stream flow
00192     vector UInfHat = UInf_/mag(UInf_);
00193 
00194     // Normal to the plane defined by the free-stream and the patch normal
00195     vectorField nnInfHat = UInfHat ^ patch().nf();
00196 
00197     //vectorField UnInf = U - nnInfHat*(nnInfHat & U);
00198     //vectorField Un = UnInf - UInfHat*(UInfHat & UnInf);
00199     //vectorField nHatInf =
00200     //    (Un/(mag(Un) + SMALL)) * sign(patch().nf() & Un);
00201 
00202     // Normal to the free-stream in the plane defined by the free-stream
00203     // and the patch normal
00204     vectorField nHatInf = nnInfHat ^ UInfHat;
00205 
00206     // Component of U normal to the free-stream in the plane defined by the
00207     // free-stream and the patch normal
00208     vectorField Un = nHatInf*(nHatInf & U);
00209 
00210     // The tangential component is
00211     vectorField Ut = U - Un;
00212 
00213     // Calculate the Prandtl-Meyer function of the free-stream
00214     scalar nuMachInf =
00215         sqrt((gamma_ + 1)/(gamma_ - 1))
00216        *atan(sqrt((gamma_ - 1)/(gamma_ + 1)*(sqr(MachInf) - 1)))
00217       - atan(sqr(MachInf) - 1);
00218 
00219 
00220     // Set the patch boundary condition based on the Mach number and direction
00221     // of the flow dictated by the boundary/free-stream pressure difference
00222 
00223     forAll(Up, facei)
00224     {
00225         if (pp[facei] >= pInf_) // If outflow
00226         {
00227             // Assume supersonic outflow and calculate the boundary velocity
00228             // according to ???
00229 
00230             scalar fpp =
00231                 sqrt(sqr(MachInf) - 1)
00232                /(gamma_*sqr(MachInf))*mag(Ut[facei])*log(pp[facei]/pInf_);
00233 
00234             Up[facei] = Ut[facei] + fpp*nHatInf[facei];
00235 
00236             // Calculate the Mach number of the boundary velocity
00237             scalar Mach = mag(Up[facei])/sqrt(gamma_/ppsi[facei]);
00238 
00239             if (Mach <= 1) // If subsonic
00240             {
00241                 // Zero-gradient subsonic outflow
00242 
00243                 Up[facei] = U[facei];
00244                 valueFraction()[facei] = 0;
00245             }
00246         }
00247         else // if inflow
00248         {
00249             // Calculate the Mach number of the boundary velocity
00250             // from the boundary pressure assuming constant total pressure
00251             // expansion from the free-stream
00252             scalar Mach =
00253                 sqrt
00254                 (
00255                     (2/(gamma_ - 1))*(1 + ((gamma_ - 1)/2)*sqr(MachInf))
00256                    *pow(pp[facei]/pInf_, (1 - gamma_)/gamma_)
00257                   - 2/(gamma_ - 1)
00258                 );
00259 
00260             if (Mach > 1) // If supersonic
00261             {
00262                 // Supersonic inflow is assumed to occur according to the
00263                 // Prandtl-Meyer expansion process
00264 
00265                 scalar nuMachf =
00266                     sqrt((gamma_ + 1)/(gamma_ - 1))
00267                    *atan(sqrt((gamma_ - 1)/(gamma_ + 1)*(sqr(Mach) - 1)))
00268                   - atan(sqr(Mach) - 1);
00269 
00270                 scalar fpp = (nuMachInf - nuMachf)*mag(Ut[facei]);
00271 
00272                 Up[facei] = Ut[facei] + fpp*nHatInf[facei];
00273             }
00274             else // If subsonic
00275             {
00276                 FatalErrorIn
00277                 (
00278                     "supersonicFreestreamFvPatchVectorField::updateCoeffs()"
00279                 )   << "unphysical subsonic inflow has been generated"
00280                     << "\n    on patch " << this->patch().name()
00281                     << " of field " << this->dimensionedInternalField().name()
00282                     << " in file "
00283                     << this->dimensionedInternalField().objectPath()
00284                     << exit(FatalError);
00285             }
00286         }
00287     }
00288 
00289     mixedFvPatchVectorField::updateCoeffs();
00290 }
00291 
00292 
00293 void supersonicFreestreamFvPatchVectorField::write(Ostream& os) const
00294 {
00295     fvPatchVectorField::write(os);
00296     os.writeKeyword("UInf") << UInf_ << token::END_STATEMENT << nl;
00297     os.writeKeyword("pInf") << pInf_ << token::END_STATEMENT << nl;
00298     os.writeKeyword("TInf") << TInf_ << token::END_STATEMENT << nl;
00299     os.writeKeyword("gamma") << gamma_ << token::END_STATEMENT << nl;
00300     writeEntry("value", os);
00301 }
00302 
00303 
00304 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00305 
00306 makePatchTypeField
00307 (
00308     fvPatchVectorField,
00309     supersonicFreestreamFvPatchVectorField
00310 );
00311 
00312 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00313 
00314 } // End namespace Foam
00315 
00316 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines