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  Copyright (C) 2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "attachDetach.H"
30 #include "polyTopoChanger.H"
31 #include "polyMesh.H"
32 #include "Time.H"
33 #include "primitiveMesh.H"
34 #include "polyTopoChange.H"
36 
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 
39 namespace Foam
40 {
41  defineTypeNameAndDebug(attachDetach, 0);
43  (
44  polyMeshModifier,
45  attachDetach,
46  dictionary
47  );
48 }
49 
50 
51 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52 
53 void Foam::attachDetach::checkDefinition()
54 {
55  if
56  (
57  !faceZoneID_.active()
58  || !masterPatchID_.active()
59  || !slavePatchID_.active()
60  )
61  {
63  << "Not all zones and patches needed in the definition "
64  << "have been found. Please check your mesh definition."
65  << abort(FatalError);
66  }
67 
68  const polyMesh& mesh = topoChanger().mesh();
69 
70  if (debug)
71  {
72  Pout<< "Attach/detach object " << name() << " :" << nl
73  << " faceZoneID: " << faceZoneID_ << nl
74  << " masterPatchID: " << masterPatchID_ << nl
75  << " slavePatchID: " << slavePatchID_ << endl;
76  }
77 
78  // Check the sizes and set up state
79  if
80  (
81  mesh.boundaryMesh()[masterPatchID_.index()].empty()
82  && mesh.boundaryMesh()[slavePatchID_.index()].empty()
83  )
84  {
85  // Boundary is attached
86  if (debug)
87  {
88  Pout<< " Attached on construction" << endl;
89  }
90 
91  state_ = ATTACHED;
92 
93  // Check if there are faces in the master zone
94  if (mesh.faceZones()[faceZoneID_.index()].empty())
95  {
97  << "mesh definition."
98  << abort(FatalError);
99  }
100 
101  // Check that all the faces in the face zone are internal
102  if (debug)
103  {
104  const labelList& addr = mesh.faceZones()[faceZoneID_.index()];
105 
106  DynamicList<label> bouFacesInZone(addr.size());
107 
108  forAll(addr, facei)
109  {
110  if (!mesh.isInternalFace(addr[facei]))
111  {
112  bouFacesInZone.append(addr[facei]);
113  }
114  }
115 
116  if (bouFacesInZone.size())
117  {
119  << "Found boundary faces in the zone defining "
120  << "attach/detach boundary "
121  << " for object " << name()
122  << " : . This is not allowed." << nl
123  << "Boundary faces: " << bouFacesInZone
124  << abort(FatalError);
125  }
126  }
127  }
128  else
129  {
130  // Boundary is detached
131  if (debug)
132  {
133  Pout<< " Detached on construction" << endl;
134  }
135 
136  state_ = DETACHED;
137 
138  // Check that the sizes of master and slave patch are identical
139  // and identical to the size of the face zone
140  if
141  (
142  (
143  mesh.boundaryMesh()[masterPatchID_.index()].size()
144  != mesh.boundaryMesh()[slavePatchID_.index()].size()
145  )
146  || (
147  mesh.boundaryMesh()[masterPatchID_.index()].size()
148  != mesh.faceZones()[faceZoneID_.index()].size()
149  )
150  )
151  {
153  << "Problem with sizes in mesh modifier. The face zone,"
154  << " master and slave patch should have the same size"
155  << " for object " << name() << ". " << nl
156  << "Zone size: "
157  << mesh.faceZones()[faceZoneID_.index()].size()
158  << " Master patch size: "
159  << mesh.boundaryMesh()[masterPatchID_.index()].size()
160  << " Slave patch size: "
161  << mesh.boundaryMesh()[slavePatchID_.index()].size()
162  << abort(FatalError);
163  }
164 
165  // Check that all the faces belong to either master or slave patch
166  if (debug)
167  {
168  const labelList& addr = mesh.faceZones()[faceZoneID_.index()];
169 
170  DynamicList<label> zoneProblemFaces(addr.size());
171 
172  forAll(addr, facei)
173  {
174  label facePatch =
175  mesh.boundaryMesh().whichPatch(addr[facei]);
176 
177  if
178  (
179  facePatch != masterPatchID_.index()
180  && facePatch != slavePatchID_.index()
181  )
182  {
183  zoneProblemFaces.append(addr[facei]);
184  }
185  }
186 
187  if (zoneProblemFaces.size())
188  {
190  << "Found faces in the zone defining "
191  << "attach/detach boundary which do not belong to "
192  << "either master or slave patch. "
193  << "This is not allowed." << nl
194  << "Problem faces: " << zoneProblemFaces
195  << abort(FatalError);
196  }
197  }
198  }
199 
200  // Check that trigger times are in ascending order
201  bool triggersOK = true;
202 
203  for (label i = 0; i < triggerTimes_.size() - 1; i++)
204  {
205  triggersOK = triggersOK && (triggerTimes_[i] < triggerTimes_[i + 1]);
206  }
207 
208  if
209  (
210  !triggersOK
211  || (triggerTimes_.empty() && !manualTrigger_)
212  )
213  {
215  << "Problem with definition of trigger times: "
216  << triggerTimes_
217  << abort(FatalError);
218  }
219 }
220 
221 
222 void Foam::attachDetach::clearAddressing() const
223 {
224  pointMatchMapPtr_.reset(nullptr);
225 }
226 
227 
228 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
229 
230 Foam::attachDetach::attachDetach
231 (
232  const word& name,
233  const label index,
234  const polyTopoChanger& mme,
235  const word& faceZoneName,
236  const word& masterPatchName,
237  const word& slavePatchName,
238  const scalarField& triggerTimes,
239  const bool manualTrigger
240 )
241 :
242  polyMeshModifier(name, index, mme, true),
243  faceZoneID_(faceZoneName, mme.mesh().faceZones()),
244  masterPatchID_(masterPatchName, mme.mesh().boundaryMesh()),
245  slavePatchID_(slavePatchName, mme.mesh().boundaryMesh()),
246  triggerTimes_(triggerTimes),
247  triggerIndex_(0),
248  state_(UNKNOWN),
249  manualTrigger_(manualTrigger),
250  trigger_(false),
251  pointMatchMapPtr_(nullptr)
252 {
253  checkDefinition();
254 }
255 
256 
257 Foam::attachDetach::attachDetach
258 (
259  const word& name,
260  const dictionary& dict,
261  const label index,
262  const polyTopoChanger& mme
263 )
264 :
265  polyMeshModifier(name, index, mme, dict.get<bool>("active")),
266  faceZoneID_
267  (
268  dict.lookup("faceZoneName"),
269  mme.mesh().faceZones()
270  ),
271  masterPatchID_
272  (
273  dict.lookup("masterPatchName"),
274  mme.mesh().boundaryMesh()
275  ),
276  slavePatchID_
277  (
278  dict.lookup("slavePatchName"),
279  mme.mesh().boundaryMesh()
280  ),
281  triggerTimes_(dict.lookup("triggerTimes")),
282  triggerIndex_(0),
283  state_(UNKNOWN),
284  manualTrigger_(dict.get<bool>("manualTrigger")),
285  trigger_(false),
286  pointMatchMapPtr_(nullptr)
287 {
288  checkDefinition();
289 }
290 
291 
292 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
293 
295 {
296  trigger_ = (!attached());
297 
298  return trigger_;
299 }
300 
301 
303 {
304  trigger_ = (attached());
305 
306  return trigger_;
307 }
308 
309 
311 {
312  if (manualTrigger_)
313  {
314  if (debug)
315  {
316  Pout<< "bool attachDetach::changeTopology() const "
317  << " for object " << name() << " : "
318  << "Manual trigger" << endl;
319  }
320 
321  return trigger_;
322  }
323 
324  // To deal with multiple calls within the same time step, return true
325  // if trigger is already set
326  if (trigger_)
327  {
328  if (debug)
329  {
330  Pout<< "bool attachDetach::changeTopology() const "
331  << " for object " << name() << " : "
332  << "Already triggered for current time step" << endl;
333  }
334 
335  return true;
336  }
337 
338  // If the end of the list of trigger times has been reached, no
339  // new topological changes will happen
340  if (triggerIndex_ >= triggerTimes_.size())
341  {
342  if (debug)
343  {
344  Pout<< "bool attachDetach::changeTopology() const "
345  << " for object " << name() << " : "
346  << "Reached end of trigger list" << endl;
347  }
348  return false;
349  }
350 
351  if (debug)
352  {
353  Pout<< "bool attachDetach::changeTopology() const "
354  << " for object " << name() << " : "
355  << "Triggering attach/detach topology change." << nl
356  << "Current time: " << topoChanger().mesh().time().value()
357  << " current trigger time: " << triggerTimes_[triggerIndex_]
358  << " trigger index: " << triggerIndex_ << endl;
359  }
360 
361  // Check if the time is greater than the currentTime. If so, increment
362  // the current lookup and request topology change
363  if (topoChanger().mesh().time().value() >= triggerTimes_[triggerIndex_])
364  {
365  trigger_ = true;
366 
367  // Increment the trigger index
368  triggerIndex_++;
369 
370  return true;
371  }
372 
373  // No topological change
374  return false;
375 }
376 
377 
379 {
380  // Insert the attach/detach instructions into the topological change
381 
382  if (trigger_)
383  {
384  // Clear point addressing from previous attach/detach event
385  clearAddressing();
386 
387  if (state_ == ATTACHED)
388  {
389  detachInterface(ref);
390 
391  // Set the state to detached
392  state_ = DETACHED;
393  }
394  else if (state_ == DETACHED)
395  {
396  attachInterface(ref);
397 
398  // Set the state to attached
399  state_ = ATTACHED;
400  }
401  else
402  {
404  << "Requested attach/detach event. Current state is unknown."
405  << abort(FatalError);
406  }
407 
408  trigger_ = false;
409  }
410 }
411 
412 
414 {
415  // Mesh has changed topologically. Update local topological data
416  const polyMesh& mesh = topoChanger().mesh();
417 
418  faceZoneID_.update(mesh.faceZones());
419  masterPatchID_.update(mesh.boundaryMesh());
420  slavePatchID_.update(mesh.boundaryMesh());
421 
422  clearAddressing();
423 }
424 
425 
427 {
428  os << nl << type() << nl
429  << name()<< nl
430  << faceZoneID_.name() << nl
431  << masterPatchID_.name() << nl
432  << slavePatchID_.name() << nl
433  << triggerTimes_ << endl;
434 }
435 
436 
438 {
439  os << nl;
440  os.beginBlock(name());
441 
442  os.writeEntry("type", type());
443  os.writeEntry("faceZoneName", faceZoneID_.name());
444  os.writeEntry("masterPatchName", masterPatchID_.name());
445  os.writeEntry("slavePatchName", slavePatchID_.name());
446  os.writeEntry("triggerTimes", triggerTimes_);
447  os.writeEntry("manualTrigger", Switch::name(manualTrigger_));
448  os.writeEntry("active", active());
449 
450  os.endBlock();
451 }
452 
453 
454 // ************************************************************************* //
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:67
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::attachDetach::changeTopology
virtual bool changeTopology() const
Check for topology change.
Definition: attachDetach.C:310
Foam::attachDetach::updateMesh
virtual void updateMesh(const mapPolyMesh &)
Force recalculation of locally stored data on topological change.
Definition: attachDetach.C:413
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:63
Foam::attachDetach::writeDict
virtual void writeDict(Ostream &) const
Write dictionary.
Definition: attachDetach.C:437
Foam::polyTopoChanger
List of mesh modifiers defining the mesh dynamics.
Definition: polyTopoChanger.H:62
polyTopoChanger.H
polyTopoChange.H
Foam::polyTopoChange
Direct mesh changes based on v1.3 polyTopoChange syntax.
Definition: polyTopoChange.H:99
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:444
primitiveMesh.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
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:107
ref
rDeltaT ref()
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
polyMesh.H
Foam::attachDetach::write
virtual void write(Ostream &) const
Write.
Definition: attachDetach.C:426
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:296
Foam::Field< scalar >
Foam::attachDetach::setDetach
bool setDetach() const
Definition: attachDetach.C:302
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:486
Foam::Switch::name
static const char * name(const bool b) noexcept
A string representation of bool as "false" / "true".
Definition: Switch.C:145
Foam::attachDetach::setAttach
bool setAttach() const
Definition: attachDetach.C:294
Foam::dictionary::lookup
ITstream & lookup(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionary.C:386
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:123
os
OBJstream os(runTime.globalPath()/outputName)
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:144
Foam::polyMeshModifier
Virtual base class for mesh modifiers.
Definition: polyMeshModifier.H:68
Foam::polyMeshModifier::name
const word & name() const
Return name of this modifier.
Definition: polyMeshModifier.H:150
Time.H
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::polyTopoChanger::mesh
const polyMesh & mesh() const
Return the mesh reference.
Definition: polyTopoChanger.H:111
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:236
Foam::DynamicID::active
bool active() const noexcept
Has the zone been found.
Definition: DynamicID.H:129
Foam::mapPolyMesh
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:161
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
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:378
Foam::DynamicID::index
label index() const
The index of the first matching items, -1 if no matches.
Definition: DynamicID.H:123