Skip to content

Commit

Permalink
adding a uniaxal strain analytic solution up to a max log strain of 1…
Browse files Browse the repository at this point in the history
… with a relaxation time of 25.0s and loading time of 100.0s at a strain rate of 1.0e-2. Removed the zero test since this is covered by this test now for time=0s. Will modify later to cover range of strain rates. This will lead to large test times though.
  • Loading branch information
cmhamel committed May 3, 2024
1 parent ca64be2 commit 8134e6c
Showing 1 changed file with 138 additions and 33 deletions.
171 changes: 138 additions & 33 deletions optimism/material/test/test_HyperVisco.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,21 @@
from optimism.material import HyperViscoelastic as HyperVisco
from optimism.test.TestFixture import TestFixture
from optimism.material import MaterialUniaxialSimulator
from optimism.TensorMath import deviator
from optimism.TensorMath import log_symm

plotting=True
plotting = False

class HyperViscoModelFixture(TestFixture):
def setUp(self):

G_eq = 0.855 # MPa
K_eq = 1000*G_eq # MPa
G_neq_1 = 5.0
tau_1 = 0.1
# tau_1 = 0.1
tau_1 = 25.0
self.G_neq_1 = G_neq_1
self.tau_1 = tau_1 # needed for analytic calculation below
self.props = {
'equilibrium bulk modulus' : K_eq,
'equilibrium shear modulus' : G_eq,
Expand All @@ -26,49 +31,146 @@ def setUp(self):
}

materialModel = HyperVisco.create_material_model_functions(self.props)

# do this on base fixture class to reduce jitting in test fixtures
self.energy_density = jax.jit(materialModel.compute_energy_density)
self.compute_state_new = materialModel.compute_state_new
self.compute_state_new = jax.jit(materialModel.compute_state_new)
self.compute_initial_state = materialModel.compute_initial_state
self.compute_material_qoi = materialModel.compute_material_qoi

def test_zero_point(self):
dispGrad = np.zeros((3,3))
initialState = self.compute_initial_state()
dt = 1.0
self.compute_material_qoi = jax.jit(materialModel.compute_material_qoi)

energy = self.energy_density(dispGrad, initialState, dt)
self.assertNear(energy, 0.0, 12)

state = self.compute_state_new(dispGrad, initialState, dt)
self.assertArrayNear(state, np.eye(3).ravel(), 12)
# This test is covered from the others
# class HyperViscoZeroTest(HyperViscoModelFixture):
# def test_zero_point(self):
# dispGrad = np.zeros((3,3))
# initialState = self.compute_initial_state()
# dt = 1.0

dissipatedEnergy = self.compute_material_qoi(dispGrad, initialState, dt)
self.assertNear(dissipatedEnergy, 0.0, 12)
# energy = self.energy_density(dispGrad, initialState, dt)
# self.assertNear(energy, 0.0, 12)

def test_regression_nonzero_point(self):
key = jax.random.PRNGKey(1)
dispGrad = jax.random.uniform(key, (3, 3))
initialState = self.compute_initial_state()
dt = 1.0
# state = self.compute_state_new(dispGrad, initialState, dt)
# self.assertArrayNear(state, np.eye(3).ravel(), 12)

energy = self.energy_density(dispGrad, initialState, dt)
self.assertNear(energy, 133.4634466468207, 12)
# dissipatedEnergy = self.compute_material_qoi(dispGrad, initialState, dt)
# self.assertNear(dissipatedEnergy, 0.0, 12)

state = self.compute_state_new(dispGrad, initialState, dt)
stateGold = np.array([0.988233534321, 0.437922586964, 0.433881277313,
0.437922586964, 1.378870045574, 0.079038974065,
0.433881277313, 0.079038974065, 1.055381729505])
self.assertArrayNear(state, stateGold, 12)
# def test_regression_nonzero_point(self):
# key = jax.random.PRNGKey(1)
# dispGrad = jax.random.uniform(key, (3, 3))
# initialState = self.compute_initial_state()
# dt = 1.0

dissipatedEnergy = self.compute_material_qoi(dispGrad, initialState, dt)
self.assertNear(dissipatedEnergy, 0.8653744383204761, 12)
# energy = self.energy_density(dispGrad, initialState, dt)
# self.assertNear(energy, 133.4634466468207, 12)

class HyperViscoUniaxial(TestFixture):
# state = self.compute_state_new(dispGrad, initialState, dt)
# stateGold = np.array([0.988233534321, 0.437922586964, 0.433881277313,
# 0.437922586964, 1.378870045574, 0.079038974065,
# 0.433881277313, 0.079038974065, 1.055381729505])
# self.assertArrayNear(state, stateGold, 12)

# dissipatedEnergy = self.compute_material_qoi(dispGrad, initialState, dt)
# self.assertNear(dissipatedEnergy, 0.8653744383204761, 12)


class HyperViscoUniaxialStrain(HyperViscoModelFixture):
def test_loading_only(self):
strain_rate = 1.0e-2
total_time = 100.0
n_steps = 100
dt = total_time / n_steps
times = np.linspace(0.0, total_time, n_steps)
Fs = jax.vmap(
lambda t: np.array(
[[np.exp(strain_rate * t), 0.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 0.0, 1.0]]
)
)(times)
state_old = self.compute_initial_state()
energies = np.zeros(n_steps)
states = np.zeros((n_steps, state_old.shape[0]))

for n, F in enumerate(Fs):
dispGrad = F - np.eye(3)
energies = energies.at[n].set(self.energy_density(dispGrad, state_old, dt))
state_new = self.compute_state_new(dispGrad, state_old, dt)
states = states.at[n, :].set(state_new)
state_old = state_new


Fvs = jax.vmap(lambda Fv: Fv.reshape((3, 3)))(states)
Fes = jax.vmap(lambda F, Fv: F @ np.linalg.inv(Fv), in_axes=(0, 0))(Fs, Fvs)

Es = jax.vmap(lambda F: log_symm(F))(Fs)
Evs = jax.vmap(lambda Fv: log_symm(Fv))(Fvs)
Ees = jax.vmap(lambda Fe: log_symm(Fe))(Fes)
# print(Fs)

e_v_11 = (2. / 3.) * strain_rate * times - \
(2. / 3.) * strain_rate * self.tau_1 * (1. - np.exp(-times / self.tau_1))

e_e_11 = strain_rate * times - e_v_11
e_e_22 = 0.5 * e_v_11

Ee_analytic = jax.vmap(
lambda e_11, e_22: np.array(
[[e_11, 0., 0.],
[0., e_22, 0.],
[0., 0., e_22]]
), in_axes=(0, 0)
)(e_e_11, e_e_22)
Me_analytic = jax.vmap(lambda Ee: 2. * self.G_neq_1 * deviator(Ee))(Ee_analytic)
Dv_analytic = jax.vmap(lambda Me: 1. / (2. * self.G_neq_1 * self.tau_1) * deviator(Me))(Me_analytic)
dissipations_analytic = jax.vmap(lambda Me, Dv: np.tensordot(Me, Dv), in_axes=(0, 0))(Me_analytic, Dv_analytic)

# calculate Mandel stress to compare dissipation
Dvs = jax.vmap(lambda Ee: (1. / self.tau_1) * deviator(Ee))(Ees)
Mes = jax.vmap(lambda Ee: 2. * self.G_neq_1 * deviator(Ee))(Ees)
dissipations = jax.vmap(lambda D, M: np.tensordot(D, M), in_axes=(0, 0))(Dvs, Mes)


self.assertArrayNear(Evs[:, 0, 0], e_v_11, 3)
self.assertArrayNear(Ees[:, 0, 0], e_e_11, 3)
self.assertArrayNear(Ees[:, 1, 1], e_e_22, 3)
self.assertArrayNear(dissipations, dissipations_analytic, 3)

if plotting:
plt.figure(1)
plt.plot(times, np.log(Fs[:, 0, 0]))
plt.savefig('times_Fs.png')

plt.figure(2)
plt.plot(times, energies)
plt.savefig('times_energies.png')

plt.figure(3)
plt.plot(times, Evs[:, 0, 0], marker='o', linestyle='None', markevery=10)
plt.plot(times, e_v_11, linestyle='--')
plt.xlabel('Time (s)')
plt.ylabel('Viscous Logarithmic Strain 11 component')
plt.savefig('times_viscous_stretch.png')

plt.figure(4)
plt.plot(times, Ees[:, 0, 0], marker='o', linestyle='None', markevery=10, label='11', color='blue')
plt.plot(times, Ees[:, 1, 1], marker='o', linestyle='None', markevery=10, label='22', color='red')
plt.plot(times, e_e_11, linestyle='--', color='blue')
plt.plot(times, e_e_22, linestyle='--', color='red')
plt.xlabel('Time (s)')
plt.ylabel('Viscous Elastic Strain')
plt.legend(loc='best')
plt.savefig('times_elastic_stretch.png')

plt.figure(5)
plt.plot(times, dissipations, marker='o', linestyle='None', markevery=10)
plt.plot(times, dissipations_analytic, linestyle='--')
plt.savefig('times_dissipation.png')


class HyperViscoUniaxial(TestFixture):
def setUp(self):
G_eq = 0.855 # MPa
K_eq = 1*G_eq # MPa - artificially low bulk modulus so that volumetric strain energy doesn't drown out the dissipation (which is deviatoric)
K_eq = 1*G_eq # MPa - artificially low bulk modulus so that volumetric strain energy doesn't drown out the dissipation (which is deviator)
G_neq_1 = 5.0
tau_1 = 0.1
self.props = {
Expand Down Expand Up @@ -159,6 +261,9 @@ def free_energy(dispGrad, state, dt):

self.assertArrayNear(dissipatedEnergyHistory, internalEnergyHistory - freeEnergyHistory, 5)






if __name__ == '__main__':
unittest.main()

0 comments on commit 8134e6c

Please sign in to comment.