action functions
|
Please note that the library has not been "officially" released. While we continue to work on the documentation, these web pages are likely to contain broken links and documents in draft form. Please send an email to if you wish to be informed of the library's "official" release. |
00001 //LIC// ==================================================================== 00002 //LIC// This file forms part of oomph-lib, the object-oriented, 00003 //LIC// multi-physics finite-element library, available 00004 //LIC// at http://www.oomph-lib.org. 00005 //LIC// 00006 //LIC// Version 0.90. August 3, 2009. 00007 //LIC// 00008 //LIC// Copyright (C) 2006-2009 Matthias Heil and Andrew Hazel 00009 //LIC// 00010 //LIC// This library is free software; you can redistribute it and/or 00011 //LIC// modify it under the terms of the GNU Lesser General Public 00012 //LIC// License as published by the Free Software Foundation; either 00013 //LIC// version 2.1 of the License, or (at your option) any later version. 00014 //LIC// 00015 //LIC// This library is distributed in the hope that it will be useful, 00016 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 //LIC// Lesser General Public License for more details. 00019 //LIC// 00020 //LIC// You should have received a copy of the GNU Lesser General Public 00021 //LIC// License along with this library; if not, write to the Free Software 00022 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00023 //LIC// 02110-1301 USA. 00024 //LIC// 00025 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk. 00026 //LIC// 00027 //LIC//==================================================================== 00028 //Header file for elements that are used to apply surface loads to 00029 //the equations of elasticity 00030 00031 #ifndef OOMPH_LINEAR_ELASTICITY_TRACTION_ELEMENTS_HEADER 00032 #define OOMPH_LINEAR_ELASTICITY_TRACTION_ELEMENTS_HEADER 00033 00034 // Config header generated by autoconfig 00035 #ifdef HAVE_CONFIG_H 00036 #include <oomph-lib-config.h> 00037 #endif 00038 00039 00040 //OOMPH-LIB headers 00041 #include "../generic/Qelements.h" 00042 00043 namespace oomph 00044 { 00045 00046 00047 00048 //======================================================================= 00049 /// Namespace containing the zero traction function for solid traction 00050 /// elements 00051 //======================================================================= 00052 namespace LinearElasticityTractionElementHelper 00053 { 00054 00055 //======================================================================= 00056 /// Default load function (zero traction) 00057 //======================================================================= 00058 void Zero_traction_fct(const Vector<double> &x, 00059 const Vector<double>& N, 00060 Vector<double>& load) 00061 { 00062 unsigned n_dim=load.size(); 00063 for (unsigned i=0;i<n_dim;i++) {load[i]=0.0;} 00064 } 00065 00066 } 00067 00068 00069 //====================================================================== 00070 /// A class for elements that allow the imposition of an applied traction 00071 /// in the principle of virtual displacements. 00072 /// The geometrical information can be read from the FaceGeometry<ELEMENT> 00073 /// class and and thus, we can be generic enough without the need to have 00074 /// a separate equations class. 00075 //====================================================================== 00076 template <class ELEMENT> 00077 class LinearElasticityTractionElement : public virtual FaceGeometry<ELEMENT>, 00078 public virtual FaceElement 00079 { 00080 protected: 00081 00082 /// Index at which the i-th velocity component is stored 00083 Vector<unsigned> U_index_linear_elasticity_traction; 00084 00085 /// \short Pointer to an imposed traction function. Arguments: 00086 /// Lagrangian coordinate; Eulerian coordinate; outer unit normal; 00087 /// applied traction. (Not all of the input arguments will be 00088 /// required for all specific load functions but the list should 00089 /// cover all cases) 00090 void (*Traction_fct_pt)(const Vector<double> &x, 00091 const Vector<double> &n, 00092 Vector<double> &result); 00093 00094 00095 /// \short Get the traction vector: Pass number of integration point (dummy), 00096 /// Lagr. coordinate and normal vector and return the load vector 00097 /// (not all of the input arguments will be 00098 /// required for all specific load functions but the list should 00099 /// cover all cases). This function is virtual so it can be 00100 /// overloaded for FSI. 00101 virtual void get_traction(const unsigned& intpt, 00102 const Vector<double>& x, 00103 const Vector<double>& n, 00104 Vector<double>& traction) 00105 { 00106 Traction_fct_pt(x,n,traction); 00107 } 00108 00109 00110 /// \short Helper function that actually calculates the residuals 00111 // This small level of indirection is required to avoid calling 00112 // fill_in_contribution_to_residuals in fill_in_contribution_to_jacobian 00113 // which causes all kinds of pain if overloading later on 00114 void fill_in_contribution_to_residuals_linear_elasticity_traction( 00115 Vector<double> &residuals); 00116 00117 00118 public: 00119 00120 /// \short Constructor, which takes a "bulk" element and the 00121 /// value of the index and its limit 00122 LinearElasticityTractionElement(FiniteElement* const &element_pt, 00123 const int &face_index) : 00124 FaceGeometry<ELEMENT>(), FaceElement() 00125 { 00126 #ifdef PARANOID 00127 { 00128 //Check that the element is not a refineable 3d element 00129 ELEMENT* elem_pt = new ELEMENT; 00130 //If it's three-d 00131 if(elem_pt->dim()==3) 00132 { 00133 //Is it refineable 00134 if(dynamic_cast<RefineableElement*>(elem_pt)) 00135 { 00136 //Issue a warning 00137 OomphLibWarning( 00138 "This flux element will not work correctly if nodes are hanging\n", 00139 "LinearElasticityTractionElement::Constructor", 00140 OOMPH_EXCEPTION_LOCATION); 00141 } 00142 } 00143 } 00144 #endif 00145 00146 //Attach the geometrical information to the element. N.B. This function 00147 //also assigns nbulk_value from the required_nvalue of the bulk element 00148 element_pt->build_face_element(face_index,this); 00149 00150 //Find the dimension of the problem 00151 unsigned n_dim = element_pt->nodal_dimension(); 00152 00153 //Find the index at which the displacmenet unknowns are stored 00154 ELEMENT* cast_element_pt = dynamic_cast<ELEMENT*>(element_pt); 00155 this->U_index_linear_elasticity_traction.resize(n_dim); 00156 for(unsigned i=0;i<n_dim;i++) 00157 { 00158 this->U_index_linear_elasticity_traction[i] = 00159 cast_element_pt->u_index_linear_elasticity(i); 00160 } 00161 00162 // Zero traction 00163 Traction_fct_pt=&LinearElasticityTractionElementHelper::Zero_traction_fct; 00164 } 00165 00166 00167 /// Reference to the traction function pointer 00168 void (* &traction_fct_pt())(const Vector<double>& x, 00169 const Vector<double>& n, 00170 Vector<double>& traction) 00171 {return Traction_fct_pt;} 00172 00173 00174 /// Return the residuals 00175 void fill_in_contribution_to_residuals(Vector<double> &residuals) 00176 { 00177 fill_in_contribution_to_residuals_linear_elasticity_traction(residuals); 00178 } 00179 00180 00181 00182 /// Fill in contribution from Jacobian 00183 void fill_in_contribution_to_jacobian(Vector<double> &residuals, 00184 DenseMatrix<double> &jacobian) 00185 { 00186 //Call the residuals 00187 fill_in_contribution_to_residuals_linear_elasticity_traction(residuals); 00188 //Call the generic FD jacobian calculation 00189 //FaceGeometry<ELEMENT>::fill_in_jacobian_from_solid_position_by_fd(jacobian); 00190 } 00191 00192 /// \short Output function 00193 void output(std::ostream &outfile) 00194 {FiniteElement::output(outfile);} 00195 00196 /// \short Output function 00197 void output(std::ostream &outfile, const unsigned &n_plot) 00198 {FiniteElement::output(outfile,n_plot);} 00199 00200 /// \short C_style output function 00201 void output(FILE* file_pt) 00202 {FiniteElement::output(file_pt);} 00203 00204 /// \short C-style output function 00205 void output(FILE* file_pt, const unsigned &n_plot) 00206 {FiniteElement::output(file_pt,n_plot);} 00207 00208 00209 /// \short Compute traction vector at specified local coordinate 00210 /// Should only be used for post-processing; ignores dependence 00211 /// on integration point! 00212 void traction(const Vector<double>& s, 00213 Vector<double>& traction); 00214 00215 }; 00216 00217 /////////////////////////////////////////////////////////////////////// 00218 /////////////////////////////////////////////////////////////////////// 00219 /////////////////////////////////////////////////////////////////////// 00220 00221 //===================================================================== 00222 /// Compute traction vector at specified local coordinate 00223 /// Should only be used for post-processing; ignores dependence 00224 /// on integration point! 00225 //===================================================================== 00226 template<class ELEMENT> 00227 void LinearElasticityTractionElement<ELEMENT>::traction(const Vector<double>& s, 00228 Vector<double>& traction) 00229 { 00230 unsigned n_dim = this->nodal_dimension(); 00231 00232 // Position vector 00233 Vector<double> x(n_dim); 00234 interpolated_x(s,x); 00235 00236 // Outer unit normal 00237 Vector<double> unit_normal(n_dim); 00238 outer_unit_normal(s,unit_normal); 00239 00240 // Dummy 00241 unsigned ipt=0; 00242 00243 // Traction vector 00244 get_traction(ipt,x,unit_normal,traction); 00245 00246 } 00247 00248 00249 //===================================================================== 00250 /// Return the residuals for the LinearElasticityTractionElement equations 00251 //===================================================================== 00252 template<class ELEMENT> 00253 void LinearElasticityTractionElement<ELEMENT>:: 00254 fill_in_contribution_to_residuals_linear_elasticity_traction( 00255 Vector<double> &residuals) 00256 { 00257 //Find out how many nodes there are 00258 unsigned n_node = nnode(); 00259 00260 //Find out how many positional dofs there are 00261 unsigned n_position_type = this->nnodal_position_type(); 00262 00263 00264 if(n_position_type != 1) 00265 { 00266 throw OomphLibError( 00267 "LinearElasticity is not yet implemented for more than one position type", 00268 "LinearElasticityEquationsBase<DIM>::get_strain()", 00269 OOMPH_EXCEPTION_LOCATION); 00270 } 00271 00272 00273 //Find out the dimension of the node 00274 unsigned n_dim = this->nodal_dimension(); 00275 00276 //Cache the nodal indices at which the displacement components are stored 00277 unsigned u_nodal_index[n_dim]; 00278 for(unsigned i=0;i<n_dim;i++) 00279 { 00280 u_nodal_index[i] = this->U_index_linear_elasticity_traction[i]; 00281 } 00282 00283 //Integer to hold the local equation number 00284 int local_eqn=0; 00285 00286 //Set up memory for the shape functions 00287 //Note that in this case, the number of lagrangian coordinates is always 00288 //equal to the dimension of the nodes 00289 Shape psi(n_node); 00290 DShape dpsids(n_node,n_dim-1); 00291 00292 //Set the value of n_intpt 00293 unsigned n_intpt = integral_pt()->nweight(); 00294 00295 //Loop over the integration points 00296 for(unsigned ipt=0;ipt<n_intpt;ipt++) 00297 { 00298 //Get the integral weight 00299 double w = integral_pt()->weight(ipt); 00300 00301 //Only need to call the local derivatives 00302 dshape_local_at_knot(ipt,psi,dpsids); 00303 00304 //Calculate the Eulerian and Lagrangian coordinates 00305 Vector<double> interpolated_x(n_dim,0.0); 00306 00307 //Also calculate the surface Vectors (derivatives wrt local coordinates) 00308 DenseMatrix<double> interpolated_A(n_dim-1,n_dim,0.0); 00309 00310 //Calculate displacements and derivatives 00311 for(unsigned l=0;l<n_node;l++) 00312 { 00313 //Loop over positional dofs 00314 for(unsigned k=0;k<n_position_type;k++) 00315 { 00316 //Loop over displacement components (deformed position) 00317 for(unsigned i=0;i<n_dim;i++) 00318 { 00319 const double x_local = nodal_position(l,i); 00320 //Calculate the Eulerian and Lagrangian positions 00321 interpolated_x[i] += x_local*psi(l,k); 00322 00323 //Loop over LOCAL derivative directions, to calculate the tangent(s) 00324 for(unsigned j=0;j<n_dim-1;j++) 00325 { 00326 interpolated_A(j,i) += x_local*dpsids(l,j); 00327 } 00328 } 00329 } 00330 } 00331 00332 //Now find the local metric tensor from the tangent Vectors 00333 DenseMatrix<double> A(n_dim-1); 00334 for(unsigned i=0;i<n_dim-1;i++) 00335 { 00336 for(unsigned j=0;j<n_dim-1;j++) 00337 { 00338 //Initialise surface metric tensor to zero 00339 A(i,j) = 0.0; 00340 //Take the dot product 00341 for(unsigned k=0;k<n_dim;k++) 00342 { 00343 A(i,j) += interpolated_A(i,k)*interpolated_A(j,k); 00344 } 00345 } 00346 } 00347 00348 //Get the outer unit normal 00349 Vector<double> interpolated_normal(n_dim); 00350 outer_unit_normal(ipt,interpolated_normal); 00351 00352 //Find the determinant of the metric tensor 00353 double Adet =0.0; 00354 switch(n_dim) 00355 { 00356 case 2: 00357 Adet = A(0,0); 00358 break; 00359 case 3: 00360 Adet = A(0,0)*A(1,1) - A(0,1)*A(1,0); 00361 break; 00362 default: 00363 throw 00364 OomphLibError("Wrong dimension in LinearElasticityTractionElement", 00365 "LinearElasticityTractionElement::fill_in_contribution_to_residuals()", 00366 OOMPH_EXCEPTION_LOCATION); 00367 } 00368 00369 //Premultiply the weights and the square-root of the determinant of 00370 //the metric tensor 00371 double W = w*sqrt(Adet); 00372 00373 //Now calculate the load 00374 Vector<double> traction(n_dim); 00375 get_traction(ipt, 00376 interpolated_x, 00377 interpolated_normal, 00378 traction); 00379 00380 //=====LOAD TERMS FROM PRINCIPLE OF VIRTUAL DISPLACEMENTS======== 00381 00382 //Loop over the test functions, nodes of the element 00383 for(unsigned l=0;l<n_node;l++) 00384 { 00385 //Loop over the displacement components 00386 for(unsigned i=0;i<n_dim;i++) 00387 { 00388 local_eqn = this->nodal_local_eqn(l,u_nodal_index[i]); 00389 /*IF it's not a boundary condition*/ 00390 if(local_eqn >= 0) 00391 { 00392 //Add the loading terms to the residuals 00393 residuals[local_eqn] -= traction[i]*psi(l)*W; 00394 } 00395 } //End of if not boundary condition 00396 } //End of loop over shape functions 00397 } //End of loop over integration points 00398 00399 } 00400 00401 00402 00403 00404 00405 } 00406 00407 #endif
1.4.7