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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 Description
27  Attach/detach boundary mesh modifier. This modifier takes a set of
28  internal faces and converts them into boundary faces and vice versa
29  based on the given activation switch.
30 
31 \*---------------------------------------------------------------------------*/
32 
33 #include "attachDetach.H"
34 #include "polyTopoChanger.H"
35 #include "polyMesh.H"
36 #include "Time.H"
37 #include "primitiveMesh.H"
38 #include "polyTopoChange.H"
40 
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 
43 namespace Foam
44 {
45  defineTypeNameAndDebug(attachDetach, 0);
47  (
48  polyMeshModifier,
49  attachDetach,
50  dictionary
51  );
52 }
53 
54 
55 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
56 
57 void Foam::attachDetach::checkDefinition()
58 {
59  if
60  (
61  !faceZoneID_.active()
62  || !masterPatchID_.active()
63  || !slavePatchID_.active()
64  )
65  {
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  << "mesh definition."
102  << abort(FatalError);
103  }
104 
105  // Check that all the faces in the face zone are internal
106  if (debug)
107  {
108  const labelList& addr = mesh.faceZones()[faceZoneID_.index()];
109 
110  DynamicList<label> bouFacesInZone(addr.size());
111 
112  forAll(addr, facei)
113  {
114  if (!mesh.isInternalFace(addr[facei]))
115  {
116  bouFacesInZone.append(addr[facei]);
117  }
118  }
119 
120  if (bouFacesInZone.size())
121  {
123  << "Found boundary faces in the zone defining "
124  << "attach/detach boundary "
125  << " for object " << name()
126  << " : . This is not allowed." << nl
127  << "Boundary faces: " << bouFacesInZone
128  << abort(FatalError);
129  }
130  }
131  }
132  else
133  {
134  // Boundary is detached
135  if (debug)
136  {
137  Pout<< " Detached on construction" << endl;
138  }
139 
140  state_ = DETACHED;
141 
142  // Check that the sizes of master and slave patch are identical
143  // and identical to the size of the face zone
144  if
145  (
146  (
147  mesh.boundaryMesh()[masterPatchID_.index()].size()
148  != mesh.boundaryMesh()[slavePatchID_.index()].size()
149  )
150  || (
151  mesh.boundaryMesh()[masterPatchID_.index()].size()
152  != mesh.faceZones()[faceZoneID_.index()].size()
153  )
154  )
155  {
157  << "Problem with sizes in mesh modifier. The face zone,"
158  << " master and slave patch should have the same size"
159  << " for object " << name() << ". " << nl
160  << "Zone size: "
161  << mesh.faceZones()[faceZoneID_.index()].size()
162  << " Master patch size: "
163  << mesh.boundaryMesh()[masterPatchID_.index()].size()
164  << " Slave patch size: "
165  << mesh.boundaryMesh()[slavePatchID_.index()].size()
166  << abort(FatalError);
167  }
168 
169  // Check that all the faces belong to either master or slave patch
170  if (debug)
171  {
172  const labelList& addr = mesh.faceZones()[faceZoneID_.index()];
173 
174  DynamicList<label> zoneProblemFaces(addr.size());
175 
176  forAll(addr, facei)
177  {
178  label facePatch =
179  mesh.boundaryMesh().whichPatch(addr[facei]);
180 
181  if
182  (
183  facePatch != masterPatchID_.index()
184  && facePatch != slavePatchID_.index()
185  )
186  {
187  zoneProblemFaces.append(addr[facei]);
188  }
189  }
190 
191  if (zoneProblemFaces.size())
192  {
194  << "Found faces in the zone defining "
195  << "attach/detach boundary which do not belong to "
196  << "either master or slave patch. "
197  << "This is not allowed." << nl
198  << "Problem faces: " << zoneProblemFaces
199  << abort(FatalError);
200  }
201  }
202  }
203 
204  // Check that trigger times are in ascending order
205  bool triggersOK = true;
206 
207  for (label i = 0; i < triggerTimes_.size() - 1; i++)
208  {
209  triggersOK = triggersOK && (triggerTimes_[i] < triggerTimes_[i + 1]);
210  }
211 
212  if
213  (
214  !triggersOK
215  || (triggerTimes_.empty() && !manualTrigger())
216  )
217  {
219  << "Problem with definition of trigger times: "
220  << triggerTimes_
221  << abort(FatalError);
222  }
223 }
224 
225 
226 void Foam::attachDetach::clearAddressing() const
227 {
228  deleteDemandDrivenData(pointMatchMapPtr_);
229 }
230 
231 
232 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
233 
234 // Construct from components
235 Foam::attachDetach::attachDetach
236 (
237  const word& name,
238  const label index,
239  const polyTopoChanger& mme,
240  const word& faceZoneName,
241  const word& masterPatchName,
242  const word& slavePatchName,
243  const scalarField& triggerTimes,
244  const bool manualTrigger
245 )
246 :
247  polyMeshModifier(name, index, mme, true),
248  faceZoneID_(faceZoneName, mme.mesh().faceZones()),
249  masterPatchID_(masterPatchName, mme.mesh().boundaryMesh()),
250  slavePatchID_(slavePatchName, mme.mesh().boundaryMesh()),
251  triggerTimes_(triggerTimes),
252  manualTrigger_(manualTrigger),
253  triggerIndex_(0),
254  state_(UNKNOWN),
255  trigger_(false),
256  pointMatchMapPtr_(nullptr)
257 {
258  checkDefinition();
259 }
260 
261 
262 // Construct from components
263 Foam::attachDetach::attachDetach
264 (
265  const word& name,
266  const dictionary& dict,
267  const label index,
268  const polyTopoChanger& mme
269 )
270 :
271  polyMeshModifier(name, index, mme, dict.get<bool>("active")),
272  faceZoneID_
273  (
274  dict.lookup("faceZoneName"),
275  mme.mesh().faceZones()
276  ),
277  masterPatchID_
278  (
279  dict.lookup("masterPatchName"),
280  mme.mesh().boundaryMesh()
281  ),
282  slavePatchID_
283  (
284  dict.lookup("slavePatchName"),
285  mme.mesh().boundaryMesh()
286  ),
287  triggerTimes_(dict.lookup("triggerTimes")),
288  manualTrigger_(dict.lookup("manualTrigger")),
289  triggerIndex_(0),
290  state_(UNKNOWN),
291  trigger_(false),
292  pointMatchMapPtr_(nullptr)
293 {
294  checkDefinition();
295 }
296 
297 
298 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
299 
301 {
302  clearAddressing();
303 }
304 
305 
306 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
307 
309 {
310  if (!attached())
311  {
312  trigger_ = true;
313  }
314  else
315  {
316  trigger_ = false;
317  }
318 
319  return trigger_;
320 }
321 
322 
324 {
325  if (attached())
326  {
327  trigger_ = true;
328  }
329  else
330  {
331  trigger_ = false;
332  }
333 
334  return trigger_;
335 }
336 
337 
339 {
340  if (manualTrigger())
341  {
342  if (debug)
343  {
344  Pout<< "bool attachDetach::changeTopology() const "
345  << " for object " << name() << " : "
346  << "Manual trigger" << endl;
347  }
348 
349  return trigger_;
350  }
351 
352  // To deal with multiple calls within the same time step, return true
353  // if trigger is already set
354  if (trigger_)
355  {
356  if (debug)
357  {
358  Pout<< "bool attachDetach::changeTopology() const "
359  << " for object " << name() << " : "
360  << "Already triggered for current time step" << endl;
361  }
362 
363  return true;
364  }
365 
366  // If the end of the list of trigger times has been reached, no
367  // new topological changes will happen
368  if (triggerIndex_ >= triggerTimes_.size())
369  {
370  if (debug)
371  {
372  Pout<< "bool attachDetach::changeTopology() const "
373  << " for object " << name() << " : "
374  << "Reached end of trigger list" << endl;
375  }
376  return false;
377  }
378 
379  if (debug)
380  {
381  Pout<< "bool attachDetach::changeTopology() const "
382  << " for object " << name() << " : "
383  << "Triggering attach/detach topology change." << nl
384  << "Current time: " << topoChanger().mesh().time().value()
385  << " current trigger time: " << triggerTimes_[triggerIndex_]
386  << " trigger index: " << triggerIndex_ << endl;
387  }
388 
389  // Check if the time is greater than the currentTime. If so, increment
390  // the current lookup and request topology change
391  if (topoChanger().mesh().time().value() >= triggerTimes_[triggerIndex_])
392  {
393  trigger_ = true;
394 
395  // Increment the trigger index
396  triggerIndex_++;
397 
398  return true;
399  }
400 
401  // No topological change
402  return false;
403 }
404 
405 
407 {
408  // Insert the attach/detach instructions into the topological change
409 
410  if (trigger_)
411  {
412  // Clear point addressing from previous attach/detach event
413  clearAddressing();
414 
415  if (state_ == ATTACHED)
416  {
417  detachInterface(ref);
418 
419  // Set the state to detached
420  state_ = DETACHED;
421  }
422  else if (state_ == DETACHED)
423  {
424  attachInterface(ref);
425 
426  // Set the state to attached
427  state_ = ATTACHED;
428  }
429  else
430  {
432  << "Requested attach/detach event and currect state "
433  << "is not known."
434  << abort(FatalError);
435  }
436 
437  trigger_ = false;
438  }
439 }
440 
441 
443 {
444  // Mesh has changed topologically. Update local topological data
445  const polyMesh& mesh = topoChanger().mesh();
446 
447  faceZoneID_.update(mesh.faceZones());
448  masterPatchID_.update(mesh.boundaryMesh());
449  slavePatchID_.update(mesh.boundaryMesh());
450 
451  clearAddressing();
452 }
453 
454 
456 {
457  os << nl << type() << nl
458  << name()<< nl
459  << faceZoneID_.name() << nl
460  << masterPatchID_.name() << nl
461  << slavePatchID_.name() << nl
462  << triggerTimes_ << endl;
463 }
464 
465 
467 {
468  os << nl;
469  os.beginBlock(name());
470 
471  os.writeEntry("type", type());
472  os.writeEntry("faceZoneName", faceZoneID_.name());
473  os.writeEntry("masterPatchName", masterPatchID_.name());
474  os.writeEntry("slavePatchName", slavePatchID_.name());
475  os.writeEntry("triggerTimes", triggerTimes_);
476  os.writeEntry("manualTrigger", manualTrigger());
477  os.writeEntry("active", active());
478 
479  os.endBlock();
480 }
481 
482 
483 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:74
ref
rDeltaT ref()
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::attachDetach::changeTopology
virtual bool changeTopology() const
Check for topology change.
Definition: attachDetach.C:338
Foam::attachDetach::updateMesh
virtual void updateMesh(const mapPolyMesh &)
Force recalculation of locally stored data on topological change.
Definition: attachDetach.C:442
Foam::dynamicFvMesh::update
virtual bool update()=0
Update the mesh for both mesh motion and topology change.
Foam::polyMeshModifier::topoChanger
const polyTopoChanger & topoChanger() const
Return reference to morph engine.
Definition: polyMeshModifier.C:71
Foam::attachDetach::writeDict
virtual void writeDict(Ostream &) const
Write dictionary.
Definition: attachDetach.C:466
Foam::polyTopoChanger
List of mesh modifiers defining the mesh dynamics.
Definition: polyTopoChanger.H:67
polyTopoChanger.H
polyTopoChange.H
Foam::polyTopoChange
Direct mesh changes based on v1.3 polyTopoChange syntax.
Definition: polyTopoChange.H:100
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:435
primitiveMesh.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::Ostream::beginBlock
virtual Ostream & beginBlock(const keyType &kw)
Write begin block group with the given name.
Definition: Ostream.C:91
Foam::dictionary::get
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:81
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
polyMesh.H
Foam::attachDetach::write
virtual void write(Ostream &) const
Write.
Definition: attachDetach.C:455
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const
Return face zone mesh.
Definition: polyMesh.H:477
Foam::deleteDemandDrivenData
void deleteDemandDrivenData(DataPtr &dataPtr)
Definition: demandDrivenData.H:42
Foam::label
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:62
Foam::Field< scalar >
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::attachDetach::setDetach
bool setDetach() const
Definition: attachDetach.C:323
Foam::attachDetach::setAttach
bool setAttach() const
Definition: attachDetach.C:308
Foam::dictionary::lookup
ITstream & lookup(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionary.C:419
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::Ostream::endBlock
virtual Ostream & endBlock()
Write end block group.
Definition: Ostream.C:109
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::polyMeshModifier
Virtual base class for mesh modifiers.
Definition: polyMeshModifier.H:71
Foam::polyMeshModifier::name
const word & name() const
Return name of this modifier.
Definition: polyMeshModifier.H:153
Time.H
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::polyTopoChanger::mesh
const polyMesh & mesh() const
Return the mesh reference.
Definition: polyTopoChanger.H:116
Foam::type
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:590
attachDetach.H
Foam::Ostream::writeEntry
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:219
Foam::mapPolyMesh
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:160
Foam::attachDetach::~attachDetach
virtual ~attachDetach()
Destructor.
Definition: attachDetach.C:300
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::attachDetach::setRefinement
virtual void setRefinement(polyTopoChange &) const
Insert the layer addition/removal instructions.
Definition: attachDetach.C:406
Foam::DynamicID::active
bool active() const
Has the zone been found.
Definition: DynamicID.H:116
Foam::DynamicID::index
label index() const
Return index of first matching zone.
Definition: DynamicID.H:110
Foam::attachDetach::manualTrigger
const Switch & manualTrigger() const
Definition: attachDetach.H:199