44 namespace fs = std::filesystem;
45 fs::path n = fs::absolute(dir).lexically_normal();
46 std::string s = n.string();
47 if (!s.empty() && s.back() !=
'/' && s.back() !=
'\\')
48 s += fs::path::preferred_separator;
53 return g ==
"sphere" || g ==
"ellipsoid" || g ==
"cube" || g ==
"cuboid" || g ==
"cylinder" ||
54 g ==
"sphere_minus_sphere" || g ==
"cuboid_minus_cuboid" || g ==
"open_cuboid_channel_3d";
66 const std::filesystem::path &mesh_file_1,
67 const std::filesystem::path &mesh_file_2) {
69 const double s = 0.001;
70 const double mesh_size = s / 5.0;
71 const double horizon = 3.0 * mesh_size;
72 const double particle_dist = 0.001;
74 const double poisson1 = 0.25;
75 const double rho1 = 1200.0;
76 const double K1 = 2.16e+7;
79 const double Gc1 = 50.0;
81 const double poisson2 = 0.25;
82 const double rho2 = 1200.0;
83 const double K2 = 2.16e+7;
86 const double Gc2 = 50.0;
88 const double R_contact_factor = 0.95;
92 const double beta_n_eps = 0.9;
93 const double friction_coeff = 0.5;
94 const double beta_n_factor = 100.0;
103 const double final_time = 0.0001;
104 const size_t num_steps = 1000;
105 const size_t dt_out_n = num_steps / 4;
108 json{{
"Dimension",
static_cast<size_t>(model_dim)},
109 {
"Final_Time", final_time},
110 {
"Time_Steps", num_steps},
111 {
"Discretization_Type",
json{{
"Spatial",
"finite_difference"}, {
"Time",
"central_difference"}}},
112 {
"Populate_ElementNodeConnectivity",
true},
113 {
"Quad_Approximation_Order", 2},
114 {
"Particle_Sim_Type",
"Multi_Particle"},
118 json{{
"File_Format",
"vtu"},
119 {
"Path", output_path_for_deck},
120 {
"Tags", std::vector<std::string>({
"Displacement",
"Velocity",
"Force",
"Damage_Z",
"Damage",
"Particle_ID"})},
121 {
"Output_Interval", dt_out_n},
123 {
"Perform_FE_Out",
true},
124 {
"Compress_Type",
"zlib"},
125 {
"Perform_Out",
true},
126 {
"Test_Output_Interval", 1},
128 {
"PVD_Collection",
true}});
131 json{{
"Displacement_BC_Sets", 1},
136 json{{
"Type",
"Displacement_BC"},
137 {
"Particle_List", {0}},
138 {
"Direction", {1, 2}},
139 {
"Zero_Displacement",
true}});
141 const double free_fall_dist = particle_dist - horizon;
142 const double free_fall_vel = -std::sqrt(2.0 * std::abs(-10.0) * std::max(1e-30, free_fall_dist));
145 {
"Particle_List", {1}},
146 {
"IC_Type",
"Constant_Velocity"},
147 {
"IC_Vector", {0.0, free_fall_vel, 0.0}}});
149 auto pDeckJson =
json({});
151 std::vector<geom::GeomData> pGeomVec(2);
152 pGeomVec[0].d_geomName = geomName;
153 pGeomVec[0].d_geomParams = gp_ref;
154 pGeomVec[1].d_geomName = geomName;
155 pGeomVec[1].d_geomParams = gp_ref;
159 const std::string f1 = mesh_file_1.string();
160 const std::string f2 = mesh_file_2.string();
161 auto meshSet1 =
json({{
"File", f1},
164 {
"Info",
"gmsh_builtin_mesh"},
165 {
"Mesh_Size", mesh_size},
166 {
"Write_Mesh_File",
true}}}});
167 auto meshSet2 =
json({{
"File", f2},
170 {
"Info",
"gmsh_builtin_mesh"},
171 {
"Mesh_Size", mesh_size},
172 {
"Write_Mesh_File",
true}}}});
173 pDeckJson[
"Mesh"] =
json({{
"Sets", 2}, {
"Set_1", meshSet1}, {
"Set_2", meshSet2}});
177 json{{
"Type",
"PDState"},
178 {
"Is_Plane_Strain",
false},
179 {
"Horizon", horizon},
184 {
"Compute_From_Classical",
true},
185 {
"Influence_Function",
json{{
"Type", 0}}}});
187 json{{
"Type",
"PDState"},
188 {
"Is_Plane_Strain",
false},
189 {
"Horizon", horizon},
194 {
"Compute_From_Classical",
true},
195 {
"Influence_Function",
json{{
"Type", 0}}}});
196 pDeckJson[
"Material"] = pMatJson;
200 json{{
"Contact_Radius_Factor", R_contact_factor},
202 {
"Damping_On",
false},
203 {
"Epsilon", beta_n_eps},
204 {
"Friction_On",
false},
205 {
"Friction_Coeff", friction_coeff},
207 {
"Beta_n_Factor", beta_n_factor},
210 pContactJson[
"Set_1_1"] = contact_base;
211 pContactJson[
"Set_1_1"][
"Kn"] = Kn_11;
212 pContactJson[
"Set_1_2"] = contact_base;
213 pContactJson[
"Set_1_2"][
"Kn"] = Kn_12;
214 pContactJson[
"Set_2_2"] = contact_base;
215 pContactJson[
"Set_2_2"][
"Kn"] = Kn_22;
216 pDeckJson[
"Contact"] = pContactJson;
219 json{{
"Update_Criteria",
"simple_all"},
220 {
"Search_Factor", 10.0},
221 {
"Search_Interval", 40},
222 {
"Near_Bd_Nodes_Tol", 0.5}});
225 pGenJson[
"Data"][
"N"] = 2;
232 if (model_dim == 2) {
233 pGenJson[
"Data"][
"0"] = {
234 {
"x", s}, {
"y", s}, {
"z", 0.0},
235 {
"theta", 0.0}, {
"s", 1.0},
236 {
"ax", 0.0}, {
"ay", 0.0}, {
"az", 1.0},
237 {
"geom_id", 0}, {
"mat_id", 0}, {
"contact_id", 0}
239 pGenJson[
"Data"][
"1"] = {
240 {
"x", s}, {
"y", 2.0 * s + particle_dist + s}, {
"z", 0.0},
241 {
"theta", M_PI}, {
"s", 1.0},
242 {
"ax", 0.0}, {
"ay", 0.0}, {
"az", 1.0},
243 {
"geom_id", 1}, {
"mat_id", 1}, {
"contact_id", 1}
246 pGenJson[
"Data"][
"0"] = {
247 {
"x", s}, {
"y", s}, {
"z", s},
248 {
"theta", 0.0}, {
"s", 1.0},
249 {
"ax", 0.0}, {
"ay", 0.0}, {
"az", 1.0},
250 {
"geom_id", 0}, {
"mat_id", 0}, {
"contact_id", 0}
252 pGenJson[
"Data"][
"1"] = {
253 {
"x", s}, {
"y", 2.0 * s + particle_dist + s}, {
"z", s},
254 {
"theta", M_PI}, {
"s", 1.0},
255 {
"ax", 0.0}, {
"ay", 0.0}, {
"az", 1.0},
256 {
"geom_id", 1}, {
"mat_id", 1}, {
"contact_id", 1}
259 pDeckJson[
"Particle_Generation"] = pGenJson;
261 return json({{
"Model", modelDeckJson},
262 {
"Output", outputDeckJson},
263 {
"Force_BC", bcDeckJson[
"Force_BC"]},
264 {
"Displacement_BC", bcDeckJson[
"Displacement_BC"]},
265 {
"IC", bcDeckJson[
"IC"]},
266 {
"Particle", pDeckJson[
"Particle"]},
267 {
"Mesh", pDeckJson[
"Mesh"]},
268 {
"Material", pDeckJson[
"Material"]},
269 {
"Contact", pDeckJson[
"Contact"]},
270 {
"Neighbor", pDeckJson[
"Neighbor"]},
271 {
"Particle_Generation", pDeckJson[
"Particle_Generation"]}});
276int main(
int argc,
char *argv[]) {
280 util::io::print(std::format(
"Initialized MPI. MPI size = {}, MPI rank = {}\n", mpiSize, mpiRank));
285 unsigned int nThreads;
289 nThreads = std::thread::hardware_concurrency();
290 util::io::print(std::format(
"Running test with default number of threads = {}\n", nThreads));
295 namespace fs = std::filesystem;
296 const fs::path cwd = fs::current_path();
298 fs::path run_base = cwd;
301 run_base = p.is_absolute() ? std::move(p) : cwd / p;
304 fs::path inp_base = run_base;
307 inp_base = p.is_absolute() ? std::move(p) : cwd / p;
310 std::vector<std::string> geometriesToRun;
313 util::io::print(
"twop_general_inbuilt: -allGeometries — running full geometry list.\n");
317 throw std::runtime_error(
318 "twop_general_inbuilt: -geometry \"" + g +
319 "\" is not in geom::acceptable_geometries.");
320 geometriesToRun = {g};
321 util::io::print(std::format(
"twop_general_inbuilt: single geometry = {}.\n", g));
323 geometriesToRun = {
"circle"};
324 util::io::print(
"twop_general_inbuilt: default geometry = circle (use -geometry <name> or -allGeometries).\n");
327 for (
const std::string &geomName : geometriesToRun) {
328 util::io::print(std::format(
"--- twop_general_inbuilt: geometry = {} ---\n", geomName));
330 const fs::path out_dir = run_base / geomName /
"out";
331 const fs::path inp_dir = inp_base / geomName /
"inp";
332 fs::create_directories(out_dir);
333 fs::create_directories(inp_dir);
335 const std::string output_path_for_deck = directoryPathWithTrailingSep(out_dir);
337 const fs::path mesh1 = inp_dir / (std::string(
"mesh_gen_1_") + geomName +
".msh");
338 const fs::path mesh2 = inp_dir / (std::string(
"mesh_gen_2_") + geomName +
".msh");
340 auto inputJson =
buildInputJson(geomName, output_path_for_deck, mesh1, mesh2);
342 const fs::path input_json_path = inp_dir / (std::string(
"input_") + geomName +
".json");
344 std::ofstream os(input_json_path);
346 throw std::runtime_error(
"Failed to open " + input_json_path.string() +
" for writing.");
347 os << inputJson.dump(2);
349 util::io::print(std::format(
"Output directory (VTU, log.txt): {}\n", fs::absolute(out_dir).
string()));
350 util::io::print(std::format(
"Input directory (input.json, meshes): {}\n", fs::absolute(inp_dir).
string()));
351 util::io::print(std::format(
"Wrote deck to {}\n", fs::absolute(input_json_path).
string()));
359 auto deck = std::make_shared<inp::Input>(inputJson);
int main(int argc, char *argv[])
void run(std::shared_ptr< inp::Input > &deck)
nlohmann::ordered_json json
std::string directoryPathWithTrailingSep(const std::filesystem::path &dir)
bool is3DGeometry(const std::string &g)
json buildInputJson(const std::string &geomName, const std::string &output_path_for_deck, const std::filesystem::path &mesh_file_1, const std::filesystem::path &mesh_file_2)
bool isAcceptableGeometryName(const std::string &g)
const std::vector< std::string > & getAcceptableGeometries()
Returns list of acceptable geometries for PeriDEM simulation.
std::vector< double > exampleGeomParams(const std::string &geom_type, const util::Point &c, double s)
Canonical parameter vector for examples, mesh generation tests, and demos.
double toGE(double E, double nu)
Compute shear modulus from Young's modulus E and Poisson's ratio nu.
double toE(double K, double nu)
Compute Young's modulus E from Bulk modulus K and Poisson's ratio nu.
void print(const T &msg, int nt=print_default_tab, int printMpiRank=print_default_mpi_rank)
Prints formatted information.
unsigned int getNThreads()
Get number of threads to be used by taskflow.
void initNThreads(unsigned int nThreads=std::thread::hardware_concurrency())
Initializes MpiStatus struct.
const MpiStatus * getMpiStatus()
Returns pointer to MpiStatus struct.
void initMpi(int argc=0, char *argv[]=nullptr)
Initializes MPI and also creates MpiStatus struct.
int mpiSize()
Get size (number) of processors.
int mpiRank()
get rank (id) of this processor
double normalContactStiffness(const double &K1, const double &K2, const double &horizon, int horizonPower=5)
Silling normal contact stiffness from two bulk moduli and the horizon.
static json getExampleJson(const json &given=json::object(), const geom::GeomData *region=nullptr)
Returns example JSON object for ModelDeck configuration.
static json getExampleJson(const json &given=json::object())
Returns example JSON object for ModelDeck configuration.
static json getExampleJson(const json &given=json::object())
Returns example JSON object for ModelDeck configuration.
static json getExampleJson(const json &given=json::object())
Returns the block with the given fields set.
static json getExampleJson(const std::string &)=delete
Returns example JSON object for ModelDeck configuration.
static json getExampleJson(const json &given=json::object())
Returns the block with the given fields set.
static json getExampleJson(const json &given=json::object())
Returns the block with the given fields set.
static json getParticleContactExampleJson(size_t nSets=0)
Returns example JSON object for ModelDeck configuration.
static json getParticleGeomExampleJson(std::vector< geom::GeomData > pGeomVec=std::vector< geom::GeomData >())
Returns example JSON object for ModelDeck configuration.
static json getParticleMaterialExampleJson(size_t nSets=0)
Returns example JSON object for ModelDeck configuration.
A structure to represent 3d vectors.
std::vector< double > toVec() const
Returns coordinate in stl form.