34 #include "libmesh/libmesh.h"
35 #include "libmesh/mesh.h"
36 #include "libmesh/linear_implicit_system.h"
37 #include "libmesh/equation_systems.h"
38 #include "libmesh/fe.h"
39 #include "libmesh/quadrature.h"
40 #include "libmesh/node.h"
41 #include "libmesh/elem.h"
42 #include "libmesh/dof_map.h"
43 #include "libmesh/quadrature_gauss.h"
44 #include "libmesh/vector_value.h"
45 #include "libmesh/tensor_value.h"
46 #include "libmesh/dense_matrix.h"
47 #include "libmesh/dense_submatrix.h"
48 #include "libmesh/dense_vector.h"
49 #include "libmesh/dense_subvector.h"
50 #include "libmesh/sparse_matrix.h"
51 #include "libmesh/numeric_vector.h"
52 #include "libmesh/exodusII_io.h"
53 #include "libmesh/dirichlet_boundaries.h"
54 #include "libmesh/zero_function.h"
55 #include "libmesh/linear_solver.h"
56 #include "libmesh/getpot.h"
57 #include "libmesh/enum_solver_package.h"
58 #include "libmesh/enum_solver_type.h"
59 #include "libmesh/parallel.h"
62 #ifdef LIBMESH_HAVE_EIGEN
63 #include "libmesh/ignore_warnings.h"
64 # include <Eigen/Dense>
65 #include "libmesh/restore_warnings.h"
72 typedef Eigen::Matrix<libMesh::Real, Eigen::Dynamic, Eigen::Dynamic>
MyMatrixXd;
82 const std::string & system_name);
85 int main (
int argc,
char ** argv)
91 libmesh_example_requires (3 == LIBMESH_DIM,
"3D support");
94 #ifndef LIBMESH_ENABLE_DIRICHLET
95 libmesh_example_requires(
false,
"--enable-dirichlet");
99 #ifndef LIBMESH_HAVE_EXODUS_API
100 libmesh_example_requires (
false,
"ExodusII support");
103 #ifndef LIBMESH_ENABLE_SECOND_DERIVATIVES
104 libmesh_example_requires (
false,
"second derivatives enabled");
109 #ifndef LIBMESH_HAVE_EIGEN
110 libmesh_example_requires(
false,
"--enable-eigen");
115 #ifndef LIBMESH_HAVE_XDR
116 libmesh_example_requires (
false,
"XDR support");
121 #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
122 libmesh_example_requires (
false,
"--disable-quadruple-precision");
126 GetPot command_line (argc, argv);
127 int distributed_load = 0;
128 if (command_line.search(1,
"-distributed_load"))
129 distributed_load = command_line.next(distributed_load);
179 equation_systems.
parameters.
set<
bool>(
"distributed load") = (distributed_load != 0);
189 #ifdef LIBMESH_ENABLE_DIRICHLET
192 std::set<boundary_id_type> boundary_ids;
193 boundary_ids.insert(7);
194 unsigned int variables[] = {2, 3, 4};
201 std::vector<unsigned int>(variables, variables+3), zf,
207 std::set<boundary_id_type> boundary_ids;
208 boundary_ids.insert(8);
209 unsigned int variables[] = {1, 3, 5};
214 std::vector<unsigned int>(variables, variables+3), zf,
220 std::set<boundary_id_type> boundary_ids;
221 boundary_ids.insert(9);
222 unsigned int variables[] = {0, 4, 5};
227 std::vector<unsigned int>(variables, variables+3), zf,
233 std::set<boundary_id_type> boundary_ids;
234 boundary_ids.insert(10);
235 unsigned int variables[] = {0, 2, 4};
240 std::vector<unsigned int>(variables, variables+3), zf,
244 #endif // LIBMESH_ENABLE_DIRICHLET
247 equation_systems.
init();
267 if (distributed_load==0)
270 Node * node_C =
nullptr;
271 Point point_C(0, 3, 3);
273 Real nearest_dist_sq = std::numeric_limits<Real>::max();
281 if (dist_sq < nearest_dist_sq)
283 nearest_dist_sq = dist_sq;
289 unsigned int minrank = 0;
290 system.
comm().minloc(nearest_dist_sq, minrank);
296 nearest_node_id = node_C->
id();
297 system.
comm().broadcast(nearest_node_id, minrank);
314 system.
comm().sum(w);
317 Number w_C_bar = -E*h*w/q;
318 const Real w_C_bar_analytic = 164.24;
322 libMesh::out <<
"z-displacement of the point C: " << w_C_bar << std::endl;
323 libMesh::out <<
"Analytic solution: " << w_C_bar_analytic << std::endl;
327 Point point_D(0, 0, 3);
332 const Real v_D_bar_analytic = 4.114;
336 libMesh::out <<
"y-displacement of the point D: " << v_D_bar << std::endl;
337 libMesh::out <<
"Analytic solution: " << v_D_bar_analytic << std::endl;
349 const std::string & system_name)
356 #if defined(LIBMESH_HAVE_EIGEN) && defined(LIBMESH_ENABLE_SECOND_DERIVATIVES)
359 libmesh_assert_equal_to (system_name,
"Shell");
373 const bool distributed_load = es.
parameters.
get<
bool> (
"distributed load");
380 0., 0., 0.5 * (1-nu);
381 Hm *= h * E/(1-nu*nu);
388 0., 0., 0.5 * (1-nu);
389 Hf *= h*h*h/12 * E/(1-nu*nu);
393 Hc0 *= h * 5./6*E/(2*(1+nu));
396 Hc1 *= h*h*h/12 * 5./6*E/(2*(1+nu));
404 fe->attach_quadrature_rule (&qrule);
407 const std::vector<Real> & JxW = fe->get_JxW();
411 const std::vector<RealGradient> & dxyzdxi = fe->get_dxyzdxi();
412 const std::vector<RealGradient> & dxyzdeta = fe->get_dxyzdeta();
414 const std::vector<RealGradient> & d2xyzdxi2 = fe->get_d2xyzdxi2();
415 const std::vector<RealGradient> & d2xyzdeta2 = fe->get_d2xyzdeta2();
416 const std::vector<RealGradient> & d2xyzdxideta = fe->get_d2xyzdxideta();
417 const std::vector<std::vector<Real>> & dphidxi = fe->get_dphidxi();
418 const std::vector<std::vector<Real>> & dphideta = fe->get_dphideta();
419 const std::vector<std::vector<Real>> & phi = fe->get_phi();
448 std::vector<dof_id_type> dof_indices;
449 std::vector<std::vector<dof_id_type>> dof_indices_var(6);
456 for (
unsigned int var=0; var<6; var++)
457 dof_map.
dof_indices (elem, dof_indices_var[var], var);
459 const unsigned int n_dofs = dof_indices.size();
460 const unsigned int n_var_dofs = dof_indices_var[0].size();
463 std::vector<Point> nodes;
464 for (
auto i : elem->node_index_range())
465 nodes.push_back(elem->reference_elem()->node_ref(i));
466 fe->reinit (elem, &nodes);
469 MyVector3d X1(elem->node_ref(0)(0), elem->node_ref(0)(1), elem->node_ref(0)(2));
470 MyVector3d X2(elem->node_ref(1)(0), elem->node_ref(1)(1), elem->node_ref(1)(2));
471 MyVector3d X3(elem->node_ref(2)(0), elem->node_ref(2)(1), elem->node_ref(2)(2));
472 MyVector3d X4(elem->node_ref(3)(0), elem->node_ref(3)(1), elem->node_ref(3)(2));
475 std::vector<MyMatrix3d> F0node;
476 std::vector<MyMatrix3d> Qnode;
477 for (
auto i : elem->node_index_range())
480 a1 << dxyzdxi[i](0), dxyzdxi[i](1), dxyzdxi[i](2);
482 a2 << dxyzdeta[i](0), dxyzdeta[i](1), dxyzdeta[i](2);
491 F0node.push_back(
F0);
509 C+1./(1+C)*ny*ny, -1./(1+C)*nx*ny, nx,
510 -1./(1+C)*nx*ny, C+1./(1+C)*nx*nx, ny,
516 Ke.
resize (n_dofs, n_dofs);
517 for (
unsigned int var_i=0; var_i<6; var_i++)
518 for (
unsigned int var_j=0; var_j<6; var_j++)
519 Ke_var[var_i][var_j].reposition (var_i*n_var_dofs, var_j*n_var_dofs, n_var_dofs, n_var_dofs);
528 for (
unsigned int qp=0; qp<qrule.n_points(); ++qp)
533 a1 << dxyzdxi[qp](0), dxyzdxi[qp](1), dxyzdxi[qp](2);
535 a2 << dxyzdeta[qp](0), dxyzdeta[qp](1), dxyzdeta[qp](2);
547 F0it =
F0.inverse().transpose();
564 C+1./(1+C)*ny*ny, -1./(1+C)*nx*ny, nx,
565 -1./(1+C)*nx*ny, C+1./(1+C)*nx*nx, ny,
570 C0 = F0it.block<3,2>(0,0).transpose()*Q.block<3,2>(0,0);
573 MyVector3d d2Xdxi2(d2xyzdxi2[qp](0), d2xyzdxi2[qp](1), d2xyzdxi2[qp](2));
574 MyVector3d d2Xdeta2(d2xyzdeta2[qp](0), d2xyzdeta2[qp](1), d2xyzdeta2[qp](2));
575 MyVector3d d2Xdxideta(d2xyzdxideta[qp](0), d2xyzdxideta[qp](1), d2xyzdxideta[qp](2));
580 n.dot(d2Xdxi2), n.dot(d2Xdxideta),
581 n.dot(d2Xdxideta), n.dot(d2Xdeta2);
583 MyVector3d dndxi = -b(0,0)*F0it.col(0) - b(0,1)*F0it.col(1);
584 MyVector3d dndeta = -b(1,0)*F0it.col(0) - b(1,1)*F0it.col(1);
588 F0it.col(1).dot(dndeta), -F0it.col(0).dot(dndeta),
589 -F0it.col(1).dot(dndxi), F0it.col(0).dot(dndxi);
595 Real H = 0.5*(dndxi.dot(F0it.col(0))+dndeta.dot(F0it.col(1)));
598 Real xi = qrule.qp(qp)(0);
599 Real eta = qrule.qp(qp)(1);
609 MyVector3d nA1 = 0.5*(Qnode[0].col(2)+Qnode[1].col(2));
612 MyVector3d nB2 = 0.5*(Qnode[1].col(2)+Qnode[2].col(2));
615 MyVector3d nA2 = 0.5*(Qnode[2].col(2)+Qnode[3].col(2));
618 MyVector3d nB1 = 0.5*(Qnode[3].col(2)+Qnode[0].col(2));
629 MyVector2d AS1A1(-aA1.dot(Qnode[0].col(1)), aA1.dot(Qnode[0].col(0)));
630 MyVector2d AS2A1(-aA1.dot(Qnode[1].col(1)), aA1.dot(Qnode[1].col(0)));
634 MyVector2d AS1A2(-aA2.dot(Qnode[3].col(1)), aA2.dot(Qnode[3].col(0)));
635 MyVector2d AS2A2(-aA2.dot(Qnode[2].col(1)), aA2.dot(Qnode[2].col(0)));
639 MyVector2d AS1B1(-aB1.dot(Qnode[0].col(1)), aB1.dot(Qnode[0].col(0)));
640 MyVector2d AS2B1(-aB1.dot(Qnode[3].col(1)), aB1.dot(Qnode[3].col(0)));
644 MyVector2d AS1B2(-aB2.dot(Qnode[1].col(1)), aB2.dot(Qnode[1].col(0)));
645 MyVector2d AS2B2(-aB2.dot(Qnode[2].col(1)), aB2.dot(Qnode[2].col(0)));
650 std::vector<MyMatrixXd> Bcnode;
653 Bc.block<1,3>(0,0) = -nA1.transpose();
654 Bc.block<1,2>(0,3) = AS1A1.transpose();
655 Bc.block<1,3>(1,0) = -nB1.transpose();
656 Bc.block<1,2>(1,3) = AS1B1.transpose();
657 Bcnode.push_back(Bc);
659 Bc.block<1,3>(0,0) = nA1.transpose();
660 Bc.block<1,2>(0,3) = AS2A1.transpose();
661 Bc.block<1,3>(1,0) = -nB2.transpose();
662 Bc.block<1,2>(1,3) = AS1B2.transpose();
663 Bcnode.push_back(Bc);
665 Bc.block<1,3>(0,0) = nA2.transpose();
666 Bc.block<1,2>(0,3) = AS2A2.transpose();
667 Bc.block<1,3>(1,0) = nB2.transpose();
668 Bc.block<1,2>(1,3) = AS2B2.transpose();
669 Bcnode.push_back(Bc);
671 Bc.block<1,3>(0,0) = -nA2.transpose();
672 Bc.block<1,2>(0,3) = AS1A2.transpose();
673 Bc.block<1,3>(1,0) = nB1.transpose();
674 Bc.block<1,2>(1,3) = AS2B1.transpose();
675 Bcnode.push_back(Bc);
678 for (
unsigned int i=0; i<n_var_dofs; ++i)
681 Real C1i = dphidxi[i][qp]*C0(0,0) + dphideta[i][qp]*C0(1,0);
682 Real C2i = dphidxi[i][qp]*C0(0,1) + dphideta[i][qp]*C0(1,1);
685 B0I = MyMatrixXd::Zero(3, 5);
686 B0I.block<1,3>(0,0) = C1i*Q.col(0).transpose();
687 B0I.block<1,3>(1,0) = C2i*Q.col(1).transpose();
688 B0I.block<1,3>(2,0) = C2i*Q.col(0).transpose()+C1i*Q.col(1).transpose();
691 Real bc1i = dphidxi[i][qp]*bc(0,0) + dphideta[i][qp]*bc(1,0);
692 Real bc2i = dphidxi[i][qp]*bc(0,1) + dphideta[i][qp]*bc(1,1);
694 MyVector2d V1i(-Q.col(0).dot(Qnode[i].col(1)),
695 Q.col(0).dot(Qnode[i].col(0)));
697 MyVector2d V2i(-Q.col(1).dot(Qnode[i].col(1)),
698 Q.col(1).dot(Qnode[i].col(0)));
701 B1I = MyMatrixXd::Zero(3,5);
702 B1I.block<1,3>(0,0) = bc1i*Q.col(0).transpose();
703 B1I.block<1,3>(1,0) = bc2i*Q.col(1).transpose();
704 B1I.block<1,3>(2,0) = bc2i*Q.col(0).transpose()+bc1i*Q.col(1).transpose();
706 B1I.block<1,2>(0,3) = C1i*V1i.transpose();
707 B1I.block<1,2>(1,3) = C2i*V2i.transpose();
708 B1I.block<1,2>(2,3) = C2i*V1i.transpose()+C1i*V2i.transpose();
712 B2I = MyMatrixXd::Zero(3,5);
714 B2I.block<1,2>(0,3) = bc1i*V1i.transpose();
715 B2I.block<1,2>(1,3) = bc2i*V2i.transpose();
716 B2I.block<1,2>(2,3) = bc2i*V1i.transpose()+bc1i*V2i.transpose();
720 Bc0I = C0.transpose()*Bcnode[i];
724 Bc1I = bc.transpose()*Bcnode[i];
727 MyVector2d BdxiI(dphidxi[i][qp],dphideta[i][qp]);
730 for (
unsigned int j=0; j<n_var_dofs; ++j)
734 Real C1j = dphidxi[j][qp]*C0(0,0) + dphideta[j][qp]*C0(1,0);
735 Real C2j = dphidxi[j][qp]*C0(0,1) + dphideta[j][qp]*C0(1,1);
738 B0J = MyMatrixXd::Zero(3,5);
739 B0J.block<1,3>(0,0) = C1j*Q.col(0).transpose();
740 B0J.block<1,3>(1,0) = C2j*Q.col(1).transpose();
741 B0J.block<1,3>(2,0) = C2j*Q.col(0).transpose()+C1j*Q.col(1).transpose();
744 Real bc1j = dphidxi[j][qp]*bc(0,0) + dphideta[j][qp]*bc(1,0);
745 Real bc2j = dphidxi[j][qp]*bc(0,1) + dphideta[j][qp]*bc(1,1);
747 MyVector2d V1j(-Q.col(0).dot(Qnode[j].col(1)),
748 Q.col(0).dot(Qnode[j].col(0)));
750 MyVector2d V2j(-Q.col(1).dot(Qnode[j].col(1)),
751 Q.col(1).dot(Qnode[j].col(0)));
754 B1J = MyMatrixXd::Zero(3,5);
755 B1J.block<1,3>(0,0) = bc1j*Q.col(0).transpose();
756 B1J.block<1,3>(1,0) = bc2j*Q.col(1).transpose();
757 B1J.block<1,3>(2,0) = bc2j*Q.col(0).transpose()+bc1j*Q.col(1).transpose();
759 B1J.block<1,2>(0,3) = C1j*V1j.transpose();
760 B1J.block<1,2>(1,3) = C2j*V2j.transpose();
761 B1J.block<1,2>(2,3) = C2j*V1j.transpose()+C1j*V2j.transpose();
765 B2J = MyMatrixXd::Zero(3,5);
767 B2J.block<1,2>(0,3) = bc1j*V1j.transpose();
768 B2J.block<1,2>(1,3) = bc2j*V2j.transpose();
769 B2J.block<1,2>(2,3) = bc2j*V1j.transpose()+bc1j*V2j.transpose();
773 Bc0J = C0.transpose()*Bcnode[j];
777 Bc1J = bc.transpose()*Bcnode[j];
780 MyVector2d BdxiJ(dphidxi[j][qp], dphideta[j][qp]);
786 local_KIJ = JxW[qp] * (
787 B0I.transpose() * Hm * B0J
788 + B2I.transpose() * Hf * B0J
789 + B0I.transpose() * Hf * B2J
790 + B1I.transpose() * Hf * B1J
791 + 2*H * B0I.transpose() * Hf * B1J
792 + 2*H * B1I.transpose() * Hf * B0J
793 + Bc0I.transpose() * Hc0 * Bc0J
794 + Bc1I.transpose() * Hc1 * Bc1J
795 + 2*H * Bc0I.transpose() * Hc1 * Bc1J
796 + 2*H * Bc1I.transpose() * Hc1 * Bc0J
801 full_local_KIJ = MyMatrixXd::Zero(6, 6);
802 full_local_KIJ.block<5,5>(0,0)=local_KIJ;
813 full_local_KIJ(5,5) =
Real(Hf(0,0)*JxW[qp]*BdI.transpose()*BdJ);
818 TI = MyMatrixXd::Identity(6,6);
819 TI.block<3,3>(3,3) = Qnode[i].transpose();
821 TJ = MyMatrixXd::Identity(6,6);
822 TJ.block<3,3>(3,3) = Qnode[j].transpose();
823 global_KIJ = TI.transpose()*full_local_KIJ*TJ;
828 for (
unsigned int k=0;k<6;k++)
829 for (
unsigned int l=0;l<6;l++)
830 Ke_var[k][l](i,j) += global_KIJ(k,l);
836 if (distributed_load)
839 for (
unsigned int shellface=0; shellface<2; shellface++)
841 std::vector<boundary_id_type> bids;
844 for (std::size_t k=0; k<bids.size(); k++)
846 for (
unsigned int qp=0; qp<qrule.n_points(); ++qp)
847 for (
unsigned int i=0; i<n_var_dofs; ++i)
848 Fe_w(i) -= JxW[qp] * phi[i][qp];
862 if (!distributed_load)
873 if (((*node) - C).norm() < 1e-3)
874 system.
rhs->
set(node->dof_number(0, 2, 0), -q/4);
880 #endif // defined(LIBMESH_HAVE_EIGEN) && defined(LIBMESH_ENABLE_SECOND_DERIVATIVES)