7#ifndef FRICTIONQPOTFEM_UNIFORMSINGLELAYER2D_H
8#define FRICTIONQPOTFEM_UNIFORMSINGLELAYER2D_H
16#define SQR(x) ((x) * (x))
26namespace UniformSingleLayer2d {
78 template <
class C,
class E,
class L,
class M,
class Y>
90 const Y& plastic_epsy,
115 std::string
type()
const override
117 return "FrictionQPotFEM.UniformSingleLayer2d.System";
129 auto h_plas = xt::view(
m_coor, xt::keep(top), 1) - xt::view(
m_coor, xt::keep(bot), 1);
130 double h = h_plas(0);
143 double dV = dV_plas(0, 0);
183 double epsxx = Epsd(0, 0);
184 double epsxy = Epsd(0, 1);
190 double direction = +1.0;
191 if (target_stress < sig) {
195 double eps_new = eps + (target_stress - sig) / (2.0 *
G);
196 double dgamma = 2.0 * (-1.0 * direction * epsxy +
197 std::sqrt(std::pow(eps_new, 2.0) - std::pow(epsxx, 2.0)));
200 return direction * dgamma;
203 for (
size_t n = 0; n <
m_nnode; ++n) {
211 Sigbar = detail::myaverage(this->
Sig(),
dV, {0, 1});
215 return direction * dgamma;
257 size_t plastic_element,
258 bool trigger_weakest =
true,
259 double amplify = 1.0)
269 auto deps = epsy - eps;
273 size_t q = xt::argmin(xt::view(deps, plastic_element, xt::all()))();
274 if (!trigger_weakest) {
275 q = xt::argmax(xt::view(deps, plastic_element, xt::all()))();
283 double eps_new = epsy(plastic_element, q) + deps_kick / 2.0;
287 2.0 * (-Epsd(0, 1) + std::sqrt(std::pow(eps_new, 2.0) - std::pow(Epsd(0, 0), 2.0)));
295 for (
size_t n = 0; n <
m_nne; ++n) {
297 dgamma * amplify * (
m_coor(elem(n), 1) -
m_coor(elem(0), 1));
304 const auto& idx_new =
m_plas.
i();
310 std::abs(eps(plastic_element, q) - eps_new) / eps_new < 1e-4 || amplify != 1);
340 auto deps = xt::eval(epsy - eps);
342 auto isort = xt::argsort(deps, 1);
346 for (
size_t e = 0; e <
m_N; ++e) {
347 size_t q = isort(e, iquad);
348 double eps_new = epsy(e, q) + deps_kick / 2.0;
349 double gamma = Epsd(e, q, 0, 1);
350 double epsd_xx = Epsd(e, q, 0, 0);
351 ret(e, 0) = deps(e, q);
352 ret(e, 1) = -gamma + std::sqrt(std::pow(eps_new, 2.0) - std::pow(epsd_xx, 2.0));
393 auto vector = sys.
vector();
395 auto quad = sys.
quad();
408 auto coor = sys.
coor();
409 auto conn = sys.
conn();
411 auto u = vector.allocate_nodevec(0.0);
412 auto fint = vector.allocate_nodevec(0.0);
413 auto fext = vector.allocate_nodevec(0.0);
414 auto fres = vector.allocate_nodevec(0.0);
416 auto ue = vector.allocate_elemvec(0.0);
417 auto fe = vector.allocate_elemvec(0.0);
419 auto Eps = quad.allocate_qtensor<2>(0.0);
420 auto Sig = quad.allocate_qtensor<2>(0.0);
421 std::copy(Eps.shape().cbegin(), Eps.shape().cend(),
m_shape_T2.begin());
430 auto elmap = mesh.
roll(1);
434 for (
size_t roll = 0; roll < nroll; ++roll) {
439 for (
size_t e = 0; e < nconfig; ++e) {
443 m_u_s.emplace_back(u.shape());
444 m_Eps_s.emplace_back(Eps.shape());
445 m_Sig_s.emplace_back(Sig.shape());
461 for (
size_t q = 0; q <
m_nip; ++q) {
464 double gamma = Epsd(0, 1);
465 for (
size_t roll = 0; roll < nroll; ++roll) {
466 auto map = mesh.
roll(roll);
473 m_u_p.emplace_back(u.shape());
474 m_Eps_p.emplace_back(Eps.shape());
475 m_Sig_p.emplace_back(Sig.shape());
482 for (
size_t q = 0; q <
m_nip; ++q) {
485 double E = Epsd(0, 0);
486 for (
size_t roll = 0; roll < nroll; ++roll) {
487 auto map = mesh.
roll(roll);
513 size_t trigger_plastic,
524 size_t trigger_element =
m_elem_plas(trigger_plastic);
529 for (
size_t q = 0; q < quad.
nip(); ++q) {
530 xt::view(Sig, trigger_element, q) = -sig_star;
535 auto fext = xt::zeros_like(fint);
536 vector.
copy_p(fint, fext);
537 auto fres = xt::eval(fext - fint);
539 solver.solve(K, fres, u);
543 material.set_Eps(Eps);
544 std::copy(material.Sig().begin(), material.Sig().end(), Sig.begin());
560 size_t nconfig =
m_u_s.size();
561 size_t config = trigger_plastic % nconfig;
562 size_t roll = (trigger_plastic - trigger_plastic % nconfig) / nconfig;
578 size_t nconfig =
m_u_p.size();
579 size_t config = trigger_plastic % nconfig;
580 size_t roll = (trigger_plastic - trigger_plastic % nconfig) / nconfig;
596 size_t nconfig =
m_u_s.size();
597 size_t config = trigger_plastic % nconfig;
598 size_t roll = (trigger_plastic - trigger_plastic % nconfig) / nconfig;
614 size_t nconfig =
m_u_p.size();
615 size_t config = trigger_plastic % nconfig;
616 size_t roll = (trigger_plastic - trigger_plastic % nconfig) / nconfig;
632 size_t nconfig =
m_u_s.size();
633 size_t config = trigger_plastic % nconfig;
634 size_t roll = (trigger_plastic - trigger_plastic % nconfig) / nconfig;
650 size_t nconfig =
m_u_p.size();
651 size_t config = trigger_plastic % nconfig;
652 size_t roll = (trigger_plastic - trigger_plastic % nconfig) / nconfig;
708 for (
size_t i = 0; i < S.shape(0); ++i) {
720 auto Sig_slice = this->
slice(Sig, e);
723 for (
size_t q = 0; q <
m_nip; ++q) {
730 double gamma = Epsd(0, 1);
731 double E = Epsd(0, 0);
732 double y = epsy(e, q);
739 D =
SQR(b) - 4.0 * a * c;
740 double smax = (-b + std::sqrt(D)) / (2.0 * a);
741 double smin = (-b - std::sqrt(D)) / (2.0 * a);
747 D =
SQR(b) - 4.0 * a * c;
748 double pmax = (-b + std::sqrt(D)) / (2.0 * a);
749 double pmin = (-b - std::sqrt(D)) / (2.0 * a);
751 size_t n =
static_cast<size_t>(-smin / (smax - smin) *
static_cast<double>(N));
754 for (
size_t i = 0; i < 2; ++i) {
755 xt::view(S, i, xt::range(0, n)) = xt::linspace<double>(smin, 0, n);
756 xt::view(S, i, xt::range(n, N)) =
757 xt::linspace<double>(smax /
double(m), smax, m);
766 for (
size_t j = 1; j < N - 1; ++j) {
772 c =
SQR(E) + std::pow(gamma + S(0, j) *
dgamma, 2.0) -
SQR(y);
773 D =
SQR(b) - 4.0 * a * c;
774 P(0, j) = (-b + std::sqrt(D)) / (2.0 * a);
775 P(1, j) = (-b - std::sqrt(D)) / (2.0 * a);
778 for (
size_t i = 0; i < P.shape(0); ++i) {
779 for (
size_t j = 0; j < P.shape(1); ++j) {
781 P(i, j) *
Sig_p + S(i, j) *
Sig_s + Sig_slice;
789 W(i, j) = xt::sum(w)();
793 auto idx = xt::argmin(W)();
794 m_smin(e, q) = S.flat(idx);
795 m_pmin(e, q) = P.flat(idx);
796 m_Wmin(e, q) = W.flat(idx);
819 std::array<double, 8> S;
820 std::array<double, 8> P;
821 std::array<double, 8> W;
829 auto Sig_slice = this->
slice(Sig, e);
832 for (
size_t q = 0; q <
m_nip; ++q) {
839 double gamma = Epsd(0, 1);
840 double E = Epsd(0, 0);
841 double y = epsy(e, q);
848 D =
SQR(b) - 4.0 * a * c;
849 double smax = (-b + std::sqrt(D)) / (2.0 * a);
850 double smin = (-b - std::sqrt(D)) / (2.0 * a);
860 D =
SQR(b) - 4.0 * a * c;
861 double pmax = (-b + std::sqrt(D)) / (2.0 * a);
862 double pmin = (-b - std::sqrt(D)) / (2.0 * a);
872 for (
size_t i = 4; i < S.size(); ++i) {
878 c =
SQR(E) + std::pow(gamma + S[i] *
dgamma, 2.0) -
SQR(y);
879 D =
SQR(b) - 4.0 * a * c;
880 P[i] = (-b + std::sqrt(D)) / (2.0 * a);
881 P[i + 1] = (-b - std::sqrt(D)) / (2.0 * a);
884 for (
size_t i = 0; i < S.size(); ++i) {
893 auto idx = std::distance(W.begin(), std::min_element(W.begin(), W.end()));
918 std::array<double, 2> S;
919 std::array<double, 2> W;
925 auto Sig_slice = this->
slice(Sig, e);
928 for (
size_t q = 0; q <
m_nip; ++q) {
934 double gamma = Epsd(0, 1);
935 double E = Epsd(0, 0);
936 double y = epsy(e, q);
943 D =
SQR(b) - 4.0 * a * c;
944 S[1] = (-b + std::sqrt(D)) / (2.0 * a);
945 S[0] = (-b - std::sqrt(D)) / (2.0 * a);
947 for (
size_t i = 0; i < S.size(); ++i) {
1068 std::vector<array_type::tensor<double, 2>>
1070 std::vector<array_type::tensor<double, 2>>
1072 std::vector<array_type::tensor<double, 4>>
1074 std::vector<array_type::tensor<double, 4>>
1076 std::vector<array_type::tensor<double, 4>>
1078 std::vector<array_type::tensor<double, 4>>
1200 std::vector<array_type::tensor<size_t, 1>>
1202 std::vector<array_type::tensor<double, 4>>
1204 std::vector<array_type::tensor<double, 4>>
1206 std::vector<array_type::tensor<double, 4>>
1208 std::vector<array_type::tensor<double, 4>>
System with elastic elements and plastic elements (GMatElastoPlasticQPot).
const GooseFEM::Element::Quad4::Quadrature & quad() const
GooseFEM quadrature definition.
size_t m_nne
Number of nodes per element.
double eta() const
Get the damping at the interface.
double rho() const
Mass density.
array_type::tensor< double, 2 > G() const
Shear modulus per integration point.
const array_type::tensor< double, 4 > & Eps()
Strain tensor of each integration point.
const auto & dV() const
Integration point volume (of each integration point)
const auto & elastic_elem() const
List of elastic elements.
array_type::tensor< double, 2 > m_coor
Nodal coordinates, see coor().
GMatElastoPlasticQPot::Cartesian2d::Cusp< 2 > m_plas
Material for plastic el.
size_t m_nnode
Number of nodes.
size_t m_N
Number of plastic elements, alias of m_nelem_plas.
double eventDriven_setDeltaU(const T &delta_u, bool autoscale=true)
Set purely elastic and linear response to specific boundary conditions.
const auto & plastic_elem() const
List of plastic elements.
GooseFEM::MatrixPartitioned stiffness() const
Stiffness tensor of each integration point.
const array_type::tensor< double, 4 > & Sig()
Stress tensor of each integration point.
void setU(const T &u)
Overwrite nodal displacements.
array_type::tensor< double, 2 > K() const
Bulk modulus per integration point.
array_type::tensor< size_t, 1 > m_elem_plas
Plastic elements.
const auto & coor() const
Nodal coordinates.
const auto & conn() const
Connectivity.
GooseFEM::Element::Quad4::Quadrature m_quad
Quadrature for all elements.
double dt() const
Get time step.
array_type::tensor< double, 2 > m_u
Nodal displacements.
GooseFEM::VectorPartitioned m_vector
Convert vectors between 'nodevec', 'elemvec', ....
array_type::tensor< double, 2 > affineSimpleShear(double delta_gamma) const
Get the displacement field that corresponds to an affine simple shear of a certain strain.
const auto & dofs() const
DOFs per node.
bool isHomogeneousElastic() const
Check if elasticity is homogeneous.
double alpha() const
Background damping density.
const GooseFEM::VectorPartitioned & vector() const
GooseFEM vector definition.
size_t m_nip
Number of integration points.
virtual void updated_u()
Evaluate relevant forces when m_u is updated.
size_t m_nelem_plas
Number of plastic elements.
const array_type::tensor< size_t, N > & i() const
Index of the current yield strain per item.
array_type::tensor< double, N > epsy_right() const
Current yield strain right per item.
Array of material points with a linear elastic constitutive response.
const array_type::tensor< double, N > & G() const
Shear modulus per item.
const array_type::tensor< double, N+2 > & Eps() const
Strain tensor per item.
Interpolation and quadrature.
auto Int_gradN_dot_tensor2_dV(const T &qtensor) const -> array_type::tensor< double, 3 >
Element-by-element: integral of the dot product of the shape function gradients with a second order t...
void symGradN_vector(const T &elemvec, R &qtensor) const
Same as SymGradN_vector(), but writing to preallocated return.
auto dV() const -> const array_type::tensor< double, 2 > &
Integration volume.
auto nip() const
Number of integration points.
auto AsTensor(const T &arg) const
Convert "qscalar" to "qtensor" of certain rank.
Solve for A of the MatrixPartitioned() class.
Sparse matrix partitioned in an unknown and a prescribed part.
Mesh with fine middle layer, and coarser elements towards the top and bottom.
array_type::tensor< size_t, 1 > roll(size_t n)
Mapping to 'roll' periodically in the x-direction,.
array_type::tensor< size_t, 1 > elementgrid_around_ravel(size_t e, size_t size, bool periodic=true)
Select region of elements from 'matrix' of element numbers around an element: square box with edge-si...
Class to switch between storage types, based on a mesh and DOFs that are partitioned in:
void copy_p(const array_type::tensor< double, 2 > &nodevec_src, array_type::tensor< double, 2 > &nodevec_dest) const
Copy prescribed DOFs from "nodevec" to another "nodvec":
array_type::tensor< double, 1 > AsDofs_p(const array_type::tensor< double, 1 > &dofval) const
Extract the prescribed "dofval":
const array_type::tensor< size_t, 2 > & conn() const
void asElement(const T &arg, R &ret) const
Convert "dofval" or "nodevec" to "elemvec" (overwrite entries that occur more than once).
array_type::tensor< double, 2 > AsNode(const T &arg) const
Convert "dofval" or "elemvec" to "nodevec" (overwrite entries that occur more than once).
array_type::tensor< double, 1 > AsDofs(const T &arg) const
Convert "nodevec" or "elemvec" to "dofval" (overwrite entries that occur more than once).
array_type::tensor< double, 2 > AssembleNode(const T &arg) const
Assemble "elemvec" to "nodevec" (adds entries that occur more that once.
const array_type::tensor< size_t, 2 > & dofs() const
std::vector< std::string > version_dependencies()
Return versions of this library and of all of its dependencies.
std::vector< std::string > version_compiler()
Version information of the compilers.
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Friction simulations based on a disorder potential energy landscape and the finite element method.
auto Epsd(const T &A) -> typename GMatTensor::allocate< xt::get_rank< T >::value - 2, T >::type
Equivalent strain: norm of strain deviator.
auto Sigd(const T &A) -> typename GMatTensor::allocate< xt::get_rank< T >::value - 2, T >::type
Equivalent stress: norm of strain deviator.
auto Deviatoric(const T &A)
Deviatoric part of a tensor:
auto A2s_ddot_B2s(const T &A, const T &B)
Same as A2_ddot_B2(const T& A, const T& B, R& ret) but for symmetric tensors.
array_type::tensor< size_t, 1 > elemmap2nodemap(const T &elem_map, const C &coor, const E &conn, ElementType type)
Convert an element-map to a node-map.
#define FRICTIONQPOTFEM_REQUIRE(expr)
Assertions that cannot be disabled.
#define FRICTIONQPOTFEM_ASSERT(expr)
All assertions are implementation as::