From 8efb45a191ea9bae079f235522400f3b26751c0e Mon Sep 17 00:00:00 2001 From: Dmitri Naumov <dmitri.naumov@ufz.de> Date: Wed, 5 Apr 2017 13:13:35 +0200 Subject: [PATCH] [PL] SD; Add material forces computation. --- ProcessLib/Deformation/MaterialForces.h | 187 ++++++++++++++++++ .../LocalAssemblerInterface.h | 2 + .../SmallDeformation/SmallDeformationFEM.h | 37 ++++ .../SmallDeformationProcess-impl.h | 23 +++ .../SmallDeformationProcess.h | 3 + 5 files changed, 252 insertions(+) create mode 100644 ProcessLib/Deformation/MaterialForces.h diff --git a/ProcessLib/Deformation/MaterialForces.h b/ProcessLib/Deformation/MaterialForces.h new file mode 100644 index 00000000000..7545e2a18ef --- /dev/null +++ b/ProcessLib/Deformation/MaterialForces.h @@ -0,0 +1,187 @@ +/** + * \file + * + * \copyright + * Copyright (c) 2012-2017, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#pragma once + +#include <cassert> +#include <vector> + +#include "MathLib/LinAlg/Eigen/EigenMapTools.h" +#include "NumLib/DOF/DOFTableUtil.h" +#include "ProcessLib/Deformation/GMatrix.h" +#include "ProcessLib/Parameter/SpatialPosition.h" +#include "ProcessLib/Utils/InitShapeMatrices.h" + +namespace ProcessLib +{ +namespace SmallDeformation +{ +struct MaterialForcesInterface +{ + virtual std::vector<double> const& getMaterialForces( + std::vector<double> const& local_x, + std::vector<double>& nodal_values) = 0; + + virtual ~MaterialForcesInterface() = default; +}; + +template <int DisplacementDim, typename ShapeFunction, + typename ShapeMatricesType, typename NodalForceVectorType, + typename NodalDisplacementVectorType, typename GradientVectorType, + typename GradientMatrixType, typename IPData, + typename IntegrationMethod> +std::vector<double> const& getMaterialForces( + std::vector<double> const& local_x, std::vector<double>& nodal_values, + IntegrationMethod const& _integration_method, IPData const& _ip_data, + MeshLib::Element const& element, bool const is_axially_symmetric) +{ + unsigned const n_integration_points = + _integration_method.getNumberOfPoints(); + + nodal_values.clear(); + auto local_b = MathLib::createZeroedVector<NodalDisplacementVectorType>( + nodal_values, ShapeFunction::NPOINTS * DisplacementDim); + + for (unsigned ip = 0; ip < n_integration_points; ip++) + { + auto const& sigma = _ip_data[ip].sigma; + auto const& N = _ip_data[ip].N; + auto const& dNdx = _ip_data[ip].dNdx; + + auto const& psi = _ip_data[ip].free_energy_density; + + auto const x_coord = + interpolateXCoordinate<ShapeFunction, ShapeMatricesType>( + element, _ip_data[ip].N); + + // For the 2D case the 33-component is needed (and the four entries + // of the non-symmetric matrix); In 3d there are nine entries. + GradientMatrixType G( + DisplacementDim * DisplacementDim + (DisplacementDim == 2 ? 1 : 0), + ShapeFunction::NPOINTS * DisplacementDim); + Deformation::computeGMatrix<DisplacementDim, ShapeFunction::NPOINTS>( + dNdx, G, is_axially_symmetric, N, x_coord); + + GradientVectorType const grad_u = + G * Eigen::Map<NodalForceVectorType const>( + local_x.data(), ShapeFunction::NPOINTS * DisplacementDim); + + GradientVectorType eshelby_stress; + eshelby_stress.setZero(DisplacementDim * DisplacementDim + + (DisplacementDim == 2 ? 1 : 0)); + + if (DisplacementDim == 3) + { + eshelby_stress[0] = eshelby_stress[DisplacementDim + 1] = + eshelby_stress[8] = psi; + + eshelby_stress[0] -= sigma[0] * grad_u[0] + + sigma[3] / std::sqrt(2) * grad_u[3] + + sigma[5] / std::sqrt(2) * grad_u[6]; + + eshelby_stress[1] -= sigma[3] / std::sqrt(2) * grad_u[0] + + sigma[1] * grad_u[3] + + sigma[4] / std::sqrt(2) * grad_u[6]; + + eshelby_stress[2] -= sigma[5] / std::sqrt(2) * grad_u[0] + + sigma[4] / std::sqrt(2) * grad_u[3] + + sigma[2] * grad_u[6]; + + eshelby_stress[3] -= sigma[0] * grad_u[1] + + sigma[3] / std::sqrt(2) * grad_u[4] + + sigma[5] / std::sqrt(2) * grad_u[7]; + + eshelby_stress[4] -= sigma[3] / std::sqrt(2) * grad_u[1] + + sigma[1] * grad_u[4] + + sigma[4] / std::sqrt(2) * grad_u[7]; + + eshelby_stress[5] -= sigma[5] / std::sqrt(2) * grad_u[1] + + sigma[4] / std::sqrt(2) * grad_u[4] + + sigma[2] * grad_u[7]; + + eshelby_stress[6] -= sigma[0] * grad_u[2] + + sigma[3] / std::sqrt(2) * grad_u[5] + + sigma[5] / std::sqrt(2) * grad_u[8]; + + eshelby_stress[7] -= sigma[3] / std::sqrt(2) * grad_u[2] + + sigma[1] * grad_u[5] + + sigma[4] / std::sqrt(2) * grad_u[8]; + + eshelby_stress[8] -= sigma[5] / std::sqrt(2) * grad_u[2] + + sigma[4] / std::sqrt(2) * grad_u[5] + + sigma[2] * grad_u[8]; + } + else if (DisplacementDim == 2) + { + eshelby_stress[0] = eshelby_stress[DisplacementDim + 1] = + eshelby_stress[4] = psi; + + eshelby_stress[0] -= + sigma[0] * grad_u[0] + sigma[3] / std::sqrt(2) * grad_u[2]; + + eshelby_stress[1] -= + sigma[3] / std::sqrt(2) * grad_u[0] + sigma[1] * grad_u[2]; + + eshelby_stress[2] -= + sigma[0] * grad_u[1] + sigma[3] / std::sqrt(2) * grad_u[3]; + + eshelby_stress[3] -= + sigma[3] / std::sqrt(2) * grad_u[1] + sigma[1] * grad_u[3]; + + // for axial-symmetric case the following is not zero in general + eshelby_stress[4] -= sigma[2] * grad_u[4]; + } + else + OGS_FATAL( + "Material forces not implemented for displacement dimension " + "other than 2 and 3."); + + auto const& w = _ip_data[ip].integration_weight; + local_b += G.transpose() * eshelby_stress * w; + } + + return nodal_values; +} + +template <typename LocalAssemblerInterface> +void writeMaterialForces( + MeshLib::PropertyVector<double>& material_forces, + std::vector<std::unique_ptr<LocalAssemblerInterface>> const& + local_assemblers, + NumLib::LocalToGlobalIndexMap const& local_to_global_index_map, + GlobalVector const& x) +{ + DBUG("Compute material forces for small deformation process."); + + // Material forces + std::fill(std::begin(material_forces), std::end(material_forces), 0); + + GlobalExecutor::executeDereferenced( + [](const std::size_t mesh_item_id, + LocalAssemblerInterface& local_assembler, + const NumLib::LocalToGlobalIndexMap& dof_table, + GlobalVector const& x, + std::vector<double>& node_values) { + auto const indices = NumLib::getIndices(mesh_item_id, dof_table); + std::vector<double> local_data; + auto const local_x = x.get(indices); + + local_assembler.getMaterialForces(local_x, local_data); + + assert(local_data.size() == indices.size()); + for (std::size_t i = 0; i < indices.size(); ++i) + node_values[indices[i]] += local_data[i]; + }, + local_assemblers, local_to_global_index_map, x, material_forces); +} + +} // namespace SmallDeformation +} // namespace ProcessLib diff --git a/ProcessLib/SmallDeformation/LocalAssemblerInterface.h b/ProcessLib/SmallDeformation/LocalAssemblerInterface.h index cfc6e7b4f71..fd8347879d7 100644 --- a/ProcessLib/SmallDeformation/LocalAssemblerInterface.h +++ b/ProcessLib/SmallDeformation/LocalAssemblerInterface.h @@ -13,6 +13,7 @@ #include "MaterialLib/SolidModels/MechanicsBase.h" #include "NumLib/Extrapolation/ExtrapolatableElement.h" +#include "ProcessLib/Deformation/MaterialForces.h" #include "ProcessLib/LocalAssemblerInterface.h" namespace ProcessLib @@ -22,6 +23,7 @@ namespace SmallDeformation template <int DisplacementDim> struct SmallDeformationLocalAssemblerInterface : public ProcessLib::LocalAssemblerInterface, + public MaterialForcesInterface, public NumLib::ExtrapolatableElement { virtual std::vector<double> const& getIntPtFreeEnergyDensity( diff --git a/ProcessLib/SmallDeformation/SmallDeformationFEM.h b/ProcessLib/SmallDeformation/SmallDeformationFEM.h index 48c31de3f9b..e454243f6b7 100644 --- a/ProcessLib/SmallDeformation/SmallDeformationFEM.h +++ b/ProcessLib/SmallDeformation/SmallDeformationFEM.h @@ -18,6 +18,7 @@ #include "NumLib/Fem/FiniteElement/TemplateIsoparametric.h" #include "NumLib/Fem/ShapeMatrixPolicy.h" #include "ProcessLib/Deformation/BMatrixPolicy.h" +#include "ProcessLib/Deformation/GMatrixPolicy.h" #include "ProcessLib/Deformation/LinearBMatrix.h" #include "ProcessLib/LocalAssemblerInterface.h" #include "ProcessLib/LocalAssemblerTraits.h" @@ -93,6 +94,10 @@ public: using NodalDisplacementVectorType = typename BMatricesType::NodalForceVectorType; + using GMatricesType = GMatrixPolicyType<ShapeFunction, DisplacementDim>; + using GradientVectorType = typename GMatricesType::GradientVectorType; + using GradientMatrixType = typename GMatricesType::GradientMatrixType; + SmallDeformationLocalAssembler(SmallDeformationLocalAssembler const&) = delete; SmallDeformationLocalAssembler(SmallDeformationLocalAssembler&&) = delete; @@ -249,6 +254,35 @@ public: } } + void postTimestepConcrete(std::vector<double> const& /*local_x*/) override + { + unsigned const n_integration_points = + _integration_method.getNumberOfPoints(); + + for (unsigned ip = 0; ip < n_integration_points; ip++) + { + auto& ip_data = _ip_data[ip]; + + // Update free energy density needed for material forces. + ip_data.free_energy_density = + ip_data.solid_material.computeFreeEnergyDensity( + ip_data.eps, ip_data.sigma, + *ip_data.material_state_variables); + } + } + + std::vector<double> const& getMaterialForces( + std::vector<double> const& local_x, + std::vector<double>& nodal_values) override + { + return ProcessLib::SmallDeformation::getMaterialForces< + DisplacementDim, ShapeFunction, ShapeMatricesType, + typename BMatricesType::NodalForceVectorType, + NodalDisplacementVectorType, GradientVectorType, + GradientMatrixType>(local_x, nodal_values, _integration_method, + _ip_data, _element, _is_axially_symmetric); + } + Eigen::Map<const Eigen::RowVectorXd> getShapeMatrix( const unsigned integration_point) const override { @@ -259,6 +293,9 @@ public: } std::vector<double> const& getIntPtFreeEnergyDensity( + const double /*t*/, + GlobalVector const& /*current_solution*/, + NumLib::LocalToGlobalIndexMap const& /*dof_table*/, std::vector<double>& cache) const override { cache.clear(); diff --git a/ProcessLib/SmallDeformation/SmallDeformationProcess-impl.h b/ProcessLib/SmallDeformation/SmallDeformationProcess-impl.h index b962917fbfb..2c495666b10 100644 --- a/ProcessLib/SmallDeformation/SmallDeformationProcess-impl.h +++ b/ProcessLib/SmallDeformation/SmallDeformationProcess-impl.h @@ -38,6 +38,8 @@ SmallDeformationProcess<DisplacementDim>::SmallDeformationProcess( { _nodal_forces = MeshLib::getOrCreateMeshProperty<double>( mesh, "NodalForces", MeshLib::MeshItemType::Node, DisplacementDim); + _material_forces = MeshLib::getOrCreateMeshProperty<double>( + mesh, "MaterialForces", MeshLib::MeshItemType::Node, DisplacementDim); } template <int DisplacementDim> @@ -69,6 +71,13 @@ void SmallDeformationProcess<DisplacementDim>::initializeConcreteProcess( NumLib::ComponentOrder::BY_LOCATION); _nodal_forces->resize(DisplacementDim * mesh.getNumberOfNodes()); + _material_forces->resize(DisplacementDim * mesh.getNumberOfNodes()); + + Base::_secondary_variables.addSecondaryVariable( + "free_energy_density", + makeExtrapolator(1, getExtrapolator(), _local_assemblers, + &LocalAssemblerInterface::getIntPtFreeEnergyDensity)); + Base::_secondary_variables.addSecondaryVariable( "sigma", makeExtrapolator( @@ -248,5 +257,19 @@ void SmallDeformationProcess<DisplacementDim>::preTimestepConcreteProcess( *_local_to_global_index_map, x, t, dt); } +template <int DisplacementDim> +void SmallDeformationProcess<DisplacementDim>::postTimestepConcreteProcess( + GlobalVector const& x) +{ + DBUG("PostTimestep SmallDeformationProcess."); + + GlobalExecutor::executeMemberOnDereferenced( + &LocalAssemblerInterface::postTimestep, _local_assemblers, + *_local_to_global_index_map, x); + + ProcessLib::SmallDeformation::writeMaterialForces( + *_material_forces, _local_assemblers, *_local_to_global_index_map, x); +} + } // namespace SmallDeformation } // namespace ProcessLib diff --git a/ProcessLib/SmallDeformation/SmallDeformationProcess.h b/ProcessLib/SmallDeformation/SmallDeformationProcess.h index a1bb0e86a61..534ac993ee0 100644 --- a/ProcessLib/SmallDeformation/SmallDeformationProcess.h +++ b/ProcessLib/SmallDeformation/SmallDeformationProcess.h @@ -61,6 +61,8 @@ private: void preTimestepConcreteProcess(GlobalVector const& x, double const t, double const dt) override; + void postTimestepConcreteProcess(GlobalVector const& x) override; + private: SmallDeformationProcessData<DisplacementDim> _process_data; @@ -69,6 +71,7 @@ private: std::unique_ptr<NumLib::LocalToGlobalIndexMap> _local_to_global_index_map_single_component; MeshLib::PropertyVector<double>* _nodal_forces = nullptr; + MeshLib::PropertyVector<double>* _material_forces = nullptr; }; extern template class SmallDeformationProcess<2>; -- GitLab