#pragma once #include #include #include namespace kel { namespace lbm { namespace coll { struct Spheroid{}; } namespace sch { using namespace saw::schema; template using ParticleRigidBody = Struct< Member, "position">, Member, "position_old">, Member, Member, Member, "acceleration">, Member >; template using ParticleCollisionSpheroid = Struct< Member >; template> using Particle = Struct< Member, "rigid_body">, Member, Member >; } template saw::data, sch::ParticleCollisionSpheroid> create_spheroid_particle( saw::data> pos_p, saw::data> vec_p, saw::data> acc_p, saw::data> rot_pos_p, saw::data> rot_vel_p, saw::data> rot_acc_p, saw::data rad_p, saw::data density_p ){ saw::data> part; auto& body = part.template get<"rigid_body">(); auto& pos = body.template get<"position">(); auto& pos_old = body.template get<"position_old">(); auto& acc = body.template get<"acceleration">(); auto& rot = body.template get<"rotation">(); auto& rot_old = body.template get<"rotation_old">(); auto& coll = part.template get<"collision">(); auto& rad = coll.template get<"radius">(); pos = pos_p; pos_old = pos - vec_p; acc = acc_p; rad = rad_p; return part; } template constexpr auto verlet_step_lambda = [](saw::data>& particle, saw::data time_step_delta){ auto& body = particle.template get<"rigid_body">(); auto& pos = body.template get<"position">(); auto& pos_old = body.template get<"position_old">(); auto& rot = body.template get<"rotation">(); auto& acc = body.template get<"acceleration">(); auto tsd_squared = time_step_delta * time_step_delta; saw::data> pos_new; // Actual step for(uint64_t i = 0u; i < D; ++i){ pos_new.at({{i}}) = saw::data{2.0} * pos.at({{i}}) - pos_old.at({{i}}) + acc.at({{i}}) * tsd_squared; } pos_old = pos; pos = pos_new; }; template constexpr auto handle_collision = [](saw::data>& left, saw::data>& right, saw::data> unit_pos_rel, saw::data> vel_rel) { auto& rb_l = left.template get<"rigid_body">(); auto& pos_l = rb_l.template get<"position">(); auto& pos_old_l = rb_l.template get<"position_old">(); auto vel_l = pos_l - pos_old_l; auto& mass_l = left.template get<"mass">(); auto& rb_r = right.template get<"rigid_body">(); auto& pos_r = rb_r.template get<"position">(); auto& pos_old_r = rb_r.template get<"position_old">(); auto vel_r = pos_r - pos_old_r; auto& mass_r = left.template get<"mass">(); /** * E to 0 */ constexpr saw::data> elasticity{0u}; constexpr saw::data> one{1.0}; saw::data> j = (e - one) / ((one / mass_l) + (one / mass_r)); vel_l = vel_l + vel_rel * j; vel_r = vel_r - vel_rel * j; }; template constexpr auto broadphase_collision_distance_squared = [](saw::data>& left, saw::data>& right) -> std::pair>>{ auto rad_l = left.template get<"collision">().template get<"radius">(); auto rad_r = right.template get<"collision">().template get<"radius">(); auto& rb_l = left.template get<"rigid_body">(); auto& rb_r = right.template get<"rigid_body">(); auto& pos_l = rb_l.template get<"position">(); auto& pos_r = rb_r.template get<"position">(); auto pos_dist = pos_l - pos_r; auto norm_2 = saw::math::dot(pos_dist,pos_dist); auto rad_ab_2 = rad_l * rad_l + rad_r * rad_r + rad_r * rad_l * static_cast::type>(2); return std::make_pair((norm_2.at({}).get() < rad_ab_2.get()), norm_2); }; /** * * */ template constexpr auto broadphase_collision_check = [](saw::data>& left, saw::data>& right) -> bool{ return broadphase_collision_distance_squared(left,right).first; }; } }