diff --git a/examples/dem.py b/examples/dem.py index 2c9dcf3c5bac4294e832f5a85acaec2499ba8b01..6f426995f0b6f4607ad6eace5d99e9ecfa2f8944 100644 --- a/examples/dem.py +++ b/examples/dem.py @@ -8,7 +8,6 @@ def update_mass_and_inertia(i): rotation_quat[i] = default_quaternion() if is_sphere(i): - #mass[i] = ((4.0 / 3.0) * pi) * radius[i] * radius[i] * radius[i] * densityParticle_SI inv_inertia[i] = inversed(diagonal_matrix(0.4 * mass[i] * radius[i] * radius[i])) else: @@ -164,13 +163,17 @@ psim.add_contact_property('impact_velocity_magnitude', pairs.real(), 0.0) psim.set_domain([0.0, 0.0, 0.0, domainSize_SI[0], domainSize_SI[1], domainSize_SI[2]]) psim.set_domain_partitioner(pairs.regular_domain_partitioner_xy()) psim.pbc([True, True, False]) -psim.read_particle_data( - "data/spheres.input", - #"data/spheres_4x4x2.input", - #"data/spheres_6x6x2.input", - #"data/spheres_8x8x2.input", - ['uid', 'type', 'mass', 'radius', 'position', 'linear_velocity', 'flags'], - pairs.sphere()) +psim.dem_sc_grid( + domainSize_SI[0], domainSize_SI[1], domainSize_SI[2], generationSpacing_SI, + diameter_SI, minDiameter_SI, maxDiameter_SI, initialVelocity_SI, densityParticle_SI, ntypes) + +#psim.read_particle_data( +# "data/spheres.input", +# "data/spheres_4x4x2.input", +# "data/spheres_6x6x2.input", +# #"data/spheres_8x8x2.input", +# ['uid', 'type', 'mass', 'radius', 'position', 'linear_velocity', 'flags'], +# pairs.sphere()) #psim.read_particle_data( # "data/spheres_bottom.input", @@ -187,8 +190,8 @@ psim.setup(update_mass_and_inertia, {'densityParticle_SI': densityParticle_SI, 'infinity': math.inf }) #psim.compute_half() -psim.build_cell_lists(linkedCellWidth, store_neighbors_per_cell=True) -#psim.vtk_output(f"output/dem_{target}", frequency=visSpacing) +psim.build_cell_lists(linkedCellWidth) +psim.vtk_output(f"output/dem_{target}", frequency=visSpacing) psim.compute(gravity, symbols={'densityParticle_SI': densityParticle_SI, diff --git a/runtime/dem_sc_grid.hpp b/runtime/dem_sc_grid.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6f47fc5c50cb881fd72154212f370b13649b6e24 --- /dev/null +++ b/runtime/dem_sc_grid.hpp @@ -0,0 +1,155 @@ +#include <iostream> +#include <math.h> +#include <random> +//--- +#include "pairs.hpp" + +#pragma once + +namespace pairs { + +namespace internal { + +static std::mt19937 generator; // static std::mt19937_64 generator; + +std::mt19937 & get_generator() { + // std::mt19937_64 + return generator; +} + +} + +template< typename REAL_TYPE = real_t> +REAL_TYPE realRandom( + const REAL_TYPE min = REAL_TYPE(0), + const REAL_TYPE max = REAL_TYPE(1), + std::mt19937& generator = internal::get_generator()) { + + static_assert( + std::numeric_limits<REAL_TYPE>::is_specialized && + !std::numeric_limits<REAL_TYPE>::is_integer, + "Floating point type required/expected!" ); + + std::uniform_real_distribution<REAL_TYPE> distribution(min, max); + + REAL_TYPE value; +#ifdef _OPENMP + #pragma omp critical (Random_random) +#endif + { value = distribution( generator ); } + + return value; +} + + + +template<typename REAL_TYPE> class RealRandom { +public: + RealRandom(const std::mt19937::result_type& seed = std::mt19937::result_type()) { generator_.seed(seed); } + REAL_TYPE operator()(const REAL_TYPE min = REAL_TYPE(0), const REAL_TYPE max = REAL_TYPE(1) ) { + return realRandom(min, max, generator_); + } +private: + std::mt19937 generator_; +}; + +bool point_within_aabb(double point[], double aabb[]) { + return point[0] >= aabb[0] && point[0] < aabb[3] && + point[1] >= aabb[1] && point[1] < aabb[4] && + point[2] >= aabb[2] && point[2] < aabb[5]; +} + +int dem_sc_grid(PairsSimulation *ps, double xmax, double ymax, double zmax, double spacing, double diameter, double min_diameter, double max_diameter, double initial_velocity, double particle_density, int ntypes) { + auto uid = ps->getAsIntegerProperty(ps->getPropertyByName("uid")); + auto shape = ps->getAsIntegerProperty(ps->getPropertyByName("shape")); + auto types = ps->getAsIntegerProperty(ps->getPropertyByName("type")); + auto flags = ps->getAsIntegerProperty(ps->getPropertyByName("flags")); + auto masses = ps->getAsFloatProperty(ps->getPropertyByName("mass")); + auto radius = ps->getAsFloatProperty(ps->getPropertyByName("radius")); + auto positions = ps->getAsVectorProperty(ps->getPropertyByName("position")); + auto velocities = ps->getAsVectorProperty(ps->getPropertyByName("linear_velocity")); + int last_uid = 1; + int nparticles = 0; + + const double xmin = 0.0; + const double ymin = 0.0; + const double zmin = diameter; + + double gen_domain[] = {xmin, ymin, zmin, xmax, ymax, zmax}; + double ref_point[] = {spacing * 0.5, spacing * 0.5, spacing * 0.5}; + double sc_xmin = xmin - ref_point[0]; + double sc_ymin = ymin - ref_point[1]; + double sc_zmin = zmin - ref_point[2]; + + int iret = (int)(ceil(sc_xmin / spacing)); + int jret = (int)(ceil(sc_ymin / spacing)); + int kret = (int)(ceil(sc_zmin / spacing)); + + int i = iret; + int j = jret; + int k = kret; + + double point[3]; + point[0] = ref_point[0] + i * spacing; + point[1] = ref_point[1] + j * spacing; + point[2] = ref_point[2] + k * spacing; + + while(point_within_aabb(point, gen_domain)) { + int particle_uid = last_uid; + auto diameter = realRandom<real_t>(min_diameter, max_diameter); + + if(ps->getDomainPartitioner()->isWithinSubdomain(point[0], point[1], point[2])) { + real_t rad = diameter * 0.5; + uid(nparticles) = particle_uid; + radius(nparticles) = rad; + masses(nparticles) = ((4.0 / 3.0) * M_PI) * rad * rad * rad * particle_density; + positions(nparticles, 0) = point[0]; + positions(nparticles, 1) = point[1]; + positions(nparticles, 2) = point[2]; + velocities(nparticles, 0) = 0.1 * realRandom<real_t>(-initial_velocity, initial_velocity); + velocities(nparticles, 1) = 0.1 * realRandom<real_t>(-initial_velocity, initial_velocity); + velocities(nparticles, 2) = -initial_velocity; + types(nparticles) = rand() % ntypes; + flags(nparticles) = 0; + shape(nparticles) = 0; // sphere + + std::cout << uid(nparticles) << "," << types(nparticles) << "," << masses(nparticles) << "," << radius(nparticles) << "," + << positions(nparticles, 0) << "," << positions(nparticles, 1) << "," << positions(nparticles, 2) << "," + << velocities(nparticles, 0) << "," << velocities(nparticles, 1) << "," << velocities(nparticles, 2) << "," + << flags(nparticles) << std::endl; + + nparticles++; + } + + ++i; + point[0] = ref_point[0] + i * spacing; + point[1] = ref_point[1] + j * spacing; + point[2] = ref_point[2] + k * spacing; + + if(!point_within_aabb(point, gen_domain)) { + i = iret; + j++; + point[0] = ref_point[0] + i * spacing; + point[1] = ref_point[1] + j * spacing; + point[2] = ref_point[2] + k * spacing; + + if(!point_within_aabb(point, gen_domain)) { + j = jret; + k++; + point[0] = ref_point[0] + i * spacing; + point[1] = ref_point[1] + j * spacing; + point[2] = ref_point[2] + k * spacing; + + if(!point_within_aabb(point, gen_domain)) { + break; + } + } + } + + last_uid++; + } + + return nparticles; +} + +} diff --git a/src/pairs/code_gen/cgen.py b/src/pairs/code_gen/cgen.py index 0d6d8b05c0bf75d410e835e22144e89514bd83a9..03c52993bf4dbf408a0ad0cce3cf99d6f425179b 100644 --- a/src/pairs/code_gen/cgen.py +++ b/src/pairs/code_gen/cgen.py @@ -74,6 +74,7 @@ class CGen: self.print("//---") self.print("#include \"runtime/likwid-marker.h\"") self.print("#include \"runtime/copper_fcc_lattice.hpp\"") + self.print("#include \"runtime/dem_sc_grid.hpp\"") self.print("#include \"runtime/pairs.hpp\"") self.print("#include \"runtime/read_from_file.hpp\"") self.print("#include \"runtime/timing.hpp\"") diff --git a/src/pairs/sim/dem_sc_grid.py b/src/pairs/sim/dem_sc_grid.py new file mode 100644 index 0000000000000000000000000000000000000000..c7ef027bf8308d748f139a06afc0953ac649b650 --- /dev/null +++ b/src/pairs/sim/dem_sc_grid.py @@ -0,0 +1,29 @@ +from pairs.ir.assign import Assign +from pairs.ir.block import pairs_inline +from pairs.ir.functions import Call_Int +from pairs.sim.lowerable import Lowerable + + +class DEMSCGrid(Lowerable): + def __init__( + self, sim, xmax, ymax, zmax, spacing, diameter, min_diameter, max_diameter, initial_velocity, particle_density, ntypes): + + super().__init__(sim) + self._xmax = xmax + self._ymax = ymax + self._zmax = zmax + self._spacing = spacing + self._diameter = diameter + self._min_diameter = min_diameter + self._max_diameter = max_diameter + self._initial_velocity = initial_velocity + self._particle_density = particle_density + self._ntypes = ntypes + #sim.set_domain([0.0, 0.0, 0.0, self._xprd, self._yprd, self._zprd]) + + @pairs_inline + def lower(self): + Assign(self.sim, self.sim.nlocal, + Call_Int(self.sim, "pairs::dem_sc_grid", + [self._xmax, self._ymax, self._zmax, self._spacing, self._diameter, self._min_diameter, self._max_diameter, + self._initial_velocity, self._particle_density, self._ntypes])) diff --git a/src/pairs/sim/interaction.py b/src/pairs/sim/interaction.py index 4d3baa6d325faf614c781fd3e4f1d959a8f857ad..5502d8514e08d7f88e5d4054d2b7457a6928c7c0 100644 --- a/src/pairs/sim/interaction.py +++ b/src/pairs/sim/interaction.py @@ -75,8 +75,11 @@ class NeighborFor: if self.sim._compute_half: shape_id = self.sim.get_shape_id(shape) - shape_cond = particle_shape[particle_id] > shape_id - condition = ScalarOp.or_op(shape_cond, self.particle < particle_id) + condition = ScalarOp.or_op( + particle_shape[particle_id] > shape_id, + ScalarOp.and_op( + ScalarOp.cmp(particle_shape[particle_id], shape_id), + self.particle < particle_id)) else: condition = ScalarOp.neq(particle_id, self.particle) @@ -103,8 +106,11 @@ class NeighborFor: if self.sim._compute_half: shape_id = self.sim.get_shape_id(shape) - shape_cond = particle_shape[particle_id] > shape_id - condition = ScalarOp.or_op(shape_cond, self.particle < particle_id) + condition = ScalarOp.or_op( + particle_shape[particle_id] > shape_id, + ScalarOp.and_op( + ScalarOp.cmp(particle_shape[particle_id], shape_id), + self.particle < particle_id)) else: condition = ScalarOp.neq(particle_id, self.particle) diff --git a/src/pairs/sim/simulation.py b/src/pairs/sim/simulation.py index 8b10fe053220f2d7240e8b6898a2750cd16606d6..291f085666fdb6cdac4e4f3d3b3a28969ab76c78 100644 --- a/src/pairs/sim/simulation.py +++ b/src/pairs/sim/simulation.py @@ -16,6 +16,7 @@ from pairs.sim.cell_lists import CellLists, BuildCellLists, BuildCellListsStenci from pairs.sim.comm import Comm from pairs.sim.contact_history import ContactHistory, BuildContactHistory, ClearUnusedContactHistory, ResetContactHistoryUsageStatus from pairs.sim.copper_fcc_lattice import CopperFCCLattice +from pairs.sim.dem_sc_grid import DEMSCGrid from pairs.sim.domain import InitializeDomain from pairs.sim.domain_partitioners import DomainPartitioners from pairs.sim.domain_partitioning import DimensionRanges @@ -241,6 +242,11 @@ class Simulation: def copper_fcc_lattice(self, nx, ny, nz, rho, temperature, ntypes): self.setups.add_statement(CopperFCCLattice(self, nx, ny, nz, rho, temperature, ntypes)) + def dem_sc_grid(self, xmax, ymax, zmax, spacing, diameter, min_diameter, max_diameter, initial_velocity, particle_density, ntypes): + self.setups.add_statement( + DEMSCGrid(self, xmax, ymax, zmax, spacing, diameter, min_diameter, max_diameter, + initial_velocity, particle_density, ntypes)) + def build_cell_lists(self, spacing, store_neighbors_per_cell=False): self._store_neighbors_per_cell = store_neighbors_per_cell self.cell_lists = CellLists(self, self._dom_part, spacing, spacing)