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;
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.
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
if (numElevate!=0)
ori.degreeElevate(numElevate);
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\)):
gsBoundaryConditions<> bc;
bc.setGeoMap(ori);
bc.addCornerValue(boundary::southwest, 0.0, 0, 0);
@ 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.
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:
gsConstantFunction<> E (4.32E8,3);
gsConstantFunction<> nu(0.0 ,3);
gsConstantFunction<> t (0.25 ,3);
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);
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:
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:
gsMatrix<> refPoint(2,1);
refPoint<<0.5,1;
gsVector<> physpoint = def.patch(0).eval(refPoint);
gsVector<> refVals = displ.patch(0).eval(refPoint);
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)
{
gsField<> solField(def, displ);
gsInfo<<
"Plotting in Paraview...\n";
gsWriteParaview<>( solField, "Deformation", 1000, true);
gsPiecewiseFunction<> VMm;
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 <gsKLShell/gsKLShell.h>
int main(int argc, char *argv[])
{
bool plot = false;
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; }
std::string fileName = "surfaces/scordelis_lo_roof.xml";
if (numElevate!=0)
for (int r =0; r < numRefine; ++r)
std::vector<gsFunctionSet<>*> parameters{&E,&nu};
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);
assembler.assemble();
gsInfo<<
"Solving system with "<<assembler.numDofs()<<
" DoFs\n";
gsSparseSolver<>::CGDiagonal solver;
solver.compute( matrix );
solVector = solver.solve(vector);
refPoint<<0.5,1;
gsInfo <<
"Displacement at reference point ("
<<ori.
patch(0).eval(refPoint).transpose()<<
"): "
<<": "<<refVals.transpose()<<"\n";
if (plot)
{
gsInfo<<
"Plotting in Paraview...\n";
gsWriteParaview<>( solField, "Deformation", 1000, true);
gsWriteParaview(membraneStress,"MembraneStress",1000);
}
return EXIT_SUCCESS;
}
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.