geom_objects.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-2026 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_OBJECTS_HEADER
27#define OOMPH_GEOM_OBJECTS_HEADER
28
29
30// Config header
31#ifdef HAVE_CONFIG_H
32#include <oomph-lib-config.h>
33#endif
34
35// oomph-lib headers
36#include "nodes.h"
37#include "timesteppers.h"
38
39
40namespace oomph
41{
42 ////////////////////////////////////////////////////////////////////////
43 ////////////////////////////////////////////////////////////////////////
44 // Geometric object
45 ////////////////////////////////////////////////////////////////////////
46 ////////////////////////////////////////////////////////////////////////
47
48
49 //========================================================================
50 /// A geometric object is an object that provides a parametrised
51 /// description of its shape via the function GeomObject::position(...).
52 ///
53 /// The minimum functionality is: The geometric object has
54 /// a number of Lagrangian (intrinsic) coordinates that parametrise
55 /// the (Eulerian) position vector, whose dimension might
56 /// differ from the number of Lagrangian (intrinsic) coordinates (e.g.
57 /// for shell-like objects).
58 ///
59 /// We might also need the derivatives of the position
60 /// Vector w.r.t. to the Lagrangian (intrinsic) coordinates and interfaces
61 /// for this functionality are provided.
62 /// [Note: For some geometric objects it might be too tedious to work out
63 /// the derivatives and they might not be needed anyway. In other
64 /// cases we might always need the position vector and all
65 /// derivatives at the same time. We provide suitable interfaces
66 /// for these cases in virtual but broken (rather than pure virtual) form
67 /// so the user can (but doesn't have to) provide the required versions
68 /// by overloading.]
69 ///
70 /// The shape of a geometric object is usually determined by a number
71 /// of parameters whose value might have to be determined as part
72 /// of the overall solution (e.g. for geometric objects that represent
73 /// elastic walls). The geometric object
74 /// therefore has a vector of (pointers to) geometric Data,
75 /// which can be free/pinned and have a time history, etc. This makes
76 /// it possible to `upgrade' GeomObjects to GeneralisedElements -- in this
77 /// case the geometric Data plays the role of internal Data in the
78 /// GeneralisedElement. Conversely, FiniteElements, in which a geometry
79 /// (spatial coordinate) has been defined, inherit from GeomObjects,
80 /// which is particularly useful in FSI computations:
81 /// Meshing of moving domains is typically performed by representing the
82 /// domain as an object of type Domain and, by default, Domain boundaries are
83 /// represented by GeomObjects. In FSI computations, the boundary
84 /// of the fluid domain is represented by a number of solid mechanics
85 /// elements. These elements are, in fact, GeomObjects via inheritance so
86 /// that the we can use the standard interfaces of the GeomObject class for
87 /// mesh generation. An example is the class \c FSIHermiteBeamElement which is
88 /// derived from the class \c HermiteBeamElement (a `normal' beam element) and
89 /// the \c GeomObject class.
90 ///
91 /// The shape of a geometric object can have an explicit time-dependence, for
92 /// instance in cases where a domain boundary is performing
93 /// prescribed motions. We provide access to the `global'
94 /// time by giving the object a pointer to a timestepping scheme.
95 /// [Note that, within the overall FE code, time is only ever evaluated at
96 /// discrete instants (which are accessible via the timestepper),
97 /// never in continuous form]. The timestepper is also needed to evaluate
98 /// time-derivatives if the geometric Data carries a time history.
99 //========================================================================
101 {
102 public:
103 /// Default constructor.
105
106 /// Constructor: Pass dimension of geometric object (# of Eulerian
107 /// coords = # of Lagrangian coords; no time history available/needed)
108 GeomObject(const unsigned& ndim)
110 {
111 }
112
113
114 /// Constructor: pass # of Eulerian and Lagrangian coordinates.
115 /// No time history available/needed
116 GeomObject(const unsigned& nlagrangian, const unsigned& ndim)
118 {
119#ifdef PARANOID
120 if (nlagrangian > ndim)
121 {
122 std::ostringstream error_message;
123 error_message << "# of Lagrangian coordinates " << nlagrangian
124 << " cannot be bigger than # of Eulerian ones " << ndim
125 << std::endl;
126
127 throw OomphLibError(error_message.str(),
130 }
131#endif
132 }
133
134 /// Constructor: pass # of Eulerian and Lagrangian coordinates
135 /// and pointer to time-stepper which is used to handle the
136 /// position at previous timesteps and allows the evaluation
137 /// of veloc/acceleration etc. in cases where the GeomData
138 /// varies with time.
139 GeomObject(const unsigned& nlagrangian,
140 const unsigned& ndim,
143 Ndim(ndim),
145 {
146#ifdef PARANOID
147 if (nlagrangian > ndim)
148 {
149 std::ostringstream error_message;
150 error_message << "# of Lagrangian coordinates " << nlagrangian
151 << " cannot be bigger than # of Eulerian ones " << ndim
152 << std::endl;
153
154 throw OomphLibError(error_message.str(),
157 }
158#endif
159 }
160
161 /// Broken copy constructor
162 GeomObject(const GeomObject& dummy) = delete;
163
164 /// Broken assignment operator
165 void operator=(const GeomObject&) = delete;
166
167 /// (Empty) destructor
168 virtual ~GeomObject() {}
169
170 /// Access function to # of Lagrangian coordinates
171 unsigned nlagrangian() const
172 {
173 return NLagrangian;
174 }
175
176 /// Access function to # of Eulerian coordinates
177 unsigned ndim() const
178 {
179 return Ndim;
180 }
181
182 /// Set # of Lagrangian and Eulerian coordinates
184 const unsigned& n_dim)
185 {
187 Ndim = n_dim;
188 }
189
190 /// Access function for pointer to time stepper: Null if object is
191 /// not time-dependent
196
197 /// Access function for pointer to time stepper: Null if object is
198 /// not time-dependent. Const version
203
204 /// How many items of Data does the shape of the object depend on?
205 /// This is implemented as a broken virtual function. You must overload
206 /// this for GeomObjects that contain geometric Data, i.e. GeomObjects
207 /// whose shape depends on Data that may contain unknowns in the
208 /// overall Problem.
209 virtual unsigned ngeom_data() const
210 {
211 std::ostringstream error_message;
212 error_message
213 << "GeomObject::ngeom_data() is a broken virtual function.\n"
214 << "Please implement it (and its companion "
215 "GeomObject::geom_data_pt())\n"
216 << "for any GeomObject whose shape depends on Data whose values may \n"
217 << "be unknowns in the global Problem. \n"
218 << "If you have arrived here in a parallel job then it may be the case "
219 "\n"
220 << "that you have not set the keep_all_elements_as_halos() flag to "
221 "true \n"
222 << "for the MeshAsGeomObject representing the lower-dimensional mesh \n"
223 << "in a problem with multiple meshes. \n";
224 throw OomphLibError(
226 }
227
228 /// Return pointer to the j-th Data item that the object's
229 /// shape depends on. This is implemented as a broken virtual function.
230 /// You must overload this for GeomObjects that contain geometric Data,
231 /// i.e. GeomObjects whose shape depends on Data that may contain
232 /// unknowns in the overall Problem.
233 virtual Data* geom_data_pt(const unsigned& j)
234 {
235 std::ostringstream error_message;
236 error_message
237 << "GeomObject::geom_data_pt() is a broken virtual function.\n"
238 << "Please implement it (and its companion GeomObject::ngeom_data())\n"
239 << "for any GeomObject whose shape depends on Data whose values may \n"
240 << "be unknowns in the global Problem. \n"
241 << "If you have arrived here in a parallel job then it may be the case "
242 "\n"
243 << "that you have not set the keep_all_elements_as_halos() flag to "
244 "true \n"
245 << "for the MeshAsGeomObject representing the lower-dimensional mesh \n"
246 << "in a problem with multiple meshes. \n";
247 throw OomphLibError(
249 }
250
251 /// Parametrised position on object at current time: r(zeta).
252 virtual void position(const Vector<double>& zeta,
253 Vector<double>& r) const = 0;
254
255 /// Parametrised position on object: r(zeta). Evaluated at
256 /// previous timestep. t=0: current time; t>0: previous
257 /// timestep. Works for t=0 but needs to be overloaded
258 /// if genuine time-dependence is required.
259 virtual void position(const unsigned& t,
260 const Vector<double>& zeta,
261 Vector<double>& r) const
262 {
263 if (t != 0)
264 {
265 throw OomphLibError(
266 "Calling steady position() from discrete unsteady position()",
269 }
270 position(zeta, r);
271 }
272
273
274 /// Parametrised position on object: r(zeta). Evaluated at
275 /// the continuous time value, t.
276 virtual void position(const double& t,
277 const Vector<double>& zeta,
278 Vector<double>& r) const
279 {
280 std::ostringstream error_message;
281 error_message << "GeomObject::position() is a broken virtual function.\n"
282 << "Please implement it for any GeomObject whose shape\n"
283 << "is time-dependent and will be used in the extrusion\n"
284 << "of a mesh (in the time direction).\n";
285 throw OomphLibError(
287 }
288
289
290 /// j-th time-derivative on object at current time:
291 /// \f$ \frac{d^{j} r(\zeta)}{dt^j} \f$.
292 virtual void dposition_dt(const Vector<double>& zeta,
293 const unsigned& j,
295 {
296 // If the index is zero the return the position
297 if (j == 0)
298 {
300 }
301 // Otherwise assume that the geometric object is static
302 // and return zero after throwing a warning
303 else
304 {
305 std::ostringstream warning_stream;
307 << "Using default (static) assignment " << j
308 << "-th time derivative in GeomObject::dposition_dt(...) is zero\n"
309 << "Overload for your specific geometric object if this is not \n"
310 << "appropriate. \n";
312 "GeomObject::dposition_dt()",
314
315 unsigned n = drdt.size();
316 for (unsigned i = 0; i < n; i++)
317 {
318 drdt[i] = 0.0;
319 }
320 }
321 }
322
323 /// Return a non-const reference to the FD step size
324 /// for the first derivative, allowing modification
325 /// of the value.
327 {
329 }
330
331 /// Return a const reference to the FD step size
332 /// for the first derivative, providing read-only access.
334 {
336 }
337
338 /// Return a non-const reference to the FD step size
339 /// for the second derivative, allowing modification
340 /// of the value.
342 {
344 }
345
346 /// Return a const reference to the FD step size
347 /// for the second derivative, providing read-only access.
349 {
351 }
352
353 /// Derivative of position Vector w.r.t. to coordinates:
354 /// \f$ \frac{dR_i}{d \zeta_\alpha}\f$ = drdzeta(alpha,i).
355 /// Evaluated at current time.
356 /// By default, the finite difference method is employed.
357 virtual void dposition(const Vector<double>& zeta,
359 {
360 // Position at the current Lagrangian coordinate
361 Vector<double> r(Ndim, 0.0);
362 position(zeta, r);
363
364 // Initialize the variables
365
366 // Position after an increment in one Lagrangian coordinate
368
369 // Incremented Lagrangian coordinate
371
372 // Copy the base coordinate
373 for (unsigned l = 0; l < NLagrangian; l++)
374 {
375 zeta_plus[l] = zeta[l];
376 }
377
378 // Loop over Lagrangian coordinates
379 for (unsigned i = 0; i < NLagrangian; i++)
380 {
381 // Apply the increment in direction i
383
384 // Evaluate position at the perturbed coordinate
386
387 // Restore only the modified component
388 zeta_plus[i] = zeta[i];
389
390 // Compute the finite-difference derivative
391 for (unsigned j = 0; j < Ndim; j++)
392 {
394 }
395 }
396 }
397
398
399 /// 2nd derivative of position Vector w.r.t. to coordinates:
400 /// \f$ \frac{d^2R_i}{d \zeta_\alpha d \zeta_\beta}\f$ =
401 /// ddrdzeta(alpha,beta,i).
402 /// Evaluated at current time.
403 /// By default, we use a central-difference scheme.
404 virtual void d2position(const Vector<double>& zeta,
406 {
407 // Position at the base Lagrangian coordinate
408 Vector<double> r(Ndim, 0.0);
409 position(zeta, r);
410
411 // Perturbed Lagrangian coordinate
413
414 // Copy the base coordinate
415 for (unsigned l = 0; l < NLagrangian; l++)
416 {
418 }
419
420 // Initialize the variables
421
422 // Position at zeta + dzeta e_i
424
425 // Position at zeta - dzeta e_i
427
428 // Position at zeta + dzeta e_i + dzeta e_j
430
431 // Position at zeta - dzeta e_i - dzeta e_j
433
434 // Position at zeta + dzeta e_i - dzeta e_j
436
437 // Position at zeta - dzeta e_i + dzeta e_j
439
440 // Loop over Lagrangian coordinates to compute the second derivatives
441 for (unsigned i = 0; i < NLagrangian; i++)
442 {
443 for (unsigned j = 0; j < NLagrangian; j++)
444 {
445 // Case 1: Repeated second derivatives
446 if (i == j)
447 {
448 // Apply +dzeta e_i perturbations
450
451 // Evaluate positions with +dzeta e_i perturbations
453
454 // Apply -dzeta e_i perturbations
456
457 // Evaluate positions with -dzeta e_i perturbations
459
460 // Restore only the modified component
462
463 // Loop over the dimensions
464 for (unsigned k = 0; k < Ndim; k++)
465 {
466 // Second derivative via central difference
467 ddrdzeta(i, j, k) =
468 (r_plus[k] - 2.0 * r[k] + r_minus[k]) /
470 }
471 }
472 // Case 2: Mixed second derivatives
473 else
474 {
475 // Apply perturbations: +dzeta e_i+dzeta e_j
478
479 // Evaluate positions with +dzeta e_i+dzeta e_j perturbations
481
482 // Apply perturbations: -dzeta e_i-dzeta e_j
485
486 // Evaluate positions with -dzeta e_i-dzeta e_j perturbations
488
489 // Apply perturbations: +dzeta e_i-dzeta e_j
492
493 // Evaluate positions with +dzeta e_i-dzeta e_j perturbations
495
496 // Apply perturbations: -dzeta e_i+dzeta e_j
499
500 // Evaluate positions with -dzeta e_i+dzeta e_j perturbations
502
503 // Restore only the modified components
506
507 // Loop over the dimensions
508 for (unsigned k = 0; k < Ndim; k++)
509 {
510 // Mixed second derivative via central difference stencil
511 ddrdzeta(i, j, k) =
513 r_two_minus[k]) /
515 }
516 }
517 }
518 }
519 }
520
521
522 /// Posn Vector and its 1st & 2nd derivatives
523 /// w.r.t. to coordinates:
524 /// \f$ \frac{dR_i}{d \zeta_\alpha}\f$ = drdzeta(alpha,i).
525 /// \f$ \frac{d^2R_i}{d \zeta_\alpha d \zeta_\beta}\f$ =
526 /// ddrdzeta(alpha,beta,i).
527 /// Evaluated at current time.
528 virtual void d2position(const Vector<double>& zeta,
532 {
533 // Get the position
534 position(zeta, r);
535
536 // Get the first derivative
538
539 // Get the second derivatives
541 }
542
543 /// A geometric object may be composed of may sub-objects (e.g.
544 /// a finite-element representation of a boundary). In order to implement
545 /// sparse update functions, it is necessary to know the sub-object
546 /// and local coordinate within
547 /// that sub-object at a given intrinsic coordinate, zeta. Note that only
548 /// one sub-object can "cover" any given intrinsic position. If the position
549 /// is at an "interface" between sub-objects, either one can be returned.
550 /// The default implementation merely returns, the pointer to the "entire"
551 /// GeomObject and the coordinate, zeta
552 /// The optional boolean flag only applies if a Newton method is used to
553 /// find the value of zeta, and if true the value of the coordinate
554 /// s is used as the initial guess for the method. If the flag is false
555 /// (the default) a value of s=0 is used as the initial guess.
556 virtual void locate_zeta(
557 const Vector<double>& zeta,
560 const bool& use_coordinate_as_initial_guess = false)
561 {
562 // By default, the local coordinate is intrinsic coordinate
563 s = zeta;
564 // The sub_object is the entire object
565 sub_geom_object_pt = this;
566 }
567
568 /// A geometric object may be composed of many sub-objects
569 /// each with their own local coordinate. This function returns the
570 /// "global" intrinsic coordinate zeta (within the compound object), at
571 /// a given local coordinate s (i.e. the intrinsic coordinate of the
572 /// sub-GeomObject. In simple (non-compound) GeomObjects, the local
573 /// intrinsic coordinate is the global intrinsic coordinate
574 /// and so the function merely returns s. To make it less likely
575 /// that the default implementation is called in error (because
576 /// it is not overloaded in a derived GeomObject where the default
577 /// is not appropriate, we do at least check that s and zeta
578 /// have the same size if called in PARANOID mode.
579 virtual void interpolated_zeta(const Vector<double>& s,
580 Vector<double>& zeta) const
581 {
582#ifdef PARANOID
583 if (zeta.size() != s.size())
584 {
585 std::ostringstream error_message;
586 error_message << "You've called the default implementation of "
587 << "GeomObject::interpolated_zeta() \n"
588 << "but zeta.size()=" << zeta.size()
589 << "and s.size()=" << s.size() << std::endl
590 << "This doesn't make sense! You probably have to \n"
591 << "overload this function in your specific GeomObject\n";
592 throw OomphLibError(error_message.str(),
595 }
596#endif
597 // By default the global intrinsic coordinate is equal to the local one
598 zeta = s;
599 }
600
601 protected:
602 /// Number of Lagrangian (intrinsic) coordinates
603 unsigned NLagrangian;
604
605 /// Number of Eulerian coordinates
606 unsigned Ndim;
607
608 /// Timestepper (used to handle access to geometry
609 /// at previous timesteps)
611
612 private:
613 /// FD step for first derivatives.
614 /// For a forward difference approximation, the optimal scaling follows
615 /// h ~ sqrt(epsilon_machine_precision), obtained by balancing truncation
616 /// error O(h) and round-off error O(epsilon_machine_precision / h).
617 double First_derivative_dzeta = 1.0e-8;
618
619 /// FD step for second derivatives (central difference).
620 /// The step size is chosen to balance truncation error O(h^2) and
621 /// round-off error O(epsilon_machine_precision / h^2), giving the optimal
622 /// scaling h ~ epsilon_machine_precision^{1/4}.
623 double Second_derivative_dzeta = 1.0e-4;
624 };
625
626
627 ///////////////////////////////////////////////////////////////////////
628 ///////////////////////////////////////////////////////////////////////
629 // Straight line as geometric object
630 ///////////////////////////////////////////////////////////////////////
631 ///////////////////////////////////////////////////////////////////////
632
633
634 //=========================================================================
635 /// Steady, straight 1D line in 2D space
636 /// \f[ x = \zeta \f]
637 /// \f[ y = H \f]
638 //=========================================================================
640 {
641 public:
642 /// Constructor: One item of geometric data:
643 /// \code
644 /// Geom_data_pt[0]->value(0) = height
645 /// \endcode
647 {
648#ifdef PARANOID
649 if (geom_data_pt.size() != 1)
650 {
651 std::ostringstream error_message;
652 error_message << "geom_data_pt should have size 1, not "
653 << geom_data_pt.size() << std::endl;
654
655 if (geom_data_pt[0]->nvalue() != 1)
656 {
657 error_message << "geom_data_pt[0] should have 1 value, not "
658 << geom_data_pt[0]->nvalue() << std::endl;
659 }
660
661 throw OomphLibError(error_message.str(),
664 }
665#endif
666 Geom_data_pt.resize(1);
668
669 // Data has been created externally: Must not clean up
670 Must_clean_up = false;
671 }
672
673 /// Constructor: Pass height (pinned by default)
674 StraightLine(const double& height) : GeomObject(1, 2)
675 {
676 // Create Data for straight-line object: The only geometric data is the
677 // height which is pinned
678 Geom_data_pt.resize(1);
679
680 // Create data: One value, no timedependence, free by default
681 Geom_data_pt[0] = new Data(1);
682
683 // I've created the data, I need to clean up
684 Must_clean_up = true;
685
686 // Pin the data
687 Geom_data_pt[0]->pin(0);
688
689 // Give it a value: Initial height
690 Geom_data_pt[0]->set_value(0, height);
691 }
692
693
694 /// Broken copy constructor
696
697 /// Broken assignment operator
698 void operator=(const StraightLine&) = delete;
699
700 /// Destructor: Clean up if necessary
702 {
703 // Do I need to clean up?
704 if (Must_clean_up)
705 {
706 delete Geom_data_pt[0];
707 Geom_data_pt[0] = 0;
708 }
709 }
710
711
712 /// Position Vector at Lagrangian coordinate zeta
714 {
715 // Position Vector
716 r[0] = zeta[0];
717 r[1] = Geom_data_pt[0]->value(0);
718 }
719
720
721 /// Parametrised position on object: r(zeta). Evaluated at
722 /// previous timestep. t=0: current time; t>0: previous
723 /// timestep.
724 void position(const unsigned& t,
725 const Vector<double>& zeta,
726 Vector<double>& r) const
727 {
728#ifdef PARANOID
729 if (t > Geom_data_pt[0]->time_stepper_pt()->nprev_values())
730 {
731 std::ostringstream error_message;
732 error_message << "t > nprev_values() " << t << " "
734 << std::endl;
735
736 throw OomphLibError(error_message.str(),
739 }
740#endif
741
742 // Position Vector at time level t
743 r[0] = zeta[0];
744 r[1] = Geom_data_pt[0]->value(t, 0);
745 }
746
747
748 /// Derivative of position Vector w.r.t. to coordinates:
749 /// \f$ \frac{dR_i}{d \zeta_\alpha}\f$ = drdzeta(alpha,i).
750 /// Evaluated at current time.
751 virtual void dposition(const Vector<double>& zeta,
753 {
754 // Tangent vector
755 drdzeta(0, 0) = 1.0;
756 drdzeta(0, 1) = 0.0;
757 }
758
759
760 /// 2nd derivative of position Vector w.r.t. to coordinates:
761 /// \f$ \frac{d^2R_i}{d \zeta_\alpha d \zeta_\beta}\f$ =
762 /// ddrdzeta(alpha,beta,i). Evaluated at current time.
763 virtual void d2position(const Vector<double>& zeta,
765 {
766 // Derivative of tangent vector
767 ddrdzeta(0, 0, 0) = 0.0;
768 ddrdzeta(0, 0, 1) = 0.0;
769 }
770
771
772 /// Posn Vector and its 1st & 2nd derivatives
773 /// w.r.t. to coordinates:
774 /// \f$ \frac{dR_i}{d \zeta_\alpha}\f$ = drdzeta(alpha,i).
775 /// \f$ \frac{d^2R_i}{d \zeta_\alpha d \zeta_\beta}\f$ =
776 /// ddrdzeta(alpha,beta,i).
777 /// Evaluated at current time.
778 virtual void d2position(const Vector<double>& zeta,
782 {
783 // Position Vector
784 r[0] = zeta[0];
785 r[1] = Geom_data_pt[0]->value(0);
786
787 // Tangent vector
788 drdzeta(0, 0) = 1.0;
789 drdzeta(0, 1) = 0.0;
790
791 // Derivative of tangent vector
792 ddrdzeta(0, 0, 0) = 0.0;
793 ddrdzeta(0, 0, 1) = 0.0;
794 }
795
796
797 /// How many items of Data does the shape of the object depend on?
798 unsigned ngeom_data() const
799 {
800 return Geom_data_pt.size();
801 }
802
803 /// Return pointer to the j-th Data item that the object's
804 /// shape depends on
805 Data* geom_data_pt(const unsigned& j)
806 {
807 return Geom_data_pt[j];
808 }
809
810 private:
811 /// Vector of pointers to Data items that affects the object's shape
813
814 /// Do I need to clean up?
816 };
817
818
819 ///////////////////////////////////////////////////////////////////////
820 ///////////////////////////////////////////////////////////////////////
821 // Ellipse as geometric object
822 ///////////////////////////////////////////////////////////////////////
823 ///////////////////////////////////////////////////////////////////////
824
825
826 //=========================================================================
827 /// Steady ellipse with half axes A and B as geometric object:
828 /// \f[ x = A \cos(\zeta) \f]
829 /// \f[ y = B \sin(\zeta) \f]
830 //=========================================================================
831 class Ellipse : public GeomObject
832 {
833 public:
834 /// Constructor: 1 Lagrangian coordinate, 2 Eulerian coords. Pass
835 /// half axes as Data:
836 /// \code
837 /// Geom_data_pt[0]->value(0) = A
838 /// Geom_data_pt[0]->value(1) = B
839 /// \endcode
841 {
842#ifdef PARANOID
843 if (geom_data_pt.size() != 1)
844 {
845 std::ostringstream error_message;
846 error_message << "geom_data_pt should have size 1, not "
847 << geom_data_pt.size() << std::endl;
848
849 if (geom_data_pt[0]->nvalue() != 2)
850 {
851 error_message << "geom_data_pt[0] should have 2 values, not "
852 << geom_data_pt[0]->nvalue() << std::endl;
853 }
854
855 throw OomphLibError(error_message.str(),
858 }
859#endif
860 Geom_data_pt.resize(1);
862
863 // Data has been created externally: Must not clean up
864 Must_clean_up = false;
865 }
866
867
868 /// Constructor: 1 Lagrangian coordinate, 2 Eulerian coords. Pass
869 /// half axes A and B; both pinned.
870 Ellipse(const double& A, const double& B) : GeomObject(1, 2)
871 {
872 // Resize Data for ellipse object:
873 Geom_data_pt.resize(1);
874
875 // Create data: Two values, no timedependence, free by default
876 Geom_data_pt[0] = new Data(2);
877
878 // I've created the data, I need to clean up
879 Must_clean_up = true;
880
881 // Pin the data
882 Geom_data_pt[0]->pin(0);
883 Geom_data_pt[0]->pin(1);
884
885 // Set half axes
886 Geom_data_pt[0]->set_value(0, A);
887 Geom_data_pt[0]->set_value(1, B);
888 }
889
890 /// Broken copy constructor
891 Ellipse(const Ellipse& dummy) = delete;
892
893 /// Broken assignment operator
894 void operator=(const Ellipse&) = delete;
895
896 /// Destructor: Clean up if necessary
898 {
899 // Do I need to clean up?
900 if (Must_clean_up)
901 {
902 delete Geom_data_pt[0];
903 Geom_data_pt[0] = 0;
904 }
905 }
906
907 /// Set horizontal half axis
908 void set_A_ellips(const double& a)
909 {
910 Geom_data_pt[0]->set_value(0, a);
911 }
912
913 /// Set vertical half axis
914 void set_B_ellips(const double& b)
915 {
916 Geom_data_pt[0]->set_value(1, b);
917 }
918
919 /// Access function for horizontal half axis
920 double a_ellips()
921 {
922 return Geom_data_pt[0]->value(0);
923 }
924
925 /// Access function for vertical half axis
926 double b_ellips()
927 {
928 return Geom_data_pt[0]->value(1);
929 }
930
931
932 /// Position Vector at Lagrangian coordinate zeta
934 {
935 // Position Vector
936 r[0] = Geom_data_pt[0]->value(0) * cos(zeta[0]);
937 r[1] = Geom_data_pt[0]->value(1) * sin(zeta[0]);
938 }
939
940
941 /// Parametrised position on object: r(zeta). Evaluated at
942 /// previous timestep. t=0: current time; t>0: previous
943 /// timestep.
944 void position(const unsigned& t,
945 const Vector<double>& zeta,
946 Vector<double>& r) const
947 {
948 // If we have done the construction, it's a Steady Ellipse,
949 // so all time-history values of the position are equal to the position
950 if (Must_clean_up)
951 {
952 position(zeta, r);
953 return;
954 }
955
956 // Otherwise check that the value of t is within range
957#ifdef PARANOID
958 if (t > Geom_data_pt[0]->time_stepper_pt()->nprev_values())
959 {
960 std::ostringstream error_message;
961 error_message << "t > nprev_values() " << t << " "
963 << std::endl;
964
965 throw OomphLibError(error_message.str(),
968 }
969#endif
970
971 // Position Vector
972 r[0] = Geom_data_pt[0]->value(t, 0) * cos(zeta[0]);
973 r[1] = Geom_data_pt[0]->value(t, 1) * sin(zeta[0]);
974 }
975
976
977 /// Derivative of position Vector w.r.t. to coordinates:
978 /// \f$ \frac{dR_i}{d \zeta_\alpha}\f$ = drdzeta(alpha,i).
981 {
982 // Components of the single tangent Vector
983 drdzeta(0, 0) = -Geom_data_pt[0]->value(0) * sin(zeta[0]);
984 drdzeta(0, 1) = Geom_data_pt[0]->value(1) * cos(zeta[0]);
985 }
986
987
988 /// 2nd derivative of position Vector w.r.t. to coordinates:
989 /// \f$ \frac{d^2R_i}{d \zeta_\alpha d \zeta_\beta}\f$ =
990 /// ddrdzeta(alpha,beta,i).
991 /// Evaluated at current time.
994 {
995 // Components of the derivative of the tangent Vector
996 ddrdzeta(0, 0, 0) = -Geom_data_pt[0]->value(0) * cos(zeta[0]);
997 ddrdzeta(0, 0, 1) = -Geom_data_pt[0]->value(1) * sin(zeta[0]);
998 }
999
1000 /// Position Vector and 1st and 2nd derivs to coordinates:
1001 /// \f$ \frac{dR_i}{d \zeta_\alpha}\f$ = drdzeta(alpha,i).
1002 /// \f$ \frac{d^2R_i}{d \zeta_\alpha d \zeta_\beta}\f$ =
1003 /// ddrdzeta(alpha,beta,i).
1004 /// Evaluated at current time.
1009 {
1010 double a = Geom_data_pt[0]->value(0);
1011 double b = Geom_data_pt[0]->value(1);
1012 // Position Vector
1013 r[0] = a * cos(zeta[0]);
1014 r[1] = b * sin(zeta[0]);
1015
1016 // Components of the single tangent Vector
1017 drdzeta(0, 0) = -a * sin(zeta[0]);
1018 drdzeta(0, 1) = b * cos(zeta[0]);
1019
1020 // Components of the derivative of the tangent Vector
1021 ddrdzeta(0, 0, 0) = -a * cos(zeta[0]);
1022 ddrdzeta(0, 0, 1) = -b * sin(zeta[0]);
1023 }
1024
1025
1026 /// How many items of Data does the shape of the object depend on?
1027 unsigned ngeom_data() const
1028 {
1029 return Geom_data_pt.size();
1030 }
1031
1032 /// Return pointer to the j-th Data item that the object's
1033 /// shape depends on
1034 Data* geom_data_pt(const unsigned& j)
1035 {
1036 return Geom_data_pt[j];
1037 }
1038
1039 private:
1040 /// Vector of pointers to Data items that affects the object's shape
1042
1043 /// Do I need to clean up?
1045 };
1046
1047
1048 ///////////////////////////////////////////////////////////////////////
1049 ///////////////////////////////////////////////////////////////////////
1050 // Circle as geometric object
1051 ///////////////////////////////////////////////////////////////////////
1052 ///////////////////////////////////////////////////////////////////////
1053
1054
1055 //=========================================================================
1056 /// Circle in 2D space.
1057 /// \f[ x = X_c + R \cos(\zeta) \f]
1058 /// \f[ y = Y_c + R \sin(\zeta) \f]
1059 //=========================================================================
1060 class Circle : public GeomObject
1061 {
1062 public:
1063 /// Constructor: Pass x and y-coords of centre and radius (all pinned)
1064 Circle(const double& x_c, const double& y_c, const double& r)
1065 : GeomObject(1, 2)
1066 {
1067 // Create Data:
1068 Geom_data_pt.resize(1);
1069 Geom_data_pt[0] = new Data(3);
1070
1071 // No time-dependence
1072 Is_time_dependent = false;
1073
1074 // Assign data: X_c; no timedependence, free by default
1075
1076 // Pin the data
1077 Geom_data_pt[0]->pin(0);
1078 // Give it a value:
1079 Geom_data_pt[0]->set_value(0, x_c);
1080
1081 // Assign data: Y_c; no timedependence, free by default
1082
1083 // Pin the data
1084 Geom_data_pt[0]->pin(1);
1085 // Give it a value:
1086 Geom_data_pt[0]->set_value(1, y_c);
1087
1088 // Assign data: R; no timedependence, free by default
1089
1090 // Pin the data
1091 Geom_data_pt[0]->pin(2);
1092 // Give it a value:
1093 Geom_data_pt[0]->set_value(2, r);
1094
1095 // I've created the data, I need to clean up
1096 Must_clean_up = true;
1097 }
1098
1099
1100 /// Constructor: Pass x and y-coords of centre and radius (all
1101 /// pinned) Circle is static but can be used in time-dependent runs with
1102 /// specified timestepper.
1103 Circle(const double& x_c,
1104 const double& y_c,
1105 const double& r,
1108 {
1109 // Create Data:
1110 Geom_data_pt.resize(1);
1111 Geom_data_pt[0] = new Data(time_stepper_pt, 3);
1112
1113 // We have time-dependence
1114 Is_time_dependent = true;
1115
1116 // Assign data: X_c; no timedependence, free by default
1117
1118 // Pin the data
1119 Geom_data_pt[0]->pin(0);
1120 // Give it a value:
1121 Geom_data_pt[0]->set_value(0, x_c);
1122
1123 // Assign data: Y_c; no timedependence, free by default
1124
1125 // Pin the data
1126 Geom_data_pt[0]->pin(1);
1127 // Give it a value:
1128 Geom_data_pt[0]->set_value(1, y_c);
1129
1130 // Assign data: R; no timedependence, free by default
1131
1132 // Pin the data
1133 Geom_data_pt[0]->pin(2);
1134 // Give it a value:
1135 Geom_data_pt[0]->set_value(2, r);
1136
1137 // "Impulsive" start because there isn't any time-dependence
1139
1140 // I've created the data, I need to clean up
1141 Must_clean_up = true;
1142 }
1143
1144
1145 /// Constructor: Pass x and y-coords of centre and radius
1146 /// (all as Data)
1147 /// \code
1148 /// Geom_data_pt[0]->value(0) = X_c;
1149 /// Geom_data_pt[0]->value(1) = Y_c;
1150 /// Geom_data_pt[0]->value(2) = R;
1151 /// \endcode
1153 {
1154#ifdef PARANOID
1155 if (geom_data_pt.size() != 1)
1156 {
1157 std::ostringstream error_message;
1158 error_message << "geom_data_pt should have size 1, not "
1159 << geom_data_pt.size() << std::endl;
1160
1161 if (geom_data_pt[0]->nvalue() != 3)
1162 {
1163 error_message << "geom_data_pt[0] should have 3 values, not "
1164 << geom_data_pt[0]->nvalue() << std::endl;
1165 }
1166
1167 throw OomphLibError(error_message.str(),
1170 }
1171#endif
1172
1173 // We have time-dependence
1174 if (geom_data_pt[0]->time_stepper_pt()->nprev_values() > 0)
1175 {
1176 Is_time_dependent = true;
1177 }
1178 else
1179 {
1180 Is_time_dependent = false;
1181 }
1182
1183 Geom_data_pt.resize(1);
1184 Geom_data_pt[0] = geom_data_pt[0];
1185
1186 // Data has been created externally: Must not clean up
1187 Must_clean_up = false;
1188 }
1189
1190 /// Broken copy constructor
1191 Circle(const Circle& dummy) = delete;
1192
1193 /// Broken assignment operator
1194 void operator=(const Circle&) = delete;
1195
1196 /// Destructor: Clean up if necessary
1197 virtual ~Circle()
1198 {
1199 // Do I need to clean up?
1200 if (Must_clean_up)
1201 {
1202 unsigned ngeom_data = Geom_data_pt.size();
1203 for (unsigned i = 0; i < ngeom_data; i++)
1204 {
1205 delete Geom_data_pt[i];
1206 Geom_data_pt[i] = 0;
1207 }
1208 }
1209 }
1210
1211 /// Position Vector at Lagrangian coordinate zeta
1213 {
1214 // Extract data
1215 double X_c = Geom_data_pt[0]->value(0);
1216 double Y_c = Geom_data_pt[0]->value(1);
1217 double R = Geom_data_pt[0]->value(2);
1218
1219 // Position Vector
1220 r[0] = X_c + R * cos(zeta[0]);
1221 r[1] = Y_c + R * sin(zeta[0]);
1222 }
1223
1224
1225 /// Parametrised position on object: r(zeta). Evaluated at
1226 /// previous timestep. t=0: current time; t>0: previous
1227 /// timestep.
1228 void position(const unsigned& t,
1229 const Vector<double>& zeta,
1230 Vector<double>& r) const
1231 {
1232 // Genuine time-dependence?
1233 if (!Is_time_dependent)
1234 {
1235 position(zeta, r);
1236 }
1237 else
1238 {
1239#ifdef PARANOID
1240 if (t > Geom_data_pt[0]->time_stepper_pt()->nprev_values())
1241 {
1242 std::ostringstream error_message;
1243 error_message << "t > nprev_values() " << t << " "
1245 << std::endl;
1246
1247 throw OomphLibError(error_message.str(),
1250 }
1251#endif
1252
1253 // Extract data
1254 double X_c = Geom_data_pt[0]->value(t, 0);
1255 double Y_c = Geom_data_pt[0]->value(t, 1);
1256 double R = Geom_data_pt[0]->value(t, 2);
1257
1258 // Position Vector
1259 r[0] = X_c + R * cos(zeta[0]);
1260 r[1] = Y_c + R * sin(zeta[0]);
1261 }
1262 }
1263
1264 /// Access function to x-coordinate of centre of circle
1265 double& x_c()
1266 {
1267 return *Geom_data_pt[0]->value_pt(0);
1268 }
1269
1270 /// Access function to y-coordinate of centre of circle
1271 double& y_c()
1272 {
1273 return *Geom_data_pt[0]->value_pt(1);
1274 }
1275
1276 /// Access function to radius of circle
1277 double& R()
1278 {
1279 return *Geom_data_pt[0]->value_pt(2);
1280 }
1281
1282 /// How many items of Data does the shape of the object depend on?
1283 unsigned ngeom_data() const
1284 {
1285 return Geom_data_pt.size();
1286 }
1287
1288 /// Return pointer to the j-th Data item that the object's
1289 /// shape depends on
1290 Data* geom_data_pt(const unsigned& j)
1291 {
1292 return Geom_data_pt[j];
1293 }
1294
1295 protected:
1296 /// Vector of pointers to Data items that affects the object's shape
1298
1299 /// Do I need to clean up?
1301
1302 /// Genuine time-dependence?
1304 };
1305
1306
1307 ///////////////////////////////////////////////////////////////////////
1308 ///////////////////////////////////////////////////////////////////////
1309 ///////////////////////////////////////////////////////////////////////
1310
1311
1312 //===========================================================
1313 /// Elliptical tube with half axes a and b.
1314 ///
1315 /// \f[ {\bf r} = ( a \cos(\zeta_1), b \sin(zeta_1), \zeta_0)^T \f]
1316 ///
1317 //===========================================================
1319 {
1320 public:
1321 /// Constructor: Specify radius
1322 EllipticalTube(const double& a, const double& b)
1323 : GeomObject(2, 3), A(a), B(b)
1324 {
1325 }
1326
1327 /// Broken copy constructor
1329
1330 /// Broken assignment operator
1331 void operator=(const EllipticalTube&) = delete;
1332
1333 /// Access function to x-half axis
1334 double& a()
1335 {
1336 return A;
1337 }
1338
1339 /// Access function to y-half axis
1340 double& b()
1341 {
1342 return B;
1343 }
1344
1345 /// Position vector
1347 {
1348 r[0] = A * cos(zeta[1]);
1349 r[1] = B * sin(zeta[1]);
1350 r[2] = zeta[0];
1351 }
1352
1353
1354 /// Position vector (dummy unsteady version returns steady version)
1355 void position(const unsigned& t,
1356 const Vector<double>& zeta,
1357 Vector<double>& r) const
1358 {
1359 position(zeta, r);
1360 }
1361
1362 /// How many items of Data does the shape of the object depend on?
1363 virtual unsigned ngeom_data() const
1364 {
1365 return 0;
1366 }
1367
1368 /// Position Vector and 1st and 2nd derivs w.r.t. zeta.
1371 {
1372 ddrdzeta(0, 0, 0) = 0.0;
1373 ddrdzeta(0, 0, 1) = 0.0;
1374 ddrdzeta(0, 0, 2) = 0.0;
1375
1376 ddrdzeta(1, 1, 0) = -A * cos(zeta[1]);
1377 ddrdzeta(1, 1, 1) = -B * sin(zeta[1]);
1378 ddrdzeta(1, 1, 2) = 0.0;
1379
1380 ddrdzeta(0, 1, 0) = ddrdzeta(1, 0, 0) = 0.0;
1381 ddrdzeta(0, 1, 1) = ddrdzeta(1, 0, 1) = 0.0;
1382 ddrdzeta(0, 1, 2) = ddrdzeta(1, 0, 2) = 0.0;
1383 }
1384
1385 /// Position Vector and 1st and 2nd derivs w.r.t. zeta.
1390 {
1391 // Let's just do a simple tube
1392 r[0] = A * cos(zeta[1]);
1393 r[1] = B * sin(zeta[1]);
1394 r[2] = zeta[0];
1395
1396 // Do the azetaal derivatives
1397 drdzeta(0, 0) = 0.0;
1398 drdzeta(0, 1) = 0.0;
1399 drdzeta(0, 2) = 1.0;
1400
1401 // Do the azimuthal derivatives
1402 drdzeta(1, 0) = -A * sin(zeta[1]);
1403 drdzeta(1, 1) = B * cos(zeta[1]);
1404 drdzeta(1, 2) = 0.0;
1405
1406 // Now let's do the second derivatives
1407 ddrdzeta(0, 0, 0) = 0.0;
1408 ddrdzeta(0, 0, 1) = 0.0;
1409 ddrdzeta(0, 0, 2) = 0.0;
1410
1411 ddrdzeta(1, 1, 0) = -A * cos(zeta[1]);
1412 ddrdzeta(1, 1, 1) = -B * sin(zeta[1]);
1413 ddrdzeta(1, 1, 2) = 0.0;
1414
1415 // Mixed derivatives
1416 ddrdzeta(0, 1, 0) = ddrdzeta(1, 0, 0) = 0.0;
1417 ddrdzeta(0, 1, 1) = ddrdzeta(1, 0, 1) = 0.0;
1418 ddrdzeta(0, 1, 2) = ddrdzeta(1, 0, 2) = 0.0;
1419 }
1420
1421 private:
1422 /// x-half axis
1423 double A;
1424
1425 /// x-half axis
1426 double B;
1427 };
1428
1429
1430} // namespace oomph
1431
1432#endif
static char t char * s
Definition cfortran.h:568
cstr elem_len * i
Definition cfortran.h:603
char t
Definition cfortran.h:568
Circle in 2D space.
double & x_c()
Access function to x-coordinate of centre of circle.
double & y_c()
Access function to y-coordinate of centre of circle.
void operator=(const Circle &)=delete
Broken assignment operator.
Circle(const Circle &dummy)=delete
Broken copy constructor.
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...
Circle(const double &x_c, const double &y_c, const double &r, TimeStepper *time_stepper_pt)
Constructor: Pass x and y-coords of centre and radius (all pinned) Circle is static but can be used i...
virtual ~Circle()
Destructor: Clean up if necessary.
Vector< Data * > Geom_data_pt
Vector of pointers to Data items that affects the object's shape.
unsigned ngeom_data() const
How many items of Data does the shape of the object depend on?
bool Must_clean_up
Do I need to clean up?
bool Is_time_dependent
Genuine time-dependence?
void position(const Vector< double > &zeta, Vector< double > &r) const
Position Vector at Lagrangian coordinate zeta.
Circle(const Vector< Data * > &geom_data_pt)
Constructor: Pass x and y-coords of centre and radius (all as Data)
Circle(const double &x_c, const double &y_c, const double &r)
Constructor: Pass x and y-coords of centre and radius (all pinned)
Data * geom_data_pt(const unsigned &j)
Return pointer to the j-th Data item that the object's shape depends on.
double & R()
Access function to radius of circle.
A class that represents a collection of data; each Data object may contain many different individual ...
Definition nodes.h:86
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition nodes.h:483
Steady ellipse with half axes A and B as geometric object:
void d2position(const Vector< double > &zeta, RankThreeTensor< double > &ddrdzeta) const
2nd derivative of position Vector w.r.t. to coordinates: = ddrdzeta(alpha,beta,i)....
Ellipse(const double &A, const double &B)
Constructor: 1 Lagrangian coordinate, 2 Eulerian coords. Pass half axes A and B; both pinned.
Ellipse(const Vector< Data * > &geom_data_pt)
Constructor: 1 Lagrangian coordinate, 2 Eulerian coords. Pass half axes as Data:
void d2position(const Vector< double > &zeta, Vector< double > &r, DenseMatrix< double > &drdzeta, RankThreeTensor< double > &ddrdzeta) const
Position Vector and 1st and 2nd derivs to coordinates: = drdzeta(alpha,i). = ddrdzeta(alpha,...
void operator=(const Ellipse &)=delete
Broken assignment operator.
void set_A_ellips(const double &a)
Set horizontal half axis.
Ellipse(const Ellipse &dummy)=delete
Broken copy constructor.
unsigned ngeom_data() const
How many items of Data does the shape of the object depend on?
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...
void set_B_ellips(const double &b)
Set vertical half axis.
double b_ellips()
Access function for vertical half axis.
void position(const Vector< double > &zeta, Vector< double > &r) const
Position Vector at Lagrangian coordinate zeta.
Data * geom_data_pt(const unsigned &j)
Return pointer to the j-th Data item that the object's shape depends on.
~Ellipse()
Destructor: Clean up if necessary.
bool Must_clean_up
Do I need to clean up?
double a_ellips()
Access function for horizontal half axis.
Vector< Data * > Geom_data_pt
Vector of pointers to Data items that affects the object's shape.
void dposition(const Vector< double > &zeta, DenseMatrix< double > &drdzeta) const
Derivative of position Vector w.r.t. to coordinates: = drdzeta(alpha,i).
Elliptical tube with half axes a and b.
void position(const unsigned &t, const Vector< double > &zeta, Vector< double > &r) const
Position vector (dummy unsteady version returns steady version)
double B
x-half axis
EllipticalTube(const EllipticalTube &node)=delete
Broken copy constructor.
void operator=(const EllipticalTube &)=delete
Broken assignment operator.
void d2position(const Vector< double > &zeta, Vector< double > &r, DenseMatrix< double > &drdzeta, RankThreeTensor< double > &ddrdzeta) const
Position Vector and 1st and 2nd derivs w.r.t. zeta.
EllipticalTube(const double &a, const double &b)
Constructor: Specify radius.
double A
x-half axis
void d2position(const Vector< double > &zeta, RankThreeTensor< double > &ddrdzeta) const
Position Vector and 1st and 2nd derivs w.r.t. zeta.
double & a()
Access function to x-half axis.
virtual unsigned ngeom_data() const
How many items of Data does the shape of the object depend on?
double & b()
Access function to y-half axis.
void position(const Vector< double > &zeta, Vector< double > &r) const
Position vector.
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 d2position(const Vector< double > &zeta, RankThreeTensor< double > &ddrdzeta) const
2nd derivative of position Vector w.r.t. to coordinates: = ddrdzeta(alpha,beta,i)....
virtual void position(const Vector< double > &zeta, Vector< double > &r) const =0
Parametrised position on object at current time: r(zeta).
TimeStepper *& time_stepper_pt()
Access function for pointer to time stepper: Null if object is not time-dependent.
unsigned NLagrangian
Number of Lagrangian (intrinsic) coordinates.
double first_derivative_fd_step() const
Return a const reference to the FD step size for the first derivative, providing read-only access.
TimeStepper * Geom_object_time_stepper_pt
Timestepper (used to handle access to geometry at previous timesteps)
virtual unsigned ngeom_data() const
How many items of Data does the shape of the object depend on? This is implemented as a broken virtua...
virtual void interpolated_zeta(const Vector< double > &s, Vector< double > &zeta) const
A geometric object may be composed of many sub-objects each with their own local coordinate....
double & second_derivative_fd_step()
Return a non-const reference to the FD step size for the second derivative, allowing modification of ...
void set_nlagrangian_and_ndim(const unsigned &n_lagrangian, const unsigned &n_dim)
Set # of Lagrangian and Eulerian coordinates.
virtual void d2position(const Vector< double > &zeta, Vector< double > &r, DenseMatrix< double > &drdzeta, RankThreeTensor< double > &ddrdzeta) const
Posn Vector and its 1st & 2nd derivatives w.r.t. to coordinates: = drdzeta(alpha,...
virtual Data * geom_data_pt(const unsigned &j)
Return pointer to the j-th Data item that the object's shape depends on. This is implemented as a bro...
void operator=(const GeomObject &)=delete
Broken assignment operator.
GeomObject(const unsigned &ndim)
Constructor: Pass dimension of geometric object (# of Eulerian coords = # of Lagrangian coords; no ti...
double Second_derivative_dzeta
FD step for second derivatives (central difference). The step size is chosen to balance truncation er...
unsigned Ndim
Number of Eulerian coordinates.
double & first_derivative_fd_step()
Return a non-const reference to the FD step size for the first derivative, allowing modification of t...
GeomObject(const unsigned &nlagrangian, const unsigned &ndim, TimeStepper *time_stepper_pt)
Constructor: pass # of Eulerian and Lagrangian coordinates and pointer to time-stepper which is used ...
virtual void locate_zeta(const Vector< double > &zeta, GeomObject *&sub_geom_object_pt, Vector< double > &s, const bool &use_coordinate_as_initial_guess=false)
A geometric object may be composed of may sub-objects (e.g. a finite-element representation of a boun...
TimeStepper * time_stepper_pt() const
Access function for pointer to time stepper: Null if object is not time-dependent....
double First_derivative_dzeta
FD step for first derivatives. For a forward difference approximation, the optimal scaling follows h ...
virtual void dposition(const Vector< double > &zeta, DenseMatrix< double > &drdzeta) const
Derivative of position Vector w.r.t. to coordinates: = drdzeta(alpha,i). Evaluated at current time....
virtual void dposition_dt(const Vector< double > &zeta, const unsigned &j, Vector< double > &drdt)
j-th time-derivative on object at current time: .
virtual ~GeomObject()
(Empty) destructor
double second_derivative_fd_step() const
Return a const reference to the FD step size for the second derivative, providing read-only access.
virtual 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...
GeomObject(const unsigned &nlagrangian, const unsigned &ndim)
Constructor: pass # of Eulerian and Lagrangian coordinates. No time history available/needed.
unsigned nlagrangian() const
Access function to # of Lagrangian coordinates.
virtual void position(const double &t, const Vector< double > &zeta, Vector< double > &r) const
Parametrised position on object: r(zeta). Evaluated at the continuous time value, t.
GeomObject(const GeomObject &dummy)=delete
Broken copy constructor.
GeomObject()
Default constructor.
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....
Steady, straight 1D line in 2D space.
Data * geom_data_pt(const unsigned &j)
Return pointer to the j-th Data item that the object's shape depends on.
virtual void dposition(const Vector< double > &zeta, DenseMatrix< double > &drdzeta) const
Derivative of position Vector w.r.t. to coordinates: = drdzeta(alpha,i). Evaluated at current time.
StraightLine(const StraightLine &dummy)=delete
Broken copy constructor.
StraightLine(const Vector< Data * > &geom_data_pt)
Constructor: One item of geometric data:
~StraightLine()
Destructor: Clean up if necessary.
Vector< Data * > Geom_data_pt
Vector of pointers to Data items that affects the object's shape.
StraightLine(const double &height)
Constructor: Pass height (pinned by default)
bool Must_clean_up
Do I need to clean up?
void position(const Vector< double > &zeta, Vector< double > &r) const
Position Vector at Lagrangian coordinate zeta.
virtual void d2position(const Vector< double > &zeta, Vector< double > &r, DenseMatrix< double > &drdzeta, RankThreeTensor< double > &ddrdzeta) const
Posn Vector and its 1st & 2nd derivatives w.r.t. to coordinates: = drdzeta(alpha,...
unsigned ngeom_data() const
How many items of Data does the shape of the object depend on?
virtual void d2position(const Vector< double > &zeta, RankThreeTensor< double > &ddrdzeta) const
2nd derivative of position Vector w.r.t. to coordinates: = ddrdzeta(alpha,beta,i)....
void operator=(const StraightLine &)=delete
Broken assignment operator.
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...
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
virtual unsigned nprev_values() const =0
Number of previous values available: 0 for static, 1 for BDF<1>,...
virtual void assign_initial_values_impulsive(Data *const &data_pt)=0
Initialise the time-history for the Data values corresponding to an impulsive start.
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).