geom_obj_with_boundary.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#ifndef OOMPH_GEOM_OBJ_WITH_BOUNDARY_HEADER
27#define OOMPH_GEOM_OBJ_WITH_BOUNDARY_HEADER
28
29
30// Config header
31#ifdef HAVE_CONFIG_H
32#include <oomph-lib-config.h>
33#endif
34
35
36// oomph-lib headers
37#include "geom_objects.h"
38
39
40namespace oomph
41{
42 //===========================================================================
43 /// Base class for upgraded disk-like GeomObject (i.e. 2D surface in 3D space)
44 /// with specification of boundaries. The GeomObject's position(...)
45 /// function computes the 3D (Eulerian) position vector r as a function of the
46 /// 2D intrinsic (Lagrangian) coordinates, zeta, without reference to
47 /// any boundaries. This class specifies the boundaries by specifying
48 /// a mapping from a 1D intrinsic boundary coordinate, zeta_bound,
49 /// to the 2D intrinsic (Lagrangian) coordinates, zeta.
50 ///
51 /// The class is made functional by provision (in the derived class!) of:
52 /// - a pointer to a GeomObject<1,2> that parametrises the 2D intrinisic
53 /// coordinates zeta along boundary b in terms of the 1D boundary
54 /// coordinate, zeta_bound,
55 /// - the initial value of the 1D boundary coordinate zeta_bound on boundary
56 /// b,
57 /// - the final value of the 1D boundary coordinate zeta_bound on boundary b
58 /// .
59 /// for each of these boundaries. All three containers for these
60 /// must be resized (consistently) and populated in the derived class.
61 /// Number of boundaries is inferred from their size.
62 ///
63 /// Class also provides broken virtual function to specify boundary triads,
64 /// and various output functions.
65 //===========================================================================
67 {
68 public:
69 /// Constructor
71
72 /// How many boundaries do we have?
73 unsigned nboundary() const
74 {
76 }
77
78 /// Compute 3D vector of Eulerian coordinates at 1D boundary
79 /// coordinate zeta_bound on boundary b:
80 void position_on_boundary(const unsigned& b,
81 const double& zeta_bound,
82 Vector<double>& r) const
83 {
86 position(zeta, r);
87 }
88
89 /// Compute 2D vector of intrinsic coordinates at 1D boundary
90 /// coordinate zeta_bound on boundary b:
91 void zeta_on_boundary(const unsigned& b,
92 const double& zeta_bound,
93 Vector<double>& zeta) const
94 {
95#ifdef PARANOID
97 {
98 std::ostringstream error_message;
99 error_message << "You must create a <1,2> Geom Object that provides a\n"
100 << "mapping from the 1D boundary coordinate to the 2D\n"
101 << "intrinsic Lagrangian coordinate of disk-like object\n"
102 << std::endl;
103 throw OomphLibError(error_message.str(),
106 }
108 {
109 std::ostringstream error_message;
110 error_message << "Boundary_parametrising_geom_object_pt must point to\n"
111 << "GeomObject with one Lagrangian coordinate. Yours has "
113 << std::endl;
114 throw OomphLibError(error_message.str(),
117 }
119 {
120 std::ostringstream error_message;
121 error_message << "Boundary_parametrising_geom_object_pt must point to\n"
122 << "GeomObject with two Eulerian coordinates. Yours has "
124 << std::endl;
125 throw OomphLibError(error_message.str(),
128 }
129#endif
132 zeta);
133 }
134
135 /// Pointer to GeomObject<1,2> that parametrises intrinisc
136 /// coordinates along boundary b
141
142 /// Initial value of 1D boundary coordinate
143 /// zeta_bound on boundary b:
144 double zeta_boundary_start(const unsigned& b) const
145 {
146 return Zeta_boundary_start[b];
147 }
148
149 /// Final value of 1D boundary coordinate
150 /// zeta_bound on boundary b:
151 double zeta_boundary_end(const unsigned& b) const
152 {
153 return Zeta_boundary_end[b];
154 }
155
156
157 /// Boundary triad on boundary b at boundary coordinate zeta_bound.
158 /// Broken virtual.
159 virtual void boundary_triad(const unsigned& b,
160 const double& zeta_bound,
165 {
166 std::ostringstream error_message;
167 error_message << "Broken virtual function; please implement for your\n"
168 << "derived version of this class!" << std::endl;
169 throw OomphLibError(
171 }
172
173 /// Output boundaries at nplot plot points. Streams:
174 /// - two_d_boundaries_file: zeta_0, zeta_1, zeta_bound
175 /// - three_d_boundaries_file : x, y, z, zeta_0, zeta_1, zeta_bound
190
191
192 /// Output boundaries and triad at nplot plot points. Streams:
193 /// - two_d_boundaries_file: zeta_0, zeta_1, zeta_bound
194 /// - three_d_boundaries_file : x, y, z, zeta_0, zeta_1, zeta_bound
195 /// - boundaries_tangent_file : x, y, z, t_x, t_y, t_z
196 /// - boundaries_normal_file : x, y, z, n_x, n_y, n_z
197 /// - boundaries_binormal_file: x, y, z, N_x, N_y, N_z
199 std::ofstream& two_d_boundaries_file,
200 std::ofstream& three_d_boundaries_file,
201 std::ofstream& boundaries_tangent_file,
202 std::ofstream& boundaries_normal_file,
203 std::ofstream& boundaries_binormal_file)
204 {
205 Vector<double> r(3);
207 double zeta_bound = 0.0;
211 unsigned nb = nboundary();
212 for (unsigned b = 0; b < nb; b++)
213 {
214 two_d_boundaries_file << "ZONE" << std::endl;
215 three_d_boundaries_file << "ZONE" << std::endl;
216 boundaries_tangent_file << "ZONE" << std::endl;
217 boundaries_normal_file << "ZONE" << std::endl;
218 boundaries_binormal_file << "ZONE" << std::endl;
219
220 double zeta_min = zeta_boundary_start(b);
221 double zeta_max = zeta_boundary_end(b);
222 unsigned n = 100;
223 for (unsigned i = 0; i < n; i++)
224 {
225 zeta_bound =
226 zeta_min + (zeta_max - zeta_min) * double(i) / double(n - 1);
230
231 two_d_boundaries_file << zeta[0] << " " << zeta[1] << " "
232 << zeta_bound << " " << std::endl;
233
234 three_d_boundaries_file << r[0] << " " << r[1] << " " << r[2] << " "
235 << zeta[0] << " " << zeta[1] << " "
236 << zeta_bound << " " << std::endl;
237
238 boundaries_tangent_file << r[0] << " " << r[1] << " " << r[2] << " "
239 << tangent[0] << " " << tangent[1] << " "
240 << tangent[2] << " " << std::endl;
241
242 boundaries_normal_file << r[0] << " " << r[1] << " " << r[2] << " "
243 << normal[0] << " " << normal[1] << " "
244 << normal[2] << " " << std::endl;
245
246 boundaries_binormal_file << r[0] << " " << r[1] << " " << r[2] << " "
247 << binormal[0] << " " << binormal[1] << " "
248 << binormal[2] << " " << std::endl;
249 }
250 }
251 }
252
253
254 /// Specify intrinsic coordinates of a point within a specified
255 /// region -- region ID, r, should be positive.
256 void add_region_coordinates(const unsigned& r,
258 {
259 // Verify if not using the default region number (zero)
260 if (r == 0)
261 {
262 std::ostringstream error_message;
263 error_message
264 << "Please use another region id different from zero.\n"
265 << "It is internally used as the default region number.\n";
266 throw OomphLibError(error_message.str(),
269 }
270 // Need two coordinates
271 unsigned n = zeta_in_region.size();
272 if (n != 2)
273 {
274 std::ostringstream error_message;
275 error_message << "Vector specifying zeta coordinates of point in\n"
276 << "region has be length 2; yours has length " << n
277 << std::endl;
278 throw OomphLibError(error_message.str(),
281 }
282
283 // First check if the region with the specified id does not already exist
284 std::map<unsigned, Vector<double>>::iterator it;
285 it = Zeta_in_region.find(r);
286
287 // If it is already a region defined with that id throw an error
288 if (it != Zeta_in_region.end())
289 {
290 std::ostringstream error_message;
291 error_message << "The region id (" << r << ") that you are using for"
292 << "defining\n"
293 << "your region is already in use. Use another\n"
294 << "region id and verify that you are not re-using\n"
295 << " previously defined regions ids.\n"
296 << std::endl;
297 OomphLibWarning(error_message.str(),
300 }
301
302 // If it does not exist then create the map
304 }
305
306 /// Return map that stores zeta coordinates of points that identify regions
307 std::map<unsigned, Vector<double>> zeta_in_region() const
308 {
309 return Zeta_in_region;
310 }
311
312 protected:
313 /// Storage for initial value of 1D boundary coordinate
314 /// on boundary b:
316
317 /// Storage for final value of 1D boundary coordinate
318 /// on boundary b:
320
321 /// Pointer to GeomObject<1,2> that parametrises intrinisc
322 /// coordinates along boundary b; essentially provides a wrapper to
323 /// zeta_on_boundary(...)
325
326 /// Map to store zeta coordinates of points that identify regions
327 std::map<unsigned, Vector<double>> Zeta_in_region;
328 };
329
330
331 /////////////////////////////////////////////////////////////////////
332 /////////////////////////////////////////////////////////////////////
333 /////////////////////////////////////////////////////////////////////
334
335
336 //=========================================================================
337 /// Warped disk in 3d: zeta[0]=x; zeta[1]=y (so it doesn't have
338 /// coordinate singularities), with specification of two boundaries (b=0,1)
339 /// that turn the whole thing into a circular disk.
340 //=========================================================================
342 {
343 public:
344 /// Constructor. Pass amplitude and azimuthal wavenumber of
345 /// warping as arguments. Can specify vertical offset as final, optional
346 /// argument.
348 const unsigned& n,
349 const double& z_offset = 0.0)
351 {
352 // How many boundaries do we have?
353 unsigned nb = 2;
355 Zeta_boundary_start.resize(nb, 0.0);
356 Zeta_boundary_end.resize(nb, 0.0);
357
358 // GeomObject<1,2> representing the first boundary
360 Zeta_boundary_start[0] = 0.0;
362
363 // GeomObject<1,2> representing the second boundary
367 }
368
369 /// Empty default constructor.
371 {
372 throw OomphLibError("Don't call default constructor!",
375 }
376
377
378 /// Broken copy constructor
380
381 /// Broken assignment operator
382 void operator=(const WarpedCircularDisk&) = delete;
383
384 /// Destructor
386 {
387 unsigned n = nboundary();
388 for (unsigned b = 0; b < n; b++)
389 {
392 }
393 }
394
395 /// Access fct to amplitude of disk warping
396 double& epsilon()
397 {
398 return Epsilon;
399 }
400
401 /// Position Vector at Lagrangian coordinate zeta
403 {
404 // Position Vector
405 r[0] = zeta[0];
406 r[1] = zeta[1];
407 double radius = sqrt(r[0] * r[0] + r[1] * r[1]);
408 double phi = atan2(r[1], r[0]);
409 r[2] = Z_offset + w(radius, phi);
410 }
411
412
413 /// Parametrised position on object: r(zeta). Evaluated at
414 /// previous timestep. t=0: current time; t>0: previous
415 /// timestep. Object is steady so calls time-independent version
416 void position(const unsigned& t,
417 const Vector<double>& zeta,
418 Vector<double>& r) const
419 {
420 position(zeta, r);
421 }
422
423
424 /// Boundary triad on boundary b at boundary coordinate zeta_bound
425 void boundary_triad(const unsigned& b,
426 const double& zeta_bound,
431 {
432 double phi = zeta_bound;
433
434 // Position Vector
435 r[0] = cos(phi);
436 r[1] = sin(phi);
437 r[2] = Z_offset + w(1.0, phi);
438
440 dr_dr[0] = cos(phi);
441 dr_dr[1] = sin(phi);
442 dr_dr[2] = dwdr(1.0, phi);
443 double inv_norm = 1.0 / sqrt(dr_dr[0] * dr_dr[0] + dr_dr[1] * dr_dr[1] +
444 dr_dr[2] * dr_dr[2]);
445
446 normal[0] = dr_dr[0] * inv_norm;
447 normal[1] = dr_dr[1] * inv_norm;
448 normal[2] = dr_dr[2] * inv_norm;
449
451 dr_dphi[0] = -sin(phi);
452 dr_dphi[1] = cos(phi);
453 dr_dphi[2] = dwdphi(1.0, phi);
454
455 inv_norm = 1.0 / sqrt(dr_dphi[0] * dr_dphi[0] + dr_dphi[1] * dr_dphi[1] +
456 dr_dphi[2] * dr_dphi[2]);
457
458 tangent[0] = dr_dphi[0] * inv_norm;
459 tangent[1] = dr_dphi[1] * inv_norm;
460 tangent[2] = dr_dphi[2] * inv_norm;
461
462 binormal[0] = tangent[1] * normal[2] - tangent[2] * normal[1];
463 binormal[1] = tangent[2] * normal[0] - tangent[0] * normal[2];
464 binormal[2] = tangent[0] * normal[1] - tangent[1] * normal[0];
465 }
466
467 private:
468 /// Vertical deflection
469 double w(const double& r, const double& phi) const
470 {
471 return Epsilon * cos(double(N) * phi) * pow(r, 2);
472 }
473
474 /// Deriv of vertical deflection w.r.t. radius
475 double dwdr(const double& r, const double& phi) const
476 {
477 return Epsilon * cos(double(N) * phi) * 2.0 * r;
478 }
479
480 /// Deriv of vertical deflection w.r.t. angle
481 double dwdphi(const double& r, const double& phi) const
482 {
483 return -Epsilon * double(N) * sin(double(N) * phi) * pow(r, 2);
484 }
485
486 /// Amplitude of non-axisymmetric deformation
487 double Epsilon;
488
489 /// Wavenumber of non-axisymmetric deformation
490 unsigned N;
491
492 /// Vertical offset
493 double Z_offset;
494 };
495
496 /////////////////////////////////////////////////////////////////////
497 /////////////////////////////////////////////////////////////////////
498 /////////////////////////////////////////////////////////////////////
499
500
501 //=========================================================================
502 /// Warped disk in 3d: zeta[0]=x; zeta[1]=y (so it doesn't have
503 /// coordinate singularities), with specification of two boundaries (b=0,1)
504 /// that turn the whole thing into a circular disk. In addition
505 /// has two internal boundaries (b=2,3), a distance h_annulus from
506 /// the outer edge. Annual (outer) region is region 1.
507 //=========================================================================
509 : public virtual WarpedCircularDisk
510 {
511 public:
512 /// Constructor. Pass amplitude and azimuthal wavenumber of
513 /// warping as arguments. Can specify vertical offset as final, optional
514 /// argument.
516 const double& epsilon,
517 const unsigned& n,
518 const double& z_offset = 0.0)
520 {
521 // We have two more boundaries!
523 Zeta_boundary_start.resize(4);
524 Zeta_boundary_end.resize(4);
525
526 // Radius of the internal annular boundary
527 double r_annulus = 1.0 - h_annulus;
528
529 // GeomObject<1,2> representing the third boundary
532 Zeta_boundary_start[2] = 0.0;
534
535 // GeomObject<1,2> representing the fourth boundary
540
541 // Region 1 is the annular region; identify it by a point in
542 // this region.
543 unsigned r = 1;
545 zeta_in_region[0] = 0.0;
546 zeta_in_region[0] = 1.0 - 0.5 * h_annulus;
548 }
549
550 /// Broken copy constructor
553
554 /// Broken assignment operator
556 delete;
557
558 /// Destructor (empty; cleanup happens in base class)
560
561
562 /// Thickness of annular region (distance of internal boundary
563 /// from outer edge of unit circle)
564 double h_annulus() const
565 {
566 return H_annulus;
567 }
568
569 protected:
570 /// Thickness of annular region (distance of internal boundary
571 /// from outer edge of unit circle)
572 double H_annulus;
573 };
574
575
576} // namespace oomph
577
578#endif
cstr elem_len * i
Definition cfortran.h:603
char t
Definition cfortran.h:568
Base class for upgraded disk-like GeomObject (i.e. 2D surface in 3D space) with specification of boun...
void add_region_coordinates(const unsigned &r, Vector< double > &zeta_in_region)
Specify intrinsic coordinates of a point within a specified region – region ID, r,...
GeomObject * boundary_parametrising_geom_object_pt(const unsigned &b) const
Pointer to GeomObject<1,2> that parametrises intrinisc coordinates along boundary b.
Vector< double > Zeta_boundary_start
Storage for initial value of 1D boundary coordinate on boundary b:
void position_on_boundary(const unsigned &b, const double &zeta_bound, Vector< double > &r) const
Compute 3D vector of Eulerian coordinates at 1D boundary coordinate zeta_bound on boundary b:
std::map< unsigned, Vector< double > > zeta_in_region() const
Return map that stores zeta coordinates of points that identify regions.
void output_boundaries_and_triads(const unsigned &nplot, std::ofstream &two_d_boundaries_file, std::ofstream &three_d_boundaries_file, std::ofstream &boundaries_tangent_file, std::ofstream &boundaries_normal_file, std::ofstream &boundaries_binormal_file)
Output boundaries and triad at nplot plot points. Streams:
std::map< unsigned, Vector< double > > Zeta_in_region
Map to store zeta coordinates of points that identify regions.
Vector< GeomObject * > Boundary_parametrising_geom_object_pt
Pointer to GeomObject<1,2> that parametrises intrinisc coordinates along boundary b; essentially prov...
double zeta_boundary_end(const unsigned &b) const
Final value of 1D boundary coordinate zeta_bound on boundary b:
virtual void boundary_triad(const unsigned &b, const double &zeta_bound, Vector< double > &r, Vector< double > &tangent, Vector< double > &normal, Vector< double > &binormal)
Boundary triad on boundary b at boundary coordinate zeta_bound. Broken virtual.
unsigned nboundary() const
How many boundaries do we have?
void zeta_on_boundary(const unsigned &b, const double &zeta_bound, Vector< double > &zeta) const
Compute 2D vector of intrinsic coordinates at 1D boundary coordinate zeta_bound on boundary b:
void output_boundaries(const unsigned &nplot, std::ofstream &two_d_boundaries_file, std::ofstream &three_d_boundaries_file)
Output boundaries at nplot plot points. Streams:
double zeta_boundary_start(const unsigned &b) const
Initial value of 1D boundary coordinate zeta_bound on boundary b:
Vector< double > Zeta_boundary_end
Storage for final value of 1D boundary coordinate on boundary b:
Steady ellipse with half axes A and B as geometric object:
void position(const Vector< double > &zeta, Vector< double > &r) const
Return the parametrised position of the FiniteElement in its incarnation as a GeomObject,...
Definition elements.h:2680
double size() const
Calculate the size of the element (length, area, volume,...) in Eulerian computational coordinates....
Definition elements.cc:4320
A geometric object is an object that provides a parametrised description of its shape via the functio...
unsigned ndim() const
Access function to # of Eulerian coordinates.
virtual void position(const Vector< double > &zeta, Vector< double > &r) const =0
Parametrised position on object at current time: r(zeta).
unsigned nlagrangian() const
Access function to # of Lagrangian coordinates.
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....
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
Warped disk in 3d: zeta[0]=x; zeta[1]=y (so it doesn't have coordinate singularities),...
virtual ~WarpedCircularDiskWithAnnularInternalBoundary()
Destructor (empty; cleanup happens in base class)
double H_annulus
Thickness of annular region (distance of internal boundary from outer edge of unit circle)
WarpedCircularDiskWithAnnularInternalBoundary(const WarpedCircularDiskWithAnnularInternalBoundary &dummy)=delete
Broken copy constructor.
void operator=(const WarpedCircularDiskWithAnnularInternalBoundary &)=delete
Broken assignment operator.
WarpedCircularDiskWithAnnularInternalBoundary(const double &h_annulus, const double &epsilon, const unsigned &n, const double &z_offset=0.0)
Constructor. Pass amplitude and azimuthal wavenumber of warping as arguments. Can specify vertical of...
double h_annulus() const
Thickness of annular region (distance of internal boundary from outer edge of unit circle)
Warped disk in 3d: zeta[0]=x; zeta[1]=y (so it doesn't have coordinate singularities),...
double dwdphi(const double &r, const double &phi) const
Deriv of vertical deflection w.r.t. angle.
void operator=(const WarpedCircularDisk &)=delete
Broken assignment operator.
double Epsilon
Amplitude of non-axisymmetric deformation.
void position(const Vector< double > &zeta, Vector< double > &r) const
Position Vector at Lagrangian coordinate zeta.
WarpedCircularDisk(const WarpedCircularDisk &dummy)=delete
Broken copy constructor.
WarpedCircularDisk()
Empty default constructor.
WarpedCircularDisk(const double &epsilon, const unsigned &n, const double &z_offset=0.0)
Constructor. Pass amplitude and azimuthal wavenumber of warping as arguments. Can specify vertical of...
double Z_offset
Vertical offset.
double & epsilon()
Access fct to amplitude of disk warping.
void boundary_triad(const unsigned &b, const double &zeta_bound, Vector< double > &r, Vector< double > &tangent, Vector< double > &normal, Vector< double > &binormal)
Boundary triad on boundary b at boundary coordinate zeta_bound.
unsigned N
Wavenumber of non-axisymmetric deformation.
double w(const double &r, const double &phi) const
Vertical deflection.
virtual ~WarpedCircularDisk()
Destructor.
double dwdr(const double &r, const double &phi) const
Deriv of vertical deflection w.r.t. radius.
void position(const unsigned &t, const Vector< double > &zeta, Vector< double > &r) const
Parametrised position on object: r(zeta). Evaluated at previous timestep. t=0: current time; t>0: pre...
const double Pi
50 digits from maple
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).