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

displacementInterpolationFvMotionSolver.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 "displacementInterpolationFvMotionSolver.H"
00027 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00028 #include <OpenFOAM/SortableList.H>
00029 #include <OpenFOAM/IOList.H>
00030 #include <OpenFOAM/Tuple2.H>
00031 #include <OpenFOAM/mapPolyMesh.H>
00032 #include <OpenFOAM/interpolateXY.H>
00033 
00034 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00035 
00036 namespace Foam
00037 {
00038     defineTypeNameAndDebug(displacementInterpolationFvMotionSolver, 0);
00039 
00040     addToRunTimeSelectionTable
00041     (
00042         fvMotionSolver,
00043         displacementInterpolationFvMotionSolver,
00044         dictionary
00045     );
00046 
00047     template<>
00048     const word IOList<Tuple2<scalar, vector> >::typeName("scalarVectorTable");
00049 }
00050 
00051 
00052 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00053 
00054 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00055 
00056 Foam::displacementInterpolationFvMotionSolver::
00057 displacementInterpolationFvMotionSolver
00058 (
00059     const polyMesh& mesh,
00060     Istream& is
00061 )
00062 :
00063     displacementFvMotionSolver(mesh, is),
00064     dynamicMeshCoeffs_
00065     (
00066         IOdictionary
00067         (
00068             IOobject
00069             (
00070                 "dynamicMeshDict",
00071                 mesh.time().constant(),
00072                 mesh,
00073                 IOobject::MUST_READ,
00074                 IOobject::NO_WRITE,
00075                 false
00076             )
00077         ).subDict(typeName + "Coeffs")
00078     )
00079 {
00080     // Get zones and their interpolation tables for displacement
00081     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00082 
00083     List<Pair<word> > faceZoneToTable
00084     (
00085         dynamicMeshCoeffs_.lookup("interpolationTables")
00086     );
00087 
00088     const faceZoneMesh& fZones = mesh.faceZones();
00089 
00090     times_.setSize(fZones.size());
00091     displacements_.setSize(fZones.size());
00092 
00093     forAll(faceZoneToTable, i)
00094     {
00095         const word& zoneName = faceZoneToTable[i][0];
00096         label zoneI = fZones.findZoneID(zoneName);
00097 
00098         if (zoneI == -1)
00099         {
00100             FatalErrorIn
00101             (
00102                 "displacementInterpolationFvMotionSolver::"
00103                 "displacementInterpolationFvMotionSolver(const polyMesh&,"
00104                 "Istream&)"
00105             )   << "Cannot find zone " << zoneName << endl
00106                 << "Valid zones are " << mesh.faceZones().names()
00107                 << exit(FatalError);
00108         }
00109 
00110         const word& tableName = faceZoneToTable[i][1];
00111 
00112         IOList<Tuple2<scalar, vector> > table
00113         (
00114             IOobject
00115             (
00116                 tableName,
00117                 mesh.time().constant(),
00118                 "tables",
00119                 mesh,
00120                 IOobject::MUST_READ,
00121                 IOobject::NO_WRITE,
00122                 false
00123             )
00124         );
00125 
00126         // Copy table
00127         times_[zoneI].setSize(table.size());
00128         displacements_[zoneI].setSize(table.size());
00129 
00130         forAll(table, j)
00131         {
00132             times_[zoneI][j] = table[j].first();
00133             displacements_[zoneI][j] = table[j].second();
00134         }
00135     }
00136 
00137 
00138 
00139     // Sort points into bins according to position relative to faceZones
00140     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00141     // Done in all three directions.
00142 
00143     for (direction dir = 0; dir < vector::nComponents; dir++)
00144     {
00145         // min and max coordinates of all faceZones
00146         SortableList<scalar> zoneCoordinates(2*faceZoneToTable.size());
00147 
00148         forAll(faceZoneToTable, i)
00149         {
00150             const word& zoneName = faceZoneToTable[i][0];
00151             label zoneI = fZones.findZoneID(zoneName);
00152             const faceZone& fz = fZones[zoneI];
00153 
00154             scalar minCoord = VGREAT;
00155             scalar maxCoord = -VGREAT;
00156 
00157             forAll(fz().meshPoints(), localI)
00158             {
00159                 label pointI = fz().meshPoints()[localI];
00160                 const scalar coord = points0()[pointI][dir];
00161                 minCoord = min(minCoord, coord);
00162                 maxCoord = max(maxCoord, coord);
00163             }
00164 
00165             zoneCoordinates[2*i] = returnReduce(minCoord, minOp<scalar>());
00166             zoneCoordinates[2*i+1] = returnReduce(maxCoord, maxOp<scalar>());
00167 
00168             if (debug)
00169             {
00170                 Pout<< "direction " << dir << " : "
00171                     << "zone " << zoneName
00172                     << " ranges from coordinate " << zoneCoordinates[2*i]
00173                     << " to " << zoneCoordinates[2*i+1]
00174                     << endl;
00175             }
00176         }
00177         zoneCoordinates.sort();
00178 
00179         // Slightly tweak min and max face zone so points sort within
00180         zoneCoordinates[0] -= SMALL;
00181         zoneCoordinates[zoneCoordinates.size()-1] += SMALL;
00182 
00183         // Check if we have static min and max mesh bounds
00184         const scalarField meshCoords = points0().component(dir);
00185 
00186         scalar minCoord = gMin(meshCoords);
00187         scalar maxCoord = gMax(meshCoords);
00188 
00189         if (debug)
00190         {
00191             Pout<< "direction " << dir << " : "
00192                 << "mesh ranges from coordinate " << minCoord << " to "
00193                 << maxCoord << endl;
00194         }
00195 
00196         // Make copy of zoneCoordinates; include min and max of mesh
00197         // if necessary. Mark min and max with zoneI=-1.
00198         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00199 
00200         labelList& rangeZone = rangeToZone_[dir];
00201         labelListList& rangePoints = rangeToPoints_[dir];
00202         List<scalarField>& rangeWeights = rangeToWeights_[dir];
00203 
00204         scalarField rangeToCoord(zoneCoordinates.size());
00205         rangeZone.setSize(zoneCoordinates.size());
00206         label rangeI = 0;
00207 
00208         if (minCoord < zoneCoordinates[0])
00209         {
00210             label sz = rangeZone.size();
00211             rangeToCoord.setSize(sz+1);
00212             rangeZone.setSize(sz+1);
00213             rangeToCoord[rangeI] = minCoord-SMALL;
00214             rangeZone[rangeI] = -1;
00215 
00216             if (debug)
00217             {
00218                 Pout<< "direction " << dir << " : "
00219                     << "range " << rangeI << " at coordinate "
00220                     << rangeToCoord[rangeI] << " from min of mesh "
00221                     << rangeZone[rangeI] << endl;
00222             }
00223             rangeI = 1;
00224         }
00225         forAll(zoneCoordinates, i)
00226         {
00227             rangeToCoord[rangeI] = zoneCoordinates[i];
00228             rangeZone[rangeI] = zoneCoordinates.indices()[i]/2;
00229 
00230             if (debug)
00231             {
00232                 Pout<< "direction " << dir << " : "
00233                     << "range " << rangeI << " at coordinate "
00234                     << rangeToCoord[rangeI]
00235                     << " from zone " << rangeZone[rangeI] << endl;
00236             }
00237             rangeI++;
00238         }
00239         if (maxCoord > zoneCoordinates[zoneCoordinates.size()-1])
00240         {
00241             label sz = rangeToCoord.size();
00242             rangeToCoord.setSize(sz+1);
00243             rangeZone.setSize(sz+1);
00244             rangeToCoord[sz] = maxCoord+SMALL;
00245             rangeZone[sz] = -1;
00246 
00247             if (debug)
00248             {
00249                 Pout<< "direction " << dir << " : "
00250                     << "range " << rangeI << " at coordinate "
00251                     << rangeToCoord[sz] << " from max of mesh "
00252                     << rangeZone[sz] << endl;
00253             }
00254         }
00255 
00256 
00257         // Sort the points
00258         // ~~~~~~~~~~~~~~~
00259 
00260         // Count all the points inbetween rangeI and rangeI+1
00261         labelList nRangePoints(rangeToCoord.size(), 0);
00262 
00263         forAll(meshCoords, pointI)
00264         {
00265             label rangeI = findLower(rangeToCoord, meshCoords[pointI]);
00266 
00267             if (rangeI == -1 || rangeI == rangeToCoord.size()-1)
00268             {
00269                 FatalErrorIn
00270                 (
00271                     "displacementInterpolationFvMotionSolver::"
00272                     "displacementInterpolationFvMotionSolver"
00273                     "(const polyMesh&, Istream&)"
00274                 )   << "Did not find point " << points0()[pointI]
00275                     << " coordinate " << meshCoords[pointI]
00276                     << " in ranges " << rangeToCoord
00277                     << abort(FatalError);
00278             }
00279             nRangePoints[rangeI]++;
00280         }
00281 
00282         if (debug)
00283         {
00284             for (label rangeI = 0; rangeI < rangeToCoord.size()-1; rangeI++)
00285             {
00286                 // Get the two zones bounding the range
00287                 Pout<< "direction " << dir << " : "
00288                     << "range from " << rangeToCoord[rangeI]
00289                     << " to " << rangeToCoord[rangeI+1]
00290                     << " contains " << nRangePoints[rangeI]
00291                     << " points." << endl;
00292             }
00293         }
00294 
00295         // Sort
00296         rangePoints.setSize(nRangePoints.size());
00297         rangeWeights.setSize(nRangePoints.size());
00298         forAll(rangePoints, rangeI)
00299         {
00300             rangePoints[rangeI].setSize(nRangePoints[rangeI]);
00301             rangeWeights[rangeI].setSize(nRangePoints[rangeI]);
00302         }
00303         nRangePoints = 0;
00304         forAll(meshCoords, pointI)
00305         {
00306             label rangeI = findLower(rangeToCoord, meshCoords[pointI]);
00307             label& nPoints = nRangePoints[rangeI];
00308             rangePoints[rangeI][nPoints] = pointI;
00309             rangeWeights[rangeI][nPoints] =
00310                 (meshCoords[pointI]-rangeToCoord[rangeI])
00311               / (rangeToCoord[rangeI+1]-rangeToCoord[rangeI]);
00312             nPoints++;
00313         }
00314     }
00315 }
00316 
00317 
00318 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00319 
00320 Foam::displacementInterpolationFvMotionSolver::
00321 ~displacementInterpolationFvMotionSolver()
00322 {}
00323 
00324 
00325 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00326 
00327 Foam::tmp<Foam::pointField>
00328 Foam::displacementInterpolationFvMotionSolver::curPoints() const
00329 {
00330     if (mesh().nPoints() != points0().size())
00331     {
00332         FatalErrorIn
00333         (
00334             "displacementInterpolationFvMotionSolver::curPoints() const"
00335         )   << "The number of points in the mesh seems to have changed." << endl
00336             << "In constant/polyMesh there are " << points0().size()
00337             << " points; in the current mesh there are " << mesh().nPoints()
00338             << " points." << exit(FatalError);
00339     }
00340 
00341     tmp<pointField> tcurPoints(new pointField(points0()));
00342     pointField& curPoints = tcurPoints();
00343 
00344     // Interpolate the diplacement of the face zones.
00345     vectorField zoneDisp(displacements_.size(), vector::zero);
00346     forAll(zoneDisp, zoneI)
00347     {
00348         if (times_[zoneI].size())
00349         {
00350             zoneDisp[zoneI] = interpolateXY
00351             (
00352                 mesh().time().value(),
00353                 times_[zoneI],
00354                 displacements_[zoneI]
00355             );
00356         }
00357     }
00358     if (debug)
00359     {
00360         Pout<< "Zone displacements:" << zoneDisp << endl;
00361     }
00362 
00363 
00364     // Interpolate the point location
00365     for (direction dir = 0; dir < vector::nComponents; dir++)
00366     {
00367         const labelList& rangeZone = rangeToZone_[dir];
00368         const labelListList& rangePoints = rangeToPoints_[dir];
00369         const List<scalarField>& rangeWeights = rangeToWeights_[dir];
00370 
00371         for (label rangeI = 0; rangeI < rangeZone.size()-1; rangeI++)
00372         {
00373             const labelList& rPoints = rangePoints[rangeI];
00374             const scalarField& rWeights = rangeWeights[rangeI];
00375 
00376             // Get the two zones bounding the range
00377             label minZoneI = rangeZone[rangeI];
00378             //vector minDisp =
00379             //    (minZoneI == -1 ? vector::zero : zoneDisp[minZoneI]);
00380             scalar minDisp = (minZoneI == -1 ? 0.0 : zoneDisp[minZoneI][dir]);
00381             label maxZoneI = rangeZone[rangeI+1];
00382             //vector maxDisp =
00383             //    (maxZoneI == -1 ? vector::zero : zoneDisp[maxZoneI]);
00384             scalar maxDisp = (maxZoneI == -1 ? 0.0 : zoneDisp[maxZoneI][dir]);
00385 
00386             forAll(rPoints, i)
00387             {
00388                 label pointI = rPoints[i];
00389                 scalar w = rWeights[i];
00390                 //curPoints[pointI] += (1.0-w)*minDisp+w*maxDisp;
00391                 curPoints[pointI][dir] += (1.0-w)*minDisp+w*maxDisp;
00392             }
00393         }
00394     }
00395     return tcurPoints;
00396 }
00397 
00398 
00399 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines