55 &n_continuously_interpolated_values,
60 if((value_id < -1) || (value_id >= n_continuously_interpolated_values))
62 std::ostringstream error_stream;
63 error_stream <<
"Value_id " << value_id <<
" is out of range." 65 <<
"It can only take the values -1 (position) " 66 <<
"or an integer in the range 0 to " 67 << n_continuously_interpolated_values
71 OOMPH_CURRENT_FUNCTION,
72 OOMPH_EXCEPTION_LOCATION);
86 const unsigned el_dim =
dim();
89 const unsigned n_shape =
nnode();
98 std::ostringstream error_message;
99 error_message <<
"Dimension mismatch" << std::endl;
100 error_message <<
"The elemental dimension: " <<
dim()
101 <<
" must equal the nodal dimension: " 103 <<
" for the jacobian of the mapping to be well-defined" 107 OOMPH_CURRENT_FUNCTION,
108 OOMPH_EXCEPTION_LOCATION);
113 for(
unsigned i=0;
i<el_dim;
i++)
116 for(
unsigned j=0;j<el_dim;j++)
121 for(
unsigned l=0;l<n_shape;l++)
123 for(
unsigned k=0;k<n_shape_type;k++)
146 const unsigned el_dim =
dim();
150 const unsigned n_shape =
nnode();
153 const unsigned n_row =
N2deriv[el_dim];
158 for(
unsigned i=0;
i<n_row;
i++)
161 for(
unsigned j=0;j<el_dim;j++)
164 jacobian2(
i,j) = 0.0;
166 for(
unsigned l=0;l<n_shape;l++)
169 for(
unsigned k=0;k<n_shape_type;k++)
190 const unsigned n_node =
nnode();
194 const unsigned n_dim_element =
dim();
198 for(
unsigned i=0;
i<n_dim_element;
i++)
200 for(
unsigned j=0;j<n_dim_node;j++)
203 interpolated_G(
i,j) = 0.0;
204 for(
unsigned l=0;l<n_node;l++)
206 for(
unsigned k=0;k<n_position_type;k++)
230 const unsigned el_dim =
dim();
233 const unsigned n_shape =
nnode();
240 std::ostringstream error_message;
241 error_message <<
"Dimension mismatch" << std::endl;
242 error_message <<
"The elemental dimension: " <<
dim()
243 <<
" must equal the nodal dimension: " 245 <<
" for the jacobian of the mapping to be well-defined" 248 OOMPH_CURRENT_FUNCTION,
249 OOMPH_EXCEPTION_LOCATION);
257 for(
unsigned i=0;
i<el_dim;
i++)
260 for(
unsigned j=0;j<el_dim;j++)
261 {jacobian(
i,j) = 0.0; inverse_jacobian(
i,j) = 0.0;}
264 for(
unsigned l=0;l<n_shape;l++)
267 for(
unsigned k=0;k<n_shape_type;k++)
277 for(
unsigned i=0;
i<el_dim;
i++) {det *= jacobian(
i,
i);}
285 for(
unsigned i=0;
i<el_dim;
i++)
286 {inverse_jacobian(
i,
i) = 1.0/jacobian(
i,
i);}
299 const unsigned n_node =
nnode();
301 for(
unsigned n=0;n<n_node;n++)
314 const bool &store_local_dof_pt)
317 const unsigned n_node =
nnode();
331 bool hanging_eqn_numbers =
false;
341 std::deque<unsigned long> global_eqn_number_queue;
345 for(
unsigned n=0;n<n_node;n++)
348 for(
unsigned j=0;j<n_cont_values;j++)
356 unsigned n_master = hang_info_pt->
nmaster();
358 for(
unsigned m=0;m<n_master;m++)
365 if(local_eqn_number_done[j][Master_node_pt] ==
false)
370 if(Master_node_pt->
nvalue() < j)
372 std::ostringstream error_stream;
374 <<
"Master node for " << j
375 <<
"-th value only has " << Master_node_pt->
nvalue()
376 <<
" stored values!" << std::endl;
380 OOMPH_CURRENT_FUNCTION,
381 OOMPH_EXCEPTION_LOCATION);
393 unsigned local_node_index=n_node;
395 for(
unsigned n1=0;n1<n_node;n1++)
399 if(Master_node_pt==
node_pt(n1))
407 if(local_node_index < n_node)
423 global_eqn_number_queue.push_back(eqn_number);
425 if(store_local_dof_pt)
443 local_eqn_number_done[j][Master_node_pt] =
true;
445 hanging_eqn_numbers =
true;
456 if(store_local_dof_pt)
461 if(!hanging_eqn_numbers)
473 std::set<Node*> all_nodes;
475 for (
unsigned j=0;j<n_node;j++)
484 unsigned n_master = hang_info_pt->
nmaster();
487 for(
unsigned m=0;m<n_master;m++)
491 unsigned old_size=all_nodes.size();
492 all_nodes.insert(master_node_pt);
493 if (all_nodes.size()>old_size)
504 unsigned old_size=all_nodes.size();
505 all_nodes.insert(nod_pt);
506 if (all_nodes.size()>old_size)
524 std::set<std::pair<Data*,unsigned> > &paired_field_data)
528 for(
unsigned n=0;n<n_internal;n++)
533 const unsigned n_value = dat_pt->
nvalue();
536 for(
unsigned i=0;
i<n_value;
i++)
538 paired_field_data.insert(std::make_pair(dat_pt,
i));
543 const unsigned n_node = this->
nnode();
544 for(
unsigned n=0;n<n_node;n++)
549 const unsigned n_value = nod_pt->
nvalue();
552 for(
unsigned i=0;
i<n_value;
i++)
560 const unsigned nmaster = hang_pt->
nmaster();
563 for(
unsigned m=0;m<nmaster;m++)
571 paired_field_data.insert(std::make_pair(master_nod_pt,
i));
579 paired_field_data.insert(std::make_pair(nod_pt,
i));
602 unsigned n_nod=
nnode();
605 if (n_nod==0)
return;
611 unsigned n_dof=
ndof();
622 for (std::map<Node*,unsigned>::iterator it=
628 Node* nod_pt=it->first;
631 unsigned node_number=it->second;
634 for (
unsigned i=0;
i<dim_nod;
i++)
637 double backup=nod_pt->
x(
i);
641 nod_pt->
x(
i)+=eps_fd;
653 for (
unsigned l=0;l<n_dof;l++)
655 dresidual_dnodal_coordinates(l,
i,node_number)=
656 (res_pls[l]-res[l])/eps_fd;
683 const unsigned n_node =
nnode();
686 if(n_node == 0) {
return;}
695 const unsigned n_dof =
ndof();
707 for(
unsigned n=0;n<n_node;n++)
716 for(
unsigned i=0;
i<n_value;
i++)
724 if(local_unknown >= 0)
727 double*
const value_pt = local_node_pt->
value_pt(
i);
730 const double old_var = *value_pt;
733 *value_pt += fd_step;
744 for(
unsigned m=0;m<n_dof;m++)
747 jacobian(m,local_unknown) = (newres[m] - residuals[m])/fd_step;
780 const unsigned n_master = hang_info_pt->
nmaster();
781 for(
unsigned m=0;m<n_master;m++)
789 if(local_unknown >= 0)
792 double*
const value_pt = master_node_pt->
value_pt(
i);
795 const double old_var = *value_pt;
798 *value_pt += fd_step;
809 for(
unsigned m=0;m<n_dof;m++)
812 jacobian(m,local_unknown) = (newres[m] - residuals[m])/fd_step;
859 const unsigned el_dim =
dim();
861 const unsigned n_shape =
nnode();
862 const unsigned n_shape_type = nnodal_lagrangian_type();
865 for(
unsigned i=0;
i<el_dim;
i++)
868 for(
unsigned j=0;j<el_dim;j++)
873 for(
unsigned l=0;l<n_shape;l++)
875 for(
unsigned k=0;k<n_shape_type;k++)
880 jacobian(
i,j) += lagrangian_position_gen(l,k,j)*dpsids(l,k,
i);
898 const unsigned el_dim =
dim();
900 const unsigned n_shape =
nnode();
901 const unsigned n_shape_type = nnodal_lagrangian_type();
903 const unsigned n_row =
N2deriv[el_dim];
908 for(
unsigned i=0;
i<n_row;
i++)
911 for(
unsigned j=0;j<el_dim;j++)
914 jacobian2(
i,j) = 0.0;
916 for(
unsigned l=0;l<n_shape;l++)
919 for(
unsigned k=0;k<n_shape_type;k++)
923 jacobian2(
i,j) += lagrangian_position_gen(l,k,j)*d2psids(l,k,
i);
944 const unsigned el_dim =
dim();
946 const unsigned n_shape =
nnode();
947 const unsigned n_shape_type = nnodal_lagrangian_type();
953 for(
unsigned i=0;
i<el_dim;
i++)
956 for(
unsigned j=0;j<el_dim;j++)
957 {jacobian(
i,j) = 0.0; inverse_jacobian(
i,j) = 0.0;}
960 for(
unsigned l=0;l<n_shape;l++)
963 for(
unsigned k=0;k<n_shape_type;k++)
966 jacobian(
i,
i) += lagrangian_position_gen(l,k,
i)*dpsids(l,k,
i);
973 for(
unsigned i=0;
i<el_dim;
i++) {det *= jacobian(
i,
i);}
981 for(
unsigned i=0;
i<el_dim;
i++)
982 {inverse_jacobian(
i,
i) = 1.0/jacobian(
i,
i);}
1000 const unsigned n_node =
nnode();
1003 std::set<Data*> all_position_data_pt;
1007 for(
unsigned n=0;n<n_node;n++)
1017 unsigned n_master = hang_info_pt->
nmaster();
1020 for(
unsigned m=0;m<n_master;m++)
1026 all_position_data_pt.insert(
1027 dynamic_cast<SolidNode*>(Master_node_pt)->variable_position_pt());
1034 all_position_data_pt.insert(
1035 dynamic_cast<SolidNode*>(
node_pt(n))->variable_position_pt());
1041 return all_position_data_pt.size();
1056 const unsigned n_node =
nnode();
1061 std::set<Data*> all_position_data_pt;
1069 for(
unsigned n=0;n<n_node;n++)
1078 unsigned n_master = hang_info_pt->
nmaster();
1081 for(
unsigned m=0;m<n_master;m++)
1088 dynamic_cast<SolidNode*
>(Master_node_pt)->variable_position_pt();
1091 n_old=all_position_data_pt.size();
1092 all_position_data_pt.insert(pos_data_pt);
1095 if (all_position_data_pt.size()>n_old)
1097 all_position_data_vector_pt.push_back(pos_data_pt);
1111 n_old=all_position_data_pt.size();
1112 all_position_data_pt.insert(pos_data_pt);
1115 if (all_position_data_pt.size()>n_old)
1117 all_position_data_vector_pt.push_back(pos_data_pt);
1125 return all_position_data_vector_pt[j];
1140 const unsigned n_node=this->
nnode();
1141 for(
unsigned j=0;j<n_node;j++)
1151 unsigned n_master = hang_info_pt->
nmaster();
1154 for(
unsigned m=0;m<n_master;m++)
1160 geometric_data_pt.insert(
1161 dynamic_cast<SolidNode*>(Master_node_pt)->variable_position_pt());
1168 geometric_data_pt.insert(
1169 dynamic_cast<SolidNode*>(
node_pt(j))->variable_position_pt());
1179 const bool &store_local_dof_pt)
1182 const unsigned n_node =
nnode();
1188 Local_position_hang_eqn.clear();
1200 std::map<Node*, bool> local_eqn_number_done;
1206 std::deque<unsigned long> global_eqn_number_queue;
1210 for(
unsigned n=0;n<n_node;n++)
1220 unsigned n_master = hang_info_pt->
nmaster();
1222 for(
unsigned m=0;m<n_master;m++)
1229 if(local_eqn_number_done[Master_node_pt]==
false)
1240 unsigned local_node_index=n_node;
1242 for(
unsigned n1=0;n1<n_node;n1++)
1246 if(Master_node_pt==
node_pt(n1))
1248 local_node_index=n1;
1254 if(local_node_index < n_node)
1257 for(
unsigned j=0;j<n_position_type;j++)
1260 for(
unsigned k=0;k<nodal_dim;k++)
1263 Position_local_eqn_at_node(j,k) =
1264 position_local_eqn(local_node_index,j,k);
1272 for(
unsigned j=0;j<n_position_type;j++)
1275 for(
unsigned k=0;k<nodal_dim;k++)
1281 ->position_eqn_number(j,k);
1286 global_eqn_number_queue.push_back(eqn_number);
1288 if(store_local_dof_pt)
1291 &(Master_node_pt->
x_gen(j,k)));
1308 local_eqn_number_done[Master_node_pt] =
true;
1310 Local_position_hang_eqn[Master_node_pt] =
1311 Position_local_eqn_at_node;
1322 if(store_local_dof_pt)
1341 const unsigned n_node =
nnode();
1344 if(n_node == 0) {
return;}
1348 update_before_solid_position_fd();
1357 const unsigned n_dof =
ndof();
1366 int local_unknown=0;
1369 for(
unsigned l=0;l<n_node;l++)
1378 for(
unsigned k=0;k<n_position_type;k++)
1381 for(
unsigned i=0;
i<nodal_dim;
i++)
1383 local_unknown = position_local_eqn(l,k,
i);
1385 if(local_unknown >= 0)
1388 double*
const value_pt = &(local_node_pt->
x_gen(k,
i));
1391 const double old_var = *value_pt;
1394 *value_pt += fd_step;
1400 update_in_solid_position_fd(l);
1409 for(
unsigned m=0;m<n_dof;m++)
1412 jacobian(m,local_unknown) = (newres[m] - residuals[m])/fd_step;
1434 *value_pt = old_var;
1440 reset_in_solid_position_fd(l);
1451 const unsigned n_master = hang_info_pt->
nmaster();
1452 for(
unsigned m=0;m<n_master;m++)
1459 = Local_position_hang_eqn[master_node_pt];
1462 for(
unsigned k=0;k<n_position_type;k++)
1465 for(
unsigned i=0;
i<nodal_dim;
i++)
1467 local_unknown = Position_local_eqn_at_node(k,
i);
1469 if(local_unknown >= 0)
1472 double*
const value_pt = &(master_node_pt->
x_gen(k,
i));
1475 const double old_var = *value_pt;
1478 *value_pt += fd_step;
1484 update_in_solid_position_fd(l);
1492 for(
unsigned m=0;m<n_dof;m++)
1495 jacobian(m,local_unknown) =
1496 (newres[m] - residuals[m])/fd_step;
1518 *value_pt = old_var;
1524 reset_in_solid_position_fd(l);
1535 reset_after_solid_position_fd();
int local_hang_eqn(Node *const &node_pt, const unsigned &i)
Access function that returns the local equation number for the hanging node variables (values stored ...
virtual void get_residuals(Vector< double > &residuals)
Calculate the vector of residuals of the equations in the element. By default initialise the vector t...
virtual unsigned ncont_interpolated_values() const =0
Number of continuously interpolated values. Note: We assume that they are located at the beginning of...
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...
Data * geom_data_pt(const unsigned &j)
Return pointer to the j-th Data item that the object's shape depends on: Positional data of non-hangi...
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.
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...
void assign_hanging_local_eqn_numbers(const bool &store_local_dof_pt)
Assign the local equation numbers for hanging node variables.
HangInfo *const & hanging_pt() const
Return pointer to hanging node data (this refers to the geometric hanging node status) (const version...
static double Max_integrity_tolerance
Max. allowed discrepancy in element integrity check.
double * value_pt(const unsigned &i) const
Return the pointer to the i-the stored value. Typically this is required when direct access to the st...
void get_dresidual_dnodal_coordinates(RankThreeTensor< double > &dresidual_dnodal_coordinates)
Compute derivatives of elemental residual vector with respect to nodal coordinates. Default implementation by FD can be overwritten for specific elements. dresidual_dnodal_coordinates(l,i,j) = d res(l) / dX_{ij} This version is overloaded from the version in FiniteElement and takes hanging nodes into account – j in the above loop loops over all the nodes that actively control the shape of the element (i.e. they are non-hanging or master nodes of hanging nodes in this element).
static void check_value_id(const int &n_continuously_interpolated_values, const int &value_id)
Static helper function that is used to check that the value_id is in range.
void perform_auxiliary_node_update_fct()
Execute auxiliary update function (if any) – this can be used to update any nodal values following t...
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...
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
unsigned nmaster() const
Return the number of master nodes.
void assemble_local_to_eulerian_jacobian(const DShape &dpsids, DenseMatrix< double > &jacobian) const
Assemble the jacobian matrix for the mapping from local.
bool is_hanging() const
Test whether the node is geometrically hanging.
long & eqn_number(const unsigned &i)
Return the equation number of the i-th stored variable.
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
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...
unsigned nnodal_position_type() const
Return the number of coordinate types that the element requires to interpolate the geometry between t...
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
std::map< Node *, int > * Local_hang_eqn
Storage for local equation numbers of hanging node variables (values stored at master nodes)...
unsigned ndof() const
Return the number of equations/dofs in the element.
unsigned nodal_dimension() const
Return the required Eulerian dimension of the nodes in this element.
double & x(const unsigned &i)
Return the i-th nodal coordinate.
unsigned ngeom_data() const
The number of geometric data affecting a RefineableSolidFiniteElement is the positional Data of all n...
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...
virtual void update_before_nodal_fd()
Function that is called before the finite differencing of any nodal data. This may be overloaded to u...
static long Is_pinned
Static "Magic number" used in place of the equation number to indicate that the value is pinned...
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...
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...
Data *& internal_data_pt(const unsigned &i)
Return a pointer to i-th internal data object.
unsigned long eqn_number(const unsigned &ieqn_local) const
Return the global equation number corresponding to the ieqn_local-th local equation number...
void check_jacobian(const double &jacobian) const
Helper function used to check for singular or negative Jacobians in the transform from local to globa...
A class that represents a collection of data; each Data object may contain many different individual ...
double & x_gen(const unsigned &k, const unsigned &i)
Reference to the generalised position x(k,i).
void fill_in_jacobian_from_solid_position_by_fd(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Compute element residual Vector and element Jacobian matrix corresponding to the solid positions...
Node *const & master_node_pt(const unsigned &i) const
Return a pointer to the i-th master node.
static const unsigned N2deriv[]
Static array that holds the number of second derivatives as a function of the dimension of the elemen...
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Class that contains data for hanging nodes.
std::map< Node *, unsigned > Shape_controlling_node_lookup
Lookup scheme for unique number associated with any of the nodes that actively control the shape of t...
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...
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
unsigned ninternal_data() const
Return the number of internal data objects.
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.
virtual void reset_after_nodal_fd()
Function that is call after the finite differencing of the nodal data. This may be overloaded to rese...
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...
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...
virtual void deactivate_element()
Final operations that must be performed when the element is no longer active in the mesh...
void assign_solid_hanging_local_eqn_numbers(const bool &store_local_dof_pt)
Assign local equation numbers to the hanging values associated with positions or additional solid val...
virtual ~RefineableElement()
Destructor, delete the allocated storage for the hanging equations.
int local_eqn_number(const unsigned long &ieqn_global) const
Return the local equation number corresponding to the ieqn_global-th global equation number...
unsigned nnode() const
Return the number of nodes.
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...
static double Default_fd_jacobian_step
Double used for the default finite difference step in elemental jacobian calculations.
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, given the derivatives of the shape function Overload the standard version to use the hanging information for the lagrangian coordinates.
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...
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...