1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
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
26 Best thing is probably to look at attachDetach which does almost exactly
27 the same but for the geometric matching of points and face centres.
29 \*---------------------------------------------------------------------------*/
31 #include "perfectInterface.H"
32 #include "polyTopoChanger.H"
34 #include "polyTopoChange.H"
35 #include "addToRunTimeSelectionTable.H"
36 #include "mapPolyMesh.H"
37 #include "matchPoints.H"
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
43 defineTypeNameAndDebug(perfectInterface, 0);
44 addToRunTimeSelectionTable
53 // Tolerance used as fraction of minimum edge length.
54 const Foam::scalar Foam::perfectInterface::tol_ = 1e-3;
57 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
59 Foam::pointField Foam::perfectInterface::calcFaceCentres
61 const primitivePatch& pp
64 const pointField& points = pp.points();
66 pointField ctrs(pp.size());
68 forAll(ctrs, patchFaceI)
70 ctrs[patchFaceI] = pp[patchFaceI].centre(points);
77 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
79 // Construct from components
80 Foam::perfectInterface::perfectInterface
84 const polyTopoChanger& mme,
85 const word& faceZoneName,
86 const word& masterPatchName,
87 const word& slavePatchName
90 polyMeshModifier(name, index, mme, true),
91 faceZoneID_(faceZoneName, mme.mesh().faceZones()),
92 masterPatchID_(masterPatchName, mme.mesh().boundaryMesh()),
93 slavePatchID_(slavePatchName, mme.mesh().boundaryMesh())
97 // Construct from dictionary
98 Foam::perfectInterface::perfectInterface
101 const dictionary& dict,
103 const polyTopoChanger& mme
106 polyMeshModifier(name, index, mme, readBool(dict.lookup("active"))),
109 dict.lookup("faceZoneName"),
110 mme.mesh().faceZones()
114 dict.lookup("masterPatchName"),
115 mme.mesh().boundaryMesh()
119 dict.lookup("slavePatchName"),
120 mme.mesh().boundaryMesh()
125 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
127 Foam::perfectInterface::~perfectInterface()
131 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
133 bool Foam::perfectInterface::changeTopology() const
135 // If modifier is inactive, skip change
140 Pout<< "bool perfectInterface::changeTopology() const "
141 << "for object " << name() << " : "
142 << "Inactive" << endl;
149 // I want topo change every time step.
155 void Foam::perfectInterface::setRefinement(polyTopoChange& ref) const
159 Pout<< "bool perfectInterface::setRefinement(polyTopoChange&) const : "
160 << "for object " << name() << " : "
161 << "masterPatchID_:" << masterPatchID_
162 << " slavePatchID_:" << slavePatchID_
163 << " faceZoneID_:" << faceZoneID_ << endl;
168 masterPatchID_.active()
169 && slavePatchID_.active()
170 && faceZoneID_.active()
173 const polyMesh& mesh = topoChanger().mesh();
175 const polyBoundaryMesh& patches = mesh.boundaryMesh();
177 const polyPatch& pp0 = patches[masterPatchID_.index()];
178 const polyPatch& pp1 = patches[slavePatchID_.index()];
181 const edgeList& edges0 = pp0.edges();
182 const pointField& pts0 = pp0.localPoints();
183 const pointField& pts1 = pp1.localPoints();
184 const labelList& meshPts0 = pp0.meshPoints();
185 const labelList& meshPts1 = pp1.meshPoints();
188 // Get local dimension as fraction of minimum edge length
190 scalar minLen = GREAT;
192 forAll(edges0, edgeI)
194 minLen = min(minLen, edges0[edgeI].mag(pts0));
196 scalar typDim = tol_*minLen;
200 Pout<< "typDim:" << typDim << " edges0:" << edges0.size()
201 << " pts0:" << pts0.size() << " pts1:" << pts1.size()
202 << " pp0:" << pp0.size() << " pp1:" << pp1.size() << endl;
206 // Determine pointMapping in mesh point labels. Uses geometric
207 // comparison to find correspondence between patch points.
209 labelList renumberPoints(mesh.allPoints().size());
210 forAll(renumberPoints, i)
212 renumberPoints[i] = i;
215 labelList from1To0Points(pts1.size());
217 bool matchOk = matchPoints
221 scalarField(pts1.size(), typDim), // tolerance
230 "perfectInterface::setRefinement(polyTopoChange& ref) const"
231 ) << "Points on patches " << pp0.name() << " and "
232 << pp1.name() << " do not match to within tolerance "
233 << typDim << exit(FatalError);
238 renumberPoints[meshPts1[i]] = meshPts0[from1To0Points[i]];
244 // Calculate correspondence between patch faces
246 labelList from0To1Faces(pp1.size());
248 bool matchOk = matchPoints
250 calcFaceCentres(pp0),
251 calcFaceCentres(pp1),
252 scalarField(pp0.size(), typDim), // tolerance
261 "perfectInterface::setRefinement(polyTopoChange& ref) const"
262 ) << "Face centres of patches " << pp0.name() << " and "
263 << pp1.name() << " do not match to within tolerance " << typDim
270 // - renumber faces using pts1 (except patch1 faces)
271 // - remove patch1 faces. Remember cell label on owner side.
272 // - modify patch0 faces to be internal.
274 // 1. Get faces to be renumbered
275 labelHashSet affectedFaces(2*pp1.size());
278 label meshPointI = meshPts1[i];
280 if (meshPointI != renumberPoints[meshPointI])
282 const labelList& pFaces = mesh.pointFaces()[meshPointI];
284 forAll(pFaces, pFaceI)
286 affectedFaces.insert(pFaces[pFaceI]);
292 affectedFaces.erase(pp1.start() + i);
294 // Remove patch0 from renumbered faces. Should not be nessecary since
295 // patch0 and 1 should not share any point (if created by mergeMeshing)
296 // so affectedFaces should not contain any patch0 faces but you can
297 // never be sure what the user is doing.
300 if (affectedFaces.erase(pp0.start() + i))
304 "perfectInterface::setRefinement(polyTopoChange&) const"
305 ) << "Found face " << pp0.start() + i << " vertices "
306 << mesh.faces()[pp0.start() + i] << " whose points are"
307 << " used both by master patch " << pp0.name()
308 << " and slave patch " << pp1.name()
314 // 2. Renumber (non patch0/1) faces.
317 labelHashSet::const_iterator iter = affectedFaces.begin();
318 iter != affectedFaces.end();
322 label faceI = iter.key();
324 const face& f = mesh.faces()[faceI];
326 face newFace(f.size());
330 newFace[fp] = renumberPoints[f[fp]];
337 if (mesh.isInternalFace(faceI))
339 nbr = mesh.faceNeighbour()[faceI];
343 patchI = patches.whichPatch(faceI);
346 label zoneID = mesh.faceZones().whichZone(faceI);
348 bool zoneFlip = false;
352 const faceZone& fZone = mesh.faceZones()[zoneID];
354 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
361 newFace, // modified face
362 faceI, // label of face being modified
363 mesh.faceOwner()[faceI], // owner
366 patchI, // patch for face
367 false, // remove from zone
368 zoneID, // zone for face
369 zoneFlip // face flip in zone
375 // 3. Remove patch1 points
378 label meshPointI = meshPts1[i];
380 if (meshPointI != renumberPoints[meshPointI])
382 ref.setAction(polyRemovePoint(meshPointI));
387 // 4. Remove patch1 faces
390 ref.setAction(polyRemoveFace(pp1.start() + i));
394 // 5. Modify patch0 faces for new points (not really nessecary; see
395 // comment above about patch1 and patch0 never sharing points) and
396 // becoming internal.
397 const boolList& mfFlip =
398 mesh.faceZones()[faceZoneID_.index()].flipMap();
402 label faceI = pp0.start() + i;
404 const face& f = mesh.faces()[faceI];
406 face newFace(f.size());
410 newFace[fp] = renumberPoints[f[fp]];
413 label own = mesh.faceOwner()[faceI];
415 label pp1FaceI = pp1.start() + from0To1Faces[i];
417 label nbr = mesh.faceOwner()[pp1FaceI];
425 newFace, // modified face
426 faceI, // label of face being modified
430 -1, // patch for face
431 false, // remove from zone
432 faceZoneID_.index(), // zone for face
433 mfFlip[i] // face flip in zone
443 newFace.reverseFace(), // modified face
444 faceI, // label of face being modified
448 -1, // patch for face
449 false, // remove from zone
450 faceZoneID_.index(), // zone for face
451 !mfFlip[i] // face flip in zone
460 void Foam::perfectInterface::modifyMotionPoints(pointField& motionPoints) const
462 // Update only my points. Nothing to be done here as points already
467 void Foam::perfectInterface::updateMesh(const mapPolyMesh& morphMap)
469 // Mesh has changed topologically. Update local topological data
470 const polyMesh& mesh = topoChanger().mesh();
472 faceZoneID_.update(mesh.faceZones());
473 masterPatchID_.update(mesh.boundaryMesh());
474 slavePatchID_.update(mesh.boundaryMesh());
478 void Foam::perfectInterface::write(Ostream& os) const
480 os << nl << type() << nl
482 << faceZoneID_.name() << nl
483 << masterPatchID_.name() << nl
484 << slavePatchID_.name() << endl;
488 void Foam::perfectInterface::writeDict(Ostream& os) const
490 os << nl << name() << nl << token::BEGIN_BLOCK << nl
492 << " type " << type()
493 << token::END_STATEMENT << nl
495 << " active " << active()
496 << token::END_STATEMENT << nl
498 << " faceZoneName " << faceZoneID_.name()
499 << token::END_STATEMENT << nl
501 << " masterPatchName " << masterPatchID_.name()
502 << token::END_STATEMENT << nl
504 << " slavePatchName " << slavePatchID_.name()
505 << token::END_STATEMENT << nl
507 << token::END_BLOCK << endl;
511 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
514 // * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
517 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
520 // ************************************************************************* //