GetFEM  5.5
plasticity.cc
Go to the documentation of this file.
1 /*===========================================================================
2 
3  Copyright (C) 2000-2026 Yves Renard
4 
5  This file is a part of GetFEM
6 
7  GetFEM is free software; you can redistribute it and/or modify it
8  under the terms of the GNU Lesser General Public License as published
9  by the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version along with the GCC Runtime Library
11  Exception either version 3.1 or (at your option) any later version.
12  This program is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15  License and GCC Runtime Library Exception for more details.
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program. If not, see https://www.gnu.org/licenses/.
18 
19 ===========================================================================*/
20 
21 
22 /**
23  @file plasticity.cc
24  @brief Small deformation plasticity problem.
25 
26  This program is used to check that getfem++ is working.
27  This is also a good example of use of GetFEM.
28 */
29 
34 #include "getfem/getfem_export.h"
35 
36 using std::endl; using std::cout; using std::cerr;
37 using std::ends; using std::cin;
38 
39 /* some GetFEM types that we will be using */
40 
41 /* special class for small (dim<16) vectors */
43 /* geometrical nodes(derived from base_small_vector)*/
44 using bgeot::base_node;
45 using bgeot::scalar_type; /* = double */
46 using bgeot::size_type; /* = unsigned long */
47 using bgeot::base_matrix; /* small dense matrix. */
48 
49 /* definition of some matrix/vector types. These ones are built
50  using the predefined types in Gmm++ */
52 typedef getfem::modeling_standard_sparse_matrix sparse_matrix;
53 typedef getfem::modeling_standard_plain_vector plain_vector;
54 
55 template<typename VEC>
56 static void vecsave(std::string fname, const VEC& V);
57 
58 //function to save a vector
59 template<typename VEC>
60 static void vecsave( std::string fname, const VEC& V) {
61 
62  std::ofstream f(fname.c_str()); f.precision(16);
63  for (size_type i=0; i < V.size(); ++i)
64  f << V[i] << "\n";
65 }
66 
67 
68 
69 //=================================================================
70 // structure for the elastoplastic problem
71 //=================================================================
72 
73 struct elastoplasticity_problem {
74 
75  enum { DIRICHLET_BOUNDARY_NUM = 0,
76  NEUMANN_BOUNDARY_NUM = 1};
77 
78  getfem::mesh mesh; /* the mesh */
79  getfem::mesh_im mim; /* integration methods. */
80  getfem::im_data mim_data; /* Mim data for the pastic strain. */
81  getfem::mesh_fem mf_u; /* main mesh_fem, for the
82  elastoplastic displacement */
83  getfem::mesh_fem mf_xi; /* mesh_fem, for the plastic multiplier. */
84  getfem::mesh_fem mf_rhs; /* mesh_fem for the right hand side
85  (f(x),..) */
86  scalar_type lambda, mu; /* Lamé coefficients. */
87 
88  scalar_type residual; /* max residual for the iterative solvers */
89  scalar_type sigma_y;
90  size_type flag_hyp;
91  std::string datafilename;
92  bgeot::md_param PARAM;
93  bool do_export;
94 
95  bool solve(plain_vector &U);
96  void init(void);
97 
98  elastoplasticity_problem(void) : mim(mesh), mim_data(mim), mf_u(mesh),
99  mf_xi(mesh), mf_rhs(mesh) {}
100 
101 };
102 
103 
104 
105 
106 /* Read parameters from the .param file, build the mesh,
107  set finite element and integration methods
108  and selects the boundaries.
109 */
110 void elastoplasticity_problem::init(void) {
111 
112  std::string MESH_TYPE =
113  PARAM.string_value("MESH_TYPE","Mesh type ");
114  std::string FEM_TYPE =
115  PARAM.string_value("FEM_TYPE","FEM name");
116  std::string FEM_TYPE_XI =
117  PARAM.string_value("FEM_TYPE_XI","FEM name");
118  std::string INTEGRATION =
119  PARAM.string_value("INTEGRATION",
120  "Name of integration method");
121  do_export = (PARAM.int_value("EXPORT", "Perform or not the vtk export") != 0);
122 
123  cout << "MESH_TYPE=" << MESH_TYPE << "\n";
124  cout << "FEM_TYPE=" << FEM_TYPE << "\n";
125  cout << "INTEGRATION=" << INTEGRATION << "\n";
126 
127  residual = PARAM.real_value("RESIDUAL", "residual");
128 
129  // file to save the mesh
130  datafilename = PARAM.string_value("ROOTFILENAME",
131  "Filename for saving");
132 
133  /* First step : build the mesh */
134  size_type N;
135  bgeot::pgeometric_trans pgt = 0;
136 
137  if (MESH_TYPE != "load") {
138  std::cout << "created getfem mesh" << "\n";
139  pgt = bgeot::geometric_trans_descriptor(MESH_TYPE);
140  N = pgt->dim();
141  std::vector<size_type> nsubdiv(N);
142  nsubdiv[0]=PARAM.int_value
143  ("NX", "Number of space steps in x direction ");
144  nsubdiv[1]=PARAM.int_value
145  ("NY", "Number of space steps in y direction ");
146 
147  if(N==3)
148  nsubdiv[2]=PARAM.int_value
149  ("NZ", "Number of space steps in z direction ");
150  getfem::regular_unit_mesh(mesh, nsubdiv, pgt,
151  PARAM.int_value("MESH_NOISED")!= 0);
152 
153  bgeot::base_matrix M(N,N);
154 
155  for (size_type i=0; i < N; ++i) {
156  static const char *t[] = {"LX","LY","LZ"};
157  M(i,i) = (i<3) ? PARAM.real_value(t[i],t[i]) : 1.0;
158  }
159 
160  if (N>1) {
161  M(0,1) = PARAM.real_value("INCLINE") *
162  PARAM.real_value("LY");
163  }
164 
165  /* scale the unit mesh to [LX,LY,..] and incline it */
166  mesh.transformation(M);
167 
168  } else {
169  std ::cout << "mesh from pdetool" << "\n";
170  std::string MESH_FILE
171  = PARAM.string_value("MESH_FILE", "Mesh file name");
172 
173  mesh.read_from_file(MESH_FILE);
174 
175  N = mesh.dim();
176  pgt = mesh.trans_of_convex
177  (mesh.convex_index().first_true());
178  }
179 
180  mu = PARAM.real_value("MU", "Lamé coefficient mu");
181  /* muT = PARAM.real_value("MUT", "Lamé coefficient muT");
182  lambdaB = PARAM.real_value("LAMBDAB",
183  "Lamé coefficient lambdaB");
184  */
185  lambda = PARAM.real_value("LAMBDA",
186  "Lamé coefficient lambda");
187  mf_u.set_qdim(bgeot::dim_type(N));
188 
189 
190  /* set the finite element on the mf_u */
191  getfem::pfem pf_u =
192  getfem::fem_descriptor(FEM_TYPE);
193  getfem::pintegration_method ppi =
194  getfem::int_method_descriptor(INTEGRATION);
195 
196  mim.set_integration_method(mesh.convex_index(), ppi);
197  mim_data.set_tensor_size(bgeot::multi_index(N,N));
198  mf_u.set_finite_element(mesh.convex_index(), pf_u);
199 
200 
201  /* set the finite element on the mf_sigma */
202  getfem::pfem pf_xi = getfem::fem_descriptor(FEM_TYPE_XI);
203  mf_xi.set_finite_element(mesh.convex_index(), pf_xi);
204 
205 
206  /* set the finite element on mf_rhs
207  (same as mf_u is DATA_FEM_TYPE is not used in the .param file)*/
208  std::string data_fem_name
209  = PARAM.string_value("DATA_FEM_TYPE");
210 
211  if (data_fem_name.size() == 0) {
212  GMM_ASSERT1(pf_u->is_lagrange(),
213  "You are using a non-lagrange FEM. "
214  << "In that case you need to set "
215  << "DATA_FEM_TYPE in the .param file");
216  mf_rhs.set_finite_element(mesh.convex_index(), pf_u);
217 
218  } else {
219  mf_rhs.set_finite_element(mesh.convex_index(),
220  getfem::fem_descriptor(data_fem_name));
221  }
222 
223 
224  /* set boundary conditions
225  * (Neuman on the upper face, Dirichlet elsewhere) */
226  cout << "Selecting Neumann and Dirichlet boundaries\n";
227  getfem::mesh_region border_faces;
228  getfem::outer_faces_of_mesh(mesh, border_faces);
229 
230  for (getfem::mr_visitor it(border_faces);
231  !it.finished(); ++it) {
232  assert(it.is_face());
233  base_node un
234  = mesh.normal_of_face_of_convex(it.cv(), it.f());
235  un /= gmm::vect_norm2(un);
236 
237  if (gmm::abs(un[0] - 1.0) < 1.0E-7)
238  mesh.region(NEUMANN_BOUNDARY_NUM).add(it.cv(), it.f());
239  else if (gmm::abs(un[0] + 1.0) < 1.0E-7)
240  mesh.region(DIRICHLET_BOUNDARY_NUM).add(it.cv(),it.f());
241 
242  }
243 
244  // Plasticity part
245  sigma_y = PARAM.real_value("SIGMA_Y", "plasticity yield stress");
246  flag_hyp=PARAM.int_value("FLAG_HYP");
247 }
248 
249 
250 
251 //==================================================================
252 // Model.
253 //==================================================================
254 
255 bool elastoplasticity_problem::solve(plain_vector &U) {
256 
257  size_type nb_dof_rhs = mf_rhs.nb_dof();
258  size_type N = mesh.dim();
259  getfem::model model;
260 
261  gmm::set_traces_level(1);
262 
263  // Main unknown of the problem.
264  model.add_fem_variable("u", mf_u);
265  model.add_fem_data("Previous_u", mf_u);
266 
267  model.add_initialized_scalar_data("lambda", lambda);
268  model.add_initialized_scalar_data("mu", mu);
269  model.add_initialized_scalar_data("sigma_y", sigma_y);
270 
271  model.add_fem_data("xi", mf_xi);
272  model.add_fem_data("Previous_xi", mf_xi);
273  model.add_im_data("Previous_Ep", mim_data);
274 
275  /* choose the projection type */
276  getfem::pconstraints_projection
277  proj = std::make_shared<getfem::VM_projection>(0);
278 
279  std::vector<std::string> plastic_variables = {"u", "xi", "Previous_Ep"};
280  std::vector<std::string> plastic_data = {"lambda", "mu", "sigma_y"};
281 
282 
284  (model, mim, "Prandtl Reuss", getfem::DISPLACEMENT_ONLY,
285  plastic_variables, plastic_data);
286 
287  plain_vector F(nb_dof_rhs * N);
288  model.add_initialized_fem_data("NeumannData", mf_rhs, F);
290  (model, mim, "u", "NeumannData", NEUMANN_BOUNDARY_NUM);
291 
292  model.add_initialized_fem_data("DirichletData", mf_rhs, F);
294  (model, mim, "u", mf_u, DIRICHLET_BOUNDARY_NUM,
295  "DirichletData");
296 
297  const size_type Nb_t = 19;
298  std::vector<scalar_type> T(19);
299  T[0] = 0; T[1] = 0.9032; T[2] = 1; T[3] = 1.1; T[4] = 1.3;
300  T[5] = 1.5; T[6] = 1.7; T[7] = 1.74; T[8] = 1.7; T[9] = 1.5;
301  T[10] = 1.3; T[11] = 1.1; T[12] = 1; T[13] = 0.9032; T[14] = 0.7;
302  T[15] = 0.5; T[16] = 0.3; T[17] = 0.1; T[18] = 0;
303 
304 
305  getfem::mesh_fem mf_vm(mesh);
306  mf_vm.set_classical_discontinuous_finite_element(1);
307  getfem::base_vector VM(mf_vm.nb_dof());
308  getfem::base_vector plast(mf_vm.nb_dof());
309 
310  for (size_type nb = 0; nb < Nb_t; ++nb) {
311  cout << "=============iteration number : " << nb << "==========" << endl;
312 
313  scalar_type t = T[nb];
314 
315  // Defining the Neumann condition right hand side.
316  base_small_vector v(N);
317  v[N-1] = -PARAM.real_value("FORCE");
318  gmm::scale(v,t);
319 
320  for (size_type i = 0; i < nb_dof_rhs; ++i)
321  gmm::copy(v, gmm::sub_vector
322  (F, gmm::sub_interval(i*N, N)));
323 
324  gmm::copy(F, model.set_real_variable("NeumannData"));
325 
326  // Generic solve.
327  cout << "Number of variables : "
328  << model.nb_dof() << endl;
329 
330  getfem::newton_search_with_step_control ls;
331  // getfem::simplest_newton_line_search ls;
332  gmm::iteration iter(residual, 2, 40000);
333  getfem::standard_solve(model, iter,
334 #if defined(GMM_USES_MUMPS)
335  getfem::rselect_linear_solver(model, "mumps"), ls);
336 #else
337  getfem::rselect_linear_solver(model, "superlu"), ls);
338 #endif
339 
341  (model, mim, "Prandtl Reuss", getfem::DISPLACEMENT_ONLY,
342  plastic_variables, plastic_data);
343 
344  // Get the solution and save it
345  gmm::copy(model.real_variable("u"), U);
346 
347 
349  (model, mim, "Prandtl Reuss", getfem::DISPLACEMENT_ONLY,
350  plastic_variables, plastic_data, mf_vm, VM);
351 
352  std::stringstream fname; fname << datafilename << "_" << nb << ".vtk";
353 
354  if (do_export) {
355  getfem::vtk_export exp(fname.str());
356  exp.exporting(mf_vm);
357  exp.write_point_data(mf_vm,VM, "Von Mises stress");
358  exp.write_point_data(mf_u, U, "displacement");
359  }
360 
361  }
362 
363  if (do_export) {
364  cout << "export done, you can view the data file with "
365  "(for example)\n"
366  "mayavi2 -d " << datafilename << "_1.vtk -f "
367  "WarpVector -m Surface -m Outline\n";
368  }
369 
370  return true;
371 }
372 
373 
374 //==================================================================
375 // main program.
376 //==================================================================
377 
378 int main(int argc, char *argv[]) {
379 
380  GETFEM_MPI_INIT(argc, argv);
381  GMM_SET_EXCEPTION_DEBUG;
382  // Exceptions make a memory fault, to debug.
383 
384  FE_ENABLE_EXCEPT;
385  // Enable floating point exception for Nan.
386 
387  elastoplasticity_problem p;
388  p.PARAM.read_command_line(argc, argv);
389  p.init();
390  p.mesh.write_to_file(p.datafilename + ".mesh");
391  plain_vector U(p.mf_u.nb_dof());
392  if (!p.solve(U)) GMM_ASSERT1(false, "Solve has failed");
393  vecsave(p.datafilename + ".U", U);
394  cout << "Resultats dans fichier : "
395  <<p.datafilename<<".U \n";
396  p.mf_u.write_to_file(p.datafilename + ".meshfem",true);
397  scalar_type t[2]={p.mu,p.lambda};
398  vecsave(p.datafilename+".coef",
399  std::vector<scalar_type>(t, t+2));
400 
401  GETFEM_MPI_FINALIZE;
402 
403  return 0;
404 }
im_data provides indexing to the integration points of a mesh im object.
Describe a finite element method linked to a mesh.
Describe an integration method linked to a mesh.
"iterator" class for regions.
structure used to hold a set of convexes and/or convex faces.
Describe a mesh (collection of convexes (elements) and points).
Definition: getfem_mesh.h:98
`‘Model’' variables store the variables, the data and the description of a model.
size_type nb_dof(bool with_internal=false) const
Total number of degrees of freedom in the model.
void add_initialized_scalar_data(const std::string &name, T e)
Add a scalar data (i.e.
void add_fem_variable(const std::string &name, const mesh_fem &mf, size_type niter=1)
Add a variable being the dofs of a finite element method to the model.
void add_im_data(const std::string &name, const im_data &imd, size_type niter=1)
Add data defined at integration points.
void add_initialized_fem_data(const std::string &name, const mesh_fem &mf, const VECT &v)
Add an initialized fixed size data to the model, assumed to be a vector field if the size of the vect...
model_real_plain_vector & set_real_variable(const std::string &name, size_type niter) const
Gives the write access to the vector value of a variable.
const model_real_plain_vector & real_variable(const std::string &name, size_type niter) const
Gives the access to the vector value of a variable.
void add_fem_data(const std::string &name, const mesh_fem &mf, dim_type qdim=1, size_type niter=1)
Add a data being the dofs of a finite element method to the model.
VTK/VTU export.
Definition: getfem_export.h:67
The Iteration object calculates whether the solution has reached the desired accuracy,...
Definition: gmm_iter.h:52
sparse vector built upon std::vector.
Definition: gmm_vector.h:995
Miscelleanous assembly routines for common terms. Use the low-level generic assembly....
Export solutions to various formats.
Standard solvers for model bricks.
Plasticty bricks.
Build regular meshes.
void copy(const L1 &l1, L2 &l2)
*‍/
Definition: gmm_blas.h:976
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
Definition: gmm_blas.h:556
void APIDECL outer_faces_of_mesh(const mesh &m, const dal::bit_vector &cvlst, convex_face_ct &flist)
returns a list of "exterior" faces of a mesh (i.e.
Definition: getfem_mesh.cc:821
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
Definition: getfem_fem.h:243
pfem fem_descriptor(const std::string &name)
get a fem descriptor from its string name.
Definition: getfem_fem.cc:4659
pgeometric_trans geometric_trans_descriptor(std::string name)
Get the geometric transformation from its string name.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:48
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
size_type APIDECL add_Dirichlet_condition_with_multipliers(model &md, const mesh_im &mim, const std::string &varname, const std::string &multname, size_type region, const std::string &dataname=std::string())
Add a Dirichlet condition on the variable varname and the mesh region region.
void compute_small_strain_elastoplasticity_Von_Mises(model &md, const mesh_im &mim, std::string lawname, plasticity_unknowns_type unknowns_type, const std::vector< std::string > &varnames, const std::vector< std::string > &params, const mesh_fem &mf_vm, model_real_plain_vector &VM, size_type region=size_type(-1))
This function computes the Von Mises stress field with respect to a small strain elastoplasticity ter...
void regular_unit_mesh(mesh &m, std::vector< size_type > nsubdiv, bgeot::pgeometric_trans pgt, bool noised=false)
Build a regular mesh of the unit square/cube/, etc.
size_type add_small_strain_elastoplasticity_brick(model &md, const mesh_im &mim, std::string lawname, plasticity_unknowns_type unknowns_type, const std::vector< std::string > &varnames, const std::vector< std::string > &params, size_type region=size_type(-1))
Adds a small strain plasticity term to the model md.
pintegration_method int_method_descriptor(std::string name, bool throw_if_not_found=true)
Get an integration method from its name .
void small_strain_elastoplasticity_next_iter(model &md, const mesh_im &mim, std::string lawname, plasticity_unknowns_type unknowns_type, const std::vector< std::string > &varnames, const std::vector< std::string > &params, size_type region=size_type(-1))
Function that allows to pass from a time step to another for the small strain plastic brick.
size_type APIDECL add_source_term_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr, size_type region=size_type(-1), const std::string &directdataname=std::string())
Add a source term on the variable varname.
void standard_solve(model &md, gmm::iteration &iter, rmodel_plsolver_type lsolver, abstract_newton_line_search &ls)
A default solver for the model brick system.