shape.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// This header file includes generic shape function classes
27
28// Include guards to prevent multiple inclusions of the file
29#ifndef OOMPH_SHAPE_HEADER
30#define OOMPH_SHAPE_HEADER
31
32
33// Config header
34#ifdef HAVE_CONFIG_H
35#include <oomph-lib-config.h>
36#endif
37
38#ifdef OOMPH_HAS_MPI
39#include "mpi.h"
40#endif
41
42
43// oomph-lib includes
44#include "Vector.h"
45#include "matrices.h"
46#include "orthpoly.h"
47
48namespace oomph
49{
50 //========================================================================
51 /// A Class for shape functions. In simple cases, the shape functions
52 /// have only one index that can be thought of as corresponding to the
53 /// nodal points. In general, however, when quantities and
54 /// their gradients are interpolated separately, the shape function have
55 /// two indices: one corresponding to the nodal points, and the other
56 /// to the "type" of quantity being interpolated: function, derivative, &c
57 /// The second index can also represent the vector coordinate for
58 /// vector-valued (Nedelec) shape functions.
59 ///
60 /// The implementation of Shape functions is designed to permit fast
61 /// copying of entire sets of values by resetting the internal pointer
62 /// to the data, Psi;
63 /// functionality that is required, for example,
64 /// when setting the test functions
65 /// in Galerkin elements and when reading pre-computed values of the shape
66 /// functions.
67 /// In general, we cannot know at construction time whether the pointer to
68 /// the values will be reset or not and, therefore,
69 /// whether the storage for values should be allocated by the object.
70 /// We choose to allocate storage on construction and store an
71 /// additional pointer Allocated_data that \b always addresses the storage
72 /// allocated by the object. If the Psi pointer is reset then this storage
73 /// will be "wasted", but only for the lifetime of the object. The cost for
74 /// non-copied Shape functions is one additional pointer.
75 //=========================================================================
76 class Shape
77 {
78 protected:
79 /// Pointer that addresses the storage that will be used to read and
80 /// set the shape functions. The shape functions are packed into
81 /// a flat array of doubles.
82 double* Psi;
83
84 /// Pointer that addresses the storage allocated by the object on
85 /// construction. This will be the same as Psi if the object is not
86 /// copied.
88
89 /// Size of the first index of the shape function
90 unsigned Index1;
91
92 /// Size of the second index of the shape function
93 unsigned Index2;
94
95 /// Boolean to indicate whether the data has been copied
97
98 /// Boolean to indicate whether the data is a copy
100
101 /// Private function that checks whether the index is in range
102 void range_check(const unsigned& i, const unsigned& j) const
103 {
104 // If an index is out of range, throw an error
105 if ((i >= Index1) || (j >= Index2))
106 {
107 std::ostringstream error_stream;
108 error_stream << "Range Error: ";
109 if (i >= Index1)
110 {
111 error_stream << i << " is not in the range (0," << Index1 - 1 << ")"
112 << std::endl;
113 }
114 if (j >= Index2)
115 {
116 error_stream << j << " is not in the range (0," << Index2 - 1 << ")"
117 << std::endl;
118 }
119 throw OomphLibError(
121 }
122 }
123
124 public:
125 /// Constructor for a single-index set of shape functions.
126 Shape(const unsigned& N)
128 {
129 Allocated_storage = new double[N];
131 }
132
133 /// Constructor for a two-index set of shape functions.
134 Shape(const unsigned& N, const unsigned& M)
136 {
137 Allocated_storage = new double[N * M];
139 }
140
141 /// Broken copy constructor
142 Shape(const Shape& shape) = delete;
143
144 /// Default constructor - just assigns a null pointers and zero index
145 /// sizes.
147 : Psi(0),
149 Index1(0),
150 Index2(0),
153 {
154 }
155
156 /// Assignment operator, shallow copy (not recommended so warning given)
157 void operator=(Shape& shape)
158 {
160 {
161 std::ostringstream warning_stream;
162 warning_stream << "The assignment operator, =, makes a shallow copy."
163 << std::endl
164 << "This can have unexpected consequences, so we"
165 << std::endl
166 << "now recommend using the explicitly named function "
167 << std::endl
168 << "Shape::shallow_copy_from(.)." << std::endl
169 << "If you want to suppress" << std::endl
170 << "this warning then set the static boolean:"
171 << std::endl
172 << "Shape::Suppress_warning_about_assignment"
173 << std::endl
174 << " to true." << std::endl;
175
179 }
180
181 this->shallow_copy_from(shape);
182 }
183
184 /// Assignment operator, shallow copy (not recommended so warning given)
186 {
188 {
189 std::ostringstream warning_stream;
190 warning_stream << "The assignment operator, =, makes a shallow copy."
191 << std::endl
192 << "This can have unexpected consequences, so we"
193 << std::endl
194 << "now recommend using the explicitly named function "
195 << std::endl
196 << "Shape::shallow_copy_from(.)." << std::endl
197 << "If you want to suppress" << std::endl
198 << "this warning then set the static boolean:"
199 << std::endl
200 << "Shape::Suppress_warning_about_assignment"
201 << std::endl
202 << " to true." << std::endl;
203
207 }
208
209 this->shallow_copy_from(shape_pt);
210 }
211
212 /// This function makes a shallow copy
213 /// (sets the pointer to the allocated data to be from another Shape object)
215 {
216 // Sets the indices of this object to be consistent with that
217 // being copied
218 Index1 = shape.nindex1();
219 Index2 = shape.nindex2();
220 // Set the pointer to the data to be that from the copied object
221 Psi = shape.Psi;
222 // Indicate that data has been copied
223 shape.Is_psi_copied = true;
224 Is_psi_a_copy = true;
225 // Delete own storage??
226 }
227
228
229 /// This function make a shallow copy
230 /// (sets the pointer to the allocated data to be from another Shape object)
232 {
233 // Sets the indices of this object to be consistent with that
234 // being copied
235 Index1 = shape_pt->nindex1();
236 Index2 = shape_pt->nindex2();
237 // Set pointer
238 Psi = shape_pt->Psi;
239 // Indicate that data has been copied
240 shape_pt->Is_psi_copied = true;
241 Is_psi_a_copy = true;
242 }
243
244 /// Destructor, clear up the memory allocated by the object
246 {
247 delete[] Allocated_storage;
249 }
250
251 private:
252 /// Change the size of the storage
253 void resize(const unsigned& N, const unsigned& M = 1)
254 {
255#ifdef PARANOID
256 // If the storage is copied, do not allow a resize
257 if (Is_psi_copied)
258 {
259 std::ostringstream error_stream;
260 error_stream << "Cannot resize an object whose storage has been copied."
261 << std::endl
262 << "This could lead to a dangling pointer in the copy."
263 << std::endl;
264 throw OomphLibError(
266 }
267#endif
268 // Clear old storage
269 delete[] Allocated_storage;
271 Psi = 0;
272
273 // Allocate new storage
274 Index1 = N;
275 Index2 = M;
276 Allocated_storage = new double[N * M];
278 }
279
280 public:
281 /// Overload the bracket operator to provide access to values.
282 inline double& operator[](const unsigned& i)
283 {
284#ifdef RANGE_CHECKING
285 range_check(i, 0);
286#endif
287 return Psi[i * Index2];
288 }
289
290 /// Overload the bracket operator (const version)
291 inline const double& operator[](const unsigned& i) const
292 {
293#ifdef RANGE_CHECKING
294 range_check(i, 0);
295#endif
296 return Psi[i * Index2];
297 }
298
299 /// Overload the round bracket operator to provide access to values.
300 inline double& operator()(const unsigned& i)
301 {
302#ifdef RANGE_CHECKING
303 range_check(i, 0);
304#endif
305 return Psi[i * Index2];
306 }
307
308 /// Overload the round bracket operator (const version)
309 inline const double& operator()(const unsigned& i) const
310 {
311#ifdef RANGE_CHECKING
312 range_check(i, 0);
313#endif
314 return Psi[i * Index2];
315 }
316
317 /// Overload the round bracket operator, allowing for two indices
318 inline double& operator()(const unsigned& i, const unsigned& j)
319 {
320#ifdef RANGE_CHECKING
321 range_check(i, j);
322#endif
323 return Psi[i * Index2 + j];
324 }
325
326 /// Overload the round bracket operator, allowing for two indices
327 /// (const version)
328 inline const double& operator()(const unsigned& i, const unsigned& j) const
329 {
330#ifdef RANGE_CHECKING
331 range_check(i, j);
332#endif
333 return Psi[i * Index2 + j];
334 }
335
336 /// Return the range of index 1 of the shape function object
337 inline unsigned nindex1() const
338 {
339 return Index1;
340 }
341
342 /// Return the range of index 2 of the shape function object
343 inline unsigned nindex2() const
344 {
345 return Index2;
346 }
347
348 /// Boolean used to suppress warning about assignment operator
350 };
351
352 //================================================================
353 /// A Class for the derivatives of shape functions
354 /// The class design is essentially the same as Shape, but there is
355 /// on additional index that is used to indicate the coordinate direction in
356 /// which the derivative is taken.
357 //================================================================
358 class DShape
359 {
360 private:
361 /// Pointer that addresses the storage that will be used to read and
362 /// set the shape-function derivatives. The values are packed into
363 /// a flat array of doubles.
364 double* DPsi;
365
366 /// Pointer that addresses the storage allocated by the object on
367 /// construction. This will be the same as DPsi if the object is not
368 /// copied.
370
371 /// Size of the first index of the shape function
372 unsigned Index1;
373
374 /// Size of the second index of the shape function
375 unsigned Index2;
376
377 /// Size of the third index of the shape function
378 unsigned Index3;
379
380 /// Boolean to indicate whether the data has been copied
382
383 /// Boolean to indicate whether the data is a copy
385
386
387 /// Private function that checks whether the indices are in range
388 void range_check(const unsigned& i,
389 const unsigned& j,
390 const unsigned& k) const
391 {
392 // Check the first index
393 if ((i >= Index1) || (j >= Index2) || (k >= Index3))
394 {
395 std::ostringstream error_stream;
396 error_stream << "Range Error: ";
397 if (i >= Index1)
398 {
399 error_stream << i << " is not in the range (0," << Index1 - 1 << ")"
400 << std::endl;
401 }
402 if (j >= Index2)
403 {
404 error_stream << j << " is not in the range (0," << Index2 - 1 << ")"
405 << std::endl;
406 }
407 if (k >= Index3)
408 {
409 error_stream << k << " is not in the range (0," << Index3 - 1 << ")"
410 << std::endl;
411 }
412 throw OomphLibError(
414 }
415 }
416
417
418 public:
419 /// Constructor with two parameters: a single-index shape function
420 DShape(const unsigned& N, const unsigned& P)
421 : Index1(N),
422 Index2(1),
423 Index3(P),
426 {
427 Allocated_storage = new double[N * P];
429 }
430
431 /// Constructor with three paramters: a two-index shape function
432 DShape(const unsigned& N, const unsigned& M, const unsigned& P)
433 : Index1(N),
434 Index2(M),
435 Index3(P),
438 {
439 Allocated_storage = new double[N * M * P];
441 }
442
443 /// Default constructor - just assigns a null pointers and zero index
444 /// sizes.
446 : DPsi(0),
448 Index1(0),
449 Index2(0),
450 Index3(0),
453 {
454 }
455
456 /// Broken copy constructor
457 DShape(const DShape& dshape) = delete;
458
459 /// Assignment operator, shallow copy (not recommended so warning given)
460 void operator=(DShape& dshape)
461 {
463 {
464 std::ostringstream warning_stream;
465 warning_stream << "The assignment operator, =, makes a shallow copy."
466 << std::endl
467 << "This can have unexpected consequences, so we"
468 << std::endl
469 << "now recommend using the explicitly named function "
470 << std::endl
471 << "DShape::shallow_copy_from(.)." << std::endl
472 << "If you want to suppress" << std::endl
473 << "this warning then set the static boolean:"
474 << std::endl
475 << "DShape::Suppress_warning_about_assignment"
476 << std::endl
477 << " to true." << std::endl;
478
482 }
483
484 this->shallow_copy_from(dshape);
485 }
486
487
488 /// Assignment operator, shallow copy (not reccomended so warning given)
490 {
492 {
493 std::ostringstream warning_stream;
494 warning_stream << "The assignment operator, =, makes a shallow copy."
495 << std::endl
496 << "This can have unexpected consequences, so we"
497 << std::endl
498 << "now recommend using the explicitly named function "
499 << std::endl
500 << "DShape::shallow_copy_from(.)." << std::endl
501 << "If you want to suppress" << std::endl
502 << "this warning then set the static boolean:"
503 << std::endl
504 << "DShape::Suppress_warning_about_assignment"
505 << std::endl
506 << " to true." << std::endl;
507
511 }
512
513 this->shallow_copy_from(dshape_pt);
514 }
515
516
517 /// This function does a shallow copy
518 /// (resets the pointer to the data)
520 {
521 // Set the values of the indices from the source object
522 Index1 = dshape.nindex1();
523 Index2 = dshape.nindex2();
524 Index3 = dshape.nindex3();
525 // Copy the pointer and mark is as being a copy
526 DPsi = dshape.DPsi;
527 Is_dpsi_a_copy = true;
528 dshape.Is_dpsi_copied = true;
529 }
530
531 /// This function does a shallow copy
532 /// (resets the pointer to the data)
534 {
535 // Set values of the indices from the source object
536 Index1 = dshape_pt->nindex1();
537 Index2 = dshape_pt->nindex2();
538 Index3 = dshape_pt->nindex3();
539 // Copy pointer and mark object as being a copy
540 DPsi = dshape_pt->DPsi;
541 Is_dpsi_a_copy = true;
542 dshape_pt->Is_dpsi_copied = true;
543 }
544
545
546 /// Destructor, clean up the memory allocated by this object
548 {
549 delete[] Allocated_storage;
551 }
552
553 private:
554 /// Change the size of the storage. Note that (for some strange reason)
555 /// index2 is the "optional" index, to conform with the existing
556 /// constructor.
557 void resize(const unsigned& N, const unsigned& P, const unsigned& M = 1)
558 {
559#ifdef PARANOID
560 // If the storage is copied, do not allow a resize
561 if (Is_dpsi_copied)
562 {
563 std::ostringstream error_stream;
564 error_stream << "Cannot resize an object whose storage has been copied."
565 << std::endl
566 << "This could lead to a dangling pointer in the copy."
567 << std::endl;
568 throw OomphLibError(
570 }
571#endif
572
573 // Clear old storage
574 delete[] Allocated_storage;
576 DPsi = 0;
577
578 // Allocate new storage
579 Index1 = N;
580 Index2 = M;
581 Index3 = P;
582 Allocated_storage = new double[N * M * P];
584 }
585
586 public:
587 /// Overload the round bracket operator for access to the data
588 inline double& operator()(const unsigned& i, const unsigned& k)
589 {
590#ifdef RANGE_CHECKING
591 range_check(i, 0, k);
592#endif
593 return DPsi[i * Index2 * Index3 + k];
594 }
595
596 /// Overload the round bracket operator (const version)
597 inline const double& operator()(const unsigned& i, const unsigned& k) const
598 {
599#ifdef RANGE_CHECKING
600 range_check(i, 0, k);
601#endif
602 return DPsi[i * Index2 * Index3 + k];
603 }
604
605 /// Overload the round bracket operator, with 3 indices
606 inline double& operator()(const unsigned& i,
607 const unsigned& j,
608 const unsigned& k)
609 {
610#ifdef RANGE_CHECKING
611 range_check(i, j, k);
612#endif
613 return DPsi[(i * Index2 + j) * Index3 + k];
614 }
615
616 /// Overload the round bracket operator (const version)
617 inline const double& operator()(const unsigned& i,
618 const unsigned& j,
619 const unsigned& k) const
620 {
621#ifdef RANGE_CHECKING
622 range_check(i, j, k);
623#endif
624 return DPsi[(i * Index2 + j) * Index3 + k];
625 }
626
627 /// Direct access to internal storage of data in flat-packed C-style
628 /// column-major format. WARNING: Only for experienced users. Only
629 /// use this if raw speed is of the essence, as in the solid mechanics
630 /// problems.
631 inline double& raw_direct_access(const unsigned long& i)
632 {
633 return DPsi[i];
634 }
635
636 /// Direct access to internal storage of data in flat-packed C-style
637 /// column-major format. WARNING: Only for experienced users. Only
638 /// use this if raw speed is of the essence, as in the solid mechanics
639 /// problems.
640 inline const double& raw_direct_access(const unsigned long& i) const
641 {
642 return DPsi[i];
643 }
644
645 /// Caculate the offset in flat-packed C-style, column-major format,
646 /// required for a given i,j. WARNING: Only for experienced users. Only
647 /// use this if raw speed is of the essence, as in the solid mechanics
648 /// problems.
649 unsigned offset(const unsigned long& i, const unsigned long& j) const
650 {
651 return (i * Index2 + j) * Index3 + 0;
652 }
653
654
655 /// Return the range of index 1 of the derivatives of the shape functions
656 inline unsigned long nindex1() const
657 {
658 return Index1;
659 }
660
661 /// Return the range of index 2 of the derivatives of the shape functions
662 inline unsigned long nindex2() const
663 {
664 return Index2;
665 }
666
667 /// Return the range of index 3 of the derivatives of the shape functions
668 inline unsigned long nindex3() const
669 {
670 return Index3;
671 }
672
673 /// Boolean used to suppress warning about assignment operator
675 };
676
677 ////////////////////////////////////////////////////////////////////
678 //
679 // One dimensional shape functions and derivatives.
680 // empty -- simply establishes the template parameters.
681 //
682 ////////////////////////////////////////////////////////////////////
683
684 namespace OneDimLagrange
685 {
686 /// Definition for 1D Lagrange shape functions. The
687 /// value of all the shape functions at the local coordinate s
688 /// are returned in the array Psi.
689 template<unsigned NNODE_1D>
690 void shape(const double& s, double* Psi)
691 {
692 std::ostringstream error_stream;
693 error_stream << "One dimensional Lagrange shape functions "
694 << "have not been defined "
695 << "for " << NNODE_1D << " nodes." << std::endl;
696 throw OomphLibError(
698 }
699
700 /// Definition for derivatives of 1D Lagrange shape functions. The
701 /// value of all the shape function derivatives at the local coordinate s
702 /// are returned in the array DPsi.
703 template<unsigned NNODE_1D>
704 void dshape(const double& s, double* DPsi)
705 {
706 std::ostringstream error_stream;
707 error_stream << "One dimensional Lagrange shape function derivatives "
708 << "have not been defined "
709 << "for " << NNODE_1D << " nodes." << std::endl;
710 throw OomphLibError(
712 }
713
714 /// Definition for second derivatives of
715 /// 1D Lagrange shape functions. The
716 /// value of all the shape function derivatives at the local coordinate s
717 /// are returned in the array DPsi.
718 template<unsigned NNODE_1D>
719 void d2shape(const double& s, double* DPsi)
720 {
721 std::ostringstream error_stream;
722 error_stream << "One dimensional Lagrange shape function "
723 << "second derivatives "
724 << "have not been defined "
725 << "for " << NNODE_1D << " nodes." << std::endl;
726 throw OomphLibError(
728 }
729
730 /// 1D shape functions specialised to linear order (2 Nodes)
731 // Note that the numbering is such that shape[0] is at s = -1.0.
732 // and shape[1] is at s = 1.0
733 template<>
734 inline void shape<2>(const double& s, double* Psi)
735 {
736 Psi[0] = 0.5 * (1.0 - s);
737 Psi[1] = 0.5 * (1.0 + s);
738 }
739
740 /// Derivatives of 1D shape functions specialised to linear order (2 Nodes)
741 template<>
742 inline void dshape<2>(const double& s, double* DPsi)
743 {
744 DPsi[0] = -0.5;
745 DPsi[1] = 0.5;
746 }
747
748 /// Second Derivatives of 1D shape functions,
749 /// specialised to linear order (2 Nodes)
750 template<>
751 inline void d2shape<2>(const double& s, double* DPsi)
752 {
753 DPsi[0] = 0.0;
754 DPsi[1] = 0.0;
755 }
756
757 /// 1D shape functions specialised to quadratic order (3 Nodes)
758 // Note that the numbering is such that shape[0] is at s = -1.0,
759 // shape[1] is at s = 0.0 and shape[2] is at s = 1.0.
760 template<>
761 inline void shape<3>(const double& s, double* Psi)
762 {
763 Psi[0] = 0.5 * s * (s - 1.0);
764 Psi[1] = 1.0 - s * s;
765 Psi[2] = 0.5 * s * (s + 1.0);
766 }
767
768 /// Derivatives of 1D shape functions specialised to quadratic order (3
769 /// Nodes)
770 template<>
771 inline void dshape<3>(const double& s, double* DPsi)
772 {
773 DPsi[0] = s - 0.5;
774 DPsi[1] = -2.0 * s;
775 DPsi[2] = s + 0.5;
776 }
777
778
779 /// Second Derivatives of 1D shape functions, specialised to quadratic order
780 /// (3 Nodes)
781 template<>
782 inline void d2shape<3>(const double& s, double* DPsi)
783 {
784 DPsi[0] = 1.0;
785 DPsi[1] = -2.0;
786 DPsi[2] = 1.0;
787 }
788
789 /// 1D shape functions specialised to cubic order (4 Nodes)
790 template<>
791 inline void shape<4>(const double& s, double* Psi)
792 {
793 // Output from Maple
794 double t1 = s * s;
795 double t2 = t1 * s;
796 double t3 = 0.5625 * t2;
797 double t4 = 0.5625 * t1;
798 double t5 = 0.625E-1 * s;
799 double t7 = 0.16875E1 * t2;
800 double t8 = 0.16875E1 * s;
801 Psi[0] = -t3 + t4 + t5 - 0.625E-1;
802 Psi[1] = t7 - t4 - t8 + 0.5625;
803 Psi[2] = -t7 - t4 + t8 + 0.5625;
804 Psi[3] = t3 + t4 - t5 - 0.625E-1;
805 }
806
807
808 /// Derivatives of 1D shape functions specialised to cubic order (4 Nodes)
809 template<>
810 inline void dshape<4>(const double& s, double* DPsi)
811 {
812 // Output from Maple
813 double t1 = s * s;
814 double t2 = 0.16875E1 * t1;
815 double t3 = 0.1125E1 * s;
816 double t5 = 0.50625E1 * t1;
817 DPsi[0] = -t2 + t3 + 0.625E-1;
818 DPsi[1] = t5 - t3 - 0.16875E1;
819 DPsi[2] = -t5 - t3 + 0.16875E1;
820 DPsi[3] = t2 + t3 - 0.625E-1;
821 }
822
823 /// Second Derivatives of 1D shape functions specialised to cubic
824 /// order (4 Nodes)
825 template<>
826 inline void d2shape<4>(const double& s, double* DPsi)
827 {
828 // Output from Maple (modified by ALH, CHECK IT)
829 double t1 = 2.0 * s;
830 double t2 = 0.16875E1 * t1;
831 double t5 = 0.50625E1 * t1;
832 DPsi[0] = -t2 + 0.1125E1;
833 DPsi[1] = t5 - 0.1125E1;
834 DPsi[2] = -t5 - 0.1125E1;
835 DPsi[3] = t2 + 0.1125E1;
836 }
837
838 }; // namespace OneDimLagrange
839
840 //======================================================================
841 /// One dimensional shape functions and derivatives. Empty -- simply
842 /// establishes the template parameters.
843 //======================================================================
844 namespace OneDimDiscontinuousGalerkin
845 {
846 /// Definition for 1D Lagrange shape functions. The
847 /// value of all the shape functions at the local coordinate s
848 /// are returned in the array Psi.
849 template<unsigned NNODE_1D>
850 void shape(const double& s, double* Psi)
851 {
852 // Create an output stream
853 std::ostringstream error_stream;
854
855 // Create the error message
856 error_stream << "One dimensional Lagrange shape functions "
857 << "have not been defined "
858 << "for " << NNODE_1D << " nodes." << std::endl;
859
860 // Throw the error message
861 throw OomphLibError(
863 }
864
865 /// Definition for derivatives of 1D Lagrange shape functions. The
866 /// value of all the shape function derivatives at the local coordinate s
867 /// are returned in the array DPsi.
868 template<unsigned NNODE_1D>
869 void dshape(const double& s, double* DPsi)
870 {
871 // Create an output stream
872 std::ostringstream error_stream;
873
874 // Create the error message
875 error_stream << "One dimensional Lagrange shape function derivatives "
876 << "have not been defined "
877 << "for " << NNODE_1D << " nodes." << std::endl;
878
879 // Throw the error message
880 throw OomphLibError(
882 }
883
884 /// Definition for second derivatives of
885 /// 1D Lagrange shape functions. The
886 /// value of all the shape function derivatives at the local coordinate s
887 /// are returned in the array DPsi.
888 template<unsigned NNODE_1D>
889 void d2shape(const double& s, double* DPsi)
890 {
891 // Create an output stream
892 std::ostringstream error_stream;
893
894 // Create the error message
895 error_stream << "One dimensional Lagrange shape function "
896 << "second derivatives "
897 << "have not been defined "
898 << "for " << NNODE_1D << " nodes." << std::endl;
899
900 // Throw the error message
901 throw OomphLibError(
903 }
904
905 /// 1D shape functions specialised to linear order (2 Nodes)
906 // Note that the numbering is such that shape[0] is at s = -1.0.
907 // and shape[1] is at s = 1.0
908 template<>
909 inline void shape<2>(const double& s, double* Psi)
910 {
911 Psi[0] = 0.0;
912 Psi[1] = 1.0;
913 }
914
915 /// Derivatives of 1D shape functions specialised to linear order (2 Nodes)
916 template<>
917 inline void dshape<2>(const double& s, double* DPsi)
918 {
919 DPsi[0] = 0.0;
920 DPsi[1] = 0.0;
921 }
922
923 /// Second Derivatives of 1D shape functions,
924 /// specialised to linear order (2 Nodes)
925 template<>
926 inline void d2shape<2>(const double& s, double* DPsi)
927 {
928 DPsi[0] = 0.0;
929 DPsi[1] = 0.0;
930 }
931
932 /// 1D shape functions specialised to quadratic order (3 Nodes)
933 // Note that the numbering is such that shape[0] is at s = -1.0,
934 // shape[1] is at s = 0.0 and shape[2] is at s = 1.0.
935 template<>
936 inline void shape<3>(const double& s, double* Psi)
937 {
938 Psi[0] = 0.0;
939 Psi[1] = 0.5 * (1.0 - s);
940 Psi[2] = 0.5 * (1.0 + s);
941 }
942
943 /// Derivatives of 1D shape functions specialised to quadratic order (3
944 /// Nodes)
945 template<>
946 inline void dshape<3>(const double& s, double* DPsi)
947 {
948 DPsi[0] = 0.0;
949 DPsi[1] = -0.5;
950 DPsi[2] = 0.5;
951 }
952
953 /// Second Derivatives of 1D shape functions, specialised to quadratic order
954 /// (3 Nodes)
955 template<>
956 inline void d2shape<3>(const double& s, double* DPsi)
957 {
958 DPsi[0] = 0.0;
959 DPsi[1] = 0.0;
960 DPsi[2] = 0.0;
961 }
962
963 /// 1D shape functions specialised to cubic order (4 Nodes)
964 template<>
965 inline void shape<4>(const double& s, double* Psi)
966 {
967 Psi[0] = 0.0;
968 Psi[1] = 0.5 * s * (s - 1.0);
969 Psi[2] = 1.0 - s * s;
970 Psi[3] = 0.5 * s * (s + 1.0);
971 }
972
973
974 /// Derivatives of 1D shape functions specialised to cubic order (4 Nodes)
975 template<>
976 inline void dshape<4>(const double& s, double* DPsi)
977 {
978 DPsi[0] = 0.0;
979 DPsi[1] = s - 0.5;
980 DPsi[2] = -2.0 * s;
981 DPsi[3] = s + 0.5;
982 }
983
984 /// Second derivatives of 1D shape functions specialised to cubic
985 /// order (4 nodes)
986 template<>
987 inline void d2shape<4>(const double& s, double* DPsi)
988 {
989 DPsi[0] = 0.0;
990 DPsi[1] = 1.0;
991 DPsi[2] = -2.0;
992 DPsi[3] = 1.0;
993 }
994 }; // namespace OneDimDiscontinuousGalerkin
995
996
997 //======================================================================
998 /// One dimensional shape functions and derivatives. Empty -- simply
999 /// establishes the template parameters.
1000 //======================================================================
1001 namespace OneDimDiscontinuousGalerkinMixedOrderBasis
1002 {
1003 /// Definition for 1D Lagrange shape functions. The
1004 /// value of all the shape functions at the local coordinate s
1005 /// are returned in the array Psi.
1006 template<unsigned NNODE_1D>
1007 void shape(const double& s, double* Psi)
1008 {
1009 // Create an output stream
1010 std::ostringstream error_stream;
1011
1012 // Create the error message
1013 error_stream << "One dimensional Lagrange shape functions "
1014 << "have not been defined "
1015 << "for " << NNODE_1D << " nodes." << std::endl;
1016
1017 // Throw the error message
1018 throw OomphLibError(
1020 }
1021
1022 /// Definition for derivatives of 1D Lagrange shape functions. The
1023 /// value of all the shape function derivatives at the local coordinate s
1024 /// are returned in the array DPsi.
1025 template<unsigned NNODE_1D>
1026 void dshape(const double& s, double* DPsi)
1027 {
1028 // Create an output stream
1029 std::ostringstream error_stream;
1030
1031 // Create the error message
1032 error_stream << "One dimensional Lagrange shape function derivatives "
1033 << "have not been defined "
1034 << "for " << NNODE_1D << " nodes." << std::endl;
1035
1036 // Throw the error message
1037 throw OomphLibError(
1039 }
1040
1041 /// Definition for second derivatives of
1042 /// 1D Lagrange shape functions. The
1043 /// value of all the shape function derivatives at the local coordinate s
1044 /// are returned in the array DPsi.
1045 template<unsigned NNODE_1D>
1046 void d2shape(const double& s, double* DPsi)
1047 {
1048 // Create an output stream
1049 std::ostringstream error_stream;
1050
1051 // Create the error message
1052 error_stream << "One dimensional Lagrange shape function "
1053 << "second derivatives "
1054 << "have not been defined "
1055 << "for " << NNODE_1D << " nodes." << std::endl;
1056
1057 // Throw the error message
1058 throw OomphLibError(
1060 }
1061
1062 /// 1D shape functions specialised to linear order (2 Nodes)
1063 // Note that the numbering is such that shape[0] is at s = -1.0.
1064 // and shape[1] is at s = 1.0
1065 template<>
1066 inline void shape<2>(const double& s, double* Psi)
1067 {
1068 Psi[0] = 0.5 * (1.0 - s);
1069 Psi[1] = 0.5 * (1.0 + s);
1070 }
1071
1072 /// Derivatives of 1D shape functions specialised to linear order (2 Nodes)
1073 template<>
1074 inline void dshape<2>(const double& s, double* DPsi)
1075 {
1076 DPsi[0] = -0.5;
1077 DPsi[1] = 0.5;
1078 }
1079
1080 /// Second Derivatives of 1D shape functions,
1081 /// specialised to linear order (2 Nodes)
1082 template<>
1083 inline void d2shape<2>(const double& s, double* DPsi)
1084 {
1085 DPsi[0] = 0.0;
1086 DPsi[1] = 0.0;
1087 }
1088
1089 /// 1D shape functions specialised to quadratic order (3 Nodes)
1090 // Note that the numbering is such that shape[0] is at s = -1.0,
1091 // shape[1] is at s = 0.0 and shape[2] is at s = 1.0.
1092 template<>
1093 inline void shape<3>(const double& s, double* Psi)
1094 {
1095 Psi[0] = 0.5 * (1.0 - s);
1096 Psi[1] = 0.0;
1097 Psi[2] = 0.5 * (1.0 + s);
1098 }
1099
1100 /// Derivatives of 1D shape functions specialised to quadratic order (3
1101 /// Nodes)
1102 template<>
1103 inline void dshape<3>(const double& s, double* DPsi)
1104 {
1105 DPsi[0] = -0.5;
1106 DPsi[1] = 0.0;
1107 DPsi[2] = 0.5;
1108 }
1109
1110 /// Second Derivatives of 1D shape functions, specialised to quadratic order
1111 /// (3 Nodes)
1112 template<>
1113 inline void d2shape<3>(const double& s, double* DPsi)
1114 {
1115 DPsi[0] = 0.0;
1116 DPsi[1] = 0.0;
1117 DPsi[2] = 0.0;
1118 }
1119
1120 /// 1D shape functions specialised to cubic order (4 Nodes)
1121 template<>
1122 inline void shape<4>(const double& s, double* Psi)
1123 {
1124 Psi[0] = 0.5 * (1.0 - s);
1125 Psi[1] = 0.0;
1126 Psi[2] = 0.0;
1127 Psi[3] = 0.5 * (1.0 + s);
1128 }
1129
1130
1131 /// Derivatives of 1D shape functions specialised to cubic order (4 Nodes)
1132 template<>
1133 inline void dshape<4>(const double& s, double* DPsi)
1134 {
1135 DPsi[0] = -0.5;
1136 DPsi[1] = 0.0;
1137 DPsi[2] = 0.0;
1138 DPsi[3] = 0.5;
1139 }
1140
1141 /// Second derivatives of 1D shape functions specialised to cubic
1142 /// order (4 nodes)
1143 template<>
1144 inline void d2shape<4>(const double& s, double* DPsi)
1145 {
1146 DPsi[0] = 0.0;
1147 DPsi[1] = 0.0;
1148 DPsi[2] = 0.0;
1149 DPsi[3] = 0.0;
1150 }
1151 }; // namespace OneDimDiscontinuousGalerkinMixedOrderBasis
1152
1153
1154 //======================================================================
1155 /// One dimensional shape functions and derivatives. Empty -- simply
1156 /// establishes the template parameters.
1157 //======================================================================
1158 namespace OneDimDiscontinuousGalerkinMixedOrderTest
1159 {
1160 /// Definition for 1D Lagrange shape functions. The
1161 /// value of all the shape functions at the local coordinate s
1162 /// are returned in the array Psi.
1163 template<unsigned NNODE_1D>
1164 void shape(const double& s, double* Psi)
1165 {
1166 // Create an output stream
1167 std::ostringstream error_stream;
1168
1169 // Create the error message
1170 error_stream << "One dimensional Lagrange shape functions "
1171 << "have not been defined "
1172 << "for " << NNODE_1D << " nodes." << std::endl;
1173
1174 // Throw the error message
1175 throw OomphLibError(
1177 }
1178
1179 /// Definition for derivatives of 1D Lagrange shape functions. The
1180 /// value of all the shape function derivatives at the local coordinate s
1181 /// are returned in the array DPsi.
1182 template<unsigned NNODE_1D>
1183 void dshape(const double& s, double* DPsi)
1184 {
1185 // Create an output stream
1186 std::ostringstream error_stream;
1187
1188 // Create the error message
1189 error_stream << "One dimensional Lagrange shape function derivatives "
1190 << "have not been defined "
1191 << "for " << NNODE_1D << " nodes." << std::endl;
1192
1193 // Throw the error message
1194 throw OomphLibError(
1196 }
1197
1198 /// Definition for second derivatives of
1199 /// 1D Lagrange shape functions. The
1200 /// value of all the shape function derivatives at the local coordinate s
1201 /// are returned in the array DPsi.
1202 template<unsigned NNODE_1D>
1203 void d2shape(const double& s, double* DPsi)
1204 {
1205 // Create an output stream
1206 std::ostringstream error_stream;
1207
1208 // Create the error message
1209 error_stream << "One dimensional Lagrange shape function "
1210 << "second derivatives "
1211 << "have not been defined "
1212 << "for " << NNODE_1D << " nodes." << std::endl;
1213
1214 // Throw the error message
1215 throw OomphLibError(
1217 }
1218
1219 /// 1D shape functions specialised to linear order (2 Nodes)
1220 // Note that the numbering is such that shape[0] is at s = -1.0.
1221 // and shape[1] is at s = 1.0
1222 template<>
1223 inline void shape<2>(const double& s, double* Psi)
1224 {
1225 Psi[0] = 0.0;
1226 Psi[1] = 1.0;
1227 }
1228
1229 /// Derivatives of 1D shape functions specialised to linear order (2 Nodes)
1230 template<>
1231 inline void dshape<2>(const double& s, double* DPsi)
1232 {
1233 DPsi[0] = 0.0;
1234 DPsi[1] = 0.0;
1235 }
1236
1237 /// Second Derivatives of 1D shape functions,
1238 /// specialised to linear order (2 Nodes)
1239 template<>
1240 inline void d2shape<2>(const double& s, double* DPsi)
1241 {
1242 DPsi[0] = 0.0;
1243 DPsi[1] = 0.0;
1244 }
1245
1246 /// 1D shape functions specialised to quadratic order (3 Nodes)
1247 // Note that the numbering is such that shape[0] is at s = -1.0,
1248 // shape[1] is at s = 0.0 and shape[2] is at s = 1.0.
1249 template<>
1250 inline void shape<3>(const double& s, double* Psi)
1251 {
1252 Psi[0] = 0.0;
1253 Psi[1] = 0.0;
1254 Psi[2] = 1.0;
1255 }
1256
1257 /// Derivatives of 1D shape functions specialised to quadratic order (3
1258 /// Nodes)
1259 template<>
1260 inline void dshape<3>(const double& s, double* DPsi)
1261 {
1262 DPsi[0] = 0.0;
1263 DPsi[1] = 0.0;
1264 DPsi[2] = 0.0;
1265 }
1266
1267 /// Second Derivatives of 1D shape functions, specialised to quadratic order
1268 /// (3 Nodes)
1269 template<>
1270 inline void d2shape<3>(const double& s, double* DPsi)
1271 {
1272 DPsi[0] = 0.0;
1273 DPsi[1] = 0.0;
1274 DPsi[2] = 0.0;
1275 }
1276
1277 /// 1D shape functions specialised to cubic order (4 Nodes)
1278 template<>
1279 inline void shape<4>(const double& s, double* Psi)
1280 {
1281 Psi[0] = 0.0;
1282 Psi[1] = 0.0;
1283 Psi[2] = 0.0;
1284 Psi[3] = 1.0;
1285 }
1286
1287
1288 /// Derivatives of 1D shape functions specialised to cubic order (4 Nodes)
1289 template<>
1290 inline void dshape<4>(const double& s, double* DPsi)
1291 {
1292 DPsi[0] = 0.0;
1293 DPsi[1] = 0.0;
1294 DPsi[2] = 0.0;
1295 DPsi[3] = 0.0;
1296 }
1297
1298 /// Second derivatives of 1D shape functions specialised to cubic
1299 /// order (4 nodes)
1300 template<>
1301 inline void d2shape<4>(const double& s, double* DPsi)
1302 {
1303 DPsi[0] = 0.0;
1304 DPsi[1] = 0.0;
1305 DPsi[2] = 0.0;
1306 DPsi[3] = 0.0;
1307 }
1308 }; // namespace OneDimDiscontinuousGalerkinMixedOrderTest
1309
1310 //===============================================================
1311 /// One Dimensional Hermite shape functions
1312 //===============================================================
1313 namespace OneDimHermite
1314 {
1315 // Convention for polynomial numbering scheme
1316 // Type 0 is position, 1 is slope
1317 // Node 0 is at s=0 and 1 is s=1
1318
1319 /// Constructor sets the values of the shape functions at the position s.
1320 inline void shape(const double& s, double Psi[2][2])
1321 {
1322 // Node 0
1323 Psi[0][0] = 0.25 * (s * s * s - 3.0 * s + 2.0);
1324 Psi[0][1] = 0.25 * (s * s * s - s * s - s + 1.0);
1325 // Node 1
1326 Psi[1][0] = 0.25 * (2.0 + 3.0 * s - s * s * s);
1327 Psi[1][1] = 0.25 * (s * s * s + s * s - s - 1.0);
1328 }
1329
1330
1331 /// Derivatives of 1D Hermite shape functions
1332 inline void dshape(const double& s, double DPsi[2][2])
1333 {
1334 // Node 0
1335 DPsi[0][0] = 0.75 * (s * s - 1.0);
1336 DPsi[0][1] = 0.25 * (3.0 * s * s - 2.0 * s - 1.0);
1337 // Node 1
1338 DPsi[1][0] = 0.75 * (1.0 - s * s);
1339 DPsi[1][1] = 0.25 * (3.0 * s * s + 2.0 * s - 1.0);
1340 }
1341
1342 /// Second derivatives of the Hermite shape functions
1343 inline void d2shape(const double& s, double DPsi[2][2])
1344 {
1345 // Node 0
1346 DPsi[0][0] = 1.5 * s;
1347 DPsi[0][1] = 0.5 * (3.0 * s - 1.0);
1348 // Node 1
1349 DPsi[1][0] = -1.5 * s;
1350 DPsi[1][1] = 0.5 * (3.0 * s + 1.0);
1351 }
1352
1353 }; // namespace OneDimHermite
1354
1355 //=====================================================================
1356 /// Class that returns the shape functions associated with legendre
1357 //=====================================================================
1358 template<unsigned NNODE_1D>
1360 {
1361 static bool Nodes_calculated;
1362
1363 public:
1365
1366 /// Static function used to populate the stored positions
1367 static inline void calculate_nodal_positions()
1368 {
1369 if (!Nodes_calculated)
1370 {
1372 Nodes_calculated = true;
1373 }
1374 }
1375
1376 static inline double nodal_position(const unsigned& n)
1377 {
1378 return z[n];
1379 }
1380
1381 /// Constructor
1383 {
1384 using namespace Orthpoly;
1385
1386 unsigned p = NNODE_1D - 1;
1387 // Now populate the shape function
1388 for (unsigned i = 0; i < NNODE_1D; i++)
1389 {
1390 // If we're at one of the nodes, the value must be 1.0
1391 if (std::fabs(s - z[i]) < Orthpoly::eps)
1392 {
1393 (*this)[i] = 1.0;
1394 }
1395 // Otherwise use the lagrangian interpolant
1396 else
1397 {
1398 (*this)[i] = (1.0 - s * s) * dlegendre(p, s) /
1399 (p * (p + 1) * legendre(p, z[i]) * (z[i] - s));
1400 }
1401 }
1402 }
1403 };
1404
1405 template<unsigned NNODE_1D>
1407
1408 template<unsigned NNODE_1D>
1410
1411
1412 template<unsigned NNODE_1D>
1414 {
1415 public:
1416 // Constructor
1418 {
1419 unsigned p = NNODE_1D - 1;
1421
1422
1423 bool root = false;
1424
1425 for (unsigned i = 0; i < NNODE_1D; i++)
1426 {
1427 unsigned rootnum = 0;
1428 for (unsigned j = 0; j < NNODE_1D; j++)
1429 { // Loop over roots to check if
1430 if (std::fabs(s - z[j]) < 10 * Orthpoly::eps)
1431 { // s happens to be a root.
1432 root = true;
1433 break;
1434 }
1435 rootnum += 1;
1436 }
1437 if (root == true)
1438 {
1439 if (i == rootnum && i == 0)
1440 {
1441 (*this)[i] = -(1.0 + p) * p / 4.0;
1442 }
1443 else if (i == rootnum && i == p)
1444 {
1445 (*this)[i] = (1.0 + p) * p / 4.0;
1446 }
1447 else if (i == rootnum)
1448 {
1449 (*this)[i] = 0.0;
1450 }
1451 else
1452 {
1453 (*this)[i] = Orthpoly::legendre(p, z[rootnum]) /
1454 Orthpoly::legendre(p, z[i]) / (z[rootnum] - z[i]);
1455 }
1456 }
1457 else
1458 {
1459 (*this)[i] =
1460 ((1 + s * (s - 2 * z[i])) / (s - z[i]) * Orthpoly::dlegendre(p, s) -
1461 (1 - s * s) * Orthpoly::ddlegendre(p, s)) /
1462 p / (p + 1.0) / Orthpoly::legendre(p, z[i]) / (s - z[i]);
1463 }
1464 root = false;
1465 }
1466 }
1467 };
1468
1469
1470 //=====================================================================
1471 /// Non-templated class that returns modal hierachical shape functions
1472 /// based on Legendre polynomials
1473 //=====================================================================
1475 {
1476 public:
1477 /// Constructor
1478 OneDimensionalModalShape(const unsigned p_order, const double& s)
1479 : Shape(p_order)
1480 {
1481 // Populate the shape functions
1482 (*this)[0] = 0.5 * (1.0 - s);
1483 (*this)[1] = 0.5 * (1.0 + s);
1484 for (unsigned i = 2; i < p_order; i++)
1485 {
1486 (*this)[i] =
1487 (0.5 * (1.0 - s)) * (0.5 * (1.0 + s)) * Orthpoly::legendre(i - 2, s);
1488 }
1489 }
1490 };
1491
1493 {
1494 public:
1495 // Constructor
1496 OneDimensionalModalDShape(const unsigned p_order, const double& s)
1497 : Shape(p_order)
1498 {
1499 // Populate the shape functions
1500 (*this)[0] = -0.5;
1501 (*this)[1] = 0.5;
1502 for (unsigned i = 2; i < p_order; i++)
1503 {
1504 (*this)[i] = (0.5 * (1.0 - s)) * (0.5 * (1.0 + s)) *
1505 Orthpoly::dlegendre(i - 2, s) -
1506 0.5 * s * Orthpoly::legendre(i - 2, s);
1507 }
1508 }
1509 };
1510
1511} // namespace oomph
1512
1513#endif
static char t char * s
Definition cfortran.h:568
cstr elem_len * i
Definition cfortran.h:603
A Class for the derivatives of shape functions The class design is essentially the same as Shape,...
Definition shape.h:359
void operator=(DShape &dshape)
Assignment operator, shallow copy (not recommended so warning given)
Definition shape.h:460
double & operator()(const unsigned &i, const unsigned &j, const unsigned &k)
Overload the round bracket operator, with 3 indices.
Definition shape.h:606
const double & operator()(const unsigned &i, const unsigned &j, const unsigned &k) const
Overload the round bracket operator (const version)
Definition shape.h:617
unsigned long nindex3() const
Return the range of index 3 of the derivatives of the shape functions.
Definition shape.h:668
unsigned long nindex2() const
Return the range of index 2 of the derivatives of the shape functions.
Definition shape.h:662
static bool Suppress_warning_about_assignment
Boolean used to suppress warning about assignment operator.
Definition shape.h:674
unsigned offset(const unsigned long &i, const unsigned long &j) const
Caculate the offset in flat-packed C-style, column-major format, required for a given i,...
Definition shape.h:649
double & raw_direct_access(const unsigned long &i)
Direct access to internal storage of data in flat-packed C-style column-major format....
Definition shape.h:631
unsigned Index2
Size of the second index of the shape function.
Definition shape.h:375
const double & operator()(const unsigned &i, const unsigned &k) const
Overload the round bracket operator (const version)
Definition shape.h:597
~DShape()
Destructor, clean up the memory allocated by this object.
Definition shape.h:547
void operator=(DShape *const &dshape_pt)
Assignment operator, shallow copy (not reccomended so warning given)
Definition shape.h:489
const double & raw_direct_access(const unsigned long &i) const
Direct access to internal storage of data in flat-packed C-style column-major format....
Definition shape.h:640
void shallow_copy_from(DShape *const &dshape_pt)
This function does a shallow copy (resets the pointer to the data)
Definition shape.h:533
unsigned long nindex1() const
Return the range of index 1 of the derivatives of the shape functions.
Definition shape.h:656
DShape()
Default constructor - just assigns a null pointers and zero index sizes.
Definition shape.h:445
double * Allocated_storage
Pointer that addresses the storage allocated by the object on construction. This will be the same as ...
Definition shape.h:369
void resize(const unsigned &N, const unsigned &P, const unsigned &M=1)
Change the size of the storage. Note that (for some strange reason) index2 is the "optional" index,...
Definition shape.h:557
bool Is_dpsi_copied
Boolean to indicate whether the data has been copied.
Definition shape.h:381
unsigned Index1
Size of the first index of the shape function.
Definition shape.h:372
unsigned Index3
Size of the third index of the shape function.
Definition shape.h:378
DShape(const unsigned &N, const unsigned &M, const unsigned &P)
Constructor with three paramters: a two-index shape function.
Definition shape.h:432
void shallow_copy_from(DShape &dshape)
This function does a shallow copy (resets the pointer to the data)
Definition shape.h:519
void range_check(const unsigned &i, const unsigned &j, const unsigned &k) const
Private function that checks whether the indices are in range.
Definition shape.h:388
DShape(const unsigned &N, const unsigned &P)
Constructor with two parameters: a single-index shape function.
Definition shape.h:420
DShape(const DShape &dshape)=delete
Broken copy constructor.
bool Is_dpsi_a_copy
Boolean to indicate whether the data is a copy.
Definition shape.h:384
double * DPsi
Pointer that addresses the storage that will be used to read and set the shape-function derivatives....
Definition shape.h:364
double & operator()(const unsigned &i, const unsigned &k)
Overload the round bracket operator for access to the data.
Definition shape.h:588
OneDimensionalLegendreDShape(const double &s)
Definition shape.h:1417
Class that returns the shape functions associated with legendre.
Definition shape.h:1360
OneDimensionalLegendreShape(const double &s)
Constructor.
Definition shape.h:1382
static double nodal_position(const unsigned &n)
Definition shape.h:1376
static Vector< double > z
Definition shape.h:1364
static void calculate_nodal_positions()
Static function used to populate the stored positions.
Definition shape.h:1367
OneDimensionalModalDShape(const unsigned p_order, const double &s)
Definition shape.h:1496
Non-templated class that returns modal hierachical shape functions based on Legendre polynomials.
Definition shape.h:1475
OneDimensionalModalShape(const unsigned p_order, const double &s)
Constructor.
Definition shape.h:1478
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....
A Class for shape functions. In simple cases, the shape functions have only one index that can be tho...
Definition shape.h:77
void shallow_copy_from(Shape &shape)
This function makes a shallow copy (sets the pointer to the allocated data to be from another Shape o...
Definition shape.h:214
const double & operator[](const unsigned &i) const
Overload the bracket operator (const version)
Definition shape.h:291
const double & operator()(const unsigned &i, const unsigned &j) const
Overload the round bracket operator, allowing for two indices (const version)
Definition shape.h:328
void operator=(Shape &shape)
Assignment operator, shallow copy (not recommended so warning given)
Definition shape.h:157
double * Allocated_storage
Pointer that addresses the storage allocated by the object on construction. This will be the same as ...
Definition shape.h:87
unsigned nindex1() const
Return the range of index 1 of the shape function object.
Definition shape.h:337
const double & operator()(const unsigned &i) const
Overload the round bracket operator (const version)
Definition shape.h:309
double & operator()(const unsigned &i)
Overload the round bracket operator to provide access to values.
Definition shape.h:300
unsigned Index1
Size of the first index of the shape function.
Definition shape.h:90
double & operator[](const unsigned &i)
Overload the bracket operator to provide access to values.
Definition shape.h:282
void resize(const unsigned &N, const unsigned &M=1)
Change the size of the storage.
Definition shape.h:253
static bool Suppress_warning_about_assignment
Boolean used to suppress warning about assignment operator.
Definition shape.h:349
double & operator()(const unsigned &i, const unsigned &j)
Overload the round bracket operator, allowing for two indices.
Definition shape.h:318
bool Is_psi_a_copy
Boolean to indicate whether the data is a copy.
Definition shape.h:99
void shallow_copy_from(Shape *const &shape_pt)
This function make a shallow copy (sets the pointer to the allocated data to be from another Shape ob...
Definition shape.h:231
unsigned Index2
Size of the second index of the shape function.
Definition shape.h:93
bool Is_psi_copied
Boolean to indicate whether the data has been copied.
Definition shape.h:96
Shape(const unsigned &N, const unsigned &M)
Constructor for a two-index set of shape functions.
Definition shape.h:134
double * Psi
Pointer that addresses the storage that will be used to read and set the shape functions....
Definition shape.h:82
void operator=(Shape *const &shape_pt)
Assignment operator, shallow copy (not recommended so warning given)
Definition shape.h:185
unsigned nindex2() const
Return the range of index 2 of the shape function object.
Definition shape.h:343
Shape(const Shape &shape)=delete
Broken copy constructor.
Shape(const unsigned &N)
Constructor for a single-index set of shape functions.
Definition shape.h:126
void range_check(const unsigned &i, const unsigned &j) const
Private function that checks whether the index is in range.
Definition shape.h:102
Shape()
Default constructor - just assigns a null pointers and zero index sizes.
Definition shape.h:146
~Shape()
Destructor, clear up the memory allocated by the object.
Definition shape.h:245
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
void dshape< 4 >(const double &s, double *DPsi)
Derivatives of 1D shape functions specialised to cubic order (4 Nodes)
Definition shape.h:1133
void d2shape< 2 >(const double &s, double *DPsi)
Second Derivatives of 1D shape functions, specialised to linear order (2 Nodes)
Definition shape.h:1083
void dshape< 3 >(const double &s, double *DPsi)
Derivatives of 1D shape functions specialised to quadratic order (3 Nodes)
Definition shape.h:1103
void shape< 2 >(const double &s, double *Psi)
1D shape functions specialised to linear order (2 Nodes)
Definition shape.h:1066
void d2shape< 3 >(const double &s, double *DPsi)
Second Derivatives of 1D shape functions, specialised to quadratic order (3 Nodes)
Definition shape.h:1113
void d2shape< 4 >(const double &s, double *DPsi)
Second derivatives of 1D shape functions specialised to cubic order (4 nodes)
Definition shape.h:1144
void shape< 3 >(const double &s, double *Psi)
1D shape functions specialised to quadratic order (3 Nodes)
Definition shape.h:1093
void dshape(const double &s, double *DPsi)
Definition for derivatives of 1D Lagrange shape functions. The value of all the shape function deriva...
Definition shape.h:1026
void shape< 4 >(const double &s, double *Psi)
1D shape functions specialised to cubic order (4 Nodes)
Definition shape.h:1122
void d2shape(const double &s, double *DPsi)
Definition for second derivatives of 1D Lagrange shape functions. The value of all the shape function...
Definition shape.h:1046
void dshape< 2 >(const double &s, double *DPsi)
Derivatives of 1D shape functions specialised to linear order (2 Nodes)
Definition shape.h:1074
void shape(const double &s, double *Psi)
Definition for 1D Lagrange shape functions. The value of all the shape functions at the local coordin...
Definition shape.h:1007
void d2shape(const double &s, double *DPsi)
Definition for second derivatives of 1D Lagrange shape functions. The value of all the shape function...
Definition shape.h:1203
void d2shape< 3 >(const double &s, double *DPsi)
Second Derivatives of 1D shape functions, specialised to quadratic order (3 Nodes)
Definition shape.h:1270
void dshape< 3 >(const double &s, double *DPsi)
Derivatives of 1D shape functions specialised to quadratic order (3 Nodes)
Definition shape.h:1260
void shape< 3 >(const double &s, double *Psi)
1D shape functions specialised to quadratic order (3 Nodes)
Definition shape.h:1250
void dshape(const double &s, double *DPsi)
Definition for derivatives of 1D Lagrange shape functions. The value of all the shape function deriva...
Definition shape.h:1183
void dshape< 2 >(const double &s, double *DPsi)
Derivatives of 1D shape functions specialised to linear order (2 Nodes)
Definition shape.h:1231
void d2shape< 4 >(const double &s, double *DPsi)
Second derivatives of 1D shape functions specialised to cubic order (4 nodes)
Definition shape.h:1301
void dshape< 4 >(const double &s, double *DPsi)
Derivatives of 1D shape functions specialised to cubic order (4 Nodes)
Definition shape.h:1290
void shape(const double &s, double *Psi)
Definition for 1D Lagrange shape functions. The value of all the shape functions at the local coordin...
Definition shape.h:1164
void shape< 2 >(const double &s, double *Psi)
1D shape functions specialised to linear order (2 Nodes)
Definition shape.h:1223
void d2shape< 2 >(const double &s, double *DPsi)
Second Derivatives of 1D shape functions, specialised to linear order (2 Nodes)
Definition shape.h:1240
void shape< 4 >(const double &s, double *Psi)
1D shape functions specialised to cubic order (4 Nodes)
Definition shape.h:1279
void dshape< 3 >(const double &s, double *DPsi)
Derivatives of 1D shape functions specialised to quadratic order (3 Nodes)
Definition shape.h:946
void dshape< 4 >(const double &s, double *DPsi)
Derivatives of 1D shape functions specialised to cubic order (4 Nodes)
Definition shape.h:976
void shape< 3 >(const double &s, double *Psi)
1D shape functions specialised to quadratic order (3 Nodes)
Definition shape.h:936
void dshape(const double &s, double *DPsi)
Definition for derivatives of 1D Lagrange shape functions. The value of all the shape function deriva...
Definition shape.h:869
void d2shape< 3 >(const double &s, double *DPsi)
Second Derivatives of 1D shape functions, specialised to quadratic order (3 Nodes)
Definition shape.h:956
void dshape< 2 >(const double &s, double *DPsi)
Derivatives of 1D shape functions specialised to linear order (2 Nodes)
Definition shape.h:917
void shape< 2 >(const double &s, double *Psi)
1D shape functions specialised to linear order (2 Nodes)
Definition shape.h:909
void d2shape(const double &s, double *DPsi)
Definition for second derivatives of 1D Lagrange shape functions. The value of all the shape function...
Definition shape.h:889
void shape< 4 >(const double &s, double *Psi)
1D shape functions specialised to cubic order (4 Nodes)
Definition shape.h:965
void d2shape< 4 >(const double &s, double *DPsi)
Second derivatives of 1D shape functions specialised to cubic order (4 nodes)
Definition shape.h:987
void shape(const double &s, double *Psi)
Definition for 1D Lagrange shape functions. The value of all the shape functions at the local coordin...
Definition shape.h:850
void d2shape< 2 >(const double &s, double *DPsi)
Second Derivatives of 1D shape functions, specialised to linear order (2 Nodes)
Definition shape.h:926
void dshape(const double &s, double DPsi[2][2])
Derivatives of 1D Hermite shape functions.
Definition shape.h:1332
void d2shape(const double &s, double DPsi[2][2])
Second derivatives of the Hermite shape functions.
Definition shape.h:1343
void shape(const double &s, double Psi[2][2])
Constructor sets the values of the shape functions at the position s.
Definition shape.h:1320
void shape(const double &s, double *Psi)
Definition for 1D Lagrange shape functions. The value of all the shape functions at the local coordin...
Definition shape.h:690
void d2shape< 2 >(const double &s, double *DPsi)
Second Derivatives of 1D shape functions, specialised to linear order (2 Nodes)
Definition shape.h:751
void dshape< 3 >(const double &s, double *DPsi)
Derivatives of 1D shape functions specialised to quadratic order (3 Nodes)
Definition shape.h:771
void d2shape(const double &s, double *DPsi)
Definition for second derivatives of 1D Lagrange shape functions. The value of all the shape function...
Definition shape.h:719
void dshape< 2 >(const double &s, double *DPsi)
Derivatives of 1D shape functions specialised to linear order (2 Nodes)
Definition shape.h:742
void d2shape< 3 >(const double &s, double *DPsi)
Second Derivatives of 1D shape functions, specialised to quadratic order (3 Nodes)
Definition shape.h:782
void d2shape< 4 >(const double &s, double *DPsi)
Second Derivatives of 1D shape functions specialised to cubic order (4 Nodes)
Definition shape.h:826
void dshape< 4 >(const double &s, double *DPsi)
Derivatives of 1D shape functions specialised to cubic order (4 Nodes)
Definition shape.h:810
void shape< 3 >(const double &s, double *Psi)
1D shape functions specialised to quadratic order (3 Nodes)
Definition shape.h:761
void shape< 4 >(const double &s, double *Psi)
1D shape functions specialised to cubic order (4 Nodes)
Definition shape.h:791
void shape< 2 >(const double &s, double *Psi)
1D shape functions specialised to linear order (2 Nodes)
Definition shape.h:734
void dshape(const double &s, double *DPsi)
Definition for derivatives of 1D Lagrange shape functions. The value of all the shape function deriva...
Definition shape.h:704
double dlegendre(const unsigned &p, const double &x)
Calculates first derivative of Legendre polynomial of degree p at x using three term recursive formul...
Definition orthpoly.h:121
const double eps
Definition orthpoly.h:52
double ddlegendre(const unsigned &p, const double &x)
Calculates second derivative of Legendre polynomial of degree p at x using three term recursive formu...
Definition orthpoly.h:144
double legendre(const unsigned &p, const double &x)
Calculates Legendre polynomial of degree p at x using the three term recurrence relation .
Definition orthpoly.h:57
void gll_nodes(const unsigned &Nnode, Vector< double > &x)
Calculates the Gauss Lobatto Legendre abscissas for degree p = NNode-1.
Definition orthpoly.cc:33
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).