swh:1:snp:f521c49ab17ef7db6ec70b2430e1ed203f50383f
Tip revision: 1b7e7280c4f98dcbe72868eaa94a6fa42ca72034 authored by Wenqing Wang on 02 July 2021, 08:54:51 UTC
[web/CTest/M] added the description of the test with heterogeneous reference temperature
[web/CTest/M] added the description of the test with heterogeneous reference temperature
Tip revision: 1b7e728
ThermoMechanicalPhaseFieldFEM.h
/**
* \file
* \copyright
* Copyright (c) 2012-2021, 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 <memory>
#include <vector>
#include "LocalAssemblerInterface.h"
#include "MaterialLib/SolidModels/LinearElasticIsotropic.h"
#include "MaterialLib/SolidModels/LinearElasticIsotropicPhaseField.h"
#include "MaterialLib/SolidModels/SelectSolidConstitutiveRelation.h"
#include "MathLib/LinAlg/Eigen/EigenMapTools.h"
#include "NumLib/Fem/FiniteElement/TemplateIsoparametric.h"
#include "NumLib/Fem/InitShapeMatrices.h"
#include "NumLib/Fem/ShapeMatrixPolicy.h"
#include "ParameterLib/SpatialPosition.h"
#include "ProcessLib/Deformation/BMatrixPolicy.h"
#include "ProcessLib/Deformation/LinearBMatrix.h"
#include "ProcessLib/Utils/SetOrGetIntegrationPointData.h"
#include "ThermoMechanicalPhaseFieldProcessData.h"
namespace ProcessLib
{
namespace ThermoMechanicalPhaseField
{
template <typename BMatricesType, typename ShapeMatrixType, int DisplacementDim>
struct IntegrationPointData final
{
explicit IntegrationPointData(
MaterialLib::Solids::MechanicsBase<DisplacementDim> const&
solid_material)
: solid_material(solid_material),
material_state_variables(
solid_material.createMaterialStateVariables())
{
}
typename ShapeMatrixType::NodalRowVectorType N;
typename ShapeMatrixType::GlobalDimNodalMatrixType dNdx;
typename BMatricesType::KelvinVectorType eps, eps_prev;
typename BMatricesType::KelvinVectorType eps_m;
typename BMatricesType::KelvinVectorType sigma_tensile, sigma_compressive,
sigma;
double strain_energy_tensile, elastic_energy;
typename ShapeMatrixType::GlobalDimVectorType heatflux;
MaterialLib::Solids::MechanicsBase<DisplacementDim> const& solid_material;
std::unique_ptr<typename MaterialLib::Solids::MechanicsBase<
DisplacementDim>::MaterialStateVariables>
material_state_variables;
typename BMatricesType::KelvinMatrixType C_tensile, C_compressive;
double integration_weight;
void pushBackState()
{
eps_prev = eps;
material_state_variables->pushBackState();
}
using Invariants = MathLib::KelvinVector::Invariants<
MathLib::KelvinVector::kelvin_vector_dimensions(DisplacementDim)>;
template <typename DisplacementVectorType>
void updateConstitutiveRelation(double const t,
ParameterLib::SpatialPosition const& x,
double const /*dt*/,
DisplacementVectorType const& /*u*/,
double const alpha,
double const delta_T,
double const degradation)
{
eps_m.noalias() = eps - alpha * delta_T * Invariants::identity2;
auto linear_elastic_mp =
static_cast<MaterialLib::Solids::LinearElasticIsotropic<
DisplacementDim> const&>(solid_material)
.getMaterialProperties();
auto const bulk_modulus = linear_elastic_mp.bulk_modulus(t, x);
auto const mu = linear_elastic_mp.mu(t, x);
std::tie(sigma, sigma_tensile, C_tensile, C_compressive,
strain_energy_tensile, elastic_energy) =
MaterialLib::Solids::Phasefield::calculateDegradedStress<
DisplacementDim>(degradation, bulk_modulus, mu, eps_m);
}
EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
};
/// Used for the extrapolation of the integration point values. It is ordered
/// (and stored) by integration points.
template <typename ShapeMatrixType>
struct SecondaryData
{
std::vector<ShapeMatrixType, Eigen::aligned_allocator<ShapeMatrixType>> N;
};
template <typename ShapeFunction, typename IntegrationMethod,
int DisplacementDim>
class ThermoMechanicalPhaseFieldLocalAssembler
: public ThermoMechanicalPhaseFieldLocalAssemblerInterface
{
private:
static constexpr int temperature_index = 0;
static constexpr int temperature_size = ShapeFunction::NPOINTS;
static constexpr int displacement_index =
temperature_index + temperature_size;
static constexpr int displacement_size =
ShapeFunction::NPOINTS * DisplacementDim;
static constexpr int phasefield_index =
displacement_index + displacement_size;
static constexpr int phasefield_size = ShapeFunction::NPOINTS;
public:
using ShapeMatricesType =
ShapeMatrixPolicyType<ShapeFunction, DisplacementDim>;
// Types for displacement.
// (Higher order elements = ShapeFunction).
using ShapeMatrices = typename ShapeMatricesType::ShapeMatrices;
using BMatricesType = BMatrixPolicyType<ShapeFunction, DisplacementDim>;
using NodalForceVectorType = typename BMatricesType::NodalForceVectorType;
using GlobalDimVectorType = typename ShapeMatricesType::GlobalDimVectorType;
using TemperatureVector =
typename ShapeMatricesType::template VectorType<temperature_size>;
using DeformationVector =
typename ShapeMatricesType::template VectorType<displacement_size>;
using PhaseFieldVector =
typename ShapeMatricesType::template VectorType<phasefield_size>;
using IpData =
IntegrationPointData<BMatricesType, ShapeMatricesType, DisplacementDim>;
ThermoMechanicalPhaseFieldLocalAssembler(
ThermoMechanicalPhaseFieldLocalAssembler const&) = delete;
ThermoMechanicalPhaseFieldLocalAssembler(
ThermoMechanicalPhaseFieldLocalAssembler&&) = delete;
ThermoMechanicalPhaseFieldLocalAssembler(
MeshLib::Element const& e,
std::size_t const /*local_matrix_size*/,
bool const is_axially_symmetric,
unsigned const integration_order,
ThermoMechanicalPhaseFieldProcessData<DisplacementDim>& process_data,
int const mechanics_related_process_id,
int const phase_field_process_id,
int const heat_conduction_process_id)
: _process_data(process_data),
_integration_method(integration_order),
_element(e),
_is_axially_symmetric(is_axially_symmetric),
_mechanics_related_process_id(mechanics_related_process_id),
_phase_field_process_id(phase_field_process_id),
_heat_conduction_process_id(heat_conduction_process_id)
{
unsigned const n_integration_points =
_integration_method.getNumberOfPoints();
_ip_data.reserve(n_integration_points);
_secondary_data.N.resize(n_integration_points);
auto& solid_material =
MaterialLib::Solids::selectSolidConstitutiveRelation(
_process_data.solid_materials,
_process_data.material_ids,
e.getID());
if (!dynamic_cast<MaterialLib::Solids::LinearElasticIsotropic<
DisplacementDim> const*>(&solid_material))
{
OGS_FATAL(
"For phasefield process only linear elastic solid material "
"support is implemented.");
}
auto const shape_matrices =
NumLib::initShapeMatrices<ShapeFunction, ShapeMatricesType,
DisplacementDim>(e, is_axially_symmetric,
_integration_method);
ParameterLib::SpatialPosition x_position;
x_position.setElementID(_element.getID());
for (unsigned ip = 0; ip < n_integration_points; ip++)
{
_ip_data.emplace_back(solid_material);
auto& ip_data = _ip_data[ip];
ip_data.integration_weight =
_integration_method.getWeightedPoint(ip).getWeight() *
shape_matrices[ip].integralMeasure * shape_matrices[ip].detJ;
static const int kelvin_vector_size =
MathLib::KelvinVector::kelvin_vector_dimensions(
DisplacementDim);
ip_data.eps.setZero(kelvin_vector_size);
ip_data.eps_prev.resize(kelvin_vector_size);
ip_data.eps_m.setZero(kelvin_vector_size);
ip_data.C_tensile.setZero(kelvin_vector_size, kelvin_vector_size);
ip_data.C_compressive.setZero(kelvin_vector_size,
kelvin_vector_size);
ip_data.sigma_tensile.setZero(kelvin_vector_size);
ip_data.sigma_compressive.setZero(kelvin_vector_size);
ip_data.heatflux.setZero(DisplacementDim);
ip_data.sigma.setZero(kelvin_vector_size);
ip_data.strain_energy_tensile = 0.0;
ip_data.elastic_energy = 0.0;
ip_data.N = shape_matrices[ip].N;
ip_data.dNdx = shape_matrices[ip].dNdx;
_secondary_data.N[ip] = shape_matrices[ip].N;
}
}
void assemble(double const /*t*/, double const /*dt*/,
std::vector<double> const& /*local_x*/,
std::vector<double> const& /*local_xdot*/,
std::vector<double>& /*local_M_data*/,
std::vector<double>& /*local_K_data*/,
std::vector<double>& /*local_rhs_data*/) override
{
OGS_FATAL(
"ThermoMechanicalPhaseFieldLocalAssembler: assembly without "
"Jacobian is not implemented.");
}
void assembleWithJacobianForStaggeredScheme(
double const t, double const dt, Eigen::VectorXd const& local_x,
Eigen::VectorXd const& local_xdot, const double dxdot_dx,
const double dx_dx, int const process_id,
std::vector<double>& local_M_data, std::vector<double>& local_K_data,
std::vector<double>& local_b_data,
std::vector<double>& local_Jac_data) override;
void initializeConcrete() override
{
unsigned const n_integration_points =
_integration_method.getNumberOfPoints();
for (unsigned ip = 0; ip < n_integration_points; ip++)
{
_ip_data[ip].pushBackState();
}
}
void postTimestepConcrete(Eigen::VectorXd const& /*local_x*/,
double const /*t*/, double const /*dt*/) override
{
unsigned const n_integration_points =
_integration_method.getNumberOfPoints();
for (unsigned ip = 0; ip < n_integration_points; ip++)
{
_ip_data[ip].pushBackState();
}
}
Eigen::Map<const Eigen::RowVectorXd> getShapeMatrix(
const unsigned integration_point) const override
{
auto const& N = _secondary_data.N[integration_point];
// assumes N is stored contiguously in memory
return Eigen::Map<const Eigen::RowVectorXd>(N.data(), N.size());
}
private:
std::vector<double> const& getIntPtSigma(
const double /*t*/,
std::vector<GlobalVector*> const& /*x*/,
std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
std::vector<double>& cache) const override
{
return ProcessLib::getIntegrationPointKelvinVectorData<DisplacementDim>(
_ip_data, &IpData::sigma, cache);
}
std::vector<double> const& getIntPtEpsilon(
const double /*t*/,
std::vector<GlobalVector*> const& /*x*/,
std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
std::vector<double>& cache) const override
{
return ProcessLib::getIntegrationPointKelvinVectorData<DisplacementDim>(
_ip_data, &IpData::eps, cache);
}
std::vector<double> const& getIntPtHeatFlux(
const double /*t*/,
std::vector<GlobalVector*> const& /*x*/,
std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
std::vector<double>& cache) const override
{
using KelvinVectorType = typename BMatricesType::KelvinVectorType;
auto const n_integration_points = _ip_data.size();
cache.clear();
auto cache_mat = MathLib::createZeroedMatrix<Eigen::Matrix<
double, DisplacementDim, Eigen::Dynamic, Eigen::RowMajor>>(
cache, DisplacementDim, n_integration_points);
for (unsigned ip = 0; ip < n_integration_points; ++ip)
{
auto const& heatflux = _ip_data[ip].heatflux;
for (typename KelvinVectorType::Index component = 0;
component < DisplacementDim;
++component)
{ // x, y, z components
cache_mat(component, ip) = heatflux[component];
}
}
return cache;
}
void assembleWithJacobianForDeformationEquations(
double const t, double const dt, Eigen::VectorXd const& local_x,
std::vector<double>& local_b_data, std::vector<double>& local_Jac_data);
void assembleWithJacobianForHeatConductionEquations(
double const t, double const dt, Eigen::VectorXd const& local_x,
Eigen::VectorXd const& local_xdot, std::vector<double>& local_b_data,
std::vector<double>& local_Jac_data);
void assembleWithJacobianForPhaseFieldEquations(
double const t, Eigen::VectorXd const& local_x,
std::vector<double>& local_b_data, std::vector<double>& local_Jac_data);
ThermoMechanicalPhaseFieldProcessData<DisplacementDim>& _process_data;
std::vector<IpData, Eigen::aligned_allocator<IpData>> _ip_data;
IntegrationMethod _integration_method;
MeshLib::Element const& _element;
SecondaryData<typename ShapeMatrices::ShapeType> _secondary_data;
bool const _is_axially_symmetric;
/// ID of the processes that contains mechanical process.
int const _mechanics_related_process_id;
/// ID of phase field process.
int const _phase_field_process_id;
/// ID of heat conduction process.
int const _heat_conduction_process_id;
};
} // namespace ThermoMechanicalPhaseField
} // namespace ProcessLib
#include "ThermoMechanicalPhaseFieldFEM-impl.h"