diff --git a/examples/dem_sd.py b/examples/dem_sd.py new file mode 100644 index 0000000000000000000000000000000000000000..737da4b562249d089628bdf12926d833396f7415 --- /dev/null +++ b/examples/dem_sd.py @@ -0,0 +1,177 @@ +import math +import pairs +import sys + +def update_mass_and_inertia(i): + rotation_matrix[i] = diagonal_matrix(1.0) + rotation_quat[i] = default_quaternion() + + if is_sphere(i): + inv_inertia[i] = inversed(diagonal_matrix(0.4 * mass[i] * radius[i] * radius[i])) + + else: + mass[i] = infinity + inv_inertia[i] = 0.0 + + +def linear_spring_dashpot(i, j): + delta_ij = -penetration_depth(i, j) + skip_when(delta_ij < 0.0) + + meff = 1.0 / ((1.0 / mass[i]) + (1.0 / mass[j])) + stiffness_norm = meff * (pi * pi + lnDryResCoeff * lnDryResCoeff) / \ + (collisionTime_SI * collisionTime_SI) + damping_norm = -2.0 * meff * lnDryResCoeff / collisionTime_SI + damping_tan = sqrt(kappa) * damping_norm + + velocity_wf_i = linear_velocity[i] + cross(angular_velocity[i], contact_point(i, j) - position[i]) + velocity_wf_j = linear_velocity[j] + cross(angular_velocity[j], contact_point(i, j) - position[j]) + + rel_vel = -(velocity_wf_i - velocity_wf_j) + rel_vel_n = dot(rel_vel, contact_normal(i, j)) + rel_vel_t = rel_vel - rel_vel_n * contact_normal(i, j) + fNabs = stiffness_norm * delta_ij + damping_norm * rel_vel_n + fN = fNabs * contact_normal(i, j) + + fTabs = min(damping_tan * length(rel_vel_t), friction_dynamic[i, j] * fNabs) # static or dynamic? + fT = fTabs * normalized(rel_vel_t) + + partial_force = fN + fT + + apply(force, partial_force) + apply(torque, cross(contact_point(i, j) - position, partial_force)) + + +def euler(i): + inv_mass = 1.0 / mass[i] + position[i] += 0.5 * inv_mass * force[i] * dt * dt + linear_velocity[i] * dt + linear_velocity[i] += inv_mass * force[i] * dt + wdot = rotation_matrix[i] * (inv_inertia[i] * torque[i]) * transposed(rotation_matrix[i]) + phi = angular_velocity[i] * dt + 0.5 * wdot * dt * dt + rotation_quat[i] = quaternion(phi, length(phi)) * rotation_quat[i] + rotation_matrix[i] = quaternion_to_rotation_matrix(rotation_quat[i]) + angular_velocity[i] += wdot * dt + + +def gravity(i): + volume = (4.0 / 3.0) * pi * radius[i] * radius[i] * radius[i] + force[i][2] = force[i][2] - (densityParticle_SI - densityFluid_SI) * volume * gravity_SI + # if type[i]==0: + # printf("gravity", i, volume, force[i][2], volume/2, 2>1) + + +cmd = sys.argv[0] +target = sys.argv[1] if len(sys.argv[1]) > 1 else "none" +if target != 'cpu' and target != 'gpu': + print(f"Invalid target, use {cmd} <cpu/gpu>") + +# Config file parameters +domainSize_SI=[0.1, 0.1, 0.1] +diameter_SI = 0.009 +gravity_SI = 9.81 +densityFluid_SI = 1000 +densityParticle_SI = 2550 +generationSpacing_SI = 0.01 +initialVelocity_SI = 1 +dt_SI = 5e-5 +frictionCoefficient = 0.5 +restitutionCoefficient = 0.1 +collisionTime_SI = 5e-4 +poissonsRatio = 0.22 +timeSteps = 10000 +visSpacing = 200 +denseBottomLayer = False +bottomLayerOffsetFactor = 1.0 +kappa = 2.0 * (1.0 - poissonsRatio) / (2.0 - poissonsRatio) # from Thornton et al + +minDiameter_SI = diameter_SI #* 0.9 +maxDiameter_SI = diameter_SI #* 1.1 +linkedCellWidth = 1.01 * maxDiameter_SI + +ntypes = 1 +lnDryResCoeff = math.log(restitutionCoefficient) +frictionStatic = 0.0 +frictionDynamic = frictionCoefficient + +psim = pairs.simulation( + "dem_sd", + [pairs.sphere(), pairs.halfspace()], + timesteps=timeSteps, + double_prec=True, + use_contact_history=False, + particle_capacity=1000000, + neighbor_capacity=20, + debug=True, generate_whole_program=False) + +if target == 'gpu': + psim.target(pairs.target_gpu()) +else: + psim.target(pairs.target_cpu()) + #psim.target(pairs.target_cpu(parallel=True)) + +psim.add_position('position') +psim.add_property('mass', pairs.real(), 1.0) +psim.add_property('linear_velocity', pairs.vector()) +psim.add_property('angular_velocity', pairs.vector()) +psim.add_property('force', pairs.vector(), volatile=True) +psim.add_property('torque', pairs.vector(), volatile=True) +psim.add_property('radius', pairs.real(), 1.0) +psim.add_property('normal', pairs.vector()) +psim.add_property('inv_inertia', pairs.matrix()) +psim.add_property('rotation_matrix', pairs.matrix()) +psim.add_property('rotation_quat', pairs.quaternion()) +psim.add_feature('type', ntypes) +psim.add_feature_property('type', 'friction_static', pairs.real(), [frictionStatic for i in range(ntypes * ntypes)]) +psim.add_feature_property('type', 'friction_dynamic', pairs.real(), [frictionDynamic for i in range(ntypes * ntypes)]) + +psim.set_domain([0.0, 0.0, 0.0, domainSize_SI[0], domainSize_SI[1], domainSize_SI[2]]) +# psim.set_domain_partitioner(pairs.block_forest(), initDomainFromWalberla=True) +psim.set_domain_partitioner(pairs.block_forest()) +# psim.set_domain_partitioner(pairs.regular_domain_partitioner_xy()) +psim.pbc([True, True, False]) +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", +# ['type', 'mass', 'radius', 'position', 'linear_velocity', 'flags'], +# pairs.sphere()) + +psim.read_particle_data( + "data/planes.input", + ['uid', 'type', 'mass', 'position', 'normal', 'flags'], + pairs.halfspace()) + +psim.setup(update_mass_and_inertia, {'densityParticle_SI': densityParticle_SI, + 'pi': math.pi, + 'infinity': math.inf }) + +#psim.compute_half() +psim.build_cell_lists(linkedCellWidth) +psim.vtk_output(f"output/dem_{target}", frequency=visSpacing) + +psim.compute(gravity, + symbols={'densityParticle_SI': densityParticle_SI, + 'densityFluid_SI': densityFluid_SI, + 'gravity_SI': gravity_SI, + 'pi': math.pi }) + +psim.compute(linear_spring_dashpot, + linkedCellWidth, + symbols={'dt': dt_SI, + 'pi': math.pi, + 'kappa': kappa, + 'lnDryResCoeff': lnDryResCoeff, + 'collisionTime_SI': collisionTime_SI}) + +psim.compute(euler, symbols={'dt': dt_SI}) +psim.generate() diff --git a/src/pairs/ir/print.py b/src/pairs/ir/print.py new file mode 100644 index 0000000000000000000000000000000000000000..58c2a6e1d062342e6e2d6511fccc8ee75a7ce55a --- /dev/null +++ b/src/pairs/ir/print.py @@ -0,0 +1,24 @@ +from pairs.ir.ast_node import ASTNode +from pairs.ir.lit import Lit + +class Print(ASTNode): + def __init__(self, sim, *args): + super().__init__(sim) + self.args = [Lit.cvt(sim, a) for a in args] + self.sim.add_statement(self) + + def children(self): + return self.args + + def __str__(self): + return "Print<" + ", ".join(str(arg) for arg in self.args) + ">" + +class PrintCode(ASTNode): + def __init__(self, sim, str): + super().__init__(sim) + self.arg = Lit.cvt(sim, str) + self.sim.add_statement(self) + + def children(self): + return self.arg + \ No newline at end of file