NuTo
Numerics Tool
ElementUniaxialTest.h
Go to the documentation of this file.
1 /*
2  * ElementUniaxialTest.h
3  *
4  * Created on: 13 May 2015
5  * Author: ttitsche
6  */
7 
8 #pragma once
9 #include "BoostUnitTest.h"
10 
11 #include <iomanip>
12 #include <boost/filesystem.hpp>
13 
14 #include "nuto/mechanics/MechanicsEnums.h"
16 
17 #include "nuto/math/SparseMatrixCSRVector2.h"
18 #include "nuto/mechanics/dofSubMatrixStorage/BlockScalar.h"
20 #include "nuto/mechanics/elements/ElementBase.h"
21 #include "nuto/mechanics/groups/Group.h"
22 #include "nuto/mechanics/interpolationtypes/InterpolationBase.h"
23 #include "nuto/mechanics/interpolationtypes/InterpolationType.h"
24 #include "nuto/mechanics/structures/unstructured/Structure.h"
25 #include "nuto/mechanics/structures/StructureOutputBlockMatrix.h"
26 #include "nuto/mechanics/structures/StructureOutputBlockVector.h"
27 #include "nuto/mechanics/mesh/MeshGenerator.h"
28 
29 /*
30  * Interface for displacement controlled uni-axial tensile test
31  */
32 namespace NuToTest
33 {
34 
36 {
37 public:
38  double lX = 365;
39  double lY = 13;
40  double lZ = 37;
41 
42  double E = 42;
43  double nu = 0.26;
44  double deltaL = 0.6174;
45  double rho = M_PI;
46 
49  void Run(NuTo::Structure& s, const std::string& rVisualizationDirectory)
50  {
51 
52  CheckVolume(s);
53 
54  s.SetVerboseLevel(10);
55  s.SetShowTime(true);
56 
57 
58  SetConstitutiveLaw(s);
59  SetBoundaryConditions(s);
60 
61  s.NodeBuildGlobalDofs();
62  s.CalculateMaximumIndependentSets();
63 
64  s.NodeInfo(10);
65 
66  CheckStiffness(s);
67  Solve(s);
68  CheckSolution(s);
69  CheckMass(s);
70  Visualize(s, rVisualizationDirectory);
71  }
72 
73 private:
74  void CheckVolume(NuTo::Structure& s)
75  {
76  double volume = s.ElementGroupGetVolume(s.GroupGetElementsTotal());
77  if (s.GetDimension() == 2)
78  volume *= lZ;
79  if (s.GetDimension() == 1)
80  volume *= lY * lZ;
81 
82  BOOST_CHECK_CLOSE(volume, lX * lY * lZ, 1.e-6);
83  }
84 
85  void SetConstitutiveLaw(NuTo::Structure& s)
86  {
87  using namespace NuTo::Constitutive;
88  s.ConstitutiveLawCreate(0, eConstitutiveType::LINEAR_ELASTIC_ENGINEERING_STRESS);
89  s.ConstitutiveLawSetParameterDouble(0, eConstitutiveParameter::YOUNGS_MODULUS, E);
90  s.ConstitutiveLawSetParameterDouble(0, eConstitutiveParameter::POISSONS_RATIO, nu);
91  s.ConstitutiveLawSetParameterDouble(0, eConstitutiveParameter::DENSITY, rho);
92  s.ElementTotalSetConstitutiveLaw(0);
93  }
94 
95  void SetBoundaryConditions(NuTo::Structure& s)
96  {
97  int dimension = s.GetDimension();
98 
99  const NuTo::Node::eDof eDofDispl = NuTo::Node::eDof::DISPLACEMENTS;
100 
101  // fix origin
102  const auto& nodeOrigin = s.NodeGetAtCoordinate(Eigen::VectorXd::Zero(dimension));
103  for (int iDim = 1; iDim < dimension; ++iDim)
104  s.Constraints().Add(eDofDispl,
105  NuTo::Constraint::Component(nodeOrigin, {static_cast<NuTo::eDirection>(iDim)}));
106 
107  if (dimension == 3)
108  {
109  // fix rotation
110  const auto& nodeRotation = s.NodeGetAtCoordinate(Eigen::Vector3d(0, 0, lZ));
111  s.Constraints().Add(eDofDispl, NuTo::Constraint::Component(nodeRotation, {NuTo::eDirection::Y}));
112  }
113 
114  // fix x = 0 plane
115  const auto& groupX0 = s.GroupGetNodesAtCoordinate(NuTo::eDirection::X, 0);
116  s.Constraints().Add(eDofDispl, NuTo::Constraint::Component(groupX0, {NuTo::eDirection::X}));
117 
118  // apply displacement on x = lX plane
119  const auto& groupXlX = s.GroupGetNodesAtCoordinate(NuTo::eDirection::X, lX);
120  s.Constraints().Add(eDofDispl, NuTo::Constraint::Component(groupXlX, {NuTo::eDirection::X}, deltaL));
121  }
122 
123  void CheckStiffness(NuTo::Structure& s)
124  {
125  if (s.GetNumTotalDofs() > 50)
126  return;
127  BOOST_CHECK(s.ElementCheckHessian0(1.e-8, 1.e-6, true));
128  BOOST_CHECK(s.CheckHessian0(1.e-8, 1.e-6, true));
129  }
130 
131  void Solve(NuTo::Structure& s)
132  {
133  s.SolveGlobalSystemStaticElastic();
134  auto internalGradient = s.BuildGlobalInternalGradient();
135  BOOST_CHECK_SMALL(internalGradient.J.CalculateNormL2()[NuTo::Node::eDof::DISPLACEMENTS], 1e-8);
136  }
137 
138  void CheckSolution(NuTo::Structure& s)
139  {
140  double analyticStrainX = deltaL / lX;
141  double analyticStressX = analyticStrainX * E;
142  double analyticForce = analyticStressX * lY * lZ;
143 
144  std::cout << "\n ### analytical values ###" << std::endl;
145  std::cout << "sigma_xx: " << analyticStressX << std::endl;
146  std::cout << "force_x : " << analyticForce << std::endl;
147 
148  // get element stresses
149  int allElements = s.GroupGetElementsTotal();
150  for (int elementId : s.GroupGetMemberIds(allElements))
151  {
152  auto stress = s.ElementGetEngineeringStress(elementId);
153  for (int iIP = 0; iIP < stress.cols(); ++iIP)
154  {
155  double numericStress = stress(0, iIP);
156  std::cout << "numeric stress in element " << elementId << " at IP " << iIP << ": " << numericStress
157  << std::endl;
158 
159  BOOST_CHECK_CLOSE_FRACTION(numericStress, analyticStressX, 1.e-6);
160  }
161  }
162 
163 
164  // sum up reaction forces in x direction of all nodes on x = 0
165  double numericForce = 0;
166  const auto& nodesX0 = s.GroupGetNodesAtCoordinate(NuTo::eDirection::X, lX);
167  for (int nodeId : nodesX0.GetMemberIds())
168  {
169  Eigen::VectorXd force;
170  s.NodeInternalForce(nodeId, force);
171  numericForce += force(0);
172  }
173 
174  BOOST_CHECK_CLOSE(numericForce, analyticForce, 1.e-6);
175  }
176 
177  void CheckMass(NuTo::Structure& s)
178  {
179  double analyticMass = lX * lY * lZ * rho;
180 
181  auto hessian2 = s.BuildGlobalHessian2();
182 
183  double numericMass = 0;
184  numericMass += hessian2.JJ(NuTo::Node::eDof::DISPLACEMENTS, NuTo::Node::eDof::DISPLACEMENTS).Sum();
185  numericMass += hessian2.JK(NuTo::Node::eDof::DISPLACEMENTS, NuTo::Node::eDof::DISPLACEMENTS).Sum();
186  numericMass += hessian2.KJ(NuTo::Node::eDof::DISPLACEMENTS, NuTo::Node::eDof::DISPLACEMENTS).Sum();
187  numericMass += hessian2.KK(NuTo::Node::eDof::DISPLACEMENTS, NuTo::Node::eDof::DISPLACEMENTS).Sum();
188 
189  numericMass /= s.GetDimension(); // since the mass is added to nodes in every direction
190 
191  BOOST_CHECK_CLOSE(numericMass, analyticMass, 1.e-6);
192 
193  hessian2 = s.BuildGlobalHessian2Lumped();
194 
195  numericMass = 0;
196  numericMass += hessian2.JJ(NuTo::Node::eDof::DISPLACEMENTS, NuTo::Node::eDof::DISPLACEMENTS).Sum();
197  numericMass += hessian2.JK(NuTo::Node::eDof::DISPLACEMENTS, NuTo::Node::eDof::DISPLACEMENTS).Sum();
198  numericMass += hessian2.KJ(NuTo::Node::eDof::DISPLACEMENTS, NuTo::Node::eDof::DISPLACEMENTS).Sum();
199  numericMass += hessian2.KK(NuTo::Node::eDof::DISPLACEMENTS, NuTo::Node::eDof::DISPLACEMENTS).Sum();
200 
201  numericMass /= s.GetDimension(); // since the mass is added to nodes in every direction
202 
203  BOOST_CHECK_CLOSE(numericMass, analyticMass, 1.e-6);
204  }
205 
206  void Visualize(NuTo::Structure& s, const std::string& rVisualizationDirectory)
207  {
208  if (rVisualizationDirectory == "")
209  throw NuTo::Exception(__PRETTY_FUNCTION__, "Provide a valid visualization directory!");
210 
211  boost::filesystem::path directory(rVisualizationDirectory);
212  boost::filesystem::create_directory(directory);
213 
214  const auto& interpolationType = *s.InterpolationTypeGet(0);
215  std::string fileName = NuTo::Interpolation::ShapeTypeToString(interpolationType.GetShapeType());
216  fileName += NuTo::Interpolation::TypeOrderToString(
217  interpolationType.Get(NuTo::Node::eDof::DISPLACEMENTS).GetTypeOrder());
218  fileName += ".vtu";
219  directory /= fileName;
220 
221  int visualizationGroup = s.GroupCreate(NuTo::eGroupId::Elements);
222  s.GroupAddElementsTotal(visualizationGroup);
223 
224  s.AddVisualizationComponent(visualizationGroup, NuTo::eVisualizeWhat::DISPLACEMENTS);
225  s.AddVisualizationComponent(visualizationGroup, NuTo::eVisualizeWhat::ENGINEERING_STRAIN);
226  s.AddVisualizationComponent(visualizationGroup, NuTo::eVisualizeWhat::ENGINEERING_STRESS);
227 
228  s.ExportVtkDataFileElements(directory.string());
229  }
230 };
231 } // namespace NuToTest
path
Definition: Brick8N.py:8
Definition: ElementUniaxialTest.h:32
Base class for all exceptions thrown in NuTo.
Definition: Exception.h:9
double lX
Definition: ElementUniaxialTest.h:38
eDirection
Definition: DirectionEnum.h:5
double lY
Definition: ElementUniaxialTest.h:39
visualize engineering stress tensor
Definition: DamageLaw.h:5
s
Definition: WaveFieldSynthesis.py:99
std::vector< Equation > Component(const NodeSimple &node, std::vector< eDirection > directions, double value)
constraints components of vector valued nodes in X and/or Y and/or Z
Definition: ConstraintCompanion.cpp:21
interpolationType
Definition: Brick8NCoupling.py:48
double nu
Definition: ElementUniaxialTest.h:43
double lZ
Definition: ElementUniaxialTest.h:40
Definition: ElementUniaxialTest.h:35
visualize displacements
visualizationGroup
Definition: Brick8NCoupling.py:139
void CheckSolution(NuTo::Structure &s, double tolerance)
Definition: PlateWithHole.cpp:42
void Run(NuTo::Structure &s, const std::string &rVisualizationDirectory)
provide a structure that contains the geometry of a uniaxial test, starting from (0,0,0) to (lx, ly, lz)
Definition: ElementUniaxialTest.h:49
constexpr int dimension
Definition: single_edge_notched_tension_test.cpp:30
double rho
Definition: ElementUniaxialTest.h:45
double E
Definition: ElementUniaxialTest.h:42
double deltaL
Definition: ElementUniaxialTest.h:44
visualize engineering strain tensor