This is an example of how to use the netdem library.
#include <filesystem>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int num_samples = 1000000;
auto *ds_q_pos =
new Vec3d[num_samples];
auto *ds_q_quat =
new Vec4d[num_samples];
auto *ds_len_n = new double[num_samples];
auto *ds_dir_n =
new Vec3d[num_samples];
auto *ds_pos =
new Vec3d[num_samples];
void GenDataset(double len_n_min, double len_n_max) {
for (int i = 0; i < num_samples; i++) {
double rot_axis_theta = uniform_dist.
Get() * Math::PI;
double rot_axis_phi = uniform_dist.
Get() * 2.0 * Math::PI;
Vec3d rot_axis_sph{1.0, rot_axis_theta, rot_axis_phi};
double rot_angle = uniform_dist.
Get() * 2.0 * Math::PI;
Vec3d rot_axis = Math::SphericalToCartesian(rot_axis_sph);
ds_q_quat[i] = Math::Quaternion::FromRodrigues(rot_angle, rot_axis);
ds_len_n[i] = len_n_min + uniform_dist.
Get() * (len_n_max - len_n_min);
double dir_theta = uniform_dist.
Get() * Math::PI;
double dir_phi = uniform_dist.
Get() * 2.0 * Math::PI;
Vec3d dir_sph{1.0, dir_theta, dir_phi};
ds_dir_n[i] = Math::SphericalToCartesian(dir_sph);
Vec3d sup_pos_1, sup_pos_2;
Vec3d dir_n_inv = -1.0 * ds_dir_n[i];
sup_pos_2 = sup_pos_1 + ds_len_n[i] * ds_dir_n[i];
ds_pos[i] = sup_pos_1 + 0.5 * ds_len_n[i] * ds_dir_n[i];
Vec4d quat_conj = Math::Quaternion::Conjugate(ds_q_quat[i]);
Vec3d dir_n_ref = Math::Rotate(ds_dir_n[i], quat_conj);
Vec3d sup_pos_2_rot = Math::Rotate(sup_pos_2_ref, ds_q_quat[i]);
ds_q_pos[i] = sup_pos_2 - sup_pos_2_rot;
if (((i + 1) % 100000) == 0) {
cout << "data generated: " << i + 1 << " ..." << endl;
}
}
}
void SaveReferenceResult(string filename) {
stringbuf buf;
ostream os(&buf);
int os_width = 24;
os.setf(ios::scientific);
os.precision(15);
for (int i = 0; i < num_samples; i++) {
os << ds_q_pos[i][0] << ", " << ds_q_pos[i][1] << ", " << ds_q_pos[i][2]
<< ", " << ds_q_quat[i][0] << ", " << ds_q_quat[i][1] << ", "
<< ds_q_quat[i][2] << ", " << ds_q_quat[i][3] << ", " << ds_len_n[i]
<< ", " << ds_dir_n[i][0] << ", " << ds_dir_n[i][1] << ", "
<< ds_dir_n[i][2] << ", " << ds_pos[i][0] << ", " << ds_pos[i][1] << ", "
<< ds_pos[i][2] << endl;
}
ofstream outfile;
outfile.open(filename);
if (!outfile) {
cout << "cannot open file: " << filename << endl;
}
outfile << buf.str();
outfile.close();
cout << "data saved to: " << filename << endl;
}
void SaveGJKResult(string filename, bool use_erosion,
double erosion_ratio_initial) {
stringbuf buf;
ostream os(&buf);
int os_width = 24;
os.setf(ios::scientific);
os.precision(15);
for (int i = 0; i < num_samples; i++) {
p2.
SetPosition(ds_q_pos[i][0], ds_q_pos[i][1], ds_q_pos[i][2]);
p2.
SetQuaternion(ds_q_quat[i][0], ds_q_quat[i][1], ds_q_quat[i][2],
ds_q_quat[i][3]);
cnt_solver.
Init(&p1, &p2);
auto cnt_geoms = cnt.collision_entries[0].cnt_geoms;
os << ds_q_pos[i][0] << ", " << ds_q_pos[i][1] << ", " << ds_q_pos[i][2]
<< ", " << ds_q_quat[i][0] << ", " << ds_q_quat[i][1] << ", "
<< ds_q_quat[i][2] << ", " << ds_q_quat[i][3] << ", "
<< cnt_geoms.len_n << ", " << cnt_geoms.dir_n[0] << ", "
<< cnt_geoms.dir_n[1] << ", " << cnt_geoms.dir_n[2] << ", "
<< cnt_geoms.pos[0] << ", " << cnt_geoms.pos[1] << ", "
<< cnt_geoms.pos[2] << endl;
} else {
os << ds_q_pos[i][0] << ", " << ds_q_pos[i][1] << ", " << ds_q_pos[i][2]
<< ", " << ds_q_quat[i][0] << ", " << ds_q_quat[i][1] << ", "
<< ds_q_quat[i][2] << ", " << ds_q_quat[i][3] << ", " << 0 << ", " << 0
<< ", " << 0 << ", " << 0 << ", " << 0 << ", " << 0 << ", " << 0
<< endl;
}
}
ofstream outfile;
outfile.open(filename);
if (!outfile) {
cout << "cannot open file: " << filename << endl;
}
outfile << buf.str();
outfile.close();
cout << "data saved to: " << filename << endl;
}
void EvaluateGJK(bool use_erosion, double erosion_ratio_initial) {
dem_profiler.
StartTimer(DEMProfiler::TimerType::custom);
for (int i = 0; i < num_samples; i++) {
p2.
SetPosition(ds_q_pos[i][0], ds_q_pos[i][1], ds_q_pos[i][2]);
p2.
SetQuaternion(ds_q_quat[i][0], ds_q_quat[i][1], ds_q_quat[i][2],
ds_q_quat[i][3]);
cnt_solver.
Init(&p1, &p2);
}
}
dem_profiler.
EndTimer(DEMProfiler::TimerType::custom);
if (use_erosion) {
printf("erosion: %f s \n",
dem_profiler.
timer_list[DEMProfiler::TimerType::custom] / 1000000.0);
} else {
printf("epa: %f s \n",
dem_profiler.
timer_list[DEMProfiler::TimerType::custom] / 1000000.0);
}
}
void ClearDataset() {
delete[] ds_len_n;
delete[] ds_dir_n;
delete[] ds_pos;
delete[] ds_q_quat;
delete[] ds_q_pos;
}
void EvaluateGJKPerformance(bool save_results) {
string out_dir = "tmp/examples/gjk_erosion_issue/result_data/ev_perf/";
filesystem::create_directories(out_dir);
double erosion_ratio_initial = 0.05;
GenDataset(0, erosion_ratio_initial);
if (save_results) {
SaveReferenceResult(out_dir + "contact_ref.txt");
SaveGJKResult(out_dir + "contact_epa.txt", false, erosion_ratio_initial);
SaveGJKResult(out_dir + "contact_ero.txt", true, erosion_ratio_initial);
}
EvaluateGJK(false, erosion_ratio_initial);
EvaluateGJK(true, erosion_ratio_initial);
GenDataset(-1, 0);
if (save_results) {
SaveReferenceResult(out_dir + "noncontact_ref.txt");
SaveGJKResult(out_dir + "noncontact_epa.txt", false, erosion_ratio_initial);
SaveGJKResult(out_dir + "noncontact_ero.txt", true, erosion_ratio_initial);
}
EvaluateGJK(false, erosion_ratio_initial);
EvaluateGJK(true, erosion_ratio_initial);
ClearDataset();
}
A profiler class for measuring performance metrics in a DEM simulation.
Definition dem_profiler.hpp:22
int64t timer_list[TimerType::num_timers]
Definition dem_profiler.hpp:46
void Clear()
Definition dem_profiler.cpp:40
void EndTimer(TimerType t_type)
End a timer for measuring elapsed time.
Definition dem_profiler.cpp:32
void StartTimer(TimerType t_type)
Start a timer for measuring elapsed time.
Definition dem_profiler.cpp:27
A class for representing an ellipsoid shape.
Definition shape_ellipsoid.hpp:15
Vec3d SupportPoint(Vec3d const &dir) override
Compute the support point in a given direction for the Ellipsoid object.
Definition shape_ellipsoid.cpp:168
Definition particle.hpp:26
virtual void SetQuaternion(double q_0, double q_1, double q_2, double q_3)
Sets the orientation of the particle using a quaternion.
Definition particle.cpp:103
virtual void SetPosition(double pos_x, double pos_y, double pos_z)
Sets the position of the particle.
Definition particle.cpp:83
GJK solver for convex geometries.
Definition solver_gjk_pp.hpp:15
double erosion_ratio_initial
< The initial ratio of erosion for the terrain.
Definition solver_gjk_pp.hpp:18
bool Detect() override
Detects collisions between the two particles.
Definition solver_gjk_pp.cpp:40
bool use_erosion
Definition solver_gjk_pp.hpp:24
void Init(Particle *const p1, Particle *const p2) override
Initializes the collision solver with two particles.
Definition solver_gjk_pp.cpp:22
void ResolveInit(ContactPP *const cnt, double timestep) override
Initializes the contact point between two particles at time t = 0.
Definition solver_gjk_pp.cpp:64
Definition bond_entry.hpp:7
std::array< double, 3 > Vec3d
Definition utils_macros.hpp:18
std::array< double, 4 > Vec4d
Definition utils_macros.hpp:19