1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 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 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 defineTypeNameAndDebug(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++)
55 directions_[cmpt] = 1;
58 label nEmptyPatches = 0;
60 vector dirVec = vector::zero;
62 forAll(boundaryMesh(), patchi)
64 if (isA<emptyPolyPatch>(boundaryMesh()[patchi]))
66 if (boundaryMesh()[patchi].size())
69 dirVec += sum(cmptMag(boundaryMesh()[patchi].faceAreas()));
76 reduce(dirVec, sumOp<vector>());
78 dirVec /= mag(dirVec);
80 for (direction cmpt=0; cmpt<vector::nComponents; cmpt++)
82 if (dirVec[cmpt] > 1e-6)
84 directions_[cmpt] = -1;
88 directions_[cmpt] = 1;
95 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
97 Foam::polyMesh::polyMesh(const IOobject& io)
106 time().findInstance(meshDir(), "points"),
118 time().findInstance(meshDir(), "faces"),
130 time().findInstance(meshDir(), "faces"),
133 IOobject::READ_IF_PRESENT,
142 time().findInstance(meshDir(), "faces"),
145 IOobject::READ_IF_PRESENT,
149 clearedPrimitives_(false),
155 time().findInstance(meshDir(), "boundary"),
164 directions_(Vector<label>::zero),
174 IOobject::READ_IF_PRESENT
178 IOobject::READ_IF_PRESENT,
192 IOobject::READ_IF_PRESENT
196 IOobject::READ_IF_PRESENT,
210 IOobject::READ_IF_PRESENT
214 IOobject::READ_IF_PRESENT,
219 globalMeshDataPtr_(NULL),
222 curMotionTimeIndex_(time().timeIndex()),
225 if (exists(owner_.objectPath()))
236 time().findInstance(meshDir(), "cells"),
245 // Set the primitive mesh
252 // Calculate topology for the patches (processor-processor comms etc.)
253 boundary_.updateMesh();
255 // Calculate the geometry for the patches (transformation tensors etc.)
256 boundary_.calcGeometry();
258 // Warn if global empty mesh (constructs globalData!)
259 if (globalData().nTotalPoints() == 0)
261 WarningIn("polyMesh(const IOobject&)")
262 << "no points in mesh" << endl;
264 if (globalData().nTotalCells() == 0)
266 WarningIn("polyMesh(const IOobject&)")
267 << "no cells in mesh" << endl;
272 Foam::polyMesh::polyMesh
275 const pointField& points,
276 const faceList& faces,
277 const labelList& owner,
278 const labelList& neighbour,
336 clearedPrimitives_(false),
351 bounds_(points_, syncPar),
352 directions_(Vector<label>::zero),
395 globalMeshDataPtr_(NULL),
398 curMotionTimeIndex_(time().timeIndex()),
401 // Check if the faces and cells are valid
402 forAll (faces_, faceI)
404 const face& curFace = faces_[faceI];
406 if (min(curFace) < 0 || max(curFace) > points_.size())
410 "polyMesh::polyMesh\n"
412 " const IOobject& io,\n"
413 " const pointField& points,\n"
414 " const faceList& faces,\n"
415 " const cellList& cells\n"
417 ) << "Face " << faceI << "contains vertex labels out of range: "
418 << curFace << " Max point index = " << points_.size()
419 << abort(FatalError);
423 // Set the primitive mesh
428 Foam::polyMesh::polyMesh
431 const pointField& points,
432 const faceList& faces,
433 const cellList& cells,
491 clearedPrimitives_(false),
506 bounds_(points_, syncPar),
507 directions_(Vector<label>::zero),
550 globalMeshDataPtr_(NULL),
553 curMotionTimeIndex_(time().timeIndex()),
556 // Check if the faces and cells are valid
557 forAll (faces_, faceI)
559 const face& curFace = faces_[faceI];
561 if (min(curFace) < 0 || max(curFace) > points_.size())
565 "polyMesh::polyMesh\n"
567 " const IOobject& io,\n"
568 " const pointField& points,\n"
569 " const faceList& faces,\n"
570 " const cellList& cells\n"
572 ) << "Face " << faceI << "contains vertex labels out of range: "
573 << curFace << " Max point index = " << points_.size()
574 << abort(FatalError);
578 // Check if the faces and cells are valid
579 forAll (cells, cellI)
581 const cell& curCell = cells[cellI];
583 if (min(curCell) < 0 || max(curCell) > faces_.size())
587 "polyMesh::polyMesh\n"
589 " const IOobject& io,\n"
590 " const pointField& points,\n"
591 " const faceList& faces,\n"
592 " const cellList& cells\n"
594 ) << "Cell " << cellI << "contains face labels out of range: "
595 << curCell << " Max face index = " << faces_.size()
596 << abort(FatalError);
600 // Set the primitive mesh
601 initMesh(const_cast<cellList&>(cells));
605 void Foam::polyMesh::resetPrimitives
607 const label nUsedFaces,
608 const pointField& points,
609 const faceList& faces,
610 const labelList& owner,
611 const labelList& neighbour,
612 const labelList& patchSizes,
613 const labelList& patchStarts,
614 const bool validBoundary
617 // Clear addressing. Keep geometric props for mapping.
620 // Take over new primitive data. Note extra optimization to prevent
621 // assignment to self.
622 if (&points_ != &points)
625 bounds_ = boundBox(points_, validBoundary);
627 if (&faces_ != &faces)
631 if (&owner_ != &owner)
635 if (&neighbour_ != &neighbour)
637 neighbour_ = neighbour;
640 // Reset patch sizes and starts
641 forAll(boundary_, patchI)
643 boundary_[patchI] = polyPatch
645 boundary_[patchI].name(),
654 // Flags the mesh files as being changed
655 setInstance(time().timeName());
657 // Check if the faces and cells are valid
658 forAll (faces_, faceI)
660 const face& curFace = faces_[faceI];
662 if (min(curFace) < 0 || max(curFace) > points_.size())
666 "polyMesh::polyMesh::resetPrimitives\n"
668 " const label nUsedFaces,\n"
669 " const pointField& points,\n"
670 " const faceList& faces,\n"
671 " const labelList& owner,\n"
672 " const labelList& neighbour,\n"
673 " const labelList& patchSizes,\n"
674 " const labelList& patchStarts\n"
676 ) << "Face " << faceI << " contains vertex labels out of range: "
677 << curFace << " Max point index = " << points_.size()
678 << abort(FatalError);
683 // Set the primitive mesh from the owner_, neighbour_. Works
684 // out from patch end where the active faces stop.
690 // Note that we assume that all the patches stay the same and are
691 // correct etc. so we can already use the patches to do
692 // processor-processor comms.
694 // Calculate topology for the patches (processor-processor comms etc.)
695 boundary_.updateMesh();
697 // Calculate the geometry for the patches (transformation tensors etc.)
698 boundary_.calcGeometry();
700 // Warn if global empty mesh (constructs globalData!)
701 if (globalData().nTotalPoints() == 0 || globalData().nTotalCells() == 0)
705 "polyMesh::polyMesh::resetPrimitives\n"
707 " const label nUsedFaces,\n"
708 " const pointField& points,\n"
709 " const faceList& faces,\n"
710 " const labelList& owner,\n"
711 " const labelList& neighbour,\n"
712 " const labelList& patchSizes,\n"
713 " const labelList& patchStarts\n"
716 << "no points or no cells in mesh" << endl;
722 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
724 Foam::polyMesh::~polyMesh()
731 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
733 const Foam::fileName& Foam::polyMesh::dbDir() const
735 if (objectRegistry::dbDir() == defaultRegion)
737 return parent().dbDir();
741 return objectRegistry::dbDir();
746 Foam::fileName Foam::polyMesh::meshDir() const
748 return dbDir()/meshSubDir;
752 const Foam::fileName& Foam::polyMesh::pointsInstance() const
754 return points_.instance();
758 const Foam::fileName& Foam::polyMesh::facesInstance() const
760 return faces_.instance();
764 const Foam::Vector<Foam::label>& Foam::polyMesh::directions() const
766 if (directions_.x() == 0)
775 Foam::label Foam::polyMesh::nGeometricD() const
779 forAll(boundary_, patchi)
781 if (isA<wedgePolyPatch>(boundary_[patchi]))
787 if (nWedges != 0 && nWedges != 2 && nWedges != 4)
789 FatalErrorIn("label polyMesh::nGeometricD() const")
790 << "Number of wedge patches " << nWedges << " is incorrect, "
791 "should be 0, 2 or 4"
795 return nSolutionD() - nWedges/2;
799 Foam::label Foam::polyMesh::nSolutionD() const
801 return cmptSum(directions() + Vector<label>::one)/2;
805 // Add boundary patches. Constructor helper
806 void Foam::polyMesh::addPatches
808 const List<polyPatch*>& p,
809 const bool validBoundary
812 if (boundaryMesh().size() > 0)
816 "void polyMesh::addPatches(const List<polyPatch*>&, const bool)"
817 ) << "boundary already exists"
818 << abort(FatalError);
821 boundary_.setSize(p.size());
823 // Copy the patch pointers
826 boundary_.set(pI, p[pI]);
829 // parallelData depends on the processorPatch ordering so force
830 // recalculation. Problem: should really be done in removeBoundary but
831 // there is some info in parallelData which might be interesting inbetween
832 // removeBoundary and addPatches.
833 deleteDemandDrivenData(globalMeshDataPtr_);
837 // Calculate topology for the patches (processor-processor comms etc.)
838 boundary_.updateMesh();
840 // Calculate the geometry for the patches (transformation tensors etc.)
841 boundary_.calcGeometry();
843 boundary_.checkDefinition();
848 // Add mesh zones. Constructor helper
849 void Foam::polyMesh::addZones
851 const List<pointZone*>& pz,
852 const List<faceZone*>& fz,
853 const List<cellZone*>& cz
858 pointZones().size() > 0
859 || faceZones().size() > 0
860 || cellZones().size() > 0
867 " const List<pointZone*>& pz,\n"
868 " const List<faceZone*>& fz,\n"
869 " const List<cellZone*>& cz\n"
871 ) << "point, face or cell zone already exists"
872 << abort(FatalError);
878 pointZones_.setSize(pz.size());
880 // Copy the zone pointers
883 pointZones_.set(pI, pz[pI]);
886 pointZones_.writeOpt() = IOobject::AUTO_WRITE;
892 faceZones_.setSize(fz.size());
894 // Copy the zone pointers
897 faceZones_.set(fI, fz[fI]);
900 faceZones_.writeOpt() = IOobject::AUTO_WRITE;
906 cellZones_.setSize(cz.size());
908 // Copy the zone pointers
911 cellZones_.set(cI, cz[cI]);
914 cellZones_.writeOpt() = IOobject::AUTO_WRITE;
919 const Foam::pointField& Foam::polyMesh::points() const
921 if (clearedPrimitives_)
923 FatalErrorIn("const pointField& polyMesh::points() const")
924 << "points deallocated"
925 << abort(FatalError);
932 const Foam::faceList& Foam::polyMesh::faces() const
934 if (clearedPrimitives_)
936 FatalErrorIn("const faceList& polyMesh::faces() const")
937 << "faces deallocated"
938 << abort(FatalError);
945 const Foam::labelList& Foam::polyMesh::faceOwner() const
951 const Foam::labelList& Foam::polyMesh::faceNeighbour() const
957 // Return old mesh motion points
958 const Foam::pointField& Foam::polyMesh::oldPoints() const
964 WarningIn("const pointField& polyMesh::oldPoints() const")
965 << "Old points not available. Forcing storage of old points"
969 oldPointsPtr_ = new pointField(points_);
970 curMotionTimeIndex_ = time().timeIndex();
973 return *oldPointsPtr_;
977 Foam::tmp<Foam::scalarField> Foam::polyMesh::movePoints
979 const pointField& newPoints
984 Info<< "tmp<scalarField> polyMesh::movePoints(const pointField&) : "
985 << " Moving points for time " << time().value()
986 << " index " << time().timeIndex() << endl;
991 // Pick up old points
992 if (curMotionTimeIndex_ != time().timeIndex())
994 // Mesh motion in the new time step
995 deleteDemandDrivenData(oldPointsPtr_);
996 oldPointsPtr_ = new pointField(points_);
997 curMotionTimeIndex_ = time().timeIndex();
1000 points_ = newPoints;
1004 // Check mesh motion
1005 if (primitiveMesh::checkMeshMotion(points_, true))
1007 Info<< "tmp<scalarField> polyMesh::movePoints"
1008 << "(const pointField&) : "
1009 << "Moving the mesh with given points will "
1010 << "invalidate the mesh." << nl
1011 << "Mesh motion should not be executed." << endl;
1015 points_.writeOpt() = IOobject::AUTO_WRITE;
1016 points_.instance() = time().timeName();
1019 tmp<scalarField> sweptVols = primitiveMesh::movePoints
1025 // Adjust parallel shared points
1026 if (globalMeshDataPtr_)
1028 globalMeshDataPtr_->movePoints(points_);
1031 // Force recalculation of all geometric data with new points
1033 bounds_ = boundBox(points_);
1034 boundary_.movePoints(points_);
1036 pointZones_.movePoints(points_);
1037 faceZones_.movePoints(points_);
1038 cellZones_.movePoints(points_);
1044 // Reset motion by deleting old points
1045 void Foam::polyMesh::resetMotion() const
1047 curMotionTimeIndex_ = 0;
1048 deleteDemandDrivenData(oldPointsPtr_);
1052 // Return parallel info
1053 const Foam::globalMeshData& Foam::polyMesh::globalData() const
1055 if (!globalMeshDataPtr_)
1059 Pout<< "polyMesh::globalData() const : "
1060 << "Constructing parallelData from processor topology" << nl
1061 << "This needs the patch faces to be correctly matched"
1064 // Construct globalMeshData using processorPatch information only.
1065 globalMeshDataPtr_ = new globalMeshData(*this);
1068 return *globalMeshDataPtr_;
1072 // Remove all files and some subdirs (eg, sets)
1073 void Foam::polyMesh::removeFiles(const fileName& instanceDir) const
1075 fileName meshFilesPath = db().path()/instanceDir/meshDir();
1077 rm(meshFilesPath/"points");
1078 rm(meshFilesPath/"faces");
1079 rm(meshFilesPath/"owner");
1080 rm(meshFilesPath/"neighbour");
1081 rm(meshFilesPath/"cells");
1082 rm(meshFilesPath/"boundary");
1083 rm(meshFilesPath/"pointZones");
1084 rm(meshFilesPath/"faceZones");
1085 rm(meshFilesPath/"cellZones");
1086 rm(meshFilesPath/"meshModifiers");
1087 rm(meshFilesPath/"parallelData");
1089 // remove subdirectories
1090 if (dir(meshFilesPath/"sets"))
1092 rmDir(meshFilesPath/"sets");
1096 void Foam::polyMesh::removeFiles() const
1098 removeFiles(instance());
1102 // ************************************************************************* //