77 for(
unsigned i=0;
i<n_internal_data;
i++)
87 <<
"-----------------------------------------------------------------" 89 <<
"Info: Data is already included in this element's internal storage." 91 <<
"It's stored as entry " <<
i <<
" and I'm not adding it again." 92 << std::endl<< std::endl
93 <<
"Note: You can suppress this message by recompiling without" 94 <<
"\n PARANOID or setting the boolean \n" 95 <<
"\n GeneralisedElement::Suppress_warning_about_repeated_internal_data" 98 <<
"-----------------------------------------------------------------" 99 << std::endl << std::endl;
108 Data** new_data_pt =
new Data*[n_internal_data + n_external_data + 1];
111 for(
unsigned i=0;
i<n_internal_data;
i++) {new_data_pt[
i] =
Data_pt[
i];}
114 new_data_pt[n_internal_data] = data_pt;
117 for(
unsigned i=0;
i<n_external_data;
i++)
118 {new_data_pt[n_internal_data + 1 +
i] =
Data_pt[n_internal_data +
i];}
127 Data_fd.resize(n_internal_data + n_external_data + 1);
129 for(
unsigned i=n_external_data;
i>0;
i--)
140 return n_internal_data;
150 std::deque<unsigned long>
const &global_eqn_numbers,
151 std::deque<double*>
const &global_dof_pt)
154 const unsigned n_dof =
Ndof;
156 const unsigned n_additional_dof = global_eqn_numbers.size();
158 if(n_additional_dof==0) {
return;}
161 const unsigned new_n_dof = n_dof + n_additional_dof;
163 unsigned long *new_eqn_number =
new unsigned long[new_n_dof];
169 unsigned index = n_dof;
171 for(std::deque<unsigned long>::const_iterator it=global_eqn_numbers.begin();
172 it!=global_eqn_numbers.end();++it)
175 new_eqn_number[index] = *it;
182 const unsigned n_additional_dof_pt = global_dof_pt.size();
183 if(n_additional_dof_pt > 0)
187 if(n_additional_dof_pt != n_additional_dof)
189 std::ostringstream error_stream;
192 "global_dof_pt is non-empty, yet it does not have the same size\n" 194 "as global_eqn_numbers.\n" 196 "There are " << n_additional_dof <<
" equation numbers,\n" 198 "but " << n_additional_dof_pt << std::endl;
201 OOMPH_CURRENT_FUNCTION,
202 OOMPH_EXCEPTION_LOCATION);
207 double **new_dof_pt =
new double*[new_n_dof];
209 for(
unsigned i=0;
i<n_dof;
i++) {new_dof_pt[
i] =
Dof_pt[
i];}
212 unsigned index = n_dof;
214 for(std::deque<double*>::const_iterator it=global_dof_pt.begin();
215 it!=global_dof_pt.end();++it)
218 new_dof_pt[index] = *it;
262 GeneralisedElement::~GeneralisedElement()
303 for(
unsigned i=0;
i<n_external_data;
i++)
313 <<
"-----------------------------------------------------------------" 315 <<
"Info: Data is already included in this element's external storage." 317 <<
"It's stored as entry " <<
i <<
" and I'm not adding it again" 318 << std::endl << std::endl
319 <<
"Note: You can suppress this message by recompiling without" 320 <<
"\n PARANOID or setting the boolean \n" 321 <<
"\n GeneralisedElement::Suppress_warning_about_repeated_external_data" 324 <<
"-----------------------------------------------------------------" 325 << std::endl << std::endl;
334 Data** new_data_pt =
new Data*[n_internal_data + n_external_data + 1];
337 for(
unsigned i=0;
i<(n_internal_data + n_external_data);
i++)
341 new_data_pt[n_internal_data + n_external_data] = data_pt;
350 Data_fd.resize(n_internal_data + n_external_data + 1);
352 Data_fd[n_internal_data + n_external_data] = fd;
358 return n_external_data;
370 if(n_external_data>0)
373 Data** new_data_pt=0;
379 if(n_internal_data > 0)
382 new_data_pt =
new Data*[n_internal_data];
384 for(
unsigned i=0;
i<n_internal_data;
i++) {new_data_pt[
i] =
Data_pt[
i];}
395 Data_fd.resize(n_internal_data);
412 unsigned index = n_external_data;
414 for(
unsigned i=0;
i<n_external_data;
i++)
426 if(index < n_external_data)
429 Data** new_data_pt = 0;
435 const unsigned n_total_data = n_internal_data + n_external_data - 1;
438 if(n_total_data > 0) {new_data_pt =
new Data*[n_total_data];}
441 for(
unsigned i=0;
i<n_internal_data;
i++) {new_data_pt[
i] =
Data_pt[
i];}
445 for(
unsigned i=0;
i<n_external_data;
i++)
452 new_data_pt[n_internal_data + counter] =
Data_pt[
i];
473 std::ostringstream warning_stream;
474 warning_stream <<
"Data removed from element's external data " 476 <<
"You may have to update the indices for remaining data " 478 <<
"This can be achieved by using add_external_data() " 481 "GeneralisedElement::flush_external_data()",
482 OOMPH_EXCEPTION_LOCATION);
527 std::stringstream conversion;
528 conversion <<
" of Internal Data "<<
i<<current_string;
552 for(
unsigned i=0;
i<n_internal_data;
i++)
557 std::stringstream conversion;
558 conversion <<
" of Internal Data "<<
i<<current_string;
565 for(
unsigned i=0;
i<n_external_data;
i++)
570 std::stringstream conversion;
571 conversion<<
" of External Data "<<
i<<current_string;
584 std::map<unsigned,double*> &map_of_value_pt)
638 const Vector<long> & vector_of_eqn_numbers,
unsigned &index)
657 const bool &store_local_dof_pt)
666 std::ostringstream error_stream;
670 std::map<unsigned,bool> is_repeated;
671 std::set<unsigned long> set_of_global_eqn_numbers;
673 for(
unsigned n=0;n<
Ndof;++n)
675 set_of_global_eqn_numbers.insert(
Eqn_number[n]);
676 if (set_of_global_eqn_numbers.size()==old_ndof)
678 error_stream <<
"Repeated global eqn: " <<
Eqn_number[n] << std::endl;
681 old_ndof=set_of_global_eqn_numbers.size();
685 if(set_of_global_eqn_numbers.size() !=
Ndof)
688 error_stream <<
"Element is ";
689 if (!
is_halo()) error_stream <<
"not ";
690 error_stream <<
"a halo element\n\n";
692 error_stream <<
"\nLocal/lobal equation numbers: " << std::endl;
693 for(
unsigned n=0;n<
Ndof;++n)
695 error_stream <<
" " << n <<
" " <<
Eqn_number[n] << std::endl;
699 error_stream << std::endl <<
" element address is " <<
this << std::endl;
703 error_stream <<
"Number of internal data " << nint << std::endl;
704 for (
unsigned i=0;
i<nint;
i++)
707 unsigned nval=data_pt->
nvalue();
708 for (
unsigned j=0;j<nval;j++)
711 error_stream <<
"Internal dof: " << eqn_no << std::endl;
712 if (is_repeated[
unsigned(eqn_no)])
714 error_stream <<
"Repeated internal dof: " << eqn_no << std::endl;
721 error_stream <<
"Number of external data " << next << std::endl;
722 for (
unsigned i=0;
i<next;
i++)
725 unsigned nval=data_pt->
nvalue();
726 for (
unsigned j=0;j<nval;j++)
729 error_stream <<
"External dof: " << eqn_no << std::endl;
730 if (is_repeated[
unsigned(eqn_no)])
732 error_stream <<
"Repeated external dof: " << eqn_no;
733 Node* nod_pt=
dynamic_cast<Node*
>(data_pt);
736 error_stream <<
" (is a node at: ";
737 unsigned ndim=nod_pt->
ndim();
738 for (
unsigned ii=0;ii<ndim;ii++)
740 error_stream << nod_pt->
x(ii) <<
" ";
743 error_stream <<
")\n";
758 error_stream <<
"Number of external element data " << next << std::endl;
760 for (
unsigned i=0;
i<next;
i++)
762 unsigned nval=data_pt[
i]->nvalue();
763 for (
unsigned j=0;j<nval;j++)
765 int eqn_no=data_pt[
i]->eqn_number(j);
766 error_stream <<
"External element dof: " << eqn_no << std::endl;
767 if (is_repeated[
unsigned(eqn_no)])
769 error_stream <<
"Repeated external element dof: " 771 Node* nod_pt=
dynamic_cast<Node*
>(data_pt[
i]);
774 error_stream <<
" (is a node at: ";
775 unsigned ndim=nod_pt->
ndim();
776 for (
unsigned ii=0;ii<ndim;ii++)
778 error_stream << nod_pt->
x(ii) <<
" ";
781 error_stream <<
")\n";
791 error_stream <<
"Number of external element geom data " 792 << next << std::endl;
794 external_interaction_geometric_data_pt());
795 for (
unsigned i=0;
i<next;
i++)
797 unsigned nval=data_pt[
i]->nvalue();
798 for (
unsigned j=0;j<nval;j++)
800 int eqn_no=data_pt[
i]->eqn_number(j);
801 error_stream <<
"External element geometric dof: " 802 << eqn_no << std::endl;
803 if (is_repeated[
unsigned(eqn_no)])
805 error_stream <<
"Repeated external element geometric dof: " 807 << data_pt[
i]->value(j);
808 Node* nod_pt=
dynamic_cast<Node*
>(data_pt[
i]);
811 error_stream <<
" (is a node at: ";
812 unsigned ndim=nod_pt->
ndim();
813 for (
unsigned ii=0;ii<ndim;ii++)
815 error_stream << nod_pt->
x(
i) <<
" ";
819 error_stream <<
"\n";
831 unsigned n_node=f_el_pt->
nnode();
832 for (
unsigned n=0;n<n_node;n++)
835 unsigned nval=nod_pt->
nvalue();
836 for (
unsigned j=0;j<nval;j++)
839 error_stream <<
"Node " << n
844 if (is_repeated[
unsigned(eqn_no)])
846 error_stream <<
"Node " << n
847 <<
": Repeated nodal dof: " 851 error_stream <<
" (resized)";
853 error_stream << std::endl;
861 unsigned nval=data_pt->
nvalue();
862 for (
unsigned j=0;j<nval;j++)
865 error_stream <<
"Node " << n <<
": Positional dof: " 866 << eqn_no << std::endl;
867 if (is_repeated[
unsigned(eqn_no)])
869 error_stream <<
"Repeated positional dof: " 870 << eqn_no <<
" " << data_pt->
value(j) << std::endl;
877 n_node=f_el_pt->
nnode();
878 for (
unsigned n=0;n<n_node;n++)
881 unsigned n_dim=nod_pt->
ndim();
882 error_stream <<
"Node " << n <<
" at ( ";
883 for (
unsigned i=0;
i<n_dim;
i++)
885 error_stream << nod_pt->
x(
i) <<
" ";
887 error_stream <<
")" << std::endl;
894 OOMPH_CURRENT_FUNCTION,
895 OOMPH_EXCEPTION_LOCATION);
910 const bool &store_local_dof_pt)
916 const unsigned n_total_data = n_internal_data + n_external_data;
929 for(
unsigned i=1;
i<n_total_data;++
i)
952 for(
unsigned i=0;
i<n_total_values;++
i)
956 for(
unsigned i=1;
i<n_total_data;++
i)
967 std::deque<unsigned long> global_eqn_number_queue;
970 for(
unsigned i=0;
i<n_internal_data;
i++)
975 unsigned n_value = data_pt->
nvalue();
978 for(
unsigned j=0;j<n_value;j++)
986 global_eqn_number_queue.push_back(eqn_number);
988 if(store_local_dof_pt)
990 GeneralisedElement::Dof_pt_deque.push_back(data_pt->
value_pt(j));
1007 for(
unsigned i=0;
i<n_external_data;
i++)
1012 unsigned n_value = data_pt->
nvalue();
1015 for(
unsigned j=0;j<n_value;j++)
1023 global_eqn_number_queue.push_back(eqn_number);
1025 if(store_local_dof_pt)
1027 GeneralisedElement::Dof_pt_deque.push_back(data_pt->
value_pt(j));
1044 GeneralisedElement::Dof_pt_deque);
1046 if(store_local_dof_pt)
1047 {std::deque<double*>().swap(GeneralisedElement::Dof_pt_deque);}
1066 const bool &fd_all_data)
1072 if(n_internal_data == 0) {
return;}
1079 const unsigned n_dof =
ndof();
1085 int local_unknown=0;
1091 for(
unsigned i=0;
i<n_internal_data;
i++)
1101 for(
unsigned j=0;j<n_value;j++)
1106 if(local_unknown >= 0)
1112 const double old_var = *value_pt;
1115 *value_pt += fd_step;
1124 for(
unsigned m=0;m<n_dof;m++)
1126 double sum = (newres[m] - residuals[m])/fd_step;
1128 jacobian(m,local_unknown) = sum;
1132 *value_pt = old_var;
1160 const bool &fd_all_data)
1165 if(n_external_data == 0) {
return;}
1172 const unsigned n_dof =
ndof();
1178 int local_unknown=0;
1184 for(
unsigned i=0;
i<n_external_data;
i++)
1194 for(
unsigned j=0;j<n_value;j++)
1199 if(local_unknown >= 0)
1205 const double old_var = *value_pt;
1208 *value_pt += fd_step;
1217 for(
unsigned m=0;m<n_dof;m++)
1219 double sum = (newres[m] - residuals[m])/fd_step;
1221 jacobian(m,local_unknown) = sum;
1225 *value_pt = old_var;
1252 "Empty fill_in_contribution_to_mass_matrix() has been called.\n";
1254 "This function is called from the default implementation of\n";
1255 error_message +=
"get_mass_matrix();\n";
1257 "and must calculate the residuals vector and mass matrix ";
1258 error_message +=
"without initialising any of their entries.\n\n";
1261 "If you do not wish to use these defaults, you must overload\n";
1263 "get_mass_matrix(), which must initialise the entries\n";
1265 "of the residuals vector and mass matrix to zero.\n";
1269 "GeneralisedElement::fill_in_contribution_to_mass_matrix()",
1270 OOMPH_EXCEPTION_LOCATION);
1286 "Empty fill_in_contribution_to_jacobian_and_mass_matrix() has been ";
1287 error_message +=
"called.\n";
1289 "This function is called from the default implementation of\n";
1290 error_message +=
"get_jacobian_and_mass_matrix();\n";
1292 "and must calculate the residuals vector and mass and jacobian matrices ";
1293 error_message +=
"without initialising any of their entries.\n\n";
1296 "If you do not wish to use these defaults, you must overload\n";
1298 "get_jacobian_and_mass_matrix(), which must initialise the entries\n";
1300 "of the residuals vector, jacobian and mass matrix to zero.\n";
1305 "GeneralisedElement::fill_in_contribution_to_jacobian_and_mass_matrix()",
1306 OOMPH_EXCEPTION_LOCATION);
1321 "Empty fill_in_contribution_to_dresiduals_dparameter() has been ";
1322 error_message +=
"called.\n";
1324 "This function is called from the default implementation of\n";
1325 error_message +=
"get_dresiduals_dparameter();\n";
1327 "and must calculate the derivatives of the residuals vector with respect\n";
1328 error_message +=
"to the passed parameter ";
1329 error_message +=
"without initialising any values.\n\n";
1332 "If you do not wish to use these defaults, you must overload\n";
1334 "get_dresiduals_dparameter(), which must initialise the entries\n";
1336 "of the returned vector to zero.\n";
1339 "This function is intended for use instead of the default (global) \n";
1341 "finite-difference routine when analytic expressions are to be used\n";
1342 error_message +=
"in continuation and bifurcation tracking problems.\n\n";
1343 error_message +=
"This function is only called when the function\n";
1345 "Problem::set_analytic_dparameter() has been called in the driver code\n";
1350 "GeneralisedElement::fill_in_contribution_to_dresiduals_dparameter()",
1351 OOMPH_EXCEPTION_LOCATION);
1364 double*
const ¶meter_pt,
1369 "Empty fill_in_contribution_to_djacobian_dparameter() has been ";
1370 error_message +=
"called.\n";
1372 "This function is called from the default implementation of\n";
1373 error_message +=
"get_djacobian_dparameter();\n";
1375 "and must calculate the derivatives of residuals vector and jacobian ";
1376 error_message +=
"matrix\n";
1377 error_message +=
"with respect to the passed parameter ";
1378 error_message +=
"without initialising any values.\n\n";
1381 "If you do not wish to use these defaults, you must overload\n";
1383 "get_djacobian_dparameter(), which must initialise the entries\n";
1385 "of the returned vector and matrix to zero.\n\n";
1388 "This function is intended for use instead of the default (global) \n";
1390 "finite-difference routine when analytic expressions are to be used\n";
1391 error_message +=
"in continuation and bifurcation tracking problems.\n\n";
1392 error_message +=
"This function is only called when the function\n";
1394 "Problem::set_analytic_dparameter() has been called in the driver code\n";
1400 "GeneralisedElement::fill_in_contribution_to_djacobian_dparameter()",
1401 OOMPH_EXCEPTION_LOCATION);
1417 double*
const ¶meter_pt,
1423 "Empty fill_in_contribution_to_djacobian_and_dmass_matrix_dparameter() has";
1424 error_message +=
" been called.\n";
1426 "This function is called from the default implementation of\n";
1427 error_message +=
"get_djacobian_and_dmass_matrix_dparameter();\n";
1429 "and must calculate the residuals vector and mass and jacobian matrices ";
1430 error_message +=
"without initialising any of their entries.\n\n";
1433 "If you do not wish to use these defaults, you must overload\n";
1435 "get_djacobian_and_dmass_matrix_dparameter(), which must initialise the\n";
1437 "entries of the returned vector and matrices to zero.\n";
1441 "This function is intended for use instead of the default (global) \n";
1443 "finite-difference routine when analytic expressions are to be used\n";
1444 error_message +=
"in continuation and bifurcation tracking problems.\n\n";
1445 error_message +=
"This function is only called when the function\n";
1447 "Problem::set_analytic_dparameter() has been called in the driver code\n";
1454 "GeneralisedElement::fill_in_contribution_to_djacobian_and_dmass_matrix_dparameter()",
1455 OOMPH_EXCEPTION_LOCATION);
1475 "Empty fill_in_contribution_to_hessian_vector_products() has been ";
1476 error_message +=
"called.\n";
1478 "This function is called from the default implementation of\n";
1479 error_message +=
"get_hessian_vector_products(); ";
1480 error_message +=
" and must calculate the products \n";
1481 error_message +=
"of the hessian matrix with the (global) ";
1482 error_message +=
"vectors Y and C\n";
1483 error_message +=
"without initialising any values.\n\n";
1486 "If you do not wish to use these defaults, you must overload\n";
1488 "get_hessian_vector_products(), which must initialise the entries\n";
1490 "of the returned vector to zero.\n\n";
1493 "This function is intended for use instead of the default (global) \n";
1495 "finite-difference routine when analytic expressions are to be used.\n";
1496 error_message +=
"This function is only called when the function\n";
1498 "Problem::set_analytic_hessian_products() has been called in the driver code\n";
1503 "GeneralisedElement::fill_in_contribution_to_hessian_vector_product()",
1504 OOMPH_EXCEPTION_LOCATION);
1512 Vector<std::pair<unsigned,unsigned> >
const &history_index,
1516 "Empty fill_in_contribution_to_inner_products() has been called.\n";
1518 "This function is called from the default implementation of\n";
1519 error_message +=
"get_inner_products();\n ";
1520 error_message +=
"It must calculate the inner products over the element\n";
1521 error_message +=
"of given pairs of history values\n";
1522 error_message +=
"without initialision of the output vector.\n\n";
1525 "If you do not wish to use these defaults, you must overload\n";
1527 "get_inner_products(), which must initialise the entries\n";
1529 "of the returned vector to zero.\n\n";
1534 OOMPH_CURRENT_FUNCTION,
1535 OOMPH_EXCEPTION_LOCATION);
1548 "Empty fill_in_contribution_to_inner_product_vectors() has been called.\n";
1550 "This function is called from the default implementation of\n";
1551 error_message +=
"get_inner_product_vectors(); ";
1552 error_message +=
" and must calculate the vectors \n";
1553 error_message +=
"corresponding to the input history values\n ";
1554 error_message +=
"that when multiplied by other vectors of history values\n";
1555 error_message +=
"return the appropriate dot products.\n\n";
1556 error_message +=
"The output vectors must not be initialised.\n\n";
1559 "If you do not wish to use these defaults, you must overload\n";
1561 "get_inner_products(), which must initialise the entries\n";
1563 "of the returned vector to zero.\n\n";
1568 OOMPH_CURRENT_FUNCTION,
1569 OOMPH_EXCEPTION_LOCATION);
1592 <<
"\n ERROR: Failed GeneralisedElement::self_test()!" << std::endl;
1594 <<
"for internal data object number: " <<
i << std::endl;
1605 <<
"\n ERROR: Failed GeneralisedElement::self_test()!" << std::endl;
1607 <<
"for external data object number: " <<
i << std::endl;
1612 if (passed) {
return 0;}
1621 namespace Locate_zeta_helpers
1667 return node_pt(n)->x(i);
1687 describe_nodal_local_dofs(out,current_string);
1705 const unsigned n_node = nnode();
1706 for(
unsigned n=0;n<n_node;n++)
1709 Node*
const nod_pt = node_pt(n);
1711 std::stringstream conversion;
1712 conversion<<
" of Node "<<n<<current_string;
1727 if(std::fabs(jacobian) < Tolerance_for_singular_jacobian)
1735 std::ostringstream error_stream;
1737 <<
"Determinant of Jacobian matrix is zero --- " 1738 <<
"singular mapping!\nThe determinant of the " 1739 <<
"jacobian is " << std::fabs(jacobian)
1740 <<
" which is smaller than the treshold " 1741 << Tolerance_for_singular_jacobian <<
"\n" 1742 <<
"You can change this treshold, by specifying " 1743 <<
"FiniteElement::Tolerance_for_singular_jacobian \n" 1744 <<
"Here are the nodal coordinates of the inverted element\n" 1745 <<
"in the form \n\n x,y[,z], hang_status\n\n" 1746 <<
"where hang_status = 1 or 2 for non-hanging or hanging\n" 1747 <<
"nodes respectively (useful for automatic sizing of\n" 1748 <<
"tecplot markers to identify the hanging nodes). \n\n" ;
1749 unsigned n_dim_nod=node_pt(0)->ndim();
1750 unsigned n_nod=nnode();
1751 unsigned hang_count=0;
1752 for (
unsigned j=0;j<n_nod;j++)
1754 for (
unsigned i=0;
i<n_dim_nod;
i++)
1756 error_stream << node_pt(j)->x(
i) <<
" ";
1758 if (node_pt(j)->is_hanging())
1760 error_stream <<
" 2";
1765 error_stream <<
" 1";
1767 error_stream << std::endl;
1769 error_stream << std::endl << std::endl;
1770 if ((Macro_elem_pt!=0)&&(0!=hang_count))
1773 <<
"NOTE: Offending element is associated with a MacroElement\n" 1774 <<
" AND the element has hanging nodes! \n" 1775 <<
" If an element is thin and highly curved, the \n" 1776 <<
" constraints imposed by\n \n" 1777 <<
" (1) inter-element continuity (imposed by the hanging\n" 1778 <<
" node constraints) and \n\n" 1779 <<
" (2) the need to respect curvilinear domain boundaries\n" 1780 <<
" during mesh refinement (imposed by the element's\n" 1781 <<
" macro element mapping)\n\n" 1782 <<
" may be irreconcilable! \n \n" 1783 <<
" You may have to re-design your base mesh to avoid \n" 1784 <<
" the creation of thin, highly curved elements during\n" 1785 <<
" the refinement process.\n" 1789 OOMPH_CURRENT_FUNCTION,
1790 OOMPH_EXCEPTION_LOCATION);
1796 if((Accept_negative_jacobian==
false) && (jacobian < 0.0))
1805 std::ostringstream error_stream;
1807 <<
"Negative Jacobian in transform from " 1808 <<
"local to global coordinates" 1810 <<
" You have an inverted coordinate system!" 1811 << std::endl << std::endl;
1813 <<
"Here are the nodal coordinates of the inverted element\n" 1814 <<
"in the form \n\n x,y[,z], hang_status\n\n" 1815 <<
"where hang_status = 1 or 2 for non-hanging or hanging\n" 1816 <<
"nodes respectively (useful for automatic sizing of\n" 1817 <<
"tecplot markers to identify the hanging nodes). \n\n" ;
1818 unsigned n_dim_nod=node_pt(0)->ndim();
1819 unsigned n_nod=nnode();
1820 unsigned hang_count=0;
1821 for (
unsigned j=0;j<n_nod;j++)
1823 for (
unsigned i=0;
i<n_dim_nod;
i++)
1825 error_stream << node_pt(j)->x(
i) <<
" ";
1827 if (node_pt(j)->is_hanging())
1829 error_stream <<
" 2";
1834 error_stream <<
" 1";
1836 error_stream << std::endl;
1838 error_stream << std::endl << std::endl;
1839 if ((Macro_elem_pt!=0)&&(0!=hang_count))
1842 <<
"NOTE: The inverted element is associated with a MacroElement\n" 1843 <<
" AND the element has hanging nodes! \n" 1844 <<
" If an element is thin and highly curved, the \n" 1845 <<
" constraints imposed by\n \n" 1846 <<
" (1) inter-element continuity (imposed by the hanging\n" 1847 <<
" node constraints) and \n\n" 1848 <<
" (2) the need to respect curvilinear domain boundaries\n" 1849 <<
" during mesh refinement (imposed by the element's\n" 1850 <<
" macro element mapping)\n\n" 1851 <<
" may be irreconcilable! \n \n" 1852 <<
" You may have to re-design your base mesh to avoid \n" 1853 <<
" the creation of thin, highly curved elements during\n" 1854 <<
" the refinement process.\n" 1859 << std::endl << std::endl
1860 <<
"If you believe that inverted elements do not cause any\n" 1861 <<
"problems in your specific application you can \n " 1862 <<
"suppress this test by: " << std::endl
1863 <<
" i) setting the (static) flag " 1864 <<
"FiniteElement::Accept_negative_jacobian to be true" << std::endl;
1865 error_stream <<
" ii) switching OFF the PARANOID flag" 1866 << std::endl << std::endl;
1869 OOMPH_CURRENT_FUNCTION,
1870 OOMPH_EXCEPTION_LOCATION);
1887 const unsigned el_dim = dim();
1890 const unsigned n_shape = nnode();
1893 const unsigned n_shape_type = nnodal_position_type();
1897 if(Elemental_dimension != Nodal_dimension)
1899 std::ostringstream error_message;
1900 error_message <<
"Dimension mismatch" << std::endl;
1901 error_message <<
"The elemental dimension: " << Elemental_dimension
1902 <<
" must equal the nodal dimension: " 1904 <<
" for the jacobian of the mapping to be well-defined" 1907 OOMPH_CURRENT_FUNCTION,
1908 OOMPH_EXCEPTION_LOCATION);
1914 for(
unsigned i=0;
i<el_dim;
i++)
1917 for(
unsigned j=0;j<el_dim;j++)
1920 jacobian(
i,j) = 0.0;
1922 for(
unsigned l=0;l<n_shape;l++)
1924 for(
unsigned k=0;k<n_shape_type;k++)
1930 jacobian(
i,j) += raw_nodal_position_gen(l,k,j)*dpsids(l,k,
i);
1948 const unsigned el_dim = dim();
1952 const unsigned n_shape = nnode();
1953 const unsigned n_shape_type = nnodal_position_type();
1955 const unsigned n_row = N2deriv[el_dim];
1960 for(
unsigned i=0;
i<n_row;
i++)
1963 for(
unsigned j=0;j<el_dim;j++)
1966 jacobian2(
i,j) = 0.0;
1968 for(
unsigned l=0;l<n_shape;l++)
1971 for(
unsigned k=0;k<n_shape_type;k++)
1976 jacobian2(
i,j) += raw_nodal_position_gen(l,k,j)*d2psids(l,k,
i);
1993 const unsigned n_node = nnode();
1994 const unsigned n_position_type = nnodal_position_type();
1996 const unsigned n_dim_node = nodal_dimension();
1997 const unsigned n_dim_element = dim();
2001 for(
unsigned i=0;
i<n_dim_element;
i++)
2003 for(
unsigned j=0;j<n_dim_node;j++)
2006 interpolated_G(
i,j) = 0.0;
2007 for(
unsigned l=0;l<n_node;l++)
2009 for(
unsigned k=0;k<n_position_type;k++)
2011 interpolated_G(
i,j) += raw_nodal_position_gen(l,k,j)*dpsids(l,k,
i);
2023 double FiniteElement::
2028 oomph_info <<
"\nWarning: You are trying to invert the jacobian for " 2029 <<
"a 'point' element" << std::endl
2030 <<
"This makes no sense and is almost certainly an error" 2031 << std::endl << std::endl;
2042 double FiniteElement::
2047 const double det = jacobian(0,0);
2051 check_jacobian(det);
2055 inverse_jacobian(0,0) = 1.0/jacobian(0,0);
2065 double FiniteElement::
2070 const double det = jacobian(0,0)*jacobian(1,1) - jacobian(0,1)*jacobian(1,0);
2074 check_jacobian(det);
2078 inverse_jacobian(0,0) = jacobian(1,1)/det;
2079 inverse_jacobian(0,1) = -jacobian(0,1)/det;
2080 inverse_jacobian(1,0) = -jacobian(1,0)/det;
2081 inverse_jacobian(1,1) = jacobian(0,0)/det;
2091 double FiniteElement::
2096 const double det = jacobian(0,0)*jacobian(1,1)*jacobian(2,2)
2097 + jacobian(0,1)*jacobian(1,2)*jacobian(2,0)
2098 + jacobian(0,2)*jacobian(1,0)*jacobian(2,1)
2099 - jacobian(0,0)*jacobian(1,2)*jacobian(2,1)
2100 - jacobian(0,1)*jacobian(1,0)*jacobian(2,2)
2101 - jacobian(0,2)*jacobian(1,1)*jacobian(2,0);
2105 check_jacobian(det);
2109 inverse_jacobian(0,0) = (jacobian(1,1)*jacobian(2,2)
2110 - jacobian(1,2)*jacobian(2,1))/det;
2111 inverse_jacobian(0,1) = -(jacobian(0,1)*jacobian(2,2)
2112 - jacobian(0,2)*jacobian(2,1))/det;
2113 inverse_jacobian(0,2) = (jacobian(0,1)*jacobian(1,2)
2114 - jacobian(0,2)*jacobian(1,1))/det;
2115 inverse_jacobian(1,0) = -(jacobian(1,0)*jacobian(2,2)
2116 - jacobian(1,2)*jacobian(2,0))/det;
2117 inverse_jacobian(1,1) = (jacobian(0,0)*jacobian(2,2)
2118 - jacobian(0,2)*jacobian(2,0))/det;
2119 inverse_jacobian(1,2) = -(jacobian(0,0)*jacobian(1,2)
2120 - jacobian(0,2)*jacobian(1,0))/det;
2121 inverse_jacobian(2,0) = (jacobian(1,0)*jacobian(2,1)
2122 - jacobian(1,1)*jacobian(2,0))/det;
2123 inverse_jacobian(2,1) = -(jacobian(0,0)*jacobian(2,1)
2124 - jacobian(0,1)*jacobian(2,0))/det;
2125 inverse_jacobian(2,2) = (jacobian(0,0)*jacobian(1,1)
2126 - jacobian(0,1)*jacobian(1,0))/det;
2143 const unsigned el_dim = dim();
2149 return invert_jacobian<0>(jacobian,inverse_jacobian);
2152 return invert_jacobian<1>(jacobian,inverse_jacobian);
2155 return invert_jacobian<2>(jacobian,inverse_jacobian);
2158 return invert_jacobian<3>(jacobian,inverse_jacobian);
2162 std::ostringstream error_stream;
2164 <<
"Dimension of the element must be 0,1,2 or 3, not " << el_dim
2168 OOMPH_CURRENT_FUNCTION,
2169 OOMPH_EXCEPTION_LOCATION);
2180 void FiniteElement::dJ_eulerian_dnodal_coordinates_templated_helper<0>(
2185 oomph_info <<
"\nWarning: You are trying to calculate derivatives of " 2186 <<
"a jacobian w.r.t. nodal coordinates for a 'point' " 2187 <<
"element." << std::endl
2188 <<
"This makes no sense and is almost certainly an error." 2189 << std::endl << std::endl;
2197 void FiniteElement::dJ_eulerian_dnodal_coordinates_templated_helper<1>(
2202 const unsigned n_node = nnode();
2205 for(
unsigned j=0;j<n_node;j++)
2207 djacobian_dX(0,j) = dpsids(j,0);
2216 void FiniteElement::dJ_eulerian_dnodal_coordinates_templated_helper<2>(
2221 const unsigned n_node = nnode();
2224 for(
unsigned j=0;j<n_node;j++)
2227 djacobian_dX(0,j) = dpsids(j,0)*jacobian(1,1) - dpsids(j,1)*jacobian(0,1);
2230 djacobian_dX(1,j) = dpsids(j,1)*jacobian(0,0) - dpsids(j,0)*jacobian(1,0);
2239 void FiniteElement::dJ_eulerian_dnodal_coordinates_templated_helper<3>(
2244 const unsigned n_node = nnode();
2247 for(
unsigned j=0;j<n_node;j++)
2251 = dpsids(j,0)*(jacobian(1,1)*jacobian(2,2)
2252 - jacobian(1,2)*jacobian(2,1))
2253 + dpsids(j,1)*(jacobian(0,2)*jacobian(2,1)
2254 - jacobian(0,1)*jacobian(2,2))
2255 + dpsids(j,2)*(jacobian(0,1)*jacobian(1,2)
2256 - jacobian(0,2)*jacobian(1,1));
2260 = dpsids(j,0)*(jacobian(1,2)*jacobian(2,0)
2261 - jacobian(1,0)*jacobian(2,2))
2262 + dpsids(j,1)*(jacobian(0,0)*jacobian(2,2)
2263 - jacobian(0,2)*jacobian(2,0))
2264 + dpsids(j,2)*(jacobian(0,2)*jacobian(1,0)
2265 - jacobian(0,0)*jacobian(1,2));
2269 = dpsids(j,0)*(jacobian(1,0)*jacobian(2,1)
2270 - jacobian(1,1)*jacobian(2,0))
2271 + dpsids(j,1)*(jacobian(0,1)*jacobian(2,0)
2272 - jacobian(0,0)*jacobian(2,1))
2273 + dpsids(j,2)*(jacobian(0,0)*jacobian(1,1)
2274 - jacobian(0,1)*jacobian(1,0));
2284 void FiniteElement::d_dshape_eulerian_dnodal_coordinates_templated_helper<0>(
2285 const double &det_jacobian,
2293 oomph_info <<
"\nWarning: You are trying to calculate derivatives of " 2294 <<
"eulerian derivatives of shape functions w.r.t. nodal " 2295 <<
"coordinates for a 'point' element." << std::endl
2296 <<
"This makes no sense and is almost certainly an error." 2297 << std::endl << std::endl;
2306 void FiniteElement::d_dshape_eulerian_dnodal_coordinates_templated_helper<1>(
2307 const double &det_jacobian,
2315 const double inv_det_jac = 1.0/det_jacobian;
2318 const unsigned n_node = nnode();
2321 for(
unsigned q=0;q<n_node;q++)
2324 for(
unsigned j=0;j<n_node;j++)
2326 d_dpsidx_dX(0,q,j,0)
2327 = - djacobian_dX(0,q)*dpsids(j,0)*inv_det_jac*inv_det_jac;
2338 void FiniteElement::d_dshape_eulerian_dnodal_coordinates_templated_helper<2>(
2339 const double &det_jacobian,
2347 const double inv_det_jac = 1.0/det_jacobian;
2350 const unsigned n_node = nnode();
2353 for(
unsigned p=0;p<2;p++)
2356 for(
unsigned q=0;q<n_node;q++)
2359 for(
unsigned j=0;j<n_node;j++)
2362 d_dpsidx_dX(p,q,j,0) = - djacobian_dX(p,q)*
2363 (inverse_jacobian(0,0)*dpsids(j,0)
2364 + inverse_jacobian(0,1)*dpsids(j,1));
2368 d_dpsidx_dX(p,q,j,0)
2369 += dpsids(j,0)*dpsids(q,1) - dpsids(j,1)*dpsids(q,0);
2371 d_dpsidx_dX(p,q,j,0) *= inv_det_jac;
2374 d_dpsidx_dX(p,q,j,1) = - djacobian_dX(p,q)*
2375 (inverse_jacobian(1,1)*dpsids(j,1)
2376 + inverse_jacobian(1,0)*dpsids(j,0));
2380 d_dpsidx_dX(p,q,j,1)
2381 += dpsids(j,1)*dpsids(q,0) - dpsids(j,0)*dpsids(q,1);
2383 d_dpsidx_dX(p,q,j,1) *= inv_det_jac;
2395 void FiniteElement::d_dshape_eulerian_dnodal_coordinates_templated_helper<3>(
2396 const double &det_jacobian,
2404 const double inv_det_jac = 1.0/det_jacobian;
2407 const unsigned n_node = nnode();
2410 for(
unsigned p=0;p<3;p++)
2413 for(
unsigned q=0;q<n_node;q++)
2416 for(
unsigned j=0;j<n_node;j++)
2419 for(
unsigned i=0;
i<3;
i++)
2421 d_dpsidx_dX(p,q,j,
i)
2422 = - djacobian_dX(p,q)*(inverse_jacobian(
i,0)*dpsids(j,0)
2423 + inverse_jacobian(
i,1)*dpsids(j,1)
2424 + inverse_jacobian(
i,2)*dpsids(j,2));
2431 d_dpsidx_dX(p,q,j,1)+=((dpsids(q,2)*jacobian(1,2)
2432 - dpsids(q,1)*jacobian(2,2))*dpsids(j,0)
2433 + (dpsids(q,0)*jacobian(2,2)
2434 - dpsids(q,2)*jacobian(0,2))*dpsids(j,1)
2435 + (dpsids(q,1)*jacobian(0,2)
2436 - dpsids(q,0)*jacobian(1,2))*dpsids(j,2));
2438 d_dpsidx_dX(p,q,j,2)+=((dpsids(q,1)*jacobian(2,1)
2439 - dpsids(q,2)*jacobian(1,1))*dpsids(j,0)
2440 + (dpsids(q,2)*jacobian(0,1)
2441 - dpsids(q,0)*jacobian(2,1))*dpsids(j,1)
2442 + (dpsids(q,0)*jacobian(1,1)
2443 - dpsids(q,1)*jacobian(0,1))*dpsids(j,2));
2448 d_dpsidx_dX(p,q,j,0)+=((dpsids(q,1)*jacobian(2,2)
2449 - dpsids(q,2)*jacobian(1,2))*dpsids(j,0)
2450 + (dpsids(q,2)*jacobian(0,2)
2451 - dpsids(q,0)*jacobian(2,2))*dpsids(j,1)
2452 + (dpsids(q,0)*jacobian(1,2)
2453 - dpsids(q,1)*jacobian(0,2))*dpsids(j,2));
2455 d_dpsidx_dX(p,q,j,2)+=((dpsids(q,2)*jacobian(1,0)
2456 - dpsids(q,1)*jacobian(2,0))*dpsids(j,0)
2457 + (dpsids(q,0)*jacobian(2,0)
2458 - dpsids(q,2)*jacobian(0,0))*dpsids(j,1)
2459 + (dpsids(q,1)*jacobian(0,0)
2460 - dpsids(q,0)*jacobian(1,0))*dpsids(j,2));
2465 d_dpsidx_dX(p,q,j,0)+=((dpsids(q,2)*jacobian(1,1)
2466 - dpsids(q,1)*jacobian(2,1))*dpsids(j,0)
2467 + (dpsids(q,0)*jacobian(2,1)
2468 - dpsids(q,2)*jacobian(0,1))*dpsids(j,1)
2469 + (dpsids(q,1)*jacobian(0,1)
2470 - dpsids(q,0)*jacobian(1,1))*dpsids(j,2));
2472 d_dpsidx_dX(p,q,j,1)+=((dpsids(q,1)*jacobian(2,0)
2473 - dpsids(q,2)*jacobian(1,0))*dpsids(j,0)
2474 + (dpsids(q,2)*jacobian(0,0)
2475 - dpsids(q,0)*jacobian(2,0))*dpsids(j,1)
2476 + (dpsids(q,0)*jacobian(1,0)
2477 - dpsids(q,1)*jacobian(0,0))*dpsids(j,2));
2482 for(
unsigned i=0;
i<3;
i++)
2484 d_dpsidx_dX(p,q,j,
i) *= inv_det_jac;
2542 const unsigned el_dim = dim();
2545 const unsigned n_shape = nnode();
2546 const unsigned n_shape_type = nnodal_position_type();
2550 if(Elemental_dimension != Nodal_dimension)
2552 std::ostringstream error_message;
2553 error_message <<
"Dimension mismatch" << std::endl;
2554 error_message <<
"The elemental dimension: " << Elemental_dimension
2555 <<
" must equal the nodal dimension: " 2557 <<
" for the jacobian of the mapping to be well-defined" 2560 OOMPH_CURRENT_FUNCTION,
2561 OOMPH_EXCEPTION_LOCATION);
2569 for(
unsigned i=0;
i<el_dim;
i++)
2572 for(
unsigned j=0;j<el_dim;j++)
2573 {jacobian(
i,j) = 0.0; inverse_jacobian(
i,j) = 0.0;}
2576 for(
unsigned l=0;l<n_shape;l++)
2579 for(
unsigned k=0;k<n_shape_type;k++)
2582 jacobian(
i,
i) += raw_nodal_position_gen(l,k,
i)*dpsids(l,k,
i);
2589 for(
unsigned i=0;
i<el_dim;
i++) {det *= jacobian(
i,
i);}
2593 check_jacobian(det);
2597 for(
unsigned i=0;
i<el_dim;
i++)
2598 {inverse_jacobian(
i,
i) = 1.0/jacobian(
i,
i);}
2616 const unsigned el_dim = dim();
2620 const unsigned n_node = nnode();
2623 if(djacobian_dX.
nrow()!=el_dim)
2625 std::ostringstream error_message;
2626 error_message <<
"djacobian_dX must have the same number of rows as the" 2627 <<
"\nspatial dimension of the element.";
2629 OOMPH_CURRENT_FUNCTION,
2630 OOMPH_EXCEPTION_LOCATION);
2633 if(djacobian_dX.
ncol()!=n_node)
2635 std::ostringstream error_message;
2636 error_message <<
"djacobian_dX must have the same number of columns as the" 2637 <<
"\nnumber of nodes in the element.";
2639 OOMPH_CURRENT_FUNCTION,
2640 OOMPH_EXCEPTION_LOCATION);
2649 dJ_eulerian_dnodal_coordinates_templated_helper<0>(jacobian,dpsids,
2653 dJ_eulerian_dnodal_coordinates_templated_helper<1>(jacobian,dpsids,
2657 dJ_eulerian_dnodal_coordinates_templated_helper<2>(jacobian,dpsids,
2661 dJ_eulerian_dnodal_coordinates_templated_helper<3>(jacobian,dpsids,
2666 std::ostringstream error_stream;
2668 <<
"Dimension of the element must be 0,1,2 or 3, not " << el_dim
2672 OOMPH_CURRENT_FUNCTION,
2673 OOMPH_EXCEPTION_LOCATION);
2698 const double &det_jacobian,
2706 const unsigned el_dim = dim();
2710 const unsigned n_node = nnode();
2713 if(d_dpsidx_dX.
nindex1()!=el_dim || d_dpsidx_dX.
nindex2()!=n_node
2714 || d_dpsidx_dX.
nindex3()!=n_node || d_dpsidx_dX.
nindex4()!=el_dim)
2716 std::ostringstream error_message;
2717 error_message <<
"d_dpsidx_dX must be of the following dimensions:" 2718 <<
"\nd_dpsidx_dX(el_dim,n_node,n_node,el_dim)";
2720 OOMPH_CURRENT_FUNCTION,
2721 OOMPH_EXCEPTION_LOCATION);
2730 d_dshape_eulerian_dnodal_coordinates_templated_helper<0>(
2731 det_jacobian,jacobian,djacobian_dX,inverse_jacobian,dpsids,d_dpsidx_dX);
2734 d_dshape_eulerian_dnodal_coordinates_templated_helper<1>(
2735 det_jacobian,jacobian,djacobian_dX,inverse_jacobian,dpsids,d_dpsidx_dX);
2738 d_dshape_eulerian_dnodal_coordinates_templated_helper<2>(
2739 det_jacobian,jacobian,djacobian_dX,inverse_jacobian,dpsids,d_dpsidx_dX);
2742 d_dshape_eulerian_dnodal_coordinates_templated_helper<3>(
2743 det_jacobian,jacobian,djacobian_dX,inverse_jacobian,dpsids,d_dpsidx_dX);
2747 std::ostringstream error_stream;
2749 <<
"Dimension of the element must be 0,1,2 or 3, not " << el_dim
2753 OOMPH_CURRENT_FUNCTION,
2754 OOMPH_EXCEPTION_LOCATION);
2769 const unsigned n_basis = dbasis.
nindex1();
2770 const unsigned n_basis_type = dbasis.
nindex2();
2772 const unsigned n_dim = dim();
2775 double new_derivatives[n_dim];
2778 for(
unsigned l=0;l<n_basis;l++)
2781 for(
unsigned k=0;k<n_basis_type;k++)
2784 for(
unsigned j=0;j<n_dim;j++)
2787 new_derivatives[j] = 0.0;
2789 for(
unsigned i=0;
i<n_dim;
i++)
2791 new_derivatives[j] += inverse_jacobian(j,
i)*dbasis(l,k,
i);
2795 for(
unsigned j=0;j<n_dim;j++) {dbasis(l,k,j) = new_derivatives[j];}
2811 const unsigned n_basis = dbasis.
nindex1();
2812 const unsigned n_basis_type = dbasis.
nindex2();
2814 const unsigned n_dim = dim();
2817 for(
unsigned l=0;l<n_basis;l++)
2820 for(
unsigned k=0;k<n_basis_type;k++)
2823 for(
unsigned j=0;j<n_dim;j++)
2825 dbasis(l,k,j) *= inverse_jacobian(j,j);
2839 void FiniteElement::
2850 const unsigned n_basis = dbasis.nindex1();
2851 const unsigned n_basis_type = dbasis.nindex2();
2855 for(
unsigned l=0;l<n_basis;l++)
2858 for(
unsigned k=0;k<n_basis_type;k++)
2860 d2basis(l,k,0) = d2basis(l,k,0)/(jacobian(0,0)*jacobian(0,0))
2862 - dbasis(l,k,0)*jacobian2(0,0)/
2863 (jacobian(0,0)*jacobian(0,0)*jacobian(0,0));
2869 transform_derivatives(inverse_jacobian,dbasis);
2881 void FiniteElement::
2892 const unsigned n_basis = dbasis.nindex1();
2893 const unsigned n_basis_type = dbasis.nindex2();
2896 const double det = jacobian(0,0)*jacobian(1,1) - jacobian(0,1)*jacobian(1,0);
2904 ddetds[0] = jacobian2(0,0)*jacobian(1,1) + jacobian(0,0)*jacobian2(2,1)
2905 - jacobian2(0,1)*jacobian(1,0) - jacobian(0,1)*jacobian2(2,0);
2906 ddetds[1] = jacobian2(2,0)*jacobian(1,1) + jacobian(0,0)*jacobian2(1,1)
2907 - jacobian2(2,1)*jacobian(1,0) - jacobian(0,1)*jacobian2(1,0);
2910 double dinverse_jacobiands[2][2][2];
2912 dinverse_jacobiands[0][0][0] = jacobian2(2,1)/det -
2913 jacobian(1,1)*ddetds[0]/(det*det);
2914 dinverse_jacobiands[0][1][0] = -jacobian2(0,1)/det +
2915 jacobian(0,1)*ddetds[0]/(det*det);
2916 dinverse_jacobiands[1][0][0] = -jacobian2(2,0)/det +
2917 jacobian(1,0)*ddetds[0]/(det*det);
2918 dinverse_jacobiands[1][1][0] = jacobian2(0,0)/det -
2919 jacobian(0,0)*ddetds[0]/(det*det);
2921 dinverse_jacobiands[0][0][1] = jacobian2(1,1)/det -
2922 jacobian(1,1)*ddetds[1]/(det*det);
2923 dinverse_jacobiands[0][1][1] = -jacobian2(2,1)/det +
2924 jacobian(0,1)*ddetds[1]/(det*det);
2925 dinverse_jacobiands[1][0][1] = -jacobian2(1,0)/det +
2926 jacobian(1,0)*ddetds[1]/(det*det);
2927 dinverse_jacobiands[1][1][1] = jacobian2(2,0)/det -
2928 jacobian(0,0)*ddetds[1]/(det*det);
2931 DShape dphidXds0(n_basis,n_basis_type,2), dphidXds1(n_basis,n_basis_type,2);
2933 for(
unsigned l=0;l<n_basis;l++)
2935 for(
unsigned k=0;k<n_basis_type;k++)
2937 for(
unsigned j=0;j<2;j++)
2941 dphidXds0(l,k,j) = dinverse_jacobiands[j][0][0]*dbasis(l,k,0)
2942 + dinverse_jacobiands[j][1][0]*dbasis(l,k,1)
2943 + inverse_jacobian(j,0)*d2basis(l,k,0)
2944 + inverse_jacobian(j,1)*d2basis(l,k,2);
2946 dphidXds1(l,k,j) = dinverse_jacobiands[j][0][1]*dbasis(l,k,0)
2947 + dinverse_jacobiands[j][1][1]*dbasis(l,k,1)
2948 + inverse_jacobian(j,0)*d2basis(l,k,2)
2949 + inverse_jacobian(j,1)*d2basis(l,k,1);
2955 for(
unsigned l=0;l<n_basis;l++)
2957 for(
unsigned k=0;k<n_basis_type;k++)
2960 for(
unsigned j=0;j<3;j++) {d2basis(l,k,j) = 0.0;}
2963 for(
unsigned i=0;
i<2;
i++)
2965 d2basis(l,k,
i) = inverse_jacobian(
i,0)*dphidXds0(l,k,
i)+
2966 inverse_jacobian(
i,1)*dphidXds1(l,k,
i);
2969 d2basis(l,k,2) += inverse_jacobian(0,0)*dphidXds0(l,k,1)
2970 + inverse_jacobian(0,1)*dphidXds1(l,k,1);
2976 transform_derivatives(inverse_jacobian,dbasis);
2988 void FiniteElement::
2999 transform_second_derivatives_template<1>(jacobian,
3001 jacobian2,dbasis,d2basis);
3011 void FiniteElement::
3022 const unsigned n_basis = dbasis.nindex1();
3023 const unsigned n_basis_type = dbasis.nindex2();
3029 for(
unsigned l=0;l<n_basis;l++)
3031 for(
unsigned k=0;k<n_basis_type;k++)
3034 d2basis(l,k,0) = d2basis(l,k,0)/(jacobian(0,0)*jacobian(0,0))
3035 - dbasis(l,k,0)*jacobian2(0,0)/
3036 (jacobian(0,0)*jacobian(0,0)*jacobian(0,0));
3038 d2basis(l,k,1) = d2basis(l,k,1)/(jacobian(1,1)*jacobian(1,1))
3039 - dbasis(l,k,1)*jacobian2(1,1)/
3040 (jacobian(1,1)*jacobian(1,1)*jacobian(1,1));
3042 d2basis(l,k,2) = d2basis(l,k,2)/(jacobian(0,0)*jacobian(1,1));
3048 transform_derivatives_diagonal(inverse_jacobian,dbasis);
3069 const unsigned el_dim = dim();
3074 transform_second_derivatives_template<1>(jacobian,
3075 inverse_jacobian,jacobian2,
3079 transform_second_derivatives_template<2>(jacobian,
3080 inverse_jacobian,jacobian2,
3085 throw OomphLibError(
"Not implemented yet ... maybe one day",
3086 OOMPH_CURRENT_FUNCTION,
3087 OOMPH_EXCEPTION_LOCATION);
3095 std::ostringstream error_stream;
3097 <<
"Dimension of the element must be 1,2 or 3, not " << el_dim
3101 OOMPH_CURRENT_FUNCTION,
3102 OOMPH_EXCEPTION_LOCATION);
3121 delete[] Nodal_local_eqn[0];
3122 delete[] Nodal_local_eqn;
3136 local_coordinate_of_node(j,s_fraction);
3137 unsigned n_coordinates = s_fraction.size();
3138 for(
unsigned i=0;
i<n_coordinates;
i++)
3140 s_fraction[
i] = (s_fraction[
i] - s_min())/(s_max() - s_min());
3153 Integral_pt = integral_pt;
3163 const unsigned el_dim = dim();
3167 for(
unsigned i=0;
i<el_dim;
i++) {s[
i] = integral_pt()->knot(ipt,
i);}
3180 const unsigned el_dim = dim();
3184 for(
unsigned i=0;
i<el_dim;
i++) {s[
i] = integral_pt()->knot(ipt,
i);}
3186 dshape_local(s,psi,dpsids);
3212 const unsigned el_dim = dim();
3216 for(
unsigned i=0;
i<el_dim;
i++) {s[
i] = integral_pt()->knot(ipt,
i);}
3218 d2shape_local(s,psi,dpsids,d2psids);
3232 const unsigned el_dim = dim();
3236 dshape_local(s,psi,dpsi);
3241 const double det = local_to_eulerian_mapping(dpsi,inverse_jacobian);
3244 transform_derivatives(inverse_jacobian,dpsi);
3259 const unsigned el_dim = dim();
3263 dshape_local_at_knot(ipt,psi,dpsi);
3268 const double det = local_to_eulerian_mapping(dpsi,inverse_jacobian);
3271 transform_derivatives(inverse_jacobian,dpsi);
3284 const unsigned &ipt,
3289 const unsigned el_dim = dim();
3292 unsigned nnod=nnode();
3293 DShape dpsi(nnod,el_dim);
3294 dshape_local_at_knot(ipt,psi,dpsi);
3300 const double det = local_to_eulerian_mapping(dpsi,jacobian,inverse_jacobian);
3305 dJ_eulerian_dnodal_coordinates(jacobian,dpsi,djacobian_dX);
3321 const unsigned &ipt,
3328 const unsigned el_dim = dim();
3332 dshape_local_at_knot(ipt,psi,dpsi);
3338 const double det = local_to_eulerian_mapping(dpsi,jacobian,inverse_jacobian);
3343 dJ_eulerian_dnodal_coordinates(jacobian,dpsi,djacobian_dX);
3347 d_dshape_eulerian_dnodal_coordinates(det,jacobian,djacobian_dX,
3348 inverse_jacobian,dpsi,d_dpsidx_dX);
3351 transform_derivatives(inverse_jacobian,dpsi);
3386 const unsigned el_dim = dim();
3388 const unsigned n_deriv = N2deriv[el_dim];
3391 d2shape_local(s,psi,dpsi,d2psi);
3397 local_to_eulerian_mapping(dpsi,jacobian,inverse_jacobian);
3402 assemble_local_to_eulerian_jacobian2(d2psi,jacobian2);
3405 transform_second_derivatives(jacobian,inverse_jacobian,
3406 jacobian2,dpsi,d2psi);
3440 const unsigned el_dim = dim();
3442 const unsigned n_deriv = N2deriv[el_dim];
3445 d2shape_local_at_knot(ipt,psi,dpsi,d2psi);
3451 local_to_eulerian_mapping(dpsi,jacobian,inverse_jacobian);
3456 assemble_local_to_eulerian_jacobian2(d2psi,jacobian2);
3459 transform_second_derivatives(jacobian,inverse_jacobian,
3460 jacobian2,dpsi,d2psi);
3476 const bool &store_local_dof_pt)
3479 const unsigned n_node = nnode();
3488 unsigned n_total_values = node_pt(0)->nvalue();
3490 for(
unsigned n=1;n<n_node;n++)
3491 {n_total_values += node_pt(n)->nvalue();}
3496 delete[] Nodal_local_eqn[0];
3497 delete[] Nodal_local_eqn;
3502 if(n_total_values==0) {Nodal_local_eqn=0;
return;}
3506 Nodal_local_eqn =
new int*[n_node];
3508 Nodal_local_eqn[0] =
new int[n_total_values];
3510 for(
unsigned i=0;
i<n_total_values;
i++)
3514 for(
unsigned n=1;n<n_node;++n)
3518 Nodal_local_eqn[n] = Nodal_local_eqn[n-1];
3521 Nodal_local_eqn[n] += Node_pt[n-1]->nvalue();
3526 std::deque<unsigned long> global_eqn_number_queue;
3529 for(
unsigned n=0;n<n_node;n++)
3532 Node*
const nod_pt = node_pt(n);
3535 unsigned n_value = nod_pt->
nvalue();
3538 for(
unsigned j=0;j<n_value;j++)
3546 global_eqn_number_queue.push_back(eqn_number);
3548 if(store_local_dof_pt)
3550 GeneralisedElement::Dof_pt_deque.push_back(
3568 GeneralisedElement::Dof_pt_deque);
3570 if(store_local_dof_pt)
3571 {std::deque<double*>().swap(GeneralisedElement::Dof_pt_deque);}
3587 const unsigned n_node = nnode();
3589 if(n_node == 0) {
return;}
3593 update_before_nodal_fd();
3596 const unsigned n_dof =
ndof();
3601 int local_unknown=0;
3607 for(
unsigned n=0;n<n_node;n++)
3610 const unsigned n_value = node_pt(n)->nvalue();
3613 for(
unsigned i=0;
i<n_value;
i++)
3616 local_unknown = nodal_local_eqn(n,
i);
3618 if(local_unknown >= 0)
3621 double*
const value_pt = node_pt(n)->value_pt(
i);
3624 const double old_var = *value_pt;
3627 *value_pt += fd_step;
3630 update_in_nodal_fd(
i);
3636 for(
unsigned m=0;m<n_dof;m++)
3638 double sum = (newres[m] - residuals[m])/fd_step;
3640 jacobian(m,local_unknown) = sum;
3644 *value_pt = old_var;
3647 reset_in_nodal_fd(
i);
3654 reset_after_nodal_fd();
3670 unsigned n_nod=nnode();
3673 if (n_nod==0)
return;
3676 unsigned dim_nod=node_pt(0)->ndim();
3679 unsigned n_dof=
ndof();
3690 for (
unsigned j=0;j<n_nod;j++)
3693 Node* nod_pt=node_pt(j);
3696 for (
unsigned i=0;
i<dim_nod;
i++)
3699 double backup=nod_pt->
x(
i);
3703 nod_pt->
x(
i)+=eps_fd;
3715 for (
unsigned l=0;l<n_dof;l++)
3717 dresidual_dnodal_coordinates(l,
i,j)=(res_pls[l]-res[l])/eps_fd;
3722 nod_pt->
x(
i)=backup;
3742 unsigned n_node = nnode();
3748 std::vector<int> local_node_number;
3750 for(
unsigned i=0;
i<n_node;
i++)
3754 if(node_pt(
i)==global_node_pt)
3757 local_node_number.push_back(
i);
3764 std::ostringstream error_stream;
3765 error_stream <<
"Node " << global_node_pt <<
" appears " 3766 << count <<
" times in an element." << std::endl
3767 <<
"In positions: ";
3768 for(std::vector<int>::iterator it=local_node_number.begin();
3769 it!=local_node_number.end();++it)
3771 error_stream << *it <<
" ";
3773 error_stream << std::endl
3774 <<
"That seems very odd." << std::endl;
3777 OOMPH_CURRENT_FUNCTION,
3778 OOMPH_EXCEPTION_LOCATION);
3784 for(
unsigned i=0;
i<n_node;
i++)
3788 if(node_pt(
i)==global_node_pt)
3809 const double tol = Node_location_tolerance;
3812 const unsigned el_dim = Elemental_dimension;
3813 const unsigned n_node = Nnode;
3815 for(
unsigned n=0;n<n_node;n++)
3819 local_coordinate_of_node(n,s_node);
3820 for(
unsigned i=0;
i<el_dim;
i++)
3825 if(std::fabs(s[
i] - s_node[
i]) > tol)
3832 if(Match) {
return node_pt(n);}
3848 cog.resize(Elemental_dimension);
3852 unsigned nnod=nnode();
3853 for (
unsigned j=0;j<nnod;j++)
3855 for (
unsigned i=0;
i<Elemental_dimension;
i++)
3857 cog[
i]+=zeta_nodal(j,0,
i);
3860 for (
unsigned i=0;
i<Elemental_dimension;
i++)
3862 cog[
i]/=double(nnod);
3866 for (
unsigned j=0;j<nnod;j++)
3868 double dist_squared=0.0;
3869 for (
unsigned i=0;
i<Elemental_dimension;
i++)
3871 dist_squared+=(cog[
i]-zeta_nodal(j,0,
i))*(cog[
i]-zeta_nodal(j,0,
i));
3873 if (dist_squared>max_radius) max_radius=dist_squared;
3875 max_radius=sqrt(max_radius);
3882 const unsigned &
i)
const 3885 const unsigned n_node = nnode();
3887 const unsigned n_position_type = nnodal_position_type();
3889 Shape psi(n_node,n_position_type);
3894 double interpolated_x = 0.0;
3896 for(
unsigned l=0;l<n_node;l++)
3899 for(
unsigned k=0;k<n_position_type;k++)
3901 interpolated_x += nodal_position_gen(l,k,i)*psi(l,k);
3905 return(interpolated_x);
3914 const unsigned &
i)
const 3917 const unsigned n_node = nnode();
3919 const unsigned n_position_type = nnodal_position_type();
3922 Shape psi(n_node,n_position_type);
3927 double interpolated_x = 0.0;
3929 for(
unsigned l=0;l<n_node;l++)
3932 for(
unsigned k=0;k<n_position_type;k++)
3934 interpolated_x += nodal_position_gen(t,l,k,i)*psi(l,k);
3938 return(interpolated_x);
3948 const unsigned n_node = nnode();
3950 const unsigned n_position_type = nnodal_position_type();
3952 const unsigned nodal_dim = nodal_dimension();
3955 Shape psi(n_node,n_position_type);
3960 for(
unsigned i=0;
i<nodal_dim;
i++)
3965 for(
unsigned l=0;l<n_node;l++)
3968 for(
unsigned k=0;k<n_position_type;k++)
3970 x[
i] += nodal_position_gen(l,k,
i)*psi(l,k);
3985 const unsigned n_node = nnode();
3987 const unsigned n_position_type = nnodal_position_type();
3989 const unsigned nodal_dim = nodal_dimension();
3992 Shape psi(n_node,n_position_type);
3997 for(
unsigned i=0;
i<nodal_dim;
i++)
4002 for(
unsigned l=0;l<n_node;l++)
4005 for(
unsigned k=0;k<n_position_type;k++)
4007 x[
i] += nodal_position_gen(t,l,k,
i)*psi(l,k);
4025 const unsigned n_node = nnode();
4026 const unsigned n_position_type = nnodal_position_type();
4028 const unsigned n_dim_node = nodal_dimension();
4029 const unsigned n_dim_element = dim();
4032 Shape psi(n_node,n_position_type);
4033 DShape dpsids(n_node,n_position_type,n_dim_element);
4035 dshape_local(s,psi,dpsids);
4039 assemble_eulerian_base_vectors(dpsids,interpolated_G);
4043 for(
unsigned i=0;
i<n_dim_element;
i++)
4045 for(
unsigned j=0;j<n_dim_element;j++)
4047 for(
unsigned k=0;k<n_dim_node;k++)
4049 G(
i,j) += interpolated_G(
i,k)*interpolated_G(j,k);
4056 switch(n_dim_element)
4059 throw OomphLibError(
"Cannot calculate J_eulerian() for point element\n",
4060 OOMPH_CURRENT_FUNCTION,
4061 OOMPH_EXCEPTION_LOCATION);
4067 det = G(0,0)*G(1,1) - G(0,1)*G(1,0);
4070 det = G(0,0)*G(1,1)*G(2,2) + G(0,1)*G(1,2)*G(2,0) + G(0,2)*G(1,0)*G(2,1)
4071 - G(0,0)*G(1,2)*G(2,1) - G(0,1)*G(1,0)*G(2,2) - G(0,2)*G(1,1)*G(2,0);
4074 oomph_info <<
"More than 3 dimensions in J_eulerian()" << std::endl;
4090 const unsigned n_node = nnode();
4092 const unsigned n_position_type = nnodal_position_type();
4094 const unsigned n_dim_node = nodal_dimension();
4095 const unsigned n_dim_element = dim();
4098 Shape psi(n_node,n_position_type);
4099 DShape dpsids(n_node,n_position_type,n_dim_element);
4104 dshape_local_at_knot(ipt,psi,dpsids);
4108 assemble_eulerian_base_vectors(dpsids,interpolated_G);
4112 for(
unsigned i=0;
i<n_dim_element;
i++)
4114 for(
unsigned j=0;j<n_dim_element;j++)
4116 for(
unsigned k=0;k<n_dim_node;k++)
4118 G(
i,j) += interpolated_G(
i,k)*interpolated_G(j,k);
4125 switch(n_dim_element)
4128 throw OomphLibError(
"Cannot calculate J_eulerian() for point element\n",
4129 OOMPH_CURRENT_FUNCTION,
4130 OOMPH_EXCEPTION_LOCATION);
4136 det = G(0,0)*G(1,1) - G(0,1)*G(1,0);
4139 det = G(0,0)*G(1,1)*G(2,2) + G(0,1)*G(1,2)*G(2,0) + G(0,2)*G(1,0)*G(2,1)
4140 - G(0,0)*G(1,2)*G(2,1) - G(0,1)*G(1,0)*G(2,2) - G(0,2)*G(1,1)*G(2,0);
4143 oomph_info <<
"More than 3 dimensions in J_eulerian()" << std::endl;
4160 FiniteElement::Accept_negative_jacobian=
true;
4166 const unsigned n_node = nnode();
4169 const unsigned n_position_type = nnodal_position_type();
4172 const unsigned n_dim_element = dim();
4175 Shape psi(n_node,n_position_type);
4176 DShape dpsi(n_node,n_dim_element);
4178 unsigned nintpt=integral_pt()->nweight();
4179 for (
unsigned ipt=0;ipt<nintpt;ipt++)
4181 double jac=dshape_eulerian_at_knot(ipt,psi,dpsi);
4189 FiniteElement::Accept_negative_jacobian=backup;
4196 FiniteElement::Accept_negative_jacobian=backup;
4213 const unsigned n_intpt = integral_pt()->nweight();
4214 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
4217 double w = integral_pt()->weight(ipt);
4219 double J = J_eulerian_at_knot(ipt);
4238 const unsigned ncomponents=integral.size();
4240 for (
unsigned i=0;
i<ncomponents;
i++) {integral[
i]=0.0;}
4244 const unsigned n_dim_eulerian = nodal_dimension();
4250 const unsigned n_intpt = integral_pt()->nweight();
4253 const unsigned n_dim = dim();
4257 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
4260 for(
unsigned i=0;
i<n_dim;
i++) {s[
i] = integral_pt()->knot(ipt,
i);}
4263 for(
unsigned i=0;
i<n_dim_eulerian;
i++) {x[
i] = interpolated_x(s,
i);}
4266 double w = integral_pt()->weight(ipt);
4269 double J = J_eulerian(s);
4272 integrand_fct_pt(time,x,integrand);
4275 for (
unsigned i=0;
i<ncomponents;
i++) {integral[
i]+=integrand[
i]*w*J;}
4287 const unsigned ncomponents=integral.size();
4289 for (
unsigned i=0;
i<ncomponents;
i++) {integral[
i]=0.0;}
4293 const unsigned n_dim_eulerian = nodal_dimension();
4299 const unsigned n_intpt = integral_pt()->nweight();
4302 const unsigned n_dim = dim();
4306 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
4309 for(
unsigned i=0;
i<n_dim;
i++) {s[
i] = integral_pt()->knot(ipt,
i);}
4312 for(
unsigned i=0;
i<n_dim_eulerian;
i++) {x[
i] = interpolated_x(s,
i);}
4315 double w = integral_pt()->weight(ipt);
4318 double J = J_eulerian(s);
4321 integrand_fct_pt(x,integrand);
4324 for (
unsigned i=0;
i<ncomponents;
i++) {integral[
i]+=integrand[
i]*w*J;}
4341 if(integral_pt()==0)
4346 "Pointer to spatial integration scheme has not been set.",
4347 "FiniteElement::self_test()",
4348 OOMPH_EXCEPTION_LOCATION);
4353 const unsigned dim_el = dim();
4361 const unsigned n_intpt = integral_pt()->nweight();
4367 const unsigned n_node = nnode();
4368 const unsigned n_position_type = nnodal_position_type();
4370 Shape psi(n_node,n_position_type);
4371 DShape dpsidx(n_node,dim_el);
4394 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
4397 for(
unsigned i=0;
i<dim_el;
i++)
4399 s[
i] = integral_pt()->knot(ipt,
i);
4404 for (
unsigned test=0;test<ntest;test++)
4414 jacobian = J_eulerian(s);
4423 jacobian = dshape_eulerian_at_knot(ipt,psi,dpsidx);
4430 OOMPH_CURRENT_FUNCTION,
4431 OOMPH_EXCEPTION_LOCATION);
4436 if(std::fabs(jacobian) < 1.0
e-16)
4438 std::ostringstream warning_stream;
4439 warning_stream <<
"Determinant of Jacobian matrix is zero at ipt " 4440 << ipt << std::endl;
4442 "FiniteElement::self_test()",
4443 OOMPH_EXCEPTION_LOCATION);
4450 if ((Accept_negative_jacobian==
false) && (jacobian < 0.0))
4452 std::ostringstream warning_stream;
4453 warning_stream <<
"Jacobian negative at integration point ipt=" 4454 << ipt << std::endl;
4456 <<
"If you think that this is what you want you may: " << std::endl
4457 <<
"set the (static) flag " 4458 <<
"FiniteElement::Accept_negative_jacobian to be true" << std::endl;
4461 "FiniteElement::self_test()",
4462 OOMPH_EXCEPTION_LOCATION);
4472 if (passed) {
return 0;}
4486 const unsigned &t_deriv)
4489 const unsigned n_node = nnode();
4490 const unsigned n_position_type = nnodal_position_type();
4492 Shape psi(n_node,n_position_type);
4500 for(
unsigned l=0;l<n_node;l++)
4503 for(
unsigned k=0;k<n_position_type;k++)
4505 drdt+=dnodal_position_gen_dt(t_deriv,l,k,i)*psi(l,k);
4519 const unsigned &t_deriv,
4523 const unsigned n_node = nnode();
4524 const unsigned n_position_type = nnodal_position_type();
4525 const unsigned nodal_dim = nodal_dimension();
4528 Shape psi(n_node,n_position_type);
4532 for (
unsigned i=0;
i<nodal_dim;
i++)
4539 for(
unsigned l=0;l<n_node;l++)
4542 for(
unsigned k=0;k<n_position_type;k++)
4544 dxdt[
i]+=dnodal_position_gen_dt(t_deriv,l,k,
i)*psi(l,k);
4568 if(Macro_elem_pt!=0) {this->get_x_from_macro_element(s,zeta);}
4573 const unsigned n_node = this->nnode();
4575 const unsigned n_position_type = this->nnodal_position_type();
4577 Shape psi(n_node,n_position_type);
4582 const unsigned ncoord = this->dim();
4584 for(
unsigned i=0;
i<ncoord;
i++) {zeta[
i] = 0.0;}
4588 for(
unsigned l=0;l<n_node;l++)
4590 for(
unsigned k=0;k<n_position_type;k++)
4593 const double psi_ = psi(l,k);
4594 for(
unsigned i=0;
i<ncoord;
i++)
4596 zeta[
i] += this->zeta_nodal(l,k,
i)*psi_;
4619 const bool& use_coordinate_as_initial_guess)
4624 unsigned ncoord = this->dim();
4631 double max_radius=0.0;
4632 get_centre_of_gravity_and_max_radius_in_terms_of_zeta(cog,max_radius);
4636 for (
unsigned i=0;
i<ncoord;
i++)
4638 radius+=(cog[
i]-zeta[
i])*(cog[
i]-zeta[
i]);
4640 radius=sqrt(radius);
4664 if (!use_coordinate_as_initial_guess)
4671 for (
unsigned iplot=0;iplot<num_plot_points;iplot++)
4675 s_list.push_back(s_c);
4683 bool keep_going=
true;
4689 if (use_coordinate_as_initial_guess)
4692 this->interpolated_zeta(s,inter_x);
4695 for(
unsigned i=0;
i<ncoord;
i++) {dx[
i] = zeta[
i] - inter_x[
i];}
4700 double my_min_resid=DBL_MAX;
4705 unsigned n_list_coord=s_list.size();
4707 for (
unsigned i_coord=0; i_coord<n_list_coord; i_coord++)
4709 for (
unsigned i=0;
i<ncoord;
i++)
4711 s_local[
i]=s_list[i_coord][
i];
4714 this->interpolated_zeta(s_local,work_x);
4717 for(
unsigned i=0;
i<ncoord;
i++)
4719 work_dx[
i] = zeta[
i] - work_x[
i];
4723 std::fabs(*std::max_element(work_dx.begin(),work_dx.end(),
4727 if (maxres<my_min_resid)
4729 my_min_resid=maxres;
4755 std::fabs(*std::max_element(dx.begin(),dx.end(),
AbsCmp<double>()));
4766 if (macro_elem_pt()!=0)
4779 for (
unsigned i=0;
i<ncoord;
i++)
4785 this->interpolated_zeta(work_s,work_r);
4788 for (
unsigned j=0; j<ncoord; j++)
4790 jacobian(j,
i)=-(work_r[j]-r[j])/fd_step;
4802 unsigned n_node = this->nnode();
4803 unsigned n_position_type = this->nnodal_position_type();
4804 Shape psi(n_node,n_position_type);
4805 DShape dpsids(n_node,n_position_type,ncoord);
4808 dshape_local(s,psi,dpsids);
4831 for(
unsigned l=0;l<n_node;l++)
4835 for(
unsigned k=0;k<n_position_type;k++)
4838 for(
unsigned i=0;
i<ncoord;
i++)
4840 for(
unsigned j=0;j<ncoord;j++)
4842 interpolated_dxds(
i,j) +=
4843 this->zeta_nodal(l,k,
i)*dpsids(l,k,j);
4851 for(
unsigned i=0;
i<ncoord;
i++)
4853 for(
unsigned j=0;j<ncoord;j++)
4855 jacobian(
i,j) = - interpolated_dxds(
i,j);
4872 <<
"FiniteElement::locate_zeta()" 4874 oomph_info <<
"Should not affect the result!" << std::endl;
4879 for(
unsigned i=0;
i<ncoord;
i++) {s[
i] -= dx[
i];}
4882 this->interpolated_zeta(s,inter_x);
4883 for(
unsigned i=0;
i<ncoord;
i++) {dx[
i] = zeta[
i] - inter_x[
i];}
4887 std::fabs(*std::max_element(dx.begin(),dx.end(),
AbsCmp<double>()));
4899 bool valid=local_coord_is_valid(s);
4905 move_local_coord_back_into_element(s);
4908 this->interpolated_zeta(s,inter_x);
4909 for(
unsigned i=0;
i<ncoord;
i++) {dx[
i] = zeta[
i] - inter_x[
i];}
4913 std::fabs(*std::max_element(dx.begin(),dx.end(),
AbsCmp<double>()));
4936 geom_object_pt =
this;
4947 const unsigned n_node = nnode();
4948 for(
unsigned n=0;n<n_node;n++) {node_pt(n)->node_update();}
4967 std::set<std::pair<Data*,unsigned> > &paired_field_data)
4971 for(
unsigned n=0;n<n_internal;n++)
4976 const unsigned n_value = dat_pt->
nvalue();
4979 for(
unsigned i=0;
i<n_value;
i++)
4981 paired_field_data.insert(std::make_pair(dat_pt,
i));
4986 const unsigned n_node = this->nnode();
4987 for(
unsigned n=0;n<n_node;n++)
4990 Node*
const nod_pt = this->node_pt(n);
4992 const unsigned n_value = nod_pt->
nvalue();
4995 for(
unsigned i=0;
i<n_value;
i++)
4997 paired_field_data.insert(std::make_pair(nod_pt,
i));
5011 #ifdef OOMPH_HAS_MPI 5020 const unsigned nnode_face = nnode_on_face();
5025 face_to_bulk_coordinate_fct_pt(face_index);
5030 bulk_coordinate_derivatives_fct_pt(face_index);
5041 for(
unsigned i=0;
i<nnode_face;
i++)
5044 unsigned bulk_number = get_bulk_node_number(face_index,
i);
5047 face_element_pt->
node_pt(
i) = node_pt(bulk_number);
5051 face_element_pt->
nbulk_value(
i) = required_nvalue(bulk_number);
5055 face_element_pt->
normal_sign() = face_outer_unit_normal_sign(face_index);
5074 unsigned n_dim=dim();
5078 outfile << tecplot_zone_string(nplot);
5081 unsigned num_plot_points=nplot_points(nplot);
5082 for (
unsigned iplot=0;iplot<num_plot_points;iplot++)
5085 get_s_plot(iplot,nplot,s);
5088 for(
unsigned i=0;
i<n_dim+1;
i++)
5090 outfile << interpolated_x(s,
i) <<
" ";
5095 interpolated_zeta(s,zeta);
5096 for(
unsigned i=0;
i<n_dim;
i++)
5098 outfile << zeta[
i] <<
" ";
5100 outfile << std::endl;
5104 write_tecplot_zone_footer(outfile,nplot);
5117 unsigned n_dim_el = this->dim();
5121 if (n_dim_el==0)
return 1.0;
5124 unsigned n_node = nnode();
5127 unsigned n_position_type = this->nnodal_position_type();
5130 unsigned n_dim = this->nodal_dimension();
5133 Shape psi(n_node,n_position_type);
5134 DShape dpsids(n_node,n_position_type,n_dim_el);
5137 dshape_local(s,psi,dpsids);
5143 for(
unsigned l=0;l<n_node;l++)
5146 for(
unsigned k=0;k<n_position_type;k++)
5149 for(
unsigned i=0;
i<n_dim;
i++)
5152 for(
unsigned j=0;j<n_dim_el;j++)
5154 interpolated_A(j,
i) +=
5155 nodal_position_gen(l,bulk_position_type(k),
i)*dpsids(l,k,j);
5162 for(
unsigned i=0;
i<n_dim_el;
i++)
5164 for(
unsigned j=0;j<n_dim_el;j++)
5167 for(
unsigned k=0;k<n_dim;k++)
5169 A(
i,j) += interpolated_A(
i,k)*interpolated_A(j,k);
5182 Adet = A(0,0)*A(1,1) - A(0,1)*A(1,0);
5187 "FaceElement::J_eulerian()",
5188 OOMPH_EXCEPTION_LOCATION);
5205 const unsigned n_node = nnode();
5208 const unsigned n_position_type = nnodal_position_type();
5211 const unsigned n_dim = nodal_dimension();
5212 const unsigned n_dim_el = dim();
5215 Shape psi(n_node,n_position_type);
5216 DShape dpsids(n_node,n_position_type,n_dim_el);
5222 dshape_local_at_knot(ipt,psi,dpsids);
5228 for(
unsigned l=0;l<n_node;l++)
5231 for(
unsigned k=0;k<n_position_type;k++)
5234 for(
unsigned i=0;
i<n_dim;
i++)
5237 for(
unsigned j=0;j<n_dim_el;j++)
5239 interpolated_A(j,
i) +=
5240 nodal_position_gen(l,bulk_position_type(k),
i)*dpsids(l,k,j);
5248 for(
unsigned i=0;
i<n_dim_el;
i++)
5250 for(
unsigned j=0;j<n_dim_el;j++)
5253 for(
unsigned k=0;k<n_dim;k++)
5255 A(
i,j) += interpolated_A(
i,k)*interpolated_A(j,k);
5268 Adet = A(0,0)*A(1,1) - A(0,1)*A(1,0);
5273 "FaceElement::J_eulerian_at_knot()",
5274 OOMPH_EXCEPTION_LOCATION);
5291 const unsigned n_node = nnode();
5294 const unsigned n_position_type = nnodal_position_type();
5297 const unsigned n_dim = nodal_dimension();
5298 const unsigned n_dim_el = dim();
5301 Shape psi(n_node,n_position_type);
5302 DShape dpsids(n_node,n_position_type,n_dim_el);
5305 unsigned nintpt=integral_pt()->nweight();
5306 for (
unsigned ipt=0;ipt<nintpt;ipt++)
5313 dshape_local_at_knot(ipt,psi,dpsids);
5319 for(
unsigned l=0;l<n_node;l++)
5322 for(
unsigned k=0;k<n_position_type;k++)
5325 for(
unsigned i=0;
i<n_dim;
i++)
5328 for(
unsigned j=0;j<n_dim_el;j++)
5330 interpolated_A(j,
i) +=
5331 nodal_position_gen(l,bulk_position_type(k),
i)*dpsids(l,k,j);
5339 for(
unsigned i=0;
i<n_dim_el;
i++)
5341 for(
unsigned j=0;j<n_dim_el;j++)
5344 for(
unsigned k=0;k<n_dim;k++)
5346 A(
i,j) += interpolated_A(
i,k)*interpolated_A(j,k);
5359 Adet = A(0,0)*A(1,1) - A(0,1)*A(1,0);
5364 "FaceElement::J_eulerian_at_knot()",
5365 OOMPH_EXCEPTION_LOCATION);
5393 const unsigned element_dim = dim();
5397 const unsigned spatial_dim = nodal_dimension();
5401 if(s.size()!=element_dim)
5403 std::ostringstream error_stream;
5405 <<
"Local coordinate s passed to outer_unit_normal() has dimension " 5406 << s.size() << std::endl
5407 <<
"but element dimension is " << element_dim << std::endl;
5410 OOMPH_CURRENT_FUNCTION,
5411 OOMPH_EXCEPTION_LOCATION);
5416 if(Tangent_direction_pt != 0 && Tangent_direction_pt->size()!=spatial_dim)
5418 std::ostringstream error_stream;
5420 <<
"Tangent direction vector has dimension " 5421 << Tangent_direction_pt->size() << std::endl
5422 <<
"but spatial dimension is " << spatial_dim << std::endl;
5425 OOMPH_CURRENT_FUNCTION,
5426 OOMPH_EXCEPTION_LOCATION);
5430 if(unit_normal.size()!=spatial_dim)
5432 std::ostringstream error_stream;
5434 <<
"Unit normal passed to outer_unit_normal() has dimension " 5435 << unit_normal.size() << std::endl
5436 <<
"but spatial dimension is " << spatial_dim << std::endl;
5439 OOMPH_CURRENT_FUNCTION,
5440 OOMPH_EXCEPTION_LOCATION);
5445 unsigned ntangent_vec = tang_vec.size();
5457 if(ntangent_vec != 1)
5459 std::ostringstream error_stream;
5461 <<
"This is a 0D FaceElement, we need one tangent vector.\n" 5462 <<
"You have given me " << tang_vec.size() <<
" vector(s).\n";
5464 OOMPH_CURRENT_FUNCTION,
5465 OOMPH_EXCEPTION_LOCATION);
5474 if(ntangent_vec != 1)
5476 std::ostringstream error_stream;
5478 <<
"This is a 1D FaceElement, we need one tangent vector.\n" 5479 <<
"You have given me " << tang_vec.size() <<
" vector(s).\n";
5481 OOMPH_CURRENT_FUNCTION,
5482 OOMPH_EXCEPTION_LOCATION);
5491 if(ntangent_vec != 2)
5493 std::ostringstream error_stream;
5495 <<
"This is a 2D FaceElement, we need two tangent vectors.\n" 5496 <<
"You have given me " << tang_vec.size() <<
" vector(s).\n";
5498 OOMPH_CURRENT_FUNCTION,
5499 OOMPH_EXCEPTION_LOCATION);
5507 "Cannot have a FaceElement with dimension higher than 2",
5508 OOMPH_CURRENT_FUNCTION,
5509 OOMPH_EXCEPTION_LOCATION);
5514 for(
unsigned vec_i = 0; vec_i < ntangent_vec; vec_i++)
5516 if(tang_vec[vec_i].size() != spatial_dim)
5518 std::ostringstream error_stream;
5520 <<
"This problem has " << spatial_dim <<
" spatial dimensions.\n" 5521 <<
"But the " << vec_i <<
" tangent vector has size " 5522 << tang_vec[vec_i].size() << std::endl;
5524 OOMPH_CURRENT_FUNCTION,
5525 OOMPH_EXCEPTION_LOCATION);
5539 std::ostringstream error_stream;
5541 <<
"It is unclear how to calculate a tangent and normal vectors for " 5542 <<
"a point element.\n";
5544 OOMPH_CURRENT_FUNCTION,
5545 OOMPH_EXCEPTION_LOCATION);
5556 const unsigned n_node_bulk = Bulk_element_pt->nnode();
5558 const unsigned n_position_type_bulk =
5559 Bulk_element_pt->nnodal_position_type();
5564 get_local_coordinate_in_bulk(s,s_bulk);
5568 Shape psi(n_node_bulk,n_position_type_bulk);
5569 DShape dpsids(n_node_bulk,n_position_type_bulk,2);
5571 Bulk_element_pt->dshape_local(s_bulk,psi,dpsids);
5578 for(
unsigned l=0;l<n_node_bulk;l++)
5581 for(
unsigned k=0;k<n_position_type_bulk;k++)
5584 for(
unsigned j=0;j<2;j++)
5587 for(
unsigned i=0;
i<spatial_dim;
i++)
5590 interpolated_dxds(j,
i) +=
5591 Bulk_element_pt->nodal_position_gen(l,k,
i)*dpsids(l,k,j);
5602 Vector<double> tangent(3,0.0), interior_tangent(3,0.0), normal(3,0.0);
5608 unsigned interior_direction=0;
5609 get_ds_bulk_ds_face(s,dsbulk_dsface,interior_direction);
5611 for(
unsigned i=0;
i<spatial_dim;
i++)
5615 tangent[
i] = interpolated_dxds(0,
i)*dsbulk_dsface(0,0)
5616 + interpolated_dxds(1,
i)*dsbulk_dsface(1,0);
5619 interior_tangent[
i] = interpolated_dxds(interior_direction,
i);
5632 for(
unsigned i=0;
i<spatial_dim;
i++) {unit_normal[
i] = full_normal[
i];}
5636 for(
unsigned i=0;
i<spatial_dim;
i++)
5637 {unit_normal[
i] *= Normal_sign/length;}
5640 tang_vec[0][0]=-unit_normal[1];
5641 tang_vec[0][1]=unit_normal[0];
5655 if(spatial_dim != 3)
5657 std::ostringstream error_stream;
5658 error_stream <<
"There are only " << spatial_dim
5659 <<
"coordinates at the nodes of this 2D FaceElement,\n" 5660 <<
"which must have come from a 3D Bulk element\n";
5662 OOMPH_CURRENT_FUNCTION,
5663 OOMPH_EXCEPTION_LOCATION);
5668 const unsigned n_node = this->nnode();
5670 const unsigned n_position_type = this->nnodal_position_type();
5674 Shape psi(n_node,n_position_type);
5675 DShape dpsids(n_node,n_position_type,2);
5677 this->dshape_local(s,psi,dpsids);
5684 for(
unsigned l=0;l<n_node;l++)
5687 for(
unsigned k=0;k<n_position_type;k++)
5690 for(
unsigned j=0;j<2;j++)
5693 for(
unsigned i=0;
i<3;
i++)
5698 interpolated_dxds[j][
i] +=
5699 this->nodal_position_gen(l,bulk_position_type(k),
i)*dpsids(l,k,j);
5712 for(
unsigned i=0;
i<spatial_dim;
i++)
5713 {unit_normal[
i] *= Normal_sign/normal_length;}
5716 if(Tangent_direction_pt != 0)
5735 std::ostringstream err_stream;
5736 err_stream <<
"The angle between the unit normal and the \n" 5737 <<
"direction vector is less than 10 degrees.";
5739 OOMPH_CURRENT_FUNCTION,
5740 OOMPH_EXCEPTION_LOCATION);
5754 tang_vec[0][0] = t1_scaling*interpolated_dxds[0][0]
5755 + t2_scaling*interpolated_dxds[1][0];
5756 tang_vec[0][1] = t1_scaling*interpolated_dxds[0][1]
5757 + t2_scaling*interpolated_dxds[1][1];
5758 tang_vec[0][2] = t1_scaling*interpolated_dxds[0][2]
5759 + t2_scaling*interpolated_dxds[1][2];
5766 for(
unsigned vec_i=0; vec_i<2; vec_i++)
5771 for(
unsigned dim_i=0;dim_i<spatial_dim;dim_i++)
5772 {tang_vec[vec_i][dim_i] /= tang_length;}
5788 if(a!=0.0 || b!=0.0)
5794 tang_vec[0][0]=-b/sqrt(a_sq+b_sq);
5795 tang_vec[0][1]= a/sqrt(a_sq+b_sq);
5798 double z=(a_sq +b_sq)
5799 /sqrt(a_sq*c_sq +b_sq*c_sq +(a_sq +b_sq)*(a_sq +b_sq)) ;
5801 tang_vec[1][0]=-(a*c*z)/(a_sq + b_sq) ;
5802 tang_vec[1][1]= -(b*c*z)/(a_sq + b_sq);
5809 if(!FaceElement::Ignore_discontinuous_tangent_warning)
5811 std::ostringstream warn_stream;
5812 warn_stream <<
"I have detected that your normal vector is [0,0,1].\n" 5813 <<
"Since this function compares against 0.0, you may\n" 5814 <<
"get discontinuous tangent vectors.";
5816 OOMPH_CURRENT_FUNCTION,
5817 OOMPH_EXCEPTION_LOCATION);
5820 tang_vec[0][0]= 1.0;
5821 tang_vec[0][1]= 0.0;
5822 tang_vec[0][2]= 0.0;
5825 tang_vec[1][1]= 1.0;
5826 tang_vec[1][2]= 0.0;
5832 OOMPH_CURRENT_FUNCTION,
5833 OOMPH_EXCEPTION_LOCATION);
5843 "Cannot have a FaceElement with dimension higher than 2",
5844 OOMPH_CURRENT_FUNCTION,
5845 OOMPH_EXCEPTION_LOCATION);
5862 const unsigned element_dim = dim();
5865 for(
unsigned i=0;
i<element_dim;
i++) {s[
i] = integral_pt()->knot(ipt,
i);}
5867 continuous_tangent_and_outer_unit_normal(s, tang_vec,unit_normal);
5877 const unsigned element_dim = dim();
5881 const unsigned spatial_dim = nodal_dimension();
5885 if(s.size()!=element_dim)
5887 std::ostringstream error_stream;
5889 <<
"Local coordinate s passed to outer_unit_normal() has dimension " 5890 << s.size() << std::endl
5891 <<
"but element dimension is " << element_dim << std::endl;
5894 OOMPH_CURRENT_FUNCTION,
5895 OOMPH_EXCEPTION_LOCATION);
5899 if(unit_normal.size()!=spatial_dim)
5901 std::ostringstream error_stream;
5903 <<
"Unit normal passed to outer_unit_normal() has dimension " 5904 << unit_normal.size() << std::endl
5905 <<
"but spatial dimension is " << spatial_dim << std::endl;
5908 OOMPH_CURRENT_FUNCTION,
5909 OOMPH_EXCEPTION_LOCATION);
5976 const unsigned n_node_bulk = Bulk_element_pt->nnode();
5978 const unsigned n_position_type_bulk =
5979 Bulk_element_pt->nnodal_position_type();
5985 get_local_coordinate_in_bulk(s,s_bulk);
5989 Shape psi(n_node_bulk,n_position_type_bulk);
5990 DShape dpsids(n_node_bulk,n_position_type_bulk,1);
5992 Bulk_element_pt->dshape_local(s_bulk,psi,dpsids);
5999 for(
unsigned l=0;l<n_node_bulk;l++)
6002 for(
unsigned k=0;k<n_position_type_bulk;k++)
6005 for(
unsigned i=0;
i<spatial_dim;
i++)
6008 interpolated_dxds(0,
i) +=
6009 Bulk_element_pt->nodal_position_gen(l,k,
i)*dpsids(l,k,0);
6016 for(
unsigned i=0;
i<spatial_dim;
i++)
6017 {unit_normal[
i] = interpolated_dxds(0,
i);}
6028 const unsigned n_node_bulk = Bulk_element_pt->nnode();
6030 const unsigned n_position_type_bulk =
6031 Bulk_element_pt->nnodal_position_type();
6036 get_local_coordinate_in_bulk(s,s_bulk);
6040 Shape psi(n_node_bulk,n_position_type_bulk);
6041 DShape dpsids(n_node_bulk,n_position_type_bulk,2);
6043 Bulk_element_pt->dshape_local(s_bulk,psi,dpsids);
6050 for(
unsigned l=0;l<n_node_bulk;l++)
6053 for(
unsigned k=0;k<n_position_type_bulk;k++)
6056 for(
unsigned j=0;j<2;j++)
6059 for(
unsigned i=0;
i<spatial_dim;
i++)
6062 interpolated_dxds(j,
i) +=
6063 Bulk_element_pt->nodal_position_gen(l,k,
i)*dpsids(l,k,j);
6074 Vector<double> tangent(3,0.0), interior_tangent(3,0.0), normal(3,0.0);
6080 unsigned interior_direction=0;
6081 get_ds_bulk_ds_face(s,dsbulk_dsface,interior_direction);
6083 for(
unsigned i=0;
i<spatial_dim;
i++)
6087 tangent[
i] = interpolated_dxds(0,
i)*dsbulk_dsface(0,0)
6088 + interpolated_dxds(1,
i)*dsbulk_dsface(1,0);
6091 interior_tangent[
i] = interpolated_dxds(interior_direction,
i);
6104 for(
unsigned i=0;
i<spatial_dim;
i++) {unit_normal[
i] = full_normal[
i];}
6118 if(spatial_dim != 3)
6120 std::ostringstream error_stream;
6121 error_stream <<
"There are only " << spatial_dim
6122 <<
"coordinates at the nodes of this 2D FaceElement,\n" 6123 <<
"which must have come from a 3D Bulk element\n";
6125 OOMPH_CURRENT_FUNCTION,
6126 OOMPH_EXCEPTION_LOCATION);
6131 const unsigned n_node = this->nnode();
6133 const unsigned n_position_type = this->nnodal_position_type();
6137 Shape psi(n_node,n_position_type);
6138 DShape dpsids(n_node,n_position_type,2);
6140 this->dshape_local(s,psi,dpsids);
6147 for(
unsigned l=0;l<n_node;l++)
6150 for(
unsigned k=0;k<n_position_type;k++)
6153 for(
unsigned j=0;j<2;j++)
6156 for(
unsigned i=0;
i<3;
i++)
6161 interpolated_dxds[j][
i] +=
6162 this->nodal_position_gen(l,bulk_position_type(k),
i)*dpsids(l,k,j);
6177 "Cannot have a FaceElement with dimension higher than 2",
6178 OOMPH_CURRENT_FUNCTION,
6179 OOMPH_EXCEPTION_LOCATION);
6185 for(
unsigned i=0;
i<spatial_dim;
i++)
6186 {unit_normal[
i] *= Normal_sign/length;}
6196 const unsigned element_dim = dim();
6199 for(
unsigned i=0;
i<element_dim;
i++) {s[
i] = integral_pt()->knot(ipt,
i);}
6201 outer_unit_normal(s,unit_normal);
6214 unsigned dim_bulk = Bulk_element_pt->dim();
6220 if(Face_to_bulk_coordinate_fct_pt)
6223 (*Face_to_bulk_coordinate_fct_pt)(
s,s_bulk);
6227 throw OomphLibError(
"Face_to_bulk_coordinate mapping not set",
6228 OOMPH_CURRENT_FUNCTION,
6229 OOMPH_EXCEPTION_LOCATION);
6246 if(Face_to_bulk_coordinate_fct_pt)
6249 (*Face_to_bulk_coordinate_fct_pt)(
s,s_bulk);
6254 throw OomphLibError(
"Face_to_bulk_coordinate mapping not set",
6255 OOMPH_CURRENT_FUNCTION,
6256 OOMPH_EXCEPTION_LOCATION);
6269 unsigned &interior_direction)
const 6272 if(Bulk_coordinate_derivatives_fct_pt)
6275 (*Bulk_coordinate_derivatives_fct_pt)(
s,dsbulk_dsface,interior_direction);
6281 "No function for derivatives of bulk coords wrt face coords set",
6282 OOMPH_CURRENT_FUNCTION,
6283 OOMPH_EXCEPTION_LOCATION);
6306 unsigned n_dim=dim();
6318 unsigned n_node=this->nnode();
6324 unsigned n_intpt=this->integral_pt()->nweight();
6327 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
6330 for(
unsigned i=0;
i<n_dim;
i++)
6332 s[
i]=this->integral_pt()->knot(ipt,
i);
6336 double w=this->integral_pt()->weight(ipt);
6339 double J=this->J_eulerian(s);
6345 this->interpolated_xi(s,xi);
6346 this->interpolated_x(s,x);
6349 for (
unsigned idim=0;idim<n_dim;idim++)
6351 disp[idim]=x[idim]-xi[idim];
6355 for (
unsigned ii=0;ii<n_dim;ii++)
6357 el_norm+=(disp[ii]*disp[ii])*W;
6379 describe_solid_local_dofs(out,current_string);
6393 const unsigned el_dim = dim();
6397 const unsigned n_shape = nnode();
6398 const unsigned n_shape_type = nnodal_lagrangian_type();
6402 if(el_dim != Lagrangian_dimension)
6404 std::ostringstream error_message;
6405 error_message <<
"Dimension mismatch" << std::endl;
6406 error_message <<
"The elemental dimension: " << el_dim
6407 <<
" must equal the nodal Lagrangian dimension: " 6408 << Lagrangian_dimension
6409 <<
" for the jacobian of the mapping to be well-defined" 6412 OOMPH_CURRENT_FUNCTION,
6413 OOMPH_EXCEPTION_LOCATION);
6418 for(
unsigned i=0;
i<el_dim;
i++)
6421 for(
unsigned j=0;j<el_dim;j++)
6424 jacobian(
i,j) = 0.0;
6426 for(
unsigned l=0;l<n_shape;l++)
6428 for(
unsigned k=0;k<n_shape_type;k++)
6434 jacobian(
i,j) += raw_lagrangian_position_gen(l,k,j)*dpsids(l,k,
i);
6452 const unsigned el_dim = dim();
6456 const unsigned n_shape = nnode();
6457 const unsigned n_shape_type = nnodal_lagrangian_type();
6459 const unsigned n_row = N2deriv[el_dim];
6464 for(
unsigned i=0;
i<n_row;
i++)
6467 for(
unsigned j=0;j<el_dim;j++)
6470 jacobian2(
i,j) = 0.0;
6472 for(
unsigned l=0;l<n_shape;l++)
6475 for(
unsigned k=0;k<n_shape_type;k++)
6480 jacobian2(
i,j) += raw_lagrangian_position_gen(l,k,j)*d2psids(l,k,
i);
6493 delete[] Position_local_eqn;
6511 const unsigned el_dim = dim();
6515 const unsigned n_shape = nnode();
6516 const unsigned n_shape_type = nnodal_lagrangian_type();
6522 for(
unsigned i=0;
i<el_dim;
i++)
6525 for(
unsigned j=0;j<el_dim;j++)
6526 {jacobian(
i,j) = 0.0; inverse_jacobian(
i,j) = 0.0;}
6529 for(
unsigned l=0;l<n_shape;l++)
6532 for(
unsigned k=0;k<n_shape_type;k++)
6535 jacobian(
i,
i) += raw_lagrangian_position_gen(l,k,
i)*dpsids(l,k,
i);
6542 for(
unsigned i=0;
i<el_dim;
i++) {det *= jacobian(
i,
i);}
6546 check_jacobian(det);
6550 for(
unsigned i=0;
i<el_dim;
i++)
6551 {inverse_jacobian(
i,
i) = 1.0/jacobian(
i,
i);}
6567 const unsigned el_dim = dim();
6571 dshape_local(s,psi,dpsi);
6576 const double det = local_to_lagrangian_mapping(dpsi,inverse_jacobian);
6579 transform_derivatives(inverse_jacobian,dpsi);
6594 const unsigned el_dim = dim();
6600 dshape_local_at_knot(ipt,psi,dpsi);
6605 const double det = local_to_lagrangian_mapping(dpsi,inverse_jacobian);
6608 transform_derivatives(inverse_jacobian,dpsi);
6638 const unsigned el_dim = dim();
6640 const unsigned n_deriv = N2deriv[el_dim];
6643 d2shape_local(s,psi,dpsi,d2psi);
6649 local_to_lagrangian_mapping(dpsi,jacobian,inverse_jacobian);
6654 assemble_local_to_lagrangian_jacobian2(d2psi,jacobian2);
6657 transform_second_derivatives(jacobian,inverse_jacobian,
6658 jacobian2,dpsi,d2psi);
6690 const unsigned el_dim = dim();
6692 const unsigned n_deriv = N2deriv[el_dim];
6695 d2shape_local_at_knot(ipt,psi,dpsi,d2psi);
6701 local_to_lagrangian_mapping(dpsi,jacobian,inverse_jacobian);
6706 assemble_local_to_lagrangian_jacobian2(d2psi,jacobian2);
6709 transform_second_derivatives(jacobian,inverse_jacobian,
6710 jacobian2,dpsi,d2psi);
6730 const unsigned n_node = nnode();
6732 for(
unsigned n=0;n<n_node;n++)
6736 std::stringstream conversion;
6737 conversion<<
" of Solid Node "<<n<<current_string;
6751 const bool &store_local_dof_pt)
6754 const unsigned n_node = nnode();
6761 const unsigned n_position_type = nnodal_position_type();
6762 const unsigned nodal_dim = nodal_dimension();
6765 delete[] Position_local_eqn;
6767 Position_local_eqn =
new int[n_node*n_position_type*nodal_dim];
6770 std::deque<unsigned long> global_eqn_number_queue;
6777 for(
unsigned n=0;n<n_node;n++)
6783 for(
unsigned j=0;j<n_position_type;j++)
6786 for(
unsigned k=0;k<nodal_dim;k++)
6795 global_eqn_number_queue.push_back(eqn_number);
6797 if(store_local_dof_pt)
6799 GeneralisedElement::Dof_pt_deque.push_back(
6800 &(cast_node_pt->
x_gen(j,k)));
6804 Position_local_eqn[(n*n_position_type + j)*nodal_dim + k] =
6811 Position_local_eqn[(n*n_position_type + j)*nodal_dim + k] =
6820 GeneralisedElement::Dof_pt_deque);
6822 if(store_local_dof_pt)
6823 {std::deque<double*>().swap(GeneralisedElement::Dof_pt_deque);}
6844 const unsigned n_node = nnode();
6847 if(n_node == 0) {
return;}
6851 update_before_solid_position_fd();
6854 const unsigned n_position_type = nnodal_position_type();
6855 const unsigned nodal_dim = nodal_dimension();
6858 const unsigned n_dof = this->
ndof();
6865 int local_unknown=0;
6871 for(
unsigned n=0;n<n_node;n++)
6874 for(
unsigned k=0;k<n_position_type;k++)
6877 for(
unsigned i=0;
i<nodal_dim;
i++)
6880 local_unknown = position_local_eqn(n,k,
i);
6881 if(local_unknown >= 0)
6884 double*
const value_pt = &(node_pt(n)->x_gen(k,
i));
6887 const double old_var = *value_pt;
6890 *value_pt += fd_step;
6893 node_pt(n)->perform_auxiliary_node_update_fct();
6896 update_in_solid_position_fd(n);
6904 for(
unsigned m=0;m<n_dof;m++)
6907 jacobian(m,local_unknown) = (newres[m] - residuals[m])/fd_step;
6929 *value_pt = old_var;
6933 node_pt(n)->perform_auxiliary_node_update_fct();
6936 reset_in_solid_position_fd(n);
6944 reset_after_solid_position_fd();
6952 const unsigned &
i)
const 6955 const unsigned n_node = nnode();
6958 const unsigned n_lagrangian_type = nnodal_lagrangian_type();
6961 Shape psi(n_node,n_lagrangian_type);
6967 double interpolated_xi = 0.0;
6970 for(
unsigned l=0;l<n_node;l++)
6973 for(
unsigned k=0;k<n_lagrangian_type;k++)
6975 interpolated_xi += lagrangian_position_gen(l,k,i)*psi(l,k);
6979 return(interpolated_xi);
6990 const unsigned n_node = nnode();
6993 const unsigned n_lagrangian_type = nnodal_lagrangian_type();
6996 Shape psi(n_node,n_lagrangian_type);
7002 const unsigned n_lagrangian = lagrangian_dimension();
7005 for(
unsigned i=0;
i<n_lagrangian;
i++)
7011 for(
unsigned l=0;l<n_node;l++)
7014 for(
unsigned k=0;k<n_lagrangian_type;k++)
7016 xi[
i] += lagrangian_position_gen(l,k,
i)*psi(l,k);
7034 const unsigned n_node = nnode();
7037 const unsigned n_lagrangian_type = nnodal_lagrangian_type();
7040 unsigned el_dim=dim();
7043 Shape psi(n_node,n_lagrangian_type);
7044 DShape dpsi(n_node,n_lagrangian_type,el_dim);
7047 dshape_local(s,psi,dpsi);
7050 const unsigned n_lagrangian = lagrangian_dimension();
7053 for(
unsigned i=0;
i<n_lagrangian;
i++)
7055 for(
unsigned j=0;j<el_dim;j++)
7061 for(
unsigned l=0;l<n_node;l++)
7064 for(
unsigned k=0;k<n_lagrangian_type;k++)
7066 dxids(
i,j) += lagrangian_position_gen(l,k,
i)*dpsi(l,k,j);
7084 if ((Solid_ic_pt!=0)||(!Solve_for_consistent_newmark_accel_flag))
7086 std::ostringstream error_stream;
7087 error_stream <<
"Can only call fill_in_jacobian_for_newmark_accel()\n" 7088 <<
"With Solve_for_consistent_newmark_accel_flag:" 7089 << Solve_for_consistent_newmark_accel_flag << std::endl;
7090 error_stream <<
"Solid_ic_pt: " << Solid_ic_pt << std::endl;
7093 OOMPH_CURRENT_FUNCTION,
7094 OOMPH_EXCEPTION_LOCATION);
7099 const unsigned n_node = nnode();
7100 const unsigned n_position_type = nnodal_position_type();
7101 const unsigned nodal_dim = nodal_dimension();
7104 const unsigned n_lagrangian = dim();
7107 int local_eqn=0, local_unknown=0;
7111 Shape psi(n_node,n_position_type);
7115 DShape dpsidxi(n_node,n_position_type,n_lagrangian);
7118 const unsigned n_intpt = integral_pt()->nweight();
7124 TimeStepper* timestepper_pt= node_pt(0)->position_time_stepper_pt();
7129 if (timestepper_pt->
type()!=
"Newmark")
7131 std::ostringstream error_stream;
7133 <<
"Assignment of Newmark accelerations obviously only works\n" 7134 <<
"for Newmark timesteppers. You've called me with " 7135 << timestepper_pt->
type() << std::endl;
7138 OOMPH_CURRENT_FUNCTION,
7139 OOMPH_EXCEPTION_LOCATION);
7144 const unsigned ntstorage=timestepper_pt->
ntstorage();
7145 const double accel_weight=timestepper_pt->
weight(2,ntstorage-1);
7148 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
7152 for(
unsigned i=0;
i<n_lagrangian;
i++) {s[
i] = integral_pt()->knot(ipt,
i);}
7155 double w = integral_pt()->weight(ipt);
7159 double J = dshape_lagrangian(s,psi,dpsidxi);
7163 interpolated_xi(s,xi);
7166 double factor=multiplier(xi);
7172 for(
unsigned l0=0;l0<n_node;l0++)
7175 for(
unsigned k0=0;k0<n_position_type;k0++)
7178 for(
unsigned i0=0;i0<nodal_dim;i0++)
7180 local_eqn = position_local_eqn(l0,k0,i0);
7185 for(
unsigned l1=0;l1<n_node;l1++)
7189 for(
unsigned k1=0;k1<n_position_type;k1++)
7194 local_unknown = position_local_eqn(l1,k1,i1);
7196 if(local_unknown >= 0)
7201 jacobian(local_eqn,local_unknown) +=
7202 factor*accel_weight*psi(l0,k0)*psi(l1,k1)*
W;
7239 const unsigned& flag)
7242 const unsigned n_node = nnode();
7243 const unsigned n_position_type = nnodal_position_type();
7246 const unsigned nodal_dim = nodal_dimension();
7249 const unsigned n_lagrangian_type = nnodal_lagrangian_type();
7252 const unsigned n_lagrangian = dim();
7256 int local_unknown=0;
7259 Shape psi(n_node,n_position_type);
7266 const unsigned n_intpt = integral_pt()->nweight();
7272 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
7276 for(
unsigned i=0;
i<n_lagrangian;
i++)
7277 {s[
i] = integral_pt()->knot(ipt,
i);}
7280 double w = integral_pt()->weight(ipt);
7289 for(
unsigned i=0;
i<n_lagrangian;
i++)
7292 for(
unsigned l=0;l<n_node;l++)
7295 for(
unsigned k=0;k<n_lagrangian_type;k++)
7297 xi[
i] += lagrangian_position_gen(l,k,
i)*psi(l,k);
7304 Solid_ic_pt->geom_object_pt()->
7305 dposition_dt(xi,Solid_ic_pt->ic_time_deriv(),drdt_ic);
7310 for (
unsigned l=0;l<n_node;l++)
7313 for (
unsigned k=0;k<n_position_type;k++)
7316 for (
unsigned i=0;
i<nodal_dim;
i++)
7318 local_eqn = position_local_eqn(l,k,
i);
7327 residuals[local_eqn] += (interpolated_x(s,
i)-drdt_ic[
i])*
7336 for (
unsigned ll=0;ll<n_node;ll++)
7339 for (
unsigned kk=0;kk<n_position_type;kk++)
7345 local_unknown = position_local_eqn(ll,kk,ii);
7348 if(local_unknown >= 0)
7354 jacobian(local_eqn,local_unknown) +=
7355 psi(ll,kk)*psi(l,k)*w;
7360 <<
"WARNING: You should really free all Data" 7362 <<
" before setup of initial guess" 7364 <<
"ll, kk, ii " << ll <<
" " << kk <<
" " << ii
7375 <<
"WARNING: You should really free all Data" << std::endl
7376 <<
" before setup of initial guess" << std::endl
7377 <<
"l, k, i " << l <<
" " << k <<
" " <<
i << std::endl;
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...
virtual void get_residuals(Vector< double > &residuals)
Calculate the vector of residuals of the equations in the element. By default initialise the vector t...
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...
virtual void reset_after_internal_fd()
Function that is call after the finite differencing of the internal data. This may be overloaded to r...
Class of matrices containing doubles, and stored as a DenseMatrix<double>, but with solving functiona...
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...
double value(const unsigned &i) const
Return i-th stored value. This function is not virtual so that it can be inlined. This means that if ...
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...
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...
void clear_global_eqn_numbers()
Clear the storage for the global equation numbers and pointers to dofs (if stored) ...
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. On return the index will be set to the value at the end of the data that has been read in.
unsigned long nrow() const
Return the number of rows of the matrix.
virtual void assign_additional_local_eqn_numbers()
Setup any additional look-up schemes for local equation numbers. Examples of use include using local ...
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...
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...
std::vector< bool > Data_fd
Storage for boolean flags of size Ninternal_data + Nexternal_data that correspond to the data used in...
void output_zeta(std::ostream &outfile, const unsigned &nplot)
Output boundary coordinate zeta.
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...
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, given the derivatives of the shape function.
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...
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...
virtual void describe_nodal_local_dofs(std::ostream &out, const std::string ¤t_string) const
Function to describe the local dofs of the element[s]. The ostream specifies the output stream to whi...
static bool Ignore_discontinuous_tangent_warning
Ignores the warning when the tangent vectors from continuous_tangent_and_outer_unit_normal may not be...
unsigned long ncol() const
Return the number of columns of the matrix.
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-...
unsigned long * Eqn_number
Storage for the global equation numbers represented by the degrees of freedom in the element...
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.
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...
unsigned Max_newton_iterations
Maximum number of newton iterations.
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...
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...
int & face_index()
Index of the face (a number that uniquely identifies the face in the element)
virtual void set_integration_scheme(Integral *const &integral_pt)
Set the spatial integration scheme.
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...
void perform_auxiliary_node_update_fct()
Execute auxiliary update function (if any) – this can be used to update any nodal values following t...
virtual void fill_in_contribution_to_djacobian_and_dmass_matrix_dparameter(double *const ¶meter_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...
const double Pi
50 digits from maple
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...
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.
static bool Accept_negative_jacobian
Boolean that if set to true allows a negative jacobian in the transform between global and local coor...
virtual void add_value_pt_to_map(std::map< unsigned, double *> &map_of_value_pt)
Add pointers to all unpinned and unconstrained data to a map indexed by (global) equation number...
void outer_unit_normal(const Vector< double > &s, Vector< double > &unit_normal) const
Compute outer unit normal at the specified local coordinate.
virtual unsigned self_test()
Self-test: Check inversion of element & do self-test for GeneralisedElement. Return 0 if OK...
void disable_error_message()
Suppress issueing of the error message in destructor (useful if error is caught successfully!) ...
virtual void describe_local_dofs(std::ostream &out, const std::string ¤t_string) const
Function to describe the local dofs of the element[s]. The ostream specifies the output stream to whi...
void describe_dofs(std::ostream &out, const std::string ¤t_string) const
Function to describe the dofs of the Node. The ostream specifies the output stream to which the descr...
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...
BulkCoordinateDerivativesFctPt & bulk_coordinate_derivatives_fct_pt()
Return the pointer to the function that returns the derivatives of the bulk coordinates wrt the face ...
virtual void fill_in_contribution_to_djacobian_dparameter(double *const ¶meter_pt, Vector< double > &dres_dparam, DenseMatrix< double > &djac_dparam)
Add the elemental contribution to the derivatives of the elemental Jacobian matrix and residuals with...
A general Finite Element class.
void(* UnsteadyExactSolutionFctPt)(const double &, const Vector< double > &, Vector< double > &)
Function pointer for function that computes Vector-valued time-dependent function as ...
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...
static PointIntegral Default_integration_scheme
Return spatial dimension of element (=number of local coordinates needed to parametrise the element) ...
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...
bool is_halo() const
Is this element a halo?
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
void describe_solid_local_dofs(std::ostream &out, const std::string ¤t_string) const
Classifies dofs locally for solid specific aspects.
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...
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).
virtual void describe_dofs(std::ostream &out, const std::string ¤t_string) const
Function to describe the dofs of the Node. The ostream specifies the output stream to which the descr...
unsigned & bulk_node_number(const unsigned &n)
Return the bulk node number that corresponds to the n-th local node number.
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...
unsigned long nindex2() const
Return the range of index 2 of the derivatives of the shape functions.
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...
Vector< Data * > external_interaction_field_data_pt() const
Return vector of pointers to the field Data objects that affect the interactions on the element...
unsigned long nindex2() const
Return the range of index 2 of the tensor.
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...
unsigned add_external_data(Data *const &data_pt, const bool &fd=true)
unsigned Ndof
Number of degrees of freedom.
void shape(const Vector< double > &s, Shape &psi) const
Broken assignment operator.
double J_eulerian(const Vector< double > &s) const
Return the Jacobian of mapping from local to global coordinates at local position s...
void solve(DoubleVector &rhs)
Complete LU solve (replaces matrix by its LU decomposition and overwrites RHS with solution)...
void flush_external_data()
Flush all external data.
int & normal_sign()
Sign of outer unit normal (relative to cross-products of tangent vectors in the corresponding "bulk" ...
unsigned nexternal_data() const
Return the number of external data objects.
virtual void fill_in_contribution_to_dresiduals_dparameter(double *const ¶meter_pt, Vector< double > &dres_dparam)
Add the elemental contribution to the derivatives of the residuals with respect to a parameter...
void check_J_eulerian_at_knots(bool &passed) const
Check that Jacobian of mapping between local and Eulerian.
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
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. Used to assess approximately if a point is likely to be contained with an element in locate_zeta-like operations.
unsigned ndof() const
Return the number of equations/dofs in the element.
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...
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...
void cross(const Vector< double > &A, const Vector< double > &B, Vector< double > &C)
Cross product using "proper" output (move semantics means this is ok nowadays).
void integrate_fct(FiniteElement::SteadyExactSolutionFctPt integrand_fct_pt, Vector< double > &integral)
Evaluate integral of a Vector-valued function over the element.
int Non_halo_proc_ID
Non-halo processor ID for Data; -1 if it's not a halo.
virtual unsigned self_test()
Self-test: Have all internal values been classified as pinned/unpinned? Return 0 if OK...
double & x(const unsigned &i)
Return the i-th nodal coordinate.
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution" as ...
virtual double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s.
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...
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 ...
double angle(const Vector< double > &a, const Vector< double > &b)
Get the angle between two vector.
static bool Suppress_warning_about_repeated_external_data
Static boolean to suppress warnings about repeated external data. Defaults to true.
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...
virtual void add_values_to_vector(Vector< double > &vector_of_values)
Add all data and time history values to the vector in the internal storage order. ...
unsigned long nindex4() const
Return the range of index 4 of the tensor.
static long Is_pinned
Static "Magic number" used in place of the equation number to indicate that the value is pinned...
virtual void assign_solid_local_eqn_numbers(const bool &store_local_dof)
Assigns local equation numbers for the generic solid local equation numbering schemes. If the boolean flag is true the the degrees of freedom are stored in Dof_pt.
virtual void reset_after_external_fd()
Function that is call after the finite differencing of the external data. This may be overloaded to r...
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...
virtual ~SolidFiniteElement()
Destructor to clean up any allocated memory.
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...
void set_halo(const unsigned &non_halo_proc_ID)
Label the element as halo and specify processor that holds non-halo counterpart.
virtual void shape_at_knot(const unsigned &ipt, Shape &psi) const
Return the geometric shape function at the ipt-th integration point.
double ** Dof_pt
Storage for array of pointers to degrees of freedom ordered by local equation number. This information is not needed, except in continuation, bifurcation tracking and periodic orbit calculations. It is not set up unless the control flag Problem::Store_local_dof_pts_in_elements = true.
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-...
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...
static bool Suppress_output_while_checking_for_inverted_elements
Static boolean to suppress output while checking for inverted elements.
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_...
Data *& internal_data_pt(const unsigned &i)
Return a pointer to i-th internal data object.
double magnitude(const Vector< double > &a)
Get the magnitude of a vector.
unsigned long eqn_number(const unsigned &ieqn_local) const
Return the global equation number corresponding to the ieqn_local-th local equation number...
static double Tolerance_for_singular_jacobian
Tolerance below which the jacobian is considered singular.
unsigned long nindex3() const
Return the range of index 3 of the tensor.
void check_jacobian(const double &jacobian) const
Helper function used to check for singular or negative Jacobians in the transform from local to globa...
unsigned long nindex1() const
Return the range of index 1 of the tensor.
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...
void nbulk_value_resize(const unsigned &i)
Resize the storage for the number of values originally stored at the local nodes to i entries...
void describe_dofs(std::ostream &out, const std::string ¤t_string) const
Function to describe the dofs of the element. The ostream specifies the output stream to which the de...
A class that represents a collection of data; each Data object may contain many different individual ...
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...
double & x_gen(const unsigned &k, const unsigned &i)
Reference to the generalised position x(k,i).
virtual void read_values_from_vector(const Vector< double > &vector_of_values, unsigned &index)
Read all data and time history values from the vector starting from index. On return the index will b...
unsigned nexternal_interaction_field_data() const
Return the number of Data items that affect the external interactions in this element. This includes e.g. fluid velocities and pressures in adjacent fluid elements in an FSI problem.
Data *const & variable_position_pt() const
Pointer to variable_position data (const version)
unsigned nexternal_interaction_geometric_data() const
Return the number of geometric Data items that affect the external interactions in this element: i...
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 ...
Data ** Data_pt
Storage for pointers to internal and external data. The data is of the same type and so can be addres...
static const unsigned Default_Initial_Nvalue
Default return value for required_nvalue(n) which gives the number of "data" values required by the e...
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...
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.
static const double Node_location_tolerance
Default value for the tolerance to be used when locating nodes via local coordinates.
virtual void assign_eqn_numbers(unsigned long &global_ndof, Vector< double *> &dof_pt)
Assign global equation numbers; increment global number of unknowns, global_ndof; and add any new dof...
void shape(const double &s, double *Psi)
Definition for 1D Lagrange shape functions. The value of all the shape functions at the local coordin...
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.
virtual void update_before_internal_fd()
Function that is called before the finite differencing of any internal data. This may be overloaded t...
unsigned Nexternal_data
Number of external data.
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...
unsigned ntstorage() const
Return the number of doubles required to represent history (one for steady)
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...
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...
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...
unsigned long nindex1() const
Return the range of index 1 of the derivatives of the shape functions.
const long & position_eqn_number(const unsigned &k, const unsigned &i) const
Return the equation number for generalised Eulerian coordinate: type of coordinate: k...
Data *& external_data_pt(const unsigned &i)
Return a pointer to i-th external data object.
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. NOTE: Moved to cc file because of a possible compiler bug in gcc (yes, really!). The move to the cc file avoids inlining which appears to cause problems (only) when compiled with gcc and -O3; offensive "illegal read" is in optimised-out section of code and data that is allegedly illegal is readily readable (by other means) just before this function is called so I can't really see how we could possibly be responsible for this...
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...
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...
std::string type() const
Return string that indicates the type of the timestepper (e.g. "BDF", "Newmark", etc.)
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 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...
double dot(const Vector< double > &a, const Vector< double > &b)
Probably not always best/fastest because not optimised for dimension but useful...
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. Note that this function should NOT initialise the residuals vector or the mass matrix. It must be called after the residuals vector and jacobian matrix have been initialised to zero. The default is deliberately broken.
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;...
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...
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
static long Is_unclassified
Static "Magic number" used in place of the equation number to denote a value that hasn't been classif...
FiniteElement *& bulk_element_pt()
Pointer to higher-dimensional "bulk" element.
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...
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...
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 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 ...
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 ...
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...
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...
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 ...
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...
CoordinateMappingFctPt & face_to_bulk_coordinate_fct_pt()
Return the pointer to the function that maps the face coordinate to the bulk coordinate.
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...
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. Lagrangian coordinates at local coordinate s; Returns Jacobian of mapping from Lagrangian to local coordinates. Numbering: 1D: d2pidxi(i,0) = 2D: d2psidxi(i,0) = d2psidxi(i,1) = d2psidxi(i,2) = 3D: d2psidxi(i,0) = d2psidxi(i,1) = d2psidxi(i,2) = d2psidxi(i,3) = d2psidxi(i,4) = d2psidxi(i,5) = .
void bulk_node_number_resize(const unsigned &i)
Resize the storage for the bulk node numbers.
double Newton_tolerance
Convergence tolerance for the newton solver.
unsigned & nbulk_value(const unsigned &n)
Return the number of values originally stored at local node n (before the FaceElement added additiona...
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.
virtual void describe_local_dofs(std::ostream &out, const std::string ¤t_string) const
Function to describe the local dofs of the element. The ostream specifies the output stream to which ...
virtual ~FiniteElement()
The destructor cleans up the static memory allocated for shape function storage. Internal and externa...
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. global coordinates at local coordinate s; Returns Jacobian of mapping from global to local coordinates. Numbering: 1D: d2psidx(i,0) = 2D: d2psidx(i,0) = d2psidx(i,1) = d2psidx(i,2) = 3D: d2psidx(i,0) = d2psidx(i,1) = d2psidx(i,2) = d2psidx(i,3) = d2psidx(i,4) = d2psidx(i,5) = .
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...
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...
virtual void update_before_external_fd()
Function that is called before the finite differencing of any external data. This may be overloaded t...
int local_eqn_number(const unsigned long &ieqn_global) const
Return the local equation number corresponding to the ieqn_global-th global equation number...
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...
unsigned nnode() const
Return the number of nodes.
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...
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
virtual double weight(const unsigned &i, const unsigned &j) const
Access function for j-th weight for the i-th derivative.
virtual void read_eqn_numbers_from_vector(const Vector< long > &vector_of_eqn_numbers, unsigned &index)
Read all equation numbers from the vector starting from index. On return the index will be set to the...
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...
int ** Data_local_eqn
Pointer to array storage for local equation numbers associated with internal and external data...
virtual void add_eqn_numbers_to_vector(Vector< long > &vector_of_eqn_numbers)
Add all equation numbers to the vector in the internal storage order.
static double Default_fd_jacobian_step
Double used for the default finite difference step in elemental jacobian calculations.
static bool Suppress_warning_about_repeated_internal_data
Static boolean to suppress warnings about repeated internal data. Defaults to false.
virtual double J_eulerian(const Vector< double > &s) const
Return the Jacobian of mapping from local to global coordinates at local position s...
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...
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...
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 ...
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...
static DenseMatrix< double > Dummy_matrix
Empty dense matrix used as a dummy argument to combined residual and jacobian functions in the case w...
unsigned Ninternal_data
Number of internal data.
void describe_local_dofs(std::ostream &out, const std::string ¤t_string) const
Function to describe the local dofs of the element. The ostream specifies the output stream to which ...
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...
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...
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 ...
virtual 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}.
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...
virtual void node_update()
Update the positions of all nodes in the element using each node update function. The default impleme...