34 KiB
34 KiB
In [1]:
import numpy as np
import torch
import igl
import time
import meshplot as mp
import sys as _sys
_sys.path.append("../src")
from elasticenergy import *
from elasticsolid import *
from adjoint_sensitivity import *
from vis_utils import *
from objectives import *
from harmonic_interpolator import *
from shape_optimizer import *
from utils import *
shadingOptions = {
"flat":True,
"wireframe":False,
}
rot = np.array(
[[1, 0, 0 ],
[0, 0, 1],
[0, -1, 0 ]]
)
torch.set_default_dtype(torch.float64)
def to_numpy(tensor):
return tensor.detach().clone().numpy()In [2]:
vNP, _, _, tNP, _, _ = igl.read_obj("../data/beam.obj")
aabb = np.max(vNP, axis=0) - np.min(vNP, axis=0)
length_scale = np.mean(aabb)
v, t = torch.tensor(vNP), torch.tensor(tNP)
eNP = igl.edges(tNP)
beNP = igl.edges(igl.boundary_facets(tNP))
def get_boundary_and_interior(vlen, t):
bv = np.unique(igl.boundary_facets(t))
vIdx = np.arange(vlen)
iv = vIdx[np.invert(np.in1d(vIdx, bv))]
return bv, iv
# Compute boundary vertices and interior vertex indices
bvNP, ivNP = get_boundary_and_interior(v.shape[0], tNP)
mp.plot(vNP @ rot.T, np.array(tNP), shading=shadingOptions)Out [2]:
Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(5.0, 1.0,…
<meshplot.Viewer.Viewer at 0x7f4f18719760>
In [3]:
rho = 131 # [kg.m-3]
damping = 0.
young = 5e7 # [Pa]
poisson = 0.2
# Find some of the lowest vertices and pin them
minX = torch.min(v[:, 0])
pin_idx = torch.arange(v.shape[0])[v[:, 0] < minX + 0.2*aabb[0]]
vIdx = np.arange(v.shape[0])
pin_idx = vIdx[np.in1d(vIdx, bvNP) & np.in1d(vIdx, pin_idx)]
print("Pinned vertices: {}".format(pin_idx))Pinned vertices: [ 0 1 11 12 22 23 33 34 44 54 55 75 76 86 87 88 89]
In [4]:
# Inverted gravity
force_mass = torch.zeros(size=(3,))
force_mass[2] = + rho * 9.81
# Gravity going in the wrong direction
ee = NeoHookeanElasticEnergy(young, poisson)
v = HarmonicInterpolator(v, t, ivNP).interpolate(v[bvNP])
solid_init = ElasticSolid(v, t, ee, rho=rho, pin_idx=pin_idx, f_mass=force_mass)
solid_init.find_equilibrium()
plot_torch_solid(solid_init, beNP, rot, length_scale)
# Use these as initial guesses
v_init_rest = solid_init.v_def.clone().detach()
v_init_def = solid_init.v_rest.clone().detach()
# v_init_rest = solid_init.v_rest.clone().detach()
# v_init_def = solid_init.v_def.clone().detach()Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(4.9017367…
In [5]:
force_mass = torch.zeros(size=(3,))
force_mass[2] = - rho * 9.81
use_linear = False
# The target is the initial raw mesh
vt_surf = torch.tensor(vNP[bvNP, :])
# Create solid
if use_linear:
ee = LinearElasticEnergy(young, poisson)
else:
ee = NeoHookeanElasticEnergy(young, poisson)
solid_ = ElasticSolid(v_init_rest, t, ee, rho=rho, pin_idx=pin_idx, f_mass=force_mass)
solid_.update_def_shape(v_init_def)
optimizer = ShapeOptimizer(solid_, vt_surf, weight_reg=10.)
v_eq_init = optimizer.solid.v_def.clone().detach() #bookkeepingInitial objective: 1.6230e+00
In [6]:
optimizer.optimize(step_size_init=1e-2, max_l_iter=10, n_optim_steps=40)Objective after 40 optimization step(s): 1.5788e+00
Line search Iters: 9
Elapsed time: 97.1s.
Estimated remaining time: 0.0s
Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(5.0444669…
In [7]:
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
plt.plot(to_numpy(optimizer.objectives[optimizer.objectives > 0]))
plt.title("Objective as optimization goes", fontsize=14)
plt.xlabel("Optimization steps", fontsize=12)
plt.ylabel("Objective", fontsize=12)
plt.grid()
plt.show()In [8]:
p = mp.plot(np.array(optimizer.solid.v_def) @ rot.T, tNP, shading=shadingOptions)
# p.add_points(np.array(optimizer.solid.v_def)[pin_idx, :] @ rot.T, shading={"point_color":"black", "point_size": 0.2})
p.add_edges(np.array(v_init_rest) @ rot.T, beNP, shading={"line_color": "green"})
p.add_edges(vNP @ rot.T, beNP, shading={"line_color": "red"})
p.add_edges(np.array(v_eq_init) @ rot.T, beNP, shading={"line_color": "black"})
p.add_edges(np.array(optimizer.solid.v_rest) @ rot.T, beNP, shading={"line_color": "blue"})
Out [8]:
Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(5.0444669…
4
In [9]:
v_rest_optim_g = optimizer.solid.v_rest.clone().detach() #bookkeepingIn [10]:
maxX = torch.min(v[:, 0])
f_point_idx = torch.arange(v.shape[0])[v[:, 0] > maxX - 0.01*aabb[0]]
f_point = torch.zeros(size=(f_point_idx.shape[0], 3))
f_point[:, 2] = -5e4
optimizer.solid.add_point_load(f_point_idx, f_point)
optimizer.set_params(optimizer.params)
v_def_optim_g_under_point = optimizer.solid.v_def.clone().detach() #bookkeepingIn [ ]:
optimizer.reset_BFGS()
optimizer.optimize(step_size_init=1e-2, max_l_iter=10, n_optim_steps=100)Objective after 21 optimization step(s): 2.2335e+01
Line search Iters: 9
Elapsed time: 2215.2s.
Estimated remaining time: 8333.3s
Renderer(camera=PerspectiveCamera(children=(DirectionalLight(color='white', intensity=0.6, position=(5.0945925…
In [ ]:
p = mp.plot(np.array(optimizer.solid.v_def) @ rot.T, tNP, shading=shadingOptions)
# p.add_points(np.array(optimizer.solid.v_def)[pin_idx, :] @ rot.T, shading={"point_color":"black", "point_size": 0.2})
p.add_edges(np.array(v_rest_optim_g) @ rot.T, beNP, shading={"line_color": "green"})
p.add_edges(vNP @ rot.T, beNP, shading={"line_color": "red"})
p.add_edges(np.array(v_def_optim_g_under_point) @ rot.T, beNP, shading={"line_color": "black"})
p.add_edges(np.array(optimizer.solid.v_rest) @ rot.T, beNP, shading={"line_color": "blue"})