libMesh
miscellaneous_ex13.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2019 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 // <h1>Miscellaneous Example 12 - Quad8 Shell Elements</h1>
19 // \author Sylvain Vallaghe
20 // \date 2017
21 //
22 // This example implements shell elements using 8-noded serendipity quadrilaterals and reduced integration.
23 // Full integration Quad8 shell elements are prone to locking issues.
24 // The reduced integration version "eliminates locking in most situations
25 // although it introduces two spureous mechanisms. Fortunately,
26 // these mechanisms disappear after assembly of the global stiffness matrix and the element
27 // can be considered safe for practical purposes".
28 // (source: Onate, Structural Analysis with the Finite Element Method).
29 // The "pinched cylinder" problem is solved and the solution
30 // is compared to analytical values at selected points.
31 
32 // C++ include files that we need
33 #include <iostream>
34 
35 // LibMesh includes
36 #include "libmesh/libmesh.h"
37 #include "libmesh/mesh.h"
38 #include "libmesh/linear_implicit_system.h"
39 #include "libmesh/equation_systems.h"
40 #include "libmesh/fe.h"
41 #include "libmesh/quadrature.h"
42 #include "libmesh/node.h"
43 #include "libmesh/elem.h"
44 #include "libmesh/dof_map.h"
45 #include "libmesh/quadrature_gauss.h"
46 #include "libmesh/vector_value.h"
47 #include "libmesh/tensor_value.h"
48 #include "libmesh/dense_matrix.h"
49 #include "libmesh/dense_submatrix.h"
50 #include "libmesh/dense_vector.h"
51 #include "libmesh/dense_subvector.h"
52 #include "libmesh/sparse_matrix.h"
53 #include "libmesh/numeric_vector.h"
54 #include "libmesh/exodusII_io.h"
55 #include "libmesh/dirichlet_boundaries.h"
56 #include "libmesh/zero_function.h"
57 #include "libmesh/linear_solver.h"
58 #include "libmesh/getpot.h"
59 #include "libmesh/enum_solver_package.h"
60 #include "libmesh/enum_solver_type.h"
61 #include "libmesh/parallel.h"
62 
63 // Eigen includes
64 #ifdef LIBMESH_HAVE_EIGEN
65 #include "libmesh/ignore_warnings.h"
66 # include <Eigen/Dense>
67 #include "libmesh/restore_warnings.h"
68 
69 // Use Eigen dense numerics with libMesh::Real
70 typedef Eigen::Matrix<libMesh::Real, 2, 2> MyMatrix2d;
71 typedef Eigen::Matrix<libMesh::Real, 3, 3> MyMatrix3d;
72 typedef Eigen::Matrix<libMesh::Real, 2, 1> MyVector2d;
73 typedef Eigen::Matrix<libMesh::Real, 3, 1> MyVector3d;
74 typedef Eigen::Matrix<libMesh::Real, Eigen::Dynamic, Eigen::Dynamic> MyMatrixXd;
75 #endif
76 
77 // Bring in everything from the libMesh namespace
78 using namespace libMesh;
79 
80 // Function prototype. This is the function that will assemble
81 // the stiffness matrix and the right-hand-side vector ready
82 // for solution.
84  const std::string & system_name);
85 
86 // Begin the main program.
87 int main (int argc, char ** argv)
88 {
89  // Initialize libMesh.
90  LibMeshInit init (argc, argv);
91 
92  // Skip this 3D example if libMesh was compiled as 1D/2D-only.
93  libmesh_example_requires (3 == LIBMESH_DIM, "3D support");
94 
95  // We use Dirichlet boundary conditions here
96 #ifndef LIBMESH_ENABLE_DIRICHLET
97  libmesh_example_requires(false, "--enable-dirichlet");
98 #endif
99 
100  // Our input mesh here is in ExodusII format
101 #ifndef LIBMESH_HAVE_EXODUS_API
102  libmesh_example_requires (false, "ExodusII support");
103 #endif
104 
105 #ifndef LIBMESH_ENABLE_SECOND_DERIVATIVES
106  libmesh_example_requires (false, "second derivatives enabled");
107 #endif
108 
109  // This example does a bunch of linear algebra during assembly, and
110  // therefore requires Eigen.
111 #ifndef LIBMESH_HAVE_EIGEN
112  libmesh_example_requires(false, "--enable-eigen");
113 #endif
114 
115  // This example converts between ExodusII and XDR files, therefore
116  // it requires XDR support in libmesh.
117 #ifndef LIBMESH_HAVE_XDR
118  libmesh_example_requires (false, "XDR support");
119 #endif
120 
121  // This examples requires parallel minloc() support, which we don't
122  // implement yet for float128
123 #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
124  libmesh_example_requires (false, "--disable-quadruple-precision");
125 #endif
126 
127  // Read the "distributed_load" flag from the command line
128  GetPot command_line (argc, argv);
129  int distributed_load = 0;
130  if (command_line.search(1, "-distributed_load"))
131  distributed_load = command_line.next(distributed_load);
132 
133  {
134  Mesh mesh (init.comm(), 3);
135 
136  // To confirm that both ExodusII and Xdr formats work for shell
137  // meshes, we read in cylinder.exo, then write out cylinder.xdr,
138  // then read in cylinder.exo again below and use that for the rest
139  // of the example.
140  mesh.read("cylinder.exo");
141  mesh.write("cylinder.xdr");
142  }
143  Mesh mesh (init.comm(), 3);
144  mesh.read("cylinder.xdr");
145 
146  // Print information about the mesh to the screen.
147  mesh.print_info();
148 
149  // Create an equation systems object.
150  EquationSystems equation_systems (mesh);
151 
152  // Declare the system and its variables.
153  // Create a linear implicit system named "Shell".
154  LinearImplicitSystem & system = equation_systems.add_system<LinearImplicitSystem> ("Shell");
155 
156  // Add the three displacement variables "u", "v", "w",
157  // and the three rotational variables "theta_x", "theta_y", "theta_z".
158  // All variables are second order.
159  system.add_variable ("u",SECOND,LAGRANGE);
160  system.add_variable ("v",SECOND,LAGRANGE);
161  system.add_variable ("w",SECOND,LAGRANGE);
162  system.add_variable ("theta_x",SECOND,LAGRANGE);
163  system.add_variable ("theta_y",SECOND,LAGRANGE);
164  system.add_variable ("theta_z",SECOND,LAGRANGE);
165 
166  // Give the system a pointer to the matrix and rhs assembly
167  // function.
169 
170  // Use the parameters of the equation systems object to
171  // tell the shell system about the material properties, the
172  // shell thickness, and the external load.
173  const Real h = 0.03;
174  const Real E = 3e10;
175  const Real nu = 0.3;
176  const Real q = 1;
177  equation_systems.parameters.set<Real> ("thickness") = h;
178  equation_systems.parameters.set<Real> ("young's modulus") = E;
179  equation_systems.parameters.set<Real> ("poisson ratio") = nu;
180  equation_systems.parameters.set<Real> ("point load") = q;
181  equation_systems.parameters.set<bool>("distributed load") = (distributed_load != 0);
182 
183  // Dirichlet conditions for the pinched cylinder problem.
184  // Only one 8th of the cylinder is considered using symmetry considerations.
185  // The cylinder longitudinal axis is the y-axis.
186  // The four corners of the surface are named A(3,0,0), B(3,3,0), C(0,3,3), D(0,0,3).
187  // The point load (pinch) is applied at C in the -z direction.
188  // Edge AD is the actual edge of the cylinder and is rigid in the xz-plane.
189  // Other edges have symmetric boundary conditions.
190 
191 #ifdef LIBMESH_ENABLE_DIRICHLET
192  // AB w, theta_x, theta_y
193  {
194  std::set<boundary_id_type> boundary_ids;
195  boundary_ids.insert(7);
196  unsigned int variables[] = {2, 3, 4};
197  ZeroFunction<> zf;
198 
199  // Most DirichletBoundary users will want to supply a "locally
200  // indexed" functor
201  DirichletBoundary dirichlet_bc
202  (boundary_ids,
203  std::vector<unsigned int>(variables, variables+3), zf,
205  system.get_dof_map().add_dirichlet_boundary(dirichlet_bc);
206  }
207  // BC v, theta_x, theta_z
208  {
209  std::set<boundary_id_type> boundary_ids;
210  boundary_ids.insert(8);
211  unsigned int variables[] = {1, 3, 5};
212  ZeroFunction<> zf;
213 
214  DirichletBoundary dirichlet_bc
215  (boundary_ids,
216  std::vector<unsigned int>(variables, variables+3), zf,
218  system.get_dof_map().add_dirichlet_boundary(dirichlet_bc);
219  }
220  // CD u, theta_y, theta_z
221  {
222  std::set<boundary_id_type> boundary_ids;
223  boundary_ids.insert(9);
224  unsigned int variables[] = {0, 4, 5};
225  ZeroFunction<> zf;
226 
227  DirichletBoundary dirichlet_bc
228  (boundary_ids,
229  std::vector<unsigned int>(variables, variables+3), zf,
231  system.get_dof_map().add_dirichlet_boundary(dirichlet_bc);
232  }
233  // AD u, w, theta_y
234  {
235  std::set<boundary_id_type> boundary_ids;
236  boundary_ids.insert(10);
237  unsigned int variables[] = {0, 2, 4};
238  ZeroFunction<> zf;
239 
240  DirichletBoundary dirichlet_bc
241  (boundary_ids,
242  std::vector<unsigned int>(variables, variables+3), zf,
244  system.get_dof_map().add_dirichlet_boundary(dirichlet_bc);
245  }
246 #endif // LIBMESH_ENABLE_DIRICHLET
247 
248  // Initialize the data structures for the equation system.
249  equation_systems.init();
250 
251  // Print information about the system to the screen.
252  equation_systems.print_info();
253 
254  // This example can be run with EigenSparseLinearSolvers, but it
255  // only works with either the CG or SPARSELU types, and SparseLU
256  // turns out to be faster.
259 
260  // Solve the linear system.
261  system.solve();
262 
263  // After solving the system, write the solution to an
264  // ExodusII output file ready for import in, e.g.,
265  // Paraview.
266  ExodusII_IO(mesh).write_equation_systems ("out.e", equation_systems);
267 
268  // Compare with analytical solution for point load
269  if (distributed_load==0)
270  {
271  // Find the node nearest point C.
272  Node * node_C = nullptr;
273  Point point_C(0, 3, 3);
274  {
275  Real nearest_dist_sq = std::numeric_limits<Real>::max();
276 
277  // Find the closest local node. On a DistributedMesh we may
278  // not even know about the existence of closer non-local
279  // nodes.
280  for (const auto & node : mesh.local_node_ptr_range())
281  {
282  const Real dist_sq = (*node - point_C).norm_sq();
283  if (dist_sq < nearest_dist_sq)
284  {
285  nearest_dist_sq = dist_sq;
286  node_C = node;
287  }
288  }
289 
290  // Check with other processors to see if any found a closer node
291  unsigned int minrank = 0;
292  system.comm().minloc(nearest_dist_sq, minrank);
293 
294  // Broadcast the ID of the closest node, so every processor can
295  // see for certain whether they have it or not.
296  dof_id_type nearest_node_id = 0;
297  if (system.processor_id() == minrank)
298  nearest_node_id = node_C->id();
299  system.comm().broadcast(nearest_node_id, minrank);
300  node_C = mesh.query_node_ptr(nearest_node_id);
301  }
302 
303  // Evaluate the z-displacement "w" at the node nearest C.
304  Number w = 0;
305 
306  // If we know about the closest node, and if we also own the DoFs
307  // on that node, then we can evaluate the solution at that node.
308  if (node_C)
309  {
310  const unsigned int w_var = system.variable_number ("w");
311  dof_id_type w_dof = node_C->dof_number (system.number(), w_var, 0);
312  if (w_dof >= system.get_dof_map().first_dof() &&
313  w_dof < system.get_dof_map().end_dof())
314  w = system.current_solution(w_dof);
315  }
316  system.comm().sum(w);
317 
318 
319  Number w_C_bar = -E*h*w/q;
320  const Real w_C_bar_analytic = 164.24;
321 
322  // Print the finite element solution and the analytic
323  // prediction to the screen.
324  libMesh::out << "z-displacement of the point C: " << w_C_bar << std::endl;
325  libMesh::out << "Analytic solution: " << w_C_bar_analytic << std::endl;
326 
327  // Evaluate the y-displacement "v" at point D. This time we'll
328  // evaluate at the exact point, not just the closest node.
329  Point point_D(0, 0, 3);
330  const unsigned int v_var = system.variable_number ("v");
331  Number v = system.point_value(v_var, point_D);
332 
333  Number v_D_bar = E*h*v/q;
334  const Real v_D_bar_analytic = 4.114;
335 
336  // Print the finite element solution and the analytic
337  // prediction to the screen.
338  libMesh::out << "y-displacement of the point D: " << v_D_bar << std::endl;
339  libMesh::out << "Analytic solution: " << v_D_bar_analytic << std::endl;
340  }
341 
342  // All done.
343  return 0;
344 }
345 
346 
347 
348 // We now define the matrix and rhs vector assembly function
349 // for the shell system.
351  const std::string & system_name)
352 {
353  // This example requires Eigen to actually work, but we should still
354  // let it compile and throw a runtime error if you don't.
355 #if defined(LIBMESH_HAVE_EIGEN) && defined(LIBMESH_ENABLE_SECOND_DERIVATIVES)
356  // It is a good idea to make sure we are assembling
357  // the proper system.
358  libmesh_assert_equal_to (system_name, "Shell");
359 
360  // Get a constant reference to the mesh object.
361  const MeshBase & mesh = es.get_mesh();
362  const unsigned int dim = mesh.mesh_dimension();
363 
364  // Get a reference to the shell system object.
365  LinearImplicitSystem & system = es.get_system<LinearImplicitSystem> (system_name);
366 
367  // Get the shell parameters that we need during assembly.
368  const Real h = es.parameters.get<Real> ("thickness");
369  const Real E = es.parameters.get<Real> ("young's modulus");
370  const Real nu = es.parameters.get<Real> ("poisson ratio");
371  const Real q = es.parameters.get<Real> ("point load");
372  const bool distributed_load = es.parameters.get<bool> ("distributed load");
373 
374  // The membrane elastic matrix.
375  MyMatrix3d Hm;
376  Hm <<
377  1., nu, 0.,
378  nu, 1., 0.,
379  0., 0., 0.5 * (1-nu);
380  Hm *= h * E/(1-nu*nu);
381 
382  // The bending elastic matrix.
383  MyMatrix3d Hf;
384  Hf <<
385  1., nu, 0.,
386  nu, 1., 0.,
387  0., 0., 0.5 * (1-nu);
388  Hf *= h*h*h/12 * E/(1-nu*nu);
389 
390  // The shear elastic matrices.
391  MyMatrix2d Hc0 = MyMatrix2d::Identity();
392  Hc0 *= h * 5./6*E/(2*(1+nu));
393 
394  MyMatrix2d Hc1 = MyMatrix2d::Identity();
395  Hc1 *= h*h*h/12 * 5./6*E/(2*(1+nu));
396 
397  // Get the Finite Element type, this will be
398  // the same for all variables.
399  FEType fe_type = system.variable_type (0);
400 
401  std::unique_ptr<FEBase> fe (FEBase::build(dim, fe_type));
402  QGauss qrule (dim, SECOND); // Reduced integration, 2x2 gauss points (instead of 3x3 for full integration)
403  fe->attach_quadrature_rule (&qrule);
404 
405  // The element Jacobian * quadrature weight at each integration point.
406  const std::vector<Real> & JxW = fe->get_JxW();
407 
408  // The element shape function and its derivatives evaluated at the
409  // quadrature points.
410  const std::vector<RealGradient> & dxyzdxi = fe->get_dxyzdxi();
411  const std::vector<RealGradient> & dxyzdeta = fe->get_dxyzdeta();
412  const std::vector<RealGradient> & d2xyzdxi2 = fe->get_d2xyzdxi2();
413  const std::vector<RealGradient> & d2xyzdeta2 = fe->get_d2xyzdeta2();
414  const std::vector<RealGradient> & d2xyzdxideta = fe->get_d2xyzdxideta();
415  const std::vector<std::vector<Real>> & dphidxi = fe->get_dphidxi();
416  const std::vector<std::vector<Real>> & dphideta = fe->get_dphideta();
417  const std::vector<std::vector<Real>> & phi = fe->get_phi();
418 
419  // A reference to the DofMap object for this system. The DofMap
420  // object handles the index translation from node and element numbers
421  // to degree of freedom numbers.
422  const DofMap & dof_map = system.get_dof_map();
423 
424  // Define data structures to contain the element stiffness matrix.
426  DenseSubMatrix<Number> Ke_var[6][6] =
427  {
440  };
441 
442  // Define data structures to contain the element rhs vector.
444  DenseSubVector<Number> Fe_w(Fe);
445 
446  std::vector<dof_id_type> dof_indices;
447  std::vector<std::vector<dof_id_type>> dof_indices_var(6);
448 
449  // Now we will loop over all the elements in the mesh. We will
450  // compute the element matrix and right-hand-side contribution.
451  for (const auto & elem : mesh.active_local_element_ptr_range())
452  {
453  dof_map.dof_indices (elem, dof_indices);
454  for (unsigned int var=0; var<6; var++)
455  dof_map.dof_indices (elem, dof_indices_var[var], var);
456 
457  const unsigned int n_dofs = dof_indices.size();
458  const unsigned int n_var_dofs = dof_indices_var[0].size();
459 
460  // First compute element data at the nodes
461  std::vector<Point> nodes;
462  for (unsigned int i=0; i<elem->n_nodes(); ++i)
463  nodes.push_back(elem->reference_elem()->node_ref(i));
464  fe->reinit (elem, &nodes);
465 
466  //Store local orthonormal basis at the nodes
467  std::vector<MyMatrix3d> Qnode;
468  for (unsigned int i=0; i<elem->n_nodes(); ++i)
469  {
470  MyVector3d a1;
471  a1 << dxyzdxi[i](0), dxyzdxi[i](1), dxyzdxi[i](2);
472  MyVector3d a2;
473  a2 << dxyzdeta[i](0), dxyzdeta[i](1), dxyzdeta[i](2);
474  MyVector3d n;
475  n = a1.cross(a2);
476  n /= n.norm();
477 
478  Real nx = n(0);
479  Real ny = n(1);
480  Real C = n(2);
481  if (std::abs(1.+C)<1e-6)
482  {
483  MyMatrix3d Q;
484  Q <<
485  1, 0, 0,
486  0, -1, 0,
487  0, 0, -1;
488  Qnode.push_back(Q);
489  }
490  else
491  {
492  MyMatrix3d Q;
493  Q <<
494  C+1./(1+C)*ny*ny, -1./(1+C)*nx*ny, nx,
495  -1./(1+C)*nx*ny, C+1./(1+C)*nx*nx, ny,
496  -nx, -ny, C;
497  Qnode.push_back(Q);
498  }
499  }
500 
501  Ke.resize (n_dofs, n_dofs);
502  for (unsigned int var_i=0; var_i<6; var_i++)
503  for (unsigned int var_j=0; var_j<6; var_j++)
504  Ke_var[var_i][var_j].reposition (var_i*n_var_dofs, var_j*n_var_dofs, n_var_dofs, n_var_dofs);
505 
506  Fe.resize(n_dofs);
507  Fe_w.reposition(2*n_var_dofs,n_var_dofs);
508 
509  // Reinit element data at the regular Gauss quadrature points
510  fe->reinit (elem);
511 
512  // Now we will build the element matrix and right-hand-side.
513  for (unsigned int qp=0; qp<qrule.n_points(); ++qp)
514  {
515 
516  //Covariant basis at the quadrature point
517  MyVector3d a1;
518  a1 << dxyzdxi[qp](0), dxyzdxi[qp](1), dxyzdxi[qp](2);
519  MyVector3d a2;
520  a2 << dxyzdeta[qp](0), dxyzdeta[qp](1), dxyzdeta[qp](2);
521  MyVector3d n;
522  n = a1.cross(a2);
523  n /= n.norm();
524  MyMatrix3d F0;
525  F0 <<
526  a1(0), a2(0), n(0),
527  a1(1), a2(1), n(1),
528  a1(2), a2(2), n(2);
529 
530  //Contravariant basis
531  MyMatrix3d F0it;
532  F0it = F0.inverse().transpose();
533 
534  //Local orthonormal basis at the quadrature point
535  Real nx = n(0);
536  Real ny = n(1);
537  Real C = n(2);
538  MyMatrix3d Q;
539  if (std::abs(1.+C) < 1e-6)
540  {
541  Q <<
542  1, 0, 0,
543  0, -1, 0,
544  0, 0, -1;
545  }
546  else
547  {
548  Q <<
549  C+1./(1+C)*ny*ny, -1./(1+C)*nx*ny, nx,
550  -1./(1+C)*nx*ny, C+1./(1+C)*nx*nx, ny,
551  -nx, -ny, C;
552  }
553 
554  MyMatrix2d C0;
555  C0 = F0it.block<3,2>(0,0).transpose()*Q.block<3,2>(0,0);
556 
557  // Normal derivatives in reference coordinates
558  MyVector3d d2Xdxi2(d2xyzdxi2[qp](0), d2xyzdxi2[qp](1), d2xyzdxi2[qp](2));
559  MyVector3d d2Xdeta2(d2xyzdeta2[qp](0), d2xyzdeta2[qp](1), d2xyzdeta2[qp](2));
560  MyVector3d d2Xdxideta(d2xyzdxideta[qp](0), d2xyzdxideta[qp](1), d2xyzdxideta[qp](2));
561 
562  MyMatrix2d b;
563  b <<
564  n.dot(d2Xdxi2), n.dot(d2Xdxideta),
565  n.dot(d2Xdxideta), n.dot(d2Xdeta2);
566 
567  MyVector3d dndxi = -b(0,0)*F0it.col(0) - b(0,1)*F0it.col(1);
568  MyVector3d dndeta = -b(1,0)*F0it.col(0) - b(1,1)*F0it.col(1);
569 
570  MyMatrix2d bhat;
571  bhat <<
572  F0it.col(1).dot(dndeta), -F0it.col(0).dot(dndeta),
573  -F0it.col(1).dot(dndxi), F0it.col(0).dot(dndxi);
574 
575  MyMatrix2d bc;
576  bc = bhat*C0;
577 
578  // Mean curvature
579  Real H = 0.5*(dndxi.dot(F0it.col(0))+dndeta.dot(F0it.col(1)));
580 
581  // Loop over all pairs of nodes I,J.
582  for (unsigned int i=0; i<n_var_dofs; ++i)
583  {
584  // Matrix B0, zeroth order (through thickness) membrane-bending strain
585  Real C1i = dphidxi[i][qp]*C0(0,0) + dphideta[i][qp]*C0(1,0);
586  Real C2i = dphidxi[i][qp]*C0(0,1) + dphideta[i][qp]*C0(1,1);
587 
588  MyMatrixXd B0I(3, 5);
589  B0I = MyMatrixXd::Zero(3, 5);
590  B0I.block<1,3>(0,0) = C1i*Q.col(0).transpose();
591  B0I.block<1,3>(1,0) = C2i*Q.col(1).transpose();
592  B0I.block<1,3>(2,0) = C2i*Q.col(0).transpose()+C1i*Q.col(1).transpose();
593 
594  // Matrix B1, first order membrane-bending strain
595  Real bc1i = dphidxi[i][qp]*bc(0,0) + dphideta[i][qp]*bc(1,0);
596  Real bc2i = dphidxi[i][qp]*bc(0,1) + dphideta[i][qp]*bc(1,1);
597 
598  MyVector2d V1i(-Q.col(0).dot(Qnode[i].col(1)),
599  Q.col(0).dot(Qnode[i].col(0)));
600 
601  MyVector2d V2i(-Q.col(1).dot(Qnode[i].col(1)),
602  Q.col(1).dot(Qnode[i].col(0)));
603 
604  MyMatrixXd B1I(3,5);
605  B1I = MyMatrixXd::Zero(3,5);
606  B1I.block<1,3>(0,0) = bc1i*Q.col(0).transpose();
607  B1I.block<1,3>(1,0) = bc2i*Q.col(1).transpose();
608  B1I.block<1,3>(2,0) = bc2i*Q.col(0).transpose()+bc1i*Q.col(1).transpose();
609 
610  B1I.block<1,2>(0,3) = C1i*V1i.transpose();
611  B1I.block<1,2>(1,3) = C2i*V2i.transpose();
612  B1I.block<1,2>(2,3) = C2i*V1i.transpose()+C1i*V2i.transpose();
613 
614  // Matrix B2, second order membrane-bending strain
615  MyMatrixXd B2I(3,5);
616  B2I = MyMatrixXd::Zero(3,5);
617 
618  B2I.block<1,2>(0,3) = bc1i*V1i.transpose();
619  B2I.block<1,2>(1,3) = bc2i*V2i.transpose();
620  B2I.block<1,2>(2,3) = bc2i*V1i.transpose()+bc1i*V2i.transpose();
621 
622  // Matrix Bc0, zeroth order shear strain
623  MyMatrixXd Bc0I(2,5);
624  Bc0I = MyMatrixXd::Zero(2,5);
625  Bc0I.block<1,3>(0,0) = C1i*Q.col(2).transpose();
626  Bc0I.block<1,3>(1,0) = C2i*Q.col(2).transpose();
627  Bc0I.block<1,2>(0,3) = phi[i][qp]*V1i.transpose();
628  Bc0I.block<1,2>(1,3) = phi[i][qp]*V2i.transpose();
629 
630  // Matrix Bc1, first order shear strain
631  MyMatrixXd Bc1I(2,5);
632  Bc1I = MyMatrixXd::Zero(2,5);
633  Bc1I.block<1,3>(0,0) = bc1i*Q.col(2).transpose();
634  Bc1I.block<1,3>(1,0) = bc2i*Q.col(2).transpose();
635 
636  // Drilling dof (in-plane rotation)
637  MyVector2d BdxiI(dphidxi[i][qp],dphideta[i][qp]);
638  MyVector2d BdI = C0.transpose()*BdxiI;
639 
640  for (unsigned int j=0; j<n_var_dofs; ++j)
641  {
642 
643  // Matrix B0, zeroth order membrane-bending strain
644  Real C1j = dphidxi[j][qp]*C0(0,0) + dphideta[j][qp]*C0(1,0);
645  Real C2j = dphidxi[j][qp]*C0(0,1) + dphideta[j][qp]*C0(1,1);
646 
647  MyMatrixXd B0J(3,5);
648  B0J = MyMatrixXd::Zero(3,5);
649  B0J.block<1,3>(0,0) = C1j*Q.col(0).transpose();
650  B0J.block<1,3>(1,0) = C2j*Q.col(1).transpose();
651  B0J.block<1,3>(2,0) = C2j*Q.col(0).transpose()+C1j*Q.col(1).transpose();
652 
653  // Matrix B1, first order membrane-bending strain
654  Real bc1j = dphidxi[j][qp]*bc(0,0) + dphideta[j][qp]*bc(1,0);
655  Real bc2j = dphidxi[j][qp]*bc(0,1) + dphideta[j][qp]*bc(1,1);
656 
657  MyVector2d V1j(-Q.col(0).dot(Qnode[j].col(1)),
658  Q.col(0).dot(Qnode[j].col(0)));
659 
660  MyVector2d V2j(-Q.col(1).dot(Qnode[j].col(1)),
661  Q.col(1).dot(Qnode[j].col(0)));
662 
663  MyMatrixXd B1J(3,5);
664  B1J = MyMatrixXd::Zero(3,5);
665  B1J.block<1,3>(0,0) = bc1j*Q.col(0).transpose();
666  B1J.block<1,3>(1,0) = bc2j*Q.col(1).transpose();
667  B1J.block<1,3>(2,0) = bc2j*Q.col(0).transpose()+bc1j*Q.col(1).transpose();
668 
669  B1J.block<1,2>(0,3) = C1j*V1j.transpose();
670  B1J.block<1,2>(1,3) = C2j*V2j.transpose();
671  B1J.block<1,2>(2,3) = C2j*V1j.transpose()+C1j*V2j.transpose();
672 
673  // Matrix B2, second order membrane-bending strain
674  MyMatrixXd B2J(3,5);
675  B2J = MyMatrixXd::Zero(3,5);
676 
677  B2J.block<1,2>(0,3) = bc1j*V1j.transpose();
678  B2J.block<1,2>(1,3) = bc2j*V2j.transpose();
679  B2J.block<1,2>(2,3) = bc2j*V1j.transpose()+bc1j*V2j.transpose();
680 
681  // Matrix Bc0, zeroth order shear strain
682  MyMatrixXd Bc0J(2, 5);
683  Bc0J = MyMatrixXd::Zero(2,5);
684  Bc0J.block<1,3>(0,0) = C1j*Q.col(2).transpose();
685  Bc0J.block<1,3>(1,0) = C2j*Q.col(2).transpose();
686  Bc0J.block<1,2>(0,3) = phi[j][qp]*V1j.transpose();
687  Bc0J.block<1,2>(1,3) = phi[j][qp]*V2j.transpose();
688 
689  // Matrix Bc1, first order shear strain
690  MyMatrixXd Bc1J(2, 5);
691  Bc1J = MyMatrixXd::Zero(2,5);
692  Bc1J.block<1,3>(0,0) = bc1j*Q.col(2).transpose();
693  Bc1J.block<1,3>(1,0) = bc2j*Q.col(2).transpose();
694 
695  // Drilling dof
696  MyVector2d BdxiJ(dphidxi[j][qp], dphideta[j][qp]);
697  MyVector2d BdJ = C0.transpose()*BdxiJ;
698 
699  // The total stiffness matrix coupling the nodes
700  // I and J is a sum of membrane, bending and shear contributions.
701  MyMatrixXd local_KIJ(5, 5);
702  local_KIJ = JxW[qp] * (
703  B0I.transpose() * Hm * B0J
704  + B2I.transpose() * Hf * B0J
705  + B0I.transpose() * Hf * B2J
706  + B1I.transpose() * Hf * B1J
707  + 2*H * B0I.transpose() * Hf * B1J
708  + 2*H * B1I.transpose() * Hf * B0J
709  + Bc0I.transpose() * Hc0 * Bc0J
710  + Bc1I.transpose() * Hc1 * Bc1J
711  + 2*H * Bc0I.transpose() * Hc1 * Bc1J
712  + 2*H * Bc1I.transpose() * Hc1 * Bc0J
713  );
714 
715  // Going from 5 to 6 dofs to add drilling dof
716  MyMatrixXd full_local_KIJ(6, 6);
717  full_local_KIJ = MyMatrixXd::Zero(6, 6);
718  full_local_KIJ.block<5,5>(0,0)=local_KIJ;
719 
720  // Drilling dof stiffness contribution
721  //
722  // The explicit conversion to Real here is to work
723  // around an Eigen+boost::float128 incompatibility.
724  full_local_KIJ(5,5) = Real(Hf(0,0)*JxW[qp]*BdI.transpose()*BdJ);
725 
726  // Transform the stiffness matrix to global coordinates
727  MyMatrixXd global_KIJ(6,6);
728  MyMatrixXd TI(6,6);
729  TI = MyMatrixXd::Identity(6,6);
730  TI.block<3,3>(3,3) = Qnode[i].transpose();
731  MyMatrixXd TJ(6,6);
732  TJ = MyMatrixXd::Identity(6,6);
733  TJ.block<3,3>(3,3) = Qnode[j].transpose();
734  global_KIJ = TI.transpose()*full_local_KIJ*TJ;
735 
736  // Insert the components of the coupling stiffness
737  // matrix KIJ into the corresponding directional
738  // submatrices.
739  for (unsigned int k=0;k<6;k++)
740  for (unsigned int l=0;l<6;l++)
741  Ke_var[k][l](i,j) += global_KIJ(k,l);
742  }
743  }
744 
745  } // end of the quadrature point qp-loop
746 
747  if (distributed_load)
748  {
749  // Loop on shell faces
750  for (unsigned int shellface=0; shellface<2; shellface++)
751  {
752  std::vector<boundary_id_type> bids;
753  mesh.get_boundary_info().shellface_boundary_ids(elem, shellface, bids);
754 
755  for (std::size_t k=0; k<bids.size(); k++)
756  if (bids[k]==11) // sideset id for surface load
757  for (unsigned int qp=0; qp<qrule.n_points(); ++qp)
758  for (unsigned int i=0; i<n_var_dofs; ++i)
759  Fe_w(i) -= JxW[qp] * phi[i][qp];
760  }
761  }
762 
763  // The element matrix is now built for this element.
764  // Add it to the global matrix.
765 
766  dof_map.constrain_element_matrix_and_vector (Ke,Fe,dof_indices);
767 
768  system.matrix->add_matrix (Ke, dof_indices);
769  system.rhs->add_vector (Fe, dof_indices);
770 
771  }
772 
773  if (!distributed_load)
774  {
775  //Adding point load to the RHS
776 
777  //Pinch position
778  Point C(0, 3, 3);
779 
780  //Finish assembling rhs so we can set one value
781  system.rhs->close();
782 
783  for (const auto & node : mesh.node_ptr_range())
784  if (((*node) - C).norm() < 1e-3)
785  system.rhs->set(node->dof_number(0, 2, 0), -q/4);
786  }
787 
788 #else
789  // Avoid compiler warnings
790  libmesh_ignore(es, system_name);
791 #endif // defined(LIBMESH_HAVE_EIGEN) && defined(LIBMESH_ENABLE_SECOND_DERIVATIVES)
792 }
MyVector3d
Eigen::Matrix< libMesh::Real, 3, 1 > MyVector3d
Definition: miscellaneous_ex12.C:71
libMesh::Number
Real Number
Definition: libmesh_common.h:195
libMesh::dof_id_type
uint8_t dof_id_type
Definition: id_types.h:67
libMesh::Mesh
The Mesh class is a thin wrapper, around the ReplicatedMesh class by default.
Definition: mesh.h:50
libMesh::EquationSystems::add_system
virtual System & add_system(const std::string &system_type, const std::string &name)
Add the system of type system_type named name to the systems array.
Definition: equation_systems.C:345
libMesh::EquationSystems::get_mesh
const MeshBase & get_mesh() const
Definition: equation_systems.h:637
libMesh::MeshBase::read
virtual void read(const std::string &name, void *mesh_data=nullptr, bool skip_renumber_nodes_and_elements=false, bool skip_find_neighbors=false)=0
Interfaces for reading/writing a mesh to/from a file.
libMesh::MeshBase::get_boundary_info
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:132
libMesh::ExplicitSystem::rhs
NumericVector< Number > * rhs
The system matrix.
Definition: explicit_system.h:114
libMesh::QGauss
This class implements specific orders of Gauss quadrature.
Definition: quadrature_gauss.h:39
libMesh::DofMap::dof_indices
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Fills the vector di with the global degree of freedom indices for the element.
Definition: dof_map.C:1967
libMesh::DofMap::add_dirichlet_boundary
void add_dirichlet_boundary(const DirichletBoundary &dirichlet_boundary)
Adds a copy of the specified Dirichlet boundary to the system.
Definition: dof_map_constraints.C:4390
MyMatrixXd
Eigen::Matrix< libMesh::Real, Eigen::Dynamic, Eigen::Dynamic > MyMatrixXd
Definition: miscellaneous_ex12.C:72
libMesh::BoundaryInfo::shellface_boundary_ids
void shellface_boundary_ids(const Elem *const elem, const unsigned short int shellface, std::vector< boundary_id_type > &vec_to_fill) const
Definition: boundary_info.C:1133
libMesh::MeshBase::active_local_element_ptr_range
virtual SimpleRange< element_iterator > active_local_element_ptr_range()=0
libMesh::DenseSubMatrix
Defines a dense submatrix for use in Finite Element-type computations.
Definition: dense_submatrix.h:45
libMesh::MeshBase::write
virtual void write(const std::string &name)=0
libMesh::QBase::n_points
unsigned int n_points() const
Definition: quadrature.h:126
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::NumericVector::close
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
libMesh::EquationSystems::get_system
const T_sys & get_system(const std::string &name) const
Definition: equation_systems.h:757
libMesh::ParallelObject::comm
const Parallel::Communicator & comm() const
Definition: parallel_object.h:94
libMesh::DenseMatrix< Number >
libMesh::LinearImplicitSystem::solve
virtual void solve() override
Assembles & solves the linear system A*x=b.
Definition: linear_implicit_system.C:108
libMesh::default_solver_package
SolverPackage default_solver_package()
Definition: libmesh.C:993
MyMatrix3d
Eigen::Matrix< libMesh::Real, 3, 3 > MyMatrix3d
Definition: miscellaneous_ex13.C:71
libMesh::System::number
unsigned int number() const
Definition: system.h:2075
mesh
MeshBase & mesh
Definition: mesh_communication.C:1257
libMesh::MeshBase::mesh_dimension
unsigned int mesh_dimension() const
Definition: mesh_base.C:135
libMesh::DofMap::first_dof
dof_id_type first_dof(const processor_id_type proc) const
Definition: dof_map.h:650
libMesh::ExodusII_IO
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition: exodusII_io.h:51
libMesh::SECOND
Definition: enum_order.h:43
assemble_shell
void assemble_shell(EquationSystems &es, const std::string &system_name)
Definition: miscellaneous_ex13.C:350
dim
unsigned int dim
Definition: adaptivity_ex3.C:113
libMesh::DenseMatrix::resize
void resize(const unsigned int new_m, const unsigned int new_n)
Resize the matrix.
Definition: dense_matrix.h:822
libMesh::System::current_solution
Number current_solution(const dof_id_type global_dof_number) const
Definition: system.C:194
libMesh::TriangleWrapper::init
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
libMesh::DofObject::dof_number
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:956
libMesh::LOCAL_VARIABLE_ORDER
Definition: dirichlet_boundaries.h:62
libMesh::System::attach_assemble_function
void attach_assemble_function(void fptr(EquationSystems &es, const std::string &name))
Register a user function to use in assembling the system matrix and RHS.
Definition: system.C:1755
libMesh::NumericVector::add_vector
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices)
Computes , where v is a pointer and each dof_indices[i] specifies where to add value v[i].
Definition: numeric_vector.C:363
libMesh::MeshBase
This is the MeshBase class.
Definition: mesh_base.h:78
std::abs
MetaPhysicL::DualNumber< T, D > abs(const MetaPhysicL::DualNumber< T, D > &in)
MyMatrix3d
Eigen::Matrix< libMesh::Real, 3, 3 > MyMatrix3d
Definition: miscellaneous_ex12.C:69
libMesh::LinearSolver::set_solver_type
void set_solver_type(const SolverType st)
Sets the type of solver to use.
Definition: linear_solver.h:126
MyVector2d
Eigen::Matrix< libMesh::Real, 2, 1 > MyVector2d
Definition: miscellaneous_ex13.C:72
libMesh::LinearImplicitSystem::get_linear_solver
virtual LinearSolver< Number > * get_linear_solver() const override
Definition: linear_implicit_system.C:353
libMesh::MeshBase::node_ptr_range
virtual SimpleRange< node_iterator > node_ptr_range()=0
libMesh::ParallelObject::processor_id
processor_id_type processor_id() const
Definition: parallel_object.h:106
libMesh::libmesh_ignore
void libmesh_ignore(const Args &...)
Definition: libmesh_common.h:526
libMesh::FEGenericBase::build
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
libMesh::System::add_variable
unsigned int add_variable(const std::string &var, const FEType &type, const std::set< subdomain_id_type > *const active_subdomains=nullptr)
Adds the variable var to the list of variables for this system.
Definition: system.C:1069
libMesh::MeshBase::local_node_ptr_range
virtual SimpleRange< node_iterator > local_node_ptr_range()=0
libMesh::EquationSystems::init
virtual void init()
Initialize all the systems.
Definition: equation_systems.C:96
libMesh::Point
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:38
libMesh::ImplicitSystem::matrix
SparseMatrix< Number > * matrix
The system matrix.
Definition: implicit_system.h:393
libMesh::Node
A Node is like a Point, but with more information.
Definition: node.h:52
libMesh::LibMeshInit
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition: libmesh.h:83
libMesh::ZeroFunction
ConstFunction that simply returns 0.
Definition: zero_function.h:36
MyMatrixXd
Eigen::Matrix< libMesh::Real, Eigen::Dynamic, Eigen::Dynamic > MyMatrixXd
Definition: miscellaneous_ex13.C:74
libMesh::EquationSystems::print_info
void print_info(std::ostream &os=libMesh::out) const
Prints information about the equation systems, by default to libMesh::out.
Definition: equation_systems.C:1314
libMesh::EquationSystems
This is the EquationSystems class.
Definition: equation_systems.h:74
libMesh::Parameters::set
T & set(const std::string &)
Definition: parameters.h:460
libMesh::DofMap::constrain_element_matrix_and_vector
void constrain_element_matrix_and_vector(DenseMatrix< Number > &matrix, DenseVector< Number > &rhs, std::vector< dof_id_type > &elem_dofs, bool asymmetric_constraint_rows=true) const
Constrains the element matrix and vector.
Definition: dof_map.h:2034
libMesh::DenseSubVector< Number >
libMesh::MeshOutput::write_equation_systems
virtual void write_equation_systems(const std::string &, const EquationSystems &, const std::set< std::string > *system_names=nullptr)
This method implements writing a mesh with data to a specified file where the data is taken from the ...
Definition: mesh_output.C:31
libMesh::System::variable_type
const FEType & variable_type(const unsigned int i) const
Definition: system.h:2233
MyMatrix2d
Eigen::Matrix< libMesh::Real, 2, 2 > MyMatrix2d
Definition: miscellaneous_ex12.C:68
libMesh::DenseVector::resize
void resize(const unsigned int n)
Resize the vector.
Definition: dense_vector.h:355
libMesh::SparseMatrix::add_matrix
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols)=0
Add the full matrix dm to the SparseMatrix.
libMesh::TensorTools::norm_sq
T norm_sq(std::complex< T > a)
Definition: tensor_tools.h:85
libMesh::FEType
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:178
libMesh::System::point_value
Number point_value(unsigned int var, const Point &p, const bool insist_on_success=true, const NumericVector< Number > *sol=nullptr) const
Definition: system.C:1971
libMesh::NumericVector::set
virtual void set(const numeric_index_type i, const T value)=0
Sets v(i) = value.
libMesh::DofMap
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:176
MyVector3d
Eigen::Matrix< libMesh::Real, 3, 1 > MyVector3d
Definition: miscellaneous_ex13.C:73
libMesh::MeshBase::print_info
void print_info(std::ostream &os=libMesh::out) const
Prints relevant information about the mesh.
Definition: mesh_base.C:585
libMesh::DofObject::id
dof_id_type id() const
Definition: dof_object.h:767
libMesh::DirichletBoundary
This class allows one to associate Dirichlet boundary values with a given set of mesh boundary ids an...
Definition: dirichlet_boundaries.h:88
libMesh::System::variable_number
unsigned short int variable_number(const std::string &var) const
Definition: system.C:1232
MyMatrix2d
Eigen::Matrix< libMesh::Real, 2, 2 > MyMatrix2d
Definition: miscellaneous_ex13.C:70
F0
Definition: assembly.h:127
libMesh::DenseSubVector::reposition
void reposition(const unsigned int ioff, const unsigned int n)
Changes the location of the subvector in the parent vector.
Definition: dense_subvector.h:174
libMesh::System::get_dof_map
const DofMap & get_dof_map() const
Definition: system.h:2099
libMesh::LAGRANGE
Definition: enum_fe_family.h:36
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::LinearImplicitSystem
Manages consistently variables, degrees of freedom, coefficient vectors, matrices and linear solvers ...
Definition: linear_implicit_system.h:55
libMesh::SPARSELU
Definition: enum_solver_type.h:52
libMesh::MeshBase::query_node_ptr
virtual const Node * query_node_ptr(const dof_id_type i) const =0
libMesh::Parameters::get
const T & get(const std::string &) const
Definition: parameters.h:421
libMesh::out
OStreamProxy out
libMesh::EIGEN_SOLVERS
Definition: enum_solver_package.h:40
libMesh::DenseVector< Number >
main
int main(int argc, char **argv)
Definition: miscellaneous_ex13.C:87
MyVector2d
Eigen::Matrix< libMesh::Real, 2, 1 > MyVector2d
Definition: miscellaneous_ex12.C:70
libMesh::DofMap::end_dof
dof_id_type end_dof(const processor_id_type proc) const
Definition: dof_map.h:692
libMesh::EquationSystems::parameters
Parameters parameters
Data structure holding arbitrary parameters.
Definition: equation_systems.h:557