element_with_moving_nodes.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-2022 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 base class that specified common interfaces
27 // used in elements with moving Nodes (Spine,Algebraic,MacroElementNodeUpdate)
28 
29 // Include guards to prevent multiple inclusion of the header
30 #ifndef OOMPH_ELEMENT_WITH_MOVING_NODES
31 #define OOMPH_ELEMENT_WITH_MOVING_NODES
32 
33 
34 // oomph-lib headers
35 #include "elements.h"
36 
37 namespace oomph
38 {
42 
43 
44  //=======================================================================
63  //=======================================================================
64  class ElementWithMovingNodes : public virtual FiniteElement
65  {
66  public:
68  enum
69  {
73  };
74 
81  // hierher: Anything other than the fd-based method is currently broken;
82  // at least for refineable elements -- this all needs to be checked
83  // VERY carefully again (see instructions in commit log). Until this
84  // has all been fixed/re-validated, we've frozen the default assignment
85  // (by breaking the functions that change the setting). Ultimately,
86  // we should use:
87  // Method_for_shape_derivs(Shape_derivs_by_fastest_method)
88  {
89  }
90 
93 
95  void operator=(const ElementWithMovingNodes&) = delete;
96 
105  void describe_local_dofs(std::ostream& out,
106  const std::string& current_string) const;
107 
110  {
112  {
113  delete[] Geometric_data_local_eqn[0];
114  delete[] Geometric_data_local_eqn;
115  }
116  }
117 
119  unsigned ngeom_dof() const
120  {
121  return Ngeom_dof;
122  }
123 
126  inline int geometric_data_local_eqn(const unsigned& n, const unsigned& i)
127  {
128 #ifdef RANGE_CHECKING
129  unsigned n_data = Geom_data_pt.size();
130  if (n >= n_data)
131  {
132  std::ostringstream error_message;
133  error_message << "Range Error: Data number " << n
134  << " is not in the range (0," << n_data - 1 << ")";
135  throw OomphLibError(error_message.str(),
138  }
139  else
140  {
141  unsigned n_value = Geom_data_pt[n]->nvalue();
142  if (i >= n_value)
143  {
144  std::ostringstream error_message;
145  error_message << "Range Error: value " << i << " at data " << n
146  << " is not in the range (0," << n_value - 1 << ")";
147  throw OomphLibError(error_message.str(),
150  }
151  }
152 #endif
153 #ifdef PARANOID
154  // Check that the equations have been allocated
155  if (Geometric_data_local_eqn == 0)
156  {
157  throw OomphLibError(
158  "Geometric data local equation numbers have not been allocated",
161  }
162 #endif
163  return Geometric_data_local_eqn[n][i];
164  }
165 
166 
169  std::set<Data*>& unique_geom_data_pt);
170 
175  void identify_geometric_data(std::set<Data*>& geometric_data_pt)
176  {
177  // Loop over the node update data and add to the set
178  const unsigned n_geom_data = Geom_data_pt.size();
179  for (unsigned n = 0; n < n_geom_data; n++)
180  {
181  geometric_data_pt.insert(Geom_data_pt[n]);
182  }
183  }
184 
187  {
189  }
190 
195  {
197  }
198 
205  {
207  }
208 
211  {
212  // hierher: Harmless; simply re-sets the current (and currently only
213  // legal) default
215  }
216 
221  const bool& i_know_what_i_am_doing = false)
222  {
223  if (!i_know_what_i_am_doing)
224  {
225  std::ostringstream error_message;
226  error_message
227  << "Evaluation of shape derivatives by chain rule is currently \n"
228  << "disabled because it's broken, at least for refineable \n"
229  << "elements. This all needs to be checked again very carefully\n"
230  << "following the instructions in the commit log\n"
231  << "If you know what you're doing and want to force this "
232  "methodology\n"
233  << "call this function with the optional boolean set to true.\n";
234  throw OomphLibError(
235  error_message.str(),
236  "ElementWithMovingNodes::evaluate_shape_derivs_by_chain_rule()",
238  }
240  }
241 
246  const bool& i_know_what_i_am_doing = false)
247  {
248  if (!i_know_what_i_am_doing)
249  {
250  std::ostringstream error_message;
251  error_message
252  << "Evaluation of shape derivatives by fastest method is currently \n"
253  << "disabled because it's broken, at least for refineable \n"
254  << "elements. This all needs to be checked again very carefully\n"
255  << "following the instructions in the commit log\n"
256  << "If you know what you're doing and want to force this "
257  "methodology\n"
258  << "call this function with the optional boolean set to true.\n";
259  throw OomphLibError(
260  error_message.str(),
261  "ElementWithMovingNodes::evaluate_shape_derivs_by_fastest_method()",
263  }
265  }
266 
269  {
271  }
272 
275  {
277  }
278 
281  {
283  }
284 
288  {
290  }
291 
292  protected:
298  RankThreeTensor<double>& dnodal_coordinates_dgeom_dofs);
299 
302 
307  const bool& store_local_dof_pt);
308 
315  DenseMatrix<double>& jacobian);
316 
321  {
323  {
324  // Allocate storage for the residuals
325  const unsigned n_dof = ndof();
326  Vector<double> residuals(n_dof);
327 
328  // Get the residuals for the entire element
329  get_residuals(residuals);
330 
331  // Call the jacobian calculation
332  fill_in_jacobian_from_geometric_data(residuals, jacobian);
333  }
334  }
335 
336 
341 
342  public:
345  unsigned ngeom_data() const
346  {
347  return Geom_data_pt.size();
348  }
349 
350  private:
354 
357  unsigned Ngeom_dof;
358 
362 
368 
372  };
373 
374 
375  //===============================================================
378  //==============================================================
379  template<class ELEMENT, class NODE_TYPE>
380  class ElementWithSpecificMovingNodes : public ELEMENT,
382  {
383  public:
392  void describe_local_dofs(std::ostream& out,
393  const std::string& current_string) const
394  {
395  ELEMENT::describe_local_dofs(out, current_string);
397  }
398 
401 
404  const int& face_index)
405  : ELEMENT(element_pt, face_index), ElementWithMovingNodes()
406  {
407  }
408 
411 
413  void describe_local_dofs(std::ostream& out, std::string& curr_str)
414  {
416  ELEMENT::describe_local_dofs(out, curr_str);
417  }
418 
419 
422  Node* construct_node(const unsigned& n)
423  {
424  // Assign a node to the local node pointer
425  // The dimension and number of values are taken from internal element data
426  // The number of timesteps to be stored comes from the problem!
427  this->node_pt(n) = new NODE_TYPE(this->nodal_dimension(),
428  this->nnodal_position_type(),
429  this->required_nvalue(n));
430  // Now return a pointer to the node, so that the mesh can find it
431  return this->node_pt(n);
432  }
433 
435  Node* construct_node(const unsigned& n, TimeStepper* const& time_stepper_pt)
436  {
437  // Assign a node to the local node pointer
438  // The dimension and number of values are taken from internal element data
439  // The number of timesteps to be stored comes from the problem!
440  this->node_pt(n) = new NODE_TYPE(time_stepper_pt,
441  this->nodal_dimension(),
442  this->nnodal_position_type(),
443  this->required_nvalue(n));
444  // Now return a pointer to the node, so that the mesh can find it
445  return this->node_pt(n);
446  }
447 
449  Node* construct_boundary_node(const unsigned& n)
450  {
451  // Assign a node to the local node pointer
452  // The dimension and number of values are taken from internal element data
453  // The number of timesteps to be stored comes from the problem!
454  this->node_pt(n) =
456  this->nnodal_position_type(),
457  this->required_nvalue(n));
458  // Now return a pointer to the node, so that the mesh can find it
459  return this->node_pt(n);
460  }
461 
463  Node* construct_boundary_node(const unsigned& n,
465  {
466  // Assign a node to the local node pointer
467  // The dimension and number of values are taken from internal element data
468  // The number of timesteps to be stored comes from the problem!
469  this->node_pt(n) =
471  this->nodal_dimension(),
472  this->nnodal_position_type(),
473  this->required_nvalue(n));
474  // Now return a pointer to the node, so that the mesh can find it
475  return this->node_pt(n);
476  }
477 
478 
486  {
487  // Call function of underlying element
488  ELEMENT::complete_setup_of_dependencies();
489 
490  // Call function of the element with moving nodes
492  }
493 
494 
497  void assign_all_generic_local_eqn_numbers(const bool& store_local_dof_pt)
498  {
499  // Call the generic local equation numbering scheme of the ELEMENT
500  ELEMENT::assign_all_generic_local_eqn_numbers(store_local_dof_pt);
502  store_local_dof_pt);
503  }
504 
506  void get_jacobian(Vector<double>& residuals, DenseMatrix<double>& jacobian)
507  {
509  ELEMENT::get_jacobian(residuals, jacobian);
510 
511  // Now call the additional geometric Jacobian terms
512  this->fill_in_jacobian_from_geometric_data(jacobian);
513  }
514 
517  DenseMatrix<double>& jacobian,
518  DenseMatrix<double>& mass_matrix)
519  {
521  ELEMENT::get_jacobian_and_mass_matrix(residuals, jacobian, mass_matrix);
522 
523  // Now call the additional geometric Jacobian terms
524  this->fill_in_jacobian_from_geometric_data(jacobian);
525  }
526 
527 
528  private:
529  };
530 
531 
532 } // namespace oomph
533 #endif
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
Definition: nodes.h:2242
Definition: element_with_moving_nodes.h:65
unsigned ngeom_dof() const
Number of geometric dofs.
Definition: element_with_moving_nodes.h:119
Vector< Data * > Geom_data_pt
Definition: element_with_moving_nodes.h:340
int geometric_data_local_eqn(const unsigned &n, const unsigned &i)
Definition: element_with_moving_nodes.h:126
unsigned Ngeom_dof
Definition: element_with_moving_nodes.h:357
bool are_dresidual_dnodal_coordinates_always_evaluated_by_fd() const
Return whether shape derivatives are evaluated by fd.
Definition: element_with_moving_nodes.h:186
void operator=(const ElementWithMovingNodes &)=delete
Broken assignment operator.
virtual ~ElementWithMovingNodes()
Virtual destructor (clean up and allocated memory)
Definition: element_with_moving_nodes.h:109
bool Evaluate_dresidual_dnodal_coordinates_by_fd
Definition: element_with_moving_nodes.h:367
ElementWithMovingNodes()
Constructor.
Definition: element_with_moving_nodes.h:76
ElementWithMovingNodes(const ElementWithMovingNodes &)=delete
Broken copy constructor.
void disable_bypass_fill_in_jacobian_from_geometric_data()
Do not bypass the call to fill_in_jacobian_from_geometric_data.
Definition: element_with_moving_nodes.h:280
void enable_bypass_fill_in_jacobian_from_geometric_data()
Bypass the call to fill_in_jacobian_from_geometric_data.
Definition: element_with_moving_nodes.h:274
virtual void assign_all_generic_local_eqn_numbers(const bool &store_local_dof_pt)
Definition: element_with_moving_nodes.cc:197
int & method_for_shape_derivs()
Access to method (enumerated flag) for determination of shape derivs.
Definition: element_with_moving_nodes.h:268
virtual void get_dnodal_coordinates_dgeom_dofs(RankThreeTensor< double > &dnodal_coordinates_dgeom_dofs)
Definition: element_with_moving_nodes.cc:538
bool Bypass_fill_in_jacobian_from_geometric_data
Definition: element_with_moving_nodes.h:361
void complete_setup_of_dependencies()
Construct the vector of (unique) geometric data.
Definition: element_with_moving_nodes.cc:138
int Method_for_shape_derivs
Definition: element_with_moving_nodes.h:371
bool is_fill_in_jacobian_from_geometric_data_bypassed() const
Definition: element_with_moving_nodes.h:287
void evaluate_shape_derivs_by_direct_fd()
Evaluate shape derivatives by direct finite differencing.
Definition: element_with_moving_nodes.h:210
@ Shape_derivs_by_chain_rule
Definition: element_with_moving_nodes.h:70
@ Shape_derivs_by_fastest_method
Definition: element_with_moving_nodes.h:72
@ Shape_derivs_by_direct_fd
Definition: element_with_moving_nodes.h:71
void describe_local_dofs(std::ostream &out, const std::string &current_string) const
Definition: element_with_moving_nodes.cc:170
void evaluate_shape_derivs_by_chain_rule(const bool &i_know_what_i_am_doing=false)
Definition: element_with_moving_nodes.h:220
void identify_geometric_data(std::set< Data * > &geometric_data_pt)
Definition: element_with_moving_nodes.h:175
void fill_in_jacobian_from_geometric_data(DenseMatrix< double > &jacobian)
Definition: element_with_moving_nodes.h:320
unsigned ngeom_data() const
Definition: element_with_moving_nodes.h:345
void assemble_set_of_all_geometric_data(std::set< Data * > &unique_geom_data_pt)
Return a set of all geometric data associated with the element.
Definition: element_with_moving_nodes.cc:43
void fill_in_jacobian_from_geometric_data(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Definition: element_with_moving_nodes.cc:323
int ** Geometric_data_local_eqn
Definition: element_with_moving_nodes.h:353
void disable_always_evaluate_dresidual_dnodal_coordinates_by_fd()
Definition: element_with_moving_nodes.h:204
void evaluate_shape_derivs_by_fastest_method(const bool &i_know_what_i_am_doing=false)
Definition: element_with_moving_nodes.h:245
void enable_always_evaluate_dresidual_dnodal_coordinates_by_fd()
Definition: element_with_moving_nodes.h:194
Definition: element_with_moving_nodes.h:382
void get_jacobian_and_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix)
Compute the element's residuals vector and jacobian matrix.
Definition: element_with_moving_nodes.h:516
ElementWithSpecificMovingNodes(FiniteElement *const &element_pt, const int &face_index)
Constructor used for face elements.
Definition: element_with_moving_nodes.h:403
Node * construct_node(const unsigned &n)
Definition: element_with_moving_nodes.h:422
void assign_all_generic_local_eqn_numbers(const bool &store_local_dof_pt)
Definition: element_with_moving_nodes.h:497
void describe_local_dofs(std::ostream &out, std::string &curr_str)
Unique final overrider for describe_dofs.
Definition: element_with_moving_nodes.h:413
~ElementWithSpecificMovingNodes()
Empty Destructor,.
Definition: element_with_moving_nodes.h:410
Node * construct_boundary_node(const unsigned &n)
Overload the node assignment routine to assign boundary nodes.
Definition: element_with_moving_nodes.h:449
ElementWithSpecificMovingNodes()
Constructor, call the constructor of the base element.
Definition: element_with_moving_nodes.h:400
void describe_local_dofs(std::ostream &out, const std::string &current_string) const
Definition: element_with_moving_nodes.h:392
void get_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Compute the element's residuals vector and jacobian matrix.
Definition: element_with_moving_nodes.h:506
Node * construct_boundary_node(const unsigned &n, TimeStepper *const &time_stepper_pt)
Overloaded boundary node allocation for unsteady problems.
Definition: element_with_moving_nodes.h:463
void complete_setup_of_dependencies()
Definition: element_with_moving_nodes.h:485
Node * construct_node(const unsigned &n, TimeStepper *const &time_stepper_pt)
Overloaded node allocation for unsteady problems.
Definition: element_with_moving_nodes.h:435
Definition: elements.h:1313
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
unsigned nnodal_position_type() const
Definition: elements.h:2463
virtual unsigned required_nvalue(const unsigned &n) const
Definition: elements.h:2455
unsigned nodal_dimension() const
Return the required Eulerian dimension of the nodes in this element.
Definition: elements.h:2484
unsigned ndof() const
Return the number of equations/dofs in the element.
Definition: elements.h:835
virtual void get_residuals(Vector< double > &residuals)
Definition: elements.h:980
TimeStepper *& time_stepper_pt()
Definition: geom_objects.h:192
Definition: nodes.h:906
Definition: oomph_definitions.h:222
A Rank 3 Tensor class.
Definition: matrices.h:1370
Definition: timesteppers.h:231
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ofstream out("Result.txt")