In this document, we discuss the solution of the buckling of a cylindrical shell using oomph-lib's
KirchhoffLoveShell elements.
#include <iostream>
#include <fstream>
#include <cmath>
#include <typeinfo>
#include <algorithm>
#include <cstdio>
#include "generic.h"
#include "shell.h"
#include "meshes/rectangular_quadmesh.h"
using namespace std;
using namespace oomph;
{
const Vector<double> &x,
const Vector<double> &N,
Vector<double>& load)
{
for(unsigned i=0;i<3;i++)
{
Pcos*pow(0.05,3)/12.0*cos(2.0*xi[1]))*N[i];
}
}
}
template <class ELEMENT>
class ShellMesh :
public virtual RectangularQuadMesh<ELEMENT>,
public virtual SolidMesh
{
public:
ShellMesh(
const unsigned &nx,
const unsigned &ny,
const double &lx, const double &ly);
void assign_undeformed_positions(GeomObject* const &undeformed_midplane_pt);
};
template <class ELEMENT>
const unsigned &ny,
const double &lx,
const double &ly) :
RectangularQuadMesh<ELEMENT>(nx,ny,lx,ly)
{
unsigned n_node = nnode();
for(unsigned i=0;i<n_node;i++)
{
node_pt(i)->xi(0) = node_pt(i)->x(0);
node_pt(i)->xi(1) = node_pt(i)->x(1);
}
unsigned n_position_type = finite_element_pt(0)->nnodal_position_type();
if(n_position_type > 1)
{
double xstep = (this->Xmax - this->Xmin)/((this->Np-1)*this->Nx);
double ystep = (this->Ymax - this->Ymin)/((this->Np-1)*this->Ny);
for(unsigned n=0;n<n_node;n++)
{
node_pt(n)->xi_gen(1,0) = 0.5*xstep;
node_pt(n)->xi_gen(2,1) = 0.5*ystep;
}
}
}
template <class ELEMENT>
GeomObject* const &undeformed_midplane_pt)
{
unsigned n_node = nnode();
for(unsigned n=0;n<n_node;n++)
{
Vector<double> xi(2);
xi[0] = node_pt(n)->xi(0);
xi[1] = node_pt(n)->xi(1);
Vector<double> R(3);
DenseMatrix<double> a(2,3);
RankThreeTensor<double> dadxi(2,2,3);
undeformed_midplane_pt->d2position(xi,R,a,dadxi);
for(unsigned i=0;i<3;i++)
{
node_pt(n)->x_gen(0,i) = R[i];
node_pt(n)->x_gen(1,i) = 0.5*a(0,i)*((this->Xmax - this->Xmin)/this->Nx);
node_pt(n)->x_gen(2,i) = 0.5*a(1,i)*((this->Ymax - this->Ymin)/this->Ny);
node_pt(n)->x_gen(3,i) = 0.25*dadxi(0,1,i);
}
}
}
template<class ELEMENT>
{
public:
const double &lx, const double &ly);
private:
};
template<class ELEMENT>
const double &lx, const double &ly)
{
Undeformed_midplane_pt = new EllipticalTube(1.0,1.0);
mesh_pt()->assign_undeformed_positions(Undeformed_midplane_pt);
mesh_pt()->element_reorder();
unsigned n_ends = mesh_pt()->nboundary_node(1);
for(unsigned i=0;i<n_ends;i++)
{
mesh_pt()->boundary_node_pt(1,i)->pin_position(2);
mesh_pt()->boundary_node_pt(3,i)->pin_position(2);
mesh_pt()->boundary_node_pt(1,i)->pin_position(2,2);
mesh_pt()->boundary_node_pt(3,i)->pin_position(2,2);
mesh_pt()->boundary_node_pt(1,i)->pin_position(0);
mesh_pt()->boundary_node_pt(3,i)->pin_position(0);
mesh_pt()->boundary_node_pt(1,i)->pin_position(2,0);
mesh_pt()->boundary_node_pt(3,i)->pin_position(2,0);
mesh_pt()->boundary_node_pt(1,i)->pin_position(1);
mesh_pt()->boundary_node_pt(3,i)->pin_position(1);
mesh_pt()->boundary_node_pt(1,i)->pin_position(2,1);
mesh_pt()->boundary_node_pt(3,i)->pin_position(2,1);
mesh_pt()->boundary_node_pt(1,i)->pin_position(1,0);
mesh_pt()->boundary_node_pt(1,i)->pin_position(1,1);
mesh_pt()->boundary_node_pt(3,i)->pin_position(1,0);
mesh_pt()->boundary_node_pt(3,i)->pin_position(1,1);
mesh_pt()->boundary_node_pt(1,i)->pin_position(3,0);
mesh_pt()->boundary_node_pt(1,i)->pin_position(3,1);
mesh_pt()->boundary_node_pt(3,i)->pin_position(3,0);
mesh_pt()->boundary_node_pt(3,i)->pin_position(3,1);
}
unsigned n_side = mesh_pt()->nboundary_node(0);
for(unsigned i=0;i<n_side;i++)
{
mesh_pt()->boundary_node_pt(0,i)->pin_position(1);
mesh_pt()->boundary_node_pt(0,i)->pin_position(1,1);
mesh_pt()->boundary_node_pt(0,i)->pin_position(2,0);
mesh_pt()->boundary_node_pt(0,i)->pin_position(2,2);
mesh_pt()->boundary_node_pt(0,i)->pin_position(3,0);
mesh_pt()->boundary_node_pt(0,i)->pin_position(3,2);
mesh_pt()->boundary_node_pt(2,i)->pin_position(0);
mesh_pt()->boundary_node_pt(2,i)->pin_position(1,0);
mesh_pt()->boundary_node_pt(2,i)->pin_position(2,1);
mesh_pt()->boundary_node_pt(2,i)->pin_position(2,2);
mesh_pt()->boundary_node_pt(2,i)->pin_position(3,1);
mesh_pt()->boundary_node_pt(2,i)->pin_position(3,2);
}
unsigned nel_ctrl=0;
Vector<double> s_displ_control(2);
if (nx%2==1)
{
nel_ctrl=unsigned(floor(0.5*double(nx))+1.0)*ny-1;
s_displ_control[0]=0.0;
s_displ_control[1]=1.0;
}
else
{
nel_ctrl=unsigned(floor(0.5*double(nx))+1.0)*ny-1;
s_displ_control[0]=-1.0;
s_displ_control[1]=1.0;
}
SolidFiniteElement* controlled_element_pt=
dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(nel_ctrl));
unsigned controlled_direction=1;
DisplacementControlElement* displ_control_el_pt;
displ_control_el_pt=
new DisplacementControlElement(controlled_element_pt,
s_displ_control,
controlled_direction,
Vector<double> xi(2);
Vector<double> x(3);
controlled_element_pt->interpolated_xi(s_displ_control,xi);
controlled_element_pt->interpolated_x(s_displ_control,x);
std::cout << std::endl;
std::cout << "Controlled element: " << nel_ctrl << std::endl;
std::cout << "Displacement control applied at xi = ("
<< xi[0] << ", " << xi[1] << ")" << std::endl;
std::cout << "Corresponding to x = ("
<< x[0] << ", " << x[1] << ", " << x[2] << ")" << std::endl;
displacement_control_load_pt();
mesh_pt()->add_element_pt(displ_control_el_pt);
unsigned n_element = nx*ny;
ELEMENT* first_el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(0));
for(unsigned e=0;e<n_element;e++)
{
ELEMENT *el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(e));
el_pt->undeformed_midplane_pt() = Undeformed_midplane_pt;
if(e==0)
{
el_pt->pre_compute_d2shape_lagrangian_at_knots();
}
else
{
el_pt->set_dshape_lagrangian_stored_from_element(first_el_pt);
}
}
Trace_node_pt = mesh_pt()->finite_element_pt(2*ny-1)->node_pt(3);
Trace_node2_pt = mesh_pt()->finite_element_pt(ny)->node_pt(1);
cout << std::endl;
cout << "# of dofs " << assign_eqn_numbers() << std::endl;
cout << std::endl;
}
template<class ELEMENT>
{
Max_newton_iterations = 40;
Max_residuals=1.0e6;
ofstream trace("trace.dat");
for(unsigned i=1;i<11;i++)
{
cout << std::endl << "Increasing displacement: Prescribed_y is "
newton_solve();
<< " "
<< Trace_node_pt->x(0) << " " << Trace_node_pt->x(1) << " "
<< Trace_node2_pt->x(0) << " " << Trace_node2_pt->x(1) << std::endl;
}
trace.close();
ofstream file("final_shape.dat");
mesh_pt()->output(file,5);
file.close();
}
{
double L = 10.0;
double L_phi=0.5*MathematicalConstants::Pi;
problem(5,3,L,L_phi);
problem.solve();
}
A 2D Mesh class. The tube wall is represented by two Lagrangian coordinates that correspond to z and ...
void assign_undeformed_positions(GeomObject *const &undeformed_midplane_pt)
In all elastic problems, the nodes must be assigned an undeformed, or reference, position,...
ShellMesh(const unsigned &nx, const unsigned &ny, const double &lx, const double &ly)
Constructor for the mesh.
ShellMesh< ELEMENT > * mesh_pt()
Overload Access function for the mesh.
Node * Trace_node2_pt
Second trace node.
GeomObject * Undeformed_midplane_pt
Pointer to GeomObject that specifies the undeformed midplane.
ShellProblem(const unsigned &nx, const unsigned &ny, const double &lx, const double &ly)
Constructor.
void actions_before_newton_solve()
Actions before solve empty.
Node * Trace_node_pt
First trace node.
void actions_after_newton_solve()
Actions after solve empty.
Global variables that represent physical properties.
double external_pressure()
Return a reference to the external pressure load on the elastic tube.
void press_load(const Vector< double > &xi, const Vector< double > &x, const Vector< double > &N, Vector< double > &load)
Load function, normal pressure loading.
double Prescribed_y
Prescribed position of control point.
double Pcos
Perturbation pressure.
Data * Pext_data_pt
Pointer to pressure load (stored in Data so it can become an unknown in the problem when displacement...