def tangent_moduli(cls, material, deformation_gradient, dimension=3, test=False): """Compute the tangent moduli for the material from the deformation gradient under the specified assumptions. :param material: material to which the deformation gradient applies :param numpy.ndarray deformation_gradient: 3x3 matrix describing the deformation of the body :param int dimension: desired dimension of the returned tensor :param bool test: whether to perform the verification test for the stress result """ J = numpy.linalg.det(deformation_gradient) F_inverse = numpy.linalg.inv(deformation_gradient) # Initialize tangent moduli as an empty 4-dimensional array tangent_moduli = numpy.zeros((3, 3, 3, 3)) for i in range(3): for j in range(3): for k in range(3): for l in range(3): tangent_moduli[i][j][k][l] = (material.first_lame_parameter * F_inverse[l][k] * F_inverse[j][i] - ( material.first_lame_parameter * math.log(J) - material.shear_modulus) * F_inverse[j][k] * F_inverse[l][i]) if i == k and j == l: tangent_moduli[i][j][k][l] += material.shear_modulus # Verify the correctness of this result by comparing it to numerical differentiation if test: tests.numerical_differentiation_tangent_moduli(constitutive_model=cls, material=material, deformation_gradient=deformation_gradient, tangent_moduli=tangent_moduli) # If the requested dimension is 2, corrected the tangent moduli for plane stress if dimension == 2: return cls.tangent_moduli_two_dimensions(tangent_moduli) # Otherwise return the full tangent moduli return tangent_moduli
def error_testing(): # NOTE: this test will result in an error for the default tolerance value, because this function is intended # to violate the tolerance for the purposes of showing the behavior of the error as a function of h. deformation_gradient = operations.generate_random_deformation_gradient() # uncomment for "bad" F: - numpy.eye(3) material = materials.Custom(name='custom material', first_lame_parameter=5, shear_modulus=3) constitutive_model = constitutive_models.Neohookean() (strain_energy_density, first_piola_kirchhoff_stress, tangent_moduli) = constitutive_model.calculate_all(material=material, deformation_gradient=deformation_gradient) h_values = list(numpy.logspace(-2, -10, 100)) p_errors = [] c_errors = [] for h_value in h_values: # NOTE these functions don't normally return these values p_error = tests.numerical_differentiation_first_piola_kirchhoff_stress(constitutive_model=constitutive_model, material=material, deformation_gradient=deformation_gradient, first_piola_kirchhoff_stress=first_piola_kirchhoff_stress, h=h_value) c_error = tests.numerical_differentiation_tangent_moduli(constitutive_model=constitutive_model, material=material, deformation_gradient=deformation_gradient, tangent_moduli=tangent_moduli, h=h_value) p_errors.append(p_error) c_errors.append(c_error) plt.figure() plt.plot(h_values, p_errors, 'b', label='P error') plt.plot(h_values, c_errors, 'r', label='C error') plt.xscale('log') plt.yscale('log') plt.ylim(10e-10, 10e-3) plt.title('3-point formula errors for "good" deformation gradient') plt.xlabel('h') plt.ylabel('error') plt.legend(loc='best') plt.show()