elements.h
Go to the documentation of this file.
1// LIC// ====================================================================
2// LIC// This file forms part of oomph-lib, the object-oriented,
3// LIC// multi-physics finite-element library, available
4// LIC// at http://www.oomph-lib.org.
5// LIC//
6// LIC// Copyright (C) 2006-2025 Matthias Heil and Andrew Hazel
7// LIC//
8// LIC// This library is free software; you can redistribute it and/or
9// LIC// modify it under the terms of the GNU Lesser General Public
10// LIC// License as published by the Free Software Foundation; either
11// LIC// version 2.1 of the License, or (at your option) any later version.
12// LIC//
13// LIC// This library is distributed in the hope that it will be useful,
14// LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16// LIC// Lesser General Public License for more details.
17// LIC//
18// LIC// You should have received a copy of the GNU Lesser General Public
19// LIC// License along with this library; if not, write to the Free Software
20// LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21// LIC// 02110-1301 USA.
22// LIC//
23// LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24// LIC//
25// LIC//====================================================================
26// Header file for classes that define element objects
27
28// Include guard to prevent multiple inclusions of the header
29#ifndef OOMPH_GENERIC_ELEMENTS_HEADER
30#define OOMPH_GENERIC_ELEMENTS_HEADER
31
32// Config header
33#ifdef HAVE_CONFIG_H
34#include <oomph-lib-config.h>
35#endif
36
37#include <map>
38#include <deque>
39#include <string>
40#include <list>
41
42// oomph-lib includes
43#include "integral.h"
44#include "nodes.h"
45#include "geom_objects.h"
46
47namespace oomph
48{
49 // Forward definition for time
50 class Time;
51
52
53 //========================================================================
54 /// A Generalised Element class.
55 ///
56 /// The main components of a GeneralisedElement are:
57 /// - pointers to its internal and external Data, which are stored together
58 /// in a single array so that we need only store one pointer.
59 /// The internal Data are placed at the beginning
60 /// of the array and the external Data are stored at the end.
61 /// - a pointer to a global Time
62 /// - a lookup table that establishes the relation between local
63 /// and global equation numbers.
64 ///
65 /// We also provide interfaces for functions that compute the
66 /// element's Jacobian matrix and/or the Vector of residuals.
67 /// In addition, an interface that returns a mass matrix --- the matrix
68 /// of terms that multiply any time derivatives in the problem --- is
69 /// also provided to permit explicit time-stepping and the solution
70 /// of the generalised eigenproblems.
71 //========================================================================
73 {
74 private:
75 /// Storage for the global equation numbers represented by the
76 /// degrees of freedom in the element.
77 unsigned long* Eqn_number;
78
79 /// Storage for array of pointers to degrees of freedom ordered
80 /// by local equation number. This information is not needed, except in
81 /// continuation, bifurcation tracking and periodic orbit calculations.
82 /// It is not set up unless the control flag
83 /// Problem::Store_local_dof_pts_in_elements = true
84 double** Dof_pt;
85
86 /// Storage for pointers to internal and external data.
87 /// The data is of the same type and so can be addressed by
88 /// a single pointer. The idea is that the array is of
89 /// total size Ninternal_data + Nexternal_data.
90 /// The internal data are stored at the beginning of the array
91 /// and the external data are stored at the end of the array.
93
94 /// Pointer to array storage for local equation numbers associated
95 /// with internal and external data. Again, we save storage by using
96 /// a single pointer to access this information. The first index of the
97 /// array is of dimension Nineternal_data + Nexternal_data and the second
98 /// index varies with the number of values stored at the data object.
99 /// In the most general case, however, the scheme is as memory efficient
100 /// as possible.
102
103 /// Number of degrees of freedom
104 unsigned Ndof;
105
106 /// Number of internal data
108
109 /// Number of external data
111
112 /// Storage for boolean flags of size Ninternal_data + Nexternal_data
113 /// that correspond to the data used in the element. The flags
114 /// indicate whether the particular
115 /// internal or external data should be included in the general
116 /// finite-difference loop in fill_in_jacobian_from_internal_by_fd() or
117 /// fill_in_jacobian_from_external_by_fd(). The default is that all
118 /// data WILL be included in the finite-difference loop, but in many
119 /// circumstances it is possible to treat certain (external) data
120 /// analytically. The use of an STL vector is optimal for memory
121 /// use because the booleans are represented as single-bits.
122 std::vector<bool> Data_fd;
123
124 protected:
125#ifdef OOMPH_HAS_MPI
126
127 /// Non-halo processor ID for Data; -1 if it's not a halo.
129
130 /// Does this element need to be kept as a halo element during a distribute?
132
133#endif
134
135 /// Add a (pointer to an) internal data object to the element and
136 /// return the index required to obtain it from the access
137 /// function \c internal_data_pt(). The boolean indicates whether
138 /// the datum should be included in the general finite-difference loop
139 /// when calculating the jacobian. The default value is true, i.e.
140 /// the data will be included in the finite differencing.
141 unsigned add_internal_data(Data* const& data_pt, const bool& fd = true);
142
143
144 /// Return the status of the boolean flag indicating whether
145 /// the internal data is included in the finite difference loop
146 inline bool internal_data_fd(const unsigned& i) const
147 {
148#ifdef RANGE_CHECKING
149 if (i >= Ninternal_data)
150 {
151 std::ostringstream error_message;
152 error_message << "Range Error: Internal data " << i
153 << " is not in the range (0," << Ninternal_data - 1
154 << ")";
155 throw OomphLibError(error_message.str(),
158 }
159#endif
160 // Return the value
161 return Data_fd[i];
162 }
163
164
165 /// Set the boolean flag to exclude the internal datum from
166 /// the finite difference loop when computing the jacobian matrix
167 inline void exclude_internal_data_fd(const unsigned& i)
168 {
169#ifdef RANGE_CHECKING
170 if (i >= Ninternal_data)
171 {
172 std::ostringstream error_message;
173 error_message << "Range Error: Internal data " << i
174 << " is not in the range (0," << Ninternal_data - 1
175 << ")";
176 throw OomphLibError(error_message.str(),
179 }
180#endif
181 // Set the value
182 Data_fd[i] = false;
183 }
184
185 /// Set the boolean flag to include the internal datum in
186 /// the finite difference loop when computing the jacobian matrix
187 inline void include_internal_data_fd(const unsigned& i)
188 {
189#ifdef RANGE_CHECKING
190 if (i >= Ninternal_data)
191 {
192 std::ostringstream error_message;
193 error_message << "Range Error: Internal data " << i
194 << " is not in the range (0," << Ninternal_data - 1
195 << ")";
196 throw OomphLibError(error_message.str(),
199 }
200#endif
201 // Set the value
202 Data_fd[i] = true;
203 }
204
205 /// Clear the storage for the global equation numbers
206 /// and pointers to dofs (if stored)
208 {
209 delete[] Eqn_number;
210 Eqn_number = 0;
211 delete[] Dof_pt;
212 Dof_pt = 0;
213 Ndof = 0;
214 }
215
216 /// Add the contents of the queue global_eqn_numbers
217 /// to the local storage for the local-to-global translation scheme.
218 /// It is essential that the entries in the queue are added IN ORDER
219 /// i.e. from the front.
221 std::deque<unsigned long> const& global_eqn_numbers,
222 std::deque<double*> const& global_dof_pt);
223
224 /// Empty dense matrix used as a dummy argument to combined
225 /// residual and jacobian functions in the case when only the residuals
226 /// are being assembled
228
229 /// Static storage for deque used to add_global_equation_numbers
230 /// when pointers to the dofs in each element are not required
231 static std::deque<double*> Dof_pt_deque;
232
233 /// Assign the local equation numbers for the internal
234 /// and external Data
235 /// This must be called after the global equation numbers have all been
236 /// assigned. It is virtual so that it can be overloaded by
237 /// ElementWithExternalElements so that any external data from the
238 /// external elements in included in the numbering scheme.
239 /// If the boolean argument is true then pointers to the dofs will be
240 /// stored in Dof_pt
242 const bool& store_local_dof_pt);
243
244 /// Assign all the local equation numbering schemes that can
245 /// be applied generically for the element. In most cases, this is the
246 /// function that will be overloaded by inherited classes. It is required
247 /// to ensure that assign_additional_local_eqn_numbers() can always be
248 /// called after ALL other local equation numbering has been performed.
249 /// The default for the GeneralisedElement is simply to call internal
250 /// and external local equation numbering.
251 /// If the boolean argument is true then pointers to the dofs will be stored
252 /// in Dof_pt
254 const bool& store_local_dof_pt)
255 {
256 this->assign_internal_and_external_local_eqn_numbers(store_local_dof_pt);
257 }
258
259 /// Setup any additional look-up schemes for local equation numbers.
260 /// Examples of use include using local storage to refer to explicit
261 /// degrees of freedom. The additional memory cost of such storage may
262 /// or may not be offset by fast local access.
264
265 /// Return the local equation number corresponding to the j-th
266 /// value stored at the i-th internal data
267 inline int internal_local_eqn(const unsigned& i, const unsigned& j) const
268 {
269#ifdef RANGE_CHECKING
270 if (i >= Ninternal_data)
271 {
272 std::ostringstream error_message;
273 error_message << "Range Error: Internal data " << i
274 << " is not in the range (0," << Ninternal_data - 1
275 << ")";
276 throw OomphLibError(error_message.str(),
279 }
280 else
281 {
282 unsigned n_value = internal_data_pt(i)->nvalue();
283 if (j >= n_value)
284 {
285 std::ostringstream error_message;
286 error_message << "Range Error: value " << j << " at internal data "
287 << i << " is not in the range (0," << n_value - 1
288 << ")";
289 throw OomphLibError(error_message.str(),
292 }
293 }
294#endif
295 // Check that the data has been allocated
296#ifdef PARANOID
297 if (Data_local_eqn == 0)
298 {
299 throw OomphLibError(
300 "Internal local equation numbers have not been allocated",
303 }
304#endif
305 // Return the local equation number as stored in the Data_local_eqn array
306 return Data_local_eqn[i][j];
307 }
308
309 /// Return the local equation number corresponding to the j-th
310 /// value stored at the i-th external data
311 inline int external_local_eqn(const unsigned& i, const unsigned& j)
312 {
313 // Check that the data has been allocated
314#ifdef RANGE_CHECKING
315 if (i >= Nexternal_data)
316 {
317 std::ostringstream error_message;
318 error_message << "Range Error: External data " << i
319 << " is not in the range (0," << Nexternal_data - 1
320 << ")";
321 throw OomphLibError(error_message.str(),
324 }
325 else
326 {
327 unsigned n_value = external_data_pt(i)->nvalue();
328 if (j >= n_value)
329 {
330 std::ostringstream error_message;
331 error_message << "Range Error: value " << j << " at internal data "
332 << i << " is not in the range (0," << n_value - 1
333 << ")";
334 throw OomphLibError(error_message.str(),
337 }
338 }
339#endif
340#ifdef PARANOID
341 if (Data_local_eqn == 0)
342 {
343 throw OomphLibError(
344 "External local equation numbers have not been allocated",
347 }
348#endif
349 // Return the local equation number stored as the j-th value of the
350 // i-th external data object.
351 return Data_local_eqn[Ninternal_data + i][j];
352 }
353
354 /// Add the elemental contribution to the residuals vector. Note that
355 /// this function will NOT initialise the residuals vector. It must be
356 /// called after the residuals vector has been initialised to zero.
358 {
359 std::string error_message =
360 "Empty fill_in_contribution_to_residuals() has been called.\n";
361 error_message +=
362 "This function is called from the default implementations of\n";
363 error_message += "get_residuals() and get_jacobian();\n";
364 error_message +=
365 "and must calculate the residuals vector without initialising any of ";
366 error_message += "its entries.\n\n";
367
368 error_message +=
369 "If you do not wish to use these defaults, you must overload both\n";
370 error_message += "get_residuals() and get_jacobian(), which must "
371 "initialise the entries\n";
372 error_message += "of the residuals vector and jacobian matrix to zero.\n";
373
374 error_message += "N.B. the default get_jacobian() function employs "
375 "finite differencing\n";
376
377 throw OomphLibError(
379 }
380
381 /// Calculate the contributions to the jacobian from the internal
382 /// degrees of freedom using finite differences.
383 /// This version of the function assumes that the residuals vector has
384 /// already been calculated. If the boolean argument is true, the finite
385 /// differencing will be performed for all internal data, irrespective of
386 /// the information in Data_fd. The default value (false)
387 /// uses the information in Data_fd to selectively difference only
388 /// certain data.
390 DenseMatrix<double>& jacobian,
391 const bool& fd_all_data = false);
392
393 /// Calculate the contributions to the jacobian from the internal
394 /// degrees of freedom using finite differences. This version computes
395 /// the residuals vector before calculating the jacobian terms.
396 /// If the boolean argument is true, the finite
397 /// differencing will be performed for all internal data, irrespective of
398 /// the information in Data_fd. The default value (false)
399 /// uses the information in Data_fd to selectively difference only
400 /// certain data.
402 const bool& fd_all_data = false)
403 {
404 // Allocate storage for the residuals
406 // Get the residuals for the entire element
408 // Call the jacobian calculation
410 }
411
412
413 /// Calculate the contributions to the jacobian from the external
414 /// degrees of freedom using finite differences.
415 /// This version of the function assumes that the residuals vector has
416 /// already been calculated.
417 /// If the boolean argument is true, the finite
418 /// differencing will be performed for all external data, irrespective of
419 /// the information in Data_fd. The default value (false)
420 /// uses the information in Data_fd to selectively difference only
421 /// certain data.
423 DenseMatrix<double>& jacobian,
424 const bool& fd_all_data = false);
425
426
427 /// Calculate the contributions to the jacobian from the external
428 /// degrees of freedom using finite differences. This version computes
429 /// the residuals vector before calculating the jacobian terms.
430 /// If the boolean argument is true, the finite
431 /// differencing will be performed for all internal data, irrespective of
432 /// the information in Data_fd. The default value (false)
433 /// uses the information in Data_fd to selectively difference only
434 /// certain data.
436 const bool& fd_all_data = false)
437 {
438 // Allocate storage for a residuals vector
440 // Get the residuals for the entire element
442 // Call the jacobian calculation
444 }
445
446 /// Function that is called before the finite differencing of
447 /// any internal data. This may be overloaded to update any dependent
448 /// data before finite differencing takes place.
449 virtual inline void update_before_internal_fd() {}
450
451 /// Function that is call after the finite differencing of
452 /// the internal data. This may be overloaded to reset any dependent
453 /// variables that may have changed during the finite differencing.
454 virtual inline void reset_after_internal_fd() {}
455
456 /// Function called within the finite difference loop for
457 /// internal data after a change in any values in the i-th
458 /// internal data object.
459 virtual inline void update_in_internal_fd(const unsigned& i) {}
460
461 /// Function called within the finite difference loop for
462 /// internal data after the values in the i-th external data object
463 /// are reset. The default behaviour is to call the update function.
464 virtual inline void reset_in_internal_fd(const unsigned& i)
465 {
467 }
468
469
470 /// Function that is called before the finite differencing of
471 /// any external data. This may be overloaded to update any dependent
472 /// data before finite differencing takes place.
473 virtual inline void update_before_external_fd() {}
474
475 /// Function that is call after the finite differencing of
476 /// the external data. This may be overloaded to reset any dependent
477 /// variables that may have changed during the finite differencing.
478 virtual inline void reset_after_external_fd() {}
479
480 /// Function called within the finite difference loop for
481 /// external data after a change in any values in the i-th
482 /// external data object
483 virtual inline void update_in_external_fd(const unsigned& i) {}
484
485 /// Function called within the finite difference loop for
486 /// external data after the values in the i-th external data object
487 /// are reset. The default behaviour is to call the update function.
488 virtual inline void reset_in_external_fd(const unsigned& i)
489 {
491 }
492
493 /// Add the elemental contribution to the jacobian matrix.
494 /// and the residuals vector. Note that
495 /// this function will NOT initialise the residuals vector or the jacobian
496 /// matrix. It must be called after the residuals vector and
497 /// jacobian matrix have been initialised to zero. The default
498 /// is to use finite differences to calculate the jacobian
500 DenseMatrix<double>& jacobian)
501 {
502 // Add the contribution to the residuals
504 // Allocate storage for the full residuals (residuals of entire element)
506 // Get the residuals for the entire element
508 // Calculate the contributions from the internal dofs
509 //(finite-difference the lot by default)
511 // Calculate the contributions from the external dofs
512 //(finite-difference the lot by default)
514 }
515
516 /// Add the elemental contribution to the mass matrix matrix.
517 /// and the residuals vector. Note that
518 /// this function should NOT initialise the residuals vector or the mass
519 /// matrix. It must be called after the residuals vector and
520 /// jacobian matrix have been initialised to zero. The default
521 /// is deliberately broken
524
525 /// Add the elemental contribution to the jacobian matrix,
526 /// mass matrix and the residuals vector. Note that
527 /// this function should NOT initialise any entries.
528 /// It must be called after the residuals vector and
529 /// matrices have been initialised to zero.
532 DenseMatrix<double>& jacobian,
534
535 /// Add the elemental contribution to the derivatives of
536 /// the residuals with respect to a parameter. This function should
537 /// NOT initialise any entries and must be called after the entries
538 /// have been initialised to zero
539 /// The default implementation is to use finite differences to calculate
540 /// the derivatives.
542 double* const& parameter_pt, Vector<double>& dres_dparam);
543
544
545 /// Add the elemental contribution to the derivatives of
546 /// the elemental Jacobian matrix
547 /// and residuals with respect to a parameter. This function should
548 /// NOT initialise any entries and must be called after the entries
549 /// have been initialised to zero
550 /// The default implementation is to use finite differences to calculate
551 /// the derivatives.
553 double* const& parameter_pt,
556
557 /// Add the elemental contribution to the derivative of the
558 /// jacobian matrix,
559 /// mass matrix and the residuals vector with respect to the
560 /// passed parameter. Note that
561 /// this function should NOT initialise any entries.
562 /// It must be called after the residuals vector and
563 /// matrices have been initialised to zero.
565 double* const& parameter_pt,
569
570
571 /// Fill in contribution to the product of the Hessian
572 /// (derivative of Jacobian with
573 /// respect to all variables) an eigenvector, Y, and
574 /// other specified vectors, C
575 /// (d(J_{ij})/d u_{k}) Y_{j} C_{k}
577 Vector<double> const& Y,
578 DenseMatrix<double> const& C,
580
581 /// Fill in the contribution to the inner products between given
582 /// pairs of history values
584 Vector<std::pair<unsigned, unsigned>> const& history_index,
586
587 /// Fill in the contributions to the vectors that when taken
588 /// as dot product with other history values give the inner product
589 /// over the element
593
594 public:
595 /// Virtual destructor to clean up any memory allocated by the object.
596 virtual ~GeneralisedElement();
597
598 /// Broken copy constructor
600
601 /// Broken assignment operator
602 void operator=(const GeneralisedElement&) = delete;
603
604 /// Return a pointer to i-th internal data object.
605 Data*& internal_data_pt(const unsigned& i)
606 {
607#ifdef RANGE_CHECKING
608 if (i >= Ninternal_data)
609 {
610 std::ostringstream error_message;
611 error_message << "Range Error: Internal data " << i
612 << " is not in the range (0," << Ninternal_data - 1
613 << ")";
614 throw OomphLibError(error_message.str(),
617 }
618#endif
619 return Data_pt[i];
620 }
621
622 /// Return a pointer to i-th internal data object (const version)
623 Data* const& internal_data_pt(const unsigned& i) const
624 {
625#ifdef RANGE_CHECKING
626 if (i >= Ninternal_data)
627 {
628 std::ostringstream error_message;
629 error_message << "Range Error: Internal data " << i
630 << " is not in the range (0," << Ninternal_data - 1
631 << ")";
632 throw OomphLibError(error_message.str(),
635 }
636#endif
637 return Data_pt[i];
638 }
639
640
641 /// Return a pointer to i-th external data object.
642 Data*& external_data_pt(const unsigned& i)
643 {
644#ifdef RANGE_CHECKING
645 if (i >= Nexternal_data)
646 {
647 std::ostringstream error_message;
648 error_message << "Range Error: External data " << i
649 << " is not in the range (0," << Nexternal_data - 1
650 << ")";
651 throw OomphLibError(error_message.str(),
654 }
655#endif
656 return Data_pt[Ninternal_data + i];
657 }
658
659 /// Return a pointer to i-th external data object (const version)
660 Data* const& external_data_pt(const unsigned& i) const
661 {
662#ifdef RANGE_CHECKING
663 if (i >= Nexternal_data)
664 {
665 std::ostringstream error_message;
666 error_message << "Range Error: External data " << i
667 << " is not in the range (0," << Nexternal_data - 1
668 << ")";
669 throw OomphLibError(error_message.str(),
672 }
673#endif
674 return Data_pt[Ninternal_data + i];
675 }
676
677 /// Static boolean to suppress warnings about repeated
678 /// data. Defaults to false.
680
681 /// Static boolean to suppress warnings about repeated internal
682 /// data. Defaults to false.
684
685 /// Static boolean to suppress warnings about repeated external
686 /// data. Defaults to true.
688
689 /// Return the global equation number corresponding to the
690 /// ieqn_local-th local equation number
691 unsigned long eqn_number(const unsigned& ieqn_local) const
692 {
693#ifdef RANGE_CHECKING
694 if (ieqn_local >= Ndof)
695 {
696 std::ostringstream error_message;
697 error_message << "Range Error: Equation number " << ieqn_local
698 << " is not in the range (0," << Ndof - 1 << ")";
699 throw OomphLibError(error_message.str(),
702 }
703#endif
704 return Eqn_number[ieqn_local];
705 }
706
707
708 /// Return the local equation number corresponding to the
709 /// ieqn_global-th global equation number. Returns minus one (-1) if there
710 /// is
711 /// no local degree of freedom corresponding to the chosen global equation
712 /// number
713 int local_eqn_number(const unsigned long& ieqn_global) const
714 {
715 // Cache the number of degrees of freedom in the element
716 const unsigned n_dof = this->Ndof;
717 // Loop over the local equation numbers
718 for (unsigned n = 0; n < n_dof; n++)
719 {
720 // If the global equation numbers match return
721 if (ieqn_global == Eqn_number[n])
722 {
723 return n;
724 }
725 }
726
727 // If we've got all the way to the end the number has not been found
728 // return minus one.
729 return -1;
730 }
731
732
733 /// Add a (pointer to an) external data object to the element and return its
734 /// index (i.e. the index required to obtain it from
735 /// the access function \c external_data_pt(...). The optional boolean
736 /// flag indicates whether the data should be included in the
737 /// general finite-difference loop when calculating the jacobian.
738 /// The default value is true, i.e. the data will be included in the
739 /// finite-differencing
740 unsigned add_external_data(Data* const& data_pt, const bool& fd = true);
741
742 /// Return the status of the boolean flag indicating whether
743 /// the external data is included in the finite difference loop
744 inline bool external_data_fd(const unsigned& i) const
745 {
746#ifdef RANGE_CHECKING
747 if (i >= Nexternal_data)
748 {
749 std::ostringstream error_message;
750 error_message << "Range Error: Internal data " << i
751 << " is not in the range (0," << Nexternal_data - 1
752 << ")";
753 throw OomphLibError(error_message.str(),
756 }
757#endif
758 // Return the value
759 return Data_fd[Ninternal_data + i];
760 }
761
762
763 /// Set the boolean flag to exclude the external datum from the
764 /// the finite difference loop when computing the jacobian matrix
765 inline void exclude_external_data_fd(const unsigned& i)
766 {
767#ifdef RANGE_CHECKING
768 if (i >= Nexternal_data)
769 {
770 std::ostringstream error_message;
771 error_message << "Range Error: External data " << i
772 << " is not in the range (0," << Nexternal_data - 1
773 << ")";
774 throw OomphLibError(error_message.str(),
777 }
778#endif
779 // Set the value
780 Data_fd[Ninternal_data + i] = false;
781 }
782
783 /// Set the boolean flag to include the external datum in the
784 /// the finite difference loop when computing the jacobian matrix
785 inline void include_external_data_fd(const unsigned& i)
786 {
787#ifdef RANGE_CHECKING
788 if (i >= Nexternal_data)
789 {
790 std::ostringstream error_message;
791 error_message << "Range Error: External data " << i
792 << " is not in the range (0," << Nexternal_data - 1
793 << ")";
794 throw OomphLibError(error_message.str(),
797 }
798#endif
799 // Set the value
800 Data_fd[Ninternal_data + i] = true;
801 }
802
803 /// Flush all external data
804 void flush_external_data();
805
806 /// Flush the object addressed by data_pt from the external data array
807 void flush_external_data(Data* const& data_pt);
808
809 /// Return the number of internal data objects.
810 unsigned ninternal_data() const
811 {
812 return Ninternal_data;
813 }
814
815 /// Return the number of external data objects.
816 unsigned nexternal_data() const
817 {
818 return Nexternal_data;
819 }
820
821 /// Return the number of equations/dofs in the element.
822 unsigned ndof() const
823 {
824 return Ndof;
825 }
826
827 /// Return the vector of dof values at time level t
828 void dof_vector(const unsigned& t, Vector<double>& dof)
829 {
830 // Check that the internal storage has been set up
831#ifdef PARANOID
832 if (Dof_pt == 0)
833 {
834 std::stringstream error_stream;
835 error_stream << "Internal dof array not set up in element.\n"
836 << "In order to set it up you must call\n"
837 << " Problem::enable_store_local_dof_in_elements()\n"
838 << "before the call to Problem::assign_eqn_numbers()\n";
839 throw OomphLibError(
841 }
842#endif
843 // Resize the vector
844 dof.resize(this->Ndof);
845 // Loop over the vector and fill in the desired values
846 for (unsigned i = 0; i < this->Ndof; ++i)
847 {
848 dof[i] = Dof_pt[i][t];
849 }
850 }
851
852 /// Return the vector of pointers to dof values
854 {
855 // Check that the internal storage has been set up
856#ifdef PARANOID
857 if (Dof_pt == 0)
858 {
859 std::stringstream error_stream;
860 error_stream << "Internal dof array not set up in element.\n"
861 << "In order to set it up you must call\n"
862 << " Problem::enable_store_local_dof_in_elements()\n"
863 << "before the call to Problem::assign_eqn_numbers()\n";
864 throw OomphLibError(
866 }
867#endif
868 // Resize the vector
869 dof_pt.resize(this->Ndof);
870 // Loop over the vector and fill in the desired values
871 for (unsigned i = 0; i < this->Ndof; ++i)
872 {
873 dof_pt[i] = Dof_pt[i];
874 }
875 }
876
877
878 /// Set the timestepper associated with the i-th internal data
879 /// object
880 void set_internal_data_time_stepper(const unsigned& i,
881 TimeStepper* const& time_stepper_pt,
882 const bool& preserve_existing_data)
883 {
884 this->internal_data_pt(i)->set_time_stepper(time_stepper_pt,
886 }
887
888 /// Assign the global equation numbers to the internal Data.
889 /// The arguments are the current highest global equation number
890 /// (which will be incremented) and a Vector of pointers to the
891 /// global variables (to which any unpinned values in the internal Data are
892 /// added).
893 void assign_internal_eqn_numbers(unsigned long& global_number,
895
896 /// Function to describe the dofs of the element. The ostream
897 /// specifies the output stream to which the description
898 /// is written; the string stores the currently
899 /// assembled output that is ultimately written to the
900 /// output stream by Data::describe_dofs(...); it is typically
901 /// built up incrementally as we descend through the
902 /// call hierarchy of this function when called from
903 /// Problem::describe_dofs(...)
904 void describe_dofs(std::ostream& out,
905 const std::string& current_string) const;
906
907 /// Function to describe the local dofs of the element. The ostream
908 /// specifies the output stream to which the description
909 /// is written; the string stores the currently
910 /// assembled output that is ultimately written to the
911 /// output stream by Data::describe_dofs(...); it is typically
912 /// built up incrementally as we descend through the
913 /// call hierarchy of this function when called from
914 /// Problem::describe_dofs(...)
915 virtual void describe_local_dofs(std::ostream& out,
916 const std::string& current_string) const;
917
918 /// Add pointers to the internal data values to map indexed
919 /// by the global equation number.
921 std::map<unsigned, double*>& map_of_value_pt);
922
923#ifdef OOMPH_HAS_MPI
924 /// Add all internal data and time history values to the vector in
925 /// the internal storage order
927
928 /// Read all internal data and time history values from the vector
929 /// starting from index. On return the index will be
930 /// set to the value at the end of the data that has been read in
932 const Vector<double>& vector_of_values, unsigned& index);
933
934 /// Add all equation numbers associated with internal data
935 /// to the vector in the internal storage order
938
939 /// Read all equation numbers associated with internal data
940 /// from the vector
941 /// starting from index. On return the index will be
942 /// set to the value at the end of the data that has been read in
944 const Vector<long>& vector_of_eqn_numbers, unsigned& index);
945
946#endif
947
948 /// Setup the arrays of local equation numbers for the element.
949 /// If the optional boolean argument is true, then pointers to the
950 /// associated degrees of freedom are stored locally in the array Dof_pt
951 virtual void assign_local_eqn_numbers(const bool& store_local_dof_pt);
952
953 /// Complete the setup of any additional dependencies
954 /// that the element may have. Empty virtual function that may be
955 /// overloaded for specific derived elements. Used, e.g., for elements
956 /// with algebraic node update functions to determine the "geometric
957 /// Data", i.e. the Data that affects the element's shape.
958 /// This function is called (for all elements) at the very beginning of the
959 /// equation numbering procedure to ensure that all dependencies
960 /// are accounted for.
962
963 /// Calculate the vector of residuals of the equations in the
964 /// element. By default initialise the vector to zero and then call the
965 /// fill_in_contribution_to_residuals() function. Note that this entire
966 /// function can be overloaded if desired.
968 {
969 // Zero the residuals vector
970 residuals.initialise(0.0);
971 // Add the elemental contribution to the residuals vector
973 }
974
975 /// Calculate the elemental Jacobian matrix "d equation / d
976 /// variable".
978 DenseMatrix<double>& jacobian)
979 {
980 // Zero the residuals vector
981 residuals.initialise(0.0);
982 // Zero the jacobian matrix
983 jacobian.initialise(0.0);
984 // Add the elemental contribution to the residuals vector
986 }
987
988 /// Calculate the residuals and the elemental "mass" matrix, the
989 /// matrix that multiplies the time derivative terms in a problem.
992 {
993 // Zero the residuals vector
994 residuals.initialise(0.0);
995 // Zero the mass matrix
996 mass_matrix.initialise(0.0);
997 // Add the elemental contribution to the vector and matrix
999 }
1000
1001 /// Calculate the residuals and jacobian and elemental "mass" matrix,
1002 /// the matrix that multiplies the time derivative terms.
1004 DenseMatrix<double>& jacobian,
1006 {
1007 // Zero the residuals vector
1008 residuals.initialise(0.0);
1009 // Zero the jacobian matrix
1010 jacobian.initialise(0.0);
1011 // Zero the mass matrix
1012 mass_matrix.initialise(0.0);
1013 // Add the elemental contribution to the vector and matrix
1015 residuals, jacobian, mass_matrix);
1016 }
1017
1018
1019 /// Calculate the derivatives of the residuals with respect to
1020 /// a parameter
1021 virtual void get_dresiduals_dparameter(double* const& parameter_pt,
1023 {
1024 // Zero the dres_dparam vector
1025 dres_dparam.initialise(0.0);
1026 // Add the elemental contribution to the residuals vector
1028 dres_dparam);
1029 }
1030
1031 /// Calculate the derivatives of the elemental Jacobian matrix
1032 /// and residuals with respect to a parameter
1033 virtual void get_djacobian_dparameter(double* const& parameter_pt,
1036 {
1037 // Zero the residuals vector
1038 dres_dparam.initialise(0.0);
1039 // Zero the jacobian matrix
1040 djac_dparam.initialise(0.0);
1041 // Add the elemental contribution to the residuals vector
1043 parameter_pt, dres_dparam, djac_dparam);
1044 }
1045
1046 /// Calculate the derivatives of the elemental Jacobian matrix
1047 /// mass matrix and residuals with respect to a parameter
1049 double* const& parameter_pt,
1053 {
1054 // Zero the residuals derivative vector
1055 dres_dparam.initialise(0.0);
1056 // Zero the jacobian derivative matrix
1057 djac_dparam.initialise(0.0);
1058 // Zero the mass matrix derivative
1059 dmass_matrix_dparam.initialise(0.0);
1060 // Add the elemental contribution to the residuals vector and matrices
1063 }
1064
1065
1066 /// Calculate the product of the Hessian (derivative of Jacobian with
1067 /// respect to all variables) an eigenvector, Y, and
1068 /// other specified vectors, C
1069 /// (d(J_{ij})/d u_{k}) Y_{j} C_{k}
1071 DenseMatrix<double> const& C,
1073 {
1074 // Initialise the product to zero
1075 product.initialise(0.0);
1076 /// Add the elemental contribution to the product
1078 }
1079
1080 /// Return the vector of inner product of the given pairs of
1081 /// history values
1083 Vector<std::pair<unsigned, unsigned>> const& history_index,
1085 {
1086 inner_product.initialise(0.0);
1089 }
1090
1091 /// Compute the vectors that when taken as a dot product with
1092 /// other history values give the inner product over the element.
1096 {
1097 const unsigned n_inner_product = inner_product_vector.size();
1098 for (unsigned i = 0; i < n_inner_product; ++i)
1099 {
1100 inner_product_vector[i].initialise(0.0);
1101 }
1104 }
1105
1106
1107 /// Self-test: Have all internal values been classified as
1108 /// pinned/unpinned? Return 0 if OK.
1109 virtual unsigned self_test();
1110
1111
1112 /// Compute norm of solution -- broken virtual can be overloaded
1113 /// by element writer to implement whatever norm is desired for
1114 /// the specific element
1115 virtual void compute_norm(Vector<double>& norm)
1116 {
1117 std::string error_message =
1118 "compute_norm(...) undefined for this element\n";
1119 throw OomphLibError(
1121 }
1122
1123
1124 /// Compute norm of solution -- broken virtual can be overloaded
1125 /// by element writer to implement whatever norm is desired for
1126 /// the specific element
1127 virtual void compute_norm(double& norm)
1128 {
1129 std::string error_message = "compute_norm undefined for this element \n";
1130 throw OomphLibError(
1132 }
1133
1134#ifdef OOMPH_HAS_MPI
1135
1136 /// Label the element as halo and specify processor that holds
1137 /// non-halo counterpart
1138 void set_halo(const unsigned& non_halo_proc_ID)
1139 {
1141 }
1142
1143 /// Label the element as not being a halo
1145 {
1146 Non_halo_proc_ID = -1;
1147 }
1148
1149 /// Is this element a halo?
1150 bool is_halo() const
1151 {
1152 return (Non_halo_proc_ID != -1);
1153 }
1154
1155 /// ID of processor ID that holds non-halo counterpart
1156 /// of halo element; negative if not a halo.
1158 {
1159 return Non_halo_proc_ID;
1160 }
1161
1162 /// Insist that this element be kept as a halo element during a distribute?
1164 {
1165 Must_be_kept_as_halo = true;
1166 }
1167
1168 /// Do not insist that this element be kept as a halo element during
1169 /// distribution
1171 {
1172 Must_be_kept_as_halo = false;
1173 }
1174
1175 /// Test whether the element must be kept as a halo element
1177 {
1178 return Must_be_kept_as_halo;
1179 }
1180
1181#endif
1182
1183 /// Double used for the default finite difference step in elemental
1184 /// jacobian calculations
1186
1187 /// The number of types of degrees of freedom in this element
1188 /// are sub-divided into
1189 virtual unsigned ndof_types() const
1190 {
1191 // error message stream
1192 std::ostringstream error_message;
1193 error_message << "ndof_types() const has not been implemented for this \n"
1194 << "element\n"
1195 << std::endl;
1196 // throw error
1197 throw OomphLibError(
1198 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1199 }
1200
1201 /// Create a list of pairs for the unknowns that this element
1202 /// is "in charge of" -- ignore any unknowns associated with external
1203 /// \c Data. The first entry in each pair must contain the global equation
1204 /// number of the unknown, while the second one contains the number
1205 /// of the DOF type that this unknown is associated with.
1206 /// (The function can obviously only be called if the equation numbering
1207 /// scheme has been set up.)
1209 std::list<std::pair<unsigned long, unsigned>>& dof_lookup_list) const
1210 {
1211 // error message stream
1212 std::ostringstream error_message;
1213 error_message << "get_dof_numbers_for_unknowns() const has not been \n"
1214 << " implemented for this element\n"
1215 << std::endl;
1216 // throw error
1217 throw OomphLibError(
1218 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1219 }
1220
1221 /// Constructor: Initialise all pointers and all values to zero
1223 : Eqn_number(0),
1224 Dof_pt(0),
1225 Data_pt(0),
1226 Data_local_eqn(0),
1227 Ndof(0),
1228 Ninternal_data(0),
1231 ,
1232 Non_halo_proc_ID(-1),
1234#endif
1235 {
1236 }
1237 };
1238
1239 /// Enumeration a finite element's geometry "type". Either "Q" (square,
1240 /// cubeoid like) or "T" (triangle, tetrahedron).
1242 {
1244 {
1246 T
1248 }
1249
1250 // Forward class definitions that are used in FiniteElements
1251 class FaceElement;
1252 class MacroElement;
1253 class TimeStepper;
1254 class Shape;
1255 class DShape;
1256 class Integral;
1257
1258 //===========================================================================
1259 /// Helper namespace for tolerances and iterations within the Newton
1260 /// method used in the locate_zeta function in FiniteElements.
1261 //===========================================================================
1262 namespace Locate_zeta_helpers
1263 {
1264 /// Convergence tolerance for the Newton solver
1265 extern double Newton_tolerance;
1266
1267 /// Maximum number of Newton iterations
1268 extern unsigned Max_newton_iterations;
1269
1270 /// Multiplier for (zeta-based) outer radius of element used for
1271 /// deciding that point is outside element. Set to negative value
1272 /// to suppress test.
1274
1275 /// Number of points along one dimension of each element used
1276 /// to create coordinates within the element in order to see
1277 /// which has the smallest initial residual (and is therefore used
1278 /// as the initial guess in the Newton method for locate_zeta)
1279 extern unsigned N_local_points;
1280
1281 } // namespace Locate_zeta_helpers
1282
1283
1284 /// Typedef for the function that translates the face coordinate
1285 /// to the coordinate in the bulk element
1288
1289 /// Typedef for the function that returns the partial derivative
1290 /// of the local coordinates in the bulk element
1291 /// with respect to the coordinates along the face.
1292 /// In addition this function returns an index of one of the
1293 /// bulk local coordinates that varies away from the edge
1295 const Vector<double>& s,
1297 unsigned& interior_direction);
1298
1299
1300 //========================================================================
1301 /// A general Finite Element class.
1302 ///
1303 /// The main components of a FiniteElement are:
1304 /// - pointers to its Nodes
1305 /// - pointers to its internal Data (inherited from GeneralisedElement)
1306 /// - pointers to its external Data (inherited from GeneralisedElement)
1307 /// - a pointer to a spatial integration scheme
1308 /// - a pointer to the global Time object (inherited from GeneralisedElement)
1309 /// - a lookup table which establishes the relation between local
1310 /// and global equation numbers (inherited from GeneralisedElement)
1311 ///
1312 /// We also provide interfaces for functions that compute the
1313 /// element's Jacobian matrix and/or the Vector of residuals
1314 /// (inherited from GeneralisedElement) plus various output routines.
1315 //========================================================================
1316 class FiniteElement : public virtual GeneralisedElement, public GeomObject
1317 {
1318 private:
1319 /// Pointer to the spatial integration scheme
1321
1322 /// Storage for pointers to the nodes in the element
1324
1325 /// Storage for the local equation numbers associated with
1326 /// the values stored at the nodes
1328
1329 /// Number of nodes in the element
1330 unsigned Nnode;
1331
1332 /// The spatial dimension of the element, i.e. the number
1333 /// of local coordinates used to parametrize it.
1335
1336 /// The spatial dimension of the nodes in the element.
1337 /// We assume that nodes have the same spatial dimension, because
1338 /// we cannot think of any "real" problems for which that would not
1339 /// be the case.
1341
1342 /// The number of coordinate types required to interpolate
1343 /// the element's geometry between the nodes. For Lagrange elements
1344 /// it is 1 (the default). It must be over-ridden by using
1345 /// the set_nposition_type() function in the constructors of elements
1346 /// that use generalised coordinate, e.g. for 1D Hermite elements
1347 /// Nnodal_position_types =2.
1349
1350 protected:
1351 /// Assemble the jacobian matrix for the mapping from local
1352 /// to Eulerian coordinates, given the derivatives of the shape function
1353 /// w.r.t the local coordinates.
1355 const DShape& dpsids, DenseMatrix<double>& jacobian) const;
1356
1357 /// Assemble the the "jacobian" matrix of second derivatives of the
1358 /// mapping from local to Eulerian coordinates, given
1359 /// the second derivatives of the shape functions w.r.t. local coordinates.
1362
1363 /// Assemble the covariant Eulerian base vectors, assuming that
1364 /// the derivatives of the shape functions with respect to the local
1365 /// coordinates have already been constructed.
1366 virtual void assemble_eulerian_base_vectors(
1368
1369 /// Default return value for required_nvalue(n) which gives the
1370 /// number of "data" values required by the element at node n; for example,
1371 /// solving a Poisson equation would required only one "data" value at each
1372 /// node. The defaults is set to zero, because a general element is
1373 /// problem-less.
1374 static const unsigned Default_Initial_Nvalue;
1375
1376 /// Default value for the tolerance to be used when locating nodes
1377 /// via local coordinates
1378 static const double Node_location_tolerance;
1379
1380 public:
1381 /// Set the dimension of the element and initially set
1382 /// the dimension of the nodes to be the same as the dimension of the
1383 /// element.
1384 void set_dimension(const unsigned& dim)
1385 {
1388 }
1389
1390 /// Set the dimension of the nodes in the element. This will
1391 /// typically only be required when constructing FaceElements or
1392 /// in beam and shell type elements where a lower dimensional surface
1393 /// is embedded in a higher dimensional space.
1394 void set_nodal_dimension(const unsigned& nodal_dim)
1395 {
1397 }
1398
1399 /// Set the number of types required to interpolate the coordinate
1400 void set_nnodal_position_type(const unsigned& nposition_type)
1401 {
1402 Nnodal_position_type = nposition_type;
1403 }
1404
1405
1406 /// Set the number of nodes in the element to n, by resizing
1407 /// the storage for pointers to the Node objects.
1408 void set_n_node(const unsigned& n)
1409 {
1410 // This should only be done once, in a Node constructor
1411 // #ifdef PARANOID
1412 // if(Node_pt)
1413 // {
1414 // OomphLibWarning(
1415 // "You are resetting the number of nodes in an element -- Be careful",
1416 // "FiniteElement::set_n_node()",
1417 // OOMPH_EXCEPTION_LOCATION);
1418 // }
1419 // #endif
1420 // Delete any previous storage to avoid memory leaks
1421 // This will only happen in very special cases
1422 delete[] Node_pt;
1423 // Set the number of nodes
1424 Nnode = n;
1425 // Allocate the storage
1426 Node_pt = new Node*[n];
1427 // Initialise all the pointers to NULL
1428 for (unsigned i = 0; i < n; i++)
1429 {
1430 Node_pt[i] = 0;
1431 }
1432 }
1433
1434 /// Return the local equation number corresponding to the i-th
1435 /// value at the n-th local node.
1436 inline int nodal_local_eqn(const unsigned& n, const unsigned& i) const
1437 {
1438#ifdef RANGE_CHECKING
1439 if (n >= Nnode)
1440 {
1441 std::ostringstream error_message;
1442 error_message << "Range Error: Node number " << n
1443 << " is not in the range (0," << Nnode - 1 << ")";
1444 throw OomphLibError(error_message.str(),
1447 }
1448 else
1449 {
1450 unsigned n_value = node_pt(n)->nvalue();
1451 if (i >= n_value)
1452 {
1453 std::ostringstream error_message;
1454 error_message << "Range Error: value " << i << " at node " << n
1455 << " is not in the range (0," << n_value - 1 << ")";
1456 throw OomphLibError(error_message.str(),
1459 }
1460 }
1461#endif
1462#ifdef PARANOID
1463 // Check that the equations have been allocated
1464 if (Nodal_local_eqn == 0)
1465 {
1466 throw OomphLibError(
1467 "Nodal local equation numbers have not been allocated",
1470 }
1471#endif
1472 return Nodal_local_eqn[n][i];
1473 }
1474
1475
1476 /// Compute the geometric shape functions (psi) at integration point
1477 /// ipt. Return the determinant of the jacobian of the mapping (detJ).
1478 /// Additionally calculate the derivatives of "detJ" w.r.t. the
1479 /// nodal coordinates.
1480 double dJ_eulerian_at_knot(const unsigned& ipt,
1481 Shape& psi,
1483
1484 protected:
1485 /// Static array that holds the number of second derivatives
1486 /// as a function of the dimension of the element
1487 static const unsigned N2deriv[];
1488
1489 /// Take the matrix passed as jacobian and return its inverse in
1490 /// inverse_jacobian. This function is templated by the dimension of the
1491 /// element because matrix inversion cannot be written efficiently in a
1492 /// generic manner.
1493 template<unsigned DIM>
1494 double invert_jacobian(const DenseMatrix<double>& jacobian,
1496
1497
1498 /// A template-free interface that takes the matrix passed as
1499 /// jacobian and return its inverse in inverse_jacobian. By default the
1500 /// function will use the dimension of the element to call the correct
1501 /// invert_jacobian(..) function. This should be overloaded for efficiency
1502 /// (removal of a switch statement) in specific elements.
1503 virtual double invert_jacobian_mapping(
1504 const DenseMatrix<double>& jacobian,
1506
1507
1508 /// Calculate the mapping from local to Eulerian coordinates,
1509 /// given the derivatives of the shape functions w.r.t. local coordinates.
1510 /// Returns the determinant of the jacobian, the jacobian and inverse
1511 /// jacobian
1513 const DShape& dpsids,
1514 DenseMatrix<double>& jacobian,
1516 {
1517 // Assemble the jacobian
1519 // Invert the jacobian (use the template-free interface)
1520 return invert_jacobian_mapping(jacobian, inverse_jacobian);
1521 }
1522
1523
1524 /// Calculate the mapping from local to Eulerian coordinates,
1525 /// given the derivatives of the shape functions w.r.t. local coordinates,
1526 /// Return only the determinant of the jacobian and the inverse of the
1527 /// mapping (ds/dx).
1530 {
1531 // Find the dimension of the element
1532 const unsigned el_dim = dim();
1533 // Assign memory for the jacobian
1534 DenseMatrix<double> jacobian(el_dim);
1535 // Calculate the jacobian and inverse
1537 }
1538
1539 /// Calculate the mapping from local to Eulerian coordinates given
1540 /// the derivatives of the shape functions w.r.t the local coordinates.
1541 /// assuming that the coordinates are aligned in the direction of the local
1542 /// coordinates, i.e. there are no cross terms and the jacobian is diagonal.
1543 /// This function returns the determinant of the jacobian, the jacobian
1544 /// and the inverse jacobian.
1546 const DShape& dpsids,
1547 DenseMatrix<double>& jacobian,
1549
1550 /// A template-free interface that calculates the derivative of the
1551 /// jacobian of a mapping with respect to the nodal coordinates X_ij.
1552 /// To do this it requires the jacobian matrix and the derivatives of the
1553 /// shape functions w.r.t. the local coordinates. By default the function
1554 /// will use the dimension of the element to call the correct
1555 /// dJ_eulerian_dnodal_coordinates_templated_helper(..) function. This
1556 /// should be overloaded for efficiency (removal of a switch statement)
1557 /// in specific elements.
1558 virtual void dJ_eulerian_dnodal_coordinates(
1559 const DenseMatrix<double>& jacobian,
1560 const DShape& dpsids,
1562
1563 /// Calculate the derivative of the jacobian of a mapping with
1564 /// respect to the nodal coordinates X_ij using the jacobian matrix
1565 /// and the derivatives of the shape functions w.r.t. the local
1566 /// coordinates. This function is templated by the dimension of the
1567 /// element.
1568 template<unsigned DIM>
1570 const DenseMatrix<double>& jacobian,
1571 const DShape& dpsids,
1573
1574 /// A template-free interface that calculates the derivative w.r.t.
1575 /// the nodal coordinates \f$ X_{pq} \f$ of the derivative of the shape
1576 /// functions \f$ \psi_j \f$ w.r.t. the global eulerian coordinates
1577 /// \f$ x_i \f$. I.e. this function calculates
1578 /// \f[ \frac{\partial}{\partial X_{pq}} \left( \frac{\partial \psi_j}{\partial x_i} \right). \f]
1579 /// To do this it requires the determinant of the jacobian mapping, its
1580 /// derivative w.r.t. the nodal coordinates \f$ X_{pq} \f$, the inverse
1581 /// jacobian and the derivatives of the shape functions w.r.t. the local
1582 /// coordinates. The result is returned as a tensor of rank four.
1583 /// Numbering:
1584 /// d_dpsidx_dX(p,q,j,i) = \f$ \frac{\partial}{\partial X_{pq}} \left( \frac{\partial \psi_j}{\partial x_i} \right) \f$
1585 /// By default the function will use the dimension of the element to call
1586 /// the correct d_dshape_eulerian_dnodal_coordinates_templated_helper(..)
1587 /// function. This should be overloaded for efficiency (removal of a
1588 /// switch statement) in specific elements.
1590 const double& det_jacobian,
1591 const DenseMatrix<double>& jacobian,
1594 const DShape& dpsids,
1596
1597 /// Calculate the derivative w.r.t. the nodal coordinates
1598 /// \f$ X_{pq} \f$ of the derivative of the shape functions w.r.t. the
1599 /// global eulerian coordinates \f$ x_i \f$, using the determinant of
1600 /// the jacobian mapping, its derivative w.r.t. the nodal coordinates
1601 /// \f$ X_{pq} \f$, the inverse jacobian and the derivatives of the
1602 /// shape functions w.r.t. the local coordinates. The result is returned
1603 /// as a tensor of rank four.
1604 /// Numbering:
1605 /// d_dpsidx_dX(p,q,j,i) = \f$ \frac{\partial}{\partial X_{pq}} \left( \frac{\partial \psi_j}{\partial x_i} \right) \f$
1606 /// This function is templated by the dimension of the element.
1607 template<unsigned DIM>
1609 const double& det_jacobian,
1610 const DenseMatrix<double>& jacobian,
1613 const DShape& dpsids,
1615
1616 /// Convert derivative w.r.t.local coordinates to derivatives
1617 /// w.r.t the coordinates used to assemble the inverse_jacobian passed
1618 /// in the mapping. On entry, dbasis must contain the basis function
1619 /// derivatives w.r.t. the local coordinates; it will contain the
1620 /// derivatives w.r.t. the new coordinates on exit.
1621 /// This is virtual so that it may be overloaded if desired
1622 /// for efficiency reasons.
1623 virtual void transform_derivatives(
1625
1626 /// Convert derivative w.r.t local coordinates to derivatives
1627 /// w.r.t the coordinates used to assemble the inverse jacobian passed
1628 /// in the mapping, assuming that the coordinates are aligned in the
1629 /// direction of the local coordinates. On entry dbasis must contain
1630 /// the derivatives of the basis functions w.r.t. the local coordinates;
1631 /// it will contain the derivatives w.r.t. the new coordinates.
1632 /// are converted into the new using the mapping inverse_jacobian.
1635
1636 /// Convert derivatives and second derivatives w.r.t. local
1637 /// coordiantes to derivatives and second derivatives w.r.t. the coordinates
1638 /// used to assemble the jacobian, inverse jacobian and jacobian2 passed to
1639 /// the function. By default this function will call
1640 /// transform_second_derivatives_template<>(...) using the dimension of
1641 /// the element as the template parameter. It is virtual so that it can
1642 /// be overloaded by a specific element to save using a switch statement.
1643 /// Optionally, the element writer may wish to use the
1644 /// transform_second_derivatives_diagonal<>(...) function
1645 /// On entry dbasis and d2basis must contain the derivatives w.r.t. the
1646 /// local coordinates; on exit they will be the derivatives w.r.t. the
1647 /// transformed coordinates.
1648 virtual void transform_second_derivatives(
1649 const DenseMatrix<double>& jacobian,
1652 DShape& dbasis,
1653 DShape& d2basis) const;
1654
1655 /// Convert derivatives and second derivatives w.r.t. local
1656 /// coordinates to derivatives and second derivatives w.r.t. the coordinates
1657 /// used to asssmble the jacobian, inverse jacobian and jacobian2 passed in
1658 /// the mapping. This is templated by dimension because the method of
1659 /// calculation varies significantly with the dimension. On entry dbasis and
1660 /// d2basis must contain the derivatives w.r.t. the local coordinates; on
1661 /// exit they will be the derivatives w.r.t. the transformed coordinates.
1662 template<unsigned DIM>
1664 const DenseMatrix<double>& jacobian,
1667 DShape& dbasis,
1668 DShape& d2basis) const;
1669
1670 /// Convert derivatives and second derivatives w.r.t. local
1671 /// coordinates to derivatives and second derivatives w.r.t. the coordinates
1672 /// used to asssmble the jacobian, inverse jacobian and jacobian2 passed in
1673 /// the mapping. This version of the function assumes that the local
1674 /// coordinates are aligned with the global coordinates, i.e. the jacobians
1675 /// are diagonal On entry dbasis and d2basis must contain the derivatives
1676 /// w.r.t. the local coordinates; on exit they will be the derivatives
1677 /// w.r.t. the transformed coordinates.
1678 template<unsigned DIM>
1680 const DenseMatrix<double>& jacobian,
1683 DShape& dbasis,
1684 DShape& d2basis) const;
1685
1686 /// Pointer to the element's macro element (NULL by default)
1688
1689 /// Calculate the contributions to the jacobian from the nodal
1690 /// degrees of freedom using finite differences.
1691 /// This version of the function assumes that the residuals vector has
1692 /// already been calculated
1695
1696 /// Calculate the contributions to the jacobian from the nodal
1697 /// degrees of freedom using finite differences. This version computes
1698 /// the residuals vector before calculating the jacobian terms.
1700 {
1701 // Allocate storage for a residuals vector and initialise to zero
1702 unsigned n_dof = ndof();
1704 // Get the residuals for the entire element
1706 // Call the jacobian calculation
1708 }
1709
1710 /// Function that is called before the finite differencing of
1711 /// any nodal data. This may be overloaded to update any dependent
1712 /// data before finite differencing takes place.
1713 virtual inline void update_before_nodal_fd() {}
1714
1715 /// Function that is call after the finite differencing of
1716 /// the nodal data. This may be overloaded to reset any dependent
1717 /// variables that may have changed during the finite differencing.
1718 virtual inline void reset_after_nodal_fd() {}
1719
1720 /// Function called within the finite difference loop for
1721 /// nodal data after a change in the i-th nodal value.
1722 virtual inline void update_in_nodal_fd(const unsigned& i) {}
1723
1724 /// Function called within the finite difference loop for
1725 /// nodal data after the i-th nodal values is reset.
1726 /// The default behaviour is to call the update function.
1727 virtual inline void reset_in_nodal_fd(const unsigned& i)
1728 {
1730 }
1731
1732
1733 /// Add the elemental contribution to the jacobian matrix.
1734 /// and the residuals vector. Note that
1735 /// this function will NOT initialise the residuals vector or the jacobian
1736 /// matrix. It must be called after the residuals vector and
1737 /// jacobian matrix have been initialised to zero. The default
1738 /// is to use finite differences to calculate the jacobian
1740 DenseMatrix<double>& jacobian)
1741 {
1742 // Add the contribution to the residuals
1744 // Allocate storage for the full residuals (residuals of entire element)
1745 unsigned n_dof = ndof();
1747 // Get the residuals for the entire element
1749 // Calculate the contributions from the internal dofs
1750 //(finite-difference the lot by default)
1752 // Calculate the contributions from the external dofs
1753 //(finite-difference the lot by default)
1755 // Calculate the contributions from the nodal dofs
1757 }
1758
1759 public:
1760 /// Function pointer for function that computes vector-valued
1761 /// steady "exact solution" \f$ {\bf f}({\bf x}) \f$
1762 /// as \f$ \mbox{\tt fct}({\bf x}, {\bf f}) \f$.
1765
1766 /// Function pointer for function that computes Vector-valued
1767 /// time-dependent function \f$ {\bf f}(t,{\bf x}) \f$
1768 /// as \f$ \mbox{\tt fct}(t, {\bf x}, {\bf f}) \f$.
1769 typedef void (*UnsteadyExactSolutionFctPt)(const double&,
1770 const Vector<double>&,
1772
1773 /// Tolerance below which the jacobian is considered singular
1775
1776 /// Boolean that if set to true allows a negative jacobian
1777 /// in the transform between global and local coordinates (negative surface
1778 /// area = left-handed coordinate system).
1780
1781 /// Static boolean to suppress output while checking
1782 /// for inverted elements
1784
1785 /// Constructor
1788 Integral_pt(0),
1789 Node_pt(0),
1790 Nodal_local_eqn(0),
1791 Nnode(0),
1793 Nodal_dimension(0),
1795 Macro_elem_pt(0)
1796 {
1797 }
1798
1799 /// The destructor cleans up the static memory allocated
1800 /// for shape function storage. Internal and external data get
1801 /// wiped by the GeneralisedElement destructor; nodes get
1802 /// killed in mesh destructor.
1803 virtual ~FiniteElement();
1804
1805 /// Broken copy constructor
1807
1808 /// Broken assignment operator
1809 // Commented out broken assignment operator because this can lead to a
1810 // conflict warning when used in the virtual inheritence hierarchy.
1811 // Essentially the compiler doesn't realise that two separate
1812 // implementations of the broken function are the same and so, quite
1813 // rightly, it shouts.
1814 /*void operator=(const FiniteElement&) = delete;*/
1815
1816 /// Check whether the local coordinate are valid or not
1818 {
1819 throw OomphLibError(
1820 "local_coord_is_valid is not implemented for this element\n",
1823 return true;
1824 }
1825
1826 /// Adjust local coordinates so that they're located inside
1827 /// the element
1829 {
1830 throw OomphLibError("move_local_coords_back_into_element() is not "
1831 "implemented for this element\n",
1834 }
1835
1836
1837 /// Compute centre of gravity of all nodes and radius of node that
1838 /// is furthest from it. Used to assess approximately if a point
1839 /// is likely to be contained with an element in locate_zeta-like
1840 /// operations
1842 Vector<double>& cog, double& max_radius) const;
1843
1844 /// Get local coordinates of node j in the element; vector
1845 /// sets its own size (broken virtual)
1846 virtual void local_coordinate_of_node(const unsigned& j,
1847 Vector<double>& s) const
1848 {
1849 throw OomphLibError(
1850 "local_coordinate_of_node(...) is not implemented for this element\n",
1853 }
1854
1855 /// Get the local fraction of the node j in the element
1856 /// A dumb, but correct default implementation is provided.
1857 virtual void local_fraction_of_node(const unsigned& j,
1859
1860 /// Get the local fraction of any node in the n-th position
1861 /// in a one dimensional expansion along the i-th local coordinate
1862 virtual double local_one_d_fraction_of_node(const unsigned& n1d,
1863 const unsigned& i)
1864 {
1865 std::string error_message =
1866 "local one_d_fraction_of_node is not implemented for this element\n";
1867 error_message +=
1868 "It only makes sense for elements that use tensor-product expansions\n";
1869
1870 throw OomphLibError(
1872 }
1873
1874 /// Set pointer to macro element -- can be overloaded in derived
1875 /// elements to perform additional tasks
1880
1881 /// Access function to pointer to macro element
1883 {
1884 return Macro_elem_pt;
1885 }
1886
1887 /// Global coordinates as function of local coordinates.
1888 /// Either via FE representation or via macro-element (if Macro_elem_pt!=0)
1889 void get_x(const Vector<double>& s, Vector<double>& x) const
1890 {
1891 // If there is no macro element then return interpolated x
1892 if (Macro_elem_pt == 0)
1893 {
1894 interpolated_x(s, x);
1895 }
1896 // Otherwise call the macro element representation
1897 else
1898 {
1900 }
1901 }
1902
1903
1904 /// Global coordinates as function of local coordinates
1905 /// at previous time "level" t (t=0: present; t>0: previous).
1906 /// Either via FE representation of QElement or
1907 /// via macro-element (if Macro_elem_pt!=0).
1908 void get_x(const unsigned& t, const Vector<double>& s, Vector<double>& x)
1909 {
1910 // Get timestepper from first node
1912
1913 // Number of previous values
1914 const unsigned nprev = time_stepper_pt->nprev_values();
1915
1916 // If t > nprev_values(), we're not dealing with a previous value
1917 // but a generalised history value -- this cannot be recovered from
1918 // macro element but must be determined by finite element interpolation
1919
1920 // If there is no macro element, or we're dealing with a generalised
1921 // history value then use the FE representation
1922 if ((Macro_elem_pt == 0) || (t > nprev))
1923 {
1924 interpolated_x(t, s, x);
1925 }
1926 // Otherwise use the macro element representation
1927 else
1928 {
1930 }
1931 }
1932
1933
1934 /// Global coordinates as function of local coordinates
1935 /// using macro element representation.
1936 /// (Broken virtual --- this must be overloaded in specific geometric
1937 /// element classes)
1939 Vector<double>& x) const
1940 {
1941 throw OomphLibError(
1942 "get_x_from_macro_element(...) is not implemented for this element\n",
1945 }
1946
1947 /// Global coordinates as function of local coordinates
1948 /// at previous time "level" t (t=0: present; t>0: previous).
1949 /// using macro element representation
1950 /// (Broken virtual -- overload in specific geometric element class
1951 /// if you want to use this functionality.)
1952 virtual void get_x_from_macro_element(const unsigned& t,
1953 const Vector<double>& s,
1954 Vector<double>& x)
1955 {
1956 throw OomphLibError(
1957 "get_x_from_macro_element(...) is not implemented for this element\n",
1960 }
1961
1962
1963 /// Set the spatial integration scheme
1964 virtual void set_integration_scheme(Integral* const& integral_pt);
1965
1966 /// Return the pointer to the integration scheme (const version)
1967 Integral* const& integral_pt() const
1968 {
1969 return Integral_pt;
1970 }
1971
1972 /// Calculate the geometric shape functions
1973 /// at local coordinate s. This function must be overloaded for each
1974 /// specific geometric element.
1975 virtual void shape(const Vector<double>& s, Shape& psi) const = 0;
1976
1977 /// Return the geometric shape function at the ipt-th integration
1978 /// point
1979 virtual void shape_at_knot(const unsigned& ipt, Shape& psi) const;
1980
1981 /// Function to compute the geometric shape functions and
1982 /// derivatives w.r.t. local coordinates at local coordinate s.
1983 /// This function must be overloaded for each specific geometric element.
1984 /// (Broken virtual function --- specifies the interface)
1985 virtual void dshape_local(const Vector<double>& s,
1986 Shape& psi,
1987 DShape& dpsids) const
1988 {
1989 throw OomphLibError(
1990 "dshape_local() is not implemented for this element\n",
1993 }
1994
1995 /// Return the geometric shape function and its derivative w.r.t.
1996 /// the local coordinates at the ipt-th integration point.
1997 virtual void dshape_local_at_knot(const unsigned& ipt,
1998 Shape& psi,
1999 DShape& dpsids) const;
2000
2001 /// Function to compute the geometric shape functions and also
2002 /// first and second derivatives w.r.t.
2003 /// local coordinates at local coordinate s. This function must
2004 /// be overloaded for each specific geometric element (if required).
2005 /// (Broken virtual function --- specifies the interface).
2006 /// Numbering:
2007 /// \b 1D:
2008 /// d2psids(i,0) = \f$ d^2 \psi_j / ds^2 \f$
2009 /// \b 2D:
2010 /// d2psids(i,0) = \f$ \partial^2 \psi_j / \partial s_0^2 \f$
2011 /// d2psids(i,1) = \f$ \partial^2 \psi_j / \partial s_1^2 \f$
2012 /// d2psids(i,2) = \f$ \partial^2 \psi_j / \partial s_0 \partial s_1 \f$
2013 /// \b 3D:
2014 /// d2psids(i,0) = \f$ \partial^2 \psi_j / \partial s_0^2 \f$
2015 /// d2psids(i,1) = \f$ \partial^2 \psi_j / \partial s_1^2 \f$
2016 /// d2psids(i,2) = \f$ \partial^2 \psi_j / \partial s_2^2 \f$
2017 /// d2psids(i,3) = \f$ \partial^2 \psi_j / \partial s_0 \partial s_1 \f$
2018 /// d2psids(i,4) = \f$ \partial^2 \psi_j / \partial s_0 \partial s_2 \f$
2019 /// d2psids(i,5) = \f$ \partial^2 \psi_j / \partial s_1 \partial s_2 \f$
2020 virtual void d2shape_local(const Vector<double>& s,
2021 Shape& psi,
2022 DShape& dpsids,
2023 DShape& d2psids) const
2024 {
2025 throw OomphLibError(
2026 "d2shape_local() is not implemented for this element\n",
2029 }
2030
2031 /// Return the geometric shape function and its first and
2032 /// second derivatives w.r.t.
2033 /// the local coordinates at the ipt-th integration point.
2034 /// Numbering:
2035 /// \b 1D:
2036 /// d2psids(i,0) = \f$ d^2 \psi_j / ds^2 \f$
2037 /// \b 2D:
2038 /// d2psids(i,0) = \f$ \partial^2 \psi_j / \partial s_0^2 \f$
2039 /// d2psids(i,1) = \f$ \partial^2 \psi_j / \partial s_1^2 \f$
2040 /// d2psids(i,2) = \f$ \partial^2 \psi_j / \partial s_0 \partial s_1 \f$
2041 /// \b 3D:
2042 /// d2psids(i,0) = \f$ \partial^2 \psi_j / \partial s_0^2 \f$
2043 /// d2psids(i,1) = \f$ \partial^2 \psi_j / \partial s_1^2 \f$
2044 /// d2psids(i,2) = \f$ \partial^2 \psi_j / \partial s_2^2 \f$
2045 /// d2psids(i,3) = \f$ \partial^2 \psi_j / \partial s_0 \partial s_1 \f$
2046 /// d2psids(i,4) = \f$ \partial^2 \psi_j / \partial s_0 \partial s_2 \f$
2047 /// d2psids(i,5) = \f$ \partial^2 \psi_j / \partial s_1 \partial s_2 \f$
2048 virtual void d2shape_local_at_knot(const unsigned& ipt,
2049 Shape& psi,
2050 DShape& dpsids,
2051 DShape& d2psids) const;
2052
2053 /// Return the Jacobian of mapping from local to global
2054 /// coordinates at local position s.
2055 virtual double J_eulerian(const Vector<double>& s) const;
2056
2057 /// Return the Jacobian of the mapping from local to global
2058 /// coordinates at the ipt-th integration point
2059 virtual double J_eulerian_at_knot(const unsigned& ipt) const;
2060
2061 /// Check that Jacobian of mapping between local and Eulerian
2062 /// coordinates at all integration points is positive.
2063 void check_J_eulerian_at_knots(bool& passed) const;
2064
2065 /// Helper function used to check for singular or negative
2066 /// Jacobians in the transform from local to global or Lagrangian
2067 /// coordinates.
2068 void check_jacobian(const double& jacobian) const;
2069
2070 /// Compute the geometric shape functions and also
2071 /// first derivatives w.r.t. global coordinates at local coordinate s;
2072 /// Returns Jacobian of mapping from global to local coordinates.
2073 double dshape_eulerian(const Vector<double>& s,
2074 Shape& psi,
2075 DShape& dpsidx) const;
2076
2077 /// Return the geometric shape functions and also first
2078 /// derivatives w.r.t. global coordinates at the ipt-th integration point.
2079 virtual double dshape_eulerian_at_knot(const unsigned& ipt,
2080 Shape& psi,
2081 DShape& dpsidx) const;
2082
2083 /// Compute the geometric shape functions (psi) and first derivatives
2084 /// w.r.t. global coordinates (dpsidx) at the ipt-th integration point.
2085 /// Return the determinant of the jacobian of the mapping (detJ).
2086 /// Additionally calculate the derivatives of both "detJ" and "dpsidx"
2087 /// w.r.t. the nodal coordinates.
2088 virtual double dshape_eulerian_at_knot(
2089 const unsigned& ipt,
2090 Shape& psi,
2091 DShape& dpsi,
2094
2095 /// Compute the geometric shape functions and also first
2096 /// and second derivatives w.r.t. global coordinates at local coordinate s;
2097 /// Returns Jacobian of mapping from global to local coordinates.
2098 /// Numbering:
2099 /// \b 1D:
2100 /// d2psidx(i,0) = \f$ d^2 \psi_j / d x^2 \f$
2101 /// \b 2D:
2102 /// d2psidx(i,0) = \f$ \partial^2 \psi_j / \partial x_0^2 \f$
2103 /// d2psidx(i,1) = \f$ \partial^2 \psi_j / \partial x_1^2 \f$
2104 /// d2psidx(i,2) = \f$ \partial^2 \psi_j / \partial x_0 \partial x_1 \f$
2105 /// \b 3D:
2106 /// d2psidx(i,0) = \f$ \partial^2 \psi_j / \partial x_0^2 \f$
2107 /// d2psidx(i,1) = \f$ \partial^2 \psi_j / \partial x_1^2 \f$
2108 /// d2psidx(i,2) = \f$ \partial^2 \psi_j / \partial x_2^2 \f$
2109 /// d2psidx(i,3) = \f$ \partial^2 \psi_j / \partial x_0 \partial x_1 \f$
2110 /// d2psidx(i,4) = \f$ \partial^2 \psi_j / \partial x_0 \partial x_2 \f$
2111 /// d2psidx(i,5) = \f$ \partial^2 \psi_j / \partial x_1 \partial x_2 \f$
2112 double d2shape_eulerian(const Vector<double>& s,
2113 Shape& psi,
2114 DShape& dpsidx,
2115 DShape& d2psidx) const;
2116
2117
2118 /// Return the geometric shape functions and also first
2119 /// and second derivatives w.r.t. global coordinates at ipt-th integration
2120 /// point.
2121 /// Numbering:
2122 /// \b 1D:
2123 /// d2psidx(i,0) = \f$ d^2 \psi_j / d s^2 \f$
2124 /// \b 2D:
2125 /// d2psidx(i,0) = \f$ \partial^2 \psi_j / \partial x_0^2 \f$
2126 /// d2psidx(i,1) = \f$ \partial^2 \psi_j / \partial x_1^2 \f$
2127 /// d2psidx(i,2) = \f$ \partial^2 \psi_j / \partial x_0 \partial x_1 \f$
2128 /// \b 3D:
2129 /// d2psidx(i,0) = \f$ \partial^2 \psi_j / \partial x_0^2 \f$
2130 /// d2psidx(i,1) = \f$ \partial^2 \psi_j / \partial x_1^2 \f$
2131 /// d2psidx(i,2) = \f$ \partial^2 \psi_j / \partial x_2^2 \f$
2132 /// d2psidx(i,3) = \f$ \partial^2 \psi_j / \partial x_0 \partial x_1 \f$
2133 /// d2psidx(i,4) = \f$ \partial^2 \psi_j / \partial x_0 \partial x_2 \f$
2134 /// d2psidx(i,5) = \f$ \partial^2 \psi_j / \partial x_1 \partial x_2 \f$
2135 virtual double d2shape_eulerian_at_knot(const unsigned& ipt,
2136 Shape& psi,
2137 DShape& dpsidx,
2138 DShape& d2psidx) const;
2139
2140 /// Assign the local equation numbers for Data stored at the nodes
2141 /// Virtual so that it can be overloaded by RefineableFiniteElements.
2142 /// If the boolean is true then the pointers to the degrees of freedom
2143 /// associated with each equation number are stored in Dof_pt
2144 virtual void assign_nodal_local_eqn_numbers(const bool& store_local_dof_pt);
2145
2146 /// Function to describe the local dofs of the element[s]. The
2147 /// ostream specifies the output stream to which the description is written;
2148 /// the string stores the currently assembled output that is ultimately
2149 /// written to the output stream by Data::describe_dofs(...); it is
2150 /// typically built up incrementally as we descend through the call
2151 /// hierarchy of this function when called from Problem::describe_dofs(...)
2152 virtual void describe_local_dofs(std::ostream& out,
2153 const std::string& current_string) const;
2154
2155 /// Function to describe the local dofs of the element[s]. The
2156 /// ostream specifies the output stream to which the description is written;
2157 /// the string stores the currently assembled output that is ultimately
2158 /// written to the output stream by Data::describe_dofs(...); it is
2159 /// typically built up incrementally as we descend through the call
2160 /// hierarchy of this function when called from Problem::describe_dofs(...)
2161 virtual void describe_nodal_local_dofs(
2162 std::ostream& out, const std::string& current_string) const;
2163
2164 /// Overloaded version of the calculation of the local equation
2165 /// numbers. If the boolean argument is true then pointers to the degrees
2166 /// of freedom associated with each equation number are stored locally
2167 /// in the array Dof_pt.
2169 const bool& store_local_dof_pt)
2170 {
2171 // GeneralisedElement's version assigns internal and external data
2174 // Need simply to add the nodal numbering scheme
2176 }
2177
2178 /// Return a pointer to the local node n
2179 Node*& node_pt(const unsigned& n)
2180 {
2181#ifdef RANGE_CHECKING
2182 if (n >= Nnode)
2183 {
2184 std::ostringstream error_message;
2185 error_message << "Range Error: " << n << " is not in the range (0,"
2186 << Nnode - 1 << ")";
2187 throw OomphLibError(error_message.str(),
2190 }
2191#endif
2192 return Node_pt[n];
2193 }
2194
2195 /// Return a pointer to the local node n (const version)
2196 Node* const& node_pt(const unsigned& n) const
2197 {
2198#ifdef RANGE_CHECKING
2199 if (n >= Nnode)
2200 {
2201 std::ostringstream error_message;
2202 error_message << "Range Error: " << n << " is not in the range (0,"
2203 << Nnode - 1 << ")";
2204 throw OomphLibError(error_message.str(),
2207 }
2208#endif
2209
2210 return Node_pt[n];
2211 }
2212
2213 /// Return the number of nodes
2214 unsigned nnode() const
2215 {
2216 return Nnode;
2217 }
2218
2219 /// Return the number of nodes along one edge of the element
2220 /// Default is to return zero --- must be overloaded by geometric
2221 /// elements
2222 virtual unsigned nnode_1d() const
2223 {
2224 return 0;
2225 }
2226
2227 /// Return the i-th coordinate at local node n. Do not use
2228 /// the hanging node representation.
2229 /// NOTE: Moved to cc file because of a possible compiler bug
2230 /// in gcc (yes, really!). The move to the cc file avoids inlining
2231 /// which appears to cause problems (only) when compiled with gcc
2232 /// and -O3; offensive "illegal read" is in optimised-out section
2233 /// of code and data that is allegedly illegal is readily readable
2234 /// (by other means) just before this function is called so I can't
2235 /// really see how we could possibly be responsible for this...
2236 double raw_nodal_position(const unsigned& n, const unsigned& i) const;
2237 /* { */
2238 /* /\* oomph_info << "n: "<< n << std::endl; *\/ */
2239 /* /\* oomph_info << "i: "<< i << std::endl; *\/ */
2240 /* /\* oomph_info << "node_pt(n): "<< node_pt(n) << std::endl; *\/ */
2241 /* /\* oomph_info << "node_pt(n)->x(i): "<< node_pt(n)->x(i) << std::endl;
2242 * *\/ */
2243 /* double tmp=node_pt(n)->x(i); */
2244 /* //oomph_info << "tmp: "<< tmp << std::endl; */
2245 /* return tmp; // node_pt(n)->x(i); */
2246 /* } */
2247
2248 /// Return the i-th coordinate at local node n, at time level t
2249 /// (t=0: present; t>0: previous time level).
2250 /// Do not use the hanging node representation.
2251 double raw_nodal_position(const unsigned& t,
2252 const unsigned& n,
2253 const unsigned& i) const
2254 {
2255 return node_pt(n)->x(t, i);
2256 }
2257
2258 /// Return the i-th component of nodal velocity: dx/dt at local node
2259 /// n. Do not use the hanging node representation.
2260 double raw_dnodal_position_dt(const unsigned& n, const unsigned& i) const
2261 {
2262 return node_pt(n)->dx_dt(i);
2263 }
2264
2265 /// Return the i-th component of j-th derivative of nodal position:
2266 /// d^jx/dt^j at node n. Do not use the hanging node representation.
2267 double raw_dnodal_position_dt(const unsigned& n,
2268 const unsigned& j,
2269 const unsigned& i) const
2270 {
2271 return node_pt(n)->dx_dt(j, i);
2272 }
2273
2274 /// Return the value of the k-th type of the i-th positional variable
2275 /// at the local node n. Do not use the hanging node representation.
2276 double raw_nodal_position_gen(const unsigned& n,
2277 const unsigned& k,
2278 const unsigned& i) const
2279 {
2280 return node_pt(n)->x_gen(k, i);
2281 }
2282
2283 /// Return the generalised nodal position (type k, i-th variable)
2284 /// at previous timesteps at local node n. Do not use the hanging node
2285 /// representation.
2286 double raw_nodal_position_gen(const unsigned& t,
2287 const unsigned& n,
2288 const unsigned& k,
2289 const unsigned& i) const
2290 {
2291 return node_pt(n)->x_gen(t, k, i);
2292 }
2293
2294 /// i-th component of time derivative (velocity) of the
2295 /// generalised position, dx(k,i)/dt at local node n.
2296 /// `Type': k; Coordinate direction: i. Do not use the hanging node
2297 /// representation.
2298 double raw_dnodal_position_gen_dt(const unsigned& n,
2299 const unsigned& k,
2300 const unsigned& i) const
2301 {
2302 return node_pt(n)->dx_gen_dt(k, i);
2303 }
2304
2305 /// i-th component of j-th time derivative of the
2306 /// generalised position, dx(k,i)/dt at local node n.
2307 /// `Type': k; Coordinate direction: i. Do not use the hanging node
2308 /// representation.
2309 double raw_dnodal_position_gen_dt(const unsigned& j,
2310 const unsigned& n,
2311 const unsigned& k,
2312 const unsigned& i) const
2313 {
2314 return node_pt(n)->dx_gen_dt(j, k, i);
2315 }
2316
2317
2318 /// Return the i-th coordinate at local node n. If the
2319 /// node is hanging, the appropriate interpolation is handled by the
2320 /// position function in the Node class.
2321 double nodal_position(const unsigned& n, const unsigned& i) const
2322 {
2323 return node_pt(n)->position(i);
2324 }
2325
2326 /// Return the i-th coordinate at local node n, at time level t
2327 /// (t=0: present; t>0: previous time level)
2328 /// Returns suitably interpolated version for hanging nodes.
2329 double nodal_position(const unsigned& t,
2330 const unsigned& n,
2331 const unsigned& i) const
2332 {
2333 return node_pt(n)->position(t, i);
2334 }
2335
2336 /// Return the i-th component of nodal velocity: dx/dt at local node n.
2337 double dnodal_position_dt(const unsigned& n, const unsigned& i) const
2338 {
2339 return node_pt(n)->dposition_dt(i);
2340 }
2341
2342 /// Return the i-th component of j-th derivative of nodal position:
2343 /// d^jx/dt^j at node n.
2344 double dnodal_position_dt(const unsigned& n,
2345 const unsigned& j,
2346 const unsigned& i) const
2347 {
2348 return node_pt(n)->dposition_dt(j, i);
2349 }
2350
2351 /// Return the value of the k-th type of the i-th positional variable
2352 /// at the local node n.
2353 double nodal_position_gen(const unsigned& n,
2354 const unsigned& k,
2355 const unsigned& i) const
2356 {
2357 return node_pt(n)->position_gen(k, i);
2358 }
2359
2360 /// Return the generalised nodal position (type k, i-th variable)
2361 /// at previous timesteps at local node n
2362 double nodal_position_gen(const unsigned& t,
2363 const unsigned& n,
2364 const unsigned& k,
2365 const unsigned& i) const
2366 {
2367 return node_pt(n)->position_gen(t, k, i);
2368 }
2369
2370 /// i-th component of time derivative (velocity) of the
2371 /// generalised position, dx(k,i)/dt at local node n.
2372 /// `Type': k; Coordinate direction: i.
2373 double dnodal_position_gen_dt(const unsigned& n,
2374 const unsigned& k,
2375 const unsigned& i) const
2376 {
2377 return node_pt(n)->dposition_gen_dt(k, i);
2378 }
2379
2380 /// i-th component of j-th time derivative of the
2381 /// generalised position, dx(k,i)/dt at local node n.
2382 /// `Type': k; Coordinate direction: i.
2383 double dnodal_position_gen_dt(const unsigned& j,
2384 const unsigned& n,
2385 const unsigned& k,
2386 const unsigned& i) const
2387 {
2388 return node_pt(n)->dposition_gen_dt(j, k, i);
2389 }
2390
2391
2392 /// Compute derivatives of elemental residual vector with respect
2393 /// to nodal coordinates. Default implementation by FD can be overwritten
2394 /// for specific elements.
2395 /// dresidual_dnodal_coordinates(l,i,j) = d res(l) / dX_{ij}
2398
2399 /// This is an empty function that establishes a uniform
2400 /// interface for all (derived) elements that involve time-derivatives.
2401 /// Such elements are/should be implemented in ALE form to allow
2402 /// mesh motions. The additional expense associated with the
2403 /// computation of the mesh velocities is, of course, superfluous
2404 /// if the elements are used in problems in which the mesh is
2405 /// stationary. This function should therefore be overloaded
2406 /// in all derived elements that are formulated in ALE form
2407 /// to suppress the computation of the mesh velocities.
2408 /// The user disables the ALE functionality at his/her own risk!
2409 /// If the mesh does move after all, then the results will be wrong.
2410 /// Here we simply issue a warning message stating that the empty
2411 /// function has been called.
2412 virtual void disable_ALE()
2413 {
2414 std::ostringstream warn_message;
2416 << "Warning: You have just called the default (empty) function \n\n"
2417 << " FiniteElement::disable_ALE() \n\n"
2418 << "This suggests that you've either tried to call it for an element\n"
2419 << "that \n"
2420 << "(1) does not involve time-derivatives (e.g. a Poisson element) \n"
2421 << "(2) an element for which the time-derivatives aren't implemented \n"
2422 << " in ALE form \n"
2423 << "(3) an element for which the ALE form of the equations can't be \n"
2424 << " be disabled (yet).\n";
2426 warn_message.str(), "Problem::disable_ALE()", OOMPH_EXCEPTION_LOCATION);
2427 }
2428
2429
2430 /// (Re-)enable ALE, i.e. take possible mesh motion into account
2431 /// when evaluating the time-derivative. This function is empty
2432 /// and simply establishes a common interface for all derived
2433 /// elements that are formulated in ALE form.
2434 virtual void enable_ALE()
2435 {
2436 std::ostringstream warn_message;
2438 << "Warning: You have just called the default (empty) function \n\n"
2439 << " FiniteElement::enable_ALE() \n\n"
2440 << "This suggests that you've either tried to call it for an element\n"
2441 << "that \n"
2442 << "(1) does not involve time-derivatives (e.g. a Poisson element) \n"
2443 << "(2) an element for which the time-derivatives aren't implemented \n"
2444 << " in ALE form \n"
2445 << "(3) an element for which the ALE form of the equations can't be \n"
2446 << " be disabled (yet)\n"
2447 << "(4) an element for which this function has not been (properly) \n "
2448 << " implemented. This is likely to be a bug!\n ";
2450 warn_message.str(), "Problem::enable_ALE()", OOMPH_EXCEPTION_LOCATION);
2451 }
2452
2453 /// Number of values that must be stored at local node n by
2454 /// the element. The default is 0, until over-ridden by a particular
2455 /// element. For example, a Poisson equation requires only one value to be
2456 /// stored at each node; 2D Navier--Stokes equations require two values
2457 /// (velocity components) to be stored at each Node (provided that the
2458 /// pressure interpolation is discontinuous).
2459 virtual unsigned required_nvalue(const unsigned& n) const
2460 {
2462 }
2463
2464 /// Return the number of coordinate types that the element requires
2465 /// to interpolate the geometry between
2466 /// the nodes. For Lagrange elements it is 1.
2467 unsigned nnodal_position_type() const
2468 {
2469 return Nnodal_position_type;
2470 }
2471
2472 /// Return boolean to indicate if any of the element's nodes
2473 /// are geometrically hanging.
2475 {
2476 unsigned nnod = nnode();
2477 for (unsigned j = 0; j < nnod; j++)
2478 {
2479 if (node_pt(j)->is_hanging())
2480 {
2481 return true;
2482 }
2483 }
2484 return false;
2485 }
2486
2487 /// Return the required Eulerian dimension of the nodes in this element
2488 unsigned nodal_dimension() const
2489 {
2490 return Nodal_dimension;
2491 }
2492
2493 /// Return the number of vertex nodes in this element. Broken virtual
2494 /// function in "pure" finite elements.
2495 virtual unsigned nvertex_node() const
2496 {
2497 std::string error_msg = "Not implemented for FiniteElement.";
2498 throw OomphLibError(
2500 }
2501
2502 /// Pointer to the j-th vertex node in the element. Broken virtual
2503 /// function in "pure" finite elements.
2504 virtual Node* vertex_node_pt(const unsigned& j) const
2505 {
2506 std::string error_msg = "Not implemented for FiniteElement.";
2507 throw OomphLibError(
2509 }
2510
2511 /// Construct the local node n and return a pointer to the newly
2512 /// created node object.
2513 virtual Node* construct_node(const unsigned& n)
2514 {
2515 // Create a node and assign it to the local node pointer
2516 // The dimension and number of values are taken from internal element data
2517 node_pt(n) =
2519 // Now return a pointer to the node, so that the mesh can use it
2520 return node_pt(n);
2521 }
2522
2523 /// Construct the local node n, including
2524 /// storage for history values required by timestepper, and return a pointer
2525 /// to the newly created node object.
2526 virtual Node* construct_node(const unsigned& n,
2528 {
2529 // Create a node and assign it to the local node pointer.
2530 // The dimension and number of values are taken from internal element data
2535 // Now return a pointer to the node, so that the mesh can find it
2536 return node_pt(n);
2537 }
2538
2539 /// Construct the local node n as a boundary node;
2540 /// that is a node that MAY be placed on a mesh boundary
2541 /// and return a pointer to the newly created node object.
2542 virtual Node* construct_boundary_node(const unsigned& n)
2543 {
2544 // Create a node and assign it to the local node pointer
2545 // The dimension and number of values are taken from internal element data
2548 // Now return a pointer to the node, so that the mesh can use it
2549 return node_pt(n);
2550 }
2551
2552 /// Construct the local node n, including
2553 /// storage for history values required by timestepper,
2554 /// as a boundary node; that is a node that MAY be placed on a mesh
2555 /// boundary and return a pointer to the newly created node object.
2556 virtual Node* construct_boundary_node(const unsigned& n,
2558 {
2559 // Create a node and assign it to the local node pointer.
2560 // The dimension and number of values are taken from internal element data
2565 // Now return a pointer to the node, so that the mesh can find it
2566 return node_pt(n);
2567 }
2568
2569 /// Return the number of the node *node_pt if this node
2570 /// is in the element, else return -1;
2571 int get_node_number(Node* const& node_pt) const;
2572
2573
2574 /// If there is a node at this local coordinate, return the pointer
2575 /// to the node
2576 virtual Node* get_node_at_local_coordinate(const Vector<double>& s) const;
2577
2578 /// Return the i-th value stored at local node n
2579 /// but do NOT take hanging nodes into account
2580 double raw_nodal_value(const unsigned& n, const unsigned& i) const
2581 {
2582 return node_pt(n)->raw_value(i);
2583 }
2584
2585 /// Return the i-th value stored at local node n, at time level t
2586 /// (t=0: present; t>0 previous timesteps), but do NOT take hanging nodes
2587 /// into account
2588 double raw_nodal_value(const unsigned& t,
2589 const unsigned& n,
2590 const unsigned& i) const
2591 {
2592 return node_pt(n)->raw_value(t, i);
2593 }
2594
2595 /// Return the i-th value stored at local node n.
2596 /// Produces suitably interpolated values for hanging nodes.
2597 double nodal_value(const unsigned& n, const unsigned& i) const
2598 {
2599 return node_pt(n)->value(i);
2600 }
2601
2602 /// Return the i-th value stored at local node n, at time level t
2603 /// (t=0: present; t>0 previous timesteps). Produces suitably interpolated
2604 /// values for hanging nodes.
2605 double nodal_value(const unsigned& t,
2606 const unsigned& n,
2607 const unsigned& i) const
2608 {
2609 return node_pt(n)->value(t, i);
2610 }
2611
2612 /// Return the spatial dimension of the element, i.e.
2613 /// the number of local coordinates required to parametrise its
2614 /// geometry.
2615 unsigned dim() const
2616 {
2617 return Elemental_dimension;
2618 }
2619
2620 /// Return the geometry type of the element (either Q or T usually).
2622 {
2623 std::string err = "Broken virtual function.";
2624 throw OomphLibError(
2626 }
2627
2628 /// Return FE interpolated coordinate x[i] at local coordinate s
2629 virtual double interpolated_x(const Vector<double>& s,
2630 const unsigned& i) const;
2631
2632 /// Return FE interpolated coordinate x[i] at local coordinate s
2633 /// at previous timestep t (t=0: present; t>0: previous timestep)
2634 virtual double interpolated_x(const unsigned& t,
2635 const Vector<double>& s,
2636 const unsigned& i) const;
2637
2638 /// Return FE interpolated position x[] at local coordinate s as Vector
2639 virtual void interpolated_x(const Vector<double>& s,
2640 Vector<double>& x) const;
2641
2642 /// Return FE interpolated position x[] at local coordinate s
2643 /// at previous timestep t as Vector (t=0: present; t>0: previous timestep)
2644 virtual void interpolated_x(const unsigned& t,
2645 const Vector<double>& s,
2646 Vector<double>& x) const;
2647
2648 /// Return t-th time-derivative of the
2649 /// i-th FE-interpolated Eulerian coordinate at
2650 /// local coordinate s.
2651 virtual double interpolated_dxdt(const Vector<double>& s,
2652 const unsigned& i,
2653 const unsigned& t);
2654
2655 /// Compte t-th time-derivative of the
2656 /// FE-interpolated Eulerian coordinate vector at
2657 /// local coordinate s.
2658 virtual void interpolated_dxdt(const Vector<double>& s,
2659 const unsigned& t,
2661
2662 /// A standard FiniteElement is fixed, so there are no geometric
2663 /// data when viewed in its GeomObject incarnation
2664 inline unsigned ngeom_data() const
2665 {
2666 return 0;
2667 }
2668
2669 /// A standard FiniteElement is fixed, so there are no geometric
2670 /// data when viewed in its GeomObject incarnation
2671 inline Data* geom_data_pt(const unsigned& j)
2672 {
2673 return 0;
2674 }
2675
2676 /// Return the parametrised position of the FiniteElement in
2677 /// its incarnation as a GeomObject, r(zeta).
2678 /// The position is given by the Eulerian coordinate and the intrinsic
2679 /// coordinate (zeta) is the local coordinate of the element (s).
2681 {
2682 this->interpolated_x(zeta, r);
2683 }
2684
2685 /// Return the parametrised position of the FiniteElement
2686 /// in its GeomObject incarnation:
2687 /// r(zeta). The position is given by the Eulerian coordinate and the
2688 /// intrinsic coordinate (zeta) is the local coordinate of the element (s)
2689 /// This version of the function returns the position as a function
2690 /// of time t=0: current time; t>0: previous
2691 /// timestep. Works for t=0 but needs to be overloaded
2692 /// if genuine time-dependence is required.
2693 void position(const unsigned& t,
2694 const Vector<double>& zeta,
2695 Vector<double>& r) const
2696 {
2697 this->interpolated_x(t, zeta, r);
2698 }
2699
2700 /// Return the t-th time derivative of the
2701 /// parametrised position of the FiniteElement
2702 /// in its GeomObject incarnation:
2703 /// \f$ \frac{d^{t} dr(zeta)}{d t^{t}} \f$.
2704 /// Call the t-th time derivative of the FE-interpolated Eulerian coordinate
2706 const unsigned& t,
2708 {
2709 this->interpolated_dxdt(zeta, t, drdt);
2710 }
2711
2712 /// Specify the values of the "global" intrinsic coordinate, zeta,
2713 /// of a compound geometric object (a mesh of elements) when
2714 /// the element is viewied as a sub-geometric object.
2715 /// The default assumption is that the element will be
2716 /// treated as a sub-geometric object in a bulk Mesh of other elements
2717 /// (geometric objects). The "global" coordinate of the compound geometric
2718 /// object is simply the Eulerian coordinate, x.
2719 /// The second default assumption is that the coordinate zeta will
2720 /// be stored at the nodes and interpolated using the shape functions
2721 /// of the element. This function returns the value of zeta stored at
2722 /// local node n, where k is the type of coordinate and i is the
2723 /// coordinate direction. The function is virtual so that it can
2724 /// be overloaded by different types of element: FaceElements
2725 /// and SolidFiniteElements
2726 virtual double zeta_nodal(const unsigned& n,
2727 const unsigned& k,
2728 const unsigned& i) const
2729 {
2730 // By default return the value for nodal_position_gen
2731 return nodal_position_gen(n, k, i);
2732 }
2733
2734
2735 /// Calculate the interpolated value of zeta, the intrinsic
2736 /// coordinate of the element when viewed as a compound geometric object
2737 /// within a Mesh as a function of the local coordinate of the element, s.
2738 /// The default assumption is the zeta is interpolated using the shape
2739 /// functions of the element with the values given by zeta_nodal(). A
2740 /// MacroElement representation of the intrinsic coordinate parametrised by
2741 /// the local coordinate s is used if available. Choosing the MacroElement
2742 /// representation of zeta (Eulerian x by default) allows a correspondence
2743 /// to be established between elements on different Meshes covering the same
2744 /// curvilinear domain in cases where one element is much coarser than the
2745 /// other.
2747
2748 /// For a given value of zeta, the "global" intrinsic coordinate of
2749 /// a mesh of FiniteElements represented as a compound geometric object,
2750 /// find the local coordinate in this element that corresponds to the
2751 /// requested value of zeta.
2752 /// If zeta cannot be located in this element, geom_object_pt is set
2753 /// to NULL. If zeta is located in this element, we return its "this"
2754 /// pointer.
2755 /// By default don't use any value passed in to the local coordinate s
2756 /// as the initial guess in the Newton method
2757 void locate_zeta(const Vector<double>& zeta,
2758 GeomObject*& geom_object_pt,
2760 const bool& use_coordinate_as_initial_guess = false);
2761
2762
2763 /// Update the positions of all nodes in the element using
2764 /// each node update function. The default implementation may
2765 /// be overloaded so that more efficient versions can be written
2766 virtual void node_update();
2767
2768 /// The purpose of this function is to identify all possible
2769 /// Data that can affect the fields interpolated by the FiniteElement.
2770 /// The information will typically be used in interaction problems in
2771 /// which the FiniteElement provides a forcing term for an
2772 /// ElementWithExternalElement. The Data must be provided as
2773 /// \c paired_load data containing
2774 /// - the pointer to a Data object
2775 /// and
2776 /// - the index of the value in that Data object
2777 /// .
2778 /// The generic implementation (should be overloaded in more specific
2779 /// applications) is to include all nodal and internal Data stored in
2780 /// the FiniteElement. The geometric data, which includes the positions
2781 /// of SolidNodes, is treated separately by the function
2782 /// \c identify_geometric_data()
2784 std::set<std::pair<Data*, unsigned>>& paired_field_data);
2785
2786
2787 /// The purpose of this
2788 /// function is to identify all \c Data objects that affect the elements'
2789 /// geometry. This function is implemented as an empty virtual
2790 /// function since it can only be implemented in conjunction
2791 /// with a node-update strategy. A specific implementation
2792 /// is provided in the ElementWithMovingNodes class.
2793 virtual void identify_geometric_data(std::set<Data*>& geometric_data_pt) {}
2794
2795
2796 /// Min value of local coordinate
2797 virtual double s_min() const
2798 {
2799 throw OomphLibError("s_min() isn't implemented for this element\n",
2802 // Dummy return
2803 return 0.0;
2804 }
2805
2806 /// Max. value of local coordinate
2807 virtual double s_max() const
2808 {
2809 throw OomphLibError("s_max() isn't implemented for this element\n",
2812 // Dummy return
2813 return 0.0;
2814 }
2815
2816 /// Calculate the size of the element (length, area, volume,...)
2817 /// in Eulerian computational
2818 /// coordinates. Use suitably overloaded compute_physical_size()
2819 /// function to compute the actual size (taking into account
2820 /// factors such as 2pi or radii the integrand) -- such function
2821 /// can only be implemented on an equation-by-equation basis.
2822 double size() const;
2823
2824
2825 /// Broken virtual
2826 /// function to compute the actual size (taking into account
2827 /// factors such as 2pi or radii the integrand) -- such function
2828 /// can only be implemented on an equation-by-equation basis.
2829 virtual double compute_physical_size() const
2830 {
2831 throw OomphLibError(
2832 "compute_physical_size() isn't implemented for this element\n",
2835 // Dummy return
2836 return 0.0;
2837 }
2838
2839 /// Virtual function to write the double precision numbers that
2840 /// appear in a single line of output into the data vector. Empty virtual,
2841 /// can be overloaded for specific elements; used e.g. by LineVisualiser.
2843 Vector<double>& data)
2844 {
2845 }
2846
2847 /// Output solution (as defined by point_output_data())
2848 /// at local cordinates s
2849 void point_output(std::ostream& outfile, const Vector<double>& s)
2850 {
2851 // Get point data
2852 Vector<double> data;
2853 this->point_output_data(s, data);
2854
2855 // Output
2856 unsigned n = data.size();
2857 for (unsigned i = 0; i < n; i++)
2858 {
2859 outfile << data[i] << " ";
2860 }
2861 }
2862
2863 /// Return the number of actual plot points for paraview
2864 /// plot with parameter nplot. Broken virtual; can be overloaded
2865 /// in specific elements.
2866 virtual unsigned nplot_points_paraview(const unsigned& nplot) const
2867 {
2868 throw OomphLibError(
2869 "This function hasn't been implemented for this element",
2872
2873 // Dummy unsigned
2874 return 0;
2875 }
2876
2877 /// Return the number of local sub-elements for paraview plot with
2878 /// parameter nplot. Broken virtual; can be overloaded
2879 /// in specific elements.
2880 virtual unsigned nsub_elements_paraview(const unsigned& nplot) const
2881 {
2882 throw OomphLibError(
2883 "This function hasn't been implemented for this element",
2886
2887 // Dummy unsigned
2888 return 0;
2889 }
2890
2891 /// Paraview output -- this outputs the coordinates at the plot
2892 /// points (for parameter nplot) to specified output file.
2893 void output_paraview(std::ofstream& file_out, const unsigned& nplot) const
2894 {
2895 // Decide the dimensions of the nodes
2896 unsigned nnod = nnode();
2897 if (nnod == 0) return;
2898 unsigned n = node_pt(0)->ndim();
2899
2900 // Vector for local coordinates
2901 Vector<double> s(n, 0.0);
2902
2903 // Vector for cartesian coordinates
2904 Vector<double> x(n, 0.0);
2905
2906 // Determine the total number of plotpoints
2907 unsigned plot = nplot_points_paraview(nplot);
2908
2909 // Loop over the local points
2910 for (unsigned j = 0; j < plot; j++)
2911 {
2912 // Determine where in the local element the point is
2913 this->get_s_plot(j, nplot, s);
2914
2915 // Update the cartesian coordinates vector
2916 this->interpolated_x(s, x);
2917
2918 // Print the global coordinates. Note: no whitespace after last
2919 // coordinate or paraview is very unhappy.
2920 for (unsigned i = 0; i < n - 1; i++)
2921 {
2922 file_out << x[i] << " ";
2923 }
2924 file_out << x[n - 1];
2925
2926 // Since unstructured grid always needs 3 components for each
2927 // point, output 0's by default
2928 switch (n)
2929 {
2930 case 1:
2931 file_out << " 0"
2932 << " 0" << std::endl;
2933 break;
2934
2935 case 2:
2936 file_out << " 0" << std::endl;
2937 break;
2938
2939 case 3:
2940 file_out << std::endl;
2941 break;
2942
2943 // Paraview can't handle more than 3 dimensions, output error
2944 default:
2945 throw OomphLibError(
2946 "Printing PlotPoint to .vtu failed; it has >3 dimensions.",
2949 }
2950 }
2951 }
2952
2953 /// Fill in the offset information for paraview plot. Broken virtual.
2954 /// Needs to be implemented for each new geometric element type; see
2955 /// http://www.vtk.org/VTK/img/file-formats.pdf
2957 std::ofstream& file_out, const unsigned& nplot, unsigned& counter) const
2958 {
2959 throw OomphLibError(
2960 "This function hasn't been implemented for this element",
2963 }
2964
2965 /// Return the paraview element type. Broken virtual.
2966 /// Needs to be implemented for each new geometric element type; see
2967 /// http://www.vtk.org/VTK/img/file-formats.pdf
2968 virtual void write_paraview_type(std::ofstream& file_out,
2969 const unsigned& nplot) const
2970 {
2971 throw OomphLibError(
2972 "This function hasn't been implemented for this element",
2975 }
2976
2977 /// Return the offsets for the paraview sub-elements. Broken
2978 /// virtual. Needs to be implemented for each new geometric element type;
2979 /// see http://www.vtk.org/VTK/img/file-formats.pdf
2980 virtual void write_paraview_offsets(std::ofstream& file_out,
2981 const unsigned& nplot,
2982 unsigned& offset_sum) const
2983 {
2984 throw OomphLibError(
2985 "This function hasn't been implemented for this element",
2988 }
2989
2990 /// Number of scalars/fields output by this element. Broken
2991 /// virtual. Needs to be implemented for each new specific element type.
2992 virtual unsigned nscalar_paraview() const
2993 {
2994 throw OomphLibError(
2995 "This function hasn't been implemented for this element",
2998
2999 // Dummy unsigned
3000 return 0;
3001 }
3002
3003 /// Write values of the i-th scalar field at the plot points. Broken
3004 /// virtual. Needs to be implemented for each new specific element type.
3005 virtual void scalar_value_paraview(std::ofstream& file_out,
3006 const unsigned& i,
3007 const unsigned& nplot) const
3008 {
3009 throw OomphLibError(
3010 "This function hasn't been implemented for this element",
3013 }
3014
3015 /// Write values of the i-th scalar field at the plot points. Broken
3016 /// virtual. Needs to be implemented for each new specific element type.
3018 std::ofstream& file_out,
3019 const unsigned& i,
3020 const unsigned& nplot,
3022 {
3023 throw OomphLibError(
3024 "This function hasn't been implemented for this element",
3027 }
3028
3029 /// Write values of the i-th scalar field at the plot points. Broken
3030 /// virtual. Needs to be implemented for each new specific element type.
3032 std::ofstream& file_out,
3033 const unsigned& i,
3034 const unsigned& nplot,
3035 const double& time,
3037 {
3038 throw OomphLibError(
3039 "This function hasn't been implemented for this element",
3042 }
3043
3044 /// Name of the i-th scalar field. Default implementation
3045 /// returns V1 for the first one, V2 for the second etc. Can (should!) be
3046 /// overloaded with more meaningful names in specific elements.
3047 virtual std::string scalar_name_paraview(const unsigned& i) const
3048 {
3049 return "V" + StringConversion::to_string(i);
3050 }
3051
3052 /// Output the element data --- typically the values at the
3053 /// nodes in a format suitable for post-processing.
3054 virtual void output(std::ostream& outfile)
3055 {
3056 throw OomphLibError(
3057 "Output function function hasn't been implemented for this element",
3060 }
3061
3062 /// Output the element data --- pass (some measure of)
3063 /// the number of plot points per element
3064 virtual void output(std::ostream& outfile, const unsigned& n_plot)
3065 {
3066 throw OomphLibError(
3067 "Output function function hasn't been implemented for this element",
3070 }
3071
3072 /// Output the element data at time step t. This is const because
3073 /// it is newly added and so can be done easily. Really all the
3074 /// output(...) functions should be const!
3075 virtual void output(const unsigned& t,
3076 std::ostream& outfile,
3077 const unsigned& n_plot) const
3078 {
3079 throw OomphLibError(
3080 "Output function function hasn't been implemented for this element",
3083 }
3084
3085 /// Output the element data --- typically the values at the
3086 /// nodes in a format suitable for post-processing.
3087 /// (C style output)
3088 virtual void output(FILE* file_pt)
3089 {
3090 throw OomphLibError("C-style otput function function hasn't been "
3091 "implemented for this element",
3094 }
3095
3096 /// Output the element data --- pass (some measure of)
3097 /// the number of plot points per element
3098 /// (C style output)
3099 virtual void output(FILE* file_pt, const unsigned& n_plot)
3100 {
3101 throw OomphLibError("C-style output function function hasn't been "
3102 "implemented for this element",
3105 }
3106
3107 /// Output an exact solution over the element.
3108 virtual void output_fct(
3109 std::ostream& outfile,
3110 const unsigned& n_plot,
3112 {
3113 throw OomphLibError(
3114 "Output function function hasn't been implemented for exact solution",
3117 }
3118
3119
3120 /// Output a time-dependent exact solution over the element.
3121 virtual void output_fct(
3122 std::ostream& outfile,
3123 const unsigned& n_plot,
3124 const double& time,
3126 {
3127 throw OomphLibError(
3128 "Output function function hasn't been implemented for exact solution",
3131 }
3132
3133 /// Output a time-dependent exact solution over the element.
3134 virtual void output_fct(std::ostream& outfile,
3135 const unsigned& n_plot,
3136 const double& time,
3137 const SolutionFunctorBase& exact_soln) const
3138 {
3139 throw OomphLibError(
3140 "Output function function hasn't been implemented for exact solution",
3143 }
3144
3145
3146 /// Get cector of local coordinates of plot point i (when plotting
3147 /// nplot points in each "coordinate direction").
3148 /// Generally these plot points will be uniformly spaced across the element.
3149 /// The optional final boolean flag (default: false) allows them to
3150 /// be shifted inwards to avoid duplication of plot point points between
3151 /// elements -- useful when they are used in locate_zeta, say.
3152 virtual void get_s_plot(const unsigned& i,
3153 const unsigned& nplot,
3155 const bool& shifted_to_interior = false) const
3156 {
3157 throw OomphLibError(
3158 "get_s_plot(...) is not implemented for this element\n",
3161 };
3162
3163 /// Return string for tecplot zone header (when plotting
3164 /// nplot points in each "coordinate direction")
3165 virtual std::string tecplot_zone_string(const unsigned& nplot) const
3166 {
3167 throw OomphLibError(
3168 "tecplot_zone_string(...) is not implemented for this element\n",
3171 return "dummy return";
3172 }
3173
3174 /// Add tecplot zone "footer" to output stream (when plotting
3175 /// nplot points in each "coordinate direction").
3176 /// Empty by default -- can be used, e.g., to add FE connectivity
3177 /// lists to elements that need it.
3178 virtual void write_tecplot_zone_footer(std::ostream& outfile,
3179 const unsigned& nplot) const {};
3180
3181 /// Add tecplot zone "footer" to C-style output. (when plotting
3182 /// nplot points in each "coordinate direction").
3183 /// Empty by default -- can be used, e.g., to add FE connectivity
3184 /// lists to elements that need it.
3186 const unsigned& nplot) const {};
3187
3188 /// Return total number of plot points (when plotting
3189 /// nplot points in each "coordinate direction")
3190 virtual unsigned nplot_points(const unsigned& nplot) const
3191 {
3192 throw OomphLibError(
3193 "nplot_points(...) is not implemented for this element",
3196 // Dummy return
3197 return 0;
3198 }
3199
3200
3201 /// Calculate the norm of the error and that of the exact solution.
3202 virtual void compute_error(
3204 double& error,
3205 double& norm)
3206 {
3207 std::string error_message = "compute_error undefined for this element \n";
3208 throw OomphLibError(
3210 }
3211
3212 /// Calculate the norm of the error and that of the exact solution.
3213 virtual void compute_error(
3215 const double& time,
3216 double& error,
3217 double& norm)
3218 {
3219 std::string error_message = "time-dependent compute_error ";
3220 error_message += "undefined for this element \n";
3221 throw OomphLibError(
3223 }
3224
3225 /// Given the exact solution \f$ {\bf f}({\bf x}) \f$ this function
3226 /// calculates the norm of the error and that of the exact solution.
3227 /// Version with vectors of norms and errors so that different variables'
3228 /// norms and errors can be returned individually
3229 virtual void compute_error(
3232 Vector<double>& norm)
3233 {
3234 std::string error_message = "compute_error undefined for this element \n";
3235 throw OomphLibError(
3237 }
3238
3239 /// Given the exact solution \f$ {\bf f}({\bf x}) \f$ this function
3240 /// calculates the norm of the error and that of the exact solution.
3241 /// Version with vectors of norms and errors so that different variables'
3242 /// norms and errors can be returned individually
3243 virtual void compute_error(
3245 const double& time,
3247 Vector<double>& norm)
3248 {
3249 std::string error_message = "time-dependent compute_error ";
3250 error_message += "undefined for this element \n";
3251 throw OomphLibError(
3253 }
3254
3255
3256 /// Plot the error when compared
3257 /// against a given exact solution \f$ {\bf f}({\bf x}) \f$.
3258 /// Also calculates the norm of the
3259 /// error and that of the exact solution.
3260 virtual void compute_error(
3261 std::ostream& outfile,
3263 double& error,
3264 double& norm)
3265 {
3266 std::string error_message = "compute_error undefined for this element \n";
3267 outfile << error_message;
3268
3269 throw OomphLibError(
3271 }
3272
3273 /// Plot the error when compared against a given time-dependent exact
3274 /// solution \f$ {\bf f}(t,{\bf x}) \f$. Also calculates the norm of the
3275 /// error and that of the exact solution.
3276 virtual void compute_error(
3277 std::ostream& outfile,
3279 const double& time,
3280 double& error,
3281 double& norm)
3282 {
3283 std::string error_message =
3284 "time-dependent compute_error undefined for this element \n";
3285 outfile << error_message;
3286
3287 throw OomphLibError(
3289 }
3290
3291 /// Plot the error when compared against a given exact solution
3292 /// \f$ {\bf f}({\bf x}) \f$. Also calculates the norm of the error and
3293 /// that of the exact solution.
3294 /// The version with vectors of norms and errors so that different
3295 /// variables' norms and errors can be returned individually
3296 virtual void compute_error(
3297 std::ostream& outfile,
3300 Vector<double>& norm)
3301 {
3302 std::string error_message = "compute_error undefined for this element \n";
3303 outfile << error_message;
3304
3305 throw OomphLibError(error_message,
3306 "FiniteElement::compute_error()",
3308 }
3309
3310 /// Plot the error when compared against a given time-dependent exact
3311 /// solution \f$ {\bf f}(t,{\bf x}) \f$. Also calculates the norm of the
3312 /// error and that of the exact solution.
3313 /// The version with vectors of norms and errors so that different
3314 /// variables' norms and errors can be returned individually
3315 virtual void compute_error(
3316 std::ostream& outfile,
3318 const double& time,
3320 Vector<double>& norm)
3321 {
3322 std::string error_message =
3323 "time-dependent compute_error undefined for this element \n";
3324 outfile << error_message;
3325
3326 throw OomphLibError(error_message,
3327 "FiniteElement::compute_error()",
3329 }
3330
3331 /// Plot the error when compared
3332 /// against a given exact solution \f$ {\bf f}({\bf x}) \f$.
3333 /// Also calculates the maximum absolute error
3334 virtual void compute_abs_error(
3335 std::ostream& outfile,
3337 double& error)
3338 {
3339 std::string error_message =
3340 "compute_abs_error undefined for this element \n";
3341 outfile << error_message;
3342
3343 throw OomphLibError(
3345 }
3346
3347 /// Evaluate integral of a Vector-valued function
3348 /// \f$ {\bf f}({\bf x}) \f$ over the element.
3350 Vector<double>& integral);
3351
3352
3353 /// Evaluate integral of a Vector-valued, time-dependent function
3354 /// \f$ {\bf f}(t,{\bf x}) \f$ over the element.
3355 void integrate_fct(
3357 const double& time,
3358 Vector<double>& integral);
3359
3360 /// Function for building a lower dimensional FaceElement
3361 /// on the specified face of the FiniteElement.
3362 /// The arguments are the index of the face, an integer whose value
3363 /// depends on the particular element type, and a pointer to the
3364 /// FaceElement.
3365 virtual void build_face_element(const int& face_index,
3366 FaceElement* face_element_pt);
3367
3368
3369 /// Self-test: Check inversion of element & do self-test for
3370 /// GeneralisedElement. Return 0 if OK.
3371 virtual unsigned self_test();
3372
3373 /// Get the number of the ith node on face face_index (in the bulk node
3374 /// vector).
3375 virtual unsigned get_bulk_node_number(const int& face_index,
3376 const unsigned& i) const
3377 {
3378 std::string err = "Not implemented for this element.";
3379 throw OomphLibError(
3381 }
3382
3383 /// Get the sign of the outer unit normal on the face given by face_index.
3384 virtual int face_outer_unit_normal_sign(const int& face_index) const
3385 {
3386 std::string err = "Not implemented for this element.";
3387 throw OomphLibError(
3389 }
3390
3391 virtual unsigned nnode_on_face() const
3392 {
3393 std::string err = "Not implemented for this element.";
3394 throw OomphLibError(
3396 }
3397
3398 /// Range check for face node numbers
3399 void face_node_number_error_check(const unsigned& i) const
3400 {
3401#ifdef RANGE_CHECKING
3402 if (i > nnode_on_face())
3403 {
3404 std::string err = "Face node index i out of range on face.";
3405 throw OomphLibError(
3407 }
3408#endif
3409 }
3410
3411 /// Get a pointer to the function mapping face coordinates to bulk
3412 /// coordinates
3414 const int& face_index) const
3415 {
3416 std::string err = "Not implemented for this element.";
3417 throw OomphLibError(
3419 }
3420
3421 /// Get a pointer to the derivative of the mapping from face to bulk
3422 /// coordinates.
3424 const int& face_index) const
3425 {
3426 std::string err = "Not implemented for this element.";
3427 throw OomphLibError(
3429 }
3430 };
3431
3432
3433 //////////////////////////////////////////////////////////////////////////
3434 //////////////////////////////////////////////////////////////////////////
3435 //////////////////////////////////////////////////////////////////////////
3436
3437
3438 //=======================================================================
3439 /// Point element has just a single node and a single shape function
3440 /// which is identically equal to one.
3441 //=======================================================================
3442 class PointElement : public virtual FiniteElement
3443 {
3444 public:
3445 /// Constructor
3447 {
3448 /// Allocate storage for the pointers to the nodes,
3449 /// There is only one nodes
3450 this->set_n_node(1);
3451
3452 // Set the integration scheme
3454 }
3455
3456 /// Broken copy constructor
3457 PointElement(const PointElement&) = delete;
3458
3459 /// Broken assignment operator
3460 /*void operator=(const PointElement&) = delete;*/
3461
3462 /// Calculate the geometric shape functions at local coordinate s
3463 void shape(const Vector<double>& s, Shape& psi) const;
3464
3465 /// Get local coordinates of node j in the element; vector sets its own size
3466 void local_coordinate_of_node(const unsigned& j, Vector<double>& s) const
3467 {
3468 s.resize(0);
3469 }
3470
3471 /// Return spatial dimension of element (=number of local
3472 /// coordinates needed to parametrise the element)
3473 // unsigned dim() const {return 0;}
3474
3475 private:
3476 /// Default integration scheme
3478 };
3479
3480
3481 //////////////////////////////////////////////////////////////////////////
3482 //////////////////////////////////////////////////////////////////////////
3483 //////////////////////////////////////////////////////////////////////////
3484
3485
3486 class GeomObject;
3487
3488 //=======================================================================
3489 /// A class to specify the initial conditions for a solid body.
3490 /// Solid bodies are often discretised with
3491 /// Hermite-type elements, for which the assignment
3492 /// of the generalised nodal values is nontrivial since they represent
3493 /// derivatives w.r.t. to the local coordinates. A SolidInitialCondition
3494 /// object specifies initial position (i.e. shape), velocity and acceleration
3495 /// of the structure with a geometric object.
3496 /// An integer specifies which time-derivative derivative is currently
3497 /// assigned. See example codes for a demonstration of its use.
3498 //=======================================================================
3500 {
3501 public:
3502 /// Constructor: Pass geometric object; initialise time deriv to 0
3505
3506
3507 /// Broken copy constructor
3509
3510 /// Broken assignment operator
3511 void operator=(const SolidInitialCondition&) = delete;
3512
3513 /// (Reference to) pointer to geom object that specifies the initial
3514 /// condition
3516 {
3517 return Geom_object_pt;
3518 }
3519
3520 /// Which time derivative are we currently assigning?
3521 unsigned& ic_time_deriv()
3522 {
3523 return IC_time_deriv;
3524 }
3525
3526
3527 private:
3528 /// Pointer to the GeomObject that specifies the initial
3529 /// condition (shape, veloc and accel)
3531
3532 /// Which time derivative (0,1,2) are we currently assigning
3534 };
3535
3536
3537 /////////////////////////////////////////////////////////////////////////
3538 /////////////////////////////////////////////////////////////////////////
3539 /////////////////////////////////////////////////////////////////////////
3540
3541
3542 //============================================================================
3543 /// SolidFiniteElement class.
3544 ///
3545 /// Solid elements are elements whose nodal positions are unknowns
3546 /// in the problem -- their nodes are SolidNodes. In such elements,
3547 /// the nodes not only have a variable (Eulerian) but also a fixed
3548 /// (Lagrangian) position. The positional variables have their own
3549 /// local equation numbering scheme which is set up with
3550 /// \code assign_solid_local_eqn_numbers () \endcode
3551 /// The derivatives of the
3552 /// `solid equations' (i.e. the equations that determine the
3553 /// nodal positions) with respect to the nodal positions, required
3554 /// in the Jacobian matrix, are determined by finite differencing.
3555 ///
3556 /// In the present form, the SolidFiniteElement represents
3557 /// a fully functional base class for `proper' solid mechanics elements,
3558 /// but it can also be combined
3559 /// (via inheritance) with elements that solve additional equations.
3560 /// This is particularly useful in cases where the solid equations
3561 /// are merely used to update the nodal positions in a moving mesh
3562 /// problem, although this can prove costly in practice.
3563 //============================================================================
3564 class SolidFiniteElement : public virtual FiniteElement
3565 {
3566 public:
3567 /// Set the lagrangian dimension of the element --- the number
3568 /// of lagrangian coordinates stored at the nodes in the element.
3573
3574 /// Return whether there is internal solid data (e.g. discontinuous
3575 /// solid pressure). At present, this is used to report an error in
3576 /// setting initial conditions for ElasticProblems which can't
3577 /// handle such cases. The default is false.
3579 {
3580 return false;
3581 }
3582
3583 /// Pointer to function that computes the "multiplier" for the
3584 /// inertia terms in the consistent determination of the initial
3585 /// conditions for Newmark timestepping.
3587
3588 /// Constructor: Set defaults
3600
3601 /// Destructor to clean up any allocated memory
3602 virtual ~SolidFiniteElement();
3603
3604 /// Broken copy constructor
3606
3607 /// Broken assignment operator
3608 /*void operator=(const SolidFiniteElement&) = delete;*/
3609
3610 /// The number of geometric data affecting a SolidFiniteElemnet is
3611 /// the same as the number of nodes (one variable position data per node)
3612 inline unsigned ngeom_data() const
3613 {
3614 return nnode();
3615 }
3616
3617 /// Return pointer to the j-th Data item that the object's
3618 /// shape depends on. (Redirects to the nodes' positional Data).
3619 inline Data* geom_data_pt(const unsigned& j)
3620 {
3621 return static_cast<SolidNode*>(node_pt(j))->variable_position_pt();
3622 }
3623
3624 /// Specify Data that affects the geometry of the element
3625 /// by adding the position Data to the set that's passed in.
3626 /// (This functionality is required in FSI problems; set is used to
3627 /// avoid double counting).
3629 {
3630 // Loop over the node update data and add to the set
3631 const unsigned n_node = this->nnode();
3632 for (unsigned n = 0; n < n_node; n++)
3633 {
3634 geometric_data_pt.insert(
3635 dynamic_cast<SolidNode*>(this->node_pt(n))->variable_position_pt());
3636 }
3637 }
3638
3639
3640 /// In a SolidFiniteElement, the "global" intrinsic coordinate
3641 /// of the element when viewed as part of a compound geometric
3642 /// object (a Mesh) is, by default, the Lagrangian coordinate
3643 /// Note the assumption here is that we are always using isoparameteric
3644 /// elements in which the lagrangian coordinate is interpolated by the
3645 /// same shape functions as the eulerian coordinate.
3646 inline double zeta_nodal(const unsigned& n,
3647 const unsigned& k,
3648 const unsigned& i) const
3649 {
3650 return lagrangian_position_gen(n, k, i);
3651 }
3652
3653 /// Eulerian and Lagrangian coordinates as function of the
3654 /// local coordinates: The Eulerian position is returned in
3655 /// FE-interpolated form (\c x_fe) and then in the form obtained
3656 /// from the "current" MacroElement representation (if it exists -- if not,
3657 /// \c x is the same as \c x_fe). This allows the Domain/MacroElement-
3658 /// based representation to be used to apply displacement boundary
3659 /// conditions exactly. Ditto for the Lagrangian coordinates returned
3660 /// in xi_fe and xi.
3661 /// (Broken virtual -- overload in specific geometric element class
3662 /// if you want to use this functionality.)
3663 virtual void get_x_and_xi(const Vector<double>& s,
3665 Vector<double>& x,
3667 Vector<double>& xi) const
3668 {
3669 throw OomphLibError(
3670 "get_x_and_xi(...) is not implemented for this element\n",
3673 }
3674
3675 /// Set pointer to MacroElement -- overloads generic version
3676 /// and uses the MacroElement
3677 /// also as the default for the "undeformed" configuration.
3678 /// This assignment must be overwritten with
3679 /// set_undeformed_macro_elem_pt(...) if the deformation of
3680 /// the solid body is driven by a deformation of the
3681 /// "current" Domain/MacroElement representation of it's boundary.
3682 /// Can be overloaded in derived classes to perform additional
3683 /// tasks
3689
3690 /// Set pointers to "current" and "undeformed" MacroElements.
3691 /// Can be overloaded in derived classes to perform additional
3692 /// tasks
3699
3700 /// Set pointer to "undeformed" macro element.
3701 /// Can be overloaded in derived classes to perform additional
3702 /// tasks.
3707
3708
3709 /// Access function to pointer to "undeformed" macro element
3714
3715 /// Calculate shape functions and derivatives w.r.t. Lagrangian
3716 /// coordinates at local coordinate s. Returns the Jacobian of the mapping
3717 /// from Lagrangian to local coordinates.
3718 double dshape_lagrangian(const Vector<double>& s,
3719 Shape& psi,
3720 DShape& dpsidxi) const;
3721
3722 /// Return the geometric shape functions and also first
3723 /// derivatives w.r.t. Lagrangian coordinates at ipt-th integration point.
3724 virtual double dshape_lagrangian_at_knot(const unsigned& ipt,
3725 Shape& psi,
3726 DShape& dpsidxi) const;
3727
3728 /// Compute the geometric shape functions and also first
3729 /// and second derivatives w.r.t. Lagrangian coordinates at
3730 /// local coordinate s;
3731 /// Returns Jacobian of mapping from Lagrangian to local coordinates.
3732 /// Numbering:
3733 /// \b 1D:
3734 /// d2pidxi(i,0) = \f$ d^2 \psi_j / d \xi^2 \f$
3735 /// \b 2D:
3736 /// d2psidxi(i,0) = \f$ \partial^2 \psi_j / \partial \xi_0^2 \f$
3737 /// d2psidxi(i,1) = \f$ \partial^2 \psi_j / \partial \xi_1^2 \f$
3738 /// d2psidxi(i,2) = \f$ \partial^2 \psi_j / \partial \xi_0 \partial \xi_1 \f$
3739 /// \b 3D:
3740 /// d2psidxi(i,0) = \f$ \partial^2 \psi_j / \partial \xi_0^2 \f$
3741 /// d2psidxi(i,1) = \f$ \partial^2 \psi_j / \partial \xi_1^2 \f$
3742 /// d2psidxi(i,2) = \f$ \partial^2 \psi_j / \partial \xi_2^2 \f$
3743 /// d2psidxi(i,3) = \f$ \partial^2 \psi_j/\partial \xi_0 \partial \xi_1 \f$
3744 /// d2psidxi(i,4) = \f$ \partial^2 \psi_j/\partial \xi_0 \partial \xi_2 \f$
3745 /// d2psidxi(i,5) = \f$ \partial^2 \psi_j/\partial \xi_1 \partial \xi_2 \f$
3746 double d2shape_lagrangian(const Vector<double>& s,
3747 Shape& psi,
3748 DShape& dpsidxi,
3749 DShape& d2psidxi) const;
3750
3751 /// Return the geometric shape functions and also first
3752 /// and second derivatives w.r.t. Lagrangian coordinates at
3753 /// the ipt-th integration point.
3754 /// Returns Jacobian of mapping from Lagrangian to local coordinates.
3755 /// Numbering:
3756 /// \b 1D:
3757 /// d2pidxi(i,0) = \f$ d^2 \psi_j / d^2 \xi^2 \f$
3758 /// \b 2D:
3759 /// d2psidxi(i,0) = \f$ \partial^2 \psi_j/\partial^2 \xi_0^2 \f$
3760 /// d2psidxi(i,1) = \f$ \partial^2 \psi_j/\partial^2 \xi_1^2 \f$
3761 /// d2psidxi(i,2) = \f$ \partial^2 \psi_j/\partial \xi_0 \partial \xi_1 \f$
3762 /// \b 3D:
3763 /// d2psidxi(i,0) = \f$ \partial^2 \psi_j / \partial^2 \xi_0^2 \f$
3764 /// d2psidxi(i,1) = \f$ \partial^2 \psi_j / \partial^2 \xi_1^2 \f$
3765 /// d2psidxi(i,2) = \f$ \partial^2 \psi_j / \partial^2 \xi_2^2 \f$
3766 /// d2psidxi(i,3) = \f$ \partial^2 \psi_j / \partial \xi_0 \partial \xi_1 \f$
3767 /// d2psidxi(i,4) = \f$ \partial^2 \psi_j / \partial \xi_0 \partial \xi_2 \f$
3768 /// d2psidxi(i,5) = \f$ \partial^2 \psi_j / \partial \xi_1 \partial \xi_2 \f$
3769 virtual double d2shape_lagrangian_at_knot(const unsigned& ipt,
3770 Shape& psi,
3771 DShape& dpsidxi,
3772 DShape& d2psidxi) const;
3773
3774 /// Return the number of Lagrangian coordinates that the
3775 /// element requires at all nodes.
3776 /// This is by default the elemental dimension. If we ever need any
3777 /// other case, it can be implemented.
3778 unsigned lagrangian_dimension() const
3779 {
3780 return Lagrangian_dimension;
3781 }
3782
3783 /// Return the number of types of (generalised)
3784 /// nodal Lagrangian coordinates required to
3785 /// interpolate the Lagrangian coordinates in the element. (E.g.
3786 /// 1 for Lagrange-type elements; 2 for Hermite beam elements;
3787 /// 4 for Hermite shell elements). Default value is 1. Needs to
3788 /// be overloaded for any other element.
3789 unsigned nnodal_lagrangian_type() const
3790 {
3792 }
3793
3794 /// Construct the local node n and return a pointer to it.
3795 Node* construct_node(const unsigned& n)
3796 {
3797 // Construct a solid node and assign it to the local node pointer vector.
3798 // The dimension and number of values are taken from internal element data
3799 // The number of solid pressure dofs are also taken from internal data
3800 // The number of timesteps to be stored comes from the problem!
3806 // Now return a pointer to the node, so that the mesh can find it
3807 return node_pt(n);
3808 }
3809
3810 /// Construct the local node n and return
3811 /// a pointer to it. Additionally, create storage for `history'
3812 /// values as required by timestepper
3814 {
3815 // Construct a solid node and assign it to the local node pointer vector
3816 // The dimension and number of values are taken from internal element data
3817 // The number of solid pressure dofs are also taken from internal data
3824 // Now return a pointer to the node, so that the mesh can find it
3825 return node_pt(n);
3826 }
3827
3828 /// Construct the local node n and return a pointer to it.
3829 /// in the case when it is a boundary node; that is it MAY be
3830 /// located on a Mesh boundary
3832 {
3833 // Construct a solid node and assign it to the local node pointer vector.
3834 // The dimension and number of values are taken from internal element data
3835 // The number of solid pressure dofs are also taken from internal data
3836 // The number of timesteps to be stored comes from the problem!
3842 // Now return a pointer to the node, so that the mesh can find it
3843 return node_pt(n);
3844 }
3845
3846 /// Construct the local node n and return
3847 /// a pointer to it, in the case when the node MAY be located
3848 /// on a boundary. Additionally, create storage for `history'
3849 /// values as required by timestepper
3852 {
3853 // Construct a solid node and assign it to the local node pointer vector
3854 // The dimension and number of values are taken from internal element data
3855 // The number of solid pressure dofs are also taken from internal data
3862 // Now return a pointer to the node, so that the mesh can find it
3863 return node_pt(n);
3864 }
3865
3866 /// Overload assign_all_generic_local_equation numbers to
3867 /// include the data associated with solid dofs.
3868 /// It remains virtual so that it can be overloaded
3869 /// by RefineableSolidElements. If the boolean argument is true
3870 /// then the degrees of freedom are stored in Dof_pt
3872 const bool& store_local_dof_pt)
3873 {
3874 // Call the standard finite element equation numbering
3875 //(internal, external and nodal data).
3877 // Assign the numbering for the solid dofs
3879 }
3880
3881 /// Function to describe the local dofs of the element. The ostream
3882 /// specifies the output stream to which the description
3883 /// is written; the string stores the currently
3884 /// assembled output that is ultimately written to the
3885 /// output stream by Data::describe_dofs(...); it is typically
3886 /// built up incrementally as we descend through the
3887 /// call hierarchy of this function when called from
3888 /// Problem::describe_dofs(...)
3889 void describe_local_dofs(std::ostream& out,
3890 const std::string& current_string) const;
3891
3892 /// Return i-th Lagrangian coordinate at local node n without using
3893 /// the hanging representation
3894 double raw_lagrangian_position(const unsigned& n, const unsigned& i) const
3895 {
3896 return static_cast<SolidNode*>(node_pt(n))->xi(i);
3897 }
3898
3899 /// Return Generalised Lagrangian coordinate at local node n.
3900 /// `Direction' i, `Type' k. Does not use the hanging node representation
3901 double raw_lagrangian_position_gen(const unsigned& n,
3902 const unsigned& k,
3903 const unsigned& i) const
3904 {
3905 return static_cast<SolidNode*>(node_pt(n))->xi_gen(k, i);
3906 }
3907
3908 /// Return i-th Lagrangian coordinate at local node n
3909 double lagrangian_position(const unsigned& n, const unsigned& i) const
3910 {
3911 return static_cast<SolidNode*>(node_pt(n))->lagrangian_position(i);
3912 }
3913
3914 /// Return Generalised Lagrangian coordinate at local node n.
3915 /// `Direction' i, `Type' k.
3916 double lagrangian_position_gen(const unsigned& n,
3917 const unsigned& k,
3918 const unsigned& i) const
3919 {
3920 return static_cast<SolidNode*>(node_pt(n))->lagrangian_position_gen(k, i);
3921 }
3922
3923 /// Return i-th FE-interpolated Lagrangian coordinate xi[i] at
3924 /// local coordinate s.
3925 virtual double interpolated_xi(const Vector<double>& s,
3926 const unsigned& i) const;
3927
3928 /// Compute FE interpolated Lagrangian coordinate vector xi[] at
3929 /// local coordinate s as Vector
3930 virtual void interpolated_xi(const Vector<double>& s,
3931 Vector<double>& xi) const;
3932
3933 /// Compute derivatives of FE-interpolated Lagrangian coordinates xi
3934 /// with respect to local coordinates: dxids[i][j]=dxi_i/ds_j.
3935 virtual void interpolated_dxids(const Vector<double>& s,
3936 DenseMatrix<double>& dxids) const;
3937
3938 /// Return the Jacobian of mapping from local to Lagrangian
3939 /// coordinates at local position s. NOT YET IMPLEMENTED
3940 virtual void J_lagrangian(const Vector<double>& s) const
3941 {
3942 // Must be implemented and overloaded in FaceElements
3943 throw OomphLibError("Function not implemented yet",
3946 }
3947
3948 /// Return the Jacobian of the mapping from local to Lagrangian
3949 /// coordinates at the ipt-th integration point. NOT YET IMPLEMENTED
3950 virtual double J_lagrangian_at_knot(const unsigned& ipt) const
3951 {
3952 // Must be implemented and overloaded in FaceElements
3953 throw OomphLibError("Function not implemented yet",
3956 }
3957
3958 /// Pointer to object that describes the initial condition.
3960 {
3961 return Solid_ic_pt;
3962 }
3963
3964 /// Set to alter the problem being solved when
3965 /// assigning the initial conditions for time-dependent problems:
3966 /// solve for the history value that
3967 /// corresponds to the acceleration in the Newmark scheme by demanding
3968 /// that the PDE is satisifed at the initial time. In this case
3969 /// the Jacobian is replaced by the mass matrix.
3974
3975 /// Set to reset the problem being solved to be the standard problem
3980
3981 /// Access function: Pointer to multiplicator function for assignment
3982 /// of consistent assignement of initial conditions for Newmark scheme
3987
3988
3989 /// Access function: Pointer to multiplicator function for assignment
3990 /// of consistent assignement of initial conditions for Newmark scheme
3991 /// (const version)
3993 {
3994 return Multiplier_fct_pt;
3995 }
3996
3997
3998 /// Compute the residuals for the setup of an initial condition.
3999 /// The global equations are:
4000 /// \f[ 0 = \int \left( \sum_{j=1}^N \sum_{k=1}^K X_{ijk} \psi_{jk}(\xi_n) - \frac{\partial^D R^{(IC)}_i(\xi_n)}{\partial t^D} \right) \psi_{lm}(\xi_n) \ dv \mbox{ \ \ \ \ for \ \ \ $l=1,...,N, \ \ m=1,...,K$} \f]
4001 /// where \f$ N \f$ is the number of nodes in the mesh and \f$ K \f$
4002 /// the number of generalised nodal coordinates. The initial shape
4003 /// of the solid body, \f$ {\bf R}^{(IC)},\f$ and its time-derivatives
4004 /// are specified via the \c GeomObject that is stored in the
4005 /// \c SolidFiniteElement::SolidInitialCondition object. The latter also
4006 /// stores the order of the time-derivative \f$ D \f$ to be assigned.
4012
4013 /// Fill in the residuals for the setup of an initial condition.
4014 /// The global equations are:
4015 /// \f[ 0 = \int \left( \sum_{j=1}^N \sum_{k=1}^K X_{ijk} \psi_{jk}(\xi_n) - \frac{\partial^D R^{(IC)}_i(\xi_n)}{\partial t^D} \right) \psi_{lm}(\xi_n) \ dv \mbox{ \ \ \ \ for \ \ \ $l=1,...,N, \ \ m=1,...,K$} \f]
4016 /// where \f$ N \f$ is the number of nodes in the mesh and \f$ K \f$
4017 /// the number of generalised nodal coordinates. The initial shape
4018 /// of the solid body, \f$ {\bf R}^{(IC)},\f$ and its time-derivatives
4019 /// are specified via the \c GeomObject that is stored in the
4020 /// \c SolidFiniteElement::SolidInitialCondition object. The latter also
4021 /// stores the order of the time-derivative \f$ D \f$ to be assigned.
4023 {
4024 // Call the generic residuals function with flag set to 0
4025 // using a dummy matrix argument
4028 }
4029
4030 /// Fill in the residuals and Jacobian for the setup of an
4031 /// initial condition. The global equations are:
4032 /// \f[ 0 = \int \left( \sum_{j=1}^N \sum_{k=1}^K X_{ijk} \psi_{jk}(\xi_n) - \frac{\partial^D R^{(IC)}_i(\xi_n)}{\partial t^D} \right) \psi_{lm}(\xi_n) \ dv \mbox{ \ \ \ \ for \ \ \ $l=1,...,N, \ \ m=1,...,K$} \f]
4033 /// where \f$ N \f$ is the number of nodes in the mesh and \f$ K \f$
4034 /// the number of generalised nodal coordinates. The initial shape
4035 /// of the solid body, \f$ {\bf R}^{(IC)},\f$ and its time-derivatives
4036 /// are specified via the \c GeomObject that is stored in the
4037 /// \c SolidFiniteElement::SolidInitialCondition object. The latter also
4038 /// stores the order of the time-derivative \f$ D \f$ to be assigned.
4040 DenseMatrix<double>& jacobian)
4041 {
4042 // Call the generic routine with the flag set to 1
4044 }
4045
4046
4047 /// Fill in the contributions of the Jacobian matrix
4048 /// for the consistent assignment of the initial "accelerations" in
4049 /// Newmark scheme. In this case the Jacobian is the mass matrix.
4051
4052
4053 /// Calculate the L2 norm of the displacement u=R-r to overload the
4054 /// compute_norm function in the GeneralisedElement base class
4055 void compute_norm(double& el_norm);
4056
4057 protected:
4058 /// Helper function to fill in the residuals and (if flag==1) the
4059 /// Jacobian for the setup of an initial condition. The global equations
4060 /// are:
4061 /// \f[ 0 = \int \left( \sum_{j=1}^N \sum_{k=1}^K X_{ijk} \psi_{jk}(\xi_n) - \frac{\partial^D R^{(IC)}_i(\xi_n)}{\partial t^D} \right) \psi_{lm}(\xi_n) \ dv \mbox{ \ \ \ \ for \ \ \ $l=1,...,N, \ \ m=1,...,K$} \f]
4062 /// where \f$ N \f$ is the number of nodes in the mesh and \f$ K \f$
4063 /// the number of generalised nodal coordinates. The initial shape
4064 /// of the solid body, \f$ {\bf R}^{(IC)},\f$ and its time-derivatives
4065 /// are specified via the \c GeomObject that is stored in the
4066 /// \c SolidFiniteElement::SolidInitialCondition object. The latter also
4067 /// stores the order of the time-derivative \f$ D \f$ to be assigned.
4069 DenseMatrix<double>& jacobian,
4070 const unsigned& flag);
4071
4072 /// Set the number of types required to interpolate the
4073 /// Lagrangian coordinates
4074 void set_nnodal_lagrangian_type(const unsigned& nlagrangian_type)
4075 {
4076 Nnodal_lagrangian_type = nlagrangian_type;
4077 }
4078
4079 /// Pointer to the element's "undeformed" macro element (NULL by default)
4081
4082 /// Calculate the mapping from local to lagrangian coordinates,
4083 /// given the derivatives of the shape functions w.r.t. local coorindates.
4084 /// Return the determinant of the jacobian, the jacobian and inverse
4085 /// jacobian
4087 const DShape& dpsids,
4088 DenseMatrix<double>& jacobian,
4090 {
4091 // Assemble the jacobian
4093 // Invert the jacobian
4094 return invert_jacobian_mapping(jacobian, inverse_jacobian);
4095 }
4096
4097 /// Calculate the mapping from local to lagrangian coordinates,
4098 /// given the derivatives of the shape functions w.r.t. local coordinates,
4099 /// Return only the determinant of the jacobian and the inverse of the
4100 /// mapping (ds/dx)
4103 {
4104 // Find the dimension of the element
4105 unsigned el_dim = dim();
4106 // Assign memory for the jacobian
4107 DenseMatrix<double> jacobian(el_dim);
4108 // Calculate the jacobian and inverse
4110 }
4111
4112 /// Calculate the mapping from local to Lagrangian coordinates given
4113 /// the derivatives of the shape functions w.r.t the local coorindates.
4114 /// assuming that the coordinates are aligned in the direction of the local
4115 /// coordinates, i.e. there are no cross terms and the jacobian is diagonal.
4116 /// This function returns the determinant of the jacobian, the jacobian
4117 /// and the inverse jacobian.
4119 const DShape& dpsids,
4120 DenseMatrix<double>& jacobian,
4122
4123
4124 /// Assigns local equation numbers for the generic solid
4125 /// local equation numbering schemes.
4126 /// If the boolean flag is true the the degrees of freedom are stored in
4127 /// Dof_pt
4128 virtual void assign_solid_local_eqn_numbers(const bool& store_local_dof);
4129
4130 /// Classifies dofs locally for solid specific aspects.
4131 void describe_solid_local_dofs(std::ostream& out,
4132 const std::string& current_string) const;
4133
4134 /// Pointer to object that specifies the initial condition
4136
4137 public:
4138 /// Access function that returns the local equation number that
4139 /// corresponds to the j-th coordinate of the k-th position-type at the
4140 /// n-th local node.
4141 inline int position_local_eqn(const unsigned& n,
4142 const unsigned& k,
4143 const unsigned& j) const
4144 {
4145#ifdef RANGE_CHECKING
4146 std::ostringstream error_message;
4147 bool error = false;
4148 if (n >= nnode())
4149 {
4150 error = true;
4151 error_message << "Range Error: Nodal number " << n
4152 << " is not in the range (0," << nnode() << ")";
4153 }
4154
4155 if (k >= nnodal_position_type())
4156 {
4157 error = true;
4158 error_message << "Range Error: Position type " << k
4159 << " is not in the range (0," << nnodal_position_type()
4160 << ")";
4161 }
4162
4163 if (j >= nodal_dimension())
4164 {
4165 error = true;
4166 error_message << "Range Error: Nodal coordinate " << j
4167 << " is not in the range (0," << nodal_dimension() << ")";
4168 }
4169
4170 if (error)
4171 {
4172 // Throw the error
4173 throw OomphLibError(error_message.str(),
4176 }
4177#endif
4178
4179 // Return the value
4181 nodal_dimension() +
4182 j];
4183 }
4184
4185 protected:
4186 /// Overload the fill_in_contribution_to_jacobian() function to
4187 /// use finite
4188 /// differences to calculate the solid residuals by default
4190 DenseMatrix<double>& jacobian)
4191 {
4192 // Add the contribution to the residuals
4194
4195 // Solve for the consistent acceleration in Newmark scheme?
4197 {
4199 return;
4200 }
4201
4202 // Allocate storage for the full residuals (residuals of entire element)
4203 unsigned n_dof = ndof();
4205 // Get the residuals for the entire element
4207 // Get the solid entries in the jacobian using finite differences
4209 // There could be internal data
4210 //(finite-difference the lot by default)
4212 // There could also be external data
4213 //(finite-difference the lot by default)
4215 // There could also be nodal data
4217 }
4218
4219
4220 /// Use finite differences to calculate the Jacobian entries
4221 /// corresponding to the solid positions. This version assumes
4222 /// that the residuals vector has already been computed
4225
4226
4227 /// Use finite differences to calculate the Jacobian entries
4228 /// corresponding to the solid positions.
4230 DenseMatrix<double>& jacobian)
4231 {
4232 // Allocate storage for a residuals vector and initialise to zero
4233 unsigned n_dof = ndof();
4235 // Get the residuals for the entire element
4237 // Call the jacobian calculation
4239 }
4240
4241 /// Function that is called before the finite differencing of
4242 /// any solid position data. This may be overloaded to update any dependent
4243 /// data before finite differencing takes place.
4244 virtual inline void update_before_solid_position_fd() {}
4245
4246 /// Function that is call after the finite differencing of
4247 /// the solid position data. This may be overloaded to reset any dependent
4248 /// variables that may have changed during the finite differencing.
4249 virtual inline void reset_after_solid_position_fd() {}
4250
4251 /// Function called within the finite difference loop for
4252 /// the solid position dat after a change in any values in the n-th
4253 /// node.
4254 virtual inline void update_in_solid_position_fd(const unsigned& i) {}
4255
4256 /// Function called within the finite difference loop for
4257 /// solid position data after the values in the i-th node
4258 /// are reset. The default behaviour is to call the update function.
4259 virtual inline void reset_in_solid_position_fd(const unsigned& i)
4260 {
4262 }
4263
4264
4265 private:
4266 /// Assemble the jacobian matrix for the mapping from local
4267 /// to lagrangian coordinates, given the derivatives of the shape function
4269 const DShape& dpsids, DenseMatrix<double>& jacobian) const;
4270
4271
4272 /// Assemble the the "jacobian" matrix of second derivatives, given
4273 /// the second derivatives of the shape functions w.r.t. local coordinates
4276
4277 /// Pointer to function that computes the "multiplier" for the
4278 /// inertia terms in the consistent determination of the initial
4279 /// conditions for Newmark timestepping.
4281
4282 /// Array to hold the local equation number information for the
4283 /// solid equations, whatever they may be.
4284 // ALH: (This is here so that the numbering can be done automatically)
4286
4287 /// The Lagrangian dimension of the nodes stored in the element,
4288 /// / i.e. the number of Lagrangian coordinates
4290
4291 /// The number of coordinate types requried to intepolate the
4292 /// Lagrangian coordinates in the element. For Lagrange elements
4293 /// it is 1 (the default). It must be over-ridden by using
4294 /// the set_nlagrangian_type() function in the constructors of elements
4295 /// that use generalised coordinate, e.g. for 1D Hermite elements
4296 /// Nnodal_position_types =2.
4298
4299 protected:
4300 /// Flag to indicate which system of equations to solve
4301 /// when assigning initial conditions for time-dependent problems.
4302 /// If true, solve for the history value that
4303 /// corresponds to the acceleration in the Newmark scheme by demanding
4304 /// that the PDE is satisifed at the initial time. In this case
4305 /// the Jacobian is replaced by the mass matrix.
4307
4308 private:
4309 /// Access to the "multiplier" for the
4310 /// inertia terms in the consistent determination of the initial
4311 /// conditions for Newmark timestepping.
4312 inline double multiplier(const Vector<double>& xi)
4313 {
4314 // If no function has been set, return 1
4315 if (Multiplier_fct_pt == 0)
4316 {
4317 return 1.0;
4318 }
4319 else
4320 {
4321 // Evaluate function pointer
4322 return (*Multiplier_fct_pt)(xi);
4323 }
4324 }
4325 };
4326
4327
4328 //========================================================================
4329 /// FaceElements are elements that coincide with the faces of
4330 /// higher-dimensional "bulk" elements. They are used on
4331 /// boundaries where additional non-trivial boundary conditions need to be
4332 /// applied. Examples include free surfaces, and applied traction conditions.
4333 /// In many cases, FaceElements need to evaluate to quantities
4334 /// in the associated bulk elements. For instance, the evaluation
4335 /// of a shear stresses on 2D FaceElement requires the evaluation
4336 /// of velocity derivatives in the associated 3D volume element etc.
4337 /// Therefore we store a pointer to the associated bulk element,
4338 /// and information about the relation between the local
4339 /// coordinates in the face and bulk elements.
4340 //========================================================================
4341 class FaceElement : public virtual FiniteElement
4342 {
4343 /// Typedef for the function that translates the face coordinate
4344 /// to the coordinate in the bulk element
4347
4348 /// Typedef for the function that returns the partial derivative
4349 /// of the local coordinates in the bulk element
4350 /// with respect to the coordinates along the face.
4351 /// In addition this function returns an index of one of the
4352 /// bulk local coordinates that varies away from the edge
4354 const Vector<double>& s,
4356 unsigned& interior_direction);
4357
4358 private:
4359 /// Pointer to a function that translates the face coordinate
4360 /// to the coordinate in the bulk element
4362
4363 /// Pointer to a function that returns the derivatives of the local
4364 /// "bulk" coordinates with respect to the local face coordinates.
4366
4367 /// Vector holding integers to translate additional position types
4368 /// to those of the "bulk" element; e.g. Bulk_position_type(1) is
4369 /// the position type of the "bulk" element that corresponds to face
4370 /// position type 1. This is required in QHermiteElements, where the slope
4371 /// in the direction of the 1D element is face position type 1, but may be
4372 /// position type 1 or 2 in the "bulk" element, depending upon which face,
4373 /// we are located.
4375
4376 /// Sign of outer unit normal (relative to cross-products of tangent
4377 /// vectors in the corresponding "bulk" element.
4379
4380 /// Index of the face
4382
4383 /// Ignores the warning when the tangent vectors from
4384 /// continuous_tangent_and_outer_unit_normal may not be continuous
4385 /// as a result of the unit normal being aligned with the z axis.
4386 /// This can be avoided by supplying a general direction vector for
4387 /// the tangent vector via set_tangent_direction(...).
4389
4390 protected:
4391 /// The boundary number in the bulk mesh to which this element is attached
4393
4394#ifdef PARANOID
4395
4396 /// Has the Boundary_number_in_bulk_mesh been set? Only included if
4397 /// compiled with PARANOID switched on.
4399
4400#endif
4401
4402 /// Pointer to the associated higher-dimensional "bulk" element
4404
4405 /// List of indices of the local node numbers in the "bulk" element
4406 /// that correspond to the local node numbers in the FaceElement
4408
4409 /// A vector that will hold the number of data values at the nodes
4410 /// that are associated with the "bulk" element. i.e. not including any
4411 /// additional degrees of freedom that might be required for extra equations
4412 /// that are being solved by
4413 /// the FaceElement.
4414 // NOTE: This breaks if the nodes have already been resized
4415 // before calling the face element, i.e. two separate sets of equations on
4416 // the face!
4418
4419 /// A general direction pointer for the tangent vectors.
4420 /// This is used in the function continuous_tangent_and_outer_unit_normal()
4421 /// for creating continuous tangent vectors in spatial dimensions.
4422 /// The general direction is projected on to the surface. This technique is
4423 /// not required in two spatial dimensions.
4425
4426 /// Helper function adding additional values for the unknowns
4427 /// associated with the FaceElement. This function also sets the map
4428 /// containing the position of the first entry of this face element's
4429 /// additional values.The inputs are the number of additional values
4430 /// and the face element's ID. Note the same number of additonal values
4431 /// are allocated at ALL nodes.
4432 void add_additional_values(const Vector<unsigned>& nadditional_values,
4433 const unsigned& id)
4434 {
4435 // How many nodes?
4436 const unsigned n_node = nnode();
4437
4438 // loop over the nodes
4439 for (unsigned n = 0; n < n_node; n++)
4440 {
4441 // Assign the required number of additional nodes to the node
4442 dynamic_cast<BoundaryNodeBase*>(this->node_pt(n))
4443 ->assign_additional_values_with_face_id(nadditional_values[n], id);
4444 }
4445 }
4446
4447
4448 public:
4449 /// Constructor: Initialise all appropriate member data
4453 Normal_sign(0),
4454 Face_index(0),
4456 Bulk_element_pt(0),
4458 {
4459 // Check whether things have been set
4460#ifdef PARANOID
4462#endif
4463
4464 // Bulk_position_type[0] is always 0 (the position)
4465 Bulk_position_type.push_back(0);
4466 }
4467
4468 /// Empty virtual destructor
4469 virtual ~FaceElement() {}
4470
4471
4472 /// Broken copy constructor
4473 FaceElement(const FaceElement&) = delete;
4474
4475 /// Broken assignment operator
4476 /*void operator=(const FaceElement&) = delete;*/
4477
4478 /// Access function for the boundary number in bulk mesh
4479 inline const unsigned& boundary_number_in_bulk_mesh() const
4480 {
4482 }
4483
4484
4485 /// Set function for the boundary number in bulk mesh
4486 inline void set_boundary_number_in_bulk_mesh(const unsigned& b)
4487 {
4489#ifdef PARANOID
4491#endif
4492 }
4493
4494 /// In a FaceElement, the "global" intrinsic coordinate
4495 /// of the element along the boundary, when viewed as part of
4496 /// a compound geometric object is specified using the
4497 /// boundary coordinate defined by the mesh.
4498 /// Note: Boundary coordinates will have been set up when
4499 /// creating the underlying mesh, and their values will have
4500 /// been stored at the nodes.
4501 double zeta_nodal(const unsigned& n,
4502 const unsigned& k,
4503 const unsigned& i) const
4504 {
4505 // Vector in which to hold the intrinsic coordinate
4506 Vector<double> zeta(this->dim());
4507
4508 // Get the k-th generalised boundary coordinate at node n
4511
4512 // Return the individual coordinate
4513 return zeta[i];
4514 }
4515
4516 /// Return the Jacobian of mapping from local to global
4517 /// coordinates at local position s.
4518 /// Overloaded from FiniteElement.
4519 double J_eulerian(const Vector<double>& s) const;
4520
4521 /// Return the Jacobian of the mapping from local to global
4522 /// coordinates at the ipt-th integration point
4523 /// Overloaded from FiniteElement.
4524 double J_eulerian_at_knot(const unsigned& ipt) const;
4525
4526 /// Check that Jacobian of mapping between local and Eulerian
4527 /// coordinates at all integration points is positive.
4528 void check_J_eulerian_at_knots(bool& passed) const;
4529
4530 /// Return FE interpolated coordinate x[i] at local coordinate s.
4531 /// Overloaded to get information from bulk.
4532 double interpolated_x(const Vector<double>& s, const unsigned& i) const
4533 {
4534 // Local coordinates in bulk element
4535 Vector<double> s_bulk(dim() + 1);
4537
4538 // Return Eulerian coordinate as computed by bulk
4540 }
4541
4542 /// Return FE interpolated coordinate x[i] at local coordinate s
4543 /// at previous timestep t (t=0: present; t>0: previous timestep).
4544 /// Overloaded to get information from bulk.
4545 double interpolated_x(const unsigned& t,
4546 const Vector<double>& s,
4547 const unsigned& i) const
4548 {
4549 // Local coordinates in bulk element
4550 Vector<double> s_bulk(dim() + 1);
4552
4553 // Return Eulerian coordinate as computed by bulk
4555 }
4556
4557 /// Return FE interpolated position x[] at local coordinate s as
4558 /// Vector Overloaded to get information from bulk.
4560 {
4561 // Local coordinates in bulk element
4562 Vector<double> s_bulk(dim() + 1);
4564
4565 // Get Eulerian position vector
4567 }
4568
4569 /// Return FE interpolated position x[] at local coordinate s
4570 /// at previous timestep t as Vector (t=0: present; t>0: previous timestep).
4571 /// Overloaded to get information from bulk.
4572 void interpolated_x(const unsigned& t,
4573 const Vector<double>& s,
4574 Vector<double>& x) const
4575 {
4576 // Local coordinates in bulk element
4577 Vector<double> s_bulk(dim() + 1);
4579
4580 // Get Eulerian position vector
4582 }
4583
4584 /// Return t-th time-derivative of the
4585 /// i-th FE-interpolated Eulerian coordinate at
4586 /// local coordinate s. Overloaded to get information from bulk.
4588 const unsigned& i,
4589 const unsigned& t)
4590 {
4591 // Local coordinates in bulk element
4592 Vector<double> s_bulk(dim() + 1);
4594
4595 // Return Eulerian coordinate as computed by bulk
4597 }
4598
4599 /// Compte t-th time-derivative of the
4600 /// FE-interpolated Eulerian coordinate vector at
4601 /// local coordinate s. Overloaded to get information from bulk.
4603 const unsigned& t,
4605 {
4606 // Local coordinates in bulk element
4607 Vector<double> s_bulk(dim() + 1);
4609
4610 // Get Eulerian position vector
4612 }
4613
4614 /// Sign of outer unit normal (relative to cross-products of tangent
4615 /// vectors in the corresponding "bulk" element.
4617 {
4618 return Normal_sign;
4619 }
4620
4621 /// Return sign of outer unit normal (relative to cross-products
4622 /// of tangent vectors in the corresponding "bulk" element. (const version)
4623 int normal_sign() const
4624 {
4625 return Normal_sign;
4626 }
4627
4628 /// Index of the face (a number that uniquely identifies the face
4629 /// in the element)
4631 {
4632 return Face_index;
4633 }
4634
4635 /// Index of the face (a number that uniquely identifies the face
4636 /// in the element) (const version)
4637 int face_index() const
4638 {
4639 return Face_index;
4640 }
4641
4642 /// Public access function for the tangent direction pointer.
4644 {
4645 return Tangent_direction_pt;
4646 }
4647
4648 /// Set the tangent direction vector.
4650 {
4651#ifdef PARANOID
4652 // Check that tangent_direction_pt is not null.
4653 if (tangent_direction_pt == 0)
4654 {
4655 std::ostringstream error_message;
4656 error_message << "The pointer tangent_direction_pt is null.\n";
4657 throw OomphLibError(error_message.str(),
4660 }
4661
4662 // Check that the vector is the correct size.
4663 // The size of the tangent vector.
4665 unsigned spatial_dimension = this->nodal_dimension();
4666 if (tang_dir_size != spatial_dimension)
4667 {
4668 std::ostringstream error_message;
4669 error_message << "The tangent direction vector has size "
4670 << tang_dir_size << "\n"
4671 << "but this element has spatial dimension "
4672 << spatial_dimension << ".\n";
4673 throw OomphLibError(error_message.str(),
4676 }
4677
4678 if (tang_dir_size == 2)
4679 {
4680 std::ostringstream warning_message;
4682 << "The spatial dimension is " << spatial_dimension << ".\n"
4683 << "I do not need a tangent direction vector to create \n"
4684 << "continuous tangent vectors in two spatial dimensions.";
4688 }
4689#endif
4690
4691 // Set the direction vector for the tangent.
4693 }
4694
4695 /// Turn on warning for when there may be discontinuous tangent
4696 /// vectors from continuous_tangent_and_outer_unit_normal(...)
4701
4702 /// Turn off warning for when there may be discontinuous tangent
4703 /// vectors from continuous_tangent_and_outer_unit_normal(...)
4708
4709 /// Compute the tangent vector(s) and the outer unit normal
4710 /// vector at the specified local coordinate.
4711 /// In two spatial dimensions, a "tangent direction" is not required.
4712 /// In three spatial dimensions, a tangent direction is required
4713 /// (set via set_tangent_direction(...)), and we project the tanent
4714 /// direction on to the surface. The second tangent vector is taken to be
4715 /// the cross product of the projection and the unit normal.
4717 const Vector<double>& s,
4720
4721 /// Compute the tangent vector(s) and the outer unit normal
4722 /// vector at the ipt-th integration point. This is a wrapper around
4723 /// continuous_tangent_and_outer_unit_normal(...) with the integration
4724 /// points converted into local coordinates.
4726 const unsigned& ipt,
4729
4730 /// Compute outer unit normal at the specified local coordinate
4733
4734 /// Compute outer unit normal at ipt-th integration point
4735 void outer_unit_normal(const unsigned& ipt,
4737
4738 /// Pointer to higher-dimensional "bulk" element
4740 {
4741 return Bulk_element_pt;
4742 }
4743
4744
4745 /// Pointer to higher-dimensional "bulk" element (const version)
4747 {
4748 return Bulk_element_pt;
4749 }
4750
4751 // Clang specific pragma's
4752#ifdef __clang__
4753#pragma clang diagnostic push
4754#pragma clang diagnostic ignored "-Woverloaded-virtual"
4755#endif
4756
4757 /// Return the pointer to the function that maps the face
4758 /// coordinate to the bulk coordinate
4763
4764 /// Return the pointer to the function that maps the face
4765 /// coordinate to the bulk coordinate (const version)
4770
4771
4772 /// Return the pointer to the function that returns the derivatives
4773 /// of the bulk coordinates wrt the face coordinates
4778
4779 /// Return the pointer to the function that returns the derivatives
4780 /// of the bulk coordinates wrt the face coordinates (const version)
4785
4786#ifdef __clang__
4787#pragma clang diagnostic pop
4788#endif
4789
4790 /// Return vector of local coordinates in bulk element,
4791 /// given the local coordinates in this FaceElement
4793
4794 /// Calculate the vector of local coordinate in the bulk element
4795 /// given the local coordinates in this FaceElement
4797 Vector<double>& s_bulk) const;
4798
4799 /// Calculate the derivatives of the local coordinates in the
4800 /// bulk element with respect to the local coordinates in this FaceElement.
4801 /// In addition return the index of a bulk local coordinate that varies away
4802 /// from the face.
4805 unsigned& interior_direction) const;
4806
4807 /// Return the position type in the "bulk" element that corresponds
4808 /// to position type i on the FaceElement.
4809 unsigned& bulk_position_type(const unsigned& i)
4810 {
4811 return Bulk_position_type[i];
4812 }
4813
4814 /// Return the position type in the "bulk" element that corresponds
4815 /// to the position type i on the FaceElement. Const version
4816 const unsigned& bulk_position_type(const unsigned& i) const
4817 {
4818 return Bulk_position_type[i];
4819 }
4820
4821 /// Resize the storage for the bulk node numbers
4822 void bulk_node_number_resize(const unsigned& i)
4823 {
4824 Bulk_node_number.resize(i);
4825 }
4826
4827 /// Return the bulk node number that corresponds to the n-th
4828 /// local node number
4829 unsigned& bulk_node_number(const unsigned& n)
4830 {
4831 return Bulk_node_number[n];
4832 }
4833
4834 /// Return the bulk node number that corresponds to the n-th
4835 /// local node number (const version)
4836 const unsigned& bulk_node_number(const unsigned& n) const
4837 {
4838 return Bulk_node_number[n];
4839 }
4840
4841 /// Resize the storage for bulk_position_type to i entries.
4842 void bulk_position_type_resize(const unsigned& i)
4843 {
4844 Bulk_position_type.resize(i);
4845 }
4846
4847 /// Return the number of values originally stored at local node n
4848 /// (before the FaceElement added additional values to it (if it did))
4849 unsigned& nbulk_value(const unsigned& n)
4850 {
4851 return Nbulk_value[n];
4852 }
4853
4854 /// Return the number of values originally stored at local node n
4855 /// (before the FaceElement added additional values to it (if it did))
4856 /// (const version)
4857 unsigned nbulk_value(const unsigned& n) const
4858 {
4859 return Nbulk_value[n];
4860 }
4861
4862 /// Resize the storage for the number of values originally
4863 /// stored at the local nodes to i entries.
4864 void nbulk_value_resize(const unsigned& i)
4865 {
4866 Nbulk_value.resize(i);
4867 }
4868
4869 /// Provide additional storage for a specified number of
4870 /// values at the nodes of the FaceElement. (This is needed, for
4871 /// instance, in free-surface elements, if the non-penetration
4872 /// condition is imposed by Lagrange multipliers whose values
4873 /// are only stored at the surface nodes but not in the interior of
4874 /// the bulk element). \c nadditional_data_values[n] specifies the
4875 /// number of additional values required at node \c n of the
4876 /// FaceElement. \b Note: Since this function is executed separately
4877 /// for each FaceElement, nodes that are common to multiple elements
4878 /// might be resized repeatedly. To avoid this, we only allow
4879 /// a single resize operation by comparing the number of values stored
4880 /// at each node to the number of values the node had when it
4881 /// was simply a member of the associated "bulk"
4882 /// element. <b>There are cases where this will break!</b> -- e.g. if
4883 /// a node is common to two FaceElements which require
4884 /// additional storage for distinct quantities. Such cases
4885 /// need to be handled by "hand-crafted" face elements.
4887 {
4888 // Locally cache the number of node
4889 unsigned n_node = nnode();
4890 // Resize the storage for values at the nodes:
4891 for (unsigned l = 0; l < n_node; l++)
4892 {
4893 // Find number of values stored at the node
4894 unsigned Initial_Nvalue = node_pt(l)->nvalue();
4895 // Read out the number of additional values
4897 // If the node has not already been resized, resize it
4898 if ((Initial_Nvalue == Nbulk_value[l]) && (Nadditional > 0))
4899 {
4900 // Resize the node according to the number of additional values
4902 }
4903 } // End of loop over nodes
4904 }
4905
4906 /// Output boundary coordinate zeta
4907 void output_zeta(std::ostream& outfile, const unsigned& nplot);
4908 };
4909
4910
4911 //========================================================================
4912 /// SolidFaceElements combine FaceElements and SolidFiniteElements
4913 /// and overload various functions so they work properly in the
4914 /// FaceElement context
4915 //========================================================================
4916 class SolidFaceElement : public virtual FaceElement,
4917 public virtual SolidFiniteElement
4918 {
4919 public:
4920 /// The "global" intrinsic coordinate of the element when
4921 /// viewed as part of a geometric object should be given by
4922 /// the FaceElement representation, by default
4923 /// This final over-ride is required because both SolidFiniteElements
4924 /// and FaceElements overload zeta_nodal
4925 double zeta_nodal(const unsigned& n,
4926 const unsigned& k,
4927 const unsigned& i) const
4928 {
4929 return FaceElement::zeta_nodal(n, k, i);
4930 }
4931
4932
4933 /// Return i-th FE-interpolated Lagrangian coordinate xi[i] at
4934 /// local coordinate s. Overloaded from SolidFiniteElement. Note that
4935 /// the Lagrangian coordinates are those defined in the bulk!
4936 /// For instance, in a 1D FaceElement that is aligned with
4937 /// the Lagrangian coordinate line xi_0=const, only xi_1 will vary
4938 /// in the FaceElement. This may confuse you if you (wrongly!) believe that
4939 /// in a 1D SolidElement there should only a single Lagrangian
4940 /// coordinate, namely xi_0!
4941 double interpolated_xi(const Vector<double>& s, const unsigned& i) const
4942 {
4943 // Local coordinates in bulk element
4944 Vector<double> s_bulk(dim() + 1);
4946
4947 // Return Lagrangian coordinate as computed by bulk
4948 return dynamic_cast<SolidFiniteElement*>(bulk_element_pt())
4950 }
4951
4952
4953 /// Compute FE interpolated Lagrangian coordinate vector xi[] at
4954 /// local coordinate s as Vector. Overloaded from SolidFiniteElement. Note
4955 /// that the Lagrangian coordinates are those defined in the bulk!
4956 /// For instance, in a 1D FaceElement that is aligned with
4957 /// the Lagrangian coordinate line xi_0=const, only xi_1 will vary
4958 /// in the FaceElement. This may confuse you if you (wrongly!) believe that
4959 /// in a 1D SolidElement there should only a single Lagrangian
4960 /// coordinate, namely xi_0!
4962 {
4963 // Local coordinates in bulk element
4964 Vector<double> s_bulk(dim() + 1);
4966
4967 // Get Lagrangian position vector
4968 dynamic_cast<SolidFiniteElement*>(bulk_element_pt())
4969 ->interpolated_xi(s_bulk, xi);
4970 }
4971 };
4972
4973
4974 ///////////////////////////////////////////////////////////////////////
4975 ///////////////////////////////////////////////////////////////////////
4976 ///////////////////////////////////////////////////////////////////////
4977
4978
4979 //=======================================================================
4980 /// Solid point element
4981 //=======================================================================
4983 public virtual PointElement
4984 {
4985 };
4986
4987
4988 ///////////////////////////////////////////////////////////////////////
4989 ///////////////////////////////////////////////////////////////////////
4990 ///////////////////////////////////////////////////////////////////////
4991
4992
4993 //=======================================================================
4994 /// FaceGeometry class definition: This policy class is used to allow
4995 /// construction of face elements that solve arbitrary equations without
4996 /// having to tamper with the corresponding "bulk" elements.
4997 /// The geometrical information for the face element must be specified
4998 /// by each "bulk" element using an explicit specialisation of this class.
4999 //=======================================================================
5000 template<class ELEMENT>
5002 {
5003 };
5004
5005
5006 ///////////////////////////////////////////////////////////////////////
5007 ///////////////////////////////////////////////////////////////////////
5008 ///////////////////////////////////////////////////////////////////////
5009
5010
5011 //======================================================================
5012 /// Dummy FaceElement for use with purely geometric operations
5013 /// such as mesh generation.
5014 //======================================================================
5015 template<class ELEMENT>
5016 class DummyFaceElement : public virtual FaceGeometry<ELEMENT>,
5017 public virtual FaceElement
5018 {
5019 public:
5020 /// Constructor, which takes a "bulk" element and the
5021 /// face index
5022 DummyFaceElement(FiniteElement* const& element_pt, const int& face_index)
5023 : FaceGeometry<ELEMENT>(), FaceElement()
5024 {
5025 // Attach the geometrical information to the element. N.B. This function
5026 // also assigns nbulk_value from the required_nvalue of the bulk element
5027 element_pt->build_face_element(face_index, this);
5028 }
5029
5030
5031 /// Constructor
5033
5034
5035 /// The "global" intrinsic coordinate of the element when
5036 /// viewed as part of a geometric object should be given by
5037 /// the FaceElement representation, by default
5038 double zeta_nodal(const unsigned& n,
5039 const unsigned& k,
5040 const unsigned& i) const
5041 {
5042 return FaceElement::zeta_nodal(n, k, i);
5043 }
5044
5045 /// Output nodal coordinates
5046 void output(std::ostream& outfile)
5047 {
5048 outfile << "ZONE" << std::endl;
5049 unsigned nnod = nnode();
5050 for (unsigned j = 0; j < nnod; j++)
5051 {
5052 Node* nod_pt = node_pt(j);
5053 unsigned dim = nod_pt->ndim();
5054 for (unsigned i = 0; i < dim; i++)
5055 {
5056 outfile << nod_pt->x(i) << " ";
5057 }
5058 outfile << std::endl;
5059 }
5060 }
5061
5062 /// Output at n_plot points
5063 void output(std::ostream& outfile, const unsigned& n_plot)
5064 {
5066 }
5067
5068 /// C-style output
5070 {
5072 }
5073
5074 /// C_style output at n_plot points
5075 void output(FILE* file_pt, const unsigned& n_plot)
5076 {
5078 }
5079 };
5080
5081 ///////////////////////////////////////////////////////////////////////
5082 ///////////////////////////////////////////////////////////////////////
5083 ///////////////////////////////////////////////////////////////////////
5084
5085
5086 //=========================================================================
5087 /// Base class for elements that can specify a drag and torque
5088 /// (about the origin) -- typically used for immersed particle
5089 /// computations.
5090 //=========================================================================
5092 {
5093 public:
5094 /// Empty constructor
5096
5097 /// Empty virtual destructor
5099
5100 /// Function that specifies the drag force and the torque about
5101 /// the origin
5102 virtual void get_drag_and_torque(Vector<double>& drag_force,
5104 };
5105
5106
5107 ///////////////////////////////////////////////////////////////////////
5108 ///////////////////////////////////////////////////////////////////////
5109 ///////////////////////////////////////////////////////////////////////
5110
5111
5112 //======================================================================
5113 /// Basic-ified FaceElement, without any of the functionality of
5114 /// of actual FaceElements -- it's just a surface element of the
5115 /// same geometric type as the FaceGeometry associated with
5116 /// bulk element specified by the template parameter. The element
5117 /// can be used to represent boundaries without actually being
5118 /// attached to a bulk element. Used mainly during unstructured
5119 /// mesh generation.
5120 //======================================================================
5121 template<class ELEMENT>
5122 class FreeStandingFaceElement : public virtual FaceGeometry<ELEMENT>
5123 {
5124 public:
5125 /// Constructor
5128 {
5129 // Check whether things have been set
5130#ifdef PARANOID
5132#endif
5133 }
5134
5135 /// Access function for the boundary number in bulk mesh
5136 inline const unsigned& boundary_number_in_bulk_mesh() const
5137 {
5139 }
5140
5141
5142 /// Set function for the boundary number in bulk mesh
5143 inline void set_boundary_number_in_bulk_mesh(const unsigned& b)
5144 {
5146#ifdef PARANOID
5148#endif
5149 }
5150
5151 /// In a FaceElement, the "global" intrinsic coordinate
5152 /// of the element along the boundary, when viewed as part of
5153 /// a compound geometric object is specified using the
5154 /// boundary coordinate defined by the mesh.
5155 /// Note: Boundary coordinates will have been set up when
5156 /// creating the underlying mesh, and their values will have
5157 /// been stored at the nodes.
5158 double zeta_nodal(const unsigned& n,
5159 const unsigned& k,
5160 const unsigned& i) const
5161 {
5162 // Vector in which to hold the intrinsic coordinate
5163 Vector<double> zeta(this->dim());
5164
5165 // Get the k-th generalised boundary coordinate at node n
5166 this->node_pt(n)->get_coordinates_on_boundary(
5168
5169 // Return the individual coordinate
5170 return zeta[i];
5171 }
5172
5173 protected:
5174 /// The boundary number in the bulk mesh to which this element is attached
5176
5177#ifdef PARANOID
5178
5179 /// Has the Boundary_number_in_bulk_mesh been set? Only included if
5180 /// compiled with PARANOID switched on.
5182
5183#endif
5184 };
5185
5186
5187 ///////////////////////////////////////////////////////////////////////
5188 ///////////////////////////////////////////////////////////////////////
5189 ///////////////////////////////////////////////////////////////////////
5190
5191
5192 //======================================================================
5193 /// Pure virtual base class for elements that can be used with
5194 /// PressureBasedSolidLSCPreconditioner.
5195 //======================================================================
5197 {
5198 public:
5199 /// Empty constructor
5201
5202 /// Virtual destructor
5204
5205 /// Broken copy constructor
5207 const SolidElementWithDiagonalMassMatrix&) = delete;
5208
5209 /// Broken assignment operator
5211
5212 /// Get the diagonal of whatever represents the mass matrix
5213 /// in the specific preconditionable element. For Navier-Stokes
5214 /// elements this is the velocity mass matrix; for incompressible solids
5215 /// it's the mass matrix; ...
5217 };
5218
5219
5220 ///////////////////////////////////////////////////////////////////////
5221 ///////////////////////////////////////////////////////////////////////
5222 ///////////////////////////////////////////////////////////////////////
5223
5224
5225 //======================================================================
5226 /// Pure virtual base class for elements that can be used with
5227 /// Navier-Stokes Schur complement preconditioner and provide the diagonal
5228 /// of their velocity and pressure mass matrices -- needs to be defined here
5229 /// (in generic) because this applies to a variety of Navier-Stokes
5230 /// elements (cartesian, cylindrical polar, ...)
5231 /// that can be preconditioned effectively by the Navier Stokes (!)
5232 /// preconditioners in the (cartesian) Navier-Stokes directory.
5233 //======================================================================
5235 {
5236 public:
5237 /// Empty constructor
5239
5240 /// Virtual destructor
5242
5243 /// Broken copy constructor
5246
5247 /// Broken assignment operator
5249
5250 /// Compute the diagonal of the velocity/pressure mass matrices.
5251 /// If which one=0, both are computed, otherwise only the pressure
5252 /// (which_one=1) or the velocity mass matrix (which_one=2 -- the
5253 /// LSC version of the preconditioner only needs that one)
5257 const unsigned& which_one = 0) = 0;
5258 };
5259
5260
5261 ///////////////////////////////////////////////////////////////////////
5262 ///////////////////////////////////////////////////////////////////////
5263 ///////////////////////////////////////////////////////////////////////
5264
5265
5266 //=======================================================================
5267 /// A class to specify when the error is caused by an inverted element.
5268 //=======================================================================
5270 {
5271 public:
5273 const std::string& function_name,
5274 const char* location)
5276 {
5277 }
5278 };
5279
5280} // namespace oomph
5281
5282#endif
static char t char * s
Definition cfortran.h:568
cstr elem_len * i
Definition cfortran.h:603
char t
Definition cfortran.h:568
A class that contains the information required by Nodes that are located on Mesh boundaries....
Definition nodes.h:1996
A Class for the derivatives of shape functions The class design is essentially the same as Shape,...
Definition shape.h:278
A class that represents a collection of data; each Data object may contain many different individual ...
Definition nodes.h:86
TimeStepper *& time_stepper_pt()
Return the pointer to the timestepper.
Definition nodes.h:238
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition nodes.h:483
void set_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Set a new timestepper by resizing the appropriate storage. If already assigned the equation numbering...
Definition nodes.cc:406
Dummy FaceElement for use with purely geometric operations such as mesh generation.
Definition elements.h:5018
DummyFaceElement()
Constructor.
Definition elements.h:5032
void output(std::ostream &outfile)
Output nodal coordinates.
Definition elements.h:5046
double zeta_nodal(const unsigned &n, const unsigned &k, const unsigned &i) const
The "global" intrinsic coordinate of the element when viewed as part of a geometric object should be ...
Definition elements.h:5038
void output(FILE *file_pt, const unsigned &n_plot)
C_style output at n_plot points.
Definition elements.h:5075
void output(std::ostream &outfile, const unsigned &n_plot)
Output at n_plot points.
Definition elements.h:5063
DummyFaceElement(FiniteElement *const &element_pt, const int &face_index)
Constructor, which takes a "bulk" element and the face index.
Definition elements.h:5022
void output(FILE *file_pt)
C-style output.
Definition elements.h:5069
Base class for elements that can specify a drag and torque (about the origin) – typically used for im...
Definition elements.h:5092
virtual void get_drag_and_torque(Vector< double > &drag_force, Vector< double > &drag_torque)=0
Function that specifies the drag force and the torque about the origin.
virtual ~ElementWithDragFunction()
Empty virtual destructor.
Definition elements.h:5098
ElementWithDragFunction()
Empty constructor.
Definition elements.h:5095
FaceElements are elements that coincide with the faces of higher-dimensional "bulk" elements....
Definition elements.h:4342
void interpolated_x(const Vector< double > &s, Vector< double > &x) const
Return FE interpolated position x[] at local coordinate s as Vector Overloaded to get information fro...
Definition elements.h:4559
void turn_on_warning_for_discontinuous_tangent()
Turn on warning for when there may be discontinuous tangent vectors from continuous_tangent_and_outer...
Definition elements.h:4697
int & normal_sign()
Sign of outer unit normal (relative to cross-products of tangent vectors in the corresponding "bulk" ...
Definition elements.h:4616
double interpolated_dxdt(const Vector< double > &s, const unsigned &i, const unsigned &t)
Return t-th time-derivative of the i-th FE-interpolated Eulerian coordinate at local coordinate s....
Definition elements.h:4587
unsigned nbulk_value(const unsigned &n) const
Return the number of values originally stored at local node n (before the FaceElement added additiona...
Definition elements.h:4857
bool Boundary_number_in_bulk_mesh_has_been_set
Has the Boundary_number_in_bulk_mesh been set? Only included if compiled with PARANOID switched on.
Definition elements.h:4398
unsigned Boundary_number_in_bulk_mesh
The boundary number in the bulk mesh to which this element is attached.
Definition elements.h:4392
int & face_index()
Index of the face (a number that uniquely identifies the face in the element)
Definition elements.h:4630
void continuous_tangent_and_outer_unit_normal(const Vector< double > &s, Vector< Vector< double > > &tang_vec, Vector< double > &unit_normal) const
Compute the tangent vector(s) and the outer unit normal vector at the specified local coordinate....
Definition elements.cc:5543
const unsigned & boundary_number_in_bulk_mesh() const
Broken assignment operator.
Definition elements.h:4479
CoordinateMappingFctPt face_to_bulk_coordinate_fct_pt() const
Return the pointer to the function that maps the face coordinate to the bulk coordinate (const versio...
Definition elements.h:4766
Vector< unsigned > Bulk_node_number
List of indices of the local node numbers in the "bulk" element that correspond to the local node num...
Definition elements.h:4407
FiniteElement * Bulk_element_pt
Pointer to the associated higher-dimensional "bulk" element.
Definition elements.h:4403
void bulk_node_number_resize(const unsigned &i)
Resize the storage for the bulk node numbers.
Definition elements.h:4822
int face_index() const
Index of the face (a number that uniquely identifies the face in the element) (const version)
Definition elements.h:4637
BulkCoordinateDerivativesFctPt bulk_coordinate_derivatives_fct_pt() const
Return the pointer to the function that returns the derivatives of the bulk coordinates wrt the face ...
Definition elements.h:4781
BulkCoordinateDerivativesFctPt & bulk_coordinate_derivatives_fct_pt()
Return the pointer to the function that returns the derivatives of the bulk coordinates wrt the face ...
Definition elements.h:4774
void outer_unit_normal(const Vector< double > &s, Vector< double > &unit_normal) const
Compute outer unit normal at the specified local coordinate.
Definition elements.cc:6037
void turn_off_warning_for_discontinuous_tangent()
Turn off warning for when there may be discontinuous tangent vectors from continuous_tangent_and_oute...
Definition elements.h:4704
int Face_index
Index of the face.
Definition elements.h:4381
double zeta_nodal(const unsigned &n, const unsigned &k, const unsigned &i) const
In a FaceElement, the "global" intrinsic coordinate of the element along the boundary,...
Definition elements.h:4501
int Normal_sign
Sign of outer unit normal (relative to cross-products of tangent vectors in the corresponding "bulk" ...
Definition elements.h:4378
BulkCoordinateDerivativesFctPt Bulk_coordinate_derivatives_fct_pt
Pointer to a function that returns the derivatives of the local "bulk" coordinates with respect to th...
Definition elements.h:4365
Vector< double > local_coordinate_in_bulk(const Vector< double > &s) const
Return vector of local coordinates in bulk element, given the local coordinates in this FaceElement.
Definition elements.cc:6384
FaceElement()
Constructor: Initialise all appropriate member data.
Definition elements.h:4450
void add_additional_values(const Vector< unsigned > &nadditional_values, const unsigned &id)
Helper function adding additional values for the unknowns associated with the FaceElement....
Definition elements.h:4432
void(* BulkCoordinateDerivativesFctPt)(const Vector< double > &s, DenseMatrix< double > &ds_bulk_dsface, unsigned &interior_direction)
Typedef for the function that returns the partial derivative of the local coordinates in the bulk ele...
Definition elements.h:4353
Vector< double > * Tangent_direction_pt
A general direction pointer for the tangent vectors. This is used in the function continuous_tangent_...
Definition elements.h:4424
void interpolated_x(const unsigned &t, const Vector< double > &s, Vector< double > &x) const
Return FE interpolated position x[] at local coordinate s at previous timestep t as Vector (t=0: pres...
Definition elements.h:4572
const Vector< double > * tangent_direction_pt() const
Public access function for the tangent direction pointer.
Definition elements.h:4643
unsigned & nbulk_value(const unsigned &n)
Return the number of values originally stored at local node n (before the FaceElement added additiona...
Definition elements.h:4849
int normal_sign() const
Return sign of outer unit normal (relative to cross-products of tangent vectors in the corresponding ...
Definition elements.h:4623
double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s. Overloaded to get information from bulk...
Definition elements.h:4532
unsigned & bulk_node_number(const unsigned &n)
Return the bulk node number that corresponds to the n-th local node number.
Definition elements.h:4829
void bulk_position_type_resize(const unsigned &i)
Resize the storage for bulk_position_type to i entries.
Definition elements.h:4842
const unsigned & bulk_node_number(const unsigned &n) const
Return the bulk node number that corresponds to the n-th local node number (const version)
Definition elements.h:4836
FiniteElement *& bulk_element_pt()
Pointer to higher-dimensional "bulk" element.
Definition elements.h:4739
double J_eulerian(const Vector< double > &s) const
Return the Jacobian of mapping from local to global coordinates at local position s....
Definition elements.cc:5273
Vector< unsigned > Bulk_position_type
Vector holding integers to translate additional position types to those of the "bulk" element; e....
Definition elements.h:4374
static bool Ignore_discontinuous_tangent_warning
Ignores the warning when the tangent vectors from continuous_tangent_and_outer_unit_normal may not be...
Definition elements.h:4388
void set_tangent_direction(Vector< double > *tangent_direction_pt)
Set the tangent direction vector.
Definition elements.h:4649
double J_eulerian_at_knot(const unsigned &ipt) const
Return the Jacobian of the mapping from local to global coordinates at the ipt-th integration point O...
Definition elements.cc:5359
void(* CoordinateMappingFctPt)(const Vector< double > &s, Vector< double > &s_bulk)
Typedef for the function that translates the face coordinate to the coordinate in the bulk element.
Definition elements.h:4345
void set_boundary_number_in_bulk_mesh(const unsigned &b)
Set function for the boundary number in bulk mesh.
Definition elements.h:4486
void check_J_eulerian_at_knots(bool &passed) const
Check that Jacobian of mapping between local and Eulerian coordinates at all integration points is po...
Definition elements.cc:5441
Vector< unsigned > Nbulk_value
A vector that will hold the number of data values at the nodes that are associated with the "bulk" el...
Definition elements.h:4417
const unsigned & bulk_position_type(const unsigned &i) const
Return the position type in the "bulk" element that corresponds to the position type i on the FaceEle...
Definition elements.h:4816
unsigned & bulk_position_type(const unsigned &i)
Return the position type in the "bulk" element that corresponds to position type i on the FaceElement...
Definition elements.h:4809
void get_ds_bulk_ds_face(const Vector< double > &s, DenseMatrix< double > &dsbulk_dsface, unsigned &interior_direction) const
Calculate the derivatives of the local coordinates in the bulk element with respect to the local coor...
Definition elements.cc:6440
double interpolated_x(const unsigned &t, const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s at previous timestep t (t=0: present; t>...
Definition elements.h:4545
void get_local_coordinate_in_bulk(const Vector< double > &s, Vector< double > &s_bulk) const
Calculate the vector of local coordinate in the bulk element given the local coordinates in this Face...
Definition elements.cc:6415
CoordinateMappingFctPt Face_to_bulk_coordinate_fct_pt
Pointer to a function that translates the face coordinate to the coordinate in the bulk element.
Definition elements.h:4361
FiniteElement * bulk_element_pt() const
Pointer to higher-dimensional "bulk" element (const version)
Definition elements.h:4746
CoordinateMappingFctPt & face_to_bulk_coordinate_fct_pt()
Return the pointer to the function that maps the face coordinate to the bulk coordinate.
Definition elements.h:4759
void output_zeta(std::ostream &outfile, const unsigned &nplot)
Output boundary coordinate zeta.
Definition elements.cc:5231
void resize_nodes(Vector< unsigned > &nadditional_data_values)
Provide additional storage for a specified number of values at the nodes of the FaceElement....
Definition elements.h:4886
void interpolated_dxdt(const Vector< double > &s, const unsigned &t, Vector< double > &dxdt)
Compte t-th time-derivative of the FE-interpolated Eulerian coordinate vector at local coordinate s....
Definition elements.h:4602
FaceElement(const FaceElement &)=delete
Broken copy constructor.
virtual ~FaceElement()
Empty virtual destructor.
Definition elements.h:4469
void nbulk_value_resize(const unsigned &i)
Resize the storage for the number of values originally stored at the local nodes to i entries.
Definition elements.h:4864
FaceGeometry class definition: This policy class is used to allow construction of face elements that ...
Definition elements.h:5002
A general Finite Element class.
Definition elements.h:1317
virtual void scalar_value_paraview(std::ofstream &file_out, const unsigned &i, const unsigned &nplot) const
Write values of the i-th scalar field at the plot points. Broken virtual. Needs to be implemented for...
Definition elements.h:3005
virtual void write_tecplot_zone_footer(FILE *file_pt, const unsigned &nplot) const
Add tecplot zone "footer" to C-style output. (when plotting nplot points in each "coordinate directio...
Definition elements.h:3185
virtual void output(const unsigned &t, std::ostream &outfile, const unsigned &n_plot) const
Output the element data at time step t. This is const because it is newly added and so can be done ea...
Definition elements.h:3075
virtual unsigned nplot_points_paraview(const unsigned &nplot) const
Return the number of actual plot points for paraview plot with parameter nplot. Broken virtual; can b...
Definition elements.h:2866
virtual double J_eulerian(const Vector< double > &s) const
Return the Jacobian of mapping from local to global coordinates at local position s.
Definition elements.cc:4133
virtual void output_fct(std::ostream &outfile, const unsigned &n_plot, const double &time, const SolutionFunctorBase &exact_soln) const
Output a time-dependent exact solution over the element.
Definition elements.h:3134
virtual int face_outer_unit_normal_sign(const int &face_index) const
Get the sign of the outer unit normal on the face given by face_index.
Definition elements.h:3384
double d2shape_eulerian(const Vector< double > &s, Shape &psi, DShape &dpsidx, DShape &d2psidx) const
Compute the geometric shape functions and also first and second derivatives w.r.t....
Definition elements.cc:3478
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Add the elemental contribution to the jacobian matrix. and the residuals vector. Note that this funct...
Definition elements.h:1739
virtual void update_before_nodal_fd()
Function that is called before the finite differencing of any nodal data. This may be overloaded to u...
Definition elements.h:1713
virtual void identify_geometric_data(std::set< Data * > &geometric_data_pt)
The purpose of this function is to identify all Data objects that affect the elements' geometry....
Definition elements.h:2793
void get_x(const unsigned &t, const Vector< double > &s, Vector< double > &x)
Global coordinates as function of local coordinates at previous time "level" t (t=0: present; t>0: pr...
Definition elements.h:1908
double dJ_eulerian_at_knot(const unsigned &ipt, Shape &psi, DenseMatrix< double > &djacobian_dX) const
Compute the geometric shape functions (psi) at integration point ipt. Return the determinant of the j...
Definition elements.cc:3384
void set_nodal_dimension(const unsigned &nodal_dim)
Set the dimension of the nodes in the element. This will typically only be required when constructing...
Definition elements.h:1394
double raw_dnodal_position_gen_dt(const unsigned &j, const unsigned &n, const unsigned &k, const unsigned &i) const
i-th component of j-th time derivative of the generalised position, dx(k,i)/dt at local node n....
Definition elements.h:2309
void dposition_dt(const Vector< double > &zeta, const unsigned &t, Vector< double > &drdt)
Return the t-th time derivative of the parametrised position of the FiniteElement in its GeomObject i...
Definition elements.h:2705
Node *const & node_pt(const unsigned &n) const
Return a pointer to the local node n (const version)
Definition elements.h:2196
virtual void set_macro_elem_pt(MacroElement *macro_elem_pt)
Set pointer to macro element – can be overloaded in derived elements to perform additional tasks.
Definition elements.h:1876
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition elements.h:1967
void position(const Vector< double > &zeta, Vector< double > &r) const
Return the parametrised position of the FiniteElement in its incarnation as a GeomObject,...
Definition elements.h:2680
double dnodal_position_dt(const unsigned &n, const unsigned &j, const unsigned &i) const
Return the i-th component of j-th derivative of nodal position: d^jx/dt^j at node n.
Definition elements.h:2344
virtual void dshape_local_at_knot(const unsigned &ipt, Shape &psi, DShape &dpsids) const
Return the geometric shape function and its derivative w.r.t. the local coordinates at the ipt-th int...
Definition elements.cc:3269
virtual void output_fct(std::ostream &outfile, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output an exact solution over the element.
Definition elements.h:3108
virtual void local_coordinate_of_node(const unsigned &j, Vector< double > &s) const
Get local coordinates of node j in the element; vector sets its own size (broken virtual)
Definition elements.h:1846
double raw_nodal_position(const unsigned &t, const unsigned &n, const unsigned &i) const
Return the i-th coordinate at local node n, at time level t (t=0: present; t>0: previous time level)....
Definition elements.h:2251
void d_dshape_eulerian_dnodal_coordinates_templated_helper(const double &det_jacobian, const DenseMatrix< double > &jacobian, const DenseMatrix< double > &djacobian_dX, const DenseMatrix< double > &inverse_jacobian, const DShape &dpsids, RankFourTensor< double > &d_dpsidx_dX) const
Calculate the derivative w.r.t. the nodal coordinates of the derivative of the shape functions w....
Integral * Integral_pt
Pointer to the spatial integration scheme.
Definition elements.h:1320
void set_nnodal_position_type(const unsigned &nposition_type)
Set the number of types required to interpolate the coordinate.
Definition elements.h:1400
double nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n. Produces suitably interpolated values for hanging nodes...
Definition elements.h:2597
virtual void output_fct(std::ostream &outfile, const unsigned &n_plot, const double &time, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt)
Output a time-dependent exact solution over the element.
Definition elements.h:3121
virtual void output(std::ostream &outfile)
Output the element data — typically the values at the nodes in a format suitable for post-processing.
Definition elements.h:3054
virtual void transform_derivatives(const DenseMatrix< double > &inverse_jacobian, DShape &dbasis) const
Convert derivative w.r.t.local coordinates to derivatives w.r.t the coordinates used to assemble the ...
Definition elements.cc:2863
virtual unsigned get_bulk_node_number(const int &face_index, const unsigned &i) const
Get the number of the ith node on face face_index (in the bulk node vector).
Definition elements.h:3375
virtual Node * get_node_at_local_coordinate(const Vector< double > &s) const
If there is a node at this local coordinate, return the pointer to the node.
Definition elements.cc:3912
virtual std::string tecplot_zone_string(const unsigned &nplot) const
Return string for tecplot zone header (when plotting nplot points in each "coordinate direction")
Definition elements.h:3165
Data * geom_data_pt(const unsigned &j)
A standard FiniteElement is fixed, so there are no geometric data when viewed in its GeomObject incar...
Definition elements.h:2671
virtual double s_min() const
Min value of local coordinate.
Definition elements.h:2797
virtual double dshape_eulerian_at_knot(const unsigned &ipt, Shape &psi, DShape &dpsidx) const
Return the geometric shape functions and also first derivatives w.r.t. global coordinates at the ipt-...
Definition elements.cc:3355
unsigned nnodal_position_type() const
Return the number of coordinate types that the element requires to interpolate the geometry between t...
Definition elements.h:2467
virtual void compute_error(FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, Vector< double > &error, Vector< double > &norm)
Given the exact solution this function calculates the norm of the error and that of the exact soluti...
Definition elements.h:3243
double nodal_value(const unsigned &t, const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n, at time level t (t=0: present; t>0 previous timesteps)....
Definition elements.h:2605
virtual void assign_nodal_local_eqn_numbers(const bool &store_local_dof_pt)
Assign the local equation numbers for Data stored at the nodes Virtual so that it can be overloaded b...
Definition elements.cc:3574
virtual void local_fraction_of_node(const unsigned &j, Vector< double > &s_fraction)
Get the local fraction of the node j in the element A dumb, but correct default implementation is pro...
Definition elements.cc:3221
virtual double invert_jacobian_mapping(const DenseMatrix< double > &jacobian, DenseMatrix< double > &inverse_jacobian) const
A template-free interface that takes the matrix passed as jacobian and return its inverse in inverse_...
Definition elements.cc:2196
void interpolated_zeta(const Vector< double > &s, Vector< double > &zeta) const
Calculate the interpolated value of zeta, the intrinsic coordinate of the element when viewed as a co...
Definition elements.cc:4705
virtual void update_in_nodal_fd(const unsigned &i)
Function called within the finite difference loop for nodal data after a change in the i-th nodal val...
Definition elements.h:1722
virtual unsigned nvertex_node() const
Return the number of vertex nodes in this element. Broken virtual function in "pure" finite elements.
Definition elements.h:2495
double dnodal_position_gen_dt(const unsigned &n, const unsigned &k, const unsigned &i) const
i-th component of time derivative (velocity) of the generalised position, dx(k,i)/dt at local node n....
Definition elements.h:2373
virtual double local_to_eulerian_mapping_diagonal(const DShape &dpsids, DenseMatrix< double > &jacobian, DenseMatrix< double > &inverse_jacobian) const
Calculate the mapping from local to Eulerian coordinates given the derivatives of the shape functions...
Definition elements.cc:2618
double size() const
Calculate the size of the element (length, area, volume,...) in Eulerian computational coordinates....
Definition elements.cc:4320
virtual std::string scalar_name_paraview(const unsigned &i) const
Name of the i-th scalar field. Default implementation returns V1 for the first one,...
Definition elements.h:3047
static double Tolerance_for_singular_jacobian
Tolerance below which the jacobian is considered singular.
Definition elements.h:1774
virtual void fill_in_jacobian_from_nodal_by_fd(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Calculate the contributions to the jacobian from the nodal degrees of freedom using finite difference...
Definition elements.cc:3690
void locate_zeta(const Vector< double > &zeta, GeomObject *&geom_object_pt, Vector< double > &s, const bool &use_coordinate_as_initial_guess=false)
For a given value of zeta, the "global" intrinsic coordinate of a mesh of FiniteElements represented ...
Definition elements.cc:4764
void check_jacobian(const double &jacobian) const
Helper function used to check for singular or negative Jacobians in the transform from local to globa...
Definition elements.cc:1778
virtual void d2shape_local_at_knot(const unsigned &ipt, Shape &psi, DShape &dpsids, DShape &d2psids) const
Return the geometric shape function and its first and second derivatives w.r.t. the local coordinates...
Definition elements.cc:3304
virtual void d2shape_local(const Vector< double > &s, Shape &psi, DShape &dpsids, DShape &d2psids) const
Function to compute the geometric shape functions and also first and second derivatives w....
Definition elements.h:2020
virtual Node * construct_node(const unsigned &n)
Construct the local node n and return a pointer to the newly created node object.
Definition elements.h:2513
virtual void assign_all_generic_local_eqn_numbers(const bool &store_local_dof_pt)
Overloaded version of the calculation of the local equation numbers. If the boolean argument is true ...
Definition elements.h:2168
virtual unsigned required_nvalue(const unsigned &n) const
Number of values that must be stored at local node n by the element. The default is 0,...
Definition elements.h:2459
static const double Node_location_tolerance
Default value for the tolerance to be used when locating nodes via local coordinates.
Definition elements.h:1378
void point_output(std::ostream &outfile, const Vector< double > &s)
Output solution (as defined by point_output_data()) at local cordinates s.
Definition elements.h:2849
virtual void shape(const Vector< double > &s, Shape &psi) const =0
Calculate the geometric shape functions at local coordinate s. This function must be overloaded for e...
void set_dimension(const unsigned &dim)
Set the dimension of the element and initially set the dimension of the nodes to be the same as the d...
Definition elements.h:1384
virtual double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s.
Definition elements.cc:3992
int nodal_local_eqn(const unsigned &n, const unsigned &i) const
Return the local equation number corresponding to the i-th value at the n-th local node.
Definition elements.h:1436
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
Definition elements.h:2615
MacroElement * Macro_elem_pt
Pointer to the element's macro element (NULL by default)
Definition elements.h:1687
virtual void assemble_local_to_eulerian_jacobian(const DShape &dpsids, DenseMatrix< double > &jacobian) const
Assemble the jacobian matrix for the mapping from local to Eulerian coordinates, given the derivative...
Definition elements.cc:1935
double nodal_position_gen(const unsigned &n, const unsigned &k, const unsigned &i) const
Return the value of the k-th type of the i-th positional variable at the local node n.
Definition elements.h:2353
unsigned nnode() const
Return the number of nodes.
Definition elements.h:2214
virtual void disable_ALE()
This is an empty function that establishes a uniform interface for all (derived) elements that involv...
Definition elements.h:2412
virtual double s_max() const
Max. value of local coordinate.
Definition elements.h:2807
virtual ElementGeometry::ElementGeometry element_geometry() const
Return the geometry type of the element (either Q or T usually).
Definition elements.h:2621
void face_node_number_error_check(const unsigned &i) const
Range check for face node numbers.
Definition elements.h:3399
virtual void compute_error(FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
Calculate the norm of the error and that of the exact solution.
Definition elements.h:3202
unsigned Nodal_dimension
The spatial dimension of the nodes in the element. We assume that nodes have the same spatial dimensi...
Definition elements.h:1340
virtual void write_paraview_type(std::ofstream &file_out, const unsigned &nplot) const
Return the paraview element type. Broken virtual. Needs to be implemented for each new geometric elem...
Definition elements.h:2968
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution" as .
Definition elements.h:1763
virtual void compute_error(std::ostream &outfile, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, Vector< double > &error, Vector< double > &norm)
Plot the error when compared against a given time-dependent exact solution . Also calculates the norm...
Definition elements.h:3315
double nodal_position_gen(const unsigned &t, const unsigned &n, const unsigned &k, const unsigned &i) const
Return the generalised nodal position (type k, i-th variable) at previous timesteps at local node n.
Definition elements.h:2362
virtual void reset_in_nodal_fd(const unsigned &i)
Function called within the finite difference loop for nodal data after the i-th nodal values is reset...
Definition elements.h:1727
void transform_second_derivatives_template(const DenseMatrix< double > &jacobian, const DenseMatrix< double > &inverse_jacobian, const DenseMatrix< double > &jacobian2, DShape &dbasis, DShape &d2basis) const
Convert derivatives and second derivatives w.r.t. local coordinates to derivatives and second derivat...
void dJ_eulerian_dnodal_coordinates_templated_helper(const DenseMatrix< double > &jacobian, const DShape &dpsids, DenseMatrix< double > &djacobian_dX) const
Calculate the derivative of the jacobian of a mapping with respect to the nodal coordinates X_ij usin...
double dnodal_position_gen_dt(const unsigned &j, const unsigned &n, const unsigned &k, const unsigned &i) const
i-th component of j-th time derivative of the generalised position, dx(k,i)/dt at local node n....
Definition elements.h:2383
void get_x(const Vector< double > &s, Vector< double > &x) const
Global coordinates as function of local coordinates. Either via FE representation or via macro-elemen...
Definition elements.h:1889
virtual void output(FILE *file_pt)
Output the element data — typically the values at the nodes in a format suitable for post-processing....
Definition elements.h:3088
virtual Node * construct_node(const unsigned &n, TimeStepper *const &time_stepper_pt)
Construct the local node n, including storage for history values required by timestepper,...
Definition elements.h:2526
virtual void compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
Plot the error when compared against a given exact solution . Also calculates the norm of the error a...
Definition elements.h:3260
virtual void compute_error(FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, Vector< double > &error, Vector< double > &norm)
Given the exact solution this function calculates the norm of the error and that of the exact soluti...
Definition elements.h:3229
virtual void compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, Vector< double > &error, Vector< double > &norm)
Plot the error when compared against a given exact solution . Also calculates the norm of the error a...
Definition elements.h:3296
virtual double compute_physical_size() const
Broken virtual function to compute the actual size (taking into account factors such as 2pi or radii ...
Definition elements.h:2829
virtual double interpolated_dxdt(const Vector< double > &s, const unsigned &i, const unsigned &t)
Return t-th time-derivative of the i-th FE-interpolated Eulerian coordinate at local coordinate s.
Definition elements.cc:4626
virtual void compute_error(std::ostream &outfile, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, double &error, double &norm)
Plot the error when compared against a given time-dependent exact solution . Also calculates the norm...
Definition elements.h:3276
MacroElement * macro_elem_pt()
Access function to pointer to macro element.
Definition elements.h:1882
virtual void get_s_plot(const unsigned &i, const unsigned &nplot, Vector< double > &s, const bool &shifted_to_interior=false) const
Get cector of local coordinates of plot point i (when plotting nplot points in each "coordinate direc...
Definition elements.h:3152
virtual double zeta_nodal(const unsigned &n, const unsigned &k, const unsigned &i) const
Specify the values of the "global" intrinsic coordinate, zeta, of a compound geometric object (a mesh...
Definition elements.h:2726
virtual unsigned nscalar_paraview() const
Number of scalars/fields output by this element. Broken virtual. Needs to be implemented for each new...
Definition elements.h:2992
Node ** Node_pt
Storage for pointers to the nodes in the element.
Definition elements.h:1323
virtual Node * construct_boundary_node(const unsigned &n)
Construct the local node n as a boundary node; that is a node that MAY be placed on a mesh boundary a...
Definition elements.h:2542
virtual void compute_abs_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error)
Plot the error when compared against a given exact solution . Also calculates the maximum absolute er...
Definition elements.h:3334
double raw_dnodal_position_dt(const unsigned &n, const unsigned &j, const unsigned &i) const
Return the i-th component of j-th derivative of nodal position: d^jx/dt^j at node n....
Definition elements.h:2267
virtual double local_to_eulerian_mapping(const DShape &dpsids, DenseMatrix< double > &jacobian, DenseMatrix< double > &inverse_jacobian) const
Calculate the mapping from local to Eulerian coordinates, given the derivatives of the shape function...
Definition elements.h:1512
virtual BulkCoordinateDerivativesFctPt bulk_coordinate_derivatives_fct_pt(const int &face_index) const
Get a pointer to the derivative of the mapping from face to bulk coordinates.
Definition elements.h:3423
virtual void point_output_data(const Vector< double > &s, Vector< double > &data)
Virtual function to write the double precision numbers that appear in a single line of output into th...
Definition elements.h:2842
unsigned Nnodal_position_type
The number of coordinate types required to interpolate the element's geometry between the nodes....
Definition elements.h:1348
void get_centre_of_gravity_and_max_radius_in_terms_of_zeta(Vector< double > &cog, double &max_radius) const
Compute centre of gravity of all nodes and radius of node that is furthest from it....
Definition elements.cc:3954
virtual unsigned nplot_points(const unsigned &nplot) const
Return total number of plot points (when plotting nplot points in each "coordinate direction")
Definition elements.h:3190
virtual void reset_after_nodal_fd()
Function that is call after the finite differencing of the nodal data. This may be overloaded to rese...
Definition elements.h:1718
virtual void compute_error(FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, double &error, double &norm)
Calculate the norm of the error and that of the exact solution.
Definition elements.h:3213
double nodal_position(const unsigned &n, const unsigned &i) const
Return the i-th coordinate at local node n. If the node is hanging, the appropriate interpolation is ...
Definition elements.h:2321
double dshape_eulerian(const Vector< double > &s, Shape &psi, DShape &dpsidx) const
Compute the geometric shape functions and also first derivatives w.r.t. global coordinates at local c...
Definition elements.cc:3328
virtual void enable_ALE()
(Re-)enable ALE, i.e. take possible mesh motion into account when evaluating the time-derivative....
Definition elements.h:2434
unsigned Elemental_dimension
The spatial dimension of the element, i.e. the number of local coordinates used to parametrize it.
Definition elements.h:1334
void transform_second_derivatives_diagonal(const DenseMatrix< double > &jacobian, const DenseMatrix< double > &inverse_jacobian, const DenseMatrix< double > &jacobian2, DShape &dbasis, DShape &d2basis) const
Convert derivatives and second derivatives w.r.t. local coordinates to derivatives and second derivat...
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition elements.h:2179
virtual bool local_coord_is_valid(const Vector< double > &s)
Broken assignment operator.
Definition elements.h:1817
void check_J_eulerian_at_knots(bool &passed) const
Check that Jacobian of mapping between local and Eulerian coordinates at all integration points is po...
Definition elements.cc:4267
virtual void dshape_local(const Vector< double > &s, Shape &psi, DShape &dpsids) const
Function to compute the geometric shape functions and derivatives w.r.t. local coordinates at local c...
Definition elements.h:1985
virtual void move_local_coord_back_into_element(Vector< double > &s) const
Adjust local coordinates so that they're located inside the element.
Definition elements.h:1828
double raw_nodal_value(const unsigned &t, const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n, at time level t (t=0: present; t>0 previous timesteps),...
Definition elements.h:2588
FiniteElement(const FiniteElement &)=delete
Broken copy constructor.
virtual unsigned nsub_elements_paraview(const unsigned &nplot) const
Return the number of local sub-elements for paraview plot with parameter nplot. Broken virtual; can b...
Definition elements.h:2880
virtual void assemble_eulerian_base_vectors(const DShape &dpsids, DenseMatrix< double > &interpolated_G) const
Assemble the covariant Eulerian base vectors, assuming that the derivatives of the shape functions wi...
Definition elements.cc:2039
virtual void assemble_local_to_eulerian_jacobian2(const DShape &d2psids, DenseMatrix< double > &jacobian2) const
Assemble the the "jacobian" matrix of second derivatives of the mapping from local to Eulerian coordi...
Definition elements.cc:1993
virtual void d_dshape_eulerian_dnodal_coordinates(const double &det_jacobian, const DenseMatrix< double > &jacobian, const DenseMatrix< double > &djacobian_dX, const DenseMatrix< double > &inverse_jacobian, const DShape &dpsids, RankFourTensor< double > &d_dpsidx_dX) const
A template-free interface that calculates the derivative w.r.t. the nodal coordinates of the derivat...
Definition elements.cc:2779
void set_n_node(const unsigned &n)
Set the number of nodes in the element to n, by resizing the storage for pointers to the Node objects...
Definition elements.h:1408
virtual double J_eulerian_at_knot(const unsigned &ipt) const
Return the Jacobian of the mapping from local to global coordinates at the ipt-th integration point.
Definition elements.cc:4198
void integrate_fct(FiniteElement::SteadyExactSolutionFctPt integrand_fct_pt, Vector< double > &integral)
Evaluate integral of a Vector-valued function over the element.
Definition elements.cc:4407
double raw_dnodal_position_dt(const unsigned &n, const unsigned &i) const
Return the i-th component of nodal velocity: dx/dt at local node n. Do not use the hanging node repre...
Definition elements.h:2260
virtual void describe_local_dofs(std::ostream &out, const std::string &current_string) const
Function to describe the local dofs of the element[s]. The ostream specifies the output stream to whi...
Definition elements.cc:1737
virtual void build_face_element(const int &face_index, FaceElement *face_element_pt)
Function for building a lower dimensional FaceElement on the specified face of the FiniteElement....
Definition elements.cc:5163
virtual void transform_second_derivatives(const DenseMatrix< double > &jacobian, const DenseMatrix< double > &inverse_jacobian, const DenseMatrix< double > &jacobian2, DShape &dbasis, DShape &d2basis) const
Convert derivatives and second derivatives w.r.t. local coordiantes to derivatives and second derivat...
Definition elements.cc:3155
virtual void describe_nodal_local_dofs(std::ostream &out, const std::string &current_string) const
Function to describe the local dofs of the element[s]. The ostream specifies the output stream to whi...
Definition elements.cc:1755
double raw_dnodal_position_gen_dt(const unsigned &n, const unsigned &k, const unsigned &i) const
i-th component of time derivative (velocity) of the generalised position, dx(k,i)/dt at local node n....
Definition elements.h:2298
virtual void scalar_value_fct_paraview(std::ofstream &file_out, const unsigned &i, const unsigned &nplot, const double &time, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt) const
Write values of the i-th scalar field at the plot points. Broken virtual. Needs to be implemented for...
Definition elements.h:3031
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overload...
Definition elements.h:2222
unsigned nodal_dimension() const
Return the required Eulerian dimension of the nodes in this element.
Definition elements.h:2488
int ** Nodal_local_eqn
Storage for the local equation numbers associated with the values stored at the nodes.
Definition elements.h:1327
virtual ~FiniteElement()
The destructor cleans up the static memory allocated for shape function storage. Internal and externa...
Definition elements.cc:3203
double raw_nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n but do NOT take hanging nodes into account.
Definition elements.h:2580
virtual void get_x_from_macro_element(const Vector< double > &s, Vector< double > &x) const
Global coordinates as function of local coordinates using macro element representation....
Definition elements.h:1938
double raw_nodal_position(const unsigned &n, const unsigned &i) const
Return the i-th coordinate at local node n. Do not use the hanging node representation....
Definition elements.cc:1714
virtual void get_x_from_macro_element(const unsigned &t, const Vector< double > &s, Vector< double > &x)
Global coordinates as function of local coordinates at previous time "level" t (t=0: present; t>0: pr...
Definition elements.h:1952
virtual void node_update()
Update the positions of all nodes in the element using each node update function. The default impleme...
Definition elements.cc:5102
virtual void write_tecplot_zone_footer(std::ostream &outfile, const unsigned &nplot) const
Add tecplot zone "footer" to output stream (when plotting nplot points in each "coordinate direction"...
Definition elements.h:3178
virtual void scalar_value_fct_paraview(std::ofstream &file_out, const unsigned &i, const unsigned &nplot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt) const
Write values of the i-th scalar field at the plot points. Broken virtual. Needs to be implemented for...
Definition elements.h:3017
unsigned Nnode
Number of nodes in the element.
Definition elements.h:1330
virtual void set_integration_scheme(Integral *const &integral_pt)
Set the spatial integration scheme.
Definition elements.cc:3240
virtual Node * vertex_node_pt(const unsigned &j) const
Pointer to the j-th vertex node in the element. Broken virtual function in "pure" finite elements.
Definition elements.h:2504
void output_paraview(std::ofstream &file_out, const unsigned &nplot) const
Paraview output – this outputs the coordinates at the plot points (for parameter nplot) to specified ...
Definition elements.h:2893
static const unsigned N2deriv[]
Static array that holds the number of second derivatives as a function of the dimension of the elemen...
Definition elements.h:1487
void position(const unsigned &t, const Vector< double > &zeta, Vector< double > &r) const
Return the parametrised position of the FiniteElement in its GeomObject incarnation: r(zeta)....
Definition elements.h:2693
static bool Accept_negative_jacobian
Boolean that if set to true allows a negative jacobian in the transform between global and local coor...
Definition elements.h:1779
void(* UnsteadyExactSolutionFctPt)(const double &, const Vector< double > &, Vector< double > &)
Function pointer for function that computes Vector-valued time-dependent function as .
Definition elements.h:1769
double raw_nodal_position_gen(const unsigned &t, const unsigned &n, const unsigned &k, const unsigned &i) const
Return the generalised nodal position (type k, i-th variable) at previous timesteps at local node n....
Definition elements.h:2286
virtual unsigned nnode_on_face() const
Definition elements.h:3391
void transform_derivatives_diagonal(const DenseMatrix< double > &inverse_jacobian, DShape &dbasis) const
Convert derivative w.r.t local coordinates to derivatives w.r.t the coordinates used to assemble the ...
Definition elements.cc:2907
virtual double local_one_d_fraction_of_node(const unsigned &n1d, const unsigned &i)
Get the local fraction of any node in the n-th position in a one dimensional expansion along the i-th...
Definition elements.h:1862
double dnodal_position_dt(const unsigned &n, const unsigned &i) const
Return the i-th component of nodal velocity: dx/dt at local node n.
Definition elements.h:2337
double raw_nodal_position_gen(const unsigned &n, const unsigned &k, const unsigned &i) const
Return the value of the k-th type of the i-th positional variable at the local node n....
Definition elements.h:2276
virtual void output(FILE *file_pt, const unsigned &n_plot)
Output the element data — pass (some measure of) the number of plot points per element (C style outpu...
Definition elements.h:3099
FiniteElement()
Constructor.
Definition elements.h:1786
unsigned ngeom_data() const
A standard FiniteElement is fixed, so there are no geometric data when viewed in its GeomObject incar...
Definition elements.h:2664
virtual Node * construct_boundary_node(const unsigned &n, TimeStepper *const &time_stepper_pt)
Construct the local node n, including storage for history values required by timestepper,...
Definition elements.h:2556
virtual void get_dresidual_dnodal_coordinates(RankThreeTensor< double > &dresidual_dnodal_coordinates)
Compute derivatives of elemental residual vector with respect to nodal coordinates....
Definition elements.cc:3774
double nodal_position(const unsigned &t, const unsigned &n, const unsigned &i) const
Return the i-th coordinate at local node n, at time level t (t=0: present; t>0: previous time level) ...
Definition elements.h:2329
static bool Suppress_output_while_checking_for_inverted_elements
Static boolean to suppress output while checking for inverted elements.
Definition elements.h:1783
double invert_jacobian(const DenseMatrix< double > &jacobian, DenseMatrix< double > &inverse_jacobian) const
Take the matrix passed as jacobian and return its inverse in inverse_jacobian. This function is templ...
int get_node_number(Node *const &node_pt) const
Return the number of the node *node_pt if this node is in the element, else return -1;.
Definition elements.cc:3844
virtual void shape_at_knot(const unsigned &ipt, Shape &psi) const
Return the geometric shape function at the ipt-th integration point.
Definition elements.cc:3250
virtual double d2shape_eulerian_at_knot(const unsigned &ipt, Shape &psi, DShape &dpsidx, DShape &d2psidx) const
Return the geometric shape functions and also first and second derivatives w.r.t. global coordinates ...
Definition elements.cc:3532
virtual void identify_field_data_for_interactions(std::set< std::pair< Data *, unsigned > > &paired_field_data)
The purpose of this function is to identify all possible Data that can affect the fields interpolated...
Definition elements.cc:5127
virtual void dJ_eulerian_dnodal_coordinates(const DenseMatrix< double > &jacobian, const DShape &dpsids, DenseMatrix< double > &djacobian_dX) const
A template-free interface that calculates the derivative of the jacobian of a mapping with respect to...
Definition elements.cc:2699
virtual void write_paraview_offsets(std::ofstream &file_out, const unsigned &nplot, unsigned &offset_sum) const
Return the offsets for the paraview sub-elements. Broken virtual. Needs to be implemented for each ne...
Definition elements.h:2980
virtual CoordinateMappingFctPt face_to_bulk_coordinate_fct_pt(const int &face_index) const
Get a pointer to the function mapping face coordinates to bulk coordinates.
Definition elements.h:3413
static const unsigned Default_Initial_Nvalue
Default return value for required_nvalue(n) which gives the number of "data" values required by the e...
Definition elements.h:1374
bool has_hanging_nodes() const
Return boolean to indicate if any of the element's nodes are geometrically hanging.
Definition elements.h:2474
double local_to_eulerian_mapping(const DShape &dpsids, DenseMatrix< double > &inverse_jacobian) const
Calculate the mapping from local to Eulerian coordinates, given the derivatives of the shape function...
Definition elements.h:1528
virtual unsigned self_test()
Self-test: Check inversion of element & do self-test for GeneralisedElement. Return 0 if OK.
Definition elements.cc:4470
void fill_in_jacobian_from_nodal_by_fd(DenseMatrix< double > &jacobian)
Calculate the contributions to the jacobian from the nodal degrees of freedom using finite difference...
Definition elements.h:1699
virtual void output(std::ostream &outfile, const unsigned &n_plot)
Output the element data — pass (some measure of) the number of plot points per element.
Definition elements.h:3064
virtual void write_paraview_output_offset_information(std::ofstream &file_out, const unsigned &nplot, unsigned &counter) const
Fill in the offset information for paraview plot. Broken virtual. Needs to be implemented for each ne...
Definition elements.h:2956
Basic-ified FaceElement, without any of the functionality of of actual FaceElements – it's just a sur...
Definition elements.h:5123
void set_boundary_number_in_bulk_mesh(const unsigned &b)
Set function for the boundary number in bulk mesh.
Definition elements.h:5143
unsigned Boundary_number_in_bulk_mesh
The boundary number in the bulk mesh to which this element is attached.
Definition elements.h:5175
FreeStandingFaceElement()
Constructor.
Definition elements.h:5126
const unsigned & boundary_number_in_bulk_mesh() const
Access function for the boundary number in bulk mesh.
Definition elements.h:5136
bool Boundary_number_in_bulk_mesh_has_been_set
Has the Boundary_number_in_bulk_mesh been set? Only included if compiled with PARANOID switched on.
Definition elements.h:5181
double zeta_nodal(const unsigned &n, const unsigned &k, const unsigned &i) const
In a FaceElement, the "global" intrinsic coordinate of the element along the boundary,...
Definition elements.h:5158
A Generalised Element class.
Definition elements.h:73
void set_nonhalo()
Label the element as not being a halo.
Definition elements.h:1144
void fill_in_jacobian_from_external_by_fd(Vector< double > &residuals, DenseMatrix< double > &jacobian, const bool &fd_all_data=false)
Calculate the contributions to the jacobian from the external degrees of freedom using finite differe...
Definition elements.cc:1227
unsigned nexternal_data() const
Return the number of external data objects.
Definition elements.h:816
virtual void reset_in_external_fd(const unsigned &i)
Function called within the finite difference loop for external data after the values in the i-th exte...
Definition elements.h:488
virtual void get_dof_numbers_for_unknowns(std::list< std::pair< unsigned long, unsigned > > &dof_lookup_list) const
Create a list of pairs for the unknowns that this element is "in charge of" – ignore any unknowns ass...
Definition elements.h:1208
virtual void fill_in_contribution_to_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &mass_matrix)
Add the elemental contribution to the mass matrix matrix. and the residuals vector....
Definition elements.cc:1320
virtual unsigned ndof_types() const
The number of types of degrees of freedom in this element are sub-divided into.
Definition elements.h:1189
virtual void update_in_internal_fd(const unsigned &i)
Function called within the finite difference loop for internal data after a change in any values in t...
Definition elements.h:459
bool is_halo() const
Is this element a halo?
Definition elements.h:1150
virtual void reset_after_external_fd()
Function that is call after the finite differencing of the external data. This may be overloaded to r...
Definition elements.h:478
virtual void update_before_external_fd()
Function that is called before the finite differencing of any external data. This may be overloaded t...
Definition elements.h:473
bool Must_be_kept_as_halo
Does this element need to be kept as a halo element during a distribute?
Definition elements.h:131
void dof_vector(const unsigned &t, Vector< double > &dof)
Return the vector of dof values at time level t.
Definition elements.h:828
void assign_internal_eqn_numbers(unsigned long &global_number, Vector< double * > &Dof_pt)
Assign the global equation numbers to the internal Data. The arguments are the current highest global...
Definition elements.cc:534
static double Default_fd_jacobian_step
Double used for the default finite difference step in elemental jacobian calculations.
Definition elements.h:1185
void set_internal_data_time_stepper(const unsigned &i, TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Set the timestepper associated with the i-th internal data object.
Definition elements.h:880
void operator=(const GeneralisedElement &)=delete
Broken assignment operator.
static bool Suppress_warning_about_repeated_external_data
Static boolean to suppress warnings about repeated external data. Defaults to true.
Definition elements.h:687
virtual void get_hessian_vector_products(Vector< double > const &Y, DenseMatrix< double > const &C, DenseMatrix< double > &product)
Calculate the product of the Hessian (derivative of Jacobian with respect to all variables) an eigenv...
Definition elements.h:1070
bool internal_data_fd(const unsigned &i) const
Return the status of the boolean flag indicating whether the internal data is included in the finite ...
Definition elements.h:146
unsigned long * Eqn_number
Storage for the global equation numbers represented by the degrees of freedom in the element.
Definition elements.h:77
void read_internal_eqn_numbers_from_vector(const Vector< long > &vector_of_eqn_numbers, unsigned &index)
Read all equation numbers associated with internal data from the vector starting from index....
Definition elements.cc:675
virtual void fill_in_contribution_to_jacobian_and_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix)
Add the elemental contribution to the jacobian matrix, mass matrix and the residuals vector....
Definition elements.cc:1350
virtual void fill_in_contribution_to_djacobian_and_dmass_matrix_dparameter(double *const &parameter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam, DenseMatrix< double > &dmass_matrix_dparam)
Add the elemental contribution to the derivative of the jacobian matrix, mass matrix and the residual...
Definition elements.cc:1481
void fill_in_jacobian_from_internal_by_fd(DenseMatrix< double > &jacobian, const bool &fd_all_data=false)
Calculate the contributions to the jacobian from the internal degrees of freedom using finite differe...
Definition elements.h:401
virtual void fill_in_contribution_to_residuals(Vector< double > &residuals)
Add the elemental contribution to the residuals vector. Note that this function will NOT initialise t...
Definition elements.h:357
void fill_in_jacobian_from_internal_by_fd(Vector< double > &residuals, DenseMatrix< double > &jacobian, const bool &fd_all_data=false)
Calculate the contributions to the jacobian from the internal degrees of freedom using finite differe...
Definition elements.cc:1130
Data *& external_data_pt(const unsigned &i)
Return a pointer to i-th external data object.
Definition elements.h:642
bool external_data_fd(const unsigned &i) const
Return the status of the boolean flag indicating whether the external data is included in the finite ...
Definition elements.h:744
virtual void assign_all_generic_local_eqn_numbers(const bool &store_local_dof_pt)
Assign all the local equation numbering schemes that can be applied generically for the element....
Definition elements.h:253
void exclude_internal_data_fd(const unsigned &i)
Set the boolean flag to exclude the internal datum from the finite difference loop when computing the...
Definition elements.h:167
unsigned add_internal_data(Data *const &data_pt, const bool &fd=true)
Add a (pointer to an) internal data object to the element and return the index required to obtain it ...
Definition elements.cc:67
unsigned ndof() const
Return the number of equations/dofs in the element.
Definition elements.h:822
unsigned long eqn_number(const unsigned &ieqn_local) const
Return the global equation number corresponding to the ieqn_local-th local equation number.
Definition elements.h:691
int ** Data_local_eqn
Pointer to array storage for local equation numbers associated with internal and external data....
Definition elements.h:101
Data *& internal_data_pt(const unsigned &i)
Return a pointer to i-th internal data object.
Definition elements.h:605
int local_eqn_number(const unsigned long &ieqn_global) const
Return the local equation number corresponding to the ieqn_global-th global equation number....
Definition elements.h:713
void add_internal_data_values_to_vector(Vector< double > &vector_of_values)
Add all internal data and time history values to the vector in the internal storage order.
Definition elements.cc:633
void fill_in_jacobian_from_external_by_fd(DenseMatrix< double > &jacobian, const bool &fd_all_data=false)
Calculate the contributions to the jacobian from the external degrees of freedom using finite differe...
Definition elements.h:435
virtual void get_inner_product_vectors(Vector< unsigned > const &history_index, Vector< Vector< double > > &inner_product_vector)
Compute the vectors that when taken as a dot product with other history values give the inner product...
Definition elements.h:1093
static DenseMatrix< double > Dummy_matrix
Empty dense matrix used as a dummy argument to combined residual and jacobian functions in the case w...
Definition elements.h:227
virtual void assign_additional_local_eqn_numbers()
Setup any additional look-up schemes for local equation numbers. Examples of use include using local ...
Definition elements.h:263
Data *const & external_data_pt(const unsigned &i) const
Return a pointer to i-th external data object (const version)
Definition elements.h:660
GeneralisedElement(const GeneralisedElement &)=delete
Broken copy constructor.
virtual void get_inner_products(Vector< std::pair< unsigned, unsigned > > const &history_index, Vector< double > &inner_product)
Return the vector of inner product of the given pairs of history values.
Definition elements.h:1082
virtual void get_residuals(Vector< double > &residuals)
Calculate the vector of residuals of the equations in the element. By default initialise the vector t...
Definition elements.h:967
int non_halo_proc_ID()
ID of processor ID that holds non-halo counterpart of halo element; negative if not a halo.
Definition elements.h:1157
virtual void get_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &mass_matrix)
Calculate the residuals and the elemental "mass" matrix, the matrix that multiplies the time derivati...
Definition elements.h:990
void unset_must_be_kept_as_halo()
Do not insist that this element be kept as a halo element during distribution.
Definition elements.h:1170
virtual void get_dresiduals_dparameter(double *const &parameter_pt, Vector< double > &dres_dparam)
Calculate the derivatives of the residuals with respect to a parameter.
Definition elements.h:1021
virtual void fill_in_contribution_to_dresiduals_dparameter(double *const &parameter_pt, Vector< double > &dres_dparam)
Add the elemental contribution to the derivatives of the residuals with respect to a parameter....
Definition elements.cc:1386
static bool Suppress_warning_about_any_repeated_data
Static boolean to suppress warnings about repeated data. Defaults to false.
Definition elements.h:679
virtual ~GeneralisedElement()
Virtual destructor to clean up any memory allocated by the object.
Definition elements.cc:281
virtual void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Add the elemental contribution to the jacobian matrix. and the residuals vector. Note that this funct...
Definition elements.h:499
unsigned ninternal_data() const
Return the number of internal data objects.
Definition elements.h:810
bool must_be_kept_as_halo() const
Test whether the element must be kept as a halo element.
Definition elements.h:1176
int Non_halo_proc_ID
Non-halo processor ID for Data; -1 if it's not a halo.
Definition elements.h:128
void clear_global_eqn_numbers()
Clear the storage for the global equation numbers and pointers to dofs (if stored)
Definition elements.h:207
void include_internal_data_fd(const unsigned &i)
Set the boolean flag to include the internal datum in the finite difference loop when computing the j...
Definition elements.h:187
void dof_pt_vector(Vector< double * > &dof_pt)
Return the vector of pointers to dof values.
Definition elements.h:853
unsigned Ninternal_data
Number of internal data.
Definition elements.h:107
unsigned Nexternal_data
Number of external data.
Definition elements.h:110
void add_internal_value_pt_to_map(std::map< unsigned, double * > &map_of_value_pt)
Add pointers to the internal data values to map indexed by the global equation number.
Definition elements.cc:616
void add_global_eqn_numbers(std::deque< unsigned long > const &global_eqn_numbers, std::deque< double * > const &global_dof_pt)
Add the contents of the queue global_eqn_numbers to the local storage for the local-to-global transla...
Definition elements.cc:161
virtual void update_before_internal_fd()
Function that is called before the finite differencing of any internal data. This may be overloaded t...
Definition elements.h:449
virtual void reset_in_internal_fd(const unsigned &i)
Function called within the finite difference loop for internal data after the values in the i-th exte...
Definition elements.h:464
virtual void fill_in_contribution_to_djacobian_dparameter(double *const &parameter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam)
Add the elemental contribution to the derivatives of the elemental Jacobian matrix and residuals with...
Definition elements.cc:1430
virtual void fill_in_contribution_to_hessian_vector_products(Vector< double > const &Y, DenseMatrix< double > const &C, DenseMatrix< double > &product)
Fill in contribution to the product of the Hessian (derivative of Jacobian with respect to all variab...
Definition elements.cc:1531
unsigned Ndof
Number of degrees of freedom.
Definition elements.h:104
int internal_local_eqn(const unsigned &i, const unsigned &j) const
Return the local equation number corresponding to the j-th value stored at the i-th internal data.
Definition elements.h:267
virtual void describe_local_dofs(std::ostream &out, const std::string &current_string) const
Function to describe the local dofs of the element. The ostream specifies the output stream to which ...
Definition elements.cc:578
static std::deque< double * > Dof_pt_deque
Static storage for deque used to add_global_equation_numbers when pointers to the dofs in each elemen...
Definition elements.h:231
virtual void get_djacobian_and_dmass_matrix_dparameter(double *const &parameter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam, DenseMatrix< double > &dmass_matrix_dparam)
Calculate the derivatives of the elemental Jacobian matrix mass matrix and residuals with respect to ...
Definition elements.h:1048
virtual void assign_internal_and_external_local_eqn_numbers(const bool &store_local_dof_pt)
Assign the local equation numbers for the internal and external Data This must be called after the gl...
Definition elements.cc:966
virtual void fill_in_contribution_to_inner_products(Vector< std::pair< unsigned, unsigned > > const &history_index, Vector< double > &inner_product)
Fill in the contribution to the inner products between given pairs of history values.
Definition elements.cc:1571
virtual void fill_in_contribution_to_inner_product_vectors(Vector< unsigned > const &history_index, Vector< Vector< double > > &inner_product_vector)
Fill in the contributions to the vectors that when taken as dot product with other history values giv...
Definition elements.cc:1599
void set_halo(const unsigned &non_halo_proc_ID)
Label the element as halo and specify processor that holds non-halo counterpart.
Definition elements.h:1138
void add_internal_eqn_numbers_to_vector(Vector< long > &vector_of_eqn_numbers)
Add all equation numbers associated with internal data to the vector in the internal storage order.
Definition elements.cc:660
virtual void reset_after_internal_fd()
Function that is call after the finite differencing of the internal data. This may be overloaded to r...
Definition elements.h:454
void set_must_be_kept_as_halo()
Insist that this element be kept as a halo element during a distribute?
Definition elements.h:1163
virtual unsigned self_test()
Self-test: Have all internal values been classified as pinned/unpinned? Return 0 if OK.
Definition elements.cc:1631
virtual void get_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Calculate the elemental Jacobian matrix "d equation / d variable".
Definition elements.h:977
virtual void get_djacobian_dparameter(double *const &parameter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam)
Calculate the derivatives of the elemental Jacobian matrix and residuals with respect to a parameter.
Definition elements.h:1033
virtual void assign_local_eqn_numbers(const bool &store_local_dof_pt)
Setup the arrays of local equation numbers for the element. If the optional boolean argument is true,...
Definition elements.cc:696
void include_external_data_fd(const unsigned &i)
Set the boolean flag to include the external datum in the the finite difference loop when computing t...
Definition elements.h:785
Data ** Data_pt
Storage for pointers to internal and external data. The data is of the same type and so can be addres...
Definition elements.h:92
static bool Suppress_warning_about_repeated_internal_data
Static boolean to suppress warnings about repeated internal data. Defaults to false.
Definition elements.h:683
Data *const & internal_data_pt(const unsigned &i) const
Return a pointer to i-th internal data object (const version)
Definition elements.h:623
virtual void get_jacobian_and_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix)
Calculate the residuals and jacobian and elemental "mass" matrix, the matrix that multiplies the time...
Definition elements.h:1003
virtual void compute_norm(Vector< double > &norm)
Compute norm of solution – broken virtual can be overloaded by element writer to implement whatever n...
Definition elements.h:1115
double ** Dof_pt
Storage for array of pointers to degrees of freedom ordered by local equation number....
Definition elements.h:84
int external_local_eqn(const unsigned &i, const unsigned &j)
Return the local equation number corresponding to the j-th value stored at the i-th external data.
Definition elements.h:311
void describe_dofs(std::ostream &out, const std::string &current_string) const
Function to describe the dofs of the element. The ostream specifies the output stream to which the de...
Definition elements.cc:556
std::vector< bool > Data_fd
Storage for boolean flags of size Ninternal_data + Nexternal_data that correspond to the data used in...
Definition elements.h:122
void flush_external_data()
Flush all external data.
Definition elements.cc:392
virtual void complete_setup_of_dependencies()
Complete the setup of any additional dependencies that the element may have. Empty virtual function t...
Definition elements.h:961
virtual void compute_norm(double &norm)
Compute norm of solution – broken virtual can be overloaded by element writer to implement whatever n...
Definition elements.h:1127
void read_internal_data_values_from_vector(const Vector< double > &vector_of_values, unsigned &index)
Read all internal data and time history values from the vector starting from index....
Definition elements.cc:647
void exclude_external_data_fd(const unsigned &i)
Set the boolean flag to exclude the external datum from the the finite difference loop when computing...
Definition elements.h:765
virtual void update_in_external_fd(const unsigned &i)
Function called within the finite difference loop for external data after a change in any values in t...
Definition elements.h:483
unsigned add_external_data(Data *const &data_pt, const bool &fd=true)
Add a (pointer to an) external data object to the element and return its index (i....
Definition elements.cc:312
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.
TimeStepper *& time_stepper_pt()
Access function for pointer to time stepper: Null if object is not time-dependent.
Generic class for numerical integration schemes:
Definition integral.h:49
A class to specify when the error is caused by an inverted element.
Definition elements.h:5270
InvertedElementError(const std::string &error_description, const std::string &function_name, const char *location)
Definition elements.h:5272
Base class for MacroElement s that are used during mesh refinement in domains with curvlinear and/or ...
Pure virtual base class for elements that can be used with Navier-Stokes Schur complement preconditio...
Definition elements.h:5235
void operator=(const NavierStokesElementWithDiagonalMassMatrices &)=delete
Broken assignment operator.
virtual void get_pressure_and_velocity_mass_matrix_diagonal(Vector< double > &press_mass_diag, Vector< double > &veloc_mass_diag, const unsigned &which_one=0)=0
Compute the diagonal of the velocity/pressure mass matrices. If which one=0, both are computed,...
virtual ~NavierStokesElementWithDiagonalMassMatrices()
Virtual destructor.
Definition elements.h:5241
NavierStokesElementWithDiagonalMassMatrices(const NavierStokesElementWithDiagonalMassMatrices &)=delete
Broken copy constructor.
NavierStokesElementWithDiagonalMassMatrices()
Empty constructor.
Definition elements.h:5238
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition nodes.h:906
double dx_gen_dt(const unsigned &k, const unsigned &i) const
i-th component of time derivative (velocity) of the generalised position, dx(k,i)/dt....
Definition nodes.cc:1865
void position(Vector< double > &pos) const
Compute Vector of nodal positions either directly or via hanging node representation.
Definition nodes.cc:2499
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition nodes.h:1054
double position_gen(const unsigned &k, const unsigned &i) const
Return generalised nodal coordinate either directly or via hanging node representation.
Definition nodes.cc:2592
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition nodes.h:1060
virtual void get_coordinates_on_boundary(const unsigned &b, const unsigned &k, Vector< double > &boundary_zeta)
Return the vector of the k-th generalised boundary coordinates on mesh boundary b....
Definition nodes.cc:2379
double raw_value(const unsigned &i) const
Return the i-th value stored at the Node. This interface does NOT take the hanging status of the Node...
Definition nodes.h:1455
double dposition_dt(const unsigned &i) const
Return the i-th component of nodal velocity: dx/dt, either directly or via hanging node representatio...
Definition nodes.cc:2659
double dx_dt(const unsigned &i) const
Return the i-th component of nodal velocity: dx/dt.
Definition nodes.cc:1817
void resize(const unsigned &n_value)
Resize the number of equations.
Definition nodes.cc:2167
double & x_gen(const unsigned &k, const unsigned &i)
Reference to the generalised position x(k,i). ‘Type’: k; Coordinate direction: i.
Definition nodes.h:1126
double dposition_gen_dt(const unsigned &k, const unsigned &i) const
i-th component of time derivative (velocity) of the generalised position, dx(k,i)/dt....
Definition nodes.cc:2708
double value(const unsigned &i) const
Return i-th value (dofs or pinned) at this node either directly or via hanging node representation....
Definition nodes.cc:2408
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....
Point element has just a single node and a single shape function which is identically equal to one.
Definition elements.h:3443
PointElement()
Constructor.
Definition elements.h:3446
void shape(const Vector< double > &s, Shape &psi) const
Broken assignment operator.
Definition elements.cc:7560
PointElement(const PointElement &)=delete
Broken copy constructor.
static PointIntegral Default_integration_scheme
Return spatial dimension of element (=number of local coordinates needed to parametrise the element)
Definition elements.h:3477
void local_coordinate_of_node(const unsigned &j, Vector< double > &s) const
Get local coordinates of node j in the element; vector sets its own size.
Definition elements.h:3466
Broken pseudo-integration scheme for points elements: Iit's not clear in general what this integratio...
Definition integral.h:89
A Class for shape functions. In simple cases, the shape functions have only one index that can be tho...
Definition shape.h:76
Pure virtual base class for elements that can be used with PressureBasedSolidLSCPreconditioner.
Definition elements.h:5197
SolidElementWithDiagonalMassMatrix()
Empty constructor.
Definition elements.h:5200
void operator=(const SolidElementWithDiagonalMassMatrix &)=delete
Broken assignment operator.
SolidElementWithDiagonalMassMatrix(const SolidElementWithDiagonalMassMatrix &)=delete
Broken copy constructor.
virtual void get_mass_matrix_diagonal(Vector< double > &mass_diag)=0
Get the diagonal of whatever represents the mass matrix in the specific preconditionable element....
virtual ~SolidElementWithDiagonalMassMatrix()
Virtual destructor.
Definition elements.h:5203
SolidFaceElements combine FaceElements and SolidFiniteElements and overload various functions so they...
Definition elements.h:4918
double zeta_nodal(const unsigned &n, const unsigned &k, const unsigned &i) const
The "global" intrinsic coordinate of the element when viewed as part of a geometric object should be ...
Definition elements.h:4925
double interpolated_xi(const Vector< double > &s, const unsigned &i) const
Return i-th FE-interpolated Lagrangian coordinate xi[i] at local coordinate s. Overloaded from SolidF...
Definition elements.h:4941
void interpolated_xi(const Vector< double > &s, Vector< double > &xi) const
Compute FE interpolated Lagrangian coordinate vector xi[] at local coordinate s as Vector....
Definition elements.h:4961
SolidFiniteElement class.
Definition elements.h:3565
unsigned lagrangian_dimension() const
Return the number of Lagrangian coordinates that the element requires at all nodes....
Definition elements.h:3778
virtual void set_macro_elem_pt(MacroElement *macro_elem_pt, MacroElement *undeformed_macro_elem_pt)
Set pointers to "current" and "undeformed" MacroElements. Can be overloaded in derived classes to per...
Definition elements.h:3693
virtual void set_macro_elem_pt(MacroElement *macro_elem_pt)
Set pointer to MacroElement – overloads generic version and uses the MacroElement also as the default...
Definition elements.h:3684
Data * geom_data_pt(const unsigned &j)
Return pointer to the j-th Data item that the object's shape depends on. (Redirects to the nodes' pos...
Definition elements.h:3619
double lagrangian_position(const unsigned &n, const unsigned &i) const
Return i-th Lagrangian coordinate at local node n.
Definition elements.h:3909
void set_undeformed_macro_elem_pt(MacroElement *undeformed_macro_elem_pt)
Set pointer to "undeformed" macro element. Can be overloaded in derived classes to perform additional...
Definition elements.h:3703
void disable_solve_for_consistent_newmark_accel()
Set to reset the problem being solved to be the standard problem.
Definition elements.h:3976
void describe_solid_local_dofs(std::ostream &out, const std::string &current_string) const
Classifies dofs locally for solid specific aspects.
Definition elements.cc:6905
double lagrangian_position_gen(const unsigned &n, const unsigned &k, const unsigned &i) const
Return Generalised Lagrangian coordinate at local node n. ‘Direction’ i, ‘Type’ k.
Definition elements.h:3916
double(* MultiplierFctPt)(const Vector< double > &xi)
Pointer to function that computes the "multiplier" for the inertia terms in the consistent determinat...
Definition elements.h:3586
double raw_lagrangian_position_gen(const unsigned &n, const unsigned &k, const unsigned &i) const
Return Generalised Lagrangian coordinate at local node n. ‘Direction’ i, ‘Type’ k....
Definition elements.h:3901
Node * construct_boundary_node(const unsigned &n)
Construct the local node n and return a pointer to it. in the case when it is a boundary node; that i...
Definition elements.h:3831
MacroElement * undeformed_macro_elem_pt()
Access function to pointer to "undeformed" macro element.
Definition elements.h:3710
virtual void get_x_and_xi(const Vector< double > &s, Vector< double > &x_fe, Vector< double > &x, Vector< double > &xi_fe, Vector< double > &xi) const
Eulerian and Lagrangian coordinates as function of the local coordinates: The Eulerian position is re...
Definition elements.h:3663
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Overload the fill_in_contribution_to_jacobian() function to use finite differences to calculate the s...
Definition elements.h:4189
int * Position_local_eqn
Array to hold the local equation number information for the solid equations, whatever they may be.
Definition elements.h:4285
virtual void assemble_local_to_lagrangian_jacobian2(const DShape &d2psids, DenseMatrix< double > &jacobian2) const
Assemble the the "jacobian" matrix of second derivatives, given the second derivatives of the shape f...
Definition elements.cc:6617
void fill_in_jacobian_from_solid_position_by_fd(DenseMatrix< double > &jacobian)
Use finite differences to calculate the Jacobian entries corresponding to the solid positions.
Definition elements.h:4229
virtual void assign_solid_local_eqn_numbers(const bool &store_local_dof)
Assigns local equation numbers for the generic solid local equation numbering schemes....
Definition elements.cc:6929
double dshape_lagrangian(const Vector< double > &s, Shape &psi, DShape &dpsidxi) const
Calculate shape functions and derivatives w.r.t. Lagrangian coordinates at local coordinate s....
Definition elements.cc:6741
double raw_lagrangian_position(const unsigned &n, const unsigned &i) const
Return i-th Lagrangian coordinate at local node n without using the hanging representation.
Definition elements.h:3894
unsigned nnodal_lagrangian_type() const
Return the number of types of (generalised) nodal Lagrangian coordinates required to interpolate the ...
Definition elements.h:3789
void enable_solve_for_consistent_newmark_accel()
Set to alter the problem being solved when assigning the initial conditions for time-dependent proble...
Definition elements.h:3970
double zeta_nodal(const unsigned &n, const unsigned &k, const unsigned &i) const
In a SolidFiniteElement, the "global" intrinsic coordinate of the element when viewed as part of a co...
Definition elements.h:3646
unsigned Lagrangian_dimension
The Lagrangian dimension of the nodes stored in the element, / i.e. the number of Lagrangian coordina...
Definition elements.h:4289
virtual void update_before_solid_position_fd()
Function that is called before the finite differencing of any solid position data....
Definition elements.h:4244
bool Solve_for_consistent_newmark_accel_flag
Flag to indicate which system of equations to solve when assigning initial conditions for time-depend...
Definition elements.h:4306
MultiplierFctPt & multiplier_fct_pt()
Access function: Pointer to multiplicator function for assignment of consistent assignement of initia...
Definition elements.h:3983
MacroElement * Undeformed_macro_elem_pt
Pointer to the element's "undeformed" macro element (NULL by default)
Definition elements.h:4080
SolidInitialCondition * Solid_ic_pt
Pointer to object that specifies the initial condition.
Definition elements.h:4135
void fill_in_residuals_for_solid_ic(Vector< double > &residuals)
Fill in the residuals for the setup of an initial condition. The global equations are:
Definition elements.h:4022
virtual double d2shape_lagrangian_at_knot(const unsigned &ipt, Shape &psi, DShape &dpsidxi, DShape &d2psidxi) const
Return the geometric shape functions and also first and second derivatives w.r.t. Lagrangian coordina...
Definition elements.cc:6863
void fill_in_generic_jacobian_for_solid_ic(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag)
Helper function to fill in the residuals and (if flag==1) the Jacobian for the setup of an initial co...
Definition elements.cc:7407
virtual void J_lagrangian(const Vector< double > &s) const
Return the Jacobian of mapping from local to Lagrangian coordinates at local position s....
Definition elements.h:3940
unsigned ngeom_data() const
Broken assignment operator.
Definition elements.h:3612
void set_nnodal_lagrangian_type(const unsigned &nlagrangian_type)
Set the number of types required to interpolate the Lagrangian coordinates.
Definition elements.h:4074
SolidInitialCondition *& solid_ic_pt()
Pointer to object that describes the initial condition.
Definition elements.h:3959
virtual double local_to_lagrangian_mapping_diagonal(const DShape &dpsids, DenseMatrix< double > &jacobian, DenseMatrix< double > &inverse_jacobian) const
Calculate the mapping from local to Lagrangian coordinates given the derivatives of the shape functio...
Definition elements.cc:6674
unsigned Nnodal_lagrangian_type
The number of coordinate types requried to intepolate the Lagrangian coordinates in the element....
Definition elements.h:4297
virtual void update_in_solid_position_fd(const unsigned &i)
Function called within the finite difference loop for the solid position dat after a change in any va...
Definition elements.h:4254
int position_local_eqn(const unsigned &n, const unsigned &k, const unsigned &j) const
Access function that returns the local equation number that corresponds to the j-th coordinate of the...
Definition elements.h:4141
virtual double local_to_lagrangian_mapping(const DShape &dpsids, DenseMatrix< double > &jacobian, DenseMatrix< double > &inverse_jacobian) const
Calculate the mapping from local to lagrangian coordinates, given the derivatives of the shape functi...
Definition elements.h:4086
virtual void get_residuals_for_solid_ic(Vector< double > &residuals)
Compute the residuals for the setup of an initial condition. The global equations are:
Definition elements.h:4007
virtual void assemble_local_to_lagrangian_jacobian(const DShape &dpsids, DenseMatrix< double > &jacobian) const
Assemble the jacobian matrix for the mapping from local to lagrangian coordinates,...
Definition elements.cc:6559
virtual double interpolated_xi(const Vector< double > &s, const unsigned &i) const
Return i-th FE-interpolated Lagrangian coordinate xi[i] at local coordinate s.
Definition elements.cc:7135
void identify_geometric_data(std::set< Data * > &geometric_data_pt)
Specify Data that affects the geometry of the element by adding the position Data to the set that's p...
Definition elements.h:3628
virtual void reset_in_solid_position_fd(const unsigned &i)
Function called within the finite difference loop for solid position data after the values in the i-t...
Definition elements.h:4259
virtual void interpolated_dxids(const Vector< double > &s, DenseMatrix< double > &dxids) const
Compute derivatives of FE-interpolated Lagrangian coordinates xi with respect to local coordinates: d...
Definition elements.cc:7211
Node * construct_node(const unsigned &n)
Construct the local node n and return a pointer to it.
Definition elements.h:3795
Node * construct_node(const unsigned &n, TimeStepper *const &time_stepper_pt)
Construct the local node n and return a pointer to it. Additionally, create storage for ‘history’ val...
Definition elements.h:3813
virtual double dshape_lagrangian_at_knot(const unsigned &ipt, Shape &psi, DShape &dpsidxi) const
Return the geometric shape functions and also first derivatives w.r.t. Lagrangian coordinates at ipt-...
Definition elements.cc:6768
virtual void fill_in_jacobian_from_solid_position_by_fd(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Use finite differences to calculate the Jacobian entries corresponding to the solid positions....
Definition elements.cc:7016
SolidFiniteElement()
Constructor: Set defaults.
Definition elements.h:3589
virtual bool has_internal_solid_data()
Return whether there is internal solid data (e.g. discontinuous solid pressure). At present,...
Definition elements.h:3578
void fill_in_jacobian_for_solid_ic(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Fill in the residuals and Jacobian for the setup of an initial condition. The global equations are:
Definition elements.h:4039
double multiplier(const Vector< double > &xi)
Access to the "multiplier" for the inertia terms in the consistent determination of the initial condi...
Definition elements.h:4312
virtual void assign_all_generic_local_eqn_numbers(const bool &store_local_dof_pt)
Overload assign_all_generic_local_equation numbers to include the data associated with solid dofs....
Definition elements.h:3871
double d2shape_lagrangian(const Vector< double > &s, Shape &psi, DShape &dpsidxi, DShape &d2psidxi) const
Compute the geometric shape functions and also first and second derivatives w.r.t....
Definition elements.cc:6812
void compute_norm(double &el_norm)
Calculate the L2 norm of the displacement u=R-r to overload the compute_norm function in the Generali...
Definition elements.cc:6473
Node * construct_boundary_node(const unsigned &n, TimeStepper *const &time_stepper_pt)
Construct the local node n and return a pointer to it, in the case when the node MAY be located on a ...
Definition elements.h:3850
virtual double J_lagrangian_at_knot(const unsigned &ipt) const
Return the Jacobian of the mapping from local to Lagrangian coordinates at the ipt-th integration poi...
Definition elements.h:3950
void describe_local_dofs(std::ostream &out, const std::string &current_string) const
Function to describe the local dofs of the element. The ostream specifies the output stream to which ...
Definition elements.cc:6545
SolidFiniteElement(const SolidFiniteElement &)=delete
Broken copy constructor.
MultiplierFctPt Multiplier_fct_pt
Pointer to function that computes the "multiplier" for the inertia terms in the consistent determinat...
Definition elements.h:4280
virtual ~SolidFiniteElement()
Destructor to clean up any allocated memory.
Definition elements.cc:6660
void fill_in_jacobian_for_newmark_accel(DenseMatrix< double > &jacobian)
Fill in the contributions of the Jacobian matrix for the consistent assignment of the initial "accele...
Definition elements.cc:7258
double local_to_lagrangian_mapping(const DShape &dpsids, DenseMatrix< double > &inverse_jacobian) const
Calculate the mapping from local to lagrangian coordinates, given the derivatives of the shape functi...
Definition elements.h:4101
virtual void reset_after_solid_position_fd()
Function that is call after the finite differencing of the solid position data. This may be overloade...
Definition elements.h:4249
void set_lagrangian_dimension(const unsigned &lagrangian_dimension)
Set the lagrangian dimension of the element — the number of lagrangian coordinates stored at the node...
Definition elements.h:3569
MultiplierFctPt multiplier_fct_pt() const
Access function: Pointer to multiplicator function for assignment of consistent assignement of initia...
Definition elements.h:3992
A class to specify the initial conditions for a solid body. Solid bodies are often discretised with H...
Definition elements.h:3500
unsigned & ic_time_deriv()
Which time derivative are we currently assigning?
Definition elements.h:3521
GeomObject *& geom_object_pt()
(Reference to) pointer to geom object that specifies the initial condition
Definition elements.h:3515
unsigned IC_time_deriv
Which time derivative (0,1,2) are we currently assigning.
Definition elements.h:3533
GeomObject * Geom_object_pt
Pointer to the GeomObject that specifies the initial condition (shape, veloc and accel)
Definition elements.h:3530
void operator=(const SolidInitialCondition &)=delete
Broken assignment operator.
SolidInitialCondition(GeomObject *geom_object_pt)
Constructor: Pass geometric object; initialise time deriv to 0.
Definition elements.h:3503
SolidInitialCondition(const SolidInitialCondition &)=delete
Broken copy constructor.
A Class for nodes that deform elastically (i.e. position is an unknown in the problem)....
Definition nodes.h:1686
Solid point element.
Definition elements.h:4984
Function base class for exact solutions/initial conditions/boundary conditions. This is needed so tha...
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>,...
A slight extension to the standard template vector class so that we can include "graceful" array rang...
Definition Vector.h:58
unsigned Max_newton_iterations
Maximum number of newton iterations.
Definition elements.cc:1682
double Newton_tolerance
Convergence tolerance for the newton solver.
Definition elements.cc:1679
unsigned N_local_points
Number of points along one dimension of each element used to create coordinates within the element in...
Definition elements.cc:1693
double Radius_multiplier_for_fast_exit_from_locate_zeta
Multiplier for (zeta-based) outer radius of element used for deciding that point is outside element....
Definition elements.cc:1687
std::string to_string(T object, unsigned float_precision=8)
Conversion function that should work for anything with operator<< defined (at least all basic types).
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
void(* BulkCoordinateDerivativesFctPt)(const Vector< double > &s, DenseMatrix< double > &ds_bulk_dsface, unsigned &interior_direction)
Typedef for the function that returns the partial derivative of the local coordinates in the bulk ele...
Definition elements.h:1294
void(* CoordinateMappingFctPt)(const Vector< double > &s, Vector< double > &s_bulk)
Typedef for the function that translates the face coordinate to the coordinate in the bulk element.
Definition elements.h:1286