diff --git a/applications/utilities/mesh/generation/extrudeToRegionMesh/createShellMesh.C b/applications/utilities/mesh/generation/extrudeToRegionMesh/createShellMesh.C index 944ff9cb48726bf01fd57bc17cc9c1106989898d..ffea6709521b973551b9b52ddea76dbebb4d622e 100644 --- a/applications/utilities/mesh/generation/extrudeToRegionMesh/createShellMesh.C +++ b/applications/utilities/mesh/generation/extrudeToRegionMesh/createShellMesh.C @@ -158,7 +158,6 @@ void Foam::createShellMesh::calcPointRegions } - // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::createShellMesh::createShellMesh @@ -184,7 +183,6 @@ Foam::createShellMesh::createShellMesh // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - void Foam::createShellMesh::setRefinement ( const pointField& thickness, diff --git a/applications/utilities/mesh/generation/extrudeToRegionMesh/extrudeToRegionMesh.C b/applications/utilities/mesh/generation/extrudeToRegionMesh/extrudeToRegionMesh.C index 6a3b7dd7eadd0a926c8dabc1b9823be7d101caeb..4cf3c67ff998f2f1f6b9f8146ef03dc0c59f6242 100644 --- a/applications/utilities/mesh/generation/extrudeToRegionMesh/extrudeToRegionMesh.C +++ b/applications/utilities/mesh/generation/extrudeToRegionMesh/extrudeToRegionMesh.C @@ -130,6 +130,7 @@ Usage #include "volFields.H" #include "surfaceFields.H" #include "cyclicPolyPatch.H" +#include "syncTools.H" using namespace Foam; @@ -595,6 +596,237 @@ void createDummyFvMeshFiles(const polyMesh& mesh, const word& regionName) } +//XXXXXXXXX +label findUncoveredPatchFace +( + const fvMesh& mesh, + const UIndirectList<label>& extrudeMeshFaces,// mesh faces that are extruded + const label meshEdgeI // mesh edge +) +{ + // Make set of extruded faces. + labelHashSet extrudeFaceSet(extrudeMeshFaces.size()); + forAll(extrudeMeshFaces, i) + { + extrudeFaceSet.insert(extrudeMeshFaces[i]); + } + + label patchI = -1; + + const labelList& eFaces = mesh.edgeFaces()[meshEdgeI]; + forAll(eFaces, i) + { + label faceI = eFaces[i]; + if (!mesh.isInternalFace(faceI) && !extrudeFaceSet.found(faceI)) + { + patchI = mesh.boundaryMesh().whichPatch(faceI); + break; + } + } + return patchI; +} +// Count the number of faces in patches that need to be created +void countExtrudePatches +( + const fvMesh& mesh, + const primitiveFacePatch& extrudePatch, + const label nZones, + const labelList& zoneID, + const labelList& extrudeMeshFaces, + const labelList& extrudeMeshEdges, + + labelList& zoneSidePatch, + labelList& zoneZonePatch +) +{ + const labelListList& edgeFaces = extrudePatch.edgeFaces(); + + forAll(edgeFaces, edgeI) + { + const labelList& eFaces = edgeFaces[edgeI]; + if (eFaces.size() == 2) + { + label zone0 = zoneID[eFaces[0]]; + label zone1 = zoneID[eFaces[1]]; + + if (zone0 != zone1) + { + label minZone = min(zone0,zone1); + label maxZone = max(zone0,zone1); + zoneZonePatch[minZone*nZones+maxZone]++; + } + } + else + { + // Check whether we are on a mesh edge with external patches. If + // so choose any uncovered one. If none found put face in + // undetermined zone 'side' patch + + label patchI = findUncoveredPatchFace + ( + mesh, + UIndirectList<label>(extrudeMeshFaces, eFaces), + extrudeMeshEdges[edgeI] + ); + + if (patchI == -1) + { + // Determine the min zone of all connected zones. + label minZone = zoneID[eFaces[0]]; + for (label i = 1; i < eFaces.size(); i++) + { + minZone = min(minZone, zoneID[eFaces[i]]); + } + zoneSidePatch[minZone]++; + } + } + } + Pstream::listCombineGather(zoneSidePatch, plusEqOp<label>()); + Pstream::listCombineScatter(zoneSidePatch); + Pstream::listCombineGather(zoneZonePatch, plusEqOp<label>()); + Pstream::listCombineScatter(zoneZonePatch); +} +bool lessThan(const point& x, const point& y) +{ + for (direction dir = 0; dir < point::nComponents; dir++) + { + if (x[dir] < y[dir]) return true; + if (x[dir] > y[dir]) return false; + } + return false; +} + +class minEqVectorListOp +{ + public: + void operator()(List<vector>& x, const List<vector>& y) const + { + if (y.size()) + { + if (x.size()) + { + forAll(x, i) + { + if (lessThan(y[i], x[i])) + { + x[i] = y[i]; + } + } + } + else + { + x = y; + } + } + } +}; +// Constrain&sync normals on points that are on coupled patches. +void constrainCoupledNormals +( + const fvMesh& mesh, + const primitiveFacePatch& extrudePatch, + const labelList& regionToPoint, + + vectorField& regionNormals +) +{ + // Invert regionToPoint to create pointToRegions. + labelListList pointToRegions + ( + invertOneToMany + ( + extrudePatch.nPoints(), + regionToPoint + ) + ); + // Sort acc. to region so (hopefully) coupled points will do the same. + forAll(pointToRegions, pointI) + { + sort(pointToRegions[pointI]); + } + + + const polyBoundaryMesh& patches = mesh.boundaryMesh(); + + // Constrain displacement on cyclic patches + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Note: bit contentious to always do this on cyclic - should user use + // different patch type, e.g. 'cyclicSlip' instead? + + forAll(patches, patchI) + { + const polyPatch& pp = patches[patchI]; + + if (isA<cyclicPolyPatch>(pp)) + { + forAll(pp.meshPoints(), pointI) + { + Map<label>::const_iterator fnd = + extrudePatch.meshPointMap().find + ( + pp.meshPoints()[pointI] + ); + if (fnd != extrudePatch.meshPointMap().end()) + { + // fnd() is a point on this cyclic. + const vector& cycNormal = pp.pointNormals()[pointI]; + const labelList& pRegions = pointToRegions[fnd()]; + forAll(pRegions, i) + { + // Remove cyclic normal component. + vector& regionNormal = regionNormals[pRegions[i]]; + regionNormal -= (regionNormal&cycNormal)*cycNormal; + } + } + } + } + } + + + // Synchronise regionNormals + // ~~~~~~~~~~~~~~~~~~~~~~~~~ + + // Re-work regionNormals into multiple normals per point + List<List<vector> > pointNormals(mesh.nPoints()); + forAll(pointToRegions, pointI) + { + const labelList& pRegions = pointToRegions[pointI]; + + label meshPointI = extrudePatch.meshPoints()[pointI]; + List<vector>& pNormals = pointNormals[meshPointI]; + pNormals.setSize(pRegions.size()); + forAll(pRegions, i) + { + pNormals[i] = regionNormals[pRegions[i]]; + } + } + + // Synchronise + syncTools::syncPointList + ( + mesh, + pointNormals, + minEqVectorListOp(), + List<vector>(), // nullValue + false // applySeparation + ); + + // Re-work back into regionNormals + forAll(pointToRegions, pointI) + { + const labelList& pRegions = pointToRegions[pointI]; + + label meshPointI = extrudePatch.meshPoints()[pointI]; + const List<vector>& pNormals = pointNormals[meshPointI]; + forAll(pRegions, i) + { + regionNormals[pRegions[i]] = pNormals[i]; + } + } +} +//XXXXXXXXX + + tmp<pointField> calcOffset ( const primitiveFacePatch& extrudePatch, @@ -739,6 +971,16 @@ int main(int argc, char *argv[]) << endl; + // Determine corresponding mesh edges + const labelList extrudeMeshEdges + ( + extrudePatch.meshEdges + ( + mesh.edges(), + mesh.pointEdges() + ) + ); + // Check whether the zone is internal or external faces to determine @@ -772,7 +1014,7 @@ int main(int argc, char *argv[]) Info<< "FaceZone " << fz.name() << " has boundary faces" << endl; } } - + Info<< endl; @@ -866,36 +1108,18 @@ int main(int argc, char *argv[]) labelList zoneSidePatch(faceZones.size(), 0); labelList zoneZonePatch(faceZones.size()*faceZones.size(), 0); - forAll(edgeFaces, edgeI) - { - const labelList& eFaces = edgeFaces[edgeI]; - if (eFaces.size() == 2) - { - label zone0 = zoneID[eFaces[0]]; - label zone1 = zoneID[eFaces[1]]; + countExtrudePatches + ( + mesh, + extrudePatch, + faceZones.size(), + zoneID, + extrudeMeshFaces, + extrudeMeshEdges, - if (zone0 != zone1) - { - label minZone = min(zone0,zone1); - label maxZone = max(zone0,zone1); - zoneZonePatch[minZone*faceZones.size()+maxZone]++; - } - } - else - { - // Determine the min zone of all connected zones. - label minZone = zoneID[eFaces[0]]; - for (label i = 1; i < eFaces.size(); i++) - { - minZone = min(minZone, zoneID[eFaces[i]]); - } - zoneSidePatch[minZone]++; - } - } - Pstream::listCombineGather(zoneSidePatch, plusEqOp<label>()); - Pstream::listCombineScatter(zoneSidePatch); - Pstream::listCombineGather(zoneZonePatch, plusEqOp<label>()); - Pstream::listCombineScatter(zoneZonePatch); + zoneSidePatch, + zoneZonePatch + ); // Now check which patches to add. Info<< "Adding patches for edges on zones:" << nl << nl @@ -980,6 +1204,7 @@ int main(int argc, char *argv[]) // Is edge an non-manifold edge PackedBoolList nonManifoldEdge(extrudePatch.nEdges()); + // Note: logic has to be same as in countExtrudePatches. forAll(edgeFaces, edgeI) { const labelList& eFaces = edgeFaces[edgeI]; @@ -1004,65 +1229,31 @@ int main(int argc, char *argv[]) } else { - ePatches.setSize(eFaces.size()); - forAll(eFaces, i) - { - ePatches[i] = zoneSidePatch[zoneID[eFaces[i]]]; - } - nonManifoldEdge[edgeI] = 1; - } - } - - // Override constraint types - { - const edgeList& extrudeEdges = extrudePatch.edges(); - const labelList& extrudeMeshPts = extrudePatch.meshPoints(); - - // Map from mesh edge to local patch edge index - EdgeMap<label> extrudeMeshEdges(extrudePatch.nEdges()); + label patchI = findUncoveredPatchFace + ( + mesh, + UIndirectList<label>(extrudeMeshFaces, eFaces), + extrudeMeshEdges[edgeI] + ); - forAll(extrudeEdges, edgeI) - { - if (edgeFaces[edgeI].size() == 1) + if (patchI != -1) { - const edge& e = extrudeEdges[edgeI]; - const edge meshE(extrudeMeshPts[e[0]], extrudeMeshPts[e[1]]); - extrudeMeshEdges.insert(meshE, edgeI); + ePatches.setSize(eFaces.size(), patchI); } - } - forAll(patches, patchI) - { - const polyPatch& pp = patches[patchI]; - - if (polyPatch::constraintType(pp.type())) + else { - const edgeList& edges = pp.edges(); - - forAll(edges, ppEdgeI) + ePatches.setSize(eFaces.size()); + forAll(eFaces, i) { - const edge& e = edges[ppEdgeI]; - edge meshE(pp.meshPoints()[e[0]], pp.meshPoints()[e[1]]); - EdgeMap<label>::const_iterator iter = extrudeMeshEdges.find - ( - meshE - ); - if (iter != extrudeMeshEdges.end()) - { - label extrudeEdgeI = iter(); - extrudeEdgePatches[extrudeEdgeI] = labelList - ( - edgeFaces[extrudeEdgeI].size(), - patchI - ); - } + ePatches[i] = zoneSidePatch[zoneID[eFaces[i]]]; } } + nonManifoldEdge[edgeI] = 1; } } - // Assign point regions // ~~~~~~~~~~~~~~~~~~~~ @@ -1075,6 +1266,7 @@ int main(int argc, char *argv[]) ( extrudePatch, nonManifoldEdge, + pointRegions, regionPoints ); @@ -1096,6 +1288,18 @@ int main(int argc, char *argv[]) } regionNormals /= mag(regionNormals); + + // Constrain&sync normals on points that are on coupled patches. + constrainCoupledNormals + ( + mesh, + extrudePatch, + regionPoints, + + regionNormals + ); + + // For debugging: dump hedgehog plot of normals { OFstream str(runTime.path()/"regionNormals.obj"); @@ -1112,7 +1316,7 @@ int main(int argc, char *argv[]) meshTools::writeOBJ(str, pt); vertI++; - meshTools::writeOBJ(str, pt+0.01*regionNormals[region]); + meshTools::writeOBJ(str, pt+thickness*regionNormals[region]); vertI++; str << "l " << vertI-1 << ' ' << vertI << nl; }