46 #include <type_traits>
51 template <
int nDim,
int nNodes >
70 static constexpr
int idxU = 0;
80 using RhsSized = Eigen::Matrix< double, sizeLoadVector, 1 >;
81 using KSizedMatrix = Eigen::Matrix< double, sizeLoadVector, sizeLoadVector >;
103 { .name =
"stress", .length = 9 },
104 { .name =
"F0 XX", .length = 1 },
105 { .name =
"F0 YY", .length = 1 },
106 { .name =
"F0 ZZ", .length = 1 },
107 { .name =
"begin of material state", .length = 0 },
145 managedStateVars = std::make_unique< QPStateVarManager >( stateVars, nStateVars );
154 std::vector< QuadraturePoint >
qps;
189 const int elementFace,
191 const double* QTotal,
198 const double* QTotal,
219 template <
int nDim,
int nNodes >
223 const auto& qp = qps[qpNumber];
224 if ( qp.managedStateVars->contains( stateName ) ) {
225 return qp.managedStateVars->getStateView( stateName );
228 return qp.material->getStateView( stateName );
232 template <
int nDim,
int nNodes >
238 elementProperties( Eigen::Map< const Eigen::VectorXd >( nullptr, 0 ) ),
239 elLabel( elementID ),
240 sectionType( sectionType ),
241 hasEigenDeformation( false )
245 qps.push_back( std::move( qp ) );
249 template <
int nDim,
int nNodes >
252 return qps[0].getNumberOfRequiredStateVars() * qps.size();
255 template <
int nDim,
int nNodes >
260 static vector< vector< string > > nodeFields;
261 if ( nodeFields.empty() )
263 nodeFields.push_back( vector< string >() );
264 nodeFields[
i].push_back(
"displacement" );
270 template <
int nDim,
int nNodes >
273 static std::vector< int > permutationPattern;
274 if ( permutationPattern.empty() ) {
276 for (
int j = 0;
j <
nDim;
j++ )
277 permutationPattern.push_back(
i *
nDim +
j );
280 return permutationPattern;
283 template <
int nDim,
int nNodes >
286 const int nQpStateVars = nStateVars / qps.size();
288 for (
size_t i = 0;
i < qps.size();
i++ ) {
290 double* qpStateVars = &managedStateVars[
i * nQpStateVars];
291 qp.assignStateVars( qpStateVars, nQpStateVars );
295 template <
int nDim,
int nNodes >
299 new ( &elementProperties ) Eigen::Map< const Eigen::VectorXd >( elementPropertiesInfo.
elementProperties,
303 template <
int nDim,
int nNodes >
307 for (
auto& qp : qps ) {
308 qp.material = std::unique_ptr< Material >(
316 template <
int nDim,
int nNodes >
319 ParentGeometryElement::assignNodeCoordinates( coordinates );
322 template <
int nDim,
int nNodes >
331 const double detJ = J.determinant();
333 qp.dNdX = this->dNdX( dNdXi_, JInv );
335 if constexpr (
nDim == 3 ) {
336 qp.J0xW = qp.weight * detJ;
338 if constexpr (
nDim == 2 ) {
339 const double& thickness = elementProperties[0];
340 qp.J0xW = qp.weight * detJ * thickness;
342 if constexpr (
nDim == 1 ) {
343 const double& crossSection = elementProperties[0];
344 qp.J0xW = qp.weight * detJ * crossSection;
349 template <
int nDim,
int nNodes >
352 double* rightHandSide,
353 double* stiffnessMatrix,
358 using namespace Fastor;
360 const static Tensor< double, nDim, nDim >
I(
361 ( Eigen::Matrix< double, nDim, nDim >() << Eigen::Matrix< double, nDim, nDim >::Identity() ).finished().data() );
364 const auto qU_np = TensorMap< const double, nNodes, nDim >( qTotal );
367 TensorMap< double, nNodes, nDim > r_U( rightHandSide );
370 Tensor< double, nDim, nNodes, nDim, nNodes > k_UU( 0.0 );
372 Eigen::Map< Eigen::VectorXd > rhs( rightHandSide, sizeLoadVector );
374 for (
auto& qp : qps ) {
378 const auto& dNdX_ = qp.dNdX;
380 const auto dNdX = Tensor< double, nDim, nNodes >( dNdX_.data(), ColumnMajor );
382 const auto F_np = evaluate( einsum< Ai, jA >( qU_np, dNdX ) +
I );
391 if constexpr (
nDim == 2 ) {
393 if ( sectionType == SectionType::PlaneStrain ) {
408 deformation3D.F( 2, 2 ) = 1.0;
410 if ( hasEigenDeformation )
411 qp.material->computePlaneStrain( response3D,
415 { qp.managedStateVars->F0_XX,
416 qp.managedStateVars->F0_YY,
417 qp.managedStateVars->F0_ZZ } );
419 qp.material->computePlaneStrain( response3D, algorithmicModuli3D, deformation3D, timeIncrement );
421 response = { reduceTo2D< U, U >( response3D.tau ), response3D.
rho, response3D.elasticEnergyDensity };
424 reduceTo2D< U, U, U, U >( algorithmicModuli3D.
dTau_dF ),
435 qp.material->computeStress( response, tangents, deformation, timeIncrement );
441 catch (
const std::runtime_error& ) {
445 const auto dNdx = evaluate( einsum< ji, jA >( inv( F_np ), dNdX ) );
447 const double& J0xW = qp.J0xW;
449 const auto& tau = response.
tau;
451 const auto& t = tangents;
454 const auto dTau_dqU = evaluate( +einsum< ijkl, lB >( t.dTau_dF, dNdX ) );
458 r_U -= ( +einsum< iA, ij >( dNdx, tau ) ) * J0xW;
461 k_UU += ( +einsum< iA, ijkB, to_jAkB >( dNdx, dTau_dqU ) ) * J0xW;
464 k_UU += ( -einsum< kA, ij, iB, to_jAkB >( dNdx, tau, dNdx ) ) * J0xW;
470 using namespace Eigen;
472 Map< KSizedMatrix > K( stiffnessMatrix );
474 K.template block< bsU, bsU >( idxU, idxU ) += Map< Matrix< double, bsU, bsU > >( torowmajor( k_UU ).data() );
477 template <
int nDim,
int nNodes >
480 double* rightHandSide,
481 double* stiffnessMatrix,
482 const int elementFace,
484 const double* QTotal_,
489 Eigen::Map< USizedVector > r_U( rightHandSide );
491 switch ( loadType ) {
494 const double p = load[0];
495 const Eigen::Map< const RhsSized > QTotal( QTotal_ );
496 const Eigen::Ref< const USizedVector > qU( QTotal.head( bsU ) );
497 Eigen::Map< Eigen::Matrix< double, sizeLoadVector, sizeLoadVector > > K( stiffnessMatrix );
498 Eigen::Ref< Eigen::Matrix< double, bsU, bsU > > kUU( K.topLeftCorner( bsU, bsU ) );
500 const USizedVector coordinates_np = this->coordinates + qU;
507 Pb *= elementProperties[0];
508 Kb *= elementProperties[0];
520 const XiSized tractionVector( load );
524 Pk *= elementProperties[0];
530 throw std::invalid_argument(
"Invalid Load Type specified" );
535 template <
int nDim,
int nNodes >
538 const double* initialConditionDefinition )
540 if constexpr (
nDim > 1 ) {
546 qp.managedStateVars->F0_XX = 1.0;
547 qp.managedStateVars->F0_YY = 1.0;
548 qp.managedStateVars->F0_ZZ = 1.0;
550 qp.material->initializeYourself();
559 XiSized coordAtGauss = this->
NB( this->
N( qp.xi ) ) * this->coordinates;
566 F0_ZZ] = qp.material->findEigenDeformationForEigenStress( { qp.managedStateVars->F0_XX,
567 qp.managedStateVars->F0_YY,
568 qp.managedStateVars->F0_ZZ },
569 geostaticNormalStressComponents );
571 qp.managedStateVars->F0_XX = F0_XX;
572 qp.managedStateVars->F0_YY = F0_YY;
573 qp.managedStateVars->F0_ZZ = F0_ZZ;
575 hasEigenDeformation =
true;
579 default:
throw std::invalid_argument(
MakeString() << __PRETTY_FUNCTION__ <<
": invalid initial condition" );
584 template <
int nDim,
int nNodes >
586 double* stiffnessMatrix,
589 const double* qTotal,
593 Eigen::Map< RhsSized > r( rightHandSide );
594 Eigen::Ref< USizedVector > r_U( r.head( bsU ) );
595 const Eigen::Map< const Eigen::Matrix< double, nDim, 1 > > f( load );
597 for (
const auto& qp : qps )
598 r_U += this->
NB( this->
N( qp.xi ) ).transpose() * f * qp.J0xW;
601 template <
int nDim,
int nNodes >
604 std::vector< double > coords(
nDim );
606 Eigen::Map< XiSized > coordsMap( &coords[0] );
607 const auto centerXi = XiSized::Zero();
608 coordsMap = this->
NB( this->
N( centerXi ) ) * this->coordinates;
612 template <
int nDim,
int nNodes >
614 nNodes >::getCoordinatesAtQuadraturePoints()
616 std::vector< std::vector< double > > listedCoords;
618 std::vector< double > coords(
nDim );
619 Eigen::Map< XiSized > coordsMap( &coords[0] );
621 for (
const auto& qp : qps ) {
622 coordsMap = this->
NB( this->
N( qp.xi ) ) * this->coordinates;
623 listedCoords.push_back( coords );
629 template <
int nDim,
int nNodes >
635 template <
int nNodes >
640 void computeYourself(
const double* QTotal,
649 template <
int nNodes >
652 double* rightHandSide,
653 double* stiffnessMatrix,
658 constexpr
int nDim = 2;
661 const auto idxU = Parent::idxU;
665 using namespace Fastor;
667 const static Tensor< double, nDim, nDim >
I(
668 ( Eigen::Matrix< double, nDim, nDim >() << Eigen::Matrix< double, nDim, nDim >::Identity() ).finished().data() );
671 const auto qU_np = TensorMap< const double, nNodes, nDim >( qTotal );
674 TensorMap< double, nNodes, nDim > r_U( rightHandSide );
677 Tensor< double, nDim, nNodes, nDim, nNodes > k_UU( 0.0 );
679 Eigen::Map< Eigen::VectorXd > rhs( rightHandSide, sizeLoadVector );
681 for (
auto& qp : Parent::qps ) {
685 auto N_ = this->
N( qp.xi );
686 const auto& dNdX_ = qp.dNdX;
688 Eigen::Vector2d coords = this->
NB(
N_ ) * this->coordinates;
689 const double r = coords[0];
691 const auto N = Tensor< double, nNodes >(
N_.data() );
692 const auto dNdX = Tensor< double, nDim, nNodes >( dNdX_.data(), ColumnMajor );
694 const auto u_np = evaluate( einsum< A, Ai >(
N, qU_np ) );
696 const auto F_np = evaluate( einsum< Ai, jA >( qU_np, dNdX ) +
I );
702 const Material ::TimeIncrement timeIncrement{ time[0], dT };
717 deformation3D.F( 2, 2 ) = 1 + u_np[0] / r;
720 qp.material->computePlaneStrain( response3D, algorithmicModuli3D, deformation3D, timeIncrement );
722 catch (
const std::runtime_error& ) {
726 response = { reduceTo2D< U, U >( response3D.tau ), response3D.
rho, response3D.elasticEnergyDensity };
729 reduceTo2D< U, U, U, U >( algorithmicModuli3D.
dTau_dF ),
734 const auto dNdx = evaluate( einsum< ji, jA >( inv( F_np ), dNdX ) );
738 const auto& tau = response.
tau;
740 const auto& t = tangents;
743 auto dTau_dqU = evaluate( +einsum< ijkl, lB >( t.dTau_dF, dNdX ) );
745 Fastor::Tensor< double, 2, 2 > dTau33_dF_2D( 0.0 );
746 for (
int i = 0;
i < 2;
i++ )
747 for (
int j = 0;
j < 2;
j++ ) {
748 dTau33_dF_2D(
i,
j ) = algorithmicModuli3D.
dTau_dF( 2, 2,
i,
j );
750 auto dTau33_dqU = evaluate( +einsum< kl, lB >( dTau33_dF_2D, dNdX ) );
755 for (
int i = 0;
i < 2;
i++ )
756 for (
int j = 0;
j < 2;
j++ ) {
757 dTau_dqU(
i,
j, 0,
B ) += algorithmicModuli3D.
dTau_dF(
i,
j, 2, 2 ) *
N(
B ) / r;
759 dTau33_dqU( 0,
B ) += algorithmicModuli3D.
dTau_dF( 2, 2, 2, 2 ) *
N(
B ) / r;
764 r_U -= ( +einsum< iA, ij >( dNdx, tau ) ) * J0xWxRx2Pi;
766 const double F33 = 1 + u_np[0] / r;
767 const double invF33 = 1. / F33;
768 const double dInvF33_dF33 = -1. / ( F33 * F33 );
771 r_U(
A, 0 ) -= ( +
N(
A ) * invF33 * response3D.tau( 2, 2 ) / r ) * J0xWxRx2Pi;
774 for (
int j = 0;
j < 2;
j++ ) {
775 k_UU( 0,
A,
j,
B ) += ( +
N(
A ) * invF33 * dTau33_dqU(
j,
B ) / r ) * J0xWxRx2Pi;
777 const double dF33_dN_qU_0 = (
N(
B ) / r );
778 k_UU( 0,
A, 0,
B ) += ( +
N(
A ) * dInvF33_dF33 * dF33_dN_qU_0 * response3D.tau( 2, 2 ) / r ) * J0xWxRx2Pi;
783 k_UU += ( +einsum< iA, ijkB, to_jAkB >( dNdx, dTau_dqU ) ) * J0xWxRx2Pi;
789 using namespace Eigen;
791 Map< typename Parent::KSizedMatrix > K( stiffnessMatrix );
793 K.template block< Parent::bsU, Parent::bsU >( idxU, idxU ) += Map< Matrix< double, Parent::bsU, Parent::bsU > >(
794 torowmajor( k_UU ).data() );