14 KiB
14 KiB
In [1]:
import numpy as np
import igl
import meshplot as mp
import time
import sys as _sys
_sys.path.append("../src")
from elasticsolid import *
from elasticenergy import *
from matplotlib import gridspec
import matplotlib.pyplot as plt
shadingOptions = {
"flat":True,
"wireframe":False,
}
rot = np.array(
[[1, 0, 0 ],
[0, 0, 1],
[0, -1, 0 ]]
)In [2]:
v, _, _, t, _, _ = igl.read_obj("../data/dinosaur.obj")
# v, _, _, t, _, _ = igl.read_obj("../data/beam.obj")
# t = np.array([
# [0, 1, 2, 3],
# [1, 2, 3, 4]
# ])
# v = np.array([
# [0., 0., 0.],
# [1., 0., 0.],
# [0., 1., 0.],
# [0., 0., 1.],
# [2/3, 2/3, 2/3]
# ])
be = igl.edges(igl.boundary_facets(t))
e = igl.edges(t)
aabb = np.max(v, axis=0) - np.min(v, axis=0)
length_scale = np.mean(aabb)
p = mp.plot(v @ rot.T, t, shading=shadingOptions)Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-1.987469…
In [3]:
rho = 131 # [kg.m-3]
young = 3e8 # [Pa]
poisson = 0.2
force_mass = np.zeros(shape = (3,))
force_mass[2] = - rho * 9.81
# minX = np.min(v[:, 0])
# pin_idx = np.arange(v.shape[0])[v[:, 0] < minX + 0.2*aabb[0]]
minZ = np.min(v[:, 2])
pin_idx = np.arange(v.shape[0])[v[:, 2] < minZ + 0.1*aabb[2]]
# ee = LinearElasticEnergy(young, poisson)
ee = NeoHookeanElasticEnergy(young, poisson)
solid = ElasticSolid(v, t, ee, rho=rho, pin_idx=pin_idx, f_mass=force_mass)
In [4]:
v_def = v.copy()
v_def[:, 0] *= 2.
solid.update_def_shape(v_def)
p = mp.plot(solid.v_def @ rot.T, solid.t, shading=shadingOptions)
p.add_points(solid.v_def[solid.pin_idx, :] @ rot.T, shading={"point_color":"black", "point_size": 0.1 * length_scale})
forcesScale = 2 * np.max(np.linalg.norm(solid.f_ext, axis=1))
p.add_lines(solid.v_def @ rot.T, (solid.v_def + solid.f_ext / forcesScale) @ rot.T)
p.add_edges(v @ rot.T, be, shading={"line_color": "blue"})
Out [4]:
Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-3.974938…
3
In [5]:
n_steps = 1000
thresh = 1.
v_init = v.copy()In [6]:
%run ../src/Utils.py
report_GD = equilibrium_convergence_report_GD(solid, v_init, n_steps, 1e-8, thresh=thresh)
energies_el_GD = report_GD['energies_el']
energies_ext_GD = report_GD['energies_ext']
energy_GD = energies_el_GD + energies_ext_GD
residuals_GD = report_GD['residuals']
times_GD = report_GD['times']
idx_stop_GD = report_GD['idx_stop']
v_def_GD = solid.v_def.copy()
# Lastly, plot the resulting shape
p = mp.plot(v_def_GD @ rot.T, solid.t, shading=shadingOptions)
forcesScale = 2 * np.max(np.linalg.norm(solid.f_ext, axis=1))
p.add_lines(v_def_GD @ rot.T, (solid.v_def + solid.f_ext / forcesScale) @ rot.T)
p.add_points(v_def_GD[pin_idx, :] @ rot.T, shading={"point_color":"black", "point_size": 0.1 * length_scale})
p.add_edges(v @ rot.T, be, shading={"line_color": "blue"})Out [6]:
Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-1.987469…
3
In [7]:
report_BFGS = equilibrium_convergence_report_BFGS(solid, v_init, n_steps, 1e-8, thresh=thresh)
energies_el_BFGS = report_BFGS['energies_el']
energies_ext_BFGS = report_BFGS['energies_ext']
energy_BFGS = energies_el_BFGS + energies_ext_BFGS
residuals_BFGS = report_BFGS['residuals']
times_BFGS = report_BFGS['times']
idx_stop_BFGS = report_BFGS['idx_stop']
v_def_BFGS = solid.v_def.copy()
# Lastly, plot the resulting shape
p = mp.plot(v_def_BFGS @ rot.T, solid.t, shading=shadingOptions)
forcesScale = 2 * np.max(np.linalg.norm(solid.f_ext, axis=1))
p.add_lines(v_def_BFGS @ rot.T, (solid.v_def + solid.f_ext / forcesScale) @ rot.T)
p.add_points(v_def_BFGS[pin_idx, :] @ rot.T, shading={"point_color":"black", "point_size": 0.1 * length_scale})
p.add_edges(v @ rot.T, be, shading={"line_color": "blue"})Out [7]:
Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(-0.297981…
3
In [ ]:
report_NCG = equilibrium_convergence_report_NCG(solid, v_init, n_steps, thresh=thresh)
energies_el_NCG = report_NCG['energies_el']
energies_ext_NCG = report_NCG['energies_ext']
energy_NCG = energies_el_NCG + energies_ext_NCG
residuals_NCG = report_NCG['residuals']
times_NCG = report_NCG['times']
idx_stop_NCG = report_NCG['idx_stop']
v_def_NCG = solid.v_def.copy()
# Lastly, plot the resulting shape
p = mp.plot(v_def_NCG @ rot.T, solid.t, shading=shadingOptions)
forcesScale = 2 * np.max(np.linalg.norm(solid.f_ext, axis=1))
p.add_lines(v_def_NCG @ rot.T, (solid.v_def + solid.f_ext / forcesScale) @ rot.T)
p.add_points(v_def_NCG[pin_idx, :] @ rot.T, shading={"point_color":"black", "point_size": 0.1 * length_scale})
p.add_edges(v @ rot.T, be, shading={"line_color": "blue"})Energy: -127985.65419881282 Force norm: 287742.8969935862 Line search Iters: 0 Energy: -178892.14400109363 Force norm: 182952.00531737506 Line search Iters: 0 Energy: -206901.42653635694 Force norm: 151950.01953001413 Line search Iters: 0 Energy: -227792.85782151608 Force norm: 135158.66283929092 Line search Iters: 0 Energy: -244838.85692066932 Force norm: 123433.77675577633 Line search Iters: 0 Energy: -259318.48388755036 Force norm: 114389.35466936302 Line search Iters: 0 Energy: -271937.0843840749 Force norm: 107190.15322070086 Line search Iters: 0 Energy: -283160.0740997393 Force norm: 101411.77988596291 Line search Iters: 0
In [ ]:
cmap = plt.get_cmap('viridis')
colors = cmap(np.linspace(0., 1., 4))
gs = gridspec.GridSpec(nrows=1, ncols=1, width_ratios=[1], height_ratios=[1])
fig = plt.figure(figsize=(10, 6))
axTmp = plt.subplot(gs[0, 0])
axTmp.plot(times_GD[:idx_stop_GD+1], residuals_GD[:idx_stop_GD+1], c=colors[0],
label="Gradient Descent ({:}its)".format(idx_stop_GD))
axTmp.plot(times_BFGS[:idx_stop_BFGS+1], residuals_BFGS[:idx_stop_BFGS+1], c=colors[1],
label="BFGS ({:}its)".format(idx_stop_BFGS))
axTmp.plot(times_NCG[:idx_stop_NCG+1], residuals_NCG[:idx_stop_NCG+1], c=colors[2],
label="Newton-CG ({:}its)".format(idx_stop_NCG))
y_lim = axTmp.get_ylim()
axTmp.set_title("Residuals as optimization goes", fontsize=14)
axTmp.set_xlabel("Computation time [s]", fontsize=12)
axTmp.set_ylabel("Force residuals [N]", fontsize=12)
axTmp.set_ylim(y_lim)
plt.legend(fontsize=12)
plt.grid()
plt.show()In [ ]:
gs = gridspec.GridSpec(nrows=1, ncols=1, width_ratios=[1], height_ratios=[1])
fig = plt.figure(figsize=(10, 6))
axTmp = plt.subplot(gs[0, 0])
axTmp.plot(times_GD[:idx_stop_GD+1], energy_GD[:idx_stop_GD+1], c=colors[0],
label="Gradient Descent ({:}its)".format(idx_stop_GD))
axTmp.plot(times_BFGS[:idx_stop_BFGS+1], energy_BFGS[:idx_stop_BFGS+1], c=colors[1],
label="BFGS ({:}its)".format(idx_stop_BFGS))
axTmp.plot(times_NCG[:idx_stop_NCG+1], energy_NCG[:idx_stop_NCG+1], c=colors[2],
label="Newton-CG ({:}its)".format(idx_stop_NCG))
y_lim = axTmp.get_ylim()
axTmp.set_title("Total energy as optimization goes", fontsize=14)
axTmp.set_xlabel("Computation time [s]", fontsize=12)
axTmp.set_ylabel("Energy [J]", fontsize=12)
axTmp.set_ylim(y_lim)
plt.legend(fontsize=12)
plt.grid()
plt.show()In [ ]: