1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
29 #include "cellIOList.H"
31 #include "wedgePolyPatch.H"
32 #include "emptyPolyPatch.H"
33 #include "globalMeshData.H"
34 #include "processorPolyPatch.H"
35 #include "OSspecific.H"
36 #include "demandDrivenData.H"
38 #include "pointMesh.H"
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 defineTypeNameAndDebug(Foam::polyMesh, 0);
45 Foam::word Foam::polyMesh::defaultRegion = "region0";
46 Foam::word Foam::polyMesh::meshSubDir = "polyMesh";
49 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
51 void Foam::polyMesh::calcDirections() const
53 for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
58 // Knock out empty and wedge directions. Note:they will be present on all
61 label nEmptyPatches = 0;
62 label nWedgePatches = 0;
64 vector emptyDirVec = vector::zero;
65 vector wedgeDirVec = vector::zero;
67 forAll(boundaryMesh(), patchi)
69 if (boundaryMesh()[patchi].size())
71 if (isA<emptyPolyPatch>(boundaryMesh()[patchi]))
74 emptyDirVec += sum(cmptMag(boundaryMesh()[patchi].faceAreas()));
76 else if (isA<wedgePolyPatch>(boundaryMesh()[patchi]))
78 const wedgePolyPatch& wpp = refCast<const wedgePolyPatch>
80 boundaryMesh()[patchi]
84 wedgeDirVec += cmptMag(wpp.centreNormal());
91 reduce(emptyDirVec, sumOp<vector>());
93 emptyDirVec /= mag(emptyDirVec);
95 for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
97 if (emptyDirVec[cmpt] > 1e-6)
99 solutionD_[cmpt] = -1;
103 solutionD_[cmpt] = 1;
109 // Knock out wedge directions
111 geometricD_ = solutionD_;
115 reduce(wedgeDirVec, sumOp<vector>());
117 wedgeDirVec /= mag(wedgeDirVec);
119 for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
121 if (wedgeDirVec[cmpt] > 1e-6)
123 geometricD_[cmpt] = -1;
127 geometricD_[cmpt] = 1;
134 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
136 Foam::polyMesh::polyMesh(const IOobject& io)
145 time().findInstance(meshDir(), "points"),
157 time().findInstance(meshDir(), "faces"),
169 time().findInstance(meshDir(), "faces"),
172 IOobject::READ_IF_PRESENT,
181 time().findInstance(meshDir(), "faces"),
184 IOobject::READ_IF_PRESENT,
188 clearedPrimitives_(false),
194 time().findInstance(meshDir(), "boundary"),
203 geometricD_(Vector<label>::zero),
204 solutionD_(Vector<label>::zero),
214 IOobject::READ_IF_PRESENT
218 IOobject::READ_IF_PRESENT,
232 IOobject::READ_IF_PRESENT
236 IOobject::READ_IF_PRESENT,
250 IOobject::READ_IF_PRESENT
254 IOobject::READ_IF_PRESENT,
259 globalMeshDataPtr_(NULL),
262 curMotionTimeIndex_(time().timeIndex()),
265 if (exists(owner_.objectPath()))
276 time().findInstance(meshDir(), "cells"),
284 // Set the primitive mesh
291 // Calculate topology for the patches (processor-processor comms etc.)
292 boundary_.updateMesh();
294 // Calculate the geometry for the patches (transformation tensors etc.)
295 boundary_.calcGeometry();
297 // Warn if global empty mesh (constructs globalData!)
298 if (globalData().nTotalPoints() == 0)
300 WarningIn("polyMesh(const IOobject&)")
301 << "no points in mesh" << endl;
303 if (globalData().nTotalCells() == 0)
305 WarningIn("polyMesh(const IOobject&)")
306 << "no cells in mesh" << endl;
311 Foam::polyMesh::polyMesh
314 const Xfer<pointField>& points,
315 const Xfer<faceList>& faces,
316 const Xfer<labelList>& owner,
317 const Xfer<labelList>& neighbour,
375 clearedPrimitives_(false),
390 bounds_(points_, syncPar),
391 geometricD_(Vector<label>::zero),
392 solutionD_(Vector<label>::zero),
435 globalMeshDataPtr_(NULL),
438 curMotionTimeIndex_(time().timeIndex()),
441 // Check if the faces and cells are valid
442 forAll (faces_, faceI)
444 const face& curFace = faces_[faceI];
446 if (min(curFace) < 0 || max(curFace) > points_.size())
450 "polyMesh::polyMesh\n"
452 " const IOobject& io,\n"
453 " const pointField& points,\n"
454 " const faceList& faces,\n"
455 " const cellList& cells\n"
457 ) << "Face " << faceI << "contains vertex labels out of range: "
458 << curFace << " Max point index = " << points_.size()
459 << abort(FatalError);
463 // Set the primitive mesh
468 Foam::polyMesh::polyMesh
471 const Xfer<pointField>& points,
472 const Xfer<faceList>& faces,
473 const Xfer<cellList>& cells,
531 clearedPrimitives_(false),
546 bounds_(points_, syncPar),
547 geometricD_(Vector<label>::zero),
548 solutionD_(Vector<label>::zero),
591 globalMeshDataPtr_(NULL),
594 curMotionTimeIndex_(time().timeIndex()),
597 // Check if faces are valid
598 forAll (faces_, faceI)
600 const face& curFace = faces_[faceI];
602 if (min(curFace) < 0 || max(curFace) > points_.size())
606 "polyMesh::polyMesh\n"
608 " const IOobject&,\n"
609 " const Xfer<pointField>&,\n"
610 " const Xfer<faceList>&,\n"
611 " const Xfer<cellList>&\n"
613 ) << "Face " << faceI << "contains vertex labels out of range: "
614 << curFace << " Max point index = " << points_.size()
615 << abort(FatalError);
619 // transfer in cell list
620 cellList cLst(cells);
622 // Check if cells are valid
625 const cell& curCell = cLst[cellI];
627 if (min(curCell) < 0 || max(curCell) > faces_.size())
631 "polyMesh::polyMesh\n"
633 " const IOobject&,\n"
634 " const Xfer<pointField>&,\n"
635 " const Xfer<faceList>&,\n"
636 " const Xfer<cellList>&\n"
638 ) << "Cell " << cellI << "contains face labels out of range: "
639 << curCell << " Max face index = " << faces_.size()
640 << abort(FatalError);
644 // Set the primitive mesh
649 void Foam::polyMesh::resetPrimitives
651 const Xfer<pointField>& points,
652 const Xfer<faceList>& faces,
653 const Xfer<labelList>& owner,
654 const Xfer<labelList>& neighbour,
655 const labelList& patchSizes,
656 const labelList& patchStarts,
657 const bool validBoundary
660 // Clear addressing. Keep geometric props for mapping.
663 // Take over new primitive data.
664 // Optimized to avoid overwriting data at all
667 points_.transfer(points());
668 bounds_ = boundBox(points_, validBoundary);
673 faces_.transfer(faces());
678 owner_.transfer(owner());
683 neighbour_.transfer(neighbour());
687 // Reset patch sizes and starts
688 forAll(boundary_, patchI)
690 boundary_[patchI] = polyPatch
692 boundary_[patchI].name(),
701 // Flags the mesh files as being changed
702 setInstance(time().timeName());
704 // Check if the faces and cells are valid
705 forAll (faces_, faceI)
707 const face& curFace = faces_[faceI];
709 if (min(curFace) < 0 || max(curFace) > points_.size())
713 "polyMesh::polyMesh::resetPrimitives\n"
715 " const Xfer<pointField>&,\n"
716 " const Xfer<faceList>&,\n"
717 " const Xfer<labelList>& owner,\n"
718 " const Xfer<labelList>& neighbour,\n"
719 " const labelList& patchSizes,\n"
720 " const labelList& patchStarts\n"
722 ) << "Face " << faceI << " contains vertex labels out of range: "
723 << curFace << " Max point index = " << points_.size()
724 << abort(FatalError);
729 // Set the primitive mesh from the owner_, neighbour_.
730 // Works out from patch end where the active faces stop.
736 // Note that we assume that all the patches stay the same and are
737 // correct etc. so we can already use the patches to do
738 // processor-processor comms.
740 // Calculate topology for the patches (processor-processor comms etc.)
741 boundary_.updateMesh();
743 // Calculate the geometry for the patches (transformation tensors etc.)
744 boundary_.calcGeometry();
746 // Warn if global empty mesh (constructs globalData!)
747 if (globalData().nTotalPoints() == 0 || globalData().nTotalCells() == 0)
751 "polyMesh::polyMesh::resetPrimitives\n"
753 " const Xfer<pointField>&,\n"
754 " const Xfer<faceList>&,\n"
755 " const Xfer<labelList>& owner,\n"
756 " const Xfer<labelList>& neighbour,\n"
757 " const labelList& patchSizes,\n"
758 " const labelList& patchStarts\n"
761 << "no points or no cells in mesh" << endl;
767 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
769 Foam::polyMesh::~polyMesh()
776 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
778 const Foam::fileName& Foam::polyMesh::dbDir() const
780 if (objectRegistry::dbDir() == defaultRegion)
782 return parent().dbDir();
786 return objectRegistry::dbDir();
791 Foam::fileName Foam::polyMesh::meshDir() const
793 return dbDir()/meshSubDir;
797 const Foam::fileName& Foam::polyMesh::pointsInstance() const
799 return points_.instance();
803 const Foam::fileName& Foam::polyMesh::facesInstance() const
805 return faces_.instance();
809 const Foam::Vector<Foam::label>& Foam::polyMesh::geometricD() const
811 if (geometricD_.x() == 0)
820 Foam::label Foam::polyMesh::nGeometricD() const
822 return cmptSum(geometricD() + Vector<label>::one)/2;
826 const Foam::Vector<Foam::label>& Foam::polyMesh::solutionD() const
828 if (solutionD_.x() == 0)
837 Foam::label Foam::polyMesh::nSolutionD() const
839 return cmptSum(solutionD() + Vector<label>::one)/2;
843 // Add boundary patches. Constructor helper
844 void Foam::polyMesh::addPatches
846 const List<polyPatch*>& p,
847 const bool validBoundary
850 if (boundaryMesh().size())
854 "void polyMesh::addPatches(const List<polyPatch*>&, const bool)"
855 ) << "boundary already exists"
856 << abort(FatalError);
859 // Reset valid directions
860 geometricD_ = Vector<label>::zero;
861 solutionD_ = Vector<label>::zero;
863 boundary_.setSize(p.size());
865 // Copy the patch pointers
868 boundary_.set(pI, p[pI]);
871 // parallelData depends on the processorPatch ordering so force
872 // recalculation. Problem: should really be done in removeBoundary but
873 // there is some info in parallelData which might be interesting inbetween
874 // removeBoundary and addPatches.
875 deleteDemandDrivenData(globalMeshDataPtr_);
879 // Calculate topology for the patches (processor-processor comms etc.)
880 boundary_.updateMesh();
882 // Calculate the geometry for the patches (transformation tensors etc.)
883 boundary_.calcGeometry();
885 boundary_.checkDefinition();
890 // Add mesh zones. Constructor helper
891 void Foam::polyMesh::addZones
893 const List<pointZone*>& pz,
894 const List<faceZone*>& fz,
895 const List<cellZone*>& cz
898 if (pointZones().size() || faceZones().size() || cellZones().size())
904 " const List<pointZone*>&,\n"
905 " const List<faceZone*>&,\n"
906 " const List<cellZone*>&\n"
908 ) << "point, face or cell zone already exists"
909 << abort(FatalError);
915 pointZones_.setSize(pz.size());
917 // Copy the zone pointers
920 pointZones_.set(pI, pz[pI]);
923 pointZones_.writeOpt() = IOobject::AUTO_WRITE;
929 faceZones_.setSize(fz.size());
931 // Copy the zone pointers
934 faceZones_.set(fI, fz[fI]);
937 faceZones_.writeOpt() = IOobject::AUTO_WRITE;
943 cellZones_.setSize(cz.size());
945 // Copy the zone pointers
948 cellZones_.set(cI, cz[cI]);
951 cellZones_.writeOpt() = IOobject::AUTO_WRITE;
956 const Foam::pointField& Foam::polyMesh::points() const
958 if (clearedPrimitives_)
960 FatalErrorIn("const pointField& polyMesh::points() const")
961 << "points deallocated"
962 << abort(FatalError);
969 const Foam::faceList& Foam::polyMesh::faces() const
971 if (clearedPrimitives_)
973 FatalErrorIn("const faceList& polyMesh::faces() const")
974 << "faces deallocated"
975 << abort(FatalError);
982 const Foam::labelList& Foam::polyMesh::faceOwner() const
988 const Foam::labelList& Foam::polyMesh::faceNeighbour() const
994 // Return old mesh motion points
995 const Foam::pointField& Foam::polyMesh::oldPoints() const
1001 WarningIn("const pointField& polyMesh::oldPoints() const")
1002 << "Old points not available. Forcing storage of old points"
1006 oldPointsPtr_ = new pointField(points_);
1007 curMotionTimeIndex_ = time().timeIndex();
1010 return *oldPointsPtr_;
1014 Foam::tmp<Foam::scalarField> Foam::polyMesh::movePoints
1016 const pointField& newPoints
1021 Info<< "tmp<scalarField> polyMesh::movePoints(const pointField&) : "
1022 << " Moving points for time " << time().value()
1023 << " index " << time().timeIndex() << endl;
1028 // Pick up old points
1029 if (curMotionTimeIndex_ != time().timeIndex())
1031 // Mesh motion in the new time step
1032 deleteDemandDrivenData(oldPointsPtr_);
1033 oldPointsPtr_ = new pointField(points_);
1034 curMotionTimeIndex_ = time().timeIndex();
1037 points_ = newPoints;
1041 // Check mesh motion
1042 if (primitiveMesh::checkMeshMotion(points_, true))
1044 Info<< "tmp<scalarField> polyMesh::movePoints"
1045 << "(const pointField&) : "
1046 << "Moving the mesh with given points will "
1047 << "invalidate the mesh." << nl
1048 << "Mesh motion should not be executed." << endl;
1052 points_.writeOpt() = IOobject::AUTO_WRITE;
1053 points_.instance() = time().timeName();
1056 tmp<scalarField> sweptVols = primitiveMesh::movePoints
1062 // Adjust parallel shared points
1063 if (globalMeshDataPtr_)
1065 globalMeshDataPtr_->movePoints(points_);
1068 // Force recalculation of all geometric data with new points
1070 bounds_ = boundBox(points_);
1071 boundary_.movePoints(points_);
1073 pointZones_.movePoints(points_);
1074 faceZones_.movePoints(points_);
1075 cellZones_.movePoints(points_);
1077 // Reset valid directions (could change with rotation)
1078 geometricD_ = Vector<label>::zero;
1079 solutionD_ = Vector<label>::zero;
1082 // Hack until proper callbacks. Below are all the polyMeh MeshObjects with a
1083 // movePoints function.
1086 if (thisDb().foundObject<pointMesh>(pointMesh::typeName))
1088 const_cast<pointMesh&>
1090 thisDb().lookupObject<pointMesh>
1094 ).movePoints(points_);
1101 // Reset motion by deleting old points
1102 void Foam::polyMesh::resetMotion() const
1104 curMotionTimeIndex_ = 0;
1105 deleteDemandDrivenData(oldPointsPtr_);
1109 // Return parallel info
1110 const Foam::globalMeshData& Foam::polyMesh::globalData() const
1112 if (!globalMeshDataPtr_)
1116 Pout<< "polyMesh::globalData() const : "
1117 << "Constructing parallelData from processor topology" << nl
1118 << "This needs the patch faces to be correctly matched"
1121 // Construct globalMeshData using processorPatch information only.
1122 globalMeshDataPtr_ = new globalMeshData(*this);
1125 return *globalMeshDataPtr_;
1129 // Remove all files and some subdirs (eg, sets)
1130 void Foam::polyMesh::removeFiles(const fileName& instanceDir) const
1132 fileName meshFilesPath = thisDb().path()/instanceDir/meshDir();
1134 rm(meshFilesPath/"points");
1135 rm(meshFilesPath/"faces");
1136 rm(meshFilesPath/"owner");
1137 rm(meshFilesPath/"neighbour");
1138 rm(meshFilesPath/"cells");
1139 rm(meshFilesPath/"boundary");
1140 rm(meshFilesPath/"pointZones");
1141 rm(meshFilesPath/"faceZones");
1142 rm(meshFilesPath/"cellZones");
1143 rm(meshFilesPath/"meshModifiers");
1144 rm(meshFilesPath/"parallelData");
1146 // remove subdirectories
1147 if (isDir(meshFilesPath/"sets"))
1149 rmDir(meshFilesPath/"sets");
1153 void Foam::polyMesh::removeFiles() const
1155 removeFiles(instance());
1159 // ************************************************************************* //