//- Calculate the offset to the next layer Foam::tmp<Foam::vectorField> Foam::layerAdditionRemovalMC::extrusionDir() const { const polyMesh& mesh = topoChanger().mesh(); const primitiveFacePatch& masterFaceLayer = mesh.faceZones()[faceZoneID_.index()](); const pointField& points = mesh.points(); const labelList& mp = masterFaceLayer.meshPoints(); tmp<vectorField> textrusionDir(new vectorField(mp.size())); vectorField& extrusionDir = textrusionDir(); if (setLayerPairing()) { if (debug) { Pout<< "void layerAdditionRemovalMC::extrusionDir() const " << " for object " << name() << " : " << "Using edges for point insertion" << endl; } // Detected a valid layer. Grab the point and face collapse mapping const labelList& ptc = pointsPairing(); forAll(extrusionDir, mpI) { extrusionDir[mpI] = points[ptc[mpI]] - points[mp[mpI]]; } }
void Foam::layerAdditionRemoval::addCellLayer ( polyTopoChange& ref ) const { // Insert the layer addition instructions into the topological change // Algorithm: // 1. For every point in the master zone add a new point // 2. For every face in the master zone add a cell // 3. Go through all the edges of the master zone. For all internal // edges, add a face with the correct orientation and make it internal. // For all boundary edges, find the patch it belongs to and add the // face to this patch // 4. Create a set of new faces on the patch image and assign them to be // between the old master cells and the newly created cells // 5. Modify all the faces in the patch such that they are located // between the old slave cells and newly created cells if (debug) { Pout<< "void layerAdditionRemoval::addCellLayer(" << "polyTopoChange& ref) const for object " << name() << " : " << "Adding cell layer" << endl; } // Create the points const polyMesh& mesh = topoChanger().mesh(); const primitiveFacePatch& masterFaceLayer = mesh.faceZones()[faceZoneID_.index()](); const pointField& points = mesh.points(); const labelList& mp = masterFaceLayer.meshPoints(); // Calculation of point normals, using point pairing vectorField extrusionDir(mp.size()); if (setLayerPairing()) { if (debug) { Pout<< "void layerAdditionRemoval::addCellLayer(" << "polyTopoChange& ref) const " << " for object " << name() << " : " << "Using edges for point insertion" << endl; } // Detected a valid layer. Grab the point and face collapse mapping const labelList& ptc = pointsPairing(); forAll (extrusionDir, mpI) { extrusionDir[mpI] = points[ptc[mpI]] - points[mp[mpI]]; } extrusionDir *= addDelta_*maxLayerThickness_; }
void Foam::repatchCoverage::updateMesh(const mapPolyMesh&) { // Mesh has changed topologically. Update local topological data const polyMesh& mesh = topoChanger().mesh(); masterCoveredPatchID_.update(mesh.boundaryMesh()); masterUncoveredPatchID_.update(mesh.boundaryMesh()); slaveCoveredPatchID_.update(mesh.boundaryMesh()); slaveUncoveredPatchID_.update(mesh.boundaryMesh()); }
bool Foam::layerAdditionRemoval::changeTopology() const { // Protect from multiple calculation in the same time-step if (triggerRemoval_ > -1 || triggerAddition_ > -1) { return true; } // Go through all the cells in the master layer and calculate // approximate layer thickness as the ratio of the cell volume and // face area in the face zone. // Layer addition: // When the max thickness exceeds the threshold, trigger refinement. // Layer removal: // When the min thickness falls below the threshold, trigger removal. const faceZone& fz = topoChanger().mesh().faceZones()[faceZoneID_.index()]; const labelList& mc = fz.masterCells(); const scalarField& V = topoChanger().mesh().cellVolumes(); const vectorField& S = topoChanger().mesh().faceAreas(); if (min(V) < -VSMALL) { FatalErrorIn("bool layerAdditionRemoval::changeTopology() const") << "negative cell volume. Error in mesh motion before " << "topological change.\n V: " << V << abort(FatalError); } scalar avgDelta = 0; scalar minDelta = GREAT; scalar maxDelta = 0; forAll (fz, faceI) { scalar curDelta = V[mc[faceI]]/mag(S[fz[faceI]]); avgDelta += curDelta; minDelta = min(minDelta, curDelta); maxDelta = max(maxDelta, curDelta); }
void Foam::attachDetach::attachInterface ( polyTopoChange& ref ) const { // Algorithm: // 1. Create the reverse patch out of the slave faces. // 2. Go through all the mesh points from the master and slave patch. // If the point labels are different, insert them into the point // renumbering list and remove them from the mesh. // 3. Remove all faces from the slave patch // 4. Modify all the faces from the master patch by making them internal // between the faceCell cells for the two patches. If the master owner // is higher than the slave owner, turn the face around // 5. Get all the faces attached to the slave patch points. // If they have not been removed, renumber them using the // point renumbering list. if (debug) { Pout<< "void attachDetach::attachInterface(" << "polyTopoChange& ref) const " << " for object " << name() << " : " << "Attaching interface" << endl; } const polyMesh& mesh = topoChanger().mesh(); const faceList& faces = mesh.faces(); const labelList& own = mesh.faceOwner(); const labelList& nei = mesh.faceNeighbour(); const polyPatch& masterPatch = mesh.boundaryMesh()[masterPatchID_.index()]; const polyPatch& slavePatch = mesh.boundaryMesh()[slavePatchID_.index()]; const label masterPatchStart = masterPatch.start(); const label slavePatchStart = slavePatch.start(); const labelList& slaveMeshPoints = slavePatch.meshPoints(); const Map<label>& removedPointMap = pointMatchMap(); const labelList removedPoints = removedPointMap.toc(); forAll (removedPoints, pointI) { ref.setAction(polyRemovePoint(removedPoints[pointI])); }
bool Foam::layerAdditionRemoval::validCollapse() const { // Check for valid layer collapse // - no boundary-to-boundary collapse if (debug) { Pout<< "Checking layer collapse for object " << name() << endl; } // Grab the face collapse mapping const polyMesh& mesh = topoChanger().mesh(); const labelList& ftc = facesPairing(); const labelList& mf = mesh.faceZones()[faceZoneID_.index()]; label nBoundaryHits = 0; forAll(mf, facei) { if ( !mesh.isInternalFace(mf[facei]) && !mesh.isInternalFace(ftc[facei]) ) { nBoundaryHits++; } } if (debug) { Pout<< "Finished checking layer collapse for object " << name() <<". Number of boundary-on-boundary hits: " << nBoundaryHits << endl; } if (returnReduce(nBoundaryHits, sumOp<label>()) > 0) { return false; } else { return true; } }
void Foam::layerAdditionRemoval::removeCellLayer ( polyTopoChange& ref ) const { // Algorithm for layer removal. Second phase: topological change // 2) Go through all the faces of the master cell layer and remove // the ones that are not in the master face zone. // // 3) Grab all the faces coming out of points that are collapsed // and select the ones that are not marked for removal. Go // through the remaining faces and replace the point to remove by // the equivalent point in the master face zone. if (debug) { Pout<< "Removing the cell layer for object " << name() << endl; } const polyMesh& mesh = topoChanger().mesh(); const labelList& own = mesh.faceOwner(); const labelList& nei = mesh.faceNeighbour(); const labelList& ptc = pointsPairing(); const labelList& ftc = facesPairing(); // Remove all the cells from the master layer const labelList& mc = mesh.faceZones()[faceZoneID_.index()].masterCells(); forAll(mc, facei) { label slaveSideCell = own[ftc[facei]]; if (mesh.isInternalFace(ftc[facei]) && slaveSideCell == mc[facei]) { // Owner cell of the face is being removed. // Grab the neighbour instead slaveSideCell = nei[ftc[facei]]; } ref.setAction(polyRemoveCell(mc[facei], slaveSideCell)); }
void Foam::layerAdditionRemoval::checkDefinition() { if (!faceZoneID_.active()) { FatalErrorIn ( "void Foam::layerAdditionRemoval::checkDefinition()" ) << "Master face zone named " << faceZoneID_.name() << " cannot be found." << abort(FatalError); } if ( minLayerThickness_ < VSMALL || maxLayerThickness_ < minLayerThickness_ ) { FatalErrorIn ( "void Foam::layerAdditionRemoval::checkDefinition()" ) << "Incorrect layer thickness definition." << abort(FatalError); } if (topoChanger().mesh().faceZones()[faceZoneID_.index()].empty()) { FatalErrorIn ( "void Foam::layerAdditionRemoval::checkDefinition()" ) << "Face extrusion zone contains no faces. " << " Please check your mesh definition." << abort(FatalError); } if (debug) { Pout<< "Cell layer addition/removal object " << name() << " :" << nl << " faceZoneID: " << faceZoneID_ << endl; } }
void Foam::slidingInterface::clearCouple ( polyTopoChange& ref ) const { if (debug) { Pout<< "void slidingInterface::clearCouple(" << "polyTopoChange& ref) const for object " << name() << " : " << "Clearing old couple points and faces." << endl; } // Remove all points from the point zone const polyMesh& mesh = topoChanger().mesh(); const labelList& cutPointZoneLabels = mesh.pointZones()[cutPointZoneID_.index()]; forAll(cutPointZoneLabels, pointI) { ref.setAction(polyRemovePoint(cutPointZoneLabels[pointI])); }
void Foam::faceCracker::detachFaceCracker ( polyTopoChange& ref ) const { if (debug) { Pout<< "void faceCracker::detachFaceCracker(" << "polyTopoChange& ref) const " << " for object " << name() << " : " << "Detaching faces" << endl; } const polyMesh& mesh = topoChanger().mesh(); const faceZoneMesh& zoneMesh = mesh.faceZones(); const primitiveFacePatch& masterFaceLayer = zoneMesh[crackZoneID_.index()](); const pointField& points = mesh.points(); const labelListList& meshEdgeFaces = mesh.edgeFaces(); const labelList& mp = masterFaceLayer.meshPoints(); const edgeList& zoneLocalEdges = masterFaceLayer.edges(); const labelList& meshEdges = zoneMesh[crackZoneID_.index()].meshEdges(); // Create the points labelList addedPoints(mp.size(), -1); // Go through boundary edges of the master patch. If all the faces from // this patch are internal, mark the points in the addedPoints lookup // with their original labels to stop duplication label nIntEdges = masterFaceLayer.nInternalEdges(); for ( label curEdgeID = nIntEdges; curEdgeID < meshEdges.size(); curEdgeID++ ) { const labelList& curFaces = meshEdgeFaces[meshEdges[curEdgeID]]; bool edgeIsInternal = true; forAll (curFaces, faceI) { if (!mesh.isInternalFace(curFaces[faceI])) { // The edge belongs to a boundary face edgeIsInternal = false; break; } } if (edgeIsInternal) { // Reset the point creation addedPoints[zoneLocalEdges[curEdgeID].start()] = mp[zoneLocalEdges[curEdgeID].start()]; addedPoints[zoneLocalEdges[curEdgeID].end()] = mp[zoneLocalEdges[curEdgeID].end()]; } } // Create new points for face zone forAll (addedPoints, pointI) { if (addedPoints[pointI] < 0) { addedPoints[pointI] = ref.setAction ( polyAddPoint ( points[mp[pointI]], // point mp[pointI], // master point -1, // zone ID true // supports a cell ) ); } } // Modify faces in the master zone and duplicate for the slave zone const labelList& mf = zoneMesh[crackZoneID_.index()]; const boolList& mfFlip = zoneMesh[crackZoneID_.index()].flipMap(); const faceList& zoneFaces = masterFaceLayer.localFaces(); const faceList& faces = mesh.faces(); const labelList& own = mesh.faceOwner(); const labelList& nei = mesh.faceNeighbour(); forAll (mf, faceI) { const label curFaceID = mf[faceI]; // Build the face for the slave patch by renumbering const face oldFace = zoneFaces[faceI].reverseFace(); face newFace(oldFace.size()); forAll (oldFace, pointI) { newFace[pointI] = addedPoints[oldFace[pointI]]; } if (mfFlip[faceI]) { // Face needs to be flipped for the master patch ref.setAction ( polyModifyFace ( faces[curFaceID].reverseFace(), // modified face curFaceID, // label of face being modified nei[curFaceID], // owner -1, // neighbour true, // face flip crackPatchID_.index(), // patch for face false, // remove from zone crackZoneID_.index(), // zone for face !mfFlip[faceI] // face flip in zone ) ); // Add renumbered face into the slave patch ref.setAction ( polyAddFace ( newFace, // face own[curFaceID], // owner -1, // neighbour -1, // master point -1, // master edge curFaceID, // master face false, // flip flux crackPatchID_.index(), // patch to add the face to -1, // zone for face false // zone flip ) ); } else { // No flip ref.setAction ( polyModifyFace ( faces[curFaceID], // modified face curFaceID, // label of face being modified own[curFaceID], // owner -1, // neighbour false, // face flip crackPatchID_.index(), // patch for face false, // remove from zone crackZoneID_.index(), // zone for face mfFlip[faceI] // face flip in zone ) ); // Add renumbered face into the slave patch ref.setAction ( polyAddFace ( newFace, // face nei[curFaceID], // owner -1, // neighbour -1, // master point -1, // master edge curFaceID, // master face true, // flip flux crackPatchID_.index(), // patch to add the face to -1, // zone for face false // face flip in zone ) ); } } // Modify the remaining faces of the master cells to reconnect to the new // layer of faces. // Algorithm: Go through all the cells of the master zone and make // a map of faces to avoid duplicates. Do not insert the faces in // the master patch (as they have already been dealt with). Make // a master layer point renumbering map, which for every point in // the master layer gives its new label. Loop through all faces in // the map and attempt to renumber them using the master layer // point renumbering map. Once the face is renumbered, compare it // with the original face; if they are the same, the face has not // changed; if not, modify the face but keep all of its old // attributes (apart from the vertex numbers). // Create the map of faces in the master cell layer // Bug-fix: PC, HJ and ZT, 19 Feb 2013 labelHashSet masterCellFaceMap(12*mf.size()); const labelListList& pointFaces = mesh.pointFaces(); forAll(mf, faceI) { const labelList& curFacePoints = faces[mf[faceI]]; forAll(curFacePoints, pointI) { const labelList& curPointFaces = pointFaces[curFacePoints[pointI]]; forAll(curPointFaces, fI) { if ( zoneMesh.whichZone(curPointFaces[fI]) != crackZoneID_.index() ) { masterCellFaceMap.insert(curPointFaces[fI]); } } } } // // Create the map of faces in the master cell layer // const labelList& mc = // mesh.faceZones()[crackZoneID_.index()].masterCells(); // labelHashSet masterCellFaceMap(6*mc.size()); // const cellList& cells = mesh.cells(); // forAll (mc, cellI) // { // const labelList& curFaces = cells[mc[cellI]]; // forAll (curFaces, faceI) // { // // Check if the face belongs to the master patch; if not add it // if (zoneMesh.whichZone(curFaces[faceI]) != crackZoneID_.index()) // { // masterCellFaceMap.insert(curFaces[faceI]); // } // } // } // // Extend the map to include first neighbours of the master cells to // // deal with multiple corners. // { // Protection and memory management // // Make a map of master cells for quick reject // labelHashSet mcMap(2*mc.size()); // forAll (mc, mcI) // { // mcMap.insert(mc[mcI]); // } // // Go through all the faces in the masterCellFaceMap. If the // // cells around them are not already used, add all of their // // faces to the map // const labelList mcf = masterCellFaceMap.toc(); // forAll (mcf, mcfI) // { // // Do the owner side // const label ownCell = own[mcf[mcfI]]; // if (!mcMap.found(ownCell)) // { // // Cell not found. Add its faces to the map // const cell& curFaces = cells[ownCell]; // forAll (curFaces, faceI) // { // masterCellFaceMap.insert(curFaces[faceI]); // } // } // // Do the neighbour side if face is internal // if (mesh.isInternalFace(mcf[mcfI])) // { // const label neiCell = nei[mcf[mcfI]]; // if (!mcMap.found(neiCell)) // { // // Cell not found. Add its faces to the map // const cell& curFaces = cells[neiCell]; // forAll (curFaces, faceI) // { // masterCellFaceMap.insert(curFaces[faceI]); // } // } // } // } // } // Create the master layer point map Map<label> masterLayerPointMap(2*mp.size()); forAll (mp, pointI) { masterLayerPointMap.insert ( mp[pointI], addedPoints[pointI] ); }
bool Foam::slidingInterface::projectPoints() const { if (debug) { Pout<< "bool slidingInterface::projectPoints() : " << " for object " << name() << " : " << "Projecting slave points onto master surface." << endl; } // Algorithm: // 1) Go through all the points of the master and slave patch and calculate // minimum edge length coming from the point. Calculate the point // merge tolerance as the fraction of mimimum edge length. // 2) Project all the slave points onto the master patch // in the normal direction. // 3) If some points have missed and the match is integral, the // points in question will be adjusted. Find the nearest face for // those points and continue with the procedure. // 4) For every point, check all the points of the face it has hit. // For every pair of points find if their distance is smaller than // both the master and slave merge tolerance. If so, the slave point // is moved to the location of the master point. Remember the master // point index. // 5) For every unmerged slave point, check its distance to all the // edges of the face it has hit. If the distance is smaller than the // edge merge tolerance, the point will be moved onto the edge. // Remember the master edge index. // 6) The remaning slave points will be projected into faces. Remember the // master face index. // 7) For the points that miss the master patch, grab the nearest face // on the master and leave the slave point where it started // from and the miss is recorded. const polyMesh& mesh = topoChanger().mesh(); const primitiveFacePatch& masterPatch = mesh.faceZones()[masterFaceZoneID_.index()](); const primitiveFacePatch& slavePatch = mesh.faceZones()[slaveFaceZoneID_.index()](); // Get references to local points, local edges and local faces // for master and slave patch // const labelList& masterMeshPoints = masterPatch.meshPoints(); const pointField& masterLocalPoints = masterPatch.localPoints(); const faceList& masterLocalFaces = masterPatch.localFaces(); const edgeList& masterEdges = masterPatch.edges(); const labelListList& masterEdgeFaces = masterPatch.edgeFaces(); const labelListList& masterFaceEdges = masterPatch.faceEdges(); const labelListList& masterFaceFaces = masterPatch.faceFaces(); // Pout<< "Master patch. Local points: " << masterLocalPoints << nl // << "Master patch. Mesh points: " << masterPatch.meshPoints() << nl // << "Local faces: " << masterLocalFaces << nl // << "local edges: " << masterEdges << endl; // const labelList& slaveMeshPoints = slavePatch.meshPoints(); const pointField& slaveLocalPoints = slavePatch.localPoints(); const edgeList& slaveEdges = slavePatch.edges(); const labelListList& slaveEdgeFaces = slavePatch.edgeFaces(); const vectorField& slavePointNormals = slavePatch.pointNormals(); // const vectorField& slaveFaceNormals = slavePatch.faceNormals(); // Pout<< "Slave patch. Local points: " << slaveLocalPoints << nl // << "Slave patch. Mesh points: " << slavePatch.meshPoints() << nl // << "Local faces: " << slavePatch.localFaces() << nl // << "local edges: " << slaveEdges << endl; // Calculate min edge distance for points and faces // Calculate min edge length for the points and faces of master patch scalarField minMasterPointLength(masterLocalPoints.size(), GREAT); scalarField minMasterFaceLength(masterPatch.size(), GREAT); forAll(masterEdges, edgeI) { const edge& curEdge = masterEdges[edgeI]; const scalar curLength = masterEdges[edgeI].mag(masterLocalPoints); // Do points minMasterPointLength[curEdge.start()] = min ( minMasterPointLength[curEdge.start()], curLength ); minMasterPointLength[curEdge.end()] = min ( minMasterPointLength[curEdge.end()], curLength ); // Do faces const labelList& curFaces = masterEdgeFaces[edgeI]; forAll(curFaces, faceI) { minMasterFaceLength[curFaces[faceI]] = min ( minMasterFaceLength[curFaces[faceI]], curLength ); } }
bool Foam::layerAdditionRemoval::setLayerPairing() const { // Note: // This is also the most complex part of the topological change. // Therefore it will be calculated here and stored as temporary // data until the actual topological change, after which it will // be cleared. // Algorithm for point collapse // 1) Go through the master cell layer and for every face of // the face zone find the opposite face in the master cell. // Check the direction of the opposite face and adjust as // necessary. Check other faces to find an edge defining // relative orientation of the two faces and adjust the face // as necessary. Once the face is adjusted, record the // addressing between the master and slave vertex layer. const polyMesh& mesh = topoChanger().mesh(); const labelList& mc = mesh.faceZones()[faceZoneID_.index()].masterCells(); const labelList& mf = mesh.faceZones()[faceZoneID_.index()]; const boolList& mfFlip = mesh.faceZones()[faceZoneID_.index()].flipMap(); const faceList& faces = mesh.faces(); const cellList& cells = mesh.cells(); // Grab the local faces from the master zone const faceList& mlf = mesh.faceZones()[faceZoneID_.index()]().localFaces(); const labelList& meshPoints = mesh.faceZones()[faceZoneID_.index()]().meshPoints(); // Create a list of points to collapse for every point of // the master patch if (pointsPairingPtr_ || facesPairingPtr_) { FatalErrorIn ( "void Foam::layerAdditionRemoval::setLayerPairing() const" ) << "Problem with layer pairing data" << abort(FatalError); } pointsPairingPtr_ = new labelList(meshPoints.size(), -1); labelList& ptc = *pointsPairingPtr_; facesPairingPtr_ = new labelList(mf.size(), -1); labelList& ftc = *facesPairingPtr_; // Pout<< "meshPoints: " << meshPoints << nl // << "localPoints: " // << mesh.faceZones()[faceZoneID_.index()]().localPoints() // << endl; // For all faces, create the mapping label nPointErrors = 0; label nFaceErrors = 0; forAll(mf, faceI) { // Get the local master face face curLocalFace = mlf[faceI]; // Flip face based on flip index to recover original orientation if (mfFlip[faceI]) { curLocalFace.flip(); } // Get the opposing face from the master cell oppositeFace lidFace = cells[mc[faceI]].opposingFace(mf[faceI], faces); if (!lidFace.found()) { // This is not a valid layer; cannot continue nFaceErrors++; continue; } // Pout<< "curMasterFace: " << faces[mf[faceI]] << nl // << "cell shape: " << mesh.cellShapes()[mc[faceI]] << nl // << "curLocalFace: " << curLocalFace << nl // << "lidFace: " << lidFace // << " master index: " << lidFace.masterIndex() // << " oppositeIndex: " << lidFace.oppositeIndex() << endl; // Grab the opposite face for face collapse addressing ftc[faceI] = lidFace.oppositeIndex(); // Using the local face insert the points into the lid list forAll(curLocalFace, pointI) { const label clp = curLocalFace[pointI]; if (ptc[clp] == -1) { // Point not mapped yet. Insert the label ptc[clp] = lidFace[pointI]; } else { // Point mapped from some other face. Check the label if (ptc[clp] != lidFace[pointI]) { nPointErrors++; // Pout<< "Topological error in cell layer pairing. " // << "This mesh is either topologically incorrect " // << "or the master afce layer is not defined " // << "consistently. Please check the " // << "face zone flip map." << nl // << "First index: " << ptc[clp] // << " new index: " << lidFace[pointI] << endl; } } } // Pout<< "ptc: " << ptc << endl; }
void Foam::attachDetach::checkDefinition() { if ( !faceZoneID_.active() || !masterPatchID_.active() || !slavePatchID_.active() ) { FatalErrorInFunction << "Not all zones and patches needed in the definition " << "have been found. Please check your mesh definition." << abort(FatalError); } const polyMesh& mesh = topoChanger().mesh(); if (debug) { Pout<< "Attach/detach object " << name() << " :" << nl << " faceZoneID: " << faceZoneID_ << nl << " masterPatchID: " << masterPatchID_ << nl << " slavePatchID: " << slavePatchID_ << endl; } // Check the sizes and set up state if ( mesh.boundaryMesh()[masterPatchID_.index()].empty() && mesh.boundaryMesh()[slavePatchID_.index()].empty() ) { // Boundary is attached if (debug) { Pout<< " Attached on construction" << endl; } state_ = ATTACHED; // Check if there are faces in the master zone if (mesh.faceZones()[faceZoneID_.index()].empty()) { FatalErrorInFunction << "mesh definition." << abort(FatalError); } // Check that all the faces in the face zone are internal if (debug) { const labelList& addr = mesh.faceZones()[faceZoneID_.index()]; DynamicList<label> bouFacesInZone(addr.size()); forAll(addr, facei) { if (!mesh.isInternalFace(addr[facei])) { bouFacesInZone.append(addr[facei]); } } if (bouFacesInZone.size()) { FatalErrorInFunction << "Found boundary faces in the zone defining " << "attach/detach boundary " << " for object " << name() << " : . This is not allowed." << nl << "Boundary faces: " << bouFacesInZone << abort(FatalError); } } } else { // Boundary is detached if (debug)
bool Foam::repatchCoverage::changeTopology() const { // Check that masks are empty if (!uncMaster_.empty() || !uncSlave_.empty()) { FatalErrorIn("bool repatchCoverage::changeTopology() const") << "Uncovered masks are not empty. Topo change is out of sync" << abort(FatalError); } // Get mesh reference const polyMesh& mesh = topoChanger().mesh(); const pointField& allPoints = mesh.allPoints(); const faceList& allFaces = mesh.allFaces(); // Collect all faces for interpolation // Master side const polyPatch& masterCoveredPatch = mesh.boundaryMesh()[masterCoveredPatchID_.index()]; const polyPatch& masterUncoveredPatch = mesh.boundaryMesh()[masterUncoveredPatchID_.index()]; faceList masterSide ( masterCoveredPatch.size() + masterUncoveredPatch.size() ); { label nFaces = 0; // Insert covered faces for ( label faceI = masterCoveredPatch.start(); faceI < masterCoveredPatch.start() + masterCoveredPatch.size(); faceI++ ) { masterSide[nFaces] = allFaces[faceI]; nFaces++; } // Insert uncovered faces for ( label faceI = masterUncoveredPatch.start(); faceI < masterUncoveredPatch.start() + masterUncoveredPatch.size(); faceI++ ) { masterSide[nFaces] = allFaces[faceI]; nFaces++; } } // Slave side const polyPatch& slaveCoveredPatch = mesh.boundaryMesh()[slaveCoveredPatchID_.index()]; const polyPatch& slaveUncoveredPatch = mesh.boundaryMesh()[slaveUncoveredPatchID_.index()]; faceList slaveSide ( slaveCoveredPatch.size() + slaveUncoveredPatch.size() ); { label nFaces = 0; // Insert covered faces for ( label faceI = slaveCoveredPatch.start(); faceI < slaveCoveredPatch.start() + slaveCoveredPatch.size(); faceI++ ) { slaveSide[nFaces] = allFaces[faceI]; nFaces++; } // Insert uncovered faces for ( label faceI = slaveUncoveredPatch.start(); faceI < slaveUncoveredPatch.start() + slaveUncoveredPatch.size(); faceI++ ) { slaveSide[nFaces] = allFaces[faceI]; nFaces++; } } // Create interpolator primitiveFacePatch master(masterSide, allPoints); primitiveFacePatch slave(slaveSide, allPoints); if ( Pstream::parRun() && ( (masterSide.empty() && !slaveSide.empty()) || (!masterSide.empty() && slaveSide.empty()) ) ) { FatalErrorIn("bool repatchCoverage::changeTopology() const") << "Parallel run with partial visibility" << abort(FatalError); } if (masterSide.empty() && slaveSide.empty()) { // Empty master and slave patches. No local topo change return false; } GGIInterpolation<primitiveFacePatch, primitiveFacePatch> patchToPatch ( master, slave, tensorField::zero, // forwardT tensorField::zero, // reverseT vectorField::zero // separation ); // Check uncovered master and slave faces // Check uncovered master faces // All faces between 0 and masterCoveredPatch.size() - 1 should be covered // All faces between masterCoveredPatch.size() - 1 and // uncoveredMaster.size() - 1 should be uncovered // If this is not the case, faces should be changed // Master side label nMasterChanges = 0; { // Set size of uncovered master mask. This indicates a topo change // is in preparation uncMaster_.setSize(master.size(), false); const labelList& umf = patchToPatch.uncoveredMasterFaces(); forAll(umf, umfI) { uncMaster_[umf[umfI]] = true; } // Check coverage forAll (uncMaster_, mfI) { if (uncMaster_[mfI] && mfI < masterCoveredPatch.size()) { // Found uncovered master in covered section nMasterChanges++; } if (!uncMaster_[mfI] && mfI >= masterCoveredPatch.size()) { // Found covered master in uncovered section nMasterChanges++; } } } // Slave side label nSlaveChanges = 0; { // Set size of uncovered master mask. This indicates a topo change // is in preparation uncSlave_.setSize(slave.size(), false); const labelList& umf = patchToPatch.uncoveredSlaveFaces(); forAll(umf, umfI) { uncSlave_[umf[umfI]] = true; } // Check coverage forAll (uncSlave_, mfI) { if (uncSlave_[mfI] && mfI < slaveCoveredPatch.size()) { // Found uncovered slave in covered section nSlaveChanges++; } if (!uncSlave_[mfI] && mfI >= slaveCoveredPatch.size()) { // Found covered slave in uncovered section nSlaveChanges++; } } } if (nMasterChanges > 0 || nSlaveChanges > 0) { InfoIn("bool repatchCoverage::changeTopology() const") << "Changing " << nMasterChanges << " master and " << nSlaveChanges << " slave faces" << endl; return true; } else { // Clear uncovered masks to indicate that the topological change // is not required uncMaster_.clear(); uncSlave_.clear(); return false; } }
void Foam::slidingInterface::calcAttachedAddressing() const { if (debug) { Pout<< "void Foam::slidingInterface::calcAttachedAddressing() const " << " for object " << name() << " : " << "Calculating zone face-cell addressing." << endl; } if (!attached_) { // Clear existing addressing clearAttachedAddressing(); const polyMesh& mesh = topoChanger().mesh(); const labelList& own = mesh.faceOwner(); const labelList& nei = mesh.faceNeighbour(); const faceZoneMesh& faceZones = mesh.faceZones(); // Master side const primitiveFacePatch& masterPatch = faceZones[masterFaceZoneID_.index()](); const labelList& masterPatchFaces = faceZones[masterFaceZoneID_.index()]; const boolList& masterFlip = faceZones[masterFaceZoneID_.index()].flipMap(); masterFaceCellsPtr_ = new labelList(masterPatchFaces.size()); labelList& mfc = *masterFaceCellsPtr_; forAll (masterPatchFaces, faceI) { if (masterFlip[faceI]) { mfc[faceI] = nei[masterPatchFaces[faceI]]; } else { mfc[faceI] = own[masterPatchFaces[faceI]]; } } // Slave side const primitiveFacePatch& slavePatch = faceZones[slaveFaceZoneID_.index()](); const labelList& slavePatchFaces = faceZones[slaveFaceZoneID_.index()]; const boolList& slaveFlip = faceZones[slaveFaceZoneID_.index()].flipMap(); slaveFaceCellsPtr_ = new labelList(slavePatchFaces.size()); labelList& sfc = *slaveFaceCellsPtr_; forAll (slavePatchFaces, faceI) { if (slaveFlip[faceI]) { sfc[faceI] = nei[slavePatchFaces[faceI]]; } else { sfc[faceI] = own[slavePatchFaces[faceI]]; } } // Check that the addressing is valid if (min(mfc) < 0 || min(sfc) < 0) { if (debug) { forAll (mfc, faceI) { if (mfc[faceI] < 0) { Pout << "No cell next to master patch face " << faceI << ". Global face no: " << mfc[faceI] << " own: " << own[masterPatchFaces[faceI]] << " nei: " << nei[masterPatchFaces[faceI]] << " flip: " << masterFlip[faceI] << endl; } } forAll (sfc, faceI) { if (sfc[faceI] < 0) { Pout << "No cell next to slave patch face " << faceI << ". Global face no: " << sfc[faceI] << " own: " << own[slavePatchFaces[faceI]] << " nei: " << nei[slavePatchFaces[faceI]] << " flip: " << slaveFlip[faceI] << endl; } } } FatalErrorIn ( "void slidingInterface::calcAttachedAddressing()" "const" ) << "Error is zone face-cell addressing. Probable error in " << "decoupled mesh or sliding interface definition." << abort(FatalError); } // Calculate stick-out faces const labelListList& pointFaces = mesh.pointFaces(); // Master side labelHashSet masterStickOutFaceMap ( primitiveMesh::facesPerCell_*(masterPatch.size()) ); const labelList& masterMeshPoints = masterPatch.meshPoints(); forAll (masterMeshPoints, pointI) { const labelList& curFaces = pointFaces[masterMeshPoints[pointI]]; forAll (curFaces, faceI) { // Check if the face belongs to the master face zone; // if not add it if ( faceZones.whichZone(curFaces[faceI]) != masterFaceZoneID_.index() ) { masterStickOutFaceMap.insert(curFaces[faceI]); } } } masterStickOutFacesPtr_ = new labelList(masterStickOutFaceMap.toc()); // Slave side labelHashSet slaveStickOutFaceMap ( primitiveMesh::facesPerCell_*(slavePatch.size()) ); const labelList& slaveMeshPoints = slavePatch.meshPoints(); forAll (slaveMeshPoints, pointI) { const labelList& curFaces = pointFaces[slaveMeshPoints[pointI]]; forAll (curFaces, faceI) { // Check if the face belongs to the slave face zone; // if not add it if ( faceZones.whichZone(curFaces[faceI]) != slaveFaceZoneID_.index() ) { slaveStickOutFaceMap.insert(curFaces[faceI]); } } } slaveStickOutFacesPtr_ = new labelList(slaveStickOutFaceMap.toc()); // Retired point addressing does not exist at this stage. // It will be filled when the interface is coupled. retiredPointMapPtr_ = new Map<label> ( 2*faceZones[slaveFaceZoneID_.index()]().nPoints() ); // Ditto for cut point edge map. This is a rough guess of its size // cutPointEdgePairMapPtr_ = new Map<Pair<edge> > ( faceZones[slaveFaceZoneID_.index()]().nEdges() ); }
void Foam::repatchCoverage::setRefinement(polyTopoChange& ref) const { // Get mesh reference const polyMesh& mesh = topoChanger().mesh(); const faceList& allFaces = mesh.allFaces(); const faceZoneMesh& faceZones = mesh.faceZones(); const labelList& owner = mesh.faceOwner(); // Master side { // Get master patches const polyPatch& masterCoveredPatch = mesh.boundaryMesh()[masterCoveredPatchID_.index()]; const label cStart = masterCoveredPatch.start(); const label cSize = masterCoveredPatch.size(); const polyPatch& masterUncoveredPatch = mesh.boundaryMesh()[masterUncoveredPatchID_.index()]; const label uncStart = masterUncoveredPatch.start(); // Adjust coverage forAll (uncMaster_, faceI) { if (uncMaster_[faceI] && faceI < masterCoveredPatch.size()) { // Found uncovered face in covered section // Get face index const label faceIndex = cStart + faceI; // Find zone index const label faceZoneIndex = faceZones.whichZone(faceIndex); // Face flip bool faceZoneFlip = false; if (faceZoneIndex > -1) { // Find face in zone const label fizIndex = faceZones[faceZoneIndex].whichFace(faceIndex); faceZoneFlip = faceZones[faceZoneIndex].flipMap()[fizIndex]; } // Found uncovered master in covered section // Move to uncovered patch ref.setAction ( polyModifyFace ( allFaces[faceIndex], // modified face faceIndex, // modified face index owner[faceIndex], // owner -1, // neighbour false, // face flip masterUncoveredPatch.index(), // patch for face false, // remove from zone faceZoneIndex, // zone for face faceZoneFlip // face flip in zone ) ); } if (!uncMaster_[faceI] && faceI >= masterCoveredPatch.size()) { // Found covered face in uncovered section // Get face index const label faceIndex = uncStart - cSize + faceI; // Find zone index const label faceZoneIndex = faceZones.whichZone(faceIndex); // Face flip bool faceZoneFlip = false; if (faceZoneIndex > -1) { // Find face in zone const label fizIndex = faceZones[faceZoneIndex].whichFace(faceIndex); faceZoneFlip = faceZones[faceZoneIndex].flipMap()[fizIndex]; } // Found uncovered master in covered section // Move to uncovered patch ref.setAction ( polyModifyFace ( allFaces[faceIndex], // modified face faceIndex, // modified face index owner[faceIndex], // owner -1, // neighbour false, // face flip masterCoveredPatch.index(), // patch for face false, // remove from zone faceZoneIndex, // zone for face faceZoneFlip // face flip in zone ) ); } } } { // Get slave patches const polyPatch& slaveCoveredPatch = mesh.boundaryMesh()[slaveCoveredPatchID_.index()]; const label cStart = slaveCoveredPatch.start(); const label cSize = slaveCoveredPatch.size(); const polyPatch& slaveUncoveredPatch = mesh.boundaryMesh()[slaveUncoveredPatchID_.index()]; const label uncStart = slaveUncoveredPatch.start(); // Check coverage forAll (uncSlave_, faceI) { if (uncSlave_[faceI] && faceI < slaveCoveredPatch.size()) { // Found uncovered face in covered section // Get face index const label faceIndex = cStart + faceI; // Find zone index const label faceZoneIndex = faceZones.whichZone(faceIndex); // Face flip bool faceZoneFlip = false; if (faceZoneIndex > -1) { // Find face in zone const label fizIndex = faceZones[faceZoneIndex].whichFace(faceIndex); faceZoneFlip = faceZones[faceZoneIndex].flipMap()[fizIndex]; } // Found uncovered slave in covered section // Move to uncovered patch ref.setAction ( polyModifyFace ( allFaces[faceIndex], // modified face faceIndex, // modified face index owner[faceIndex], // owner -1, // neighbour false, // face flip slaveUncoveredPatch.index(), // patch for face false, // remove from zone faceZoneIndex, // zone for face faceZoneFlip // face flip in zone ) ); } if (!uncSlave_[faceI] && faceI >= slaveCoveredPatch.size()) { // Found covered face in uncovered section // Get face index const label faceIndex = uncStart - cSize + faceI; // Find zone index const label faceZoneIndex = faceZones.whichZone(faceIndex); // Face flip bool faceZoneFlip = false; if (faceZoneIndex > -1) { // Find face in zone const label fizIndex = faceZones[faceZoneIndex].whichFace(faceIndex); faceZoneFlip = faceZones[faceZoneIndex].flipMap()[fizIndex]; } // Found uncovered slave in covered section // Move to uncovered patch ref.setAction ( polyModifyFace ( allFaces[faceIndex], // modified face faceIndex, // modified face index owner[faceIndex], // owner -1, // neighbour false, // face flip slaveCoveredPatch.index(), // patch for face false, // remove from zone faceZoneIndex, // zone for face faceZoneFlip // face flip in zone ) ); } } } // Clear uncovered masks to indicate that the topological change // has been performed uncMaster_.clear(); uncSlave_.clear(); }
void Foam::attachDetach::detachInterface ( polyTopoChange& ref ) const { // Algorithm: // 1. Create new points for points of the master face zone // 2. Modify all faces of the master zone, by putting them into the master // patch (look for orientation) and their renumbered mirror images // into the slave patch // 3. Create a point renumbering list, giving a new point index for original // points in the face patch // 4. Grab all faces in cells on the master side and renumber them // using the point renumbering list. Exclude the ones that belong to // the master face zone // // Note on point creation: // In order to take into account the issues related to partial // blocking in an attach/detach mesh modifier, special treatment // is required for the duplication of points on the edge of the // face zone. Points which are shared only by internal edges need // not to be duplicated, as this would propagate the discontinuity // in the mesh beyond the face zone. Therefore, before creating // the new points, check the external edge loop. For each edge // check if the edge is internal (i.e. does not belong to a // patch); if so, exclude both of its points from duplication. if (debug) { Pout<< "void attachDetach::detachInterface(" << "polyTopoChange& ref) const " << " for object " << name() << " : " << "Detaching interface" << endl; } const polyMesh& mesh = topoChanger().mesh(); const faceZoneMesh& zoneMesh = mesh.faceZones(); const primitiveFacePatch& masterFaceLayer = zoneMesh[faceZoneID_.index()](); const pointField& points = mesh.points(); const labelListList& meshEdgeFaces = mesh.edgeFaces(); const labelList& mp = masterFaceLayer.meshPoints(); const edgeList& zoneLocalEdges = masterFaceLayer.edges(); const labelList& meshEdges = zoneMesh[faceZoneID_.index()].meshEdges(); // Create the points labelList addedPoints(mp.size(), -1); // Go through boundary edges of the master patch. If all the faces from // this patch are internal, mark the points in the addedPoints lookup // with their original labels to stop duplication label nIntEdges = masterFaceLayer.nInternalEdges(); for (label curEdgeID = nIntEdges; curEdgeID < meshEdges.size(); curEdgeID++) { const labelList& curFaces = meshEdgeFaces[meshEdges[curEdgeID]]; bool edgeIsInternal = true; forAll (curFaces, faceI) { if (!mesh.isInternalFace(curFaces[faceI])) { // The edge belongs to a boundary face edgeIsInternal = false; break; } } if (edgeIsInternal) { // Pout<< "Internal edge found: (" << mp[zoneLocalEdges[curEdgeID].start()] << " " << mp[zoneLocalEdges[curEdgeID].end()] << ")" << endl; // Reset the point creation addedPoints[zoneLocalEdges[curEdgeID].start()] = mp[zoneLocalEdges[curEdgeID].start()]; addedPoints[zoneLocalEdges[curEdgeID].end()] = mp[zoneLocalEdges[curEdgeID].end()]; } } // Pout << "addedPoints before point creation: " << addedPoints << endl; // Create new points for face zone forAll (addedPoints, pointI) { if (addedPoints[pointI] < 0) { addedPoints[pointI] = ref.setAction ( polyAddPoint ( points[mp[pointI]], // point mp[pointI], // master point -1, // zone ID true // supports a cell ) ); // Pout << "Adding point " << points[mp[pointI]] << " for original point " << mp[pointI] << endl; } } // Modify faces in the master zone and duplicate for the slave zone const labelList& mf = zoneMesh[faceZoneID_.index()]; const boolList& mfFlip = zoneMesh[faceZoneID_.index()].flipMap(); const faceList& zoneFaces = masterFaceLayer.localFaces(); const faceList& faces = mesh.faces(); const labelList& own = mesh.faceOwner(); const labelList& nei = mesh.faceNeighbour(); forAll (mf, faceI) { const label curFaceID = mf[faceI]; // Build the face for the slave patch by renumbering const face oldFace = zoneFaces[faceI].reverseFace(); face newFace(oldFace.size()); forAll (oldFace, pointI) { newFace[pointI] = addedPoints[oldFace[pointI]]; } if (mfFlip[faceI]) { // Face needs to be flipped for the master patch // No need to check for nei index: internal face. HJ, 16/Dec/2008 ref.setAction ( polyModifyFace ( faces[curFaceID].reverseFace(), // modified face curFaceID, // label of face being modified nei[curFaceID], // owner -1, // neighbour true, // face flip masterPatchID_.index(), // patch for face false, // remove from zone faceZoneID_.index(), // zone for face !mfFlip[faceI] // face flip in zone ) ); // Add renumbered face into the slave patch ref.setAction ( polyAddFace ( newFace, // face own[curFaceID], // owner -1, // neighbour -1, // master point -1, // master edge curFaceID, // master face false, // flip flux slavePatchID_.index(), // patch to add the face to -1, // zone for face false // zone flip ) ); // Pout << "Flip. Modifying face: " << faces[curFaceID].reverseFace() << " next to cell: " << nei[curFaceID] << " and adding face: " << newFace << " next to cell: " << own[curFaceID] << endl; } else { // No flip ref.setAction ( polyModifyFace ( faces[curFaceID], // modified face curFaceID, // label of face being modified own[curFaceID], // owner -1, // neighbour false, // face flip masterPatchID_.index(), // patch for face false, // remove from zone faceZoneID_.index(), // zone for face mfFlip[faceI] // face flip in zone ) ); // Add renumbered face into the slave patch // No need to check for nei index: internal face. HJ, 16/Dec/2008 ref.setAction ( polyAddFace ( newFace, // face nei[curFaceID], // owner -1, // neighbour -1, // master point -1, // master edge curFaceID, // master face true, // flip flux slavePatchID_.index(), // patch to add the face to -1, // zone for face false // face flip in zone ) ); // Pout << "No flip. Modifying face: " << faces[curFaceID] << " next to cell: " << own[curFaceID] << " and adding face: " << newFace << " next to cell: " << nei[curFaceID] << endl; } } // Modify the remaining faces of the master cells to reconnect to the new // layer of faces. // Algorithm: Go through all the cells of the master zone and make // a map of faces to avoid duplicates. Do not insert the faces in // the master patch (as they have already been dealt with). Make // a master layer point renumbering map, which for every point in // the master layer gives its new label. Loop through all faces in // the map and attempt to renumber them using the master layer // point renumbering map. Once the face is renumbered, compare it // with the original face; if they are the same, the face has not // changed; if not, modify the face but keep all of its old // attributes (apart from the vertex numbers). // Create the map of faces in the master cell layer const labelList& mc = mesh.faceZones()[faceZoneID_.index()].masterCells(); labelHashSet masterCellFaceMap(6*mc.size()); const cellList& cells = mesh.cells(); forAll (mc, cellI) { const labelList& curFaces = cells[mc[cellI]]; forAll (curFaces, faceI) { // Check if the face belongs to the master patch; if not add it if (zoneMesh.whichZone(curFaces[faceI]) != faceZoneID_.index()) { masterCellFaceMap.insert(curFaces[faceI]); } } } // Extend the map to include first neighbours of the master cells to // deal with multiple corners. { // Protection and memory management // Make a map of master cells for quick reject labelHashSet mcMap(2*mc.size()); forAll (mc, mcI) { mcMap.insert(mc[mcI]); } // Go through all the faces in the masterCellFaceMap. If the // cells around them are not already used, add all of their // faces to the map const labelList mcf = masterCellFaceMap.toc(); forAll (mcf, mcfI) { // Do the owner side const label ownCell = own[mcf[mcfI]]; if (!mcMap.found(ownCell)) { // Cell not found. Add its faces to the map const cell& curFaces = cells[ownCell]; forAll (curFaces, faceI) { masterCellFaceMap.insert(curFaces[faceI]); } } // Do the neighbour side if face is internal if (mesh.isInternalFace(mcf[mcfI])) { const label neiCell = nei[mcf[mcfI]]; if (!mcMap.found(neiCell)) { // Cell not found. Add its faces to the map const cell& curFaces = cells[neiCell]; forAll (curFaces, faceI) { masterCellFaceMap.insert(curFaces[faceI]); } } }