NetDEM v1.0
Loading...
Searching...
No Matches
81_voronoi_packing.cpp

This is an example of how to use the netdem library.

#include "data_dumper.hpp"
#include "gen_pack.hpp"
#include "gravity.hpp"
#include "shape_sphere.hpp"
#include "simulation.hpp"
#include <filesystem>
#include <iostream>
#include <omp.h>
#include <unordered_map>
using namespace netdem;
using namespace std;
STLModel GetKernelPolyhedron() {
int num_verts{30 / 2 + 2}; // V = E-F+2
UniformDistribution uniform_dist(0, Math::PI);
auto theta_list = uniform_dist.Get(num_verts);
auto phi_list = uniform_dist.Get(num_verts);
VecXT<Vec3d> vertices;
VecXT<Vec3i> facets;
vertices.resize(num_verts);
for (int i = 0; i < num_verts; i++) {
vertices[i][0] = sin(theta_list[i]) * cos(phi_list[i] * 2);
vertices[i][1] = sin(theta_list[i]) * sin(phi_list[i] * 2);
vertices[i][2] = cos(theta_list[i]);
}
IGLWrapper::ConvexHull(vertices, &vertices, &facets);
STLModel kernel_stl(vertices, facets);
Vec3d origin{0, 0, 0};
if (!kernel_stl.CheckEnclose(origin)) {
return GetKernelPolyhedron();
} else {
return kernel_stl;
}
}
void PrepareTemplates() {
std::filesystem::create_directories(
"local/polybezier_model/voronoi_packing/kernel_stl/");
int num_p{0};
for (int i = 0; i < 1000 * 1000; i++) {
auto kernel_stl = GetKernelPolyhedron();
Polybezier polybezier;
polybezier.InitFromKernelSTL(kernel_stl);
auto [bound_aabb_min, bound_aabb_max] = polybezier.GetBoundAABB();
auto bound_len = bound_aabb_max - bound_aabb_min;
auto len_max = max(bound_len[0], max(bound_len[1], bound_len[2]));
auto len_min = min(bound_len[0], min(bound_len[1], bound_len[2]));
auto len_mid =
bound_len[0] + bound_len[1] + bound_len[2] - len_max - len_min;
auto flatness = len_min / len_mid;
auto elongation = len_mid / len_max;
if (flatness > 0.7 && flatness < 0.9 && elongation > 0.6 &&
elongation < 0.8) {
num_p++;
kernel_stl.SaveAsSTL(
"local/polybezier_model/voronoi_packing/kernel_stl/" +
to_string(num_p - 1) + ".stl");
}
if (num_p > 999) {
break;
}
}
}
void PolybezierCase() {
Simulation *sim = new Simulation();
sim->domain_manager.SetBound(-0.6, -0.6, -0.6, 0.6, 0.6, 0.6);
sim->domain_manager.SetCellSpacing(0.3, 0.3, 0.3);
LinearSpring cnt_model = LinearSpring(2.0e6, 1.0e6, 0.5, 0.0);
sim->scene.InsertContactModel(&cnt_model);
sim->scene.SetCollisionModel(0, 0, cnt_model.label);
// voronoi cells
STLModel stl_model;
stl_model.InitFromSTL("data/box.stl");
auto [vt_nodes, vt_cells, vt_seeds] =
Voronoi::Solve(stl_model, 1000, 1000, 1.0e-3);
Voronoi::SaveAsVTK("local/polybezier_model/voronoi_packing/voronoi.vtk",
vt_nodes, vt_cells, vt_seeds);
for (int i = 0; i < 1000; i++) {
STLModel kernel_stl;
kernel_stl.InitFromSTL(
"local/polybezier_model/voronoi_packing/kernel_stl/" + to_string(i) +
".stl");
Polybezier polybezier;
polybezier.InitFromKernelSTL(kernel_stl);
polybezier.SetSize(0.08);
auto shape_prt = sim->scene.InsertShape(&polybezier);
p.SetShape(shape_prt);
p.SetPosition(vt_seeds[i][0], vt_seeds[i][1], vt_seeds[i][2]);
}
// container
WallBoxPlane wall_box(1, 1, 1, 0, 0, 0);
wall_box.ImportToScene(&(sim->scene));
Gravity grav;
grav.Init(sim);
sim->modifier_manager.Insert(&grav);
DataDumper data_dumper;
data_dumper.Init(sim);
data_dumper.SetRootPath("local/polybezier_model/voronoi_packing/out/");
data_dumper.SetSaveByCycles(100);
data_dumper.SaveShapeInfoAsSTL();
data_dumper.dump_mesh = true;
sim->modifier_manager.Insert(&data_dumper);
sim->modifier_manager.Enable(data_dumper.label);
sim->Run(2.0);
auto gjk_solver = static_cast<SolverGJKPP *>(cnt_solver);
omp_set_num_threads(1);
sim->dem_solver.Cycle(1);
delete sim;
MPI_Finalize();
}
void TrimeshCase() {
Simulation *sim = new Simulation();
sim->domain_manager.SetBound(-0.6, -0.6, -0.6, 0.6, 0.6, 0.6);
sim->domain_manager.SetCellSpacing(0.3, 0.3, 0.3);
LinearSpring cnt_model = LinearSpring(2.0e6, 1.0e6, 0.5, 0.0);
sim->scene.InsertContactModel(&cnt_model);
sim->scene.SetCollisionModel(0, 0, cnt_model.label);
// voronoi cells
STLModel stl_model;
stl_model.InitFromSTL("data/box.stl");
auto [vt_nodes, vt_cells, vt_seeds] =
Voronoi::Solve(stl_model, 1000, 1000, 1.0e-3);
Voronoi::SaveAsVTK("local/polybezier_model/voronoi_packing/voronoi.vtk",
vt_nodes, vt_cells, vt_seeds);
for (int i = 0; i < 1000; i++) {
STLModel kernel_stl;
kernel_stl.InitFromSTL(
"local/polybezier_model/voronoi_packing/kernel_stl/" + to_string(i) +
".stl");
Polybezier polybezier;
polybezier.InitFromKernelSTL(kernel_stl);
polybezier.SetSize(0.08);
TriMesh trimesh;
// trimesh.use_linked_patches = true;
trimesh.InitFromSTL(polybezier.GetSTLModel());
trimesh.MakeConvex();
trimesh.AlignAxes();
auto shape_prt = sim->scene.InsertShape(&trimesh);
p.SetShape(shape_prt);
p.SetPosition(vt_seeds[i][0], vt_seeds[i][1], vt_seeds[i][2]);
p.damp_numerical = 0.7;
}
// container
WallBoxPlane wall_box(1, 1, 1, 0, 0, 0);
wall_box.ImportToScene(&(sim->scene));
Gravity grav;
grav.Init(sim);
sim->modifier_manager.Insert(&grav);
DataDumper data_dumper;
data_dumper.Init(sim);
data_dumper.SetRootPath("local/polybezier_model/voronoi_packing/out/");
data_dumper.SetSaveByCycles(100);
data_dumper.SaveShapeInfoAsSTL();
data_dumper.dump_mesh = true;
sim->modifier_manager.Insert(&data_dumper);
sim->modifier_manager.Enable(data_dumper.label);
sim->Run(2.0);
for (auto shape_ptr : sim->scene.GetShapes()) {
if (shape_ptr->shape_type == Shape::trimesh_convex) {
auto trimesh_ptr = static_cast<TriMesh *>(shape_ptr);
// trimesh_ptr->use_linked_patches = true;
// trimesh_ptr->Init();
trimesh_ptr->enable_debugging = true;
}
}
auto gjk_solver = static_cast<SolverGJKPP *>(cnt_solver);
omp_set_num_threads(1);
sim->dem_solver.Cycle(1);
delete sim;
MPI_Finalize();
}
void MeshTemplates() {
std::filesystem::create_directories(
"local/polybezier_model/voronoi_packing/mesh_stl/");
for (int i = 0; i < 1000; i++) {
STLModel kernel_stl;
kernel_stl.InitFromSTL(
"local/polybezier_model/voronoi_packing/kernel_stl/" + to_string(i) +
".stl");
Polybezier polybezier;
polybezier.InitFromKernelSTL(kernel_stl);
polybezier.SetSize(0.08);
polybezier.GetSTLModel(2000).SaveAsSTL(
"local/polybezier_model/voronoi_packing/mesh_stl/" + to_string(i) +
".stl");
}
}
void VoronoiPacking(int argc, char **argv) {
if (argc <= 2) {
cout << "please specify the id of the task. \n"
<< "e.g.: netdem_example_polybezier_model 81 i" << endl;
cout << ">> 1: PrepareTemplates" << endl;
cout << ">> 2: PolybezierCase" << endl;
cout << ">> 3: TrimeshCase" << endl;
cout << ">> 4: MeshTemplates" << endl;
return;
}
int id = atof(argv[2]);
switch (id) {
case 1:
PrepareTemplates();
break;
case 2:
PolybezierCase();
break;
case 3:
TrimeshCase();
break;
case 4:
MeshTemplates();
break;
default:
break;
}
return;
}
std::string label
Definition contact_model.hpp:34
CollisionSolverPP * GetCollisionSolver(Particle *const p1, Particle *const p2)
Get the collision solver to use for a given pair of particles.
Definition contact_solver_factory.cpp:145
void Cycle(int num_cycles)
Perform a given number of cycles of the simulation.
Definition dem_solver.cpp:235
ContactSolverFactory contact_solver_factory
Definition dem_solver.hpp:50
A class used to dump particle data into vtk files. This is a post-modifier, which will be executed at...
Definition data_dumper.hpp:12
void Init(Simulation *sim) override
Initializes the DataDumper instance.
Definition data_dumper.cpp:24
void SaveShapeInfoAsSTL()
Saves shape information as an STL file.
Definition data_dumper.cpp:2245
bool dump_mesh
A flag that determines whether to dump mesh information.
Definition data_dumper.hpp:33
void SetSaveByCycles(double interval)
Sets the interval for saving data by cycles.
Definition data_dumper.cpp:39
void SetRootPath(std::string const &root_path)
Sets the root directory path for the output file.
Definition data_dumper.cpp:26
void SetBound(double bmin_x, double bmin_y, double bmin_z, double bmax_x, double bmax_y, double bmax_z)
Sets the lower and upper bounds of the domain.
Definition domain_manager.cpp:83
void SetCellSpacing(double s_x, double s_y, double s_z)
Sets the spacing between cells in each dimension.
Definition domain_manager.cpp:105
A class used to apply gravity to particles in a DEM simulation.
Definition gravity.hpp:10
void Init(Simulation *sim) override
Initializes the Gravity instance.
Definition gravity.cpp:14
Contact model that uses linear spring elements to evaluate contact forces and moments.
Definition model_linear_spring.hpp:16
std::string label
Definition modifier.hpp:20
Modifier * Insert(Modifier *e)
Inserts new modifier into the simulation.
Definition modifier_manager.cpp:17
void Enable(std::string const &label)
Enables a modifier in the simulation.
Definition particle.hpp:26
virtual void SetShape(Shape *const shape)
Sets the Shape object representing the particle's shape.
Definition particle.cpp:29
virtual void SetPosition(double pos_x, double pos_y, double pos_z)
Sets the position of the particle.
Definition particle.cpp:83
double damp_numerical
The numerical damping coefficient of the particle.
Definition particle.hpp:98
A class representing a polybezier with variable orders and patches.
Definition shape_polybezier.hpp:21
STLModel GetSTLModel(int num_nodes=200) override
Generate an STL model for the Polybezier object.
Definition shape_polybezier.cpp:251
void InitFromKernelSTL(std::string const &file)
Initialize the Polybezier object from a kernel STL model read from file.
void SetSize(double d) override
Set the size of the Polybezier object.
Definition shape_polybezier.cpp:225
Class for working with STL models.
Definition stl_model.hpp:17
void InitFromSTL(std::string const &file)
Initialize the model from an STL file.
Definition stl_model.cpp:25
void SaveAsSTL(std::string const &file) const
Save the model as an STL file.
Definition stl_model.cpp:205
bool CheckEnclose(Vec3d const &pos) const
Check if a point is enclosed by the model.
Definition stl_model.cpp:437
ContactModel * InsertContactModel(const ContactModel *const cm_ptr)
Insert a contact model into this scene.
Definition scene.cpp:290
void SetNumberOfMaterials(int num)
Set the number of materials in this scene and initialize the contact lookup table accordingly.
Definition scene.cpp:346
Shape * InsertShape(const Shape *const s_ptr)
Insert a single shape into this scene.
Definition scene.cpp:19
VecXT< Particle * > particle_list
A list of pointers to all particles that belong to this sub-domain (scene).
Definition scene.hpp:93
void SetCollisionModel(int mat_type_1, int mat_type_2, ContactModel *const cnt_model)
Set the collision model between two materials.
Definition scene.cpp:397
Particle * InsertParticle(const Particle *const p_ptr)
Insert a single particle into this scene.
Definition scene.cpp:76
VecXT< Shape * > GetShapes()
Return a vector of pointers to all shapes in this scene.
Definition scene.cpp:316
virtual std::tuple< Vec3d, Vec3d > GetBoundAABB() const
Gets the boundary AABB of the shape instance.
Definition shape.cpp:128
Class for managing a DEM simulation.
Definition simulation.hpp:21
DEMSolver dem_solver
Implements DEM algorithms to solve the scene.
Definition simulation.hpp:47
void Run(double time)
Runs the simulation for a specified period of time.
Definition simulation.cpp:28
DomainManager domain_manager
Manager for domain and sub-domain calculations.
Definition simulation.hpp:31
ModifierManager modifier_manager
Manages add-on features (i.e., customized evaluations not hard-coded in the DEM calculation cycle).
Definition simulation.hpp:53
Scene scene
Contains and manages basic DEM objects (e.g., shapes, particles, walls) for a DEM simulation.
Definition simulation.hpp:42
GJK solver for convex geometries.
Definition solver_gjk_pp.hpp:15
A class representing a triangular mesh in 3D space.
Definition shape_trimesh.hpp:23
void MakeConvex()
Make the TriMesh object convex.
Definition shape_trimesh.cpp:128
void InitFromSTL(std::string const &file)
Initialize the TriMesh object from an STL file.
bool enable_debugging
Flag indicating whether to output debugging data.
Definition shape_trimesh.hpp:66
void AlignAxes()
Align the axes of the TriMesh object.
Definition shape_trimesh.cpp:107
Generates random numbers from a uniform distribution.
Definition distribution_uniform.hpp:15
double Get() override
Get a single random number from the uniform distribution.
Definition distribution_uniform.hpp:58
A class for generating a box of six walls.
Definition gen_wall_box_plane.hpp:23
Definition bond_entry.hpp:7
std::vector< T > VecXT
Definition utils_macros.hpp:31
std::array< double, 3 > Vec3d
Definition utils_macros.hpp:18