stored_shape_function_elements.cc
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// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 //Non-inline member functions for generic elements
31 
33 #include "shape.h"
34 #include "integral.h"
35 
36 
37 
38 namespace oomph
39 {
40 
41 ///////////////////////////////////////////////////////////////////////////
42 ///////////////////////////////////////////////////////////////////////////
43 // Functions for finite elements
44 ///////////////////////////////////////////////////////////////////////////
45 ///////////////////////////////////////////////////////////////////////////
46 
47 
48 
49 //=========================================================================
50 /// Delete all the objects stored in the vectors:
51 /// Shape_stored, DShape_local_stored, and D2Shape_local_stored
52 //========================================================================
54 {
58 }
59 
60 
61 //=========================================================================
62 /// Delete stored shape functions
63 //========================================================================
65 {
66  //Can this element delete the stored data?
68  {
69  //Find the number of entries in the shape function storage vector
70  //N.B. This *should* be the same for all three vectors
71  unsigned n_intpt = Shape_stored_pt->size();
72  //Loop over the entries of each vector, in reverse and delete them
73  for(unsigned ipt=n_intpt;ipt>0;ipt--)
74  {
75  delete (*Shape_stored_pt)[ipt-1];
76  (*Shape_stored_pt)[ipt-1] = 0;
77  }
78  //Delete the vector itself
79  delete Shape_stored_pt;
80  }
81  //Reset the pointer to zero {Must do this even if copied}
82  Shape_stored_pt = 0;
83 }
84 
85 
86 //=========================================================================
87 /// Delete stored derivatives of shape functions w.r.t. to local
88 /// coordinates
89 //========================================================================
91 {
92  //Can this element delete the stored data?
94  {
95  unsigned n_intpt = DShape_local_stored_pt->size();
96  for(unsigned ipt=n_intpt;ipt>0;ipt--)
97  {
98  delete (*DShape_local_stored_pt)[ipt-1];
99  (*DShape_local_stored_pt)[ipt-1] = 0;
100  }
101  //Delete the vector itself
102  delete DShape_local_stored_pt;
103  }
104  //Reset the pointer to zero, must do this, even if copied
106 }
107 
108 
109 //=========================================================================
110 /// Delete stored second derivatives of shape functions w.r.t. to local
111 /// coordinates
112 //========================================================================
114 {
115  //Can this element delete the stored data?
117  {
118  unsigned n_intpt = D2Shape_local_stored_pt->size();
119  for(unsigned ipt=n_intpt;ipt>0;ipt--)
120  {
121  delete (*D2Shape_local_stored_pt)[ipt-1];
122  (*D2Shape_local_stored_pt)[ipt-1] = 0;
123  }
124  //Delete the vector itself
126  }
127  //Reset the pointer to zero, must do it, even if copied
129 }
130 
131 
132 //=========================================================================
133 /// Delete all stored quantities related to derivatives of shape
134 /// fcts w.r.t. to global Eulerian coordinates
135 //========================================================================
137 {
141 }
142 
143 //=========================================================================
144 /// Delete stored derivatives w.r.t. Eulerian coordinates
145 //========================================================================
147 {
148  //If the storage has been allocated and we can delete it
150  {
151  //Find the number of entries in the first vector
152  unsigned n_intpt = DShape_eulerian_stored_pt->size();
153  //Loop over the entries of the vectors, in reverse and delete them
154  for(unsigned ipt=n_intpt;ipt>0;ipt--)
155  {
156  delete (*DShape_eulerian_stored_pt)[ipt-1];
157  (*DShape_eulerian_stored_pt)[ipt-1] = 0;
158  }
159  //Delete the vector itself
161  }
162  //Reset the pointer to zero, even if copied
164 }
165 
166 
167 
168 
169 //=========================================================================
170 /// Delete stored 2nd derivatives w.r.t. Eulerian coordinates
171 //========================================================================
173 {
174  //If the storage has been allocated
176  {
177  //Find the number of entries in the second vector
178  unsigned n_intpt = D2Shape_eulerian_stored_pt->size();
179  //Loop over the entries in reverse and delete them
180  for(unsigned ipt=n_intpt;ipt>0;ipt--)
181  {
182  delete (*D2Shape_eulerian_stored_pt)[ipt-1];
183  (*D2Shape_eulerian_stored_pt)[ipt-1] = 0;
184  }
185  //Delete the vector itself
187  }
188  //Reset the pointer to zero, even if copied
190 }
191 
192 
193 //=========================================================================
194 /// Delete stored Jacobian of mapping between local and global Eulerian
195 /// coordinates
196 //========================================================================
198 {
199  //If the element originally allocated the storage, delete it
201  {
202  //Delete the stored Jacobians
204  }
205  //Reset the pointer to zero, even if copied
207 }
208 
209 
210 //======================================================================
211 /// \short The destructor cleans up the memory allocated
212 /// for shape function storage.
213 //=======================================================================
215 {
216  //Merely need to call the private functions to clean up storages
219 }
220 
221 //=======================================================================
222 /// Set the spatial integration scheme and also calculate the values of the
223 /// shape functions and their derivatives w.r.t. the local coordinates,
224 /// placing the values into storage so that they may be re-used,
225 /// without recalculation
226 //=======================================================================
229 {
230  //Assign the integration scheme
232 
233  //If we are storing the shape functions and first and second derivatives
235  {
237  }
238  //If we are storing the shape functions and first derivatives
239  else if(DShape_local_stored_pt!=0)
240  {
242  }
243  //If we are storing the shape functions
244  else if(Shape_stored_pt!=0)
245  {
247  }
248 
249  //If we are storing Eulerian first and second derivatives, recompute them
251  {
253  }
254  //If we are storing Eulerian first derivatives, recompute them
255  else if(DShape_eulerian_stored_pt!=0)
256  {
258  }
259  //If we are storing the Jacobian of the mapping from local to Eulerian
260  //coordinates, recompute it
261  else if(Jacobian_eulerian_stored_pt!=0)
262  {
264  }
265 
266 }
267 
268 //========================================================================
269 /// Calculate the shape functions at the integration points and store in
270 /// internal storage of the element
271 //========================================================================
273 {
274  // Find the number of nodes in the element
275  unsigned n_node = nnode();
276 #ifdef PARANOID
277  if(n_node == 0)
278  {
279  std::string error_message =
280  "FiniteElement::Node_pt must be resized to a value greater than\n";
281  error_message +=
282  "zero before calling pre_compute_shape_at_knots()";
283 
284  throw OomphLibError(error_message,
285  OOMPH_CURRENT_FUNCTION,
286  OOMPH_EXCEPTION_LOCATION);
287  }
288 #endif
289  //Find number of interpolated position dofs
290  unsigned n_position_type = nnodal_position_type();
291 
292  //In case we have an exisiting integration scheme, wipe the stored data
294  //Element is now in charge of deleting its own stored data again
296 
297  //Allocate internal storage for the shape functions
299 
300  // Storage for the shape functions and their local derivatives
301  Shape psi(n_node,n_position_type);
302 
303  //Loop over the integration points
304  unsigned n_intpt = integral_pt()->nweight();
305  for(unsigned ipt=0;ipt<n_intpt;ipt++)
306  {
307  //Get the shape functions
309 
310  //Set up local storage for the shape functions and derivatives
311  Shape *psi_pt = new Shape(n_node,n_position_type);
312 
313  //Copy the values of the shape functions and their local derivatives
314  //into the element storage
315  for(unsigned n=0;n<n_node;n++)
316  {
317  for(unsigned k=0;k<n_position_type;k++)
318  {
319  (*psi_pt)(n,k) = psi(n,k);
320  }
321  }
322 
323  //Add the pointers to the shape functions to the internal storage
324  Shape_stored_pt->push_back(psi_pt);
325  } //End of loop over integration points
326 }
327 
328 //========================================================================
329 /// Calculate the shape functions and thir first derivatives
330 /// w.r.t. local coordinates at the integration points and store in
331 /// internal storage of the element
332 //========================================================================
334 {
335  // Find the number of nodes in the element
336  unsigned n_node = nnode();
337 #ifdef PARANOID
338  if(n_node == 0)
339  {
340  std::string error_message =
341  "FiniteElement::Node_pt must be resized to a value greater than\n";
342  error_message +=
343  "zero before calling pre_compute_dshape_local_at_knots()";
344 
345  throw OomphLibError(
346  error_message,
347  OOMPH_CURRENT_FUNCTION,
348  OOMPH_EXCEPTION_LOCATION);
349  }
350 #endif
351  //Find number of interpolated position dofs
352  unsigned n_position_type = nnodal_position_type();
353  //Find spatial dimension of the element
354  unsigned Dim = dim();
355 
356  //In case we have an exisiting integration scheme, wipe the stored data
359  //Element is now in charge of deleting its own stored data again
361 
362  //Allocate internal storage for the shape functions
365 
366  // Storage for the shape functions and their local derivatives
367  Shape psi(n_node,n_position_type);
368  DShape dpsids(n_node,n_position_type,Dim);
369 
370  //Loop over the integration points
371  unsigned n_intpt = integral_pt()->nweight();
372  for(unsigned ipt=0;ipt<n_intpt;ipt++)
373  {
374  //Get the shape functions and local derivatives at the integration point
375  FiniteElement::dshape_local_at_knot(ipt,psi,dpsids);
376 
377  //Set up local storage for the shape functions and derivatives
378  Shape *psi_pt = new Shape(n_node,n_position_type);
379  DShape *dpsids_pt = new DShape(n_node,n_position_type,Dim);
380 
381  //Copy the values of the shape functions and their local derivatives
382  //into the element storage
383  for(unsigned n=0;n<n_node;n++)
384  {
385  for(unsigned k=0;k<n_position_type;k++)
386  {
387  (*psi_pt)(n,k) = psi(n,k);
388 
389  for(unsigned i=0;i<Dim;i++)
390  {(*dpsids_pt)(n,k,i) = dpsids(n,k,i);}
391  }
392  }
393 
394  //Add the pointers to the shape functions and derivatives to the internal
395  //storage
396  Shape_stored_pt->push_back(psi_pt);
397  DShape_local_stored_pt->push_back(dpsids_pt);
398  } //End of loop over integration points
399 }
400 
401 //========================================================================
402 /// Calculate the shape functions and thir first and second derivatives
403 /// w.r.t. local coordinates at the integration points and store in
404 /// internal storage of the element
405 //========================================================================
407 {
408  // Find the number of nodes in the element
409  unsigned n_node = nnode();
410 #ifdef PARANOID
411  if(n_node == 0)
412  {
413  std::string error_message =
414  "FiniteElement::Node_pt must be resized to a value greater than\n";
415  error_message +=
416  "zero before calling pre_compute_d2shape_local_at_knots()";
417 
418  throw OomphLibError(
419  error_message,
420  OOMPH_CURRENT_FUNCTION,
421  OOMPH_EXCEPTION_LOCATION);
422  }
423 #endif
424  //Find number of interpolated position dofs
425  unsigned n_position_type = nnodal_position_type();
426  //Find spatial dimension of the element
427  unsigned Dim = dim();
428 
429  //Find the number of second derivatives required
430  //N.B. We are assuming that the mixed derivatives are symmetric here
431  unsigned n_deriv=0;
432  switch(Dim)
433  {
434  case 1: n_deriv = 1; break;
435  case 2: n_deriv = 3; break;
436  case 3: n_deriv = 6; break;
437  default: oomph_info << "Really more than 3 dimensions?" << std::endl; break;
438  }
439 
440  //In case we have an exisiting integration scheme, wipe the stored data
444  //Element is now in charge of deleting its own stored data again
446 
447  //Allocate internal storage for the shape functions
451 
452  // Storage for the shape functions and their local derivatives
453  Shape psi(n_node,n_position_type);
454  DShape dpsids(n_node,n_position_type,Dim);
455  DShape d2psids(n_node,n_position_type,n_deriv);
456 
457  //Loop over the integration points
458  unsigned n_intpt = integral_pt()->nweight();
459  for(unsigned ipt=0;ipt<n_intpt;ipt++)
460  {
461  //Get the shape functions and local derivatives at the integration point
462  FiniteElement::d2shape_local_at_knot(ipt,psi,dpsids,d2psids);
463 
464  //Set up local storage for the shape functions and derivatives
465  Shape *psi_pt = new Shape(n_node,n_position_type);
466  DShape *dpsids_pt = new DShape(n_node,n_position_type,Dim);
467  DShape *d2psids_pt = new DShape(n_node,n_position_type,n_deriv);
468 
469  //Copy the values of the shape functions and their local derivatives
470  //into the element storage
471  for(unsigned n=0;n<n_node;n++)
472  {
473  for(unsigned k=0;k<n_position_type;k++)
474  {
475  (*psi_pt)(n,k) = psi(n,k);
476 
477  for(unsigned i=0;i<Dim;i++)
478  {(*dpsids_pt)(n,k,i) = dpsids(n,k,i);}
479 
480  for(unsigned i=0;i<n_deriv;i++)
481  {(*d2psids_pt)(n,k,i) = d2psids(n,k,i);}
482  }
483  }
484 
485  //Add the pointers to the shape functions and derivatives to the internal
486  //storage
487  Shape_stored_pt->push_back(psi_pt);
488  DShape_local_stored_pt->push_back(dpsids_pt);
489  D2Shape_local_stored_pt->push_back(d2psids_pt);
490  } //End of loop over integration points
491 }
492 
493 //=======================================================================
494 /// Calculate the value of the Jacobian of the mapping from local to
495 /// global coordinates at the integration points and store internally
496 //=======================================================================
498 {
499  //Delete previously existing storage
501  //Now we're in change of deletion again
503 
504  //Allocate storage for the stored Jacobian values
506 
507  //Loop over the integration points
508  unsigned n_intpt = integral_pt()->nweight();
509  for(unsigned ipt=0;ipt<n_intpt;ipt++)
510  {
511  //Add the value of the Jacobian to the internally stored vector
513  ->push_back(FiniteElement::J_eulerian_at_knot(ipt));
514  }
515 }
516 
517 //========================================================================
518 /// Calculate the values of the derivatives of the shape functions at the
519 /// integration points and store in the internal storage of the element
520 //========================================================================
522 {
523  //Pre-compute the basic shape functions
525 
526  //Find the number of nodes
527  unsigned n_node = nnode();
528  //Get the number of position types and the dimension from the element
529  unsigned n_position_type = this->nnodal_position_type();
530  unsigned n_dim = this->nodal_dimension();
531 
532  //Delete the exisiting stored objects
535  //Now we're in change of deletion again
537 
538  //Allocate storage for the stored shape function derivatives
541 
542  //Assign local variables for the shape function and derivatives
543  Shape psi(n_node,n_position_type);
544  DShape dpsidx(n_node,n_position_type,n_dim);
545 
546  //Loop over the integration points
547  unsigned n_intpt = integral_pt()->nweight();
548  for(unsigned ipt=0;ipt<n_intpt;ipt++)
549  {
550  //Get the values of the shape function and derivatives at the
551  //integration point and add to the value of the Jacobian to the
552  //internally stored vector
554  push_back(FiniteElement::dshape_eulerian_at_knot(ipt,psi,dpsidx));
555 
556  //Set up local storage for the shape function derivatives
557  DShape* dpsidx_pt = new DShape(n_node,n_position_type,n_dim);
558 
559  //Now copy the values over
560  for(unsigned l=0;l<n_node;l++)
561  {
562  for(unsigned k=0;k<n_position_type;k++)
563  {
564  //First derivatives
565  for(unsigned i=0;i<n_dim;i++) {(*dpsidx_pt)(l,k,i) = dpsidx(l,k,i);}
566  }
567  }
568 
569  //Add the pointer to the vector of stored DShape objects
570  DShape_eulerian_stored_pt->push_back(dpsidx_pt);
571  } //End of loop over integration points
572 }
573 
574 //========================================================================
575 /// Calculate the values of the first and second derivatives of the shape
576 /// functions at the integration points and store in the internal storage
577 /// of the element
578 //========================================================================
580 {
581  //Pre-compute the basic shape functions
583 
584  //Find the number of nodes
585  unsigned n_node = nnode();
586  //Get the number of position types and the dimension from element
587  unsigned n_position_type = this->nnodal_position_type();
588  unsigned n_dim = this->nodal_dimension();
589 
590  //Find the number of second derivatives required
591  //N.B. We are assuming that the mixed derivatives are symmetric here
592  unsigned n_deriv=0;
593  switch(n_dim)
594  {
595  case 1: n_deriv = 1; break;
596  case 2: n_deriv = 3; break;
597  case 3: n_deriv = 6; break;
598  default: oomph_info << "Really more than 3 dimensions?" << std::endl; break;
599  }
600 
601  //Delete the existing objects, if there are any
605  //Now we're in change of deletion again
607 
608  //Allocate storage for the stored shape function derivatives
612 
613  //Assign local variables for the shape function and derivatives
614  Shape psi(n_node,n_position_type);
615  DShape dpsidx(n_node,n_position_type,n_dim);
616  DShape d2psidx(n_node,n_position_type,n_deriv);
617 
618  //Loop over the integration points
619  unsigned n_intpt = integral_pt()->nweight();
620  for(unsigned ipt=0;ipt<n_intpt;ipt++)
621  {
622  //Get the values of the shape function and derivatives at the
623  //integration point and assign the value of the Jacobian to the
624  //internally stored vector
626  push_back(FiniteElement::d2shape_eulerian_at_knot(ipt,psi,dpsidx,d2psidx));
627 
628  //Set up local storage for the shape function derivatives
629  DShape *dpsidx_pt = new DShape(n_node,n_position_type,n_dim);
630  DShape *d2psidx_pt = new DShape(n_node,n_position_type,n_deriv);
631 
632  //Now copy the values over
633  for(unsigned l=0;l<n_node;l++)
634  {
635  for(unsigned k=0;k<n_position_type;k++)
636  {
637  //First derivatives
638  for(unsigned i=0;i<n_dim;i++)
639  {(*dpsidx_pt)(l,k,i) = dpsidx(l,k,i);}
640 
641  //Second derivatives
642  for(unsigned i=0;i<n_deriv;i++)
643  {(*d2psidx_pt)(l,k,i) = d2psidx(l,k,i);}
644  }
645  }
646 
647  //Add the pointers to the shape function derivatives to the internal
648  //storage
649  DShape_eulerian_stored_pt->push_back(dpsidx_pt);
650  D2Shape_eulerian_stored_pt->push_back(d2psidx_pt);
651  } //End of loop over the shape functions
652 }
653 
654 //=========================================================================
655 /// \short Return the shape function stored at the ipt-th integration
656 /// point.
657 //=========================================================================
658 void StorableShapeElementBase::shape_at_knot(const unsigned &ipt, Shape &psi)
659  const
660 {
661  //If we are not storing the shape functions, calculate the values
662  if(Shape_stored_pt==0)
663  {
665  }
666  else
667  {
668  //Read out the stored shape functions
669  //Note this will copy the values by pointer (fast)
670  psi = (*Shape_stored_pt)[ipt];
671  }
672 }
673 
674 
675 //=========================================================================
676 /// \short Return the shape function and its derivatives w.r.t. the local
677 /// coordinates at the ipt-th integration point.
678 //=========================================================================
680 dshape_local_at_knot(const unsigned &ipt, Shape &psi,
681  DShape &dpsids) const
682 {
683  //If we are not storing the first derivatives, calculate them
685  {
686  FiniteElement::dshape_local_at_knot(ipt,psi,dpsids);
687  }
688  else
689  {
690  //Read out the stored shape functions
691  //Set the internal pointers in psi and dpsids
692  psi = (*Shape_stored_pt)[ipt];
693  dpsids = (*DShape_local_stored_pt)[ipt];
694  }
695 }
696 
697 //=========================================================================
698 /// \short Return the shape function and its first and second derivatives
699 /// w.r.t. the local coordinates at the ipt-th integration point.
700 //=========================================================================
702 d2shape_local_at_knot(const unsigned &ipt, Shape &psi,
703  DShape &dpsids, DShape &d2psids)
704  const
705 {
706  //If we are not storing the second derivatives, calculate them on the fly
708  {
709  FiniteElement::d2shape_local_at_knot(ipt,psi,dpsids,d2psids);
710  }
711  else
712  {
713  //Read out the stored shape functions
714  //Set the internal pointers in psi, dpsids, and d2psids
715  psi = (*Shape_stored_pt)[ipt];
716  dpsids = (*DShape_local_stored_pt)[ipt];
717  d2psids = (*D2Shape_local_stored_pt)[ipt];
718  }
719 }
720 
721 
722 //==========================================================================
723 /// \short Compute the geometric shape functions, and
724 /// derivatives w.r.t eulerian coordinates at the ipt-th integration point.
725 /// If the values have already been computed, return the stored values.
726 //==========================================================================
728 dshape_eulerian_at_knot(const unsigned &ipt, Shape &psi,
729  DShape &dpsidx) const
730 {
731  //If we are not storing the values, return the calculated values
733  {
734  return FiniteElement::dshape_eulerian_at_knot(ipt,psi,dpsidx);
735  }
736  else
737  {
738  //Set internal pointers in the shape functions.
739  psi = (*Shape_stored_pt)[ipt];
740  dpsidx = (*DShape_eulerian_stored_pt)[ipt];
741 
742  //Return the stored value of the jacobian
743  return ((*Jacobian_eulerian_stored_pt)[ipt]);
744  }
745 }
746 
747 //==========================================================================
748 /// \short Return the geometric shape functions, first and second
749 /// derivatives w.r.t eulerian coordinates at the ipt-th integration point.
750 /// If the values have already been computed, return the stored values.
751 //==========================================================================
753 d2shape_eulerian_at_knot(const unsigned &ipt, Shape &psi,
754  DShape &dpsidx, DShape &d2psidx) const
755 {
756  //If we are not storing the values return the calculated values
758  {
759  return FiniteElement::d2shape_eulerian_at_knot(ipt,psi,dpsidx,d2psidx);
760  }
761  else
762  {
763  //Set internal pointers in the shape functions
764  psi = (*Shape_stored_pt)[ipt];
765  dpsidx = (*DShape_eulerian_stored_pt)[ipt];
766  d2psidx = (*D2Shape_eulerian_stored_pt)[ipt];
767 
768  //Return the stored value of the jacobian
769  return ((*Jacobian_eulerian_stored_pt)[ipt]);
770  }
771 }
772 
773 //==========================================================================
774 /// \short Return the Jacobian of the mapping between the local and global
775 /// coordinates. If the value has been precomputed return that
776 //==========================================================================
777 double StorableShapeElementBase::J_eulerian_at_knot(const unsigned &ipt) const
778 {
779  //If we are not storing the values, return the calculated values
781  {
783  }
784  else
785  {
786  //Return the stored value of the jacobian
787  return ((*Jacobian_eulerian_stored_pt)[ipt]);
788  }
789 }
790 
791 //========================================================================
792 /// Set the shape functions referenced in the internal vectors to be
793 /// those stored in the StorableShapeElementBase pointed to by element_pt.
794 /// Using this function will allow a saving in the storage required
795 /// for integration schemes in the (most common)
796 /// case when a large number of elements have the same integration scheme
797 //=======================================================================
800  const &element_pt)
801 {
802 #ifdef PARANOID
803  //Check that we aren't nulling out
804  if(element_pt->shape_stored_pt()==0)
805  {
806  std::string error_message =
807  "Element does not have stored shape functions\n";
808 
809  throw OomphLibError(
810  error_message,
811  OOMPH_CURRENT_FUNCTION,
812  OOMPH_EXCEPTION_LOCATION);
813  }
814 #endif
815 
816  //Only do this if the referenced Shape objects are not already the same
817  //Assume that if the stored shape functions are the same, the rest will be
818  if(Shape_stored_pt != element_pt->shape_stored_pt())
819  {
820  //Delete the existing data
822  //Now this element can no longer delete the data pointed at by
823  //the internal vectors
825 
826  //Assign the pointers
827  Shape_stored_pt = element_pt->shape_stored_pt();
830  }
831 }
832 
833 //========================================================================
834 /// Set the stored derivatives of shape functions w.r.t Eulerian coordinates
835 /// to be
836 /// those stored in the StorableShapeElementBase pointed to by element_pt.
837 /// Using this function will allow a saving in the storage required
838 /// for integration schemes in the (most common)
839 /// case when a large number of elements have the same integration scheme
840 //=======================================================================
843  const &element_pt)
844 {
846 
847  //Only do this if the referenced Shape objects are not already the same
848  //Assume that if the stored shape functions are the same, the rest will be
850  {
851  //Delete the existing data
853  //Now this element can no longer delete the data pointed at by
854  //the internal vectors
856 
857  //Assign the pointers
861  }
862 }
863 
864 
865 
866 ///////////////////////////////////////////////////////////////////////////
867 ///////////////////////////////////////////////////////////////////////////
868 // Functions for solid elements with stored shape functions
869 ///////////////////////////////////////////////////////////////////////////
870 ///////////////////////////////////////////////////////////////////////////
871 
872 //=========================================================================
873 /// Delete all the objects and storage associated with stored derivatives
874 /// of shape functions with respect to Lagrangian coordinates
875 //=========================================================================
877 {
878  delete_dshape_lagrangian_stored();
879  delete_d2shape_lagrangian_stored();
880  delete_J_lagrangian_stored();
881 }
882 
883 
884 //=========================================================================
885 /// Delete all the objects stored in the vectors:
886 /// DShape_lagrangian_stored
887 //========================================================================
889 {
890  //If storage has been allocated
891  if((Can_delete_dshape_lagrangian_stored) && (DShape_lagrangian_stored_pt))
892  {
893  //Find the number of entries in the shape function storage vector
894  unsigned n_intpt = DShape_lagrangian_stored_pt->size();
895  //Loop over the entries of the vectors, in reverse and delete them
896  for(unsigned ipt=n_intpt;ipt>0;ipt--)
897  {
898  delete (*DShape_lagrangian_stored_pt)[ipt-1];
899  (*DShape_lagrangian_stored_pt)[ipt-1] = 0;
900  }
901  //Delete the actual vector
902  delete DShape_lagrangian_stored_pt;
903  }
904  //Reset the pointer to zero
905  DShape_lagrangian_stored_pt = 0;
906 }
907 
908 
909 //=========================================================================
910 /// Delete all the objects stored in the vectors:
911 /// D2Shape_lagrangian_stored
912 //========================================================================
914 {
915  //If storage has been allocated
916  if((Can_delete_dshape_lagrangian_stored) && (D2Shape_lagrangian_stored_pt))
917  {
918  //Now find the number of entries in the second vector
919  unsigned n_intpt = D2Shape_lagrangian_stored_pt->size();
920  //Loop over the entries in reverse and delete them
921  for(unsigned ipt=n_intpt;ipt>0;ipt--)
922  {
923  delete (*D2Shape_lagrangian_stored_pt)[ipt-1];
924  (*D2Shape_lagrangian_stored_pt)[ipt-1] = 0;
925  }
926  //Delete the actual vector
927  delete D2Shape_lagrangian_stored_pt;
928  }
929  //Reset the pointer to zero
930  D2Shape_lagrangian_stored_pt = 0;
931 }
932 
933 //=======================================================================
934 /// Delete the stored Jacobian of the mapping between the Lagrangian and
935 /// local coordinates.
936 //=======================================================================
938 {
939  //If we allocated the storage, delete it
940  if(Can_delete_dshape_lagrangian_stored)
941  {
942  //Delete the stored Jacobian
943  delete Jacobian_lagrangian_stored_pt;
944  }
945  //Reset the pointer to zero
946  Jacobian_lagrangian_stored_pt = 0;
947 }
948 
949 //========================================================================
950 /// Calculate the values of the derivatives of the shape functions at the
951 /// integration points and store in the internal storage of the element
952 //========================================================================
954 {
955  //Pre-compute the basic shape functions
957 
958  //Find the number of nodes
959  unsigned n_node = nnode();
960  //Get the number of position types and the dimension from first node
961  //N.B. Assume that it is the same for all nodes
962  unsigned n_lagrangian_type =
963  static_cast<SolidNode*>(node_pt(0))->nlagrangian_type();
964  unsigned n_lagrangian =
965  static_cast<SolidNode*>(node_pt(0))->nlagrangian();
966 
967  //Delete the exisiting stored objects
968  delete_J_lagrangian_stored();
969  delete_dshape_lagrangian_stored();
970  //Now we're in charge of deletion again
971  Can_delete_dshape_lagrangian_stored=true;
972 
973  //Allocate storage for the stored shape function derivatives
974  DShape_lagrangian_stored_pt = new Vector<DShape*>;
975  Jacobian_lagrangian_stored_pt = new Vector<double>;
976 
977  //Assign local variables for the shape function and derivatives
978  Shape psi(n_node,n_lagrangian_type);
979  DShape dpsidxi(n_node,n_lagrangian_type,n_lagrangian);
980 
981  //Loop over the integration points
982  unsigned n_intpt = integral_pt()->nweight();
983  for(unsigned ipt=0;ipt<n_intpt;ipt++)
984  {
985  //Get the values of the shape function and derivatives at the
986  //integration point and add to the value of the Jacobian to the
987  //internally stored vector
988  Jacobian_lagrangian_stored_pt->
989  push_back(SolidFiniteElement::dshape_lagrangian_at_knot(ipt,psi,dpsidxi));
990 
991  //Set up local storage for the shape function derivatives
992  DShape* dpsidxi_pt = new DShape(n_node,n_lagrangian_type,n_lagrangian);
993 
994  //Now copy the values over
995  for(unsigned l=0;l<n_node;l++)
996  {
997  for(unsigned k=0;k<n_lagrangian_type;k++)
998  {
999  //First derivatives
1000  for(unsigned i=0;i<n_lagrangian;i++)
1001  {(*dpsidxi_pt)(l,k,i) = dpsidxi(l,k,i);}
1002  }
1003  }
1004 
1005  //Add the pointer to the vector of stored DShape objects
1006  DShape_lagrangian_stored_pt->push_back(dpsidxi_pt);
1007  } //End of loop over integration points
1008 }
1009 
1010 //========================================================================
1011 /// Calculate the values of the first and second derivatives of the shape
1012 /// functions at the integration points and store in the internal storage
1013 /// of the element
1014 //========================================================================
1016 {
1017  //Pre-compute the basic shape functions
1019 
1020  //Find the number of nodes
1021  unsigned n_node = nnode();
1022  //Get the number of position types and the dimension from first node
1023  //N.B. Assume that it is the same for all nodes
1024  unsigned n_lagrangian_type =
1025  static_cast<SolidNode*>(node_pt(0))->nlagrangian_type();
1026  unsigned n_lagrangian =
1027  static_cast<SolidNode*>(node_pt(0))->nlagrangian();
1028 
1029  //Find the number of second derivatives required
1030  //N.B. We are assuming that the mixed derivatives are symmetric here
1031  unsigned n_deriv=0;
1032  switch(n_lagrangian)
1033  {
1034  case 1: n_deriv = 1; break;
1035  case 2: n_deriv = 3; break;
1036  case 3: n_deriv = 6; break;
1037  default: oomph_info << "Really more than 3 dimensions?" << std::endl; break;
1038  }
1039 
1040  //Delete the existing objects, if there are any
1041  delete_J_lagrangian_stored();
1042  delete_dshape_lagrangian_stored();
1043  delete_d2shape_lagrangian_stored();
1044  //We are in charge of deleting again
1045  Can_delete_dshape_lagrangian_stored=true;
1046 
1047  //Allocate storage for the stored shape function derivatives
1048  DShape_lagrangian_stored_pt = new Vector<DShape*>;
1049  D2Shape_lagrangian_stored_pt = new Vector<DShape*>;
1050  Jacobian_lagrangian_stored_pt = new Vector<double>;
1051 
1052  //Assign local variables for the shape function and derivatives
1053  Shape psi(n_node,n_lagrangian_type);
1054  DShape dpsidxi(n_node,n_lagrangian_type,n_lagrangian);
1055  DShape d2psidxi(n_node,n_lagrangian_type,n_deriv);
1056 
1057  //Loop over the integration points
1058  unsigned n_intpt = integral_pt()->nweight();
1059  for(unsigned ipt=0;ipt<n_intpt;ipt++)
1060  {
1061  //Get the values of the shape function and derivatives at the
1062  //integration point and assign the value of the Jacobian to the
1063  //internally stored vector
1064  Jacobian_lagrangian_stored_pt->
1065  push_back(
1066  SolidFiniteElement::d2shape_lagrangian_at_knot(ipt,psi,dpsidxi,d2psidxi));
1067 
1068  //Set up local storage for the shape function derivatives
1069  DShape *dpsidxi_pt = new DShape(n_node,n_lagrangian_type,n_lagrangian);
1070  DShape *d2psidxi_pt = new DShape(n_node,n_lagrangian_type,n_deriv);
1071 
1072  //Now copy the values over
1073  for(unsigned l=0;l<n_node;l++)
1074  {
1075  for(unsigned k=0;k<n_lagrangian_type;k++)
1076  {
1077  //First derivatives
1078  for(unsigned i=0;i<n_lagrangian;i++)
1079  {(*dpsidxi_pt)(l,k,i) = dpsidxi(l,k,i);}
1080 
1081  //Second derivatives
1082  for(unsigned i=0;i<n_deriv;i++)
1083  {(*d2psidxi_pt)(l,k,i) = d2psidxi(l,k,i);}
1084  }
1085  }
1086 
1087  //Add the pointers to the shape function derivatives to the internal
1088  //storage
1089  DShape_lagrangian_stored_pt->push_back(dpsidxi_pt);
1090  D2Shape_lagrangian_stored_pt->push_back(d2psidxi_pt);
1091  } //End of loop over the shape functions
1092 }
1093 
1094 
1095 //==========================================================================
1096 /// \short Compute the geometric shape functions, and
1097 /// derivatives w.r.t Lagrangian coordinates at the ipt-th integration point.
1098 /// If the values have already been computed, return the stored values.
1099 //==========================================================================
1101 dshape_lagrangian_at_knot(const unsigned &ipt, Shape &psi, DShape &dpsidxi)
1102 const
1103 {
1104  //If we are not storing the values, return the calculated values
1105  if(DShape_lagrangian_stored_pt==0)
1106  {
1107  return SolidFiniteElement::dshape_lagrangian_at_knot(ipt,psi,dpsidxi);
1108  }
1109  else
1110  {
1111  //Set the internal pointers in the shape functions
1112  psi = shape_stored_pt(ipt);
1113  dpsidxi = (*DShape_lagrangian_stored_pt)[ipt];
1114 
1115  //Return the stored value of the jacobian
1116  return ((*Jacobian_lagrangian_stored_pt)[ipt]);
1117  }
1118 }
1119 
1120 //==========================================================================
1121 /// \short Compute the geometric shape functions, first and second
1122 /// derivatives w.r.t Lagrangian coordinates at the ipt-th integration point.
1123 /// If the values have already been computed, return the stored values.
1124 //==========================================================================
1126 d2shape_lagrangian_at_knot(const unsigned &ipt, Shape &psi,
1127  DShape &dpsidxi, DShape &d2psidxi) const
1128 {
1129  //If we are not storing the values return the calculated values
1130  if(D2Shape_lagrangian_stored_pt==0)
1131  {
1132  return
1133  SolidFiniteElement::d2shape_lagrangian_at_knot(ipt,psi,dpsidxi,d2psidxi);
1134  }
1135  else
1136  {
1137  //Set the internal values of the pointers in the Shape objects
1138  psi = shape_stored_pt(ipt);
1139  dpsidxi = (*DShape_lagrangian_stored_pt)[ipt];
1140  d2psidxi = (*D2Shape_lagrangian_stored_pt)[ipt];
1141 
1142  //Return the stored value of the jacobian
1143  return ((*Jacobian_lagrangian_stored_pt)[ipt]);
1144  }
1145 }
1146 
1147 
1148 //========================================================================
1149 /// Set the stored derivatives of shape functions w.r.t Lagrangian coordinates
1150 /// to be
1151 /// those stored in the StorableShapeElementBase pointed to by element_pt.
1152 /// Using this function will allow a saving in the storage required
1153 /// for integration schemes in the (most common)
1154 /// case when a large number of elements have the same integration scheme
1155 //=======================================================================
1158  const &element_pt)
1159 {
1161 
1162  //Only do this if the referenced Shape objects are not already the same
1163  //Assume that if the stored shape functions are the same, the rest will be
1164  if(DShape_lagrangian_stored_pt != element_pt->dshape_lagrangian_stored_pt())
1165  {
1166  //Delete the existing data
1167  delete_all_dshape_lagrangian_stored();
1168  //Now this element can no longer delete the data pointed at by
1169  //the internal vectors
1170  Can_delete_dshape_lagrangian_stored = false;
1171 
1172  //Assign the pointers
1173  DShape_lagrangian_stored_pt = element_pt->dshape_lagrangian_stored_pt();
1174  D2Shape_lagrangian_stored_pt = element_pt->d2shape_lagrangian_stored_pt();
1175  Jacobian_lagrangian_stored_pt = element_pt->jacobian_lagrangian_stored_pt();
1176  }
1177 }
1178 
1179 
1180 }
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...
void pre_compute_dshape_lagrangian_at_knots()
Calculate the first derivatives of the shape functions w.r.t Lagrangian coordinates at the integratio...
void pre_compute_d2shape_lagrangian_at_knots()
Calculate the first and second derivatives of the shape functions w.r.t Lagrangian coordinates at the...
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...
void pre_compute_dshape_eulerian_at_knots()
Calculate the first derivatives of the shape functions w.r.t the global coordinates at the integratio...
void set_dshape_lagrangian_stored_from_element(StorableShapeSolidElementBase *const &element_pt)
Set the derivatives of stored shape functions with respect to the lagrangian coordinates to be the sa...
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:3207
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...
Vector< double > * Jacobian_eulerian_stored_pt
Pointer to storage for the Jacobian of the element w.r.t global coordinates.
Vector< Shape * > *& shape_stored_pt()
Return a pointer to the vector of pointers to the stored shape functions.
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:3254
Vector< DShape * > *& dshape_eulerian_stored_pt()
Return a pointer to the vector of pointers to the stored first derivatives of the shape functions w...
void delete_dshape_eulerian_stored()
Delete stored deriatives of shape fcts w.r.t. to global Eulerian coords.
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...
Vector< DShape * > * DShape_local_stored_pt
Pointer to storage for the pointers to the derivatives of the nodal shape functions w...
cstr elem_len * i
Definition: cfortran.h:607
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:6683
virtual void set_integration_scheme(Integral *const &integral_pt)
Set the spatial integration scheme.
Definition: elements.cc:3150
void delete_all_dshape_lagrangian_stored()
Delete all the objects stored in the [...]_lagrangian_stored_pt vectors and delete the vectors themse...
Vector< DShape * > *& dshape_lagrangian_stored_pt()
Return a pointer to the vector of pointers to the stored first derivatives of the shape functions w...
virtual ~StorableShapeElementBase()
The destructor cleans up the static memory allocated for shape function storage. Internal and externa...
OomphInfo oomph_info
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:4086
void delete_d2shape_lagrangian_stored()
Delete stored second derivatives of shape functions w.r.t. Lagrangian coordinates.
bool Can_delete_dshape_eulerian_stored
Boolean to determine whether the element can delete the stored derivatives of shape functions w...
Vector< DShape * > * DShape_eulerian_stored_pt
Pointer to storage for the derivatives of the shape functions w.r.t. global coordinates at integratio...
void delete_dshape_local_stored()
Delete stored derivatives of shape functions w.r.t. to local coordinates.
unsigned Dim
Dimension of zeta tuples (set by get_dim_helper) – needed because we store the scalar coordinates in...
Definition: multi_domain.cc:66
void set_dshape_eulerian_stored_from_element(StorableShapeElementBase *const &element_pt)
Set the derivatives of stored shape functions with respect to the global coordinates to be the same a...
Vector< DShape * > *& d2shape_lagrangian_stored_pt()
Return a pointer to the vector of pointers to the stored second derivatives of the shape functions w...
unsigned nnodal_position_type() const
Return the number of coordinate types that the element requires to interpolate the geometry between t...
Definition: elements.h:2352
Vector< DShape * > *& dshape_local_stored_pt()
Return a pointer to the vector of pointers to the stored first derivatives of the shape functions w...
unsigned nlagrangian() const
Access function to # of Lagrangian coordinates.
Definition: geom_objects.h:182
unsigned nodal_dimension() const
Return the required Eulerian dimension of the nodes in this element.
Definition: elements.h:2370
Vector< DShape * > *& d2shape_eulerian_stored_pt()
Return a pointer to the vector of pointers to the stored second derivatives of the shape functions w...
Vector< Shape * > * Shape_stored_pt
Pointer to storage for the pointers to the nodal shape functions at the integration points (knots) ...
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition: elements.h:1908
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 ...
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:3160
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:6589
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-...
void pre_compute_d2shape_local_at_knots()
Calculate the second derivatives of the shape functions w.r.t. local coordinates at the integration p...
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:3432
void pre_compute_J_eulerian_at_knots()
Calculate the Jacobian of the mapping from local to global coordinates at the integration points and ...
Vector< DShape * > * D2Shape_eulerian_stored_pt
Pointer to storage for the second derivatives of the shape functions w.r.t. global coordinates at int...
void delete_dshape_lagrangian_stored()
Delete all the objects stored in the Lagrangian_stored vectors.
Vector< double > *& jacobian_eulerian_stored_pt()
Return a pointer to the vector of Jacobians of the mapping between the local and global (eulerian) co...
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2109
void delete_all_dshape_eulerian_stored()
Delete all storage related to deriatives of shape fcts w.r.t. to global Eulerian coords.
void pre_compute_d2shape_eulerian_at_knots()
Calculate the first and second derivatives of the shape functions w.r.t global coordinates at the int...
Vector< double > *& jacobian_lagrangian_stored_pt()
Return a pointer to the vector of Jacobians of the mapping between the local and global (eulerian) co...
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-...
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
Definition: elements.h:2482
A Class for nodes that deform elastically (i.e. position is an unknown in the problem). The idea is that the Eulerian positions are stored in a Data object and the Lagrangian coordinates are stored in addition. The pointer that addresses the Eulerian positions is set to the pointer to Value in the Data object. Hence, SolidNode uses knowledge of the internal structure of Data and must be a friend of the Data class. In order to allow a mesh to deform via an elastic-style equation in deforming-domain problems, the positions are stored separately from the values, so that elastic problems may be combined with any other type of problem.
Definition: nodes.h:1569
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:3176
void delete_d2shape_local_stored()
Delete stored 2nd derivatives of shape functions w.r.t. to local coordinates.
void delete_d2shape_eulerian_stored()
Delete stored second derivatives of shape functions w.r.t. to global Eulerian coordinates.
virtual unsigned nweight() const =0
Return the number of integration points of the scheme.
void delete_J_lagrangian_stored()
Delete stored Jaocbian of mapping between local and Lagrangian coordinates.
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn&#39;t been defined.
void delete_J_eulerian_stored()
Delete stored Jacobian of mapping between local and global (Eulerian) coordinates.
void pre_compute_dshape_local_at_knots()
Calculate the shape functions and first derivatives w.r.t. local coordinatess at the integration poin...
Vector< DShape * > * D2Shape_local_stored_pt
Pointer to storage for the pointers to the second derivatives of the nodal shape functions w...
void delete_all_shape_local_stored()
Delete all the objects stored in the [...]_local_stored_pt vectors and delete the vectors themselves...
virtual void set_integration_scheme(Integral *const &integral_pt)
Set the spatial integration scheme – overloaded from the finite element base class since a change in...
void pre_compute_shape_at_knots()
Calculate the shape functions at the integration points and store the results internally.
bool Can_delete_shape_local_stored
Boolean to determine whether the element can delete the stored local shape functions.
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2146
void shape_at_knot(const unsigned &ipt, Shape &psi) const
Return the geometric shape function at the ipt-th integration point.
void delete_shape_local_stored()
Delete stored shape functions.
void set_shape_local_stored_from_element(StorableShapeElementBase *const &element_pt)
Set the shape functions pointed to internally to be those pointed to by the FiniteElement element_pt ...
Vector< DShape * > *& d2shape_local_stored_pt()
Return a pointer to the vector of pointers to the stored second derivatives of the shape functions w...