diff --git a/src/CabanaPD_Types.hpp b/src/CabanaPD_Types.hpp index fd95375a..8efb7e91 100644 --- a/src/CabanaPD_Types.hpp +++ b/src/CabanaPD_Types.hpp @@ -40,5 +40,9 @@ struct LinearLPS { }; +struct DynamicCriticalStretch +{ +}; + } // namespace CabanaPD #endif diff --git a/src/force/CabanaPD_ForceModels_PMB.hpp b/src/force/CabanaPD_ForceModels_PMB.hpp index 7f920b24..78e937a9 100644 --- a/src/force/CabanaPD_ForceModels_PMB.hpp +++ b/src/force/CabanaPD_ForceModels_PMB.hpp @@ -91,10 +91,75 @@ struct ForceModel bond_break_coeff = ( 1.0 + s0 ) * ( 1.0 + s0 ); } + // No-op. + template + KOKKOS_INLINE_FUNCTION auto + minLocalStretch( const int, const NeighListType&, const PosType&, + const PosType& ) const + { + return s0; + } + + KOKKOS_INLINE_FUNCTION + bool criticalStretch( const int, const int, const double r, const double xi, + const double ) const + { + return r * r >= bond_break_coeff * xi * xi; + } +}; + +template <> +struct ForceModel + : public ForceModel +{ + using base_type = ForceModel; + using base_model = typename base_type::base_model; + using fracture_type = Fracture; + using thermal_type = base_type::thermal_type; + + // Purposely not using the (static) base class bond_break_coeff + using base_type::c; + using base_type::delta; + using base_type::G0; + using base_type::K; + using base_type::s0; + double alpha = 0.25; + + ForceModel() {} + ForceModel( const double delta, const double K, const double G0 ) + : base_type( delta, K, G0 ) + { + } + + template + KOKKOS_INLINE_FUNCTION auto + minLocalStretch( const int i, const NeighListType& neigh_list, + const PosType& x, const PosType& u ) const + { + std::size_t num_neighbors = + Cabana::NeighborList::numNeighbor( neigh_list, i ); + double s_min = DBL_MAX; + for ( std::size_t n = 0; n < num_neighbors; n++ ) + { + std::size_t j = Cabana::NeighborList::getNeighbor( + neigh_list, i, n ); + + double xi, r, s; + double rx, ry, rz; + getDistanceComponents( x, u, i, j, xi, r, s, rx, ry, rz ); + if ( s < s_min ) + s_min = s; + } + return s0 - alpha * s_min; + } + + // Use the dynamic s0 from the minLocalStretch function, reused through the + // neighbor loop. KOKKOS_INLINE_FUNCTION - bool criticalStretch( const int, const int, const double r, - const double xi ) const + bool criticalStretch( const int, const int, const double r, const double xi, + const double s0_i ) const { + double bond_break_coeff = ( 1.0 + s0_i ) * ( 1.0 + s0_i ); return r * r >= bond_break_coeff * xi * xi; } }; @@ -231,7 +296,7 @@ struct ForceModel KOKKOS_INLINE_FUNCTION bool criticalStretch( const int i, const int j, const double r, - const double xi ) const + const double xi, const double ) const { double temp_avg = 0.5 * ( temperature( i ) + temperature( j ) ) - temp0; double bond_break_coeff = diff --git a/src/force/CabanaPD_Force_PMB.hpp b/src/force/CabanaPD_Force_PMB.hpp index cd5acce7..b36000b0 100644 --- a/src/force/CabanaPD_Force_PMB.hpp +++ b/src/force/CabanaPD_Force_PMB.hpp @@ -214,6 +214,8 @@ class Force> auto force_full = KOKKOS_LAMBDA( const int i ) { + auto s_min = model.minLocalStretch( i, neigh_list, x, u ); + std::size_t num_neighbors = Cabana::NeighborList::numNeighbor( neigh_list, i ); @@ -235,8 +237,8 @@ class Force> model.thermalStretch( s, i, j ); // Break if beyond critical stretch unless in no-fail zone. - if ( model.criticalStretch( i, j, r, xi ) && !nofail( i ) && - !nofail( j ) ) + if ( model.criticalStretch( i, j, r, xi, s_min ) && + !nofail( i ) && !nofail( j ) ) { mu( i, n ) = 0; }