attachDetach.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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
19  for more details.
20 
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/>.
23 
24 Description
25  Attach/detach boundary mesh modifier. This modifier takes a set of
26  internal faces and converts them into boundary faces and vice versa
27  based on the given activation switch.
28 
29 \*---------------------------------------------------------------------------*/
30 
31 #include "attachDetach.H"
32 #include "polyTopoChanger.H"
33 #include "polyMesh.H"
34 #include "Time.H"
35 #include "primitiveMesh.H"
36 #include "polyTopoChange.H"
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
43  defineTypeNameAndDebug(attachDetach, 0);
45  (
46  polyMeshModifier,
47  attachDetach,
48  dictionary
49  );
50 }
51 
52 
53 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
54 
55 void Foam::attachDetach::checkDefinition()
56 {
57  if
58  (
59  !faceZoneID_.active()
60  || !masterPatchID_.active()
61  || !slavePatchID_.active()
62  )
63  {
65  (
66  "void Foam::attachDetach::checkDefinition()"
67  ) << "Not all zones and patches needed in the definition "
68  << "have been found. Please check your mesh definition."
69  << abort(FatalError);
70  }
71 
72  const polyMesh& mesh = topoChanger().mesh();
73 
74  if (debug)
75  {
76  Pout<< "Attach/detach object " << name() << " :" << nl
77  << " faceZoneID: " << faceZoneID_ << nl
78  << " masterPatchID: " << masterPatchID_ << nl
79  << " slavePatchID: " << slavePatchID_ << endl;
80  }
81 
82  // Check the sizes and set up state
83  if
84  (
85  mesh.boundaryMesh()[masterPatchID_.index()].empty()
86  && mesh.boundaryMesh()[slavePatchID_.index()].empty()
87  )
88  {
89  // Boundary is attached
90  if (debug)
91  {
92  Pout<< " Attached on construction" << endl;
93  }
94 
95  state_ = ATTACHED;
96 
97  // Check if there are faces in the master zone
98  if (mesh.faceZones()[faceZoneID_.index()].empty())
99  {
101  (
102  "void Foam::attachDetach::checkDefinition()"
103  ) << "Attach/detach zone contains no faces. Please check your "
104  << "mesh definition."
105  << abort(FatalError);
106  }
107 
108  // Check that all the faces in the face zone are internal
109  if (debug)
110  {
111  const labelList& addr = mesh.faceZones()[faceZoneID_.index()];
112 
113  DynamicList<label> bouFacesInZone(addr.size());
114 
115  forAll(addr, faceI)
116  {
117  if (!mesh.isInternalFace(addr[faceI]))
118  {
119  bouFacesInZone.append(addr[faceI]);
120  }
121  }
122 
123  if (bouFacesInZone.size())
124  {
126  (
127  "void Foam::attachDetach::checkDefinition()"
128  ) << "Found boundary faces in the zone defining "
129  << "attach/detach boundary "
130  << " for object " << name()
131  << " : . This is not allowed." << nl
132  << "Boundary faces: " << bouFacesInZone
133  << abort(FatalError);
134  }
135  }
136  }
137  else
138  {
139  // Boundary is detached
140  if (debug)
141  {
142  Pout<< " Detached on construction" << endl;
143  }
144 
145  state_ = DETACHED;
146 
147  // Check that the sizes of master and slave patch are identical
148  // and identical to the size of the face zone
149  if
150  (
151  (
152  mesh.boundaryMesh()[masterPatchID_.index()].size()
153  != mesh.boundaryMesh()[slavePatchID_.index()].size()
154  )
155  || (
156  mesh.boundaryMesh()[masterPatchID_.index()].size()
157  != mesh.faceZones()[faceZoneID_.index()].size()
158  )
159  )
160  {
162  (
163  "void Foam::attachDetach::checkDefinition()"
164  ) << "Problem with sizes in mesh modifier. The face zone,"
165  << " master and slave patch should have the same size"
166  << " for object " << name() << ". " << nl
167  << "Zone size: "
168  << mesh.faceZones()[faceZoneID_.index()].size()
169  << " Master patch size: "
170  << mesh.boundaryMesh()[masterPatchID_.index()].size()
171  << " Slave patch size: "
172  << mesh.boundaryMesh()[slavePatchID_.index()].size()
173  << abort(FatalError);
174  }
175 
176  // Check that all the faces belong to either master or slave patch
177  if (debug)
178  {
179  const labelList& addr = mesh.faceZones()[faceZoneID_.index()];
180 
181  DynamicList<label> zoneProblemFaces(addr.size());
182 
183  forAll(addr, faceI)
184  {
185  label facePatch =
186  mesh.boundaryMesh().whichPatch(addr[faceI]);
187 
188  if
189  (
190  facePatch != masterPatchID_.index()
191  && facePatch != slavePatchID_.index()
192  )
193  {
194  zoneProblemFaces.append(addr[faceI]);
195  }
196  }
197 
198  if (zoneProblemFaces.size())
199  {
201  (
202  "void Foam::attachDetach::checkDefinition()"
203  ) << "Found faces in the zone defining "
204  << "attach/detach boundary which do not belong to "
205  << "either master or slave patch. "
206  << "This is not allowed." << nl
207  << "Problem faces: " << zoneProblemFaces
208  << abort(FatalError);
209  }
210  }
211  }
212 
213  // Check that trigger times are in ascending order
214  bool triggersOK = true;
215 
216  for (label i = 0; i < triggerTimes_.size() - 1; i++)
217  {
218  triggersOK = triggersOK && (triggerTimes_[i] < triggerTimes_[i + 1]);
219  }
220 
221  if
222  (
223  !triggersOK
224  || (triggerTimes_.empty() && !manualTrigger())
225  )
226  {
228  (
229  "void Foam::attachDetach::checkDefinition()"
230  ) << "Problem with definition of trigger times: "
231  << triggerTimes_
232  << abort(FatalError);
233  }
234 }
235 
236 
237 void Foam::attachDetach::clearAddressing() const
238 {
239  deleteDemandDrivenData(pointMatchMapPtr_);
240 }
241 
242 
243 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
244 
245 // Construct from components
246 Foam::attachDetach::attachDetach
247 (
248  const word& name,
249  const label index,
250  const polyTopoChanger& mme,
251  const word& faceZoneName,
252  const word& masterPatchName,
253  const word& slavePatchName,
254  const scalarField& triggerTimes,
255  const bool manualTrigger
256 )
257 :
258  polyMeshModifier(name, index, mme, true),
259  faceZoneID_(faceZoneName, mme.mesh().faceZones()),
260  masterPatchID_(masterPatchName, mme.mesh().boundaryMesh()),
261  slavePatchID_(slavePatchName, mme.mesh().boundaryMesh()),
262  triggerTimes_(triggerTimes),
263  manualTrigger_(manualTrigger),
264  triggerIndex_(0),
265  state_(UNKNOWN),
266  trigger_(false),
267  pointMatchMapPtr_(NULL)
268 {
269  checkDefinition();
270 }
271 
272 
273 // Construct from components
274 Foam::attachDetach::attachDetach
275 (
276  const word& name,
277  const dictionary& dict,
278  const label index,
279  const polyTopoChanger& mme
280 )
281 :
282  polyMeshModifier(name, index, mme, Switch(dict.lookup("active"))),
283  faceZoneID_
284  (
285  dict.lookup("faceZoneName"),
286  mme.mesh().faceZones()
287  ),
288  masterPatchID_
289  (
290  dict.lookup("masterPatchName"),
291  mme.mesh().boundaryMesh()
292  ),
293  slavePatchID_
294  (
295  dict.lookup("slavePatchName"),
296  mme.mesh().boundaryMesh()
297  ),
298  triggerTimes_(dict.lookup("triggerTimes")),
299  manualTrigger_(dict.lookup("manualTrigger")),
300  triggerIndex_(0),
301  state_(UNKNOWN),
302  trigger_(false),
303  pointMatchMapPtr_(NULL)
304 {
305  checkDefinition();
306 }
307 
308 
309 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
310 
312 {
313  clearAddressing();
314 }
315 
316 
317 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
318 
320 {
321  if (!attached())
322  {
323  trigger_ = true;
324  }
325  else
326  {
327  trigger_ = false;
328  }
329 
330  return trigger_;
331 }
332 
333 
335 {
336  if (attached())
337  {
338  trigger_ = true;
339  }
340  else
341  {
342  trigger_ = false;
343  }
344 
345  return trigger_;
346 }
347 
348 
350 {
351  if (manualTrigger())
352  {
353  if (debug)
354  {
355  Pout<< "bool attachDetach::changeTopology() const "
356  << " for object " << name() << " : "
357  << "Manual trigger" << endl;
358  }
359 
360  return trigger_;
361  }
362 
363  // To deal with multiple calls within the same time step, return true
364  // if trigger is already set
365  if (trigger_)
366  {
367  if (debug)
368  {
369  Pout<< "bool attachDetach::changeTopology() const "
370  << " for object " << name() << " : "
371  << "Already triggered for current time step" << endl;
372  }
373 
374  return true;
375  }
376 
377  // If the end of the list of trigger times has been reached, no
378  // new topological changes will happen
379  if (triggerIndex_ >= triggerTimes_.size())
380  {
381  if (debug)
382  {
383  Pout<< "bool attachDetach::changeTopology() const "
384  << " for object " << name() << " : "
385  << "Reached end of trigger list" << endl;
386  }
387  return false;
388  }
389 
390  if (debug)
391  {
392  Pout<< "bool attachDetach::changeTopology() const "
393  << " for object " << name() << " : "
394  << "Triggering attach/detach topology change." << nl
395  << "Current time: " << topoChanger().mesh().time().value()
396  << " current trigger time: " << triggerTimes_[triggerIndex_]
397  << " trigger index: " << triggerIndex_ << endl;
398  }
399 
400  // Check if the time is greater than the currentTime. If so, increment
401  // the current lookup and request topology change
402  if (topoChanger().mesh().time().value() >= triggerTimes_[triggerIndex_])
403  {
404  trigger_ = true;
405 
406  // Increment the trigger index
407  triggerIndex_++;
408 
409  return true;
410  }
411 
412  // No topological change
413  return false;
414 }
415 
416 
418 {
419  // Insert the attach/detach instructions into the topological change
420 
421  if (trigger_)
422  {
423  // Clear point addressing from previous attach/detach event
424  clearAddressing();
425 
426  if (state_ == ATTACHED)
427  {
428  detachInterface(ref);
429 
430  // Set the state to detached
431  state_ = DETACHED;
432  }
433  else if (state_ == DETACHED)
434  {
435  attachInterface(ref);
436 
437  // Set the state to attached
438  state_ = ATTACHED;
439  }
440  else
441  {
443  (
444  "void attachDetach::setRefinement(polyTopoChange&) const"
445  ) << "Requested attach/detach event and currect state "
446  << "is not known."
447  << abort(FatalError);
448  }
449 
450  trigger_ = false;
451  }
452 }
453 
454 
456 {
457  // Mesh has changed topologically. Update local topological data
458  const polyMesh& mesh = topoChanger().mesh();
459 
460  faceZoneID_.update(mesh.faceZones());
461  masterPatchID_.update(mesh.boundaryMesh());
462  slavePatchID_.update(mesh.boundaryMesh());
463 
464  clearAddressing();
465 }
466 
467 
469 {
470  os << nl << type() << nl
471  << name()<< nl
472  << faceZoneID_.name() << nl
473  << masterPatchID_.name() << nl
474  << slavePatchID_.name() << nl
475  << triggerTimes_ << endl;
476 }
477 
478 
480 {
481  os << nl << name() << nl << token::BEGIN_BLOCK << nl
482  << " type " << type()
484  << " faceZoneName " << faceZoneID_.name()
486  << " masterPatchName " << masterPatchID_.name()
488  << " slavePatchName " << slavePatchID_.name()
490  << " triggerTimes " << triggerTimes_
492  << " manualTrigger " << manualTrigger()
494  << " active " << active()
496  << token::END_BLOCK << endl;
497 }
498 
499 
500 // ************************************************************************* //
const faceZoneMesh & faceZones() const
Return face zone mesh.
Definition: polyMesh.H:463
virtual void writeDict(Ostream &) const
Write dictionary.
Definition: attachDetach.C:479
virtual void setRefinement(polyTopoChange &) const
Insert the layer addition/removal instructions.
Definition: attachDetach.C:417
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:158
Virtual base class for mesh modifiers.
void deleteDemandDrivenData(DataPtr &dataPtr)
A class for handling words, derived from string.
Definition: word.H:59
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
virtual bool changeTopology() const
Check for topology change.
Definition: attachDetach.C:349
A simple wrapper around bool so that it can be read as a word: true/false, on/off, yes/no, y/n, t/f, or none.
Definition: Switch.H:60
const polyMesh & mesh() const
Return the mesh reference.
dynamicFvMesh & mesh
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
Namespace for OpenFOAM.
static const char nl
Definition: Ostream.H:260
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
bool setDetach() const
Definition: attachDetach.C:334
virtual void updateMesh(const mapPolyMesh &)
Force recalculation of locally stored data on topological change.
Definition: attachDetach.C:455
virtual ~attachDetach()
Destructor.
Definition: attachDetach.C:311
#define forAll(list, i)
Definition: UList.H:421
Macros for easy insertion into run-time selection tables.
List of mesh modifiers defining the mesh dynamics.
errorManip< error > abort(error &err)
Definition: errorManip.H:131
fileName::Type type(const fileName &)
Return the file type: DIRECTORY or FILE.
Definition: POSIX.C:589
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:421
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:452
error FatalError
List< label > labelList
A List of labels.
Definition: labelList.H:56
bool setAttach() const
Definition: attachDetach.C:319
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
Direct mesh changes based on v1.3 polyTopoChange syntax.
virtual void write(Ostream &) const
Write.
Definition: attachDetach.C:468
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
defineTypeNameAndDebug(combustionModel, 0)
prefixOSstream Pout(cout,"Pout")
Definition: IOstreams.H:53