1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
25 Best thing is probably to look at attachDetach which does almost exactly
26 the same but for the geometric matching of points and face centres.
28 \*---------------------------------------------------------------------------*/
30 #include "perfectInterface.H"
31 #include "polyTopoChanger.H"
33 #include "polyTopoChange.H"
34 #include "addToRunTimeSelectionTable.H"
35 #include "mapPolyMesh.H"
36 #include "matchPoints.H"
37 #include "polyModifyFace.H"
38 #include "polyRemovePoint.H"
39 #include "polyRemoveFace.H"
40 #include "indirectPrimitivePatch.H"
42 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
46 defineTypeNameAndDebug(perfectInterface, 0);
47 addToRunTimeSelectionTable
56 // Tolerance used as fraction of minimum edge length.
57 const Foam::scalar Foam::perfectInterface::tol_ = 1E-3;
60 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
62 Foam::pointField Foam::perfectInterface::calcFaceCentres
64 const indirectPrimitivePatch& pp
67 const pointField& points = pp.points();
69 pointField ctrs(pp.size());
71 forAll(ctrs, patchFaceI)
73 ctrs[patchFaceI] = pp[patchFaceI].centre(points);
80 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
82 // Construct from components
83 Foam::perfectInterface::perfectInterface
87 const polyTopoChanger& mme,
88 const word& faceZoneName,
89 const word& masterPatchName,
90 const word& slavePatchName
93 polyMeshModifier(name, index, mme, true),
94 faceZoneID_(faceZoneName, mme.mesh().faceZones()),
95 masterPatchID_(masterPatchName, mme.mesh().boundaryMesh()),
96 slavePatchID_(slavePatchName, mme.mesh().boundaryMesh())
100 // Construct from dictionary
101 Foam::perfectInterface::perfectInterface
104 const dictionary& dict,
106 const polyTopoChanger& mme
109 polyMeshModifier(name, index, mme, readBool(dict.lookup("active"))),
112 dict.lookup("faceZoneName"),
113 mme.mesh().faceZones()
117 dict.lookup("masterPatchName"),
118 mme.mesh().boundaryMesh()
122 dict.lookup("slavePatchName"),
123 mme.mesh().boundaryMesh()
128 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
130 Foam::perfectInterface::~perfectInterface()
134 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
136 bool Foam::perfectInterface::changeTopology() const
138 // If modifier is inactive, skip change
143 Pout<< "bool perfectInterface::changeTopology() const "
144 << "for object " << name() << " : "
145 << "Inactive" << endl;
152 // I want topo change every time step.
158 void Foam::perfectInterface::setRefinement
160 const indirectPrimitivePatch& pp0,
161 const indirectPrimitivePatch& pp1,
165 const polyMesh& mesh = topoChanger().mesh();
167 const polyBoundaryMesh& patches = mesh.boundaryMesh();
170 const edgeList& edges0 = pp0.edges();
171 const pointField& pts0 = pp0.localPoints();
172 const pointField& pts1 = pp1.localPoints();
173 const labelList& meshPts0 = pp0.meshPoints();
174 const labelList& meshPts1 = pp1.meshPoints();
177 // Get local dimension as fraction of minimum edge length
179 scalar minLen = GREAT;
181 forAll(edges0, edgeI)
183 minLen = min(minLen, edges0[edgeI].mag(pts0));
185 scalar typDim = tol_*minLen;
189 Pout<< "typDim:" << typDim << " edges0:" << edges0.size()
190 << " pts0:" << pts0.size() << " pts1:" << pts1.size()
191 << " pp0:" << pp0.size() << " pp1:" << pp1.size() << endl;
195 // Determine pointMapping in mesh point labels. Uses geometric
196 // comparison to find correspondence between patch points.
198 labelList renumberPoints(mesh.points().size());
199 forAll(renumberPoints, i)
201 renumberPoints[i] = i;
204 labelList from1To0Points(pts1.size());
206 bool matchOk = matchPoints
210 scalarField(pts1.size(), typDim), // tolerance
219 "perfectInterface::setRefinement(polyTopoChange& ref) const"
220 ) << "Points on patch sides do not match to within tolerance "
221 << typDim << exit(FatalError);
226 renumberPoints[meshPts1[i]] = meshPts0[from1To0Points[i]];
232 // Calculate correspondence between patch faces
234 labelList from0To1Faces(pp1.size());
236 bool matchOk = matchPoints
238 calcFaceCentres(pp0),
239 calcFaceCentres(pp1),
240 scalarField(pp0.size(), typDim), // tolerance
249 "perfectInterface::setRefinement(polyTopoChange& ref) const"
250 ) << "Face centres of patch sides do not match to within tolerance "
251 << typDim << exit(FatalError);
257 // - renumber faces using pts1 (except patch1 faces)
258 // - remove patch1 faces. Remember cell label on owner side.
259 // - modify patch0 faces to be internal.
261 // 1. Get faces to be renumbered
262 labelHashSet affectedFaces(2*pp1.size());
265 label meshPointI = meshPts1[i];
267 if (meshPointI != renumberPoints[meshPointI])
269 const labelList& pFaces = mesh.pointFaces()[meshPointI];
271 forAll(pFaces, pFaceI)
273 affectedFaces.insert(pFaces[pFaceI]);
279 affectedFaces.erase(pp1.addressing()[i]);
281 // Remove patch0 from renumbered faces. Should not be nessecary since
282 // patch0 and 1 should not share any point (if created by mergeMeshing)
283 // so affectedFaces should not contain any patch0 faces but you can
284 // never be sure what the user is doing.
287 label faceI = pp0.addressing()[i];
289 if (affectedFaces.erase(faceI))
293 "perfectInterface::setRefinement(polyTopoChange&) const"
294 ) << "Found face " << faceI << " vertices "
295 << mesh.faces()[faceI] << " whose points are"
296 << " used both by master patch and slave patch" << endl;
301 // 2. Renumber (non patch0/1) faces.
302 forAllConstIter(labelHashSet, affectedFaces, iter)
304 const label faceI = iter.key();
305 const face& f = mesh.faces()[faceI];
307 face newFace(f.size());
311 newFace[fp] = renumberPoints[f[fp]];
318 if (mesh.isInternalFace(faceI))
320 nbr = mesh.faceNeighbour()[faceI];
324 patchI = patches.whichPatch(faceI);
327 label zoneID = mesh.faceZones().whichZone(faceI);
329 bool zoneFlip = false;
333 const faceZone& fZone = mesh.faceZones()[zoneID];
335 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
342 newFace, // modified face
343 faceI, // label of face being modified
344 mesh.faceOwner()[faceI], // owner
347 patchI, // patch for face
348 false, // remove from zone
349 zoneID, // zone for face
350 zoneFlip // face flip in zone
356 // 3. Remove patch1 points
359 label meshPointI = meshPts1[i];
361 if (meshPointI != renumberPoints[meshPointI])
363 ref.setAction(polyRemovePoint(meshPointI));
368 // 4. Remove patch1 faces
371 label faceI = pp1.addressing()[i];
372 ref.setAction(polyRemoveFace(faceI));
376 // 5. Modify patch0 faces for new points (not really nessecary; see
377 // comment above about patch1 and patch0 never sharing points) and
378 // becoming internal.
379 const boolList& mfFlip =
380 mesh.faceZones()[faceZoneID_.index()].flipMap();
384 label faceI = pp0.addressing()[i];
386 const face& f = mesh.faces()[faceI];
388 face newFace(f.size());
392 newFace[fp] = renumberPoints[f[fp]];
395 label own = mesh.faceOwner()[faceI];
397 label pp1FaceI = pp1.addressing()[from0To1Faces[i]];
399 label nbr = mesh.faceOwner()[pp1FaceI];
407 newFace, // modified face
408 faceI, // label of face being modified
412 -1, // patch for face
413 false, // remove from zone
414 faceZoneID_.index(), // zone for face
415 mfFlip[i] // face flip in zone
425 newFace.reverseFace(), // 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
441 void Foam::perfectInterface::setRefinement(polyTopoChange& ref) const
445 Pout<< "bool perfectInterface::setRefinement(polyTopoChange&) const : "
446 << "for object " << name() << " : "
447 << "masterPatchID_:" << masterPatchID_
448 << " slavePatchID_:" << slavePatchID_
449 << " faceZoneID_:" << faceZoneID_ << endl;
454 masterPatchID_.active()
455 && slavePatchID_.active()
456 && faceZoneID_.active()
459 const polyMesh& mesh = topoChanger().mesh();
461 const polyBoundaryMesh& patches = mesh.boundaryMesh();
462 const polyPatch& patch0 = patches[masterPatchID_.index()];
463 const polyPatch& patch1 = patches[slavePatchID_.index()];
466 labelList pp0Labels(identity(patch0.size())+patch0.start());
467 indirectPrimitivePatch pp0
469 IndirectList<face>(mesh.faces(), pp0Labels),
473 labelList pp1Labels(identity(patch1.size())+patch1.start());
474 indirectPrimitivePatch pp1
476 IndirectList<face>(mesh.faces(), pp1Labels),
480 setRefinement(pp0, pp1, ref);
485 void Foam::perfectInterface::modifyMotionPoints(pointField& motionPoints) const
487 // Update only my points. Nothing to be done here as points already
492 void Foam::perfectInterface::updateMesh(const mapPolyMesh& morphMap)
494 // Mesh has changed topologically. Update local topological data
495 const polyMesh& mesh = topoChanger().mesh();
497 faceZoneID_.update(mesh.faceZones());
498 masterPatchID_.update(mesh.boundaryMesh());
499 slavePatchID_.update(mesh.boundaryMesh());
503 void Foam::perfectInterface::write(Ostream& os) const
505 os << nl << type() << nl
507 << faceZoneID_.name() << nl
508 << masterPatchID_.name() << nl
509 << slavePatchID_.name() << endl;
513 void Foam::perfectInterface::writeDict(Ostream& os) const
515 os << nl << name() << nl << token::BEGIN_BLOCK << nl
517 << " type " << type()
518 << token::END_STATEMENT << nl
520 << " active " << active()
521 << token::END_STATEMENT << nl
523 << " faceZoneName " << faceZoneID_.name()
524 << token::END_STATEMENT << nl
526 << " masterPatchName " << masterPatchID_.name()
527 << token::END_STATEMENT << nl
529 << " slavePatchName " << slavePatchID_.name()
530 << token::END_STATEMENT << nl
532 << token::END_BLOCK << endl;
536 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
539 // * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
542 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
545 // ************************************************************************* //