mergePatchPairs.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2009 OpenFOAM Foundation
9  Copyright (C) 2017-2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
13 
14 Description
15  Handle merging of patch pairs
16 
17 \*---------------------------------------------------------------------------*/
18 
19 {
20  wordPairList mergePatchPairs;
21 
22  // Read in a list of merge patch pairs
23  if
24  (
25  meshDict.readIfPresent("mergePatchPairs", mergePatchPairs)
26  && mergePatchPairs.size()
27  )
28  {
29  Info<< "Merging " << mergePatchPairs.size() << " patch pairs" << nl;
30 
31  // Cleanup
32  wordHashSet cleanupPatches(4*mergePatchPairs.size());
33  wordHashSet cleanupPointZones(2*mergePatchPairs.size());
34  wordHashSet cleanupFaceZones(2*mergePatchPairs.size());
35 
36  Info<< " Adding point and face zones" << endl;
37  {
38  const auto& pbm = mesh.boundaryMesh();
39 
40  auto& pzs = mesh.pointZones(); pzs.clearAddressing();
41  auto& fzs = mesh.faceZones(); fzs.clearAddressing();
42 
43  forAll(mergePatchPairs, pairi)
44  {
45  // Patch pairs
46  const polyPatch& patch0 = pbm[mergePatchPairs[pairi].first()];
47  const polyPatch& patch1 = pbm[mergePatchPairs[pairi].second()];
48 
49  const word mergeName
50  (
51  mergePatchPairs[pairi].first()
52  + mergePatchPairs[pairi].second()
53  + Foam::name(pairi)
54  );
55 
56  // An empty zone for cut points
57  pzs.emplace_back
58  (
59  mergeName + "CutPointZone",
60  pzs.size(), // index
61  pzs
62  );
63  cleanupPointZones.insert(pzs.back().name());
64 
65  // Coupling side 0 (master)
66  fzs.emplace_back
67  (
68  mergeName + "Side0Zone",
69  identity(patch0.range()),
70  false, // none are flipped
71  fzs.size(), // index
72  fzs
73  );
74  cleanupFaceZones.insert(fzs.back().name());
75 
76  // Coupling side 1 (slave)
77  fzs.emplace_back
78  (
79  mergeName + "Side1Zone",
80  identity(patch1.range()),
81  false, // none are flipped
82  fzs.size(), // index
83  fzs
84  );
85  cleanupFaceZones.insert(fzs.back().name());
86 
87  // An empty zone for cut faces
88  fzs.emplace_back
89  (
90  mergeName + "CutFaceZone",
91  fzs.size(), // index
92  fzs
93  );
94  cleanupFaceZones.insert(fzs.back().name());
95  }
96  }
97 
98 
99  Info<< " Merging with attachPolyTopoChanger" << endl;
100  attachPolyTopoChanger polyMeshAttacher(mesh);
101  polyMeshAttacher.resize(1);
102 
103  forAll(mergePatchPairs, pairi)
104  {
105  cleanupPatches.insert(mergePatchPairs[pairi].first());
106  cleanupPatches.insert(mergePatchPairs[pairi].second());
107 
108  const word mergeName
109  (
110  mergePatchPairs[pairi].first()
111  + mergePatchPairs[pairi].second()
112  + Foam::name(pairi)
113  );
114 
115  // Add the sliding interface mesh modifier
116  polyMeshAttacher.set
117  (
118  0,
119  new slidingInterface
120  (
121  "couple" + Foam::name(pairi),
122  pairi,
123  polyMeshAttacher,
124  mergeName + "Side0Zone",
125  mergeName + "Side1Zone",
126  mergeName + "CutPointZone",
127  mergeName + "CutFaceZone",
128  mergePatchPairs[pairi].first(),
129  mergePatchPairs[pairi].second(),
130  slidingInterface::INTEGRAL, // always integral
131  false,
132  intersection::VISIBLE
133  )
134  );
135 
136  polyMeshAttacher.attach(false); // Do not yet remove empty patches
137  }
138 
139  // Re-do the boundary patches, removing empty merge patches
140  // but keeping any other empty patches
141  {
142  const polyBoundaryMesh& oldPatches = mesh.boundaryMesh();
143 
144  polyPatchList newPatches(oldPatches.size());
145  label nNewPatches = 0;
146 
147  wordHashSet removedPatches(cleanupPatches.capacity());
148 
149  forAll(oldPatches, patchi)
150  {
151  const word& patchName = oldPatches[patchi].name();
152 
153  if
154  (
155  !cleanupPatches.found(patchName)
156  || returnReduceOr(oldPatches[patchi].size())
157  )
158  {
159  newPatches.set
160  (
161  nNewPatches,
162  oldPatches[patchi].clone
163  (
164  mesh.boundaryMesh(),
165  nNewPatches,
166  oldPatches[patchi].size(),
167  oldPatches[patchi].start()
168  )
169  );
170 
171  ++nNewPatches;
172  }
173  else
174  {
175  removedPatches.insert(patchName);
176  }
177  }
178 
179  newPatches.resize(nNewPatches);
180 
181  mesh.removeBoundary();
182  mesh.addPatches(newPatches);
183 
184  Info<< "Removed " << removedPatches.size()
185  << " empty merged patches:" << nl
186  << " " << flatOutput(removedPatches.sortedToc()) << endl;
187  }
188 
189  // Cleanup empty merged point zones
190  {
191  PtrList<pointZone>& zones = mesh.pointZones();
192  mesh.pointZones().clearAddressing();
193 
194  wordHashSet removedZones(2*zones.size());
195 
196  label nZones = 0;
197  forAll(zones, zonei)
198  {
199  if
200  (
201  !cleanupPointZones.found(zones[zonei].name())
202  || returnReduceOr(zones[zonei].size())
203  )
204  {
205  zones.set(nZones, zones.release(zonei));
206  zones[nZones].index() = nZones; // re-index
207  ++nZones;
208  }
209  else
210  {
211  removedZones.insert(zones[zonei].name());
212  }
213  }
214  zones.resize(nZones);
215 
216  if (removedZones.size())
217  {
218  Info<< "Removed " << removedZones.size()
219  << " empty point zones:" << nl
220  << " " << flatOutput(removedZones.sortedToc()) << endl;
221  }
222  }
223 
224  // Cleanup empty merged face zones
225  {
226  PtrList<faceZone>& zones = mesh.faceZones();
227  mesh.faceZones().clearAddressing();
228 
229  wordHashSet removedZones(2*zones.size());
230 
231  label nZones = 0;
232  forAll(zones, zonei)
233  {
234  if
235  (
236  !cleanupFaceZones.found(zones[zonei].name())
237  || returnReduceOr(zones[zonei].size())
238  )
239  {
240  zones.set(nZones, zones.release(zonei));
241  zones[nZones].index() = nZones; // re-index
242  ++nZones;
243  }
244  else
245  {
246  removedZones.insert(zones[zonei].name());
247  }
248  }
249  zones.resize(nZones);
250 
251  if (removedZones.size())
252  {
253  Info<< "Removed " << removedZones.size()
254  << " empty merged face zones:" << nl
255  << " " << flatOutput(removedZones.sortedToc()) << endl;
256  }
257  }
258  }
259  else
260  {
261  Info<< "No patch pairs to merge" << endl;
262  }
263 }
264 
265 
266 // ************************************************************************* //
const IOdictionary & meshDict
const polyBoundaryMesh & pbm
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
PtrList< polyPatch > polyPatchList
Store lists of polyPatch as a PtrList.
Definition: polyPatch.H:56
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
Definition: labelLists.C:44
List< wordPair > wordPairList
List of wordPair.
Definition: wordPair.H:33
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition: HashSet.H:73
messageStream Info
Information stream (stdout output on master, null elsewhere)
bool returnReduceOr(const bool value, const label comm=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225