Hello,
I have stripped down my code to an example containing a neo-hookean
solid with displacement boundary conditions. See the attached patch. I
have just tested this with the default configure options. Any
suggestions for improvements are of course welcome.
While porting my code to the libmesh tensor classes, I discovered a
small bug in TypeTensor<T>::assign. See tensor.patch.
Regards
Robert
On Mon, Jan 09, 2012 at 09:02:29AM +1300, Mark Davies wrote:
> Hi Guys,
>
> I'm just getting started with the library and was wondering if there are
> any examples dealing with elastic solids? Thanks in advance for any
> suggestions.
>
> Regards,
> Mark
>
>
> ------------------------------------------------------------------------------
> Ridiculously easy VDI. With Citrix VDI-in-a-Box, you don't need a complex
> infrastructure or vast IT resources to deliver seamless, secure access to
> virtual desktops. With this all-in-one solution, easily deploy virtual
> desktops for less than the cost of PCs and save 60% on VDI infrastructure
> costs. Try it free! http://p.sf.net/sfu/Citrix-VDIinabox
> _______________________________________________
> Libmesh-users mailing list
> libmesh-us...@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/libmesh-users
Index: examples/fem_system/solid_ex2/solid.in
===================================================================
--- examples/fem_system/solid_ex2/solid.in (Revision 0)
+++ examples/fem_system/solid_ex2/solid.in (Revision 0)
@@ -0,0 +1,21 @@
+schedule/dt = 0.2
+solver/quiet = false
+solver/nonlinear/max_nonlinear_iterations = 100
+solver/nonlinear/relative_step_tolerance = 1.e-3
+solver/nonlinear/relative_residual_tolerance = 1.e-8
+solver/nonlinear/absolute_residual_tolerance = 1.e-8
+solver/quiet = false
+solver/nonlinear/require_reduction = false
+max_linear_iterations = 50000
+initial_linear_tolerance = 1.e-3
+assembly/use_symmetry = true
+bc/displacement = '0 0.0 0.0 0.0 5 nan nan -0.75'
+bc/displacement_penalty = 1e7
+material/neohooke/e_modulus = 10000.0
+material/neohooke/nu = 0.3
+mesh/generation/num_nodes = '4 4 4'
+mesh/generation/origin = '0.0 0.0 0.0'
+mesh/generation/size = '1.5 1.5 1.5'
+duration = 1.0
+output/frequency = 1
+results_directory = ./
Index: examples/fem_system/solid_ex2/solid_system.C
===================================================================
--- examples/fem_system/solid_ex2/solid_system.C (Revision 0)
+++ examples/fem_system/solid_ex2/solid_system.C (Revision 0)
@@ -0,0 +1,346 @@
+#include "getpot.h"
+
+#include "boundary_info.h"
+#include "fe_base.h"
+#include "fem_context.h"
+#include "dof_map.h"
+#include "mesh.h"
+#include "quadrature.h"
+
+#include "equation_systems.h"
+#include "transient_system.h"
+#include "steady_solver.h"
+#include "diff_solver.h"
+#include "newton_solver.h"
+
+#include "sparse_matrix.h"
+#include "numeric_vector.h"
+
+#include "nonlinear_neohooke_cc.h"
+#include "solid_system.h"
+
+// Bring in everything from the libMesh namespace
+using namespace libMesh;
+
+SolidSystem::SolidSystem(EquationSystems& es, const std::string& name,
+ const unsigned int number) :
+ FEMSystem(es, name, number) {
+
+ // Add a time solver. We are just looking at a steady state problem here.
+ this->time_solver = AutoPtr<TimeSolver>(new SteadySolver(*this));
+}
+
+void SolidSystem::save_initial_mesh() {
+ System & aux_sys = this->get_equation_systems().get_system("auxiliary");
+
+ const unsigned int dim = this->get_mesh().mesh_dimension();
+
+ // Loop over all nodes and copy the location from the current system to
+ // the auxiliary system.
+ const MeshBase::const_node_iterator nd_end =
+ this->get_mesh().local_nodes_end();
+ for (MeshBase::const_node_iterator nd = this->get_mesh().local_nodes_begin();
+ nd != nd_end; ++nd) {
+ const Node *node = *nd;
+ for (unsigned int d = 0; d < dim; ++d) {
+ unsigned int source_dof = node->dof_number(this->number(), var[d], 0);
+ unsigned int dest_dof = node->dof_number(aux_sys.number(), undefo_var[d],
+ 0);
+ Real value = this->current_local_solution->el(source_dof);
+ aux_sys.current_local_solution->set(dest_dof, value);
+ }
+ }
+}
+
+void SolidSystem::init_data() {
+ const unsigned int dim = this->get_mesh().mesh_dimension();
+
+ // Get the default order of the used elements. Assumption:
+ // Just one type of elements in the mesh.
+ Order order = this->get_mesh().elem(0)->default_order();
+
+ // Add the node positions as primary variables.
+ var[0] = this->add_variable("x", order);
+ var[1] = this->add_variable("y", order);
+ if (dim == 3)
+ var[2] = this->add_variable("z", order);
+ else
+ var[2] = var[1];
+
+ // Add variables for storing the initial mesh to an auxiliary system.
+ System& aux_sys = this->get_equation_systems().get_system("auxiliary");
+ undefo_var[0] = aux_sys.add_variable("undefo_x", order);
+ undefo_var[1] = aux_sys.add_variable("undefo_y", order);
+ undefo_var[2] = aux_sys.add_variable("undefo_z", order);
+
+ // Set the time stepping options
+ this->deltat = args("schedule/dt", 0.2);
+
+ // Do the parent's initialization after variables are defined
+ FEMSystem::init_data();
+
+// // Tell the system to march velocity forward in time, but
+// // leave p as a constraint only
+// this->time_evolving(var[0]);
+// this->time_evolving(var[1]);
+// if (dim == 3)
+// this->time_evolving(var[2]);
+
+ // Tell the system which variables are containing the node positions
+ set_mesh_system(this);
+
+ this->set_mesh_x_var(var[0]);
+ this->set_mesh_y_var(var[1]);
+ if (dim == 3)
+ this->set_mesh_z_var(var[2]);
+
+ // Fill the variables with the position of the nodes
+ this->mesh_position_get();
+
+ System::reinit();
+
+ // Set some options for the DiffSolver
+ DiffSolver &solver = *(this->time_solver->diff_solver().get());
+ solver.quiet = args("solver/quiet", false);
+ solver.max_nonlinear_iterations = args(
+ "solver/nonlinear/max_nonlinear_iterations", 100);
+ solver.relative_step_tolerance = args(
+ "solver/nonlinear/relative_step_tolerance", 1.e-3);
+ solver.relative_residual_tolerance = args(
+ "solver/nonlinear/relative_residual_tolerance", 1.e-8);
+ solver.absolute_residual_tolerance = args(
+ "solver/nonlinear/absolute_residual_tolerance", 1.e-8);
+ solver.verbose = !args("solver/quiet", false);
+
+ ((NewtonSolver&) solver).require_residual_reduction = args(
+ "solver/nonlinear/require_reduction", false);
+
+ // And the linear solver options
+ solver.max_linear_iterations = args("max_linear_iterations", 50000);
+ solver.initial_linear_tolerance = args("initial_linear_tolerance", 1.e-3);
+}
+
+void SolidSystem::update() {
+ System::update();
+ this->mesh_position_set();
+}
+
+void SolidSystem::init_context(DiffContext &context) {
+ FEMContext &c = libmesh_cast_ref<FEMContext&>(context);
+
+ // Pre-request all the data needed
+ c.element_fe_var[var[0]]->get_JxW();
+ c.element_fe_var[var[0]]->get_phi();
+ c.element_fe_var[var[0]]->get_dphi();
+ c.element_fe_var[var[0]]->get_xyz();
+
+ c.side_fe_var[var[0]]->get_JxW();
+ c.side_fe_var[var[0]]->get_phi();
+ c.side_fe_var[var[0]]->get_xyz();
+}
+
+/**
+ * Compute contribution from internal forces in elem_residual and contribution
from
+ * linearized internal forces (stiffness matrix) in elem_jacobian.
+ */
+bool SolidSystem::element_time_derivative(bool request_jacobian,
+ DiffContext &context) {
+ FEMContext &c = libmesh_cast_ref<FEMContext&>(context);
+
+ // First we get some references to cell-specific data that
+ // will be used to assemble the linear system.
+
+ // Element Jacobian * quadrature weights for interior integration
+ const std::vector<Real> &JxW = c.element_fe_var[var[0]]->get_JxW();
+
+ // The gradients of the shape functions at interior
+ // quadrature points.
+ const std::vector<std::vector<RealGradient> >& dphi =
+ c.element_fe_var[var[0]]->get_dphi();
+
+ // Dimension of the mesh
+ const unsigned int dim = this->get_mesh().mesh_dimension();
+
+ // The number of local degrees of freedom in each variable
+ const unsigned int n_u_dofs = c.dof_indices_var[var[0]].size();
+ libmesh_assert(n_u_dofs == c.dof_indices_var[var[1]].size());
+ if (dim == 3) {
+ libmesh_assert(n_u_dofs == c.dof_indices_var[var[2]].size());
+ }
+
+ unsigned int n_qpoints = c.element_qrule->n_points();
+
+ // Some matrices and vectors for storing the results of the constitutive
+ // law
+ DenseMatrix<Real> stiff;
+ DenseVector<Real> res;
+ VectorValue<Gradient> grad_u;
+
+ // Instantiate the constitutive law
+ NonlinearNeoHookeCurrentConfig material(dphi, args);
+
+ // Just calculate jacobian contribution when we need to
+ material.calculate_linearized_stiffness = request_jacobian;
+
+ // Get a reference to the auxiliary system
+ TransientExplicitSystem& aux_system =
this->get_equation_systems().get_system<
+ TransientExplicitSystem>("auxiliary");
+ std::vector<unsigned int> undefo_index;
+
+ // Assume symmetry of local stiffness matrices
+ bool use_symmetry = args("assembly/use_symmetry", false);
+
+ // Now we will build the element Jacobian and residual.
+ // This must be calculated at each quadrature point by
+ // summing the solution degree-of-freedom values by
+ // the appropriate weight functions.
+ // This class just takes care of the assembly. The matrix of
+ // the jacobian and the residual vector are provided by the
+ // constitutive formulation.
+
+ for (unsigned int qp = 0; qp != n_qpoints; qp++) {
+ // Compute the displacement gradient
+ grad_u(0) = grad_u(1) = grad_u(2) = 0;
+ for (unsigned int d = 0; d < dim; ++d) {
+ std::vector<Number> u_undefo;
+ aux_system.get_dof_map().dof_indices(c.elem, undefo_index,
undefo_var[d]);
+ aux_system.current_local_solution->get(undefo_index, u_undefo);
+ for (unsigned int l = 0; l != n_u_dofs; l++)
+ grad_u(d).add_scaled(dphi[l][qp], u_undefo[l]); // u_current(l)); // -
+ }
+
+ // initialize the constitutive formulation with the current displacement
+ // gradient
+ material.init_for_qp(grad_u, qp);
+
+ // Aquire, scale and assemble residual and stiffness
+ for (unsigned int i = 0; i < n_u_dofs; i++) {
+ res.resize(dim);
+ material.get_residual(res, i);
+ res.scale(JxW[qp]);
+ for (unsigned int ii = 0; ii < dim; ++ii) {
+ c.elem_subresiduals[ii]->operator ()(i) += res(ii);
+ }
+
+ if (request_jacobian && c.elem_solution_derivative) {
+ libmesh_assert(c.elem_solution_derivative == 1.0);
+ for (unsigned int j = (use_symmetry ? i : 0); j < n_u_dofs; j++) {
+ material.get_linearized_stiffness(stiff, i, j);
+ stiff.scale(JxW[qp]);
+ for (unsigned int ii = 0; ii < dim; ++ii) {
+ for (unsigned int jj = 0; jj < dim; ++jj) {
+ c.elem_subjacobians[ii][jj]->operator ()(i, j) += stiff(ii, jj);
+ if (use_symmetry && i != j) {
+ c.elem_subjacobians[ii][jj]->operator ()(j, i) += stiff(jj,
ii);
+ }
+ }
+ }
+ }
+ }
+ }
+ } // end of the quadrature point qp-loop
+
+ return request_jacobian;
+}
+
+bool SolidSystem::side_time_derivative(bool request_jacobian,
+ DiffContext &context) {
+ FEMContext &c = libmesh_cast_ref<FEMContext&>(context);
+
+ // Apply displacement boundary conditions with penalty method
+
+ // Get the current load step
+ Real ratio = this->get_equation_systems().parameters.get<Real>("progress")
+ + 0.001;
+
+ // The BC are stored in the simulation parameters as array containing
sequences of
+ // four numbers: Id of the side for the displacements and three values
describing the
+ // displacement. E.g.: bc/displacement = '5 nan nan -1.0'. This will move
all nodes of
+ // side 5 about 1.0 units down the z-axis while leaving all other directions
unrestricted
+
+ // Get number of BCs to enforce
+ unsigned int num_bc = args.vector_variable_size("bc/displacement");
+ if (num_bc % 4 != 0) {
+ libMesh::err
+ << "ERROR, Odd number of values in displacement boundary condition.\n"
+ << std::endl;
+ libmesh_error();
+ }
+ num_bc /= 4;
+
+ // Loop over all BCs
+ for (unsigned int nbc = 0; nbc < num_bc; nbc++) {
+ // Get IDs of the side for this BC
+ short int positive_boundary_id = args("bc/displacement", 1, nbc * 4);
+ // Check whether this element is on the current boundary
+ short int boundary_id = this->get_mesh().boundary_info->boundary_id(c.elem,
+ c.side);
+
+ // The current side is not on boundary to be restricted
+ if (boundary_id != positive_boundary_id)
+ continue;
+
+ // Read values from configuration file
+ Point diff_value;
+ for (unsigned int d = 0; d < c.dim; ++d) {
+ diff_value(d) = args("bc/displacement", NAN, nbc * 4 + 1 + d);
+ }
+ // Scale according to current load step
+ diff_value *= ratio;
+
+ Real penalty_number = args("bc/displacement_penalty", 1e7);
+
+ FEBase * fe = c.side_fe_var[var[0]];
+ const std::vector<std::vector<Real> > & phi = fe->get_phi();
+ const std::vector<Real>& JxW = fe->get_JxW();
+ const std::vector<Point>& coords = fe->get_xyz();
+
+ unsigned int n_x_dofs = c.dof_indices_var[this->var[0]].size();
+
+ // get mappings for dofs for auxiliary system for original mesh positions
+ const System & auxsys = this->get_equation_systems().get_system(
+ "auxiliary");
+ const DofMap & auxmap = auxsys.get_dof_map();
+ std::vector<unsigned int> undefo_dofs[3];
+ for (unsigned int d = 0; d < c.dim; ++d) {
+ auxmap.dof_indices(c.elem, undefo_dofs[d], undefo_var[d]);
+ }
+
+ for (unsigned int qp = 0; qp < c.side_qrule->n_points(); ++qp) {
+ // calculate coordinates of qp on undeformed mesh
+ Point orig_point;
+ for (unsigned int i = 0; i < n_x_dofs; ++i) {
+ for (unsigned int d = 0; d < c.dim; ++d) {
+ Real orig_val = auxsys.current_solution(undefo_dofs[d][i]);
+ orig_point(d) += phi[i][qp] * orig_val;
+ }
+ }
+
+ // Calculate displacement to be enforced.
+ Point diff = coords[qp] - orig_point - diff_value;
+
+ // Assemble
+ for (unsigned int i = 0; i < n_x_dofs; ++i) {
+ for (unsigned int d1 = 0; d1 < c.dim; ++d1) {
+ if (isnan(diff(d1)))
+ continue;
+ Real val = JxW[qp] * phi[i][qp] * diff(d1) * penalty_number;
+ c.elem_subresiduals[var[d1]]->operator ()(i) += val;
+ }
+ if (request_jacobian) {
+ for (unsigned int j = 0; j < n_x_dofs; ++j) {
+ for (unsigned int d1 = 0; d1 < c.dim; ++d1) {
+ if (isnan(diff(d1)))
+ continue;
+ Real val = JxW[qp] * phi[i][qp] * phi[j][qp] * penalty_number;
+ c.elem_subjacobians[var[d1]][var[d1]]->operator ()(i, j) += val;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return request_jacobian;
+}
+
Index: examples/fem_system/solid_ex2/nonlinear_neohooke_cc.C
===================================================================
--- examples/fem_system/solid_ex2/nonlinear_neohooke_cc.C (Revision 0)
+++ examples/fem_system/solid_ex2/nonlinear_neohooke_cc.C (Revision 0)
@@ -0,0 +1,150 @@
+#include "nonlinear_neohooke_cc.h"
+
+/**
+ * Return the inverse of the given TypeTensor. Algorithm taken from the tensor
classes
+ * of Ton van den Boogaard (http://tmku209.ctw.utwente.nl/~ton/tensor.html)
+ */
+template <typename T> TypeTensor<T> inv(const TypeTensor<T> &A ) {
+ double Sub11, Sub12, Sub13;
+ Sub11 = A._coords[4]*A._coords[8] - A._coords[5]*A._coords[7];
+ Sub12 = A._coords[3]*A._coords[8] - A._coords[6]*A._coords[5];
+ Sub13 = A._coords[3]*A._coords[7] - A._coords[6]*A._coords[4];
+ double detA = A._coords[0]*Sub11 - A._coords[1]*Sub12 + A._coords[2]*Sub13;
+ libmesh_assert( std::fabs(detA)>1.e-15 );
+
+ TypeTensor<T> Ainv(A);
+
+ Ainv._coords[0] = Sub11/detA;
+ Ainv._coords[1] =
(-A._coords[1]*A._coords[8]+A._coords[2]*A._coords[7])/detA;
+ Ainv._coords[2] = (
A._coords[1]*A._coords[5]-A._coords[2]*A._coords[4])/detA;
+ Ainv._coords[3] = -Sub12/detA;
+ Ainv._coords[4] = (
A._coords[0]*A._coords[8]-A._coords[2]*A._coords[6])/detA;
+ Ainv._coords[5] =
(-A._coords[0]*A._coords[5]+A._coords[2]*A._coords[3])/detA;
+ Ainv._coords[6] = Sub13/detA;
+ Ainv._coords[7] =
(-A._coords[0]*A._coords[7]+A._coords[1]*A._coords[6])/detA;
+ Ainv._coords[8] = (
A._coords[0]*A._coords[4]-A._coords[1]*A._coords[3])/detA;
+
+ return Ainv;
+}
+
+void NonlinearNeoHookeCurrentConfig::init_for_qp(VectorValue<Gradient> &
grad_u, unsigned int qp) {
+ this->current_qp = qp;
+ F.zero();
+ S.zero();
+
+ {
+ RealTensor invF;
+ invF.zero();
+ for (unsigned int i = 0; i < 3; ++i)
+ for (unsigned int j = 0; j < 3; ++j) {
+ invF(i, j) += grad_u(i)(j);
+ }
+ F.add(inv(invF));
+ }
+
+ if (F.det() < -TOLERANCE) {
+ std::cout << "detF < 0" << std::endl;
+ libmesh_error();
+ }
+
+ if (this->calculate_linearized_stiffness) {
+ this->calculate_tangent();
+ }
+
+ this->calculate_stress();
+}
+
+
+
+void NonlinearNeoHookeCurrentConfig::calculate_tangent() {
+ Real mu = E / (2 * (1 + nu));
+ Real lambda = E * nu / ((1 + nu) * (1 - 2 * nu));
+
+ Real detF = F.det();
+
+ C_mat.resize(6, 6);
+ for (unsigned int i = 0; i < 3; ++i) {
+ for (unsigned int j = 0; j < 3; ++j) {
+ if (i == j) {
+ C_mat(i, j) = 2 * mu + lambda;
+ C_mat(i + 3, j + 3) = mu - 0.5 * lambda * (detF
* detF - 1);
+ } else {
+ C_mat(i, j) = lambda * detF * detF;
+ }
+ }
+ }
+}
+
+
+void NonlinearNeoHookeCurrentConfig::calculate_stress() {
+
+ double mu = E / (2.0 * (1.0 + nu));
+ double lambda = E * nu / ((1 + nu) * (1 - 2 * nu));
+
+ Real detF = F.det();
+ RealTensor Ft = F.transpose();
+
+ RealTensor C = Ft * F;
+ RealTensor b = F * Ft;
+ RealTensor identity;
+ identity(0, 0) = 1.0; identity(1, 1) = 1.0; identity(2, 2) = 1.0;
+ RealTensor invC = inv(C);
+
+ S = 0.5 * lambda * (detF * detF - 1) * invC + mu * (identity - invC);
+
+ tau = (F * S) * Ft;
+ sigma = 1/detF * tau;
+}
+
+void NonlinearNeoHookeCurrentConfig::get_residual(DenseVector<Real> &
residuum, unsigned int & i) {
+ B_L.resize(3, 6);
+ DenseVector<Real> sigma_voigt(6);
+
+ this->build_b_0_mat(i, B_L);
+
+ tensor_to_voigt(sigma, sigma_voigt);
+
+ B_L.vector_mult(residuum, sigma_voigt);
+}
+
+void NonlinearNeoHookeCurrentConfig::tensor_to_voigt(const RealTensor &tensor,
DenseVector<Real> &vec) {
+ vec(0) = tensor(0, 0);
+ vec(1) = tensor(1, 1);
+ vec(2) = tensor(2, 2);
+ vec(3) = tensor(0, 1);
+ vec(4) = tensor(1, 2);
+ vec(5) = tensor(0, 2);
+
+}
+
+void
NonlinearNeoHookeCurrentConfig::get_linearized_stiffness(DenseMatrix<Real> &
stiffness, unsigned int & i, unsigned int & j) {
+ stiffness.resize(3, 3);
+
+ double G_IK = (sigma * dphi[i][current_qp]) * dphi[j][current_qp];
+ stiffness(0, 0) += G_IK;
+ stiffness(1, 1) += G_IK;
+ stiffness(2, 2) += G_IK;
+
+ B_L.resize(3, 6);
+ this->build_b_0_mat(i, B_L);
+ B_K.resize(3, 6);
+ this->build_b_0_mat(j, B_K);
+
+ B_L.right_multiply(C_mat);
+ B_L.right_multiply_transpose(B_K);
+ B_L *= 1/F.det();
+
+ stiffness += B_L;
+}
+
+void NonlinearNeoHookeCurrentConfig::build_b_0_mat(int i, DenseMatrix<Real>&
b_0_mat) {
+ for (unsigned int ii = 0; ii < 3; ++ii) {
+ b_0_mat(ii, ii) = dphi[i][current_qp](ii);
+ }
+ b_0_mat(0, 3) = dphi[i][current_qp](1);
+ b_0_mat(1, 3) = dphi[i][current_qp](0);
+ b_0_mat(1, 4) = dphi[i][current_qp](2);
+ b_0_mat(2, 4) = dphi[i][current_qp](1);
+ b_0_mat(0, 5) = dphi[i][current_qp](2);
+ b_0_mat(2, 5) = dphi[i][current_qp](0);
+}
Index: examples/fem_system/solid_ex2/solid_system.h
===================================================================
--- examples/fem_system/solid_ex2/solid_system.h (Revision 0)
+++ examples/fem_system/solid_ex2/solid_system.h (Revision 0)
@@ -0,0 +1,55 @@
+#ifndef SOLID_SYSTEM_H_
+#define SOLID_SYSTEM_H_
+
+#include "fem_system.h"
+#include "auto_ptr.h"
+
+using namespace libMesh;
+
+class SolidSystem: public FEMSystem {
+public:
+ // Constructor
+ SolidSystem(EquationSystems& es, const std::string& name,
+ const unsigned int number);
+
+ // System initialization
+ virtual void init_data();
+
+ // Context initialization
+ virtual void init_context(DiffContext &context);
+
+ // Element residual and jacobian calculations
+ virtual bool element_time_derivative(bool request_jacobian,
+ DiffContext& context);
+
+ // Contributions for adding boundary conditions
+ virtual bool side_time_derivative(bool request_jacobian,
+ DiffContext& context);
+
+ virtual bool eulerian_residual(bool, DiffContext &) {
+ return false;
+ }
+
+ // Simulation parameters
+ GetPot args;
+
+ // Custom Identifier
+ virtual std::string system_type() const {
+ return "Solid";
+ }
+
+ // override method to update mesh also
+ virtual void update();
+
+ // save the undeformed mesh to an auxiliary system
+ void save_initial_mesh();
+
+ // variable numbers of primary variables in the current system
+ unsigned int var[3];
+
+ // variable numbers of primary variables in auxiliary system (for accessing
the
+ // undeformed configuration)
+ unsigned int undefo_var[3];
+};
+
+#endif /* SOLID_SYSTEM_H_ */
Index: examples/fem_system/solid_ex2/nonlinear_neohooke_cc.h
===================================================================
--- examples/fem_system/solid_ex2/nonlinear_neohooke_cc.h (Revision 0)
+++ examples/fem_system/solid_ex2/nonlinear_neohooke_cc.h (Revision 0)
@@ -0,0 +1,65 @@
+#ifndef NONLINEAR_NEOHOOKE_CC_H_
+#define NONLINEAR_NEOHOOKE_CC_H_
+
+#include <dense_vector.h>
+#include <dense_matrix.h>
+#include <vector_value.h>
+#include <tensor_value.h>
+#include <getpot.h>
+
+/**
+ * This class implements a constitutive formulation for an Neo-Hookean elastic
solid
+ * in terms of the current configuration. This implementation is suitable for
computing
+ * large deformations. See e.g. "Nonlinear finite element methods" (P.
Wriggers, 2008,
+ * Springer) for details.
+ */
+class NonlinearNeoHookeCurrentConfig {
+public:
+ NonlinearNeoHookeCurrentConfig(
+ const std::vector<std::vector<RealGradient> >& dphi, GetPot& args) :
+ dphi(dphi) {
+ E = args("material/neohooke/e_modulus", 10000.0);
+ nu = args("material/neohooke/nu", 0.3);
+ }
+
+ /**
+ * Initialize the class for the given displacement gradient at the
+ * specified quadrature point.
+ */
+ void init_for_qp(VectorValue<Gradient> & grad_u, unsigned int qp);
+
+ /**
+ * Return the residual vector for the current state.
+ */
+ void get_residual(DenseVector<Real> & residuum, unsigned int & i);
+
+ /**
+ * Return the stiffness matrix for the current state.
+ */
+ void get_linearized_stiffness(DenseMatrix<Real> & stiffness,
+ unsigned int & i, unsigned int & j);
+
+ /**
+ * Flag to indicate if it is necessary to calculate values for stiffness
+ * matrix during initialization.
+ */
+ bool calculate_linearized_stiffness;
+private:
+ void build_b_0_mat(int i, DenseMatrix<Real>& b_l_mat);
+ void calculate_stress();
+ void calculate_tangent();
+ static void tensor_to_voigt(const RealTensor &tensor, DenseVector<Real>
&vec);
+
+ unsigned int current_qp;
+ const std::vector<std::vector<RealGradient> >& dphi;
+
+ DenseMatrix<Real> C_mat;
+ Real E;
+ Real nu;
+ RealTensor F, S, tau, sigma;
+ DenseMatrix<Real> B_L;
+ DenseMatrix<Real> B_K;
+};
+
+#endif /* NONLINEAR_NEOHOOKE_CC_H_ */
+
Index: examples/fem_system/solid_ex2/solid_ex2.C
===================================================================
--- examples/fem_system/solid_ex2/solid_ex2.C (Revision 0)
+++ examples/fem_system/solid_ex2/solid_ex2.C (Revision 0)
@@ -0,0 +1,137 @@
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <iostream>
+
+#include "libmesh.h"
+#include "mesh.h"
+#include "libmesh_logging.h"
+#include "getpot.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <time.h>
+#include <mesh_generation.h>
+#include <string_to_enum.h>
+#include <transient_system.h>
+#include <vtk_io.h>
+#include <numeric_vector.h>
+#include <time_solver.h>
+#include <equation_systems.h>
+
+using namespace libMesh;
+
+#include "solid_system.h"
+
+void setup(EquationSystems& systems, Mesh& mesh, GetPot& args) {
+
+ const unsigned int dim = mesh.mesh_dimension();
+ libmesh_assert (dim == 2 || dim == 3);
+
+ // Generating Mesh
+ ElemType eltype =
Utility::string_to_enum<ElemType>(args("mesh/generation/element_type", "hex8"));
+ int nx = args("mesh/generation/num_nodes", 4, 0);
+ int ny = args("mesh/generation/num_nodes", 4, 1);
+ int nz = args("mesh/generation/num_nodes", 4, 2);
+ double origx = args("mesh/generation/origin", -1.0, 0);
+ double origy = args("mesh/generation/origin", -1.0, 1);
+ double origz = args("mesh/generation/origin", 0.0, 2);
+ double sizex = args("mesh/generation/size", 2.0, 0);
+ double sizey = args("mesh/generation/size", 2.0, 1);
+ double sizez = args("mesh/generation/size", 2.0, 2);
+ MeshTools::Generation::build_cube(mesh, nx, ny, nz,
+ origx, origx+sizex, origy, origy+sizey, origz, origz+sizez, eltype);
+
+ // Creating Systems
+ SolidSystem& imms = systems.add_system<SolidSystem> ("solid");
+ imms.args = args;
+
+ // Build up auxiliary system
+ ExplicitSystem& aux_sys =
systems.add_system<TransientExplicitSystem>("auxiliary");
+
+ // Initialize the system
+ systems.parameters.set<unsigned int>("phase") = 0;
+ systems.init();
+
+ imms.save_initial_mesh();
+
+ // Fill global solution vector from local ones
+ aux_sys.reinit();
+}
+
+void run_timestepping(EquationSystems& systems, GetPot& args) {
+
+ TransientExplicitSystem& aux_system =
systems.get_system<TransientExplicitSystem>("auxiliary");
+
+ SolidSystem& solid_system = systems.get_system<SolidSystem>("solid");
+
+ AutoPtr<VTKIO> io = AutoPtr<VTKIO>(new VTKIO(systems.get_mesh()));
+
+ Real duration = args("duration", 1.0);
+
+ for (unsigned int t_step = 0; t_step < duration/solid_system.deltat;
t_step++) {
+ // Progress in current phase [0..1]
+ Real progress = t_step * solid_system.deltat / duration;
+ systems.parameters.set<Real>("progress") = progress;
+ systems.parameters.set<unsigned int>("step") = t_step;
+
+ // Update message
+
+ out << "===== Time Step " << std::setw(4) << t_step;
+ out << " (" << std::fixed << std::setprecision(2) << std::setw(6) <<
(progress*100.) << "%)";
+ out << ", time = " << std::setw(7) << solid_system.time;
+ out << " =====" << std::endl;
+
+ // Advance timestep in auxiliary system
+ aux_system.current_local_solution->close();
+ aux_system.old_local_solution->close();
+ *aux_system.older_local_solution = *aux_system.old_local_solution;
+ *aux_system.old_local_solution = *aux_system.current_local_solution;
+
+ out << "Solving Solid" << std::endl;
+ solid_system.solve();
+ aux_system.reinit();
+
+ // Carry out the adaptive mesh refinement/coarsening
+ out << "Doing a reinit of the equation systems" << std::endl;
+ systems.reinit();
+
+ if (t_step % args("output/frequency", 1) == 0) {
+ std::string result;
+ std::stringstream file_name;
+ file_name << args("results_directory", "./") << "fem_";
+ file_name << std::setw(6) << std::setfill('0') << t_step;
+ file_name << ".pvtu";
+
+
+ io->write_equation_systems(file_name.str(), systems);
+ }
+ // Advance to the next timestep in a transient problem
+ out << "Advancing to next step" << std::endl;
+ solid_system.time_solver->advance_timestep();
+ }
+}
+
+
+
+int main(int argc, char** argv) {
+
+ // Initialize libMesh and any dependent libraries
+ LibMeshInit init(argc, argv);
+
+ // read simulation parameters from file
+ GetPot args = GetPot("solid.in");
+
+ // Create System and Mesh
+ Mesh mesh(3);
+ EquationSystems systems(mesh);
+
+ // Create and set systems up
+ setup(systems, mesh, args);
+
+ // run the systems
+ run_timestepping(systems, args);
+
+ out << "Finished calculations" << std::endl;
+ return 0;
+}
+
Index: examples/fem_system/solid_ex2/Makefile
===================================================================
--- examples/fem_system/solid_ex2/Makefile (Revision 0)
+++ examples/fem_system/solid_ex2/Makefile (Revision 0)
@@ -0,0 +1,77 @@
+# $Id: Makefile 5000 2011-12-05 04:49:39Z knezed01 $
+
+
+# The location of the mesh library
+LIBMESH_DIR ?= ../../..
+
+# include the library options determined by configure. This will
+# set the variables INCLUDE and LIBS that we will need to build and
+# link with the library.
+include $(LIBMESH_DIR)/Make.common
+
+
+###############################################################################
+# File management. This is where the source, header, and object files are
+# defined
+
+#
+# source files
+srcfiles := $(wildcard *.C)
+
+#
+# object files
+objects := $(patsubst %.C, %.$(obj-suffix), $(srcfiles))
+###############################################################################
+
+
+
+.PHONY: clean clobber distclean
+
+###############################################################################
+# Target:
+#
+target := ./solid_ex1-$(METHOD)
+
+
+all:: $(target)
+
+# Production rules: how to make the target - depends on library configuration
+$(target): $(objects)
+ @echo "Linking "$@"..."
+ @$(libmesh_CXX) $(libmesh_CPPFLAGS) $(libmesh_CXXFLAGS) $(objects) -o
$@ $(libmesh_LIBS) $(libmesh_LDFLAGS)
+
+
+# Useful rules.
+clean:
+ @rm -f $(objects) *.*vtu *~
+
+clobber:
+ @$(MAKE) clean
+ @rm -f $(target) fem*.*vtu
+
+distclean:
+ @$(MAKE) clobber
+ @rm -f *.o *.g.o *.pg.o
+
+run: $(target)
+ @echo "***************************************************************"
+ @echo "* Running Example " $(LIBMESH_RUN) $(target) $(LIBMESH_OPTIONS)
+ @echo "***************************************************************"
+ @echo " "
+ @$(LIBMESH_RUN) $(target) $(LIBMESH_OPTIONS)
+ @echo " "
+ @echo "***************************************************************"
+ @echo "* Done Running Example " $(target)
+ @echo "***************************************************************"
+
+# include the dependency list
+include .depend
+
+
+#
+# Dependencies
+#
+.depend: $(srcfiles) $(LIBMESH_DIR)/include/*/*.h
+ @$(perl) $(LIBMESH_DIR)/contrib/bin/make_dependencies.pl -I. $(foreach
i, $(wildcard $(LIBMESH_DIR)/include/*), -I$(i)) "-S\$$(obj-suffix)"
$(srcfiles) > .depend
+
+###############################################################################
Index: include/numerics/type_tensor.h
===================================================================
--- include/numerics/type_tensor.h (Revision 5026)
+++ include/numerics/type_tensor.h (Arbeitskopie)
@@ -408,7 +408,7 @@
inline
void TypeTensor<T>::assign (const TypeTensor<T2> &p)
{
- for (unsigned int i=0; i<LIBMESH_DIM; i++)
+ for (unsigned int i=0; i<LIBMESH_DIM*LIBMESH_DIM; i++)
_coords[i] = p._coords[i];
}
------------------------------------------------------------------------------
Write once. Port to many.
Get the SDK and tools to simplify cross-platform app development. Create
new or port existing apps to sell to consumers worldwide. Explore the
Intel AppUpSM program developer opportunity. appdeveloper.intel.com/join
http://p.sf.net/sfu/intel-appdev
_______________________________________________
Libmesh-devel mailing list
Libmesh-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libmesh-devel