PeriDEM 0.3.0
PeriDEM -- Peridynamics-based high-fidelity model for granular media
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1/*
2 * -------------------------------------------
3 * Copyright (c) 2021 - 2026 Prashant K. Jha
4 * -------------------------------------------
5 * PeriDEM https://github.com/prashjha/PeriDEM
6 *
7 * Distributed under the Boost Software License, Version 1.0. (See accompanying
8 * file LICENSE)
9 */
10
11#include "inp/deckIncludes.h"
12#include "geom/geomObjects.h"
14#include "util/io.h"
15#include "util/function.h"
17#include "periDEMModel.h"
18#include <filesystem>
19#include <format>
20#include <fstream>
21#include <cmath>
22#include <memory>
23#include <thread>
24
26
27int main(int argc, char *argv[]) {
28
29 // init parallel
30 util::parallel::initMpi(argc, argv);
31 int mpiSize = util::parallel::mpiSize(), mpiRank = util::parallel::mpiRank();
32 util::io::print(std::format("Initialized MPI. MPI size = {}, MPI rank = {}\n", mpiSize, mpiRank));
34
35 util::io::InputParser input(argc, argv);
36
37 unsigned int nThreads;
38 if (input.cmdOptionExists("-nThreads")) nThreads = std::stoi(input.getCmdOption("-nThreads"));
39 else {
40 nThreads = std::thread::hardware_concurrency();
41 util::io::print(std::format("Running test with default number of threads = {}\n", nThreads));
42 }
43 // set number of threads
45 util::io::print(std::format("Number of threads = {}\n", util::parallel::getNThreads()));
46
47 auto inputJson = getInputJson();
48
49 // Create input deck
50 auto deck = std::make_shared<inp::Input>(inputJson);
51
52 // PeriDEM
53 PeriDEMModel dem(deck);
54 dem.run(deck);
55
56 return EXIT_SUCCESS;
57}
58
60
61 // Create output directory
62 std::string output_dir = "./out/";
63 std::string input_dir = "./inp/";
64 std::filesystem::create_directories(output_dir);
65 std::filesystem::create_directories(input_dir);
66
67 // Simulation parameters
68 const std::vector<double> center = {0.0, 0.0, 0.0};
69 const double R1 = 0.001; // Bottom particle radius
70 const double R2 = 0.001; // Top particle radius
71 const double mesh_size = std::min(R1, R2) / 5.0;
72 const double horizon = 3.0 * mesh_size;
73 const double particle_dist = 0.001;
74
75 // Material parameters
76 const double poisson1 = 0.25;
77 const double rho1 = 1200.0;
78 const double K1 = 2.16e+7;
79 const double E1 = material::toE(K1, poisson1);
80 const double G1 = material::toGE(E1, poisson1);
81 const double Gc1 = 50.0;
82
83 const double poisson2 = 0.25;
84 const double rho2 = 1200.0;
85 const double K2 = 2.16e+7;
86 const double E2 = material::toE(K2, poisson2);
87 const double G2 = material::toGE(E2, poisson2);
88 const double Gc2 = 50.0;
89
90 // Contact parameters
91 const double R_contact_factor = 0.95;
92 const double Kn_11 = util::normalContactStiffness(K1, K1, horizon);
93 const double Kn_22 = util::normalContactStiffness(K2, K2, horizon);
94 const double Kn_12 = util::normalContactStiffness(K1, K2, horizon);
95 const double beta_n_eps = 0.9;
96 const double friction_coeff = 0.5;
97 const double beta_n_factor = 100.0;
98
99 // Generate meshes for both particles
100
101 // Bottom particle (Zone 1)
102 std::vector<double> p1_center = center;
103 std::string mesh1_file_name = input_dir + "mesh_cir_1";
104 auto mesh_geom_1 = std::make_shared<geom::Circle>(
105 R1, util::Point(p1_center[0], p1_center[1], p1_center[2]));
106 mesh_gen::generateBuiltinParticleMeshGmsh(mesh_geom_1, mesh_size, mesh1_file_name, false, true,
107 nullptr, nullptr, nullptr);
108
109 // Top particle (Zone 2)
110 std::vector<double> p2_center = center;
111 std::string mesh2_file_name = input_dir + "mesh_cir_2";
112 auto mesh_geom_2 = std::make_shared<geom::Circle>(
113 R2, util::Point(p2_center[0], p2_center[1], p2_center[2]));
114 mesh_gen::generateBuiltinParticleMeshGmsh(mesh_geom_2, mesh_size, mesh2_file_name, false, true,
115 nullptr, nullptr, nullptr);
116
117 // Model deck
118 const double final_time = 0.0001;
119 const size_t num_steps = 1000;
120 const size_t dt_out_n = num_steps / 4;
121 auto modelDeckJson = inp::ModelDeck::getExampleJson(
122 json{{"Dimension", 2},
123 {"Final_Time", final_time},
124 {"Time_Steps", num_steps},
125 {"Discretization_Type", json{{"Spatial", "finite_difference"}, {"Time", "central_difference"}}},
126 {"Populate_ElementNodeConnectivity", true},
127 {"Quad_Approximation_Order", 2},
128 {"Particle_Sim_Type", "Multi_Particle"},
129 {"Seed", 0}});
130
131 // Output deck
132 auto outputDeckJson = inp::OutputDeck::getExampleJson(
133 json{{"File_Format", "vtu"},
134 {"Path", output_dir},
135 {"Tags", std::vector<std::string>({"Displacement", "Velocity", "Force", "Damage_Z", "Damage", "Particle_ID"})},
136 {"Output_Interval", dt_out_n},
137 {"Debug", 2},
138 {"Perform_FE_Out", true},
139 {"Compress_Type", "zlib"},
140 {"Perform_Out", true},
141 {"Test_Output_Interval", 1},
142 {"Tag_PP", ""}});
143
144 // BC deck
145 auto bcDeckJson = inp::BCDeck::getExampleJson(
146 json{{"Displacement_BC_Sets", 1},
147 {"IC_Sets", 1},
148 {"Gravity", util::Point(0, -10, 0).toVec()}});
149
150 // Displacement BC for fixing bottom particle
151 bcDeckJson["Displacement_BC"]["Set_1"] = inp::BCBaseDeck::getExampleJson(
152 json{{"Type", "Displacement_BC"},
153 {"Particle_List", {0}},
154 {"Direction", {1, 2}},
155 {"Zero_Displacement", true}});
156
157 // Initial velocity for top particle
158 const double free_fall_dist = particle_dist - horizon;
159 const double free_fall_vel = -std::sqrt(2.0 * std::abs(-10.0) * free_fall_dist);
160 bcDeckJson["IC"]["Set_1"] = inp::BCBaseDeck::getExampleJson(
161 json{{"Type", "IC"},
162 {"Particle_List", {1}},
163 {"IC_Type", "Constant_Velocity"},
164 {"IC_Vector", {0.0, free_fall_vel, 0.0}}});
165
166 // Particle deck
167 auto pDeckJson = json({});
168
169 // Particle geometry
170 std::vector<geom::GeomData> pGeomVec(2);
171
172 // Bottom particle
173 pGeomVec[0].d_geomName = "circle";
174 pGeomVec[0].d_geomParams = {R1, p1_center[0], p1_center[1], p1_center[2]};
175
176 // Top particle
177 pGeomVec[1].d_geomName = "circle";
178 pGeomVec[1].d_geomParams = {R2, p2_center[0], p2_center[1], p2_center[2]};
179
180 pDeckJson["Particle"] = inp::ParticleDeck::getParticleGeomExampleJson(pGeomVec);
181
182 // Mesh settings
184 mesh1_file_name + ".msh",
185 mesh2_file_name + ".msh"
186 });
187
188 // Material settings
190
191 // Material 1 (bottom particle)
192 pMatJson["Set_1"] = inp::MaterialDeck::getExampleJson(
193 json{{"Type", "PDState"},
194 {"Is_Plane_Strain", false},
195 {"Horizon", horizon},
196 {"Density", rho1},
197 {"K", K1},
198 {"G", G1},
199 {"Gc", Gc1},
200 {"Compute_From_Classical", true},
201 {"Influence_Function", json{{"Type", 0}}}});
202
203 // Material 2 (top particle)
204 pMatJson["Set_2"] = inp::MaterialDeck::getExampleJson(
205 json{{"Type", "PDState"},
206 {"Is_Plane_Strain", false},
207 {"Horizon", horizon},
208 {"Density", rho2},
209 {"K", K2},
210 {"G", G2},
211 {"Gc", Gc2},
212 {"Compute_From_Classical", true},
213 {"Influence_Function", json{{"Type", 0}}}});
214
215 pDeckJson["Material"] = pMatJson;
216
217 // Contact settings
219
220 // Base contact parameters
222 json{{"Contact_Radius_Factor", R_contact_factor},
223 {"Kn", Kn_11},
224 {"Damping_On", false},
225 {"Epsilon", beta_n_eps},
226 {"Friction_On", false},
227 {"Friction_Coeff", friction_coeff},
228 {"Kn_Factor", 1.0},
229 {"Beta_n_Factor", beta_n_factor},
230 {"K", 0.0}});
231
232 // Contact pair 1-1 (bottom-bottom)
233 pContactJson["Set_1_1"] = contact_base;
234 pContactJson["Set_1_1"]["Kn"] = Kn_11;
235
236 // Contact pair 1-2 (bottom-top)
237 pContactJson["Set_1_2"] = contact_base;
238 pContactJson["Set_1_2"]["Kn"] = Kn_12;
239
240 // Contact pair 2-2 (top-top)
241 pContactJson["Set_2_2"] = contact_base;
242 pContactJson["Set_2_2"]["Kn"] = Kn_22;
243
244 pDeckJson["Contact"] = pContactJson;
245
246 // Neighbor settings
247 pDeckJson["Neighbor"] = inp::PNeighborDeck::getExampleJson(
248 json{{"Update_Criteria", "simple_all"},
249 {"Search_Factor", 10.0},
250 {"Search_Interval", 40},
251 {"Near_Bd_Nodes_Tol", 0.5}});
252
253 // Particle generation settings
254 auto pGenJson = inp::PGenDeck::getExampleJson(json{{"Method", "From_File"}});
255
256 // Add data that will be used to create particles
257 pGenJson["Data"]["N"] = 2; // two particles
258
259 // Bottom particle
260 pGenJson["Data"]["0"] = {
261 {"x", R1}, {"y", R1}, {"z", 0.0},
262 {"theta", 0.0}, {"s", 1.0},
263 {"geom_id", 0}, {"mat_id", 0}, {"contact_id", 0}
264 };
265
266 // Top particle
267 pGenJson["Data"]["1"] = {
268 {"x", R1}, {"y", 2.0 * R1 + R2 + particle_dist}, {"z", 0.0},
269 {"theta", M_PI * 0.5}, {"s", 1.0},
270 {"geom_id", 1}, {"mat_id", 1}, {"contact_id", 1}
271 };
272
273 // Add to json
274 pDeckJson["Particle_Generation"] = pGenJson;
275
276 // Collect all decks into global input JSON
277 auto inputJson = json({{"Model", modelDeckJson},
278 {"Output", outputDeckJson},
279 {"Force_BC", bcDeckJson["Force_BC"]},
280 {"Displacement_BC", bcDeckJson["Displacement_BC"]},
281 {"IC", bcDeckJson["IC"]},
282 {"Particle", pDeckJson["Particle"]},
283 {"Mesh", pDeckJson["Mesh"]},
284 {"Material", pDeckJson["Material"]},
285 {"Contact", pDeckJson["Contact"]},
286 {"Neighbor", pDeckJson["Neighbor"]},
287 {"Particle_Generation", pDeckJson["Particle_Generation"]}});
288
289 // Write configuration to file
290 std::cout << "\n\nPrinting global input deck json:\n";
291 std::cout << inputJson.dump(2) << std::endl;
292
293 // save to file
294 std::ofstream f(input_dir + "/input.json");
295 f << inputJson.dump(2);
296 f.close();
297
298 return inputJson;
299}
int main(int argc, char *argv[])
Definition main.cpp:29
void run(std::shared_ptr< inp::Input > &deck)
Input command line argument parser.
Definition inputParser.h:28
bool cmdOptionExists(const std::string &option) const
Check if argument exists.
Definition inputParser.h:60
const std::string & getCmdOption(const std::string &option) const
Get value of argument specified by key.
Definition inputParser.h:45
nlohmann::ordered_json json
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 generateBuiltinParticleMeshGmsh(const std::shared_ptr< geom::GeomObject > &geomObj, double h, const std::string &filenameStem, bool vtk_out, bool write_mesh_file, mesh::Mesh *out_mesh, const inp::MeshDeck *meshDeck, const inp::ModelDeck *modelDeck)
In-process Gmsh mesh from geom::GeomObject (after createGeomObject on deck / Particle data).
void print(const T &msg, int nt=print_default_tab, int printMpiRank=print_default_mpi_rank)
Prints formatted information.
Definition io.h:171
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.
Definition function.cpp:139
static json getExampleJson(const json &given=json::object(), const geom::GeomData *region=nullptr)
Returns example JSON object for ModelDeck configuration.
Definition bcBaseDeck.h:233
static json getExampleJson(const json &given=json::object())
Returns example JSON object for ModelDeck configuration.
Definition bcDeck.h:79
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.
Definition modelDeck.h:217
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.
Definition pGenDeck.h:82
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 getParticleMeshExampleJson(std::vector< std::string > filenameVec=std::vector< std::string >(), std::vector< double > meshSizesVec=std::vector< double >())
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.
Definition point.h:30
std::vector< double > toVec() const
Returns coordinate in stl form.
Definition point.h:118
json getInputJson()
Definition main.cpp:59