def constitutive_Saint_Venant(F, mu, kappa):
    C4 = (kappa * II) + 2.0 * mu * (I4s - 1.0 / 3.0 * II)
    S = ddot42(C4, 0.5 * (dot22(trans2(F), F) - I))
    P = dot22(F, S)
    K4 = dot24(S, I4) + ddot44(ddot44(I4rt, dot42(dot24(F, C4), trans2(F))),
                               I4rt)
    return P, K4
def constitutive_Mooney_Rivlin(F, c, c1, c2):
    # First derivate of W:Neo-Hookean free energy w.r.t F
    detF = det2(F)
    if np.any(detF < 0):  # That means the calculation will return wrong values
        return -1, -1
        # pass
    invF = inv2(F)
    Cauchy = dot22(trans2(F), F)
    J = detF
    trC = trace2(Cauchy)
    invC = inv2(Cauchy)
    S = (2 * c1 + 2 * c2 * trC) * I - 2 * c2 * trans2(Cauchy) + (
        2 * c * (J - 1) * J) * trans2(invC)
    P = dot22(F, S)
    C4 = zeros([dim, dim, dim, dim, Nx, Ny])
    for i, j, k, l in itertools.product(range(dim), repeat=4):
        C4[i, j, k, l, :, :] = 2 * (2*c2*delta(i,j)*delta(k,l) - 2*c2*delta(j,k)*delta(i,l) + c*(2*J - 1) * J * invC[j,i,:,:] * invC[l,k,:,:] \
         - (2 * c * (J - 1) * J) * invC[j, k, :, :] * invC[l, i, :, :])
    K4 = zeros([dim, dim, dim, dim, Nx, Ny])
    for i, j, k, l in itertools.product(range(dim), repeat=4):
        temp = zeros([dim, dim, dim, dim, Nx, Ny])
        for m, q in itertools.product(range(dim), repeat=2):
            temp += F[i, m, :, :] * 0.5 * (
                C4[m, j, l, q, :, :] + C4[m, j, q, l, :, :]) * F[k, q, :, :]
        K4[i, j, k,
           l, :, :] = delta(i, k) * S[l, j, :, :] + temp[i, j, k, l, :, :]
    return P, K4
def get_energy_Mooney_Rivlin(F, c, c1, c2):
    # J = det2(F)
    Cauchy = dot22(trans2(F), F)
    J = np.sqrt(det2(Cauchy))
    Inv1 = trace2(Cauchy)
    Inv2 = 0.5 * (np.power(Inv1, 2) - trace2(dot22(Cauchy, Cauchy)))
    W = c * np.power(J - 1, 2) + c1 * (Inv1 - 2) + c2 * (Inv2 - 2)
    return W
def get_energy_Neo_Hookean(F, mu, beta):
    dim = F.shape[0]
    C = dot22(trans2(F), F)
    trC = np.zeros([F.shape[2], F.shape[3]])
    for i in range(dim):
        trC += C[i, i, :, :]
    detF = det2(F)
    energy = mu / 2 * (trC - dim) + mu / beta * (np.power(detF, -beta) - 1)
    return energy
def get_energy_Neo_Hookean2(F, mu, lam):
    dim = F.shape[0]
    C = dot22(trans2(F), F)
    trC = np.zeros([F.shape[2], F.shape[3]])
    for i in range(dim):
        trC += C[i, i, :, :]
    detF = det2(F)
    energy = 0.5 * lam * np.power(np.log(detF),
                                  2) - mu * np.log(detF) + 0.5 * mu * (trC - 2)
    return energy