1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 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 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"
38 #include "polyModifyFace.H"
39 #include "polyRemovePoint.H"
40 #include "polyRemoveFace.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 primitivePatch& 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(polyTopoChange& ref) const
162 Pout<< "bool perfectInterface::setRefinement(polyTopoChange&) const : "
163 << "for object " << name() << " : "
164 << "masterPatchID_:" << masterPatchID_
165 << " slavePatchID_:" << slavePatchID_
166 << " faceZoneID_:" << faceZoneID_ << endl;
171 masterPatchID_.active()
172 && slavePatchID_.active()
173 && faceZoneID_.active()
176 const polyMesh& mesh = topoChanger().mesh();
178 const polyBoundaryMesh& patches = mesh.boundaryMesh();
180 const polyPatch& pp0 = patches[masterPatchID_.index()];
181 const polyPatch& pp1 = patches[slavePatchID_.index()];
184 const edgeList& edges0 = pp0.edges();
185 const pointField& pts0 = pp0.localPoints();
186 const pointField& pts1 = pp1.localPoints();
187 const labelList& meshPts0 = pp0.meshPoints();
188 const labelList& meshPts1 = pp1.meshPoints();
191 // Get local dimension as fraction of minimum edge length
193 scalar minLen = GREAT;
195 forAll(edges0, edgeI)
197 minLen = min(minLen, edges0[edgeI].mag(pts0));
199 scalar typDim = tol_*minLen;
203 Pout<< "typDim:" << typDim << " edges0:" << edges0.size()
204 << " pts0:" << pts0.size() << " pts1:" << pts1.size()
205 << " pp0:" << pp0.size() << " pp1:" << pp1.size() << endl;
209 // Determine pointMapping in mesh point labels. Uses geometric
210 // comparison to find correspondence between patch points.
212 labelList renumberPoints(mesh.points().size());
213 forAll(renumberPoints, i)
215 renumberPoints[i] = i;
218 labelList from1To0Points(pts1.size());
220 bool matchOk = matchPoints
224 scalarField(pts1.size(), typDim), // tolerance
233 "perfectInterface::setRefinement(polyTopoChange& ref) const"
234 ) << "Points on patches " << pp0.name() << " and "
235 << pp1.name() << " do not match to within tolerance "
236 << typDim << exit(FatalError);
241 renumberPoints[meshPts1[i]] = meshPts0[from1To0Points[i]];
247 // Calculate correspondence between patch faces
249 labelList from0To1Faces(pp1.size());
251 bool matchOk = matchPoints
253 calcFaceCentres(pp0),
254 calcFaceCentres(pp1),
255 scalarField(pp0.size(), typDim), // tolerance
264 "perfectInterface::setRefinement(polyTopoChange& ref) const"
265 ) << "Face centres of patches " << pp0.name() << " and "
266 << pp1.name() << " do not match to within tolerance " << typDim
273 // - renumber faces using pts1 (except patch1 faces)
274 // - remove patch1 faces. Remember cell label on owner side.
275 // - modify patch0 faces to be internal.
277 // 1. Get faces to be renumbered
278 labelHashSet affectedFaces(2*pp1.size());
281 label meshPointI = meshPts1[i];
283 if (meshPointI != renumberPoints[meshPointI])
285 const labelList& pFaces = mesh.pointFaces()[meshPointI];
287 forAll(pFaces, pFaceI)
289 affectedFaces.insert(pFaces[pFaceI]);
295 affectedFaces.erase(pp1.start() + i);
297 // Remove patch0 from renumbered faces. Should not be nessecary since
298 // patch0 and 1 should not share any point (if created by mergeMeshing)
299 // so affectedFaces should not contain any patch0 faces but you can
300 // never be sure what the user is doing.
303 if (affectedFaces.erase(pp0.start() + i))
307 "perfectInterface::setRefinement(polyTopoChange&) const"
308 ) << "Found face " << pp0.start() + i << " vertices "
309 << mesh.faces()[pp0.start() + i] << " whose points are"
310 << " used both by master patch " << pp0.name()
311 << " and slave patch " << pp1.name()
317 // 2. Renumber (non patch0/1) faces.
320 labelHashSet::const_iterator iter = affectedFaces.begin();
321 iter != affectedFaces.end();
325 label faceI = iter.key();
327 const face& f = mesh.faces()[faceI];
329 face newFace(f.size());
333 newFace[fp] = renumberPoints[f[fp]];
340 if (mesh.isInternalFace(faceI))
342 nbr = mesh.faceNeighbour()[faceI];
346 patchI = patches.whichPatch(faceI);
349 label zoneID = mesh.faceZones().whichZone(faceI);
351 bool zoneFlip = false;
355 const faceZone& fZone = mesh.faceZones()[zoneID];
357 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
364 newFace, // modified face
365 faceI, // label of face being modified
366 mesh.faceOwner()[faceI], // owner
369 patchI, // patch for face
370 false, // remove from zone
371 zoneID, // zone for face
372 zoneFlip // face flip in zone
378 // 3. Remove patch1 points
381 label meshPointI = meshPts1[i];
383 if (meshPointI != renumberPoints[meshPointI])
385 ref.setAction(polyRemovePoint(meshPointI));
390 // 4. Remove patch1 faces
393 ref.setAction(polyRemoveFace(pp1.start() + i));
397 // 5. Modify patch0 faces for new points (not really nessecary; see
398 // comment above about patch1 and patch0 never sharing points) and
399 // becoming internal.
400 const boolList& mfFlip =
401 mesh.faceZones()[faceZoneID_.index()].flipMap();
405 label faceI = pp0.start() + i;
407 const face& f = mesh.faces()[faceI];
409 face newFace(f.size());
413 newFace[fp] = renumberPoints[f[fp]];
416 label own = mesh.faceOwner()[faceI];
418 label pp1FaceI = pp1.start() + from0To1Faces[i];
420 label nbr = mesh.faceOwner()[pp1FaceI];
428 newFace, // modified face
429 faceI, // label of face being modified
433 -1, // patch for face
434 false, // remove from zone
435 faceZoneID_.index(), // zone for face
436 mfFlip[i] // face flip in zone
446 newFace.reverseFace(), // modified face
447 faceI, // label of face being modified
451 -1, // patch for face
452 false, // remove from zone
453 faceZoneID_.index(), // zone for face
454 !mfFlip[i] // face flip in zone
463 void Foam::perfectInterface::modifyMotionPoints(pointField& motionPoints) const
465 // Update only my points. Nothing to be done here as points already
470 void Foam::perfectInterface::updateMesh(const mapPolyMesh& morphMap)
472 // Mesh has changed topologically. Update local topological data
473 const polyMesh& mesh = topoChanger().mesh();
475 faceZoneID_.update(mesh.faceZones());
476 masterPatchID_.update(mesh.boundaryMesh());
477 slavePatchID_.update(mesh.boundaryMesh());
481 void Foam::perfectInterface::write(Ostream& os) const
483 os << nl << type() << nl
485 << faceZoneID_.name() << nl
486 << masterPatchID_.name() << nl
487 << slavePatchID_.name() << endl;
491 void Foam::perfectInterface::writeDict(Ostream& os) const
493 os << nl << name() << nl << token::BEGIN_BLOCK << nl
495 << " type " << type()
496 << token::END_STATEMENT << nl
498 << " active " << active()
499 << token::END_STATEMENT << nl
501 << " faceZoneName " << faceZoneID_.name()
502 << token::END_STATEMENT << nl
504 << " masterPatchName " << masterPatchID_.name()
505 << token::END_STATEMENT << nl
507 << " slavePatchName " << slavePatchID_.name()
508 << token::END_STATEMENT << nl
510 << token::END_BLOCK << endl;
514 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
517 // * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
520 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
523 // ************************************************************************* //