1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2010 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
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"
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45 defineTypeNameAndDebug(perfectInterface, 0);
46 addToRunTimeSelectionTable
55 // Tolerance used as fraction of minimum edge length.
56 const Foam::scalar Foam::perfectInterface::tol_ = 1E-3;
59 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
61 Foam::pointField Foam::perfectInterface::calcFaceCentres
63 const primitivePatch& pp
66 const pointField& points = pp.points();
68 pointField ctrs(pp.size());
70 forAll(ctrs, patchFaceI)
72 ctrs[patchFaceI] = pp[patchFaceI].centre(points);
79 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
81 // Construct from components
82 Foam::perfectInterface::perfectInterface
86 const polyTopoChanger& mme,
87 const word& faceZoneName,
88 const word& masterPatchName,
89 const word& slavePatchName
92 polyMeshModifier(name, index, mme, true),
93 faceZoneID_(faceZoneName, mme.mesh().faceZones()),
94 masterPatchID_(masterPatchName, mme.mesh().boundaryMesh()),
95 slavePatchID_(slavePatchName, mme.mesh().boundaryMesh())
99 // Construct from dictionary
100 Foam::perfectInterface::perfectInterface
103 const dictionary& dict,
105 const polyTopoChanger& mme
108 polyMeshModifier(name, index, mme, readBool(dict.lookup("active"))),
111 dict.lookup("faceZoneName"),
112 mme.mesh().faceZones()
116 dict.lookup("masterPatchName"),
117 mme.mesh().boundaryMesh()
121 dict.lookup("slavePatchName"),
122 mme.mesh().boundaryMesh()
127 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
129 Foam::perfectInterface::~perfectInterface()
133 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
135 bool Foam::perfectInterface::changeTopology() const
137 // If modifier is inactive, skip change
142 Pout<< "bool perfectInterface::changeTopology() const "
143 << "for object " << name() << " : "
144 << "Inactive" << endl;
151 // I want topo change every time step.
157 void Foam::perfectInterface::setRefinement(polyTopoChange& ref) const
161 Pout<< "bool perfectInterface::setRefinement(polyTopoChange&) const : "
162 << "for object " << name() << " : "
163 << "masterPatchID_:" << masterPatchID_
164 << " slavePatchID_:" << slavePatchID_
165 << " faceZoneID_:" << faceZoneID_ << endl;
170 masterPatchID_.active()
171 && slavePatchID_.active()
172 && faceZoneID_.active()
175 const polyMesh& mesh = topoChanger().mesh();
177 const polyBoundaryMesh& patches = mesh.boundaryMesh();
179 const polyPatch& pp0 = patches[masterPatchID_.index()];
180 const polyPatch& pp1 = patches[slavePatchID_.index()];
183 const edgeList& edges0 = pp0.edges();
184 const pointField& pts0 = pp0.localPoints();
185 const pointField& pts1 = pp1.localPoints();
186 const labelList& meshPts0 = pp0.meshPoints();
187 const labelList& meshPts1 = pp1.meshPoints();
190 // Get local dimension as fraction of minimum edge length
192 scalar minLen = GREAT;
194 forAll(edges0, edgeI)
196 minLen = min(minLen, edges0[edgeI].mag(pts0));
198 scalar typDim = tol_*minLen;
202 Pout<< "typDim:" << typDim << " edges0:" << edges0.size()
203 << " pts0:" << pts0.size() << " pts1:" << pts1.size()
204 << " pp0:" << pp0.size() << " pp1:" << pp1.size() << endl;
208 // Determine pointMapping in mesh point labels. Uses geometric
209 // comparison to find correspondence between patch points.
211 labelList renumberPoints(mesh.points().size());
212 forAll(renumberPoints, i)
214 renumberPoints[i] = i;
217 labelList from1To0Points(pts1.size());
219 bool matchOk = matchPoints
223 scalarField(pts1.size(), typDim), // tolerance
232 "perfectInterface::setRefinement(polyTopoChange& ref) const"
233 ) << "Points on patches " << pp0.name() << " and "
234 << pp1.name() << " do not match to within tolerance "
235 << typDim << exit(FatalError);
240 renumberPoints[meshPts1[i]] = meshPts0[from1To0Points[i]];
246 // Calculate correspondence between patch faces
248 labelList from0To1Faces(pp1.size());
250 bool matchOk = matchPoints
252 calcFaceCentres(pp0),
253 calcFaceCentres(pp1),
254 scalarField(pp0.size(), typDim), // tolerance
263 "perfectInterface::setRefinement(polyTopoChange& ref) const"
264 ) << "Face centres of patches " << pp0.name() << " and "
265 << pp1.name() << " do not match to within tolerance " << typDim
272 // - renumber faces using pts1 (except patch1 faces)
273 // - remove patch1 faces. Remember cell label on owner side.
274 // - modify patch0 faces to be internal.
276 // 1. Get faces to be renumbered
277 labelHashSet affectedFaces(2*pp1.size());
280 label meshPointI = meshPts1[i];
282 if (meshPointI != renumberPoints[meshPointI])
284 const labelList& pFaces = mesh.pointFaces()[meshPointI];
286 forAll(pFaces, pFaceI)
288 affectedFaces.insert(pFaces[pFaceI]);
294 affectedFaces.erase(pp1.start() + i);
296 // Remove patch0 from renumbered faces. Should not be nessecary since
297 // patch0 and 1 should not share any point (if created by mergeMeshing)
298 // so affectedFaces should not contain any patch0 faces but you can
299 // never be sure what the user is doing.
302 if (affectedFaces.erase(pp0.start() + i))
306 "perfectInterface::setRefinement(polyTopoChange&) const"
307 ) << "Found face " << pp0.start() + i << " vertices "
308 << mesh.faces()[pp0.start() + i] << " whose points are"
309 << " used both by master patch " << pp0.name()
310 << " and slave patch " << pp1.name()
316 // 2. Renumber (non patch0/1) faces.
319 labelHashSet::const_iterator iter = affectedFaces.begin();
320 iter != affectedFaces.end();
324 label faceI = iter.key();
326 const face& f = mesh.faces()[faceI];
328 face newFace(f.size());
332 newFace[fp] = renumberPoints[f[fp]];
339 if (mesh.isInternalFace(faceI))
341 nbr = mesh.faceNeighbour()[faceI];
345 patchI = patches.whichPatch(faceI);
348 label zoneID = mesh.faceZones().whichZone(faceI);
350 bool zoneFlip = false;
354 const faceZone& fZone = mesh.faceZones()[zoneID];
356 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
363 newFace, // modified face
364 faceI, // label of face being modified
365 mesh.faceOwner()[faceI], // owner
368 patchI, // patch for face
369 false, // remove from zone
370 zoneID, // zone for face
371 zoneFlip // face flip in zone
377 // 3. Remove patch1 points
380 label meshPointI = meshPts1[i];
382 if (meshPointI != renumberPoints[meshPointI])
384 ref.setAction(polyRemovePoint(meshPointI));
389 // 4. Remove patch1 faces
392 ref.setAction(polyRemoveFace(pp1.start() + i));
396 // 5. Modify patch0 faces for new points (not really nessecary; see
397 // comment above about patch1 and patch0 never sharing points) and
398 // becoming internal.
399 const boolList& mfFlip =
400 mesh.faceZones()[faceZoneID_.index()].flipMap();
404 label faceI = pp0.start() + i;
406 const face& f = mesh.faces()[faceI];
408 face newFace(f.size());
412 newFace[fp] = renumberPoints[f[fp]];
415 label own = mesh.faceOwner()[faceI];
417 label pp1FaceI = pp1.start() + from0To1Faces[i];
419 label nbr = mesh.faceOwner()[pp1FaceI];
427 newFace, // modified face
428 faceI, // label of face being modified
432 -1, // patch for face
433 false, // remove from zone
434 faceZoneID_.index(), // zone for face
435 mfFlip[i] // face flip in zone
445 newFace.reverseFace(), // modified face
446 faceI, // label of face being modified
450 -1, // patch for face
451 false, // remove from zone
452 faceZoneID_.index(), // zone for face
453 !mfFlip[i] // face flip in zone
462 void Foam::perfectInterface::modifyMotionPoints(pointField& motionPoints) const
464 // Update only my points. Nothing to be done here as points already
469 void Foam::perfectInterface::updateMesh(const mapPolyMesh& morphMap)
471 // Mesh has changed topologically. Update local topological data
472 const polyMesh& mesh = topoChanger().mesh();
474 faceZoneID_.update(mesh.faceZones());
475 masterPatchID_.update(mesh.boundaryMesh());
476 slavePatchID_.update(mesh.boundaryMesh());
480 void Foam::perfectInterface::write(Ostream& os) const
482 os << nl << type() << nl
484 << faceZoneID_.name() << nl
485 << masterPatchID_.name() << nl
486 << slavePatchID_.name() << endl;
490 void Foam::perfectInterface::writeDict(Ostream& os) const
492 os << nl << name() << nl << token::BEGIN_BLOCK << nl
494 << " type " << type()
495 << token::END_STATEMENT << nl
497 << " active " << active()
498 << token::END_STATEMENT << nl
500 << " faceZoneName " << faceZoneID_.name()
501 << token::END_STATEMENT << nl
503 << " masterPatchName " << masterPatchID_.name()
504 << token::END_STATEMENT << nl
506 << " slavePatchName " << slavePatchID_.name()
507 << token::END_STATEMENT << nl
509 << token::END_BLOCK << endl;
513 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
516 // * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
519 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
522 // ************************************************************************* //