This example solves a non-linear shell problem using the gsThinShellAssembler. The goals of the tutorial are the following:
- Solve a geometrically non-linear problem and export the solutions
For detailed information about the construction of gsThinShellAssembler and gsMaterialMatrixBase, please consult the tutorial Tutorial: Linear Kirchhoff-Love shell analysis.
Geometry and basis
For the non-linear problem, we consider the paraboloid geometry, stored in the file below. Like for the Tutorial: Linear Kirchhoff-Love shell analysis, the geometry is loaded using gsReadFile.
gsMultiPatch<> ori;
gsReadFile<>("surfaces/paraboloid.xml", ori);
ori.computeTopology();
The geometry and basis refinement are the same as for Tutorial: Linear Kirchhoff-Love shell analysis.
Boundary conditions and loads
For this problem, we fix all four corners of the paraboloid, hence the boundary conditions are defined as:
gsBoundaryConditions<> bc;
bc.setGeoMap(ori);
bc.addCornerValue(boundary::southwest, 0.0, 0, -1);
bc.addCornerValue(boundary::southeast, 0.0, 0, -1);
bc.addCornerValue(boundary::northwest, 0.0, 0, -1);
bc.addCornerValue(boundary::northeast, 0.0, 0, -1);
In addition, a point load is applied using the gsPointLoads class. This point load is defined using a parametric point, and a load in the physical space:
gsPointLoads<real_t> pLoads = gsPointLoads<real_t>();
gsVector<> point(2);
gsVector<> load (3);
point<< 0.5, 0.5 ; load << 0, 0.0, -1e4 ;
pLoads.addLoad(point, load, 0 );
gsFunctionExpr<> force("0","0","0",3);
Configuration of the assembler
The configuration of the material matrix and the shell assembler is the same as in Tutorial: Linear Kirchhoff-Love shell analysis. The only differences are that we now use a Neo-Hookean material (by passing another value to "Material"
):
gsConstantFunction<> E (1.E9,3);
gsConstantFunction<> nu(0.45,3);
gsConstantFunction<> t (1E-2,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",1);
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
And that the point loads need to be registered in the assembler, i.e.
gsThinShellAssembler<3, real_t, true > assembler(ori,bases,bc,force,materialMatrix);
assembler.setPointLoads(pLoads);
Jacobian and Residual
For the non-linear problem, we need the tangential stiffness matrix (i.e. the Jacobian) and the residual vector. Both operators depend on the deformed configuration, through the solution vector. A convenient way of defining these operators is through an std::function
, as is also done in the Structural Analysis Module module:
typedef std::function<bool (gsVector<real_t> const &, gsSparseMatrix<real_t>&)> Jacobian_t;
typedef std::function<bool (gsVector<real_t> const &, gsVector<real_t> &) > Residual_t;
Jacobian_t Jacobian = [&assembler](gsVector<real_t> const &x, gsSparseMatrix<real_t> & m)
{
gsMultiPatch<> def;
assembler.constructSolution(x,def);
m = assembler.matrix();
};
Residual_t Residual = [&assembler](gsVector<real_t> const &x, gsVector<real_t> & v)
{
gsMultiPatch<> def;
assembler.constructSolution(x,def);
v = assembler.rhs();
};
ThinShellAssemblerStatus
Definition gsThinShellAssembler.h:54
@ Success
Assembly is successful.
Inside the functions, it can be seen that the assembler first constructs a multi-patch object of the deformed configuration, based on the solution vector, and then it assembles the Jacobian and the residual vector by passing the deformation. The resulting operators are given as arguments, and the functions return true
if the assembly is succesful.
In principle, the gsThinShellAssembler always takes the geometric non-linearity into account when assembled with a deformed object as input. The same holds for the material non-linearity, since they are evaluated on the current deformation.
Solving the problem
To initialize the non-linear solve, a linear solve is performed first:
gsInfo<<
"Solving system with "<<assembler.numDofs()<<
" DoFs\n";
gsVector<> solVector;
gsSparseSolver<>::CGDiagonal solver;
solver.compute( matrix );
solVector = solver.solve(F);
#define gsInfo
Definition gsDebug.h:43
Afterwards, Newton-Raphson iterations are performed. The functions Residual
and Jacobian
are called inside GISMO_ENSURE macros, guarding succesful assembly. The iterative update is performed on the solution vector, which is converted inside the Jacobian
and Residual
to a multi-patch.
gsVector<> updateVector = solVector;
gsVector<> R;
GISMO_ENSURE(Residual(solVector,R),
"Assembly of the residual failed");
for (
index_t it = 0; it != 100; ++it)
{
GISMO_ENSURE(Jacobian(solVector,matrix),
"Assembly of the Jacobian failed");
solver.compute(matrix);
updateVector = solver.solve(R);
solVector += updateVector;
GISMO_ENSURE(Residual(solVector,R),
"Assembly of the residual failed");
<<", residue: "<< R.norm()/F.norm()
<<", update norm: "<<updateVector.norm()/solVector.norm()
<<"\n";
if (updateVector.norm() < 1e-6)
break;
else if (it+1 == it)
gsWarn<<
"Maximum iterations reached!\n";
}
#define index_t
Definition gsConfig.h:32
#define gsWarn
Definition gsDebug.h:50
#define GISMO_ENSURE(cond, message)
Definition gsDebug.h:102
Exporting the solution
Finally, exporting of the solution is similar to Tutorial: Linear Kirchhoff-Love shell analysis.
Annotated source file
Here is the full file nonlinear_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; }
if (numElevate!=0)
for (int r =0; r < numRefine; ++r)
point<< 0.5, 0.5 ; load << 0, 0.0, -1e4 ;
pLoads.addLoad(point, load, 0 );
std::vector<gsFunctionSet<>*> parameters{&E,&nu};
options.
addInt(
"Material",
"Material model: (0): SvK | (1): NH | (2): NH_ext | (3): MR | (4): Ogden",1);
options.
addInt(
"Implementation",
"Implementation: (0): Composites | (1): Analytical | (2): Generalized | (3): Spectral",1);
assembler.setPointLoads(pLoads);
{
assembler.constructSolution(x,def);
m = assembler.matrix();
};
{
assembler.constructSolution(x,def);
v = assembler.rhs();
};
assembler.assemble();
gsInfo<<
"Solving system with "<<assembler.numDofs()<<
" DoFs\n";
gsSparseSolver<>::CGDiagonal solver;
solver.compute( matrix );
solVector = solver.solve(F);
GISMO_ENSURE(Residual(solVector,R),
"Assembly of the residual failed");
for (
index_t it = 0; it != 100; ++it)
{
GISMO_ENSURE(Jacobian(solVector,matrix),
"Assembly of the Jacobian failed");
solver.compute(matrix);
updateVector = solver.solve(R);
solVector += updateVector;
GISMO_ENSURE(Residual(solVector,R),
"Assembly of the residual failed");
<<", residue: "<< R.norm()/F.norm()
<<", update norm: "<<updateVector.norm()/solVector.norm()
<<"\n";
if (updateVector.norm() < 1e-6)
break;
else if (it+1 == it)
gsWarn<<
"Maximum iterations reached!\n";
}
refPoint<<0.5,0.5;
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 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
bool computeTopology(T tol=1e-4, bool cornersOnly=false, bool tjunctions=false)
Attempt to compute interfaces and boundaries automatically.
Definition gsMultiPatch.hpp:377
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
Class containing a set of points on a multi-patch isogeometric domain, together with boundary conditi...
Definition gsPointLoads.h:65
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.
@ von_mises_membrane
compute only von Mises stress
Definition gsThinShellFunctions.h:42