rectangle_with_hole_domain.h
Go to the documentation of this file.
1 // LIC// ====================================================================
2 // LIC// This file forms part of oomph-lib, the object-oriented,
3 // LIC// multi-physics finite-element library, available
4 // LIC// at http://www.oomph-lib.org.
5 // LIC//
6 // LIC// Copyright (C) 2006-2023 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 #ifndef OOMPH_RECTANGLE_WITH_HOLE_DOMAIN_HEADER
27 #define OOMPH_RECTANGLE_WITH_HOLE_DOMAIN_HEADER
28 
29 
30 // Generic includes
31 #include "../generic/quadtree.h"
32 #include "../generic/geom_objects.h"
33 #include "../generic/macro_element.h"
34 #include "../generic/domain.h"
35 
36 
37 namespace oomph
38 {
39  //===========================================================
40  /// Rectangular domain with circular whole
41  //===========================================================
43  {
44  public:
45  /// Constructor. Pass pointer to geometric object that
46  /// represents the cylinder, the length of the (square) domain.
47  /// The GeomObject must be parametrised such that
48  /// \f$\zeta \in [0,2\pi]\f$ sweeps around the circumference
49  /// in anticlockwise direction.
50  RectangleWithHoleDomain(GeomObject* cylinder_pt, const double& length)
51  : Cylinder_pt(cylinder_pt)
52  {
53  // Vertices of rectangle
54  Lower_left.resize(2);
55  Lower_left[0] = -0.5 * length;
56  Lower_left[1] = -0.5 * length;
57 
58  Upper_left.resize(2);
59  Upper_left[0] = -0.5 * length;
60  Upper_left[1] = 0.5 * length;
61 
62  Lower_right.resize(2);
63  Lower_right[0] = 0.5 * length;
64  Lower_right[1] = -0.5 * length;
65 
66  Upper_right.resize(2);
67  Upper_right[0] = 0.5 * length;
68  Upper_right[1] = 0.5 * length;
69 
70 
71  // Coordinates of points where the "radial" lines from central
72  // cylinder meet the upper and lower boundaries
73  Lower_mid_left.resize(2);
74  Lower_mid_left[0] = -0.5 * length;
75  Lower_mid_left[1] = -0.5 * length;
76 
77  Upper_mid_left.resize(2);
78  Upper_mid_left[0] = -0.5 * length;
79  Upper_mid_left[1] = 0.5 * length;
80 
81  Lower_mid_right.resize(2);
82  Lower_mid_right[0] = 0.5 * length;
83  Lower_mid_right[1] = -0.5 * length;
84 
85  Upper_mid_right.resize(2);
86  Upper_mid_right[0] = 0.5 * length;
87  Upper_mid_right[1] = 0.5 * length;
88 
89 
90  // There are four macro elements
91  Macro_element_pt.resize(4);
92 
93  // Build the 2D macro elements
94  for (unsigned i = 0; i < 4; i++)
95  {
96  Macro_element_pt[i] = new QMacroElement<2>(this, i);
97  }
98  }
99 
100 
101  /// Destructor: Empty; cleanup done in base class
103 
104  /// Helper function to interpolate linearly between the
105  /// "right" and "left" points; \f$ s \in [-1,1] \f$
107  Vector<double> right,
108  const double& s,
109  Vector<double>& f)
110  {
111  for (unsigned i = 0; i < 2; i++)
112  {
113  f[i] = left[i] + (right[i] - left[i]) * 0.5 * (s + 1.0);
114  }
115  }
116 
117 
118  /// Parametrisation of macro element boundaries: f(s) is the position
119  /// vector to macro-element m's boundary in the specified direction
120  /// [N/S/E/W] at the specfied discrete time level (time=0: present; time>0:
121  /// previous)
122  void macro_element_boundary(const unsigned& time,
123  const unsigned& m,
124  const unsigned& direction,
125  const Vector<double>& s,
126  Vector<double>& f)
127  {
128 #ifdef WARN_ABOUT_SUBTLY_CHANGED_OOMPH_INTERFACES
129  // Warn about time argument being moved to the front
131  "Order of function arguments has changed between versions 0.8 and 0.85",
132  "RectangleWithHoleDomain::macro_element_boundary(...)",
133  OOMPH_EXCEPTION_LOCATION);
134 #endif
135 
136  // Lagrangian coordinate along surface of cylinder
137  Vector<double> xi(1);
138 
139  // Point on circle
140  Vector<double> point_on_circle(2);
141 
142  using namespace QuadTreeNames;
143 
144  // Switch on the macro element
145  switch (m)
146  {
147  // Macro element 0, is is immediately left of the cylinder
148  case 0:
149 
150  switch (direction)
151  {
152  case N:
153  xi[0] = 3.0 * atan(1.0);
154  Cylinder_pt->position(time, xi, point_on_circle);
155  linear_interpolate(Upper_mid_left, point_on_circle, s[0], f);
156  break;
157 
158  case S:
159  xi[0] = -3.0 * atan(1.0);
160  Cylinder_pt->position(time, xi, point_on_circle);
161  linear_interpolate(Lower_mid_left, point_on_circle, s[0], f);
162  break;
163 
164  case W:
166  break;
167 
168  case E:
169  xi[0] = 5.0 * atan(1.0) - 2.0 * atan(1.0) * 0.5 * (1.0 + s[0]);
170  Cylinder_pt->position(time, xi, f);
171  break;
172 
173  default:
174 
175  std::ostringstream error_stream;
176  error_stream << "Direction is incorrect: " << direction
177  << std::endl;
178  throw OomphLibError(error_stream.str(),
179  OOMPH_CURRENT_FUNCTION,
180  OOMPH_EXCEPTION_LOCATION);
181  }
182 
183  break;
184 
185  // Macro element 1, is immediately above the cylinder
186  case 1:
187 
188  switch (direction)
189  {
190  case N:
192  break;
193 
194  case S:
195  xi[0] = 3.0 * atan(1.0) - 2.0 * atan(1.0) * 0.5 * (1.0 + s[0]);
196  Cylinder_pt->position(time, xi, f);
197  break;
198 
199  case W:
200  xi[0] = 3.0 * atan(1.0);
201  Cylinder_pt->position(time, xi, point_on_circle);
202  linear_interpolate(point_on_circle, Upper_mid_left, s[0], f);
203  break;
204 
205  case E:
206  xi[0] = 1.0 * atan(1.0);
207  Cylinder_pt->position(time, xi, point_on_circle);
208  linear_interpolate(point_on_circle, Upper_mid_right, s[0], f);
209  break;
210 
211  default:
212 
213  std::ostringstream error_stream;
214  error_stream << "Direction is incorrect: " << direction
215  << std::endl;
216  throw OomphLibError(error_stream.str(),
217  OOMPH_CURRENT_FUNCTION,
218  OOMPH_EXCEPTION_LOCATION);
219  }
220 
221  break;
222 
223  // Macro element 2, is immediately right of the cylinder
224  case 2:
225 
226  switch (direction)
227  {
228  case N:
229  xi[0] = 1.0 * atan(1.0);
230  Cylinder_pt->position(time, xi, point_on_circle);
231  linear_interpolate(point_on_circle, Upper_mid_right, s[0], f);
232  break;
233 
234  case S:
235  xi[0] = -1.0 * atan(1.0);
236  Cylinder_pt->position(time, xi, point_on_circle);
237  linear_interpolate(point_on_circle, Lower_mid_right, s[0], f);
238  break;
239 
240  case W:
241  xi[0] = -atan(1.0) + 2.0 * atan(1.0) * 0.5 * (1.0 + s[0]);
242  Cylinder_pt->position(time, xi, f);
243  break;
244 
245  case E:
247  break;
248 
249  default:
250 
251  std::ostringstream error_stream;
252  error_stream << "Direction is incorrect: " << direction
253  << std::endl;
254  throw OomphLibError(error_stream.str(),
255  OOMPH_CURRENT_FUNCTION,
256  OOMPH_EXCEPTION_LOCATION);
257  }
258 
259  break;
260 
261  // Macro element 3, is immediately below cylinder
262  case 3:
263 
264  switch (direction)
265  {
266  case N:
267  xi[0] = -3.0 * atan(1.0) + 2.0 * atan(1.0) * 0.5 * (1.0 + s[0]);
268  Cylinder_pt->position(time, xi, f);
269  break;
270 
271  case S:
273  break;
274 
275  case W:
276  xi[0] = -3.0 * atan(1.0);
277  Cylinder_pt->position(time, xi, point_on_circle);
278  linear_interpolate(Lower_mid_left, point_on_circle, s[0], f);
279  break;
280 
281  case E:
282  xi[0] = -1.0 * atan(1.0);
283  Cylinder_pt->position(time, xi, point_on_circle);
284  linear_interpolate(Lower_mid_right, point_on_circle, s[0], f);
285  break;
286 
287  default:
288 
289  std::ostringstream error_stream;
290  error_stream << "Direction is incorrect: " << direction
291  << std::endl;
292  throw OomphLibError(error_stream.str(),
293  OOMPH_CURRENT_FUNCTION,
294  OOMPH_EXCEPTION_LOCATION);
295  }
296 
297  break;
298 
299  default:
300 
301  std::ostringstream error_stream;
302  error_stream << "Wrong macro element number" << m << std::endl;
303  throw OomphLibError(error_stream.str(),
304  OOMPH_CURRENT_FUNCTION,
305  OOMPH_EXCEPTION_LOCATION);
306  }
307  }
308 
309 
310  private:
311  /// Lower left corner of rectangle
313 
314  /// Lower right corner of rectangle
316 
317  /// Where the "radial" line from circle meets lower boundary on left
319 
320  /// Where the "radial" line from circle meets lower boundary on right
322 
323  /// Upper left corner of rectangle
325 
326  /// Upper right corner of rectangle
328 
329  /// Where the "radial" line from circle meets upper boundary on left
331 
332  /// Where the "radial" line from circle meets upper boundary on right
334 
335  /// Pointer to geometric object that represents the central cylinder
337  };
338 
339 
340 } // namespace oomph
341 #endif
static char t char * s
Definition: cfortran.h:568
cstr elem_len * i
Definition: cfortran.h:603
Base class for Domains with curvilinear and/or time-dependent boundaries. Domain boundaries are typic...
Definition: domain.h:67
Vector< MacroElement * > Macro_element_pt
Vector of pointers to macro elements.
Definition: domain.h:301
/////////////////////////////////////////////////////////////////////
Definition: geom_objects.h:101
virtual void position(const Vector< double > &zeta, Vector< double > &r) const =0
Parametrised position on object at current time: r(zeta).
An OomphLibError object which should be thrown when an run-time error is encountered....
An OomphLibWarning object which should be created as a temporary object to issue a warning....
QMacroElement specialised to 2 spatial dimensions.
Rectangular domain with circular whole.
Vector< double > Upper_mid_left
Where the "radial" line from circle meets upper boundary on left.
Vector< double > Upper_left
Upper left corner of rectangle.
Vector< double > Upper_right
Upper right corner of rectangle.
RectangleWithHoleDomain(GeomObject *cylinder_pt, const double &length)
Constructor. Pass pointer to geometric object that represents the cylinder, the length of the (square...
GeomObject * Cylinder_pt
Pointer to geometric object that represents the central cylinder.
void macro_element_boundary(const unsigned &time, const unsigned &m, const unsigned &direction, const Vector< double > &s, Vector< double > &f)
Parametrisation of macro element boundaries: f(s) is the position vector to macro-element m's boundar...
Vector< double > Lower_left
Lower left corner of rectangle.
void linear_interpolate(Vector< double > left, Vector< double > right, const double &s, Vector< double > &f)
Helper function to interpolate linearly between the "right" and "left" points; .
Vector< double > Lower_mid_right
Where the "radial" line from circle meets lower boundary on right.
Vector< double > Upper_mid_right
Where the "radial" line from circle meets upper boundary on right.
Vector< double > Lower_mid_left
Where the "radial" line from circle meets lower boundary on left.
Vector< double > Lower_right
Lower right corner of rectangle.
~RectangleWithHoleDomain()
Destructor: Empty; cleanup done in base class.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...