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

fvFieldReconstructorReconstructFields.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 "fvFieldReconstructor.H"
00027 #include <OpenFOAM/Time.H>
00028 #include <OpenFOAM/PtrList.H>
00029 #include <finiteVolume/fvPatchFields.H>
00030 #include <finiteVolume/emptyFvPatch.H>
00031 #include <finiteVolume/emptyFvPatchField.H>
00032 #include <finiteVolume/emptyFvsPatchField.H>
00033 
00034 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00035 
00036 template<class Type>
00037 Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh> >
00038 Foam::fvFieldReconstructor::reconstructFvVolumeField
00039 (
00040     const IOobject& fieldIoObject
00041 )
00042 {
00043     // Read the field for all the processors
00044     PtrList<GeometricField<Type, fvPatchField, volMesh> > procFields
00045     (
00046         procMeshes_.size()
00047     );
00048 
00049     forAll (procMeshes_, procI)
00050     {
00051         procFields.set
00052         (
00053             procI,
00054             new GeometricField<Type, fvPatchField, volMesh>
00055             (
00056                 IOobject
00057                 (
00058                     fieldIoObject.name(),
00059                     procMeshes_[procI].time().timeName(),
00060                     procMeshes_[procI],
00061                     IOobject::MUST_READ,
00062                     IOobject::NO_WRITE
00063                 ),
00064                 procMeshes_[procI]
00065             )
00066         );
00067     }
00068 
00069 
00070     // Create the internalField
00071     Field<Type> internalField(mesh_.nCells());
00072 
00073     // Create the patch fields
00074     PtrList<fvPatchField<Type> > patchFields(mesh_.boundary().size());
00075 
00076 
00077     forAll (procMeshes_, procI)
00078     {
00079         const GeometricField<Type, fvPatchField, volMesh>& procField =
00080             procFields[procI];
00081 
00082         // Set the cell values in the reconstructed field
00083         internalField.rmap
00084         (
00085             procField.internalField(),
00086             cellProcAddressing_[procI]
00087         );
00088 
00089         // Set the boundary patch values in the reconstructed field
00090         forAll(boundaryProcAddressing_[procI], patchI)
00091         {
00092             // Get patch index of the original patch
00093             const label curBPatch = boundaryProcAddressing_[procI][patchI];
00094 
00095             // Get addressing slice for this patch
00096             const labelList::subList cp =
00097                 procMeshes_[procI].boundary()[patchI].patchSlice
00098                 (
00099                     faceProcAddressing_[procI]
00100                 );
00101 
00102             // check if the boundary patch is not a processor patch
00103             if (curBPatch >= 0)
00104             {
00105                 // Regular patch. Fast looping
00106 
00107                 if (!patchFields(curBPatch))
00108                 {
00109                     patchFields.set
00110                     (
00111                         curBPatch,
00112                         fvPatchField<Type>::New
00113                         (
00114                             procField.boundaryField()[patchI],
00115                             mesh_.boundary()[curBPatch],
00116                             DimensionedField<Type, volMesh>::null(),
00117                             fvPatchFieldReconstructor
00118                             (
00119                                 mesh_.boundary()[curBPatch].size()
00120                             )
00121                         )
00122                     );
00123                 }
00124 
00125                 const label curPatchStart =
00126                     mesh_.boundaryMesh()[curBPatch].start();
00127 
00128                 labelList reverseAddressing(cp.size());
00129 
00130                 forAll(cp, faceI)
00131                 {
00132                     // Subtract one to take into account offsets for
00133                     // face direction.
00134                     reverseAddressing[faceI] = cp[faceI] - 1 - curPatchStart;
00135                 }
00136 
00137                 patchFields[curBPatch].rmap
00138                 (
00139                     procField.boundaryField()[patchI],
00140                     reverseAddressing
00141                 );
00142             }
00143             else
00144             {
00145                 const Field<Type>& curProcPatch =
00146                     procField.boundaryField()[patchI];
00147 
00148                 // In processor patches, there's a mix of internal faces (some
00149                 // of them turned) and possible cyclics. Slow loop
00150                 forAll(cp, faceI)
00151                 {
00152                     // Subtract one to take into account offsets for
00153                     // face direction.
00154                     label curF = cp[faceI] - 1;
00155 
00156                     // Is the face on the boundary?
00157                     if (curF >= mesh_.nInternalFaces())
00158                     {
00159                         label curBPatch = mesh_.boundaryMesh().whichPatch(curF);
00160 
00161                         if (!patchFields(curBPatch))
00162                         {
00163                             patchFields.set
00164                             (
00165                                 curBPatch,
00166                                 fvPatchField<Type>::New
00167                                 (
00168                                     mesh_.boundary()[curBPatch].type(),
00169                                     mesh_.boundary()[curBPatch],
00170                                     DimensionedField<Type, volMesh>::null()
00171                                 )
00172                             );
00173                         }
00174 
00175                         // add the face
00176                         label curPatchFace =
00177                             mesh_.boundaryMesh()
00178                                 [curBPatch].whichFace(curF);
00179 
00180                         patchFields[curBPatch][curPatchFace] =
00181                             curProcPatch[faceI];
00182                     }
00183                 }
00184             }
00185         }
00186     }
00187 
00188     forAll(mesh_.boundary(), patchI)
00189     {
00190         // add empty patches
00191         if
00192         (
00193             isType<emptyFvPatch>(mesh_.boundary()[patchI])
00194          && !patchFields(patchI)
00195         )
00196         {
00197             patchFields.set
00198             (
00199                 patchI,
00200                 fvPatchField<Type>::New
00201                 (
00202                     emptyFvPatchField<Type>::typeName,
00203                     mesh_.boundary()[patchI],
00204                     DimensionedField<Type, volMesh>::null()
00205                 )
00206             );
00207         }
00208     }
00209 
00210 
00211     // Now construct and write the field
00212     // setting the internalField and patchFields
00213     return tmp<GeometricField<Type, fvPatchField, volMesh> >
00214     (
00215         new GeometricField<Type, fvPatchField, volMesh>
00216         (
00217             IOobject
00218             (
00219                 fieldIoObject.name(),
00220                 mesh_.time().timeName(),
00221                 mesh_,
00222                 IOobject::NO_READ,
00223                 IOobject::NO_WRITE
00224             ),
00225             mesh_,
00226             procFields[0].dimensions(),
00227             internalField,
00228             patchFields
00229         )
00230     );
00231 }
00232 
00233 
00234 template<class Type>
00235 Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh> >
00236 Foam::fvFieldReconstructor::reconstructFvSurfaceField
00237 (
00238     const IOobject& fieldIoObject
00239 )
00240 {
00241     // Read the field for all the processors
00242     PtrList<GeometricField<Type, fvsPatchField, surfaceMesh> > procFields
00243     (
00244         procMeshes_.size()
00245     );
00246 
00247     forAll (procMeshes_, procI)
00248     {
00249         procFields.set
00250         (
00251             procI,
00252             new GeometricField<Type, fvsPatchField, surfaceMesh>
00253             (
00254                 IOobject
00255                 (
00256                     fieldIoObject.name(),
00257                     procMeshes_[procI].time().timeName(),
00258                     procMeshes_[procI],
00259                     IOobject::MUST_READ,
00260                     IOobject::NO_WRITE
00261                 ),
00262                 procMeshes_[procI]
00263             )
00264         );
00265     }
00266 
00267 
00268     // Create the internalField
00269     Field<Type> internalField(mesh_.nInternalFaces());
00270 
00271     // Create the patch fields
00272     PtrList<fvsPatchField<Type> > patchFields(mesh_.boundary().size());
00273 
00274 
00275     forAll (procMeshes_, procI)
00276     {
00277         const GeometricField<Type, fvsPatchField, surfaceMesh>& procField =
00278             procFields[procI];
00279 
00280         // Set the face values in the reconstructed field
00281 
00282         // It is necessary to create a copy of the addressing array to
00283         // take care of the face direction offset trick.
00284         //
00285         {
00286             labelList curAddr(faceProcAddressing_[procI]);
00287 
00288             forAll (curAddr, addrI)
00289             {
00290                 curAddr[addrI] -= 1;
00291             }
00292 
00293             internalField.rmap
00294             (
00295                 procField.internalField(),
00296                 curAddr
00297             );
00298         }
00299 
00300         // Set the boundary patch values in the reconstructed field
00301         forAll(boundaryProcAddressing_[procI], patchI)
00302         {
00303             // Get patch index of the original patch
00304             const label curBPatch = boundaryProcAddressing_[procI][patchI];
00305 
00306             // Get addressing slice for this patch
00307             const labelList::subList cp =
00308                 procMeshes_[procI].boundary()[patchI].patchSlice
00309                 (
00310                     faceProcAddressing_[procI]
00311                 );
00312 
00313             // check if the boundary patch is not a processor patch
00314             if (curBPatch >= 0)
00315             {
00316                 // Regular patch. Fast looping
00317 
00318                 if (!patchFields(curBPatch))
00319                 {
00320                     patchFields.set
00321                     (
00322                         curBPatch,
00323                         fvsPatchField<Type>::New
00324                         (
00325                             procField.boundaryField()[patchI],
00326                             mesh_.boundary()[curBPatch],
00327                             DimensionedField<Type, surfaceMesh>::null(),
00328                             fvPatchFieldReconstructor
00329                             (
00330                                 mesh_.boundary()[curBPatch].size()
00331                             )
00332                         )
00333                     );
00334                 }
00335 
00336                 const label curPatchStart =
00337                     mesh_.boundaryMesh()[curBPatch].start();
00338 
00339                 labelList reverseAddressing(cp.size());
00340 
00341                 forAll(cp, faceI)
00342                 {
00343                     // Subtract one to take into account offsets for
00344                     // face direction.
00345                     reverseAddressing[faceI] = cp[faceI] - 1 - curPatchStart;
00346                 }
00347 
00348                 patchFields[curBPatch].rmap
00349                 (
00350                     procField.boundaryField()[patchI],
00351                     reverseAddressing
00352                 );
00353             }
00354             else
00355             {
00356                 const Field<Type>& curProcPatch =
00357                     procField.boundaryField()[patchI];
00358 
00359                 // In processor patches, there's a mix of internal faces (some
00360                 // of them turned) and possible cyclics. Slow loop
00361                 forAll(cp, faceI)
00362                 {
00363                     label curF = cp[faceI] - 1;
00364 
00365                     // Is the face turned the right side round
00366                     if (curF >= 0)
00367                     {
00368                         // Is the face on the boundary?
00369                         if (curF >= mesh_.nInternalFaces())
00370                         {
00371                             label curBPatch =
00372                                 mesh_.boundaryMesh().whichPatch(curF);
00373 
00374                             if (!patchFields(curBPatch))
00375                             {
00376                                 patchFields.set
00377                                 (
00378                                     curBPatch,
00379                                     fvsPatchField<Type>::New
00380                                     (
00381                                         mesh_.boundary()[curBPatch].type(),
00382                                         mesh_.boundary()[curBPatch],
00383                                         DimensionedField<Type, surfaceMesh>
00384                                            ::null()
00385                                     )
00386                                 );
00387                             }
00388 
00389                             // add the face
00390                             label curPatchFace =
00391                                 mesh_.boundaryMesh()
00392                                 [curBPatch].whichFace(curF);
00393 
00394                             patchFields[curBPatch][curPatchFace] =
00395                                 curProcPatch[faceI];
00396                         }
00397                         else
00398                         {
00399                             // Internal face
00400                             internalField[curF] = curProcPatch[faceI];
00401                         }
00402                     }
00403                 }
00404             }
00405         }
00406     }
00407 
00408     forAll(mesh_.boundary(), patchI)
00409     {
00410         // add empty patches
00411         if
00412         (
00413             isType<emptyFvPatch>(mesh_.boundary()[patchI])
00414          && !patchFields(patchI)
00415         )
00416         {
00417             patchFields.set
00418             (
00419                 patchI,
00420                 fvsPatchField<Type>::New
00421                 (
00422                     emptyFvsPatchField<Type>::typeName,
00423                     mesh_.boundary()[patchI],
00424                     DimensionedField<Type, surfaceMesh>::null()
00425                 )
00426             );
00427         }
00428     }
00429 
00430 
00431     // Now construct and write the field
00432     // setting the internalField and patchFields
00433     return tmp<GeometricField<Type, fvsPatchField, surfaceMesh> >
00434     (
00435         new GeometricField<Type, fvsPatchField, surfaceMesh>
00436         (
00437             IOobject
00438             (
00439                 fieldIoObject.name(),
00440                 mesh_.time().timeName(),
00441                 mesh_,
00442                 IOobject::NO_READ,
00443                 IOobject::NO_WRITE
00444             ),
00445             mesh_,
00446             procFields[0].dimensions(),
00447             internalField,
00448             patchFields
00449         )
00450     );
00451 }
00452 
00453 
00454 // Reconstruct and write all/selected volume fields
00455 template<class Type>
00456 void Foam::fvFieldReconstructor::reconstructFvVolumeFields
00457 (
00458     const IOobjectList& objects,
00459     const HashSet<word>& selectedFields
00460 )
00461 {
00462     const word& fieldClassName =
00463         GeometricField<Type, fvPatchField, volMesh>::typeName;
00464 
00465     IOobjectList fields = objects.lookupClass(fieldClassName);
00466 
00467     if (fields.size())
00468     {
00469         Info<< "    Reconstructing " << fieldClassName << "s\n" << endl;
00470 
00471         forAllConstIter(IOobjectList, fields, fieldIter)
00472         {
00473             if
00474             (
00475                 !selectedFields.size()
00476              || selectedFields.found(fieldIter()->name())
00477             )
00478             {
00479                 Info<< "        " << fieldIter()->name() << endl;
00480 
00481                 reconstructFvVolumeField<Type>(*fieldIter())().write();
00482             }
00483         }
00484         Info<< endl;
00485     }
00486 }
00487 
00488 // Reconstruct and write all/selected surface fields
00489 template<class Type>
00490 void Foam::fvFieldReconstructor::reconstructFvSurfaceFields
00491 (
00492     const IOobjectList& objects,
00493     const HashSet<word>& selectedFields
00494 )
00495 {
00496     const word& fieldClassName =
00497         GeometricField<Type, fvsPatchField, surfaceMesh>::typeName;
00498 
00499     IOobjectList fields = objects.lookupClass(fieldClassName);
00500 
00501     if (fields.size())
00502     {
00503         Info<< "    Reconstructing " << fieldClassName << "s\n" << endl;
00504 
00505         forAllConstIter(IOobjectList, fields, fieldIter)
00506         {
00507             if
00508             (
00509                 !selectedFields.size()
00510              || selectedFields.found(fieldIter()->name())
00511             )
00512             {
00513                 Info<< "        " << fieldIter()->name() << endl;
00514 
00515                 reconstructFvSurfaceField<Type>(*fieldIter())().write();
00516             }
00517         }
00518         Info<< endl;
00519     }
00520 }
00521 
00522 
00523 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines