https://github.com/mit-gfx/diff_stokes_flow
Tip revision: 06c427ae445a42c2af68f712e4ee187753ea2d3c authored by Tao Du on 19 January 2021, 02:50:11 UTC
Added minimum compliance.
Added minimum compliance.
Tip revision: 06c427a
amplifier_env_2d.py
import numpy as np
from py_diff_stokes_flow.env.env_base import EnvBase
from py_diff_stokes_flow.common.common import ndarray
class AmplifierEnv2d(EnvBase):
def __init__(self, seed, folder):
np.random.seed(seed)
cell_nums = (64, 48)
E = 100
nu = 0.499
vol_tol = 1e-3
edge_sample_num = 2
EnvBase.__init__(self, cell_nums, E, nu, vol_tol, edge_sample_num, folder)
# Initialize the parametric shapes.
self._parametric_shape_info = [ ('bezier', 8), ('bezier', 8) ]
# Initialize the node conditions.
self._node_boundary_info = []
inlet_velocity = 1
inlet_range = ndarray([0.125, 0.875])
inlet_lb, inlet_ub = inlet_range * cell_nums[1]
for j in range(cell_nums[1] + 1):
if inlet_lb < j < inlet_ub:
self._node_boundary_info.append(((0, j, 0), inlet_velocity))
self._node_boundary_info.append(((0, j, 1), 0))
# Initialize the interface.
self._interface_boundary_type = 'free-slip'
# Other data members.
self._inlet_velocity = inlet_velocity
self._outlet_velocity = 3 * inlet_velocity
self._inlet_range = inlet_range
def _variables_to_shape_params(self, x):
x = ndarray(x).copy().ravel()
assert x.size == 5
cx, cy = self._cell_nums
# Convert x to the shape parameters.
lower = ndarray([
[1, x[4]],
x[2:4],
x[:2],
[0, self._inlet_range[0]],
])
lower[:, 0] *= cx
lower[:, 1] *= cy
upper = ndarray([
[0, self._inlet_range[1]],
[x[0], 1 - x[1]],
[x[2], 1 - x[3]],
[1, 1 - x[4]],
])
upper[:, 0] *= cx
upper[:, 1] *= cy
params = np.concatenate([lower.ravel(), upper.ravel()])
# Jacobian.
J = np.zeros((params.size, x.size))
J[1, 4] = 1
J[2, 2] = 1
J[3, 3] = 1
J[4, 0] = 1
J[5, 1] = 1
J[10, 0] = 1
J[11, 1] = -1
J[12, 2] = 1
J[13, 3] = -1
J[15, 4] = -1
# Scale it by cx and cy.
J[:, 0] *= cx
J[:, 2] *= cx
J[:, 1] *= cy
J[:, 3] *= cy
J[:, 4] *= cy
return ndarray(params).copy(), ndarray(J).copy()
def _loss_and_grad(self, scene, u):
param_size = self._variables_to_shape_params(self.lower_bound())[0].size
grad_param = ndarray(np.zeros(param_size))
u_field = self.reshape_velocity_field(u)
grad = np.zeros(u_field.shape)
cnt = 0
loss = 0
for j, (ux, uy) in enumerate(u_field[-1]):
if ux > 0:
cnt += 1
u_diff = ndarray([ux, uy]) - ndarray([self._outlet_velocity, 0])
loss += u_diff.dot(u_diff)
grad[-1, j] += 2 * u_diff
loss /= cnt
grad /= cnt
return loss, ndarray(grad).ravel(), grad_param
def sample(self):
return np.random.uniform(low=self.lower_bound(), high=self.upper_bound())
def lower_bound(self):
return ndarray([0.16, 0.05, 0.49, 0.05, 0.05])
def upper_bound(self):
return ndarray([0.49, 0.49, 0.83, 0.49, 0.49])