import json import warp as wp from mpm_solver_warp.mpm_solver_warp import MPM_Simulator_WARP from mpm_solver_warp.engine_utils import * def decode_param_json(json_file): f = open(json_file) sim_params = json.load(f) material_params = {} # material parameters if "material" in sim_params.keys(): material_params["material"] = sim_params["material"] else: material_params["material"] = "jelly" if "grid_lim" in sim_params.keys(): material_params["grid_lim"] = sim_params["grid_lim"] else: material_params["grid_lim"] = 2.0 if "n_grid" in sim_params.keys(): material_params["n_grid"] = sim_params["n_grid"] else: material_params["n_grid"] = 50 if "nu" in sim_params.keys(): material_params["nu"] = sim_params["nu"] else: material_params["nu"] = 0.4 if "E" in sim_params.keys(): material_params["E"] = sim_params["E"] else: material_params["E"] = 1e5 if "scale_E" in sim_params.keys(): material_params["scale_E"] = sim_params["scale_E"] else: material_params["scale_E"] = 1e7 # add if "mu_N" in sim_params.keys(): material_params["mu_N"] = sim_params["mu_N"] else: material_params["mu_N"] = 5 if "lam_N" in sim_params.keys(): material_params["lam_N"] = sim_params["lam_N"] else: material_params["lam_N"] = 5 if "viscosity" in sim_params.keys(): material_params["viscosity"] = sim_params["viscosity"] else: material_params["viscosity"] = 1e-1 # add end if "yield_stress" in sim_params.keys(): material_params["yield_stress"] = sim_params["yield_stress"] if "scale_ys" in sim_params.keys(): material_params["scale_ys"] = sim_params["scale_ys"] else: material_params["scale_ys"] = 1e5 if "hardening" in sim_params.keys(): material_params["hardening"] = sim_params["hardening"] if "xi" in sim_params.keys(): material_params["xi"] = sim_params["xi"] if "friction_angle" in sim_params.keys(): material_params["friction_angle"] = sim_params["friction_angle"] if "plastic_viscosity" in sim_params.keys(): material_params["plastic_viscosity"] = sim_params["plastic_viscosity"] if "scale_pv" in sim_params.keys(): material_params["scale_pv"] = sim_params["scale_pv"] else: material_params["scale_pv"] = 1e4 if "g" in sim_params.keys(): material_params["g"] = sim_params["g"] else: material_params["g"] = 9.8 if "density" in sim_params.keys(): material_params["density"] = sim_params["density"] else: material_params["density"] = 200.0 if "rpic_damping" in sim_params.keys(): material_params["rpic_damping"] = sim_params["rpic_damping"] if "pic_damping" in sim_params.keys(): material_params["pic_damping"] = sim_params["pic_damping"] if "softening" in sim_params.keys(): material_params["softening"] = sim_params["softening"] if "opacity_threshold" in sim_params.keys(): material_params["opacity_threshold"] = sim_params["opacity_threshold"] if "grid_v_damping_scale" in sim_params.keys(): material_params["grid_v_damping_scale"] = sim_params["grid_v_damping_scale"] if "additional_material_params" in sim_params.keys(): additional_params = sim_params["additional_material_params"] for i in range(len(additional_params)): if not "point" in additional_params[i].keys(): raise TypeError("point is not defined") if not "size" in additional_params[i].keys(): raise TypeError("size is not defined") if not "E" in additional_params[i].keys(): raise TypeError("E is not defined") if not "nu" in additional_params[i].keys(): raise TypeError("nu is not defined") if not "density" in additional_params[i].keys(): additional_params[i]["density"] = material_params["density"] material_params["additional_material_params"] = additional_params # boundary conditions bc_params = {} if "boundary_conditions" in sim_params.keys(): bc_params = sim_params["boundary_conditions"] # time step time_params = {} if "substep_dt" in sim_params.keys(): time_params["substep_dt"] = sim_params["substep_dt"] else: time_params["substep_dt"] = 1e-4 if "frame_dt" in sim_params.keys(): time_params["frame_dt"] = sim_params["frame_dt"] else: time_params["frame_dt"] = 1e-2 if "opt_frame_dt" in sim_params.keys(): time_params["opt_frame_dt"] = sim_params["opt_frame_dt"] else: time_params["opt_frame_dt"] = 1e-2 if "frame_num" in sim_params.keys(): time_params["frame_num"] = sim_params["frame_num"] else: time_params["frame_num"] = 100 # preprocessing_params preprocessing_params = {} if "opacity_threshold" in sim_params.keys(): preprocessing_params["opacity_threshold"] = sim_params["opacity_threshold"] else: preprocessing_params["opacity_threshold"] = 0.02 if "rotation_degree" in sim_params.keys(): preprocessing_params["rotation_degree"] = sim_params["rotation_degree"] else: preprocessing_params["rotation_degree"] = [] if "rotation_axis" in sim_params.keys(): preprocessing_params["rotation_axis"] = sim_params["rotation_axis"] else: preprocessing_params["rotation_axis"] = [] if "sim_area" in sim_params.keys(): preprocessing_params["sim_area"] = sim_params["sim_area"] else: preprocessing_params["sim_area"] = None if "particle_filling" in sim_params.keys(): preprocessing_params["particle_filling"] = sim_params["particle_filling"] filling_params = preprocessing_params["particle_filling"] if not "n_grid" in filling_params.keys(): filling_params["n_grid"] = material_params["n_grid"] * 4 if not "density_threshold" in filling_params.keys(): filling_params["density_threshold"] = 5.0 if not "search_threshold" in filling_params.keys(): filling_params["search_threshold"] = 3.0 if not "max_particles_num" in filling_params.keys(): filling_params["max_particles_num"] = 2000000 if not "max_partciels_per_cell" in filling_params.keys(): filling_params["max_partciels_per_cell"] = 1 if not "search_exclude_direction" in filling_params.keys(): filling_params["search_exclude_direction"] = 5 if not "ray_cast_direction" in filling_params.keys(): filling_params["ray_cast_direction"] = 4 if not "boundary" in filling_params.keys(): filling_params["boundary"] = None if not "smooth" in filling_params.keys(): filling_params["smooth"] = False if not "visualize" in filling_params.keys(): filling_params["visualize"] = False else: preprocessing_params["particle_filling"] = None # camera params camera_params = {} if "mpm_space_viewpoint_center" in sim_params.keys(): camera_params["mpm_space_viewpoint_center"] = sim_params[ "mpm_space_viewpoint_center" ] else: camera_params["mpm_space_viewpoint_center"] = [1.0, 1.0, 1.0] if "mpm_space_vertical_upward_axis" in sim_params.keys(): camera_params["mpm_space_vertical_upward_axis"] = sim_params[ "mpm_space_vertical_upward_axis" ] else: camera_params["mpm_space_vertical_upward_axis"] = [0, 0, 1] if "default_camera_index" in sim_params.keys(): camera_params["default_camera_index"] = sim_params["default_camera_index"] else: camera_params["default_camera_index"] = 0 if "show_hint" in sim_params.keys(): camera_params["show_hint"] = sim_params["show_hint"] else: camera_params["show_hint"] = False if "init_azimuthm" in sim_params.keys(): camera_params["init_azimuthm"] = sim_params["init_azimuthm"] else: camera_params["init_azimuthm"] = None if "init_elevation" in sim_params.keys(): camera_params["init_elevation"] = sim_params["init_elevation"] else: camera_params["init_elevation"] = None if "init_radius" in sim_params.keys(): camera_params["init_radius"] = sim_params["init_radius"] else: camera_params["init_radius"] = None if "delta_a" in sim_params.keys(): camera_params["delta_a"] = sim_params["delta_a"] else: camera_params["delta_a"] = None if "delta_e" in sim_params.keys(): camera_params["delta_e"] = sim_params["delta_e"] else: camera_params["delta_e"] = None if "delta_r" in sim_params.keys(): camera_params["delta_r"] = sim_params["delta_r"] else: camera_params["delta_r"] = None if "move_camera" in sim_params.keys(): camera_params["move_camera"] = sim_params["move_camera"] else: camera_params["move_camera"] = False optimize_params = {} if "line" in sim_params.keys(): optimize_params["line"] = sim_params["line"] if "bbox_2d" in sim_params.keys(): optimize_params["bbox_2d"] = sim_params["bbox_2d"] if "reduction" in sim_params.keys(): optimize_params["reduction"] = sim_params["reduction"] else: optimize_params["reduction"] = "sum" if "lr" in sim_params.keys(): optimize_params["lr"] = sim_params["lr"] return material_params, bc_params, time_params, preprocessing_params, camera_params, optimize_params def set_boundary_conditions( mpm_solver: MPM_Simulator_WARP, bc_params: dict, time_params: dict ): for bc in bc_params: if bc["type"] == "cuboid": assert ( "point" in bc.keys() and "size" in bc.keys() and "velocity" in bc.keys() ) start_time = 0.0 end_time = 1e3 reset = 0 if "start_time" in bc.keys(): start_time = bc["start_time"] if "end_time" in bc.keys(): end_time = bc["end_time"] if "reset" in bc.keys(): reset = bc["reset"] mpm_solver.set_velocity_on_cuboid( point=bc["point"], size=bc["size"], velocity=bc["velocity"], start_time=start_time, end_time=end_time, reset=reset, ) elif bc["type"] == "particle_impulse": assert "force" in bc.keys() start_time = 0.0 if "start_time" in bc.keys(): start_time = bc["start_time"] num_dt = 1 if "num_dt" in bc.keys(): num_dt = bc["num_dt"] point = [1, 1, 1] if "point" in bc.keys(): point = bc["point"] size = [1, 1, 1] if "size" in bc.keys(): size = bc["size"] mpm_solver.add_impulse_on_particles( force=bc["force"], dt=time_params["substep_dt"], point=point, size=size, num_dt=num_dt, start_time=start_time, ) elif bc["type"] == "bounding_box": mpm_solver.add_bounding_box() elif bc["type"] == "enforce_particle_translation": assert "point" in bc.keys() assert "size" in bc.keys() assert "velocity" in bc.keys() assert "start_time" in bc.keys() assert "end_time" in bc.keys() mpm_solver.enforce_particle_velocity_translation( point=bc["point"], size=bc["size"], velocity=bc["velocity"], start_time=bc["start_time"], end_time=bc["end_time"], ) elif bc["type"] == "surface_collider": assert "point" in bc.keys() assert "normal" in bc.keys() assert "surface" in bc.keys() assert "friction" in bc.keys() assert "start_time" in bc.keys() assert "end_time" in bc.keys() mpm_solver.add_surface_collider( point=bc["point"], normal=bc["normal"], surface=bc["surface"], friction=bc["friction"], start_time=bc["start_time"], end_time=bc["end_time"], ) elif bc["type"] == "release_particles_sequentially": assert "normal" in bc.keys() assert "start_position" in bc.keys() assert "end_position" in bc.keys() assert "num_layers" in bc.keys() assert "start_time" in bc.keys() assert "end_time" in bc.keys() mpm_solver.release_particles_sequentially( normal=bc["normal"], start_position=bc["start_position"], end_position=bc["end_position"], num_layers=bc["num_layers"], start_time=bc["start_time"], end_time=bc["end_time"], ) elif bc["type"] == "release_particles_sequentially_size": assert "normal" in bc.keys() assert "start_position" in bc.keys() assert "end_position" in bc.keys() assert "num_layers" in bc.keys() assert "start_time" in bc.keys() assert "end_time" in bc.keys() assert "size" in bc.keys() assert "point" in bc.keys() mpm_solver.release_particles_sequentially_size( normal=bc["normal"], start_position=bc["start_position"], end_position=bc["end_position"], num_layers=bc["num_layers"], start_time=bc["start_time"], end_time=bc["end_time"], size=bc["size"], point=bc["point"], ) elif bc["type"] == "enforce_particle_velocity_rotation": assert "normal" in bc.keys() assert "point" in bc.keys() assert "start_time" in bc.keys() assert "end_time" in bc.keys() assert "half_height_and_radius" in bc.keys() assert "rotation_scale" in bc.keys() assert "translation_scale" in bc.keys() mpm_solver.enforce_particle_velocity_rotation( point=bc["point"], normal=bc["normal"], half_height_and_radius=bc["half_height_and_radius"], rotation_scale=bc["rotation_scale"], translation_scale=bc["translation_scale"], start_time=bc["start_time"], end_time=bc["end_time"], ) else: raise TypeError("Undefined BC type") def find_far_points(xyzs, selected_points, thres=0.05): """ Args: xyzs: [N, 3] selected_points: [M, 3] Outs: freeze_mask: [N], 1 for points that are far away, 0 for points that are close dtype=torch.int """ chunk_size = 10000 freeze_mask_list = [] for i in range(0, xyzs.shape[0], chunk_size): end_index = min(i + chunk_size, xyzs.shape[0]) xyzs_chunk = xyzs[i:end_index] # [M, N] cdist = torch.cdist(xyzs_chunk, selected_points) min_dist, _ = torch.min(cdist, dim=-1) freeze_mask = min_dist > thres freeze_mask = freeze_mask.type(torch.int) freeze_mask_list.append(freeze_mask) freeze_mask = torch.cat(freeze_mask_list, dim=0) # 1 for points that are far away, 0 for points that are close return freeze_mask device = freeze_pts.device grid_pts_cnt = torch.zeros( (grid_size, grid_size, grid_size), dtype=torch.int32, device=device ) dx = grid_lim / grid_size inv_dx = 1.0 / dx freeze_pts = (freeze_pts * inv_dx).long() for x, y, z in freeze_pts: grid_pts_cnt[x, y, z] += 1 freeze_grid_mask = grid_pts_cnt >= 1 freeze_grid_mask_int = freeze_grid_mask.type(torch.int32) number_freeze_grid = freeze_grid_mask_int.sum().item() print("number of freeze grid", number_freeze_grid) mpm_solver.enforce_grid_velocity_by_mask(freeze_grid_mask_int) # add debug section: return freeze_grid_mask