full_circle_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-2025 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
27#ifndef OOMPH_FULL_CIRCLE_DOMAIN_HEADER
28#define OOMPH_FULL_CIRCLE_DOMAIN_HEADER
29
30// Generic oomph-lib includes
31#include "generic/quadtree.h"
32#include "generic/domain.h"
34
35namespace oomph
36{
37 //=================================================================
38 /// Topologically circular domain, e.g. a tube cross section.
39 /// The entire domain must be defined by a GeomObject with the
40 /// following convention: zeta[0] is the radial coordinate and
41 /// zeta[1] is the theta coordinate around the cross-sectin.
42 /// The outer boundary must lie at zeta[0] = 1.
43 ///
44 /// The domain is
45 /// parametrised by five macro elements (a central box surrounded by
46 /// four curved elements). The labelling of the macro elements is shown
47 /// below.
48 ///
49 /// ----------------------------
50 /// |\ /|
51 /// | \ Macro / |
52 /// | 3 Element 3 2 |
53 /// | \ / |
54 /// | \----------------/ |
55 /// | | | |
56 /// | 4 | Macro | |
57 /// | | Element 0 | 2 |
58 /// | | | |
59 /// | ----------------- |
60 /// | / \ |
61 /// | 0 Macro 1 |
62 /// | / Element 1 \ |
63 /// | / \|
64 /// |/-------------------------|
65 ///
66 ///
67 //=================================================================
68 class FullCircleDomain : public Domain
69 {
70 public:
71 /// Constructor: Pass geometric object; the theta locations
72 /// marking the division between
73 /// the elements of the outer ring, labelled from the lower left to the
74 /// upper left in order, theta should be in the range \f$-\pi\f$ to
75 /// \f$\pi\f$; and the corresponding fractions of the
76 /// radius at which the central box is to be placed.
83 {
84 // There are five macro elements
85 const unsigned n_macro = 5;
87
88 // Create the macro elements
89 for (unsigned i = 0; i < n_macro; i++)
90 {
92 }
93 }
94
95 /// Broken copy constructor
97
98 /// Broken assignment operator
99 void operator=(const FullCircleDomain&) = delete;
100
101 /// Destructor: Empty; cleanup done in base class
103
104
105 /// Vector representation of the i_macro-th macro element
106 /// boundary i_direct (N/S/W/E) at time level t
107 /// (t=0: present; t>0: previous):
108 /// f(s).
109 void macro_element_boundary(const unsigned& t,
110 const unsigned& i_macro,
111 const unsigned& i_direct,
112 const Vector<double>& s,
113 Vector<double>& f);
114
115 private:
116 /// Storage for the dividing lines on the boundary
117 /// starting from the lower left and proceeding anticlockwise to
118 /// the upper left
120
121 /// Storage for the fraction of the radius at which the central box
122 /// should be located corresponding to the chosen values of theta.
124
125 /// Pointer to geometric object that represents the domain
127
128 /// A very little linear interpolation helper.
129 /// Interpolate from the low
130 /// point to the high point using the coordinate s, which is
131 /// assumed to run from -1 to 1.
133 const Vector<double>& high,
134 const double& s,
136 {
137 // Loop over all coordinates (we are working in 2D)
138 for (unsigned i = 0; i < 2; i++)
139 {
140 f[i] = low[i] + (high[i] - low[i]) * 0.5 * (s + 1.0);
141 }
142 }
143 };
144
145
146 /////////////////////////////////////////////////////////////////////////
147 /////////////////////////////////////////////////////////////////////////
148 /////////////////////////////////////////////////////////////////////////
149
150 //=================================================================
151 /// Vector representation of the imacro-th macro element
152 /// boundary idirect (N/S/W/E) at time level t
153 /// (t=0: present; t>0: previous): f(s)
154 //=================================================================
156 const unsigned& imacro,
157 const unsigned& idirect,
158 const Vector<double>& s,
160 {
161 using namespace QuadTreeNames;
162
163 // Get the coordinates of the corners of the box
165 // Get the corresponding coordinates on the boundary
167
168 // Storage for position in the area
170
171 // Loop over the angles
172 for (unsigned j = 0; j < 4; j++)
173 {
174 // Set up the storage
175 Box[j].resize(2);
176 Wall[j].resize(2);
177
178 // Set the other values of zeta
179 zeta[0] = Radius_box[j];
180 zeta[1] = Theta_positions[j];
181 // Now get the values
182 Area_pt->position(t, zeta, Box[j]);
183
184 // Now get the position on the boundary
185 zeta[0] = 1.0;
187 }
188
189 // Define pi
190 const double pi = MathematicalConstants::Pi;
191
192 // Which macro element?
193 // --------------------
194 switch (imacro)
195 {
196 // Macro element 0: Central box
197 case 0:
198
199 // Choose a direction
200 switch (idirect)
201 {
202 case N:
203 // Linearly interpolate between the two corners of the box
204 lin_interpolate(Box[3], Box[2], s[0], f);
205 break;
206
207 case S:
208 // Linearly interpolate between the two corners of the box
209 lin_interpolate(Box[0], Box[1], s[0], f);
210
211 case W:
212 // Linearly interpolate between the two corners of the box
213 lin_interpolate(Box[0], Box[3], s[0], f);
214 break;
215
216 case E:
217 // Linearly interpolate between the two corners of the box
218 lin_interpolate(Box[1], Box[2], s[0], f);
219 break;
220
221 default:
222 std::ostringstream error_stream;
223 error_stream << "idirect is " << idirect << " not one of N, S, E, W"
224 << std::endl;
225
226 throw OomphLibError(error_stream.str(),
229 break;
230 }
231
232 break;
233
234 // Macro element 1: Bottom
235 case 1:
236
237 // Choose a direction
238 switch (idirect)
239 {
240 case N:
241 // Linearly interpolate between the two corners of the box
242 lin_interpolate(Box[0], Box[1], s[0], f);
243 break;
244
245 case S:
246 // Get the position on the wall by linearly interpolating in theta
247 zeta[0] = 1.0;
248 zeta[1] =
249 Theta_positions[0] +
250 (Theta_positions[1] - Theta_positions[0]) * 0.5 * (s[0] + 1.0);
251
252 Area_pt->position(t, zeta, f);
253 break;
254
255 case W:
256 // Now linearly interpolate between the wall and the box
257 lin_interpolate(Wall[0], Box[0], s[0], f);
258 break;
259
260 case E:
261 // Linearly interpolate between the wall and the box
262 lin_interpolate(Wall[1], Box[1], s[0], f);
263 break;
264
265 default:
266
267 std::ostringstream error_stream;
268 error_stream << "idirect is " << idirect << " not one of N, S, E, W"
269 << std::endl;
270
271 throw OomphLibError(error_stream.str(),
274 break;
275 }
276
277 break;
278
279 // Macro element 2:Right
280 case 2:
281
282 // Which direction?
283 switch (idirect)
284 {
285 case N:
286 // Linearly interpolate between the box and the wall
287 lin_interpolate(Box[2], Wall[2], s[0], f);
288 break;
289
290 case S:
291 // Linearly interpolate between the box and the wall
292 lin_interpolate(Box[1], Wall[1], s[0], f);
293 break;
294
295 case W:
296 // Linearly interpolate between the two corners of the box
297 lin_interpolate(Box[1], Box[2], s[0], f);
298 break;
299
300 case E:
301 // Get the position on the wall by linearly interpolating in theta
302 zeta[0] = 1.0;
303 zeta[1] =
304 Theta_positions[1] +
305 (Theta_positions[2] - Theta_positions[1]) * 0.5 * (s[0] + 1.0);
306
307 Area_pt->position(t, zeta, f);
308 break;
309
310 default:
311 std::ostringstream error_stream;
312 error_stream << "idirect is " << idirect << " not one of N, S, W, E"
313 << std::endl;
314
315 throw OomphLibError(error_stream.str(),
318 }
319
320 break;
321
322 // Macro element 3: Top
323 case 3:
324
325 // Which direction?
326 switch (idirect)
327 {
328 case N:
329 // Get the position on the wall by linearly interpolating in theta
330 zeta[0] = 1.0;
331 zeta[1] =
332 Theta_positions[3] +
333 (Theta_positions[2] - Theta_positions[3]) * 0.5 * (s[0] + 1.0);
334
335 Area_pt->position(t, zeta, f);
336 break;
337
338 case S:
339 // Linearly interpolate between the two corners of the box
340 lin_interpolate(Box[3], Box[1], s[0], f);
341 break;
342
343 case W:
344 // Linearly interpolate between the box and the wall
345 lin_interpolate(Box[3], Wall[3], s[0], f);
346 break;
347
348 case E:
349 // Linearly interpolate between the box and the wall
350 lin_interpolate(Box[2], Wall[2], s[0], f);
351 break;
352
353 default:
354 std::ostringstream error_stream;
355 error_stream << "idirect is " << idirect << " not one of N, S, E, W"
356 << std::endl;
357
358 throw OomphLibError(error_stream.str(),
361 }
362
363 break;
364
365 // Macro element 4: Left
366 case 4:
367
368 // Which direction?
369 switch (idirect)
370 {
371 case N:
372 // Linearly interpolate between the wall and the box
373 lin_interpolate(Wall[3], Box[3], s[0], f);
374 break;
375
376 case S:
377 // Linearly interpolate between the wall and the box
378 lin_interpolate(Wall[0], Box[0], s[0], f);
379 break;
380
381 case W:
382 // Entirely on the wall, Need to be careful
383 // because this is the point at which theta passes through the
384 //"branch cut"
385 zeta[0] = 1.0;
386 zeta[1] = Theta_positions[0] + 2.0 * pi +
387 (Theta_positions[3] - (Theta_positions[0] + 2.0 * pi)) *
388 0.5 * (s[0] + 1.0);
389
390 Area_pt->position(t, zeta, f);
391 break;
392
393 case E:
394 // Linearly interpolate between the two corners of the box
395 lin_interpolate(Box[0], Box[3], s[0], f);
396 break;
397
398 default:
399 std::ostringstream error_stream;
400 error_stream << "idirect is " << idirect << " not one of N, S, W, E"
401 << std::endl;
402
403 throw OomphLibError(error_stream.str(),
406 }
407 break;
408
409 default:
410 // Error
411 std::ostringstream error_stream;
412 error_stream << "Wrong imacro " << imacro << std::endl;
413 throw OomphLibError(
415 }
416 }
417
418} // namespace oomph
419
420#endif
static char t char * s
Definition cfortran.h:568
cstr elem_len * i
Definition cfortran.h:603
char t
Definition cfortran.h:568
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
Topologically circular domain, e.g. a tube cross section. The entire domain must be defined by a Geom...
FullCircleDomain(const FullCircleDomain &)=delete
Broken copy constructor.
FullCircleDomain(GeomObject *area_geom_object_pt, const Vector< double > &theta_positions, const Vector< double > &radius_box)
Constructor: Pass geometric object; the theta locations marking the division between the elements of ...
GeomObject * Area_pt
Pointer to geometric object that represents the domain.
void lin_interpolate(const Vector< double > &low, const Vector< double > &high, const double &s, Vector< double > &f)
A very little linear interpolation helper. Interpolate from the low point to the high point using the...
void macro_element_boundary(const unsigned &t, const unsigned &i_macro, const unsigned &i_direct, const Vector< double > &s, Vector< double > &f)
Vector representation of the i_macro-th macro element boundary i_direct (N/S/W/E) at time level t (t=...
Vector< double > Radius_box
Storage for the fraction of the radius at which the central box should be located corresponding to th...
void operator=(const FullCircleDomain &)=delete
Broken assignment operator.
Vector< double > Theta_positions
Storage for the dividing lines on the boundary starting from the lower left and proceeding anticlockw...
~FullCircleDomain()
Destructor: Empty; cleanup done in base class.
A geometric object is an object that provides a parametrised description of its shape via the functio...
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....
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
const double Pi
50 digits from maple
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).