62 mesh_size: float = MESH_SIZE) -> dict[str, object]:
63 """Pack spacing and container dimensions, all derived from R and the mesh.
65 The gap between grains is slightly larger than the contact radius, so that
66 no pair is in contact at t = 0. Gravity and the plate bring pairs into
69 horizon = 3.0 * mesh_size
70 h_est = 0.7 * mesh_size
72 padding = 1.15 * rc_est
73 rwp = horizon + padding
74 wall_t = rwp - padding
76 step = 2.0 * r + padding
77 lin = 2.0 * padding + 2.0 * r + (ncols - 1) * step
78 win = 2.0 * padding + 2.0 * r + (nrows - 1) * step
80 sites = [(padding + r + i * step, padding + r + j * step)
81 for j
in range(nrows)
for i
in range(ncols)]
83 "horizon": horizon,
"padding": padding,
"rwp": rwp,
"wall_t": wall_t,
84 "Lin": lin,
"Win": win,
"sites": sites,
86 "cup": [-rwp, -rwp, lin + rwp, win + wall_t, wall_t, 0.0],
87 "plate": [-padding, win, 0.0, lin + padding, win + wall_t, 0.0],
91def build_deck(output_path: str | os.PathLike[str] =
"runs/", *,
92 ncols: int = NCOLS, nrows: int = NROWS,
93 final_time: float = FINAL_TIME, num_steps: int = NUM_STEPS,
94 mesh_size: float = MESH_SIZE,
95 search_interval: int = SEARCH_INTERVAL,
96 mesh_dir: str | os.PathLike[str] |
None =
None,
97 write_mesh: bool =
True,
98 in_process_mesh: bool =
False) -> Deck:
100 horizon = float(g[
"horizon"])
106 Kn = contact_stiffness(K, K, horizon)
108 d = Deck(dim=2, t_final=final_time, n_steps=num_steps)
109 d.set_comment(
"jha2021_comp_contact")
111 dt_out = max(1, num_steps // 4)
112 d.set_output(output_path, tags=TAGS, interval=dt_out, debug=1,
113 dt_test_out=max(1, dt_out // 10), tag_pp=
"0",
115 d.set_gravity(0.0, -GRAVITY)
116 d.set_neighbor(update_criteria=
"simple_all", s_factor=5.0, update_interval=search_interval,
117 near_bd_nodes_tol=0.5)
119 grain = Geometry(
"circle", [R, 0.0, 0.0, 0.0])
120 cup = Geometry(
"open_rect_channel_2d", list(g[
"cup"]))
121 plate = Geometry(
"rectangle", list(g[
"plate"]))
124 meshes = [MeshSpec(size=mesh_size)
for _
in range(3)]
126 base = Path(mesh_dir)
if mesh_dir
is not None else HERE
127 meshes = [MeshSpec(file=base / name, size=mesh_size, write=write_mesh)
128 for name
in MESH_FILES]
130 g_grain = d.add_particle_type(grain, meshes[0])
131 g_cup = d.add_particle_type(cup, meshes[1])
132 g_plate = d.add_particle_type(plate, meshes[2])
134 m_grain = d.add_material(horizon=horizon, density=DENSITY, K=K, G=G, Gc=GC,
136 m_wall = d.add_material(horizon=horizon, density=DENSITY, K=K, G=G, Gc=GC,
139 for i, j
in ((0, 0), (0, 1), (1, 1)):
140 d.add_contact_pair(i, j, contact_radius_factor=0.95, Kn=Kn, eps=0.95,
141 beta_n_factor=100.0, K=K)
144 id_cup, id_plate = n_pack, n_pack + 1
145 d.add_displacement_bc(particles=[id_cup], direction=[1, 2],
146 zero_displacement=
True)
147 d.add_displacement_bc(particles=[id_plate], direction=[2],
148 time_fn_type=
"linear", time_fn_params=[WALL_VY],
149 spatial_fn_type=
"constant")
152 d.place(x, y, geometry=g_grain, material=m_grain, contact=0)
153 cx, cy, _ = cup.center
154 d.place(cx, cy, geometry=g_cup, material=m_wall, contact=1, wall=
True)
155 px, py, _ = plate.center
156 d.place(px, py, geometry=g_plate, material=m_wall, contact=1, wall=
True)
158 d.set_test(
"compressive_test", wall_id=id_plate, wall_force_direction=2)