35 namespace fs = std::filesystem;
36 fs::path n = fs::absolute(dir).lexically_normal();
37 std::string s = n.string();
38 if (!s.empty() && s.back() !=
'/' && s.back() !=
'\\')
39 s += fs::path::preferred_separator;
44 const std::filesystem::path &mesh_ell,
double final_time,
size_t num_steps,
45 double mesh_size,
double horizon) {
47 const double W = 0.0008;
48 const double H = 0.0012;
51 const double a_out = 0.0020;
52 const double b_out = 0.0014;
54 const double a_in = 0.00180;
55 const double b_in = 0.00122;
56 const double ell_theta = 0.0;
57 const double tip_gap = 0.00008;
58 const double tip_y = H;
59 const double ell_cy = tip_y + tip_gap + b_out;
61 const double rho_t = 1200.0;
62 const double K_t = 2.16e7;
63 const double nu_t = 0.25;
66 const double Gc_t = 200.0;
68 const double rho_e = 1200.0;
69 const double K_e = 2.16e7;
70 const double nu_e = 0.25;
74 const double Gc_e = 1.0;
76 const double R_contact_factor = 0.95;
81 const double g = 10.0;
82 const double ic_vy = -2.5;
84 const size_t dt_out_n = std::max<size_t>(1, num_steps / 40);
87 json{{
"Dimension", 2},
88 {
"Final_Time", final_time},
89 {
"Time_Steps", num_steps},
90 {
"Discretization_Type",
json{{
"Spatial",
"finite_difference"}, {
"Time",
"central_difference"}}},
91 {
"Populate_ElementNodeConnectivity",
true},
92 {
"Quad_Approximation_Order", 2},
93 {
"Particle_Sim_Type",
"Multi_Particle"},
95 model[
"Bond_Break"] =
"tension";
97 model[
"Self_Contact"] =
"none";
100 json{{
"File_Format",
"vtu"},
101 {
"Path", output_path},
102 {
"Tags", std::vector<std::string>({
"Displacement",
"Velocity",
"Force",
"Damage_Z",
"Damage",
103 "Particle_ID",
"Fixity"})},
104 {
"Output_Interval", dt_out_n},
106 {
"Perform_FE_Out",
true},
107 {
"Compress_Type",
"zlib"},
108 {
"Perform_Out",
true},
109 {
"Test_Output_Interval", 1},
111 {
"PVD_Collection",
true}});
114 json{{
"Displacement_BC_Sets", 1},
118 json{{
"Type",
"Displacement_BC"},
119 {
"Particle_List", {0}},
120 {
"Direction", {1, 2}},
121 {
"Zero_Displacement",
true}});
123 bc[
"IC"][
"Set_1"] = {
124 {
"Particle_List", std::vector<size_t>{1}},
125 {
"Constant_Velocity", {{
"Velocity_Vector", std::vector<double>{0., ic_vy, 0.}}}}};
127 std::vector<geom::GeomData> pGeom(2);
128 pGeom[0].d_geomName =
"triangle";
129 pGeom[0].d_geomParams = {-0.5 * W, 0., 0., 0.5 * W, 0., 0., 0., H, 0.};
131 pGeom[1].d_geomName =
"ellipse_minus_ellipse";
132 pGeom[1].d_geomParams = {a_out, b_out, a_in, b_in, ell_theta, 0., 0., 0.};
134 for (
auto &g : pGeom)
137 const util::Point c_tri = pGeom[0].d_geom_p->center();
139 json pDeck = json::object();
145 {{
"File", mesh_tri.string()},
148 {
"Info",
"gmsh_builtin_mesh"},
149 {
"Mesh_Size", mesh_size},
150 {
"Write_Mesh_File",
true}}}}},
152 {{
"File", mesh_ell.string()},
155 {
"Info",
"gmsh_builtin_mesh"},
156 {
"Mesh_Size", mesh_size},
157 {
"Write_Mesh_File",
true}}}}}};
162 json{{
"Type",
"PDState"},
163 {
"Is_Plane_Strain",
false},
164 {
"Horizon", horizon},
169 {
"Compute_From_Classical",
true},
170 {
"Influence_Function",
json{{
"Type", 0}}}});
173 json{{
"Type",
"PDState"},
174 {
"Is_Plane_Strain",
false},
175 {
"Horizon", horizon},
180 {
"Compute_From_Classical",
true},
181 {
"Influence_Function",
json{{
"Type", 0}}}});
182 pDeck[
"Material"] = mat;
186 json{{
"Contact_Radius_Factor", R_contact_factor},
188 {
"Damping_On",
true},
190 {
"Friction_On",
false},
191 {
"Friction_Coeff", 0.0},
193 {
"Beta_n_Factor", 100.0},
197 json{{
"Contact_Radius_Factor", 0.90},
199 {
"Damping_On",
true},
201 {
"Friction_On",
false},
202 {
"Friction_Coeff", 0.0},
204 {
"Beta_n_Factor", 8.0},
207 json{{
"Contact_Radius_Factor", R_contact_factor},
209 {
"Damping_On",
true},
211 {
"Friction_On",
false},
212 {
"Friction_Coeff", 0.0},
214 {
"Beta_n_Factor", 100.0},
216 contact[
"Set_1_1"] = cpair_wall;
217 contact[
"Set_1_1"][
"Kn"] = Kn_tt;
219 contact[
"Set_1_2"] = cpair_tip;
220 contact[
"Set_1_2"][
"Kn"] = Kn_te;
222 contact[
"Set_2_2"] = cpair_ell;
223 contact[
"Set_2_2"][
"Kn"] = Kn_ee;
225 contact[
"Damping_Law"] =
"com_and_node";
226 contact[
"Friction_Law"] =
"coulomb_simple";
230 json{{
"Update_Criteria",
"simple_all"},
231 {
"Search_Factor", 8.0},
232 {
"Search_Interval", 5},
233 {
"Near_Bd_Nodes_Tol", 0.5}});
236 gen[
"Random_Rotation"] =
false;
237 gen[
"Data"][
"N"] = 2;
238 gen[
"Data"][
"0"] = {{
"x", c_tri.
d_x}, {
"y", c_tri.
d_y}, {
"z", 0.0},
239 {
"theta", 0.0}, {
"s", 1.0},
240 {
"geom_id", 0}, {
"mat_id", 0}, {
"contact_id", 0},
242 gen[
"Data"][
"1"] = {{
"x", 0.0}, {
"y", ell_cy}, {
"z", 0.0},
243 {
"theta", 0.0}, {
"s", 1.0},
244 {
"geom_id", 1}, {
"mat_id", 1}, {
"contact_id", 1}};
245 pDeck[
"Particle_Generation"] = gen;
247 json j = json::object();
249 j[
"Output"] = output;
250 j[
"Force_BC"] = bc[
"Force_BC"];
251 j[
"Displacement_BC"] = bc[
"Displacement_BC"];
253 j[
"Particle"] = pDeck[
"Particle"];
254 j[
"Mesh"] = pDeck[
"Mesh"];
255 j[
"Material"] = pDeck[
"Material"];
256 j[
"Contact"] = pDeck[
"Contact"];
257 j[
"Neighbor"] = pDeck[
"Neighbor"];
258 j[
"Particle_Generation"] = pDeck[
"Particle_Generation"];
264int main(
int argc,
char *argv[]) {
268 unsigned int n_threads = std::thread::hardware_concurrency();
270 n_threads = std::stoul(input.
getCmdOption(
"-nThreads"));
274 double final_time = 0.0030;
275 size_t num_steps = 30000;
277 final_time = std::stod(input.
getCmdOption(
"-finalTime"));
279 num_steps = std::stoul(input.
getCmdOption(
"-numSteps"));
281 const double mesh_size = 0.00010;
282 const double horizon = 3.0 * mesh_size;
284 namespace fs = std::filesystem;
285 const fs::path cwd = fs::current_path();
286 fs::path out_dir = cwd /
"out";
287 fs::path inp_dir = cwd /
"inp";
290 out_dir = p.is_absolute() ? std::move(p) : cwd / p;
294 inp_dir = p.is_absolute() ? std::move(p) : cwd / p;
296 inp_dir = out_dir.parent_path() /
"inp";
298 fs::create_directories(out_dir);
299 fs::create_directories(inp_dir);
302 const fs::path mesh_tri = inp_dir /
"mesh_triangle.msh";
303 const fs::path mesh_ell = inp_dir /
"mesh_hollow_ellipse.msh";
305 auto j =
buildInputJson(output_path, mesh_tri, mesh_ell, final_time, num_steps, mesh_size,
308 std::ofstream ofs(inp_dir /
"input.json");
309 ofs << std::setw(2) << j << std::endl;
321 if (j[
"Particle"][
"Set_2"][
"Type"] !=
"ellipse_minus_ellipse")
322 throw std::runtime_error(
"ellipse_triangle: Particle Set_2 must be ellipse_minus_ellipse");
325 "[ellipse_triangle] Type={}, T={}, Nt={}, mesh={:.4e}, out={}\n",
326 j[
"Particle"][
"Set_2"][
"Type"].get<std::string>(), final_time, num_steps, mesh_size,
329 auto deck = std::make_shared<inp::Input>(j);
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)
json buildInputJson(const std::string &output_path, const std::filesystem::path &mesh_tri, const std::filesystem::path &mesh_ell, double final_time, size_t num_steps, double mesh_size, double horizon)
void createGeomObject(const std::string &geom_type, const std::vector< double > ¶ms, const std::vector< std::string > &vec_type, const std::vector< std::string > &vec_flag, std::shared_ptr< geom::GeomObject > &obj, bool perform_check)
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.
void initMpi(int argc=0, char *argv[]=nullptr)
Initializes MPI and also creates MpiStatus struct.
void finalizeMpi()
Call MPI_Finalize if this process initialized MPI.
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.
double harmonicMean(const double &m1, const double &m2)
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.
double d_y
the y coordinate
std::vector< double > toVec() const
Returns coordinate in stl form.
double d_x
the x coordinate