topologically_rectangular_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// Include guards
27#ifndef OOMPH_TOPOLOGICALLY_RECTANGULAR_DOMAIN_HEADER
28#define OOMPH_TOPOLOGICALLY_RECTANGULAR_DOMAIN_HEADER
29
30// Config header
31#ifdef HAVE_CONFIG_H
32#include <oomph-lib-config.h>
33#endif
34
35// oomph-lib headers
36#include "generic/domain.h"
37
38namespace oomph
39{
40 //=============================================================================
41 /// Topologically Rectangular Domain - a domain dexcribing a
42 /// topologically rectangular problem - primarily contains functions to access
43 /// the position of the global boundary relative to the macro element
44 /// boundary, as well as first and second derivates of the global boundary wrt
45 /// the macro element boundary NOTE : suitable for HermiteElementQuadMesh
46 //=============================================================================
48 {
49 public:
50 /// boundary function pointer - for a given boundary takes the
51 /// macro element coordinate position on that boundary and for that position
52 /// returns the global coordinates (x) coordinates, or derivatives -
53 /// dx_i/dm_t or second derivatives d2x_i/dm_t^2
54 typedef void (*BoundaryFctPt)(const double& s, Vector<double>& r);
55
56
57 /// Constructor - domain boundaries are described with four boundary
58 /// function pointers describing the topology of the north, east, south, and
59 /// west boundaries
64
65
66 /// Constructor - takes length of domain in x and y direction as
67 /// arguements. Assumes domain is rectangular, and the south west (lower
68 /// left) corner is at 0,0.
69 TopologicallyRectangularDomain(const double& l_x, const double& l_y);
70
71
72 /// Constructor - takes the minimum and maximum coordinates of the
73 /// of an assumed rectanguler domain in the x and y direction
74 TopologicallyRectangularDomain(const double& x_min,
75 const double& x_max,
76 const double& y_min,
77 const double& y_max);
78
79 /// Broken copy constructor
81 delete;
82
83 /// Broken assignment operator
85
86 /// Destructor - empty; clean up done in base class
88
89
90 /// allows the boundary derivate function pointers to be set. To
91 /// compute the derivatives of the problem domain global coordinates (x_i)
92 /// wrt the macro element coordinates (m_i), dx_i/dm_t is required along the
93 /// domain boundaries (where dm_t is the macro element coordinate tangential
94 /// to the domain boundary). The derivatives dx_i/dm_t can either be
95 /// prescribed with function pointers, or if the function pointers are not
96 /// provided then dx_i/dm_t is computed with finite differencing.
97 /// Note - these functions are only required for domains contructed with
98 /// boundary function pointers
103
104
105 /// allows the boundary second derivate function pointers to be set.
106 /// To compute the second derivatives of the problem domain global
107 /// coordinates (x_i) wrt the macro element coordinates (m_i), d2x_i/dm_t^2
108 /// is required along the domain boundaries (where dm_t is the macro element
109 /// coordinate tangential to the domain boundary). The derivatives
110 /// d2x_i/dm_t^2 can either be prescribed with function pointers, or if the
111 /// function pointers are not provided then dx_i/dm_t is computed with
112 /// finite differencing. Note - these functions are only required for
113 /// domains contructed with boundary function pointers
118
119 /// returns the global coordinate position (f) of macro element position s
120 /// on boundary i_direct (e.g. N/S/W/E in 2D) at time t (no time dependence)
121 void macro_element_boundary(const unsigned& t,
122 const unsigned& i_macro,
123 const unsigned& i_direct,
124 const Vector<double>& s,
125 Vector<double>& f);
126
127 /// returns the derivates of the global coordinate position (f) wrt to the
128 /// macro element coordinate at macro macro element position s on boundary
129 /// i_direct (e.g. N/S/W/E in 2D) at time t (no time dependence)
130 void dmacro_element_boundary(const unsigned& t,
131 const unsigned& i_macro,
132 const unsigned& i_direct,
133 const Vector<double>& s,
134 Vector<double>& f);
135
136 /// returns the second derivates of the global coordinate position (f) wrt
137 /// to the macro element coordinate at macro macro element position s on
138 /// boundary i_direct (e.g. N/S/W/E in 2D) at time t (no time dependence)
139 void d2macro_element_boundary(const unsigned& t,
140 const unsigned& i_macro,
141 const unsigned& i_direct,
142 const Vector<double>& s,
143 Vector<double>& f);
144
145 private:
146 /// Function pointer to prescribe the north boundary of this
147 /// topologically rectangular domain
149
150 /// Function pointer to prescribe the east boundary of this
151 /// topologically rectangular domain
153
154 /// Function pointer to prescribe the north boundary of this
155 /// topologically rectangular domain
157
158 /// Function pointer to prescribe the west boundary of this
159 /// topologically rectangular domain
161
162
163 /// Function pointer to prescribe the derivates of global coordinates
164 /// wrt to the macro element coordinate tangential to the north boundary
166
167 /// Function pointer to prescribe the derivates of global coordinates
168 /// wrt to the macro element coordinate tangential to the east boundary
170
171 /// Function pointer to prescribe the derivates of global coordinates
172 /// wrt to the macro element coordinate tangential to the south boundary
174
175 /// Function pointer to prescribe the derivates of global coordinates
176 /// wrt to the macro element coordinate tangential to the west boundary
178
179
180 /// Function pointer to prescribe the second derivates of global
181 /// coordinates wrt to the macro element coordinate tangential to the north
182 /// boundary
184
185 /// Function pointer to prescribe the second derivates of global
186 /// coordinates wrt to the macro element coordinate tangential to the east
187 /// boundary
189
190 /// Function pointer to prescribe the second derivates of global
191 /// coordinates wrt to the macro element coordinate tangential to the south
192 /// boundary
194
195 /// Function pointer to prescribe the second derivates of global
196 /// coordinates wrt to the macro element coordinate tangential to the west
197 /// boundary
199
200
201 /// coordinate position of south west corner of domain (only used if
202 /// boundary functions are not used)
204
205 /// coordinate position of north east corner of domain (only used if
206 /// boundary functions are not used)
208
209
210 /// takes the macro element coordinate position along the north
211 /// boundary and returns the global coordinate position along that boundary
212 void r_N(const Vector<double>& s, Vector<double>& f);
213
214 /// takes the macro element coordinate position along the east
215 /// boundary and returns the global coordinate position along that boundary
216 void r_E(const Vector<double>& s, Vector<double>& f);
217
218 /// takes the macro element coordinate position along the south
219 /// boundary and returns the global coordinate position along that boundary
220 void r_S(const Vector<double>& s, Vector<double>& f);
221
222 /// takes the macro element coordinate position along the west
223 /// boundary and returns the global coordinate position along that boundary
224 /// access down boundary function pointer
225 void r_W(const Vector<double>& s, Vector<double>& f);
226
227
228 /// takes the macro element coordinate position along the north
229 /// boundary and returns the derivates of the global coordinates with
230 /// respect to the boundary
231 void dr_N(const Vector<double>& s, Vector<double>& dr);
232
233 /// takes the macro element coordinate position along the E
234 /// boundary and returns the derivates of the global coordinates with
235 /// respect to the boundary
236 void dr_E(const Vector<double>& s, Vector<double>& dr);
237
238 /// takes the macro element coordinate position along the south
239 /// boundary and returns the derivates of the global coordinates with
240 /// respect to the boundary
241 void dr_S(const Vector<double>& s, Vector<double>& dr);
242
243 /// takes the macro element coordinate position along the W
244 /// boundary and returns the derivates of the global coordinates with
245 /// respect to the boundary
246 void dr_W(const Vector<double>& s, Vector<double>& dr);
247
248
249 /// takes the macro element coordinate position along the north
250 /// boundary and returns the second derivates of the global coordinates with
251 /// respect to the boundary
252 void d2r_N(const Vector<double>& s, Vector<double>& d2r);
253
254 /// takes the macro element coordinate position along the east
255 /// boundary and returns the second derivates of the global coordinates with
256 /// respect to the boundary
257 void d2r_E(const Vector<double>& s, Vector<double>& d2r);
258
259 /// takes the macro element coordinate position along the south
260 /// boundary and returns the second derivates of the global coordinates with
261 /// respect to the boundary
262 void d2r_S(const Vector<double>& s, Vector<double>& d2r);
263
264 /// takes the macro element coordinate position along the west
265 /// boundary and returns the second derivates of the global coordinates with
266 /// respect to the boundary
267 void d2r_W(const Vector<double>& s, Vector<double>& d2r);
268 };
269
270 //=============================================================================
271 /// \short Constructor - domain boundaries are described with four boundary
272 /// function pointers describing the topology of the north, east, south, and
273 /// west boundaries
274 //=============================================================================
276 BoundaryFctPt north_pt,
277 BoundaryFctPt east_pt,
278 BoundaryFctPt south_pt,
279 BoundaryFctPt west_pt)
280 {
281 // domain comprises one macro element
282 Macro_element_pt.resize(1);
283
284 // Create the macro element
285 Macro_element_pt[0] = new QMacroElement<2>(this, 0);
286
287 // set boundary function pointers
292
293 // by default derivative boundary function pointers are null
298
299 // also by default second derivate boundary function pointers are null
304
305 // paranoid self check to ensure that ends of boundaries meet
306#ifdef PARANOID
307 // error message stream
308 std::ostringstream error_message;
309 bool error_flag = false;
310 // check NE corner
311 {
313 (*North_boundary_fn_pt)(1.0, x_N);
315 (*East_boundary_fn_pt)(1.0, x_E);
316 if (x_N[0] != x_E[0] || x_N[1] != x_E[1])
317 {
318 error_message << "North and East Boundaries do not meet at the "
319 << "North East Corner.\n"
320 << "North Boundary : x[0] = " << x_N[0] << "\n"
321 << " x[1] = " << x_N[1] << "\n"
322 << "East Boundary : x[0] = " << x_E[0] << "\n"
323 << " x[1] = " << x_E[1] << "\n\n";
324 error_flag = true;
325 }
326 }
327 // check SE corner
328 {
330 (*South_boundary_fn_pt)(1.0, x_S);
332 (*East_boundary_fn_pt)(-1.0, x_E);
333 if (x_S[0] != x_E[0] || x_S[1] != x_E[1])
334 {
335 error_message << "South and East Boundaries do not meet at the "
336 << "South East Corner.\n"
337 << "South Boundary : x[0] = " << x_S[0] << "\n"
338 << " x[1] = " << x_S[1] << "\n"
339 << "East Boundary : x[0] = " << x_E[0] << "\n"
340 << " x[1] = " << x_E[1] << "\n\n";
341 error_flag = true;
342 }
343 }
344 // check SW corner
345 {
347 (*South_boundary_fn_pt)(-1.0, x_S);
349 (*West_boundary_fn_pt)(-1.0, x_W);
350 if (x_S[0] != x_W[0] || x_S[1] != x_W[1])
351 {
352 error_message << "South and West Boundaries do not meet at the "
353 << "South West Corner.\n"
354 << "South Boundary : x[0] = " << x_S[0] << "\n"
355 << " x[1] = " << x_S[1] << "\n"
356 << "West Boundary : x[0] = " << x_W[0] << "\n"
357 << " x[1] = " << x_W[1] << "\n\n";
358 error_flag = true;
359 }
360 }
361 // check NW corner
362 {
364 (*North_boundary_fn_pt)(-1.0, x_N);
366 (*West_boundary_fn_pt)(1.0, x_W);
367 if (x_N[0] != x_W[0] || x_N[1] != x_W[1])
368 {
369 error_message << "North and West Boundaries do not meet at the "
370 << "North West Corner.\n"
371 << "North Boundary : x[0] = " << x_N[0] << "\n"
372 << " x[1] = " << x_N[1] << "\n"
373 << "West Boundary : x[0] = " << x_W[0] << "\n"
374 << " x[1] = " << x_W[1] << "\n\n";
375 error_flag = true;
376 }
377 }
378 if (error_flag)
379 {
380 throw OomphLibError(
382 }
383#endif
384 }
385
386 //=============================================================================
387 /// \short Constructor - takes length of domain in x and y direction as
388 /// arguements. Assumes domain is rectangular, and the south west (lower
389 /// left) corner is at 0,0.
390 //=============================================================================
392 const double& l_x, const double& l_y)
393 {
394 // domain comprises one macro element
395 Macro_element_pt.resize(1);
396
397 // Create the macro element
398 Macro_element_pt[0] = new QMacroElement<2>(this, 0);
399
400 // set the boundary function pointers to zero
405
406 // resize x vectors
407 x_south_west.resize(2);
408 x_north_east.resize(2);
409
410 // set south west corner to 0,0
411 x_south_west[0] = 0.0;
412 x_south_west[1] = 0.0;
413
414 // set north east corner
415 x_north_east[0] = l_x;
416 x_north_east[1] = l_y;
417
418 // by default derivative boundary function pointers are null
423
424 // also by default second derivate boundary function pointers are null
429 }
430
431 //=============================================================================
432 /// \short Constructor - takes the minimum and maximum coordinates of the
433 /// of an assumed rectanguler domain in the x and y direction
434 //=============================================================================
436 const double& x_min,
437 const double& x_max,
438 const double& y_min,
439 const double& y_max)
440 {
441 // domain comprises one macro element
442 Macro_element_pt.resize(1);
443
444 // Create the macro element
445 Macro_element_pt[0] = new QMacroElement<2>(this, 0);
446
447 // set the boundary function pointers to zero
452
453 // resize x vectors
454 x_south_west.resize(2);
455 x_north_east.resize(2);
456
457 // set vector values
458 x_south_west[0] = x_min;
459 x_south_west[1] = y_min;
460 x_north_east[0] = x_max;
461 x_north_east[1] = y_max;
462
463 // by default derivative boundary function pointers are null
468
469 // also by default second derivate boundary function pointers are null
474 }
475
476 //=============================================================================
477 /// \short allows the boundary derivate function pointers to be set. To
478 /// compute the derivatives of the problem domain global coordinates (x_i) wrt
479 /// the macro element coordinates (m_i), dx_i/dm_t is required along the
480 /// domain boundaries (where dm_t is the macro element coordinate tangential
481 /// to the domain boundary). The derivatives dx_i/dm_t can either be
482 /// prescribed with function pointers, or if the function pointers are not
483 /// provided then dx_i/dm_t is computed with finite differencing.
484 /// Note - these functions are only required for domains contructed with
485 /// boundary function pointers
486 //=============================================================================
488 BoundaryFctPt d_north_pt,
489 BoundaryFctPt d_east_pt,
490 BoundaryFctPt d_south_pt,
491 BoundaryFctPt d_west_pt)
492 {
493 // set the boundary derivate function pointers
498 }
499
500 //=============================================================================
501 /// \short allows the boundary second derivate function pointers to be set.
502 /// To compute the second derivatives of the problem domain global
503 /// coordinates (x_i) wrt the macro element coordinates (m_i), d2x_i/dm_t^2
504 /// is required along the domain boundaries (where dm_t is the macro element
505 /// coordinate tangential to the domain boundary). The derivatives
506 /// d2x_i/dm_t^2 can either be prescribed with function pointers, or if the
507 /// function pointers are not provided then dx_i/dm_t is computed with finite
508 /// differencing.
509 /// Note - these functions are only required for domains contructed with
510 /// boundary function pointers
511 //=============================================================================
514 BoundaryFctPt d2_east_pt,
515 BoundaryFctPt d2_south_pt,
516 BoundaryFctPt d2_west_pt)
517 {
518 // set the boundary derivate function pointers
523 }
524
525 //=============================================================================
526 /// returns the global coordinate position (f) of macro element position s
527 /// on boundary i_direct (e.g. N/S/W/E in 2D) at time t (no time dependence)
528 //=============================================================================
530 const unsigned& t,
531 const unsigned& i_macro,
532 const unsigned& i_direct,
533 const Vector<double>& s,
535 {
536 // use quad tree edge names to label edge of domain
537 using namespace QuadTreeNames;
538
539#ifdef WARN_ABOUT_SUBTLY_CHANGED_OOMPH_INTERFACES
540 // Warn about time argument being moved to the front
542 "Order of function arguments has changed between versions 0.8 and 0.85",
543 "TopologicallyRectangularDomain::macro_element_boundary(...)",
545#endif
546
547 // north boundary
548 if (i_direct == N) r_N(s, f);
549 // east boundary
550 else if (i_direct == E)
551 r_E(s, f);
552 // south boundary
553 else if (i_direct == S)
554 r_S(s, f);
555 // west boundary
556 else if (i_direct == W)
557 r_W(s, f);
558 }
559
560 //=============================================================================
561 /// returns the derivates of the global coordinate position (f) wrt to the
562 /// macro element coordinate at macro macro element position s on boundary
563 /// i_direct (e.g. N/S/W/E in 2D) at time t (no time dependence)
564 //=============================================================================
566 const unsigned& t,
567 const unsigned& i_macro,
568 const unsigned& i_direct,
569 const Vector<double>& s,
571 {
572 // use quad tree edge names to label edge of domain
573 using namespace QuadTreeNames;
574
575#ifdef WARN_ABOUT_SUBTLY_CHANGED_OOMPH_INTERFACES
576 // Warn about time argument being moved to the front
578 "Order of function arguments has changed between versions 0.8 and 0.85",
579 "TopologicallyRectangularDomain::dmacro_element_boundary(...)",
581#endif
582
583 // north boundary
584 if (i_direct == N) dr_N(s, f);
585 // east boundary
586 else if (i_direct == E)
587 dr_E(s, f);
588 // south boundary
589 else if (i_direct == S)
590 dr_S(s, f);
591 // west boundary
592 else if (i_direct == W)
593 dr_W(s, f);
594 }
595
596 //=============================================================================
597 /// returns the second derivates of the global coordinate position (f) wrt to
598 /// the macro element coordinate at macro macro element position s on boundary
599 /// i_direct (e.g. N/S/W/E in 2D) at time t (no time dependence)
600 //=============================================================================
602 const unsigned& t,
603 const unsigned& i_macro,
604 const unsigned& i_direct,
605 const Vector<double>& s,
607 {
608 // use quad tree edge names to label edge of domain
609 using namespace QuadTreeNames;
610
611#ifdef WARN_ABOUT_SUBTLY_CHANGED_OOMPH_INTERFACES
612 // Warn about time argument being moved to the front
614 "Order of function arguments has changed between versions 0.8 and 0.85",
615 "TopologicallyRectangularDomain::d2macro_element_boundary(...)",
617#endif
618
619 // north boundary
620 if (i_direct == N) d2r_N(s, f);
621 // east boundary
622 else if (i_direct == E)
623 d2r_E(s, f);
624 // south boundary
625 else if (i_direct == S)
626 d2r_S(s, f);
627 // west boundary
628 else if (i_direct == W)
629 d2r_W(s, f);
630 }
631
632 //=============================================================================
633 /// \short takes the macro element coordinate position along the north
634 /// boundary and returns the global coordinate position along that boundary
635 //=============================================================================
638 {
639 if (North_boundary_fn_pt != 0)
640 {
641 (*North_boundary_fn_pt)(s[0], f);
642 }
643 else
644 {
645 f[0] =
646 x_south_west[0] + (s[0] + 1) / 2 * (x_north_east[0] - x_south_west[0]);
647 f[1] = x_north_east[1];
648 }
649 }
650
651 //=============================================================================
652 /// \short takes the macro element coordinate position along the east
653 /// boundary and returns the global coordinate position along that boundary
654 //=============================================================================
657 {
658 if (East_boundary_fn_pt != 0)
659 {
660 (*East_boundary_fn_pt)(s[0], f);
661 }
662 else
663 {
664 f[0] = x_north_east[0];
665 f[1] =
666 x_south_west[1] + (s[0] + 1) / 2 * (x_north_east[1] - x_south_west[1]);
667 }
668 }
669
670 //=============================================================================
671 /// \short takes the macro element coordinate position along the south
672 /// boundary and returns the global coordinate position along that boundary
673 //=============================================================================
676 {
677 if (South_boundary_fn_pt != 0)
678 {
679 (*South_boundary_fn_pt)(s[0], f);
680 }
681 else
682 {
683 f[0] =
684 x_south_west[0] + (s[0] + 1) / 2 * (x_north_east[0] - x_south_west[0]);
685 f[1] = x_south_west[1];
686 }
687 }
688
689 //=============================================================================
690 /// \short takes the macro element coordinate position along the west
691 /// boundary and returns the global coordinate position along that boundary
692 /// access down boundary function pointer
693 //=============================================================================
696 {
697 if (West_boundary_fn_pt != 0)
698 {
699 (*West_boundary_fn_pt)(s[0], f);
700 }
701 else
702 {
703 f[0] = x_south_west[0];
704 f[1] =
705 x_south_west[1] + (s[0] + 1) / 2 * (x_north_east[1] - x_south_west[1]);
706 }
707 }
708
709 //=============================================================================
710 /// \short takes the macro element coordinate position along the north
711 /// boundary and returns the derivates of the global coordinates with respect
712 /// to the boundary
713 //=============================================================================
716 {
717 // if N boundary fn provided
718 if (North_boundary_fn_pt != 0)
719 {
720 // if dN boundary fn provided
721 if (dNorth_boundary_fn_pt != 0)
722 {
723 (*dNorth_boundary_fn_pt)(s[0], dr);
724 }
725 // else compute by finite differencing
726 else
727 {
728 const double h = 10e-8;
730 (*North_boundary_fn_pt)(s[0] - 0.5 * h, x_N_left);
732 (*North_boundary_fn_pt)(s[0] + 0.5 * h, x_N_right);
733 dr[0] = (x_N_right[0] - x_N_left[0]) / h;
734 dr[1] = (x_N_right[1] - x_N_left[1]) / h;
735 }
736 }
737 // if N boundary fn not provided then mesh is rectangular
738 else
739 {
740 dr[0] = (x_north_east[0] - x_south_west[0]) / 2;
741 dr[1] = 0;
742 }
743 }
744
745 //=============================================================================
746 /// \short takes the macro element coordinate position along the E
747 /// boundary and returns the derivates of the global coordinates with respect
748 /// to the boundary
749 //=============================================================================
752 {
753 // if E boundary fn provided
754 if (East_boundary_fn_pt != 0)
755 {
756 // if dE boundary fn provided
757 if (dEast_boundary_fn_pt != 0)
758 {
759 (*dEast_boundary_fn_pt)(s[0], dr);
760 }
761 // else compute by finite differencing
762 else
763 {
764 const double h = 10e-8;
766 (*East_boundary_fn_pt)(s[0] - 0.5 * h, x_E_down);
768 (*East_boundary_fn_pt)(s[0] + 0.5 * h, x_E_up);
769 dr[0] = (x_E_up[0] - x_E_down[0]) / h;
770 dr[1] = (x_E_up[1] - x_E_down[1]) / h;
771 }
772 }
773 // if E boundary fn not provided then mesh is rectangular
774 else
775 {
776 dr[0] = 0;
777 dr[1] = (x_north_east[1] - x_south_west[1]) / 2;
778 }
779 }
780
781 //=============================================================================
782 /// \short takes the macro element coordinate position along the south
783 /// boundary and returns the derivates of the global coordinates with respect
784 /// to the boundary
785 //=============================================================================
788 {
789 // if S boundary fn provided
790 if (South_boundary_fn_pt != 0)
791 {
792 // if dS boundary fn provided
793 if (dSouth_boundary_fn_pt != 0)
794 {
795 (*dSouth_boundary_fn_pt)(s[0], dr);
796 }
797 // else compute by finite differencing
798 else
799 {
800 const double h = 10e-8;
802 (*South_boundary_fn_pt)(s[0] - 0.5 * h, x_N_left);
804 (*South_boundary_fn_pt)(s[0] + 0.5 * h, x_N_right);
805 dr[0] = (x_N_right[0] - x_N_left[0]) / h;
806 dr[1] = (x_N_right[1] - x_N_left[1]) / h;
807 }
808 }
809 // if S boundary fn not provided then mesh is rectangular
810 else
811 {
812 dr[0] = (x_north_east[0] - x_south_west[0]) / 2;
813 dr[1] = 0;
814 }
815 }
816
817 //=============================================================================
818 /// \short takes the macro element coordinate position along the W
819 /// boundary and returns the derivates of the global coordinates with respect
820 /// to the boundary
821 //=============================================================================
824 {
825 // if W boundary fn provided
826 if (West_boundary_fn_pt != 0)
827 {
828 // if dW boundary fn provided
829 if (dWest_boundary_fn_pt != 0)
830 {
831 (*dWest_boundary_fn_pt)(s[0], dr);
832 }
833 // else compute by finite differencing
834 else
835 {
836 const double h = 10e-8;
838 (*West_boundary_fn_pt)(s[0] - 0.5 * h, x_W_down);
840 (*West_boundary_fn_pt)(s[0] + 0.5 * h, x_W_up);
841 dr[0] = (x_W_up[0] - x_W_down[0]) / h;
842 dr[1] = (x_W_up[1] - x_W_down[1]) / h;
843 }
844 }
845 // if E boundary fn not provided then mesh is rectangular
846 else
847 {
848 dr[0] = 0;
849 dr[1] = (x_north_east[1] - x_south_west[1]) / 2;
850 }
851 }
852
853 //=============================================================================
854 /// \short takes the macro element coordinate position along the north
855 /// boundary and returns the second derivates of the global coordinates with
856 /// respect to the boundary
857 //=============================================================================
860 {
861 // if N boundary fn provided
862 if (North_boundary_fn_pt != 0)
863 {
864 // if d2N boundary fn provided
865 if (d2North_boundary_fn_pt != 0)
866 {
867 (*d2North_boundary_fn_pt)(s[0], d2r);
868 }
869 // else compute by finite differencing
870 else
871 {
872 // if dN boundary fn provided finite difference d2N from it
873 if (dNorth_boundary_fn_pt != 0)
874 {
875 const double h = 10e-8;
877 (*dNorth_boundary_fn_pt)(s[0] - 0.5 * h, dx_N_left);
879 (*dNorth_boundary_fn_pt)(s[0] + 0.5 * h, dx_N_right);
880 d2r[0] = (dx_N_right[0] - dx_N_left[0]) / h;
881 d2r[1] = (dx_N_right[1] - dx_N_left[1]) / h;
882 }
883 // else finite difference from N boundary fn
884 else
885 {
886 const double h = 10e-8;
888 (*North_boundary_fn_pt)(s[0] - h, N_left);
890 (*North_boundary_fn_pt)(s[0] + h, N_right);
892 (*North_boundary_fn_pt)(s[0], N_centre);
893 d2r[0] = (N_right[0] + N_left[0] - 2 * N_centre[0]) / (h * h);
894 d2r[1] = (N_right[1] + N_left[1] - 2 * N_centre[1]) / (h * h);
895 }
896 }
897 }
898 // if N boundary fn not provided then mesh is rectangular
899 else
900 {
901 d2r[0] = 0;
902 d2r[1] = 0;
903 }
904 }
905
906 //=============================================================================
907 /// \short takes the macro element coordinate position along the east
908 /// boundary and returns the second derivates of the global coordinates with
909 /// respect to the boundary
910 //=============================================================================
913 {
914 // if E boundary fn provided
915 if (East_boundary_fn_pt != 0)
916 {
917 // if d2E boundary fn provided
918 if (d2East_boundary_fn_pt != 0)
919 {
920 (*d2East_boundary_fn_pt)(s[0], d2r);
921 }
922 // else compute by finite differencing
923 else
924 {
925 // if dE boundary fn provided finite difference d2E from it
926 if (dEast_boundary_fn_pt != 0)
927 {
928 const double h = 10e-8;
930 (*dEast_boundary_fn_pt)(s[0] - 0.5 * h, dx_E_lower);
932 (*dEast_boundary_fn_pt)(s[0] + 0.5 * h, dx_E_upper);
933 d2r[0] = (dx_E_upper[0] - dx_E_lower[0]) / h;
934 d2r[1] = (dx_E_upper[1] - dx_E_lower[1]) / h;
935 }
936 // else finite difference from E boundary fn
937 else
938 {
939 const double h = 10e-8;
941 (*East_boundary_fn_pt)(s[0] - h, E_left);
943 (*East_boundary_fn_pt)(s[0] + h, E_right);
945 (*East_boundary_fn_pt)(s[0], E_centre);
946 d2r[0] = (E_right[0] + E_left[0] - 2 * E_centre[0]) / (h * h);
947 d2r[1] = (E_right[1] + E_left[1] - 2 * E_centre[1]) / (h * h);
948 }
949 }
950 }
951 // if E boundary fn not provided then mesh is rectangular
952 else
953 {
954 d2r[0] = 0;
955 d2r[1] = 0;
956 }
957 }
958
959 //=============================================================================
960 /// \short takes the macro element coordinate position along the south
961 /// boundary and returns the second derivates of the global coordinates with
962 /// respect to the boundary
963 //=============================================================================
966 {
967 // if S boundary fn provided
968 if (South_boundary_fn_pt != 0)
969 {
970 // if d2S boundary fn provided
971 if (d2South_boundary_fn_pt != 0)
972 {
973 (*d2South_boundary_fn_pt)(s[0], d2r);
974 }
975 // else compute by finite differencing
976 else
977 {
978 // if dS boundary fn provided finite difference d2S from it
979 if (dSouth_boundary_fn_pt != 0)
980 {
981 const double h = 10e-8;
983 (*dSouth_boundary_fn_pt)(s[0] - 0.5 * h, dx_S_left);
985 (*dSouth_boundary_fn_pt)(s[0] + 0.5 * h, dx_S_right);
986 d2r[0] = (dx_S_right[0] - dx_S_left[0]) / h;
987 d2r[1] = (dx_S_right[1] - dx_S_left[1]) / h;
988 }
989 // else finite difference from S boundary fn
990 else
991 {
992 const double h = 10e-8;
994 (*South_boundary_fn_pt)(s[0] - h, S_left);
996 (*South_boundary_fn_pt)(s[0] + h, S_right);
998 (*South_boundary_fn_pt)(s[0], S_centre);
999 d2r[0] = (S_right[0] + S_left[0] - 2 * S_centre[0]) / (h * h);
1000 d2r[1] = (S_right[1] + S_left[1] - 2 * S_centre[1]) / (h * h);
1001 }
1002 }
1003 }
1004 // if S boundary fn not provided then mesh is rectangular
1005 else
1006 {
1007 d2r[0] = 0;
1008 d2r[1] = 0;
1009 }
1010 }
1011
1012 //=============================================================================
1013 /// \short takes the macro element coordinate position along the west
1014 /// boundary and returns the second derivates of the global coordinates with
1015 /// respect to the boundary
1016 //=============================================================================
1019 {
1020 // if W boundary fn provided
1021 if (West_boundary_fn_pt != 0)
1022 {
1023 // if d2W boundary fn provided
1024 if (d2West_boundary_fn_pt != 0)
1025 {
1026 (*d2West_boundary_fn_pt)(s[0], d2r);
1027 }
1028 // else compute by finite differencing
1029 else
1030 {
1031 // if dW boundary fn provided finite difference d2W from it
1032 if (dWest_boundary_fn_pt != 0)
1033 {
1034 const double h = 10e-8;
1036 (*dWest_boundary_fn_pt)(s[0] - 0.5 * h, dx_W_lower);
1038 (*dWest_boundary_fn_pt)(s[0] + 0.5 * h, dx_W_upper);
1039 d2r[0] = (dx_W_upper[0] - dx_W_lower[0]) / h;
1040 d2r[1] = (dx_W_upper[1] - dx_W_lower[1]) / h;
1041 }
1042 // else finite difference from W boundary fn
1043 else
1044 {
1045 const double h = 10e-8;
1047 (*West_boundary_fn_pt)(s[0] - h, W_left);
1049 (*West_boundary_fn_pt)(s[0] + h, W_right);
1051 (*West_boundary_fn_pt)(s[0], W_centre);
1052 d2r[0] = (W_right[0] + W_left[0] - 2 * W_centre[0]) / (h * h);
1053 d2r[1] = (W_right[1] + W_left[1] - 2 * W_centre[1]) / (h * h);
1054 }
1055 }
1056 }
1057 // if W boundary fn not provided then mesh is rectangular
1058 else
1059 {
1060 d2r[0] = 0;
1061 d2r[1] = 0;
1062 }
1063 }
1064} // namespace oomph
1065
1066#endif
e
Definition cfortran.h:571
static char t char * s
Definition cfortran.h:568
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
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...
Topologically Rectangular Domain - a domain dexcribing a topologically rectangular problem - primaril...
void r_E(const Vector< double > &s, Vector< double > &f)
takes the macro element coordinate position along the east boundary and returns the global coordinate...
void d2macro_element_boundary(const unsigned &t, const unsigned &i_macro, const unsigned &i_direct, const Vector< double > &s, Vector< double > &f)
returns the second derivates of the global coordinate position (f) wrt to the macro element coordinat...
BoundaryFctPt d2North_boundary_fn_pt
Function pointer to prescribe the second derivates of global coordinates wrt to the macro element coo...
void dmacro_element_boundary(const unsigned &t, const unsigned &i_macro, const unsigned &i_direct, const Vector< double > &s, Vector< double > &f)
returns the derivates of the global coordinate position (f) wrt to the macro element coordinate at ma...
void dr_E(const Vector< double > &s, Vector< double > &dr)
takes the macro element coordinate position along the E boundary and returns the derivates of the glo...
void dr_S(const Vector< double > &s, Vector< double > &dr)
takes the macro element coordinate position along the south boundary and returns the derivates of the...
void operator=(const TopologicallyRectangularDomain &)=delete
Broken assignment operator.
Vector< double > x_south_west
coordinate position of south west corner of domain (only used if boundary functions are not used)
BoundaryFctPt d2East_boundary_fn_pt
Function pointer to prescribe the second derivates of global coordinates wrt to the macro element coo...
void d2r_W(const Vector< double > &s, Vector< double > &d2r)
takes the macro element coordinate position along the west boundary and returns the second derivates ...
BoundaryFctPt South_boundary_fn_pt
Function pointer to prescribe the north boundary of this topologically rectangular domain.
TopologicallyRectangularDomain(const TopologicallyRectangularDomain &)=delete
Broken copy constructor.
void macro_element_boundary(const unsigned &t, const unsigned &i_macro, const unsigned &i_direct, const Vector< double > &s, Vector< double > &f)
returns the global coordinate position (f) of macro element position s on boundary i_direct (e....
BoundaryFctPt dEast_boundary_fn_pt
Function pointer to prescribe the derivates of global coordinates wrt to the macro element coordinate...
BoundaryFctPt d2West_boundary_fn_pt
Function pointer to prescribe the second derivates of global coordinates wrt to the macro element coo...
void set_boundary_second_derivative_functions(BoundaryFctPt d2_north_pt, BoundaryFctPt d2_east_pt, BoundaryFctPt d2_south_pt, BoundaryFctPt d2_west_pt)
allows the boundary second derivate function pointers to be set. To compute the second derivatives of...
void r_N(const Vector< double > &s, Vector< double > &f)
takes the macro element coordinate position along the north boundary and returns the global coordinat...
void d2r_N(const Vector< double > &s, Vector< double > &d2r)
takes the macro element coordinate position along the north boundary and returns the second derivates...
BoundaryFctPt d2South_boundary_fn_pt
Function pointer to prescribe the second derivates of global coordinates wrt to the macro element coo...
void r_S(const Vector< double > &s, Vector< double > &f)
takes the macro element coordinate position along the south boundary and returns the global coordinat...
BoundaryFctPt North_boundary_fn_pt
Function pointer to prescribe the north boundary of this topologically rectangular domain.
void set_boundary_derivative_functions(BoundaryFctPt d_north_pt, BoundaryFctPt d_east_pt, BoundaryFctPt d_south_pt, BoundaryFctPt d_west_pt)
allows the boundary derivate function pointers to be set. To compute the derivatives of the problem d...
void(* BoundaryFctPt)(const double &s, Vector< double > &r)
boundary function pointer - for a given boundary takes the macro element coordinate position on that ...
BoundaryFctPt dWest_boundary_fn_pt
Function pointer to prescribe the derivates of global coordinates wrt to the macro element coordinate...
void dr_W(const Vector< double > &s, Vector< double > &dr)
takes the macro element coordinate position along the W boundary and returns the derivates of the glo...
void r_W(const Vector< double > &s, Vector< double > &f)
takes the macro element coordinate position along the west boundary and returns the global coordinate...
~TopologicallyRectangularDomain()
Destructor - empty; clean up done in base class.
void d2r_E(const Vector< double > &s, Vector< double > &d2r)
takes the macro element coordinate position along the east boundary and returns the second derivates ...
BoundaryFctPt West_boundary_fn_pt
Function pointer to prescribe the west boundary of this topologically rectangular domain.
BoundaryFctPt East_boundary_fn_pt
Function pointer to prescribe the east boundary of this topologically rectangular domain.
TopologicallyRectangularDomain(BoundaryFctPt north_pt, BoundaryFctPt east_pt, BoundaryFctPt south_pt, BoundaryFctPt west_pt)
Constructor - domain boundaries are described with four boundary function pointers describing the top...
void dr_N(const Vector< double > &s, Vector< double > &dr)
takes the macro element coordinate position along the north boundary and returns the derivates of the...
void d2r_S(const Vector< double > &s, Vector< double > &d2r)
takes the macro element coordinate position along the south boundary and returns the second derivates...
Vector< double > x_north_east
coordinate position of north east corner of domain (only used if boundary functions are not used)
BoundaryFctPt dSouth_boundary_fn_pt
Function pointer to prescribe the derivates of global coordinates wrt to the macro element coordinate...
BoundaryFctPt dNorth_boundary_fn_pt
Function pointer to prescribe the derivates of global coordinates wrt to the macro element coordinate...
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).