76 double mesh_size,
double R,
int N_target,
77 double padding, std::mt19937 &gen) {
78 std::vector<PackedParticle> particles;
79 std::uniform_real_distribution<double> u_r(-0.1 * R, 0.1 * R);
83 const double check_r = R;
84 const int rows =
static_cast<int>((max_y - in_rect[1]) / (2.0 * check_r));
85 const double rect_L = in_rect[3] - in_rect[0];
86 const int cols =
static_cast<int>(rect_L / (2.0 * check_r));
89 double x_old = in_rect[0];
90 double x_old_right = in_rect[3];
91 double y_old = in_rect[1];
92 const double cz = 0.0;
94 std::vector<double> cy_accptd;
95 cy_accptd.push_back(y_old);
97 std::vector<double> row_rads_prev{R, R};
98 for (
int i = 0; i < rows; ++i) {
102 std::vector<double> row_rads{R};
104 if (y_old + padding +
maxElem(row_rads) >= max_y)
110 if (num_p_cols > cols - 1 || j > 100 * N_target)
112 if (counter >= N_target)
117 x_old_right = in_rect[3];
120 const int p_zone =
static_cast<int>(gen() % 8);
122 double r = r0 + u_r(gen);
124 double cx = 0., cy = 0.;
126 std::uniform_real_distribution<double> rph(-0.1 * r0, 0.05 * r0);
127 std::uniform_real_distribution<double> rpv(-0.05 * r0, 0.05 * r0);
128 const double cx0 = x_old_right - padding - r;
130 cy = y_old + padding + r + rpv(gen);
132 std::uniform_real_distribution<double> rph(-0.05 * r0, 0.1 * r0);
133 std::uniform_real_distribution<double> rpv(-0.05 * r0, 0.05 * r0);
134 const double cx0 = x_old + padding + r;
136 cy = y_old + padding + r + rpv(gen);
141 std::uniform_real_distribution<double> orient(0.0, 2.0 * M_PI);
142 trial.theta = orient(gen);
143 particles.push_back(trial);
144 row_rads.push_back(trial.r);
145 cy_accptd.push_back(cy);
147 x_old_right = cx - trial.r;
149 x_old = cx + trial.r;
156 row_rads_prev = std::move(row_rads);
204 int argc,
char *argv[]) {
208 const std::vector<double> center = {0.0, 0.0, 0.0};
209 const double R = 0.001;
210 const double mesh_size = R / 5.0;
211 const double horizon = 2.0 * mesh_size;
213 const double Lin = 0.05;
214 const double Win = 0.04;
216 constexpr double wall_top_inset = 1e-7;
217 constexpr double annulus_inset = 1e-7;
219 constexpr double clearance_mesh = 1.5;
221 const double geom_pad = 0.25 * mesh_size;
222 const double plate_thickness = std::max(3.0 * mesh_size, 2.0 * mesh_size);
224 const double w_drum2d = R * 0.2;
226 const double final_time = 0.001;
227 size_t num_steps = 400;
229 num_steps =
static_cast<size_t>(std::stoul(input.
getCmdOption(
"-numSteps")));
231 const size_t num_outputs = 10;
232 const size_t dt_out_n = std::max<size_t>(1, num_steps / num_outputs);
233 const size_t test_dt_out_n = std::max<size_t>(1, dt_out_n / 10);
235 const double rho_wall = 600.;
236 const double poisson_wall = 0.25;
237 const double K_wall = 1.e+4;
240 const double KIc_wall = 5e+6;
241 const double Gc_wall =
material::toGc(KIc_wall, poisson_wall, E_wall);
243 const double rho_p = 600.;
244 const double poisson_p = poisson_wall;
245 const double K_p = 5.e+3;
248 const double KIc_p = 5e+6;
251 const double R_contact_factor = 0.95;
252 const double padding = 1.1 * R_contact_factor * mesh_size;
253 const int N_target = 500;
255 const std::vector<double> in_rect = {center[0] - 0.5 * Lin, center[1] - 0.5 * Win, center[2],
256 center[0] + 0.5 * Lin, center[1] + 0.5 * Win, center[2]};
258 std::mt19937 gen(30);
259 const double max_y = in_rect[4] - clearance_mesh * mesh_size;
260 std::vector<PackedParticle> packed =
263 throw std::runtime_error(
"compression_large_set_inbuilt_2mat2contact: particle pack is empty");
264 for (
auto &p : packed)
267 const double m = clearance_mesh * mesh_size;
271 const double delta_y = (in_rect[1] + m) - bb0.
min_y;
272 for (
auto &p : packed)
279 const double void_lox = bb.
min_x - m - geom_pad;
280 const double void_hix = bb.
max_x + m + geom_pad;
281 const double void_loy = in_rect[1];
283 const double plate_bottom_y = bb.
max_y + m + geom_pad;
284 double plate_top_y = plate_bottom_y + plate_thickness;
287 const double side = std::max(1.5 * horizon, 2.0 * mesh_size);
288 const double out_lox = void_lox - side;
289 const double out_hix = void_hix + side;
290 const double out_loy = void_loy - side;
291 const double out_hiy = plate_top_y + wall_top_inset + 2.5 * mesh_size;
293 std::vector<double> out_rect = {out_lox, out_loy, center[2], out_hix, out_hiy, center[2]};
296 const double void_hi_y = out_rect[4] - annulus_inset;
297 std::vector<double> remove_rect = {void_lox, void_loy, center[2], void_hix, void_hi_y, center[2]};
300 "[compression_large_set_inbuilt_2mat2contact] bbox(center±r) x∈[{:.6f},{:.6f}] y∈[{:.6f},{:.6f}]; "
301 "void x∈[{:.6f},{:.6f}] y_lo {:.6f}; plate y [{:.6f},{:.6f}]; void_hi {:.6f}; outer y∈[{:.6f},{:.6f}]\n",
302 bb.
min_x, bb.
max_x, bb.
min_y, bb.
max_y, void_lox, void_hix, void_loy, plate_bottom_y, plate_top_y,
303 void_hi_y, out_rect[1], out_rect[4]));
305 std::vector<double> moving_rect = {void_lox, plate_bottom_y, center[2], void_hix, plate_top_y, center[2]};
307 std::vector<double> fixed_container_params;
308 fixed_container_params.insert(fixed_container_params.end(), remove_rect.begin(), remove_rect.end());
309 fixed_container_params.insert(fixed_container_params.end(), out_rect.begin(), out_rect.end());
311 const size_t n_pack = packed.size();
312 const size_t n_wall_fixed = n_pack;
313 const size_t n_wall_moving = n_pack + 1;
314 const size_t n_total = n_pack + 2;
317 const double ell_a = 0.95 * R;
318 const double ell_b = 0.58 * R;
319 const double ell_theta = 0.35;
320 const double sq_half = R / std::sqrt(2.0);
322 const double rx = 0.82 * R;
323 const double ry = 0.62 * R;
325 std::vector<geom::GeomData> pGeomVec(10);
326 pGeomVec[0].d_geomName =
"circle";
327 pGeomVec[0].d_geomParams = {R, center[0], center[1], center[2]};
328 pGeomVec[1].d_geomName =
"triangle";
329 pGeomVec[1].d_geomParams = {R, center[0], center[1], center[2]};
330 pGeomVec[2].d_geomName =
"drum2d";
331 pGeomVec[2].d_geomParams = {R, w_drum2d, center[0], center[1], center[2]};
332 pGeomVec[3].d_geomName =
"hexagon";
333 pGeomVec[3].d_geomParams = {R, center[0], center[1], center[2]};
334 pGeomVec[4].d_geomName =
"ellipse";
335 pGeomVec[4].d_geomParams = {ell_a, ell_b, ell_theta, center[0], center[1], center[2]};
336 pGeomVec[5].d_geomName =
"rectangle";
337 pGeomVec[5].d_geomParams = {-rx, -ry, center[2], rx, ry, center[2]};
338 pGeomVec[6].d_geomName =
"square";
339 pGeomVec[6].d_geomParams = {-sq_half, -sq_half, center[2], sq_half, sq_half, center[2]};
340 pGeomVec[7].d_geomName =
"circle_minus_circle";
341 pGeomVec[7].d_geomParams = {center[0], center[1], center[2], R, 0.35 * R};
342 pGeomVec[8].d_geomName =
"rectangle_minus_rectangle";
343 pGeomVec[8].d_geomParams = fixed_container_params;
344 pGeomVec[9].d_geomName =
"rectangle";
345 pGeomVec[9].d_geomParams = moving_rect;
347 for (
auto &g : pGeomVec)
351 const util::Point cfix = pGeomVec[8].d_geom_p->center();
352 const util::Point cmov = pGeomVec[9].d_geom_p->center();
357 json{{
"Dimension", 2},
358 {
"Final_Time", final_time},
359 {
"Time_Steps", num_steps},
360 {
"Discretization_Type",
json{{
"Spatial",
"finite_difference"}, {
"Time",
"central_difference"}}},
361 {
"Populate_ElementNodeConnectivity",
true},
362 {
"Quad_Approximation_Order", 2},
363 {
"Particle_Sim_Type",
"Multi_Particle"},
366 std::vector<std::string> out_tags = {
"Displacement",
"Velocity",
"Force",
"Force_Density",
"Damage_Z",
367 "Damage",
"Nodal_Volume",
"Zone_ID",
"Particle_ID",
"Fixity",
368 "Force_Fixity",
"Contact_Nodes",
"No_Fail_Node",
"Boundary_Node_Flag"};
373 json{{
"File_Format",
"vtu"},
374 {
"Path", output_path_for_deck},
376 {
"Output_Interval", dt_out_n},
378 {
"Perform_FE_Out",
true},
379 {
"Compress_Type",
"zlib"},
380 {
"Perform_Out",
true},
381 {
"Test_Output_Interval", test_dt_out_n},
383 {
"PVD_Collection",
true}});
386 json{{
"Displacement_BC_Sets", 2},
390 json{{
"Type",
"Displacement_BC"},
391 {
"Particle_List", {n_wall_fixed}},
392 {
"Direction", {1, 2}},
393 {
"Zero_Displacement",
true}});
396 set2[
"Particle_List"] = std::vector<size_t>{n_wall_moving};
397 set2[
"Direction"] = std::vector<size_t>{2};
398 set2[
"Time_Function"] =
json{{
"Type",
"linear"}, {
"Parameters", std::vector<double>{-0.06}}};
399 set2[
"Spatial_Function"] =
json{{
"Type",
"constant"}};
400 bcDeckJson[
"Displacement_BC"][
"Set_2"] = set2;
402 json pDeckJson = json::object();
407 const char *mesh_names[] = {
"mesh_cir",
"mesh_tri",
"mesh_drum2d",
"mesh_hex",
408 "mesh_ellipse",
"mesh_rect",
"mesh_square",
"mesh_circirc",
409 "mesh_fixed_container",
"mesh_moving_container"};
410 for (
int zi = 0; zi < 10; ++zi) {
411 const std::string fname = (inp_dir / (std::string(mesh_names[zi]) +
".msh")).string();
412 meshRoot[
"Set_" + std::to_string(zi + 1)] =
413 json{{
"File", fname},
415 json{{
"Flag",
true}, {
"Info",
"gmsh_builtin_mesh"}, {
"Mesh_Size", mesh_size}, {
"Write_Mesh_File",
true}}}};
417 pDeckJson[
"Mesh"] = meshRoot;
422 json{{
"Type",
"PDState"},
423 {
"Is_Plane_Strain",
false},
424 {
"Horizon", horizon},
429 {
"Compute_From_Classical",
true},
430 {
"Influence_Function",
json{{
"Type", 0}}}});
433 json{{
"Type",
"PDState"},
434 {
"Is_Plane_Strain",
false},
435 {
"Horizon", horizon},
436 {
"Density", rho_wall},
440 {
"Compute_From_Classical",
true},
441 {
"Influence_Function",
json{{
"Type", 0}}}});
442 pDeckJson[
"Material"] = matRoot;
444 const double Kn_pp =
KnFromBulk(K_p, K_p, horizon);
445 const double Kn_pw =
KnFromBulk(K_p, K_wall, horizon);
446 const double Kn_ww = 0.0;
448 const double beta_n_eps = 0.95;
449 const double friction_coeff = 0.5;
450 const bool damping_on =
true;
451 const bool friction_on =
false;
452 const double beta_n_factor = 100.;
453 const double Kn_factor = 1.;
456 const json j_contact_pp =
457 contactPairJson(R_contact_factor, damping_on, friction_on, Kn_pp, beta_n_eps, friction_coeff, Kn_factor,
459 const json j_contact_pw =
460 contactPairJson(R_contact_factor, damping_on, friction_on, Kn_pw, beta_n_eps, friction_coeff, Kn_factor,
462 const json j_contact_ww =
463 contactPairJson(R_contact_factor, damping_on, friction_on, Kn_ww, beta_n_eps, friction_coeff, Kn_factor,
467 contactRoot[
"Set_1_1"] = j_contact_pp;
468 contactRoot[
"Set_1_2"] = j_contact_pw;
469 contactRoot[
"Set_2_2"] = j_contact_ww;
470 pDeckJson[
"Contact"] = contactRoot;
473 json{{
"Update_Criteria",
"simple_all"},
474 {
"Search_Factor", 10.0},
475 {
"Search_Interval", 100},
476 {
"Near_Bd_Nodes_Tol", 0.5}});
479 pGenJson[
"Random_Rotation"] =
false;
480 pGenJson[
"Data"][
"N"] = n_total;
482 constexpr size_t k_mat_particle = 0;
483 constexpr size_t k_mat_wall = 1;
484 constexpr size_t k_contact_grains = 0;
485 constexpr size_t k_contact_wall = 1;
487 for (
size_t pi = 0; pi < n_pack; ++pi) {
488 const auto &p = packed[pi];
489 pGenJson[
"Data"][std::to_string(pi)] =
json{
490 {
"x", p.x}, {
"y", p.y}, {
"z", 0.0}, {
"theta", p.theta},
491 {
"s", 1.0}, {
"geom_id",
static_cast<size_t>(p.zone)},
492 {
"mat_id", k_mat_particle},
493 {
"contact_id", k_contact_grains},
497 pGenJson[
"Data"][std::to_string(n_pack)] =
json{{
"x", site_wall_fixed.
d_x},
498 {
"y", site_wall_fixed.
d_y},
502 {
"geom_id", size_t(8)},
503 {
"mat_id", k_mat_wall},
504 {
"contact_id", k_contact_wall}};
506 pGenJson[
"Data"][std::to_string(n_pack + 1)] =
json{{
"x", site_wall_moving.
d_x},
507 {
"y", site_wall_moving.
d_y},
511 {
"geom_id", size_t(9)},
512 {
"mat_id", k_mat_wall},
513 {
"contact_id", k_contact_wall}};
515 pDeckJson[
"Particle_Generation"] = pGenJson;
518 return json{{
"Comment",
519 "compression_large_set_inbuilt"},
520 {
"Model", modelDeckJson},
521 {
"Output", outputDeckJson},
522 {
"Force_BC", bcDeckJson[
"Force_BC"]},
523 {
"Displacement_BC", bcDeckJson[
"Displacement_BC"]},
524 {
"Particle", pDeckJson[
"Particle"]},
525 {
"Mesh", pDeckJson[
"Mesh"]},
526 {
"Material", pDeckJson[
"Material"]},
527 {
"Contact", pDeckJson[
"Contact"]},
528 {
"Neighbor", pDeckJson[
"Neighbor"]},
529 {
"Particle_Generation", pDeckJson[
"Particle_Generation"]}};
int main(int argc, char *argv[])
json buildInputJson(const std::string &output_path_for_deck, const std::filesystem::path &inp_dir, int argc, char *argv[])
bool doesParticleIntersect(const PackedParticle &p, const std::vector< PackedParticle > &existing, const std::vector< double > &rect, double padding)
std::vector< PackedParticle > generateParticleLocations(const std::vector< double > &in_rect, double max_y, double mesh_size, double R, int N_target, double padding, std::mt19937 &gen)
json contactPairJson(double R_contact_factor, bool damping_on, bool friction_on, double Kn, double beta_n_eps, double friction_coeff, double Kn_factor, double beta_n_factor)
static json getParticleGeomExampleJson(std::vector< geom::GeomData > pGeomVec=std::vector< geom::GeomData >())
Returns example JSON object for ModelDeck configuration.