G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
Tutorial: Linear Kirchhoff-Love shell analysis

This example solves a linear shell problem using the gsThinShellAssembler. The goals of the tutorial are the following:

Preliminaries

Like every example in G+Smo, we start our file with some includes. In this case, we include the gsThinShellAssembler.h file containing the assembler for the Kirchhoff-Love shell, and the getMaterialMatrix.h used for getting the material matrix.

#include <gsKLShell/gsKLShell.h>

The command line options for this file are relatively easy. One can control the number of mesh refinements and degree elevations, and specify a plot flag if needed.

bool plot = false;
index_t numRefine = 1;
index_t numElevate = 1;
gsCmdLine cmd("Linear shell tutorial.");
cmd.addInt( "e", "degreeElevation","Number of degree elevation steps to perform before solving (0: equalize degree in all directions)", numElevate );
cmd.addInt( "r", "uniformRefine", "Number of Uniform h-refinement steps to perform before solving", numRefine );
cmd.addSwitch("plot", "Create a ParaView visualization file with the solution", plot);
try { cmd.getValues(argc,argv); } catch (int rv) { return rv; }
#define index_t
Definition gsConfig.h:32

Geometry and basis

The problem at hand will be the Scordelis-Lo Roof problem from the shell obstactle course, see this paper. The geometry is stored in a file, hence it is read into the original geometry ori via gsReadFile.

// Initialize [ori]ginal and [def]ormed geometry
gsMultiPatch<> ori;
std::string fileName = "surfaces/scordelis_lo_roof.xml";
gsReadFile<>(fileName, ori);

For the analysis, we will use the geometry defined in the basis that we want for analysis. This is not essential, but it makes it easier to construct the geometry later using the gsThinShellAssembler class

// p-refine
if (numElevate!=0)
ori.degreeElevate(numElevate);
// h-refine
for (int r =0; r < numRefine; ++r)
ori.uniformRefine();

The basis is simply obtained using gsMultiBasis

gsMultiBasis<> bases(ori);

Boundary conditions and loads

The boundary conditions of the problem are assigned via gsBoundaryConditions. On the east and west boundary of the geometry, the \(y\) and \(z\) displacements are fixed, and to make the problem well-defined, the south-west corner is fixed in \(x\). The boundary conditions are defined by first specifying the side (boxSide), then the type of condition (condition_type), then the function (nullptr here), the unknown (always 0, since displacements are the only unknown field), whether the condition is applied in the parametric domain (always false) and finally the component of the solution field (-1 for all, 0 for \(x\), 1 for \(y\) and 2 for \(z\)):

// Define the boundary conditions object
gsBoundaryConditions<> bc;
// Set the geometry map for computation of the Dirichlet BCs
bc.setGeoMap(ori);
// Set the boundary conditions
bc.addCondition(boundary::west, condition_type::dirichlet, 0, 0 ,false, 1 );
bc.addCondition(boundary::west, condition_type::dirichlet, 0, 0 ,false, 2 );
bc.addCornerValue(boundary::southwest, 0.0, 0, 0); // (corner,value, patch, unknown)
bc.addCondition(boundary::east, condition_type::dirichlet, 0, 0 ,false, 1 );
bc.addCondition(boundary::east, condition_type::dirichlet, 0, 0 ,false, 2 );
@ dirichlet
Dirichlet type.
Definition gsBoundaryConditions.h:31

The surface load on the shell is provided by a gsFunctionSet, which in this case is a derived gsFunctionExpr.

// The surface force is defined in the physical space, i.e. 3D
gsFunctionExpr<> force("0","0","-90",3);

Material definition

The material law used in gsThinShellAssembler is specified using a separate class, derived from gsMaterialMatrixBase. The family of this class includes several material models, and can be evaluated in every point (including a thickness coordinate) using gsMaterialMatrixEval or it can be integrated using gsMaterialMatrixIntegrate. Depending on the options specified to the latter classes, different constitutive quantities can be obtaied, including the normal force and bending moment.

To define a meterial matrix, we can use the getMaterialMatrix function. This functions needs the undeformed geometry, the thickness, a set of parameters and some options:

// Define material parameters
// The material parameters are defined in the physical domain as well (!)
gsConstantFunction<> E (4.32E8,3);
gsConstantFunction<> nu(0.0 ,3);
gsConstantFunction<> t (0.25 ,3);
// Define a linear material, see \ref gsMaterialMatrixLinear.h
// The first parameter is the physical domain dimension
// gsMaterialMatrixLinear<3,real_t> materialMatrix(ori,t,E,nu);
std::vector<gsFunctionSet<>*> parameters{&E,&nu};
gsOptionList options;
options.addInt("Material","Material model: (0): SvK | (1): NH | (2): NH_ext | (3): MR | (4): Ogden",0);
options.addInt("Implementation","Implementation: (0): Composites | (1): Analytical | (2): Generalized | (3): Spectral",1);
gsMaterialMatrixBase<real_t>::uPtr materialMatrix = getMaterialMatrix<3,real_t>(ori,t,parameters,options);
memory::unique_ptr< gsMaterialMatrixBase > uPtr
Unique pointer for gsGeometry.
Definition gsMaterialMatrixBase.h:44

In case of "Material" 0, a gsMaterialMatrixLinear is provided, which only takes the Young's Modulus ( \(E\)) and the Poisson's ratio ( \(\nu\)). For the linear material matrix, thickness integration is simply done by multiplying with the thickness moments. For hyperelastic material models (see gsMaterialMatrixNonlinear), more parameters can be required, and through-thickness integration is done numerically. We refer to the page The gsMaterialMatrixBase for more details on material matrices.

Assembling and solving the linear problem

When the geometry, the basis, the boundary conditions and forces and the material are specified, the gsThinShellAssembler is simply constructed as follows:

// Define the assembler.
// The first parameter is the physical domain dimension
// The second parameter is the real type
// The third parameter controls the bending stiffness
gsThinShellAssembler<3, real_t, true > assembler(ori,bases,bc,force,materialMatrix);

Here, the first template parameter is the physical dimension, the second is the real type and the third is a boolean specifying whether bending stiffness contributions should be assembled.

Assemlbly of the linear stiffness matrix and external load vector is simply performed by calling

assembler.assemble();
gsSparseMatrix<> matrix = assembler.matrix();
gsVector<> vector = assembler.rhs();

Having the stiffness matrix and force vector assembled, the linear shell problem can be solved accordingly. This is done with a simple gsSparseSolver:

gsInfo<<"Solving system with "<<assembler.numDofs()<<" DoFs\n";
gsVector<> solVector;
gsSparseSolver<>::CGDiagonal solver;
solver.compute( matrix );
solVector = solver.solve(vector);
#define gsInfo
Definition gsDebug.h:43

Exporting the solution

Solving the linear problem gives the displacements of the control points of the geometry. To construct the displacement field, these control points form a solution field using the same basis as used for analysis. To construct the deformed geometry, their values need to be added to the control points of the original geometry. For ease of use, these functions are available in the gsThinShellAssembler:

gsMultiPatch<> displ = assembler.constructDisplacement(solVector);
gsMultiPatch<> def = assembler.constructSolution(solVector);

Using the displacement field and the deformed geometry, one can make some evaluations like with any other gsFunction, gsGeometry or gsMultiPatch, for example to print the displacements in a point:

// Evaluate the solution on a reference point (parametric coordinates)
// The reference points are stored column-wise
gsMatrix<> refPoint(2,1);
refPoint<<0.5,1;
// Compute the values
gsVector<> physpoint = def.patch(0).eval(refPoint);
gsVector<> refVals = displ.patch(0).eval(refPoint);
// gsInfo << "Displacement at reference point: "<<numVal<<"\n";
gsInfo << "Displacement at reference point ("
<<ori.patch(0).eval(refPoint).transpose()<<"): "
<<": "<<refVals.transpose()<<"\n";

In addition, the solutions can be exported to Paraview using gsField:

if (plot)
{
// Plot the displacements on the deformed geometry
gsField<> solField(def, displ);
gsInfo<<"Plotting in Paraview...\n";
gsWriteParaview<>( solField, "Deformation", 1000, true);
// Plot the membrane Von-Mises stresses on the geometry
gsPiecewiseFunction<> VMm;
assembler.constructStress(def,VMm,stress_type::von_mises_membrane);
gsField<> membraneStress(def,VMm, true);
gsWriteParaview(membraneStress,"MembraneStress",1000);
}
@ von_mises_membrane
compute only von Mises stress
Definition gsThinShellFunctions.h:42

Annotated source file

Here is the full file linear_shell.cpp. Clicking on a function or class name will lead you to its reference documentation.

#include <gismo.h>
#include <gsKLShell/gsKLShell.h>
using namespace gismo;
int main(int argc, char *argv[])
{
bool plot = false;
index_t numRefine = 1;
index_t numElevate = 1;
gsCmdLine cmd("Linear shell tutorial.");
cmd.addInt( "e", "degreeElevation","Number of degree elevation steps to perform before solving (0: equalize degree in all directions)", numElevate );
cmd.addInt( "r", "uniformRefine", "Number of Uniform h-refinement steps to perform before solving", numRefine );
cmd.addSwitch("plot", "Create a ParaView visualization file with the solution", plot);
try { cmd.getValues(argc,argv); } catch (int rv) { return rv; }
// Initialize [ori]ginal and [def]ormed geometry
std::string fileName = "surfaces/scordelis_lo_roof.xml";
gsReadFile<>(fileName, ori);
// p-refine
if (numElevate!=0)
ori.degreeElevate(numElevate);
// h-refine
for (int r =0; r < numRefine; ++r)
gsMultiBasis<> bases(ori);
// Define the boundary conditions object
// Set the geometry map for computation of the Dirichlet BCs
bc.setGeoMap(ori);
// Set the boundary conditions
bc.addCondition(boundary::west, condition_type::dirichlet, 0, 0 ,false, 1 );
bc.addCondition(boundary::west, condition_type::dirichlet, 0, 0 ,false, 2 );
bc.addCornerValue(boundary::southwest, 0.0, 0, 0); // (corner,value, patch, unknown)
bc.addCondition(boundary::east, condition_type::dirichlet, 0, 0 ,false, 1 );
bc.addCondition(boundary::east, condition_type::dirichlet, 0, 0 ,false, 2 );
// The surface force is defined in the physical space, i.e. 3D
gsFunctionExpr<> force("0","0","-90",3);
// Define material parameters
// The material parameters are defined in the physical domain as well (!)
gsConstantFunction<> E (4.32E8,3);
gsConstantFunction<> t (0.25 ,3);
// Define a linear material, see \ref gsMaterialMatrixLinear.h
// The first parameter is the physical domain dimension
// gsMaterialMatrixLinear<3,real_t> materialMatrix(ori,t,E,nu);
std::vector<gsFunctionSet<>*> parameters{&E,&nu};
gsOptionList options;
options.addInt("Material","Material model: (0): SvK | (1): NH | (2): NH_ext | (3): MR | (4): Ogden",0);
options.addInt("Implementation","Implementation: (0): Composites | (1): Analytical | (2): Generalized | (3): Spectral",1);
gsMaterialMatrixBase<real_t>::uPtr materialMatrix = getMaterialMatrix<3,real_t>(ori,t,parameters,options);
// Define the assembler.
// The first parameter is the physical domain dimension
// The second parameter is the real type
// The third parameter controls the bending stiffness
gsThinShellAssembler<3, real_t, true > assembler(ori,bases,bc,force,materialMatrix);
assembler.assemble();
gsSparseMatrix<> matrix = assembler.matrix();
gsVector<> vector = assembler.rhs();
gsInfo<<"Solving system with "<<assembler.numDofs()<<" DoFs\n";
gsVector<> solVector;
gsSparseSolver<>::CGDiagonal solver;
solver.compute( matrix );
solVector = solver.solve(vector);
gsMultiPatch<> displ = assembler.constructDisplacement(solVector);
gsMultiPatch<> def = assembler.constructSolution(solVector);
// Evaluate the solution on a reference point (parametric coordinates)
// The reference points are stored column-wise
gsMatrix<> refPoint(2,1);
refPoint<<0.5,1;
// Compute the values
gsVector<> physpoint = def.patch(0).eval(refPoint);
gsVector<> refVals = displ.patch(0).eval(refPoint);
// gsInfo << "Displacement at reference point: "<<numVal<<"\n";
gsInfo << "Displacement at reference point ("
<<ori.patch(0).eval(refPoint).transpose()<<"): "
<<": "<<refVals.transpose()<<"\n";
// ! [Export visualization in ParaView]
if (plot)
{
// Plot the displacements on the deformed geometry
gsField<> solField(def, displ);
gsInfo<<"Plotting in Paraview...\n";
gsWriteParaview<>( solField, "Deformation", 1000, true);
// Plot the membrane Von-Mises stresses on the geometry
assembler.constructStress(def,VMm,stress_type::von_mises_membrane);
gsField<> membraneStress(def,VMm, true);
gsWriteParaview(membraneStress,"MembraneStress",1000);
}
// ! [Export visualization in ParaView]
return EXIT_SUCCESS;
}// end main
Class containing a set of boundary conditions.
Definition gsBoundaryConditions.h:342
void addCondition(int p, boxSide s, condition_type::type t, gsFunctionSet< T > *f, short_t unknown=0, bool parametric=false, int comp=-1)
Adds another boundary condition.
Definition gsBoundaryConditions.h:650
void addCornerValue(boxCorner c, T value, int p=0, short_t unknown=0, int component=-1)
Adds a boundary condition with value on a corner c of patch p for unknown component.
Definition gsBoundaryConditions.h:726
void setGeoMap(const gsFunctionSet< T > &gm)
Set the geometry map to evaluate boundary conditions.
Definition gsBoundaryConditions.h:916
Class for command-line argument parsing.
Definition gsCmdLine.h:57
Class defining a globally constant function.
Definition gsConstantFunction.h:34
A scalar of vector field defined on a m_parametric geometry.
Definition gsField.h:55
Class defining a multivariate (real or vector) function given by a string mathematical expression.
Definition gsFunctionExpr.h:52
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
Holds a set of patch-wise bases and their topology information.
Definition gsMultiBasis.h:37
Container class for a set of geometry patches and their topology, that is, the interface connections ...
Definition gsMultiPatch.h:100
void degreeElevate(short_t const elevationSteps=1, short_t const dir=-1)
Elevate the degree of all patches by elevationSteps, preserves smoothness.
Definition gsMultiPatch.hpp:282
gsGeometry< T > & patch(size_t i) const
Return the i-th patch.
Definition gsMultiPatch.h:292
void uniformRefine(int numKnots=1, int mul=1, short_t const dir=-1)
Refine uniformly all patches by inserting numKnots in each knot-span with multipliplicity mul.
Definition gsMultiPatch.hpp:271
Class which holds a list of parameters/options, and provides easy access to them.
Definition gsOptionList.h:33
void addInt(const std::string &label, const std::string &desc, const index_t &value)
Adds a option named label, with description desc and value value.
Definition gsOptionList.cpp:201
A function depending on an index i, typically referring to a patch/sub-domain. On each patch a differ...
Definition gsPiecewiseFunction.h:29
Reads an object from a data file, if such the requested object exists in the file.
Definition gsReadFile.h:43
Sparse matrix class, based on gsEigen::SparseMatrix.
Definition gsSparseMatrix.h:139
Assembles the system matrix and vectors for 2D and 3D shell problems, including geometric nonlinearit...
Definition gsThinShellAssembler.h:77
A vector with arbitrary coefficient type and fixed or dynamic size.
Definition gsVector.h:37
Main header to be included by clients using the G+Smo library.
The G+Smo namespace, containing all definitions for the library.