Skip to content

Commit

Permalink
Deal with rotation.
Browse files Browse the repository at this point in the history
  • Loading branch information
pkreissl committed Dec 14, 2022
1 parent 936e05c commit 9d144d6
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 46 deletions.
10 changes: 10 additions & 0 deletions src/core/particle_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,16 @@ void rotate_particle(int part, const Utils::Vector3d &axis, double angle) {
}
#endif

uint8_t bitfield_from_flag(Utils::Vector3i const &flag) {
auto bitfield = static_cast<uint8_t>(0u);
if (flag[0])
bitfield |= static_cast<uint8_t>(1u);
if (flag[1])
bitfield |= static_cast<uint8_t>(2u);
if (flag[2])
bitfield |= static_cast<uint8_t>(4u);
return bitfield;
}
#ifdef DIPOLES
void set_particle_dipm(int part, double dipm) {
mpi_update_particle_property<double, &ParticleProperties::dipm>(part, dipm);
Expand Down
2 changes: 2 additions & 0 deletions src/core/particle_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ void set_particle_rotation(int part, Utils::Vector3i const &flag);
void rotate_particle(int part, const Utils::Vector3d &axis, double angle);
#endif

uint8_t bitfield_from_flag(Utils::Vector3i const &flag);

#ifdef ELECTROSTATICS
/** Call only on the head node: set particle charge.
* @param part the particle.
Expand Down
105 changes: 64 additions & 41 deletions src/script_interface/particle_data/ParticleHandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,83 +187,102 @@ ParticleHandle::ParticleHandle() {
#ifdef ROTATION
{"director",
[this](Variant const &value) {
if (context()->get_comm().rank() == 0) {
set_particle_director(m_pid, get_value<Utils::Vector3d>(value));
auto const part = cell_structure.get_local_particle(m_pid);
if (not (part == nullptr or part->is_ghost())) {
auto const director = get_value<Utils::Vector3d>(value).normalized();
auto const quat = Utils::convert_director_to_quaternion(director);
(part->quat)() = quat;
}
on_particle_change();
},
[this]() { return particle().calc_director(); }},
[this]() {
auto const quat = get_particle_property(&Particle::quat);
return Utils::convert_quaternion_to_director(quat);
}},
{"quat",
[this](Variant const &value) {
if (context()->get_comm().rank() == 0) {
set_particle_quat(m_pid, get_quaternion_safe("quat", value));
auto const quat = get_quaternion_safe("quat", value);
auto const part = cell_structure.get_local_particle(m_pid);
if (not (part == nullptr or part->is_ghost())) {
(part->quat)() = quat;
}
on_particle_change();
},
[this]() { return quat2vector(particle().quat()); }},
[this]() { return quat2vector(get_particle_property(&Particle::quat)); }},
{"omega_body",
[this](Variant const &value) {
if (context()->get_comm().rank() == 0) {
set_particle_omega_body(m_pid, get_value<Utils::Vector3d>(value));
}
set_particle_property(&Particle::omega, value);
},
[this]() { return particle().omega(); }},
[this]() { return get_particle_property(&Particle::omega); }},
{"rotation",
[this](Variant const &value) {
if (context()->get_comm().rank() == 0) {
set_particle_rotation(
m_pid, Utils::Vector3i{get_value<Utils::Vector3b>(value)});
auto const part = cell_structure.get_local_particle(m_pid);
if (not (part == nullptr or part->is_ghost())) {
auto const rotation_flag = Utils::Vector3i{(get_value<Utils::Vector3b>(value))};
auto const bitfield = bitfield_from_flag(rotation_flag);
(part->rotation)() = bitfield;
}
on_particle_change();
},
[this]() {
auto const &p = particle();
return Utils::Vector3b{{p.can_rotate_around(0), p.can_rotate_around(1),
p.can_rotate_around(2)}};
auto const rotation_bits = get_particle_property(&Particle::rotation);
return Utils::Vector3b{{::detail::get_nth_bit(rotation_bits, 0),
::detail::get_nth_bit(rotation_bits, 1),
::detail::get_nth_bit(rotation_bits, 2)}};
}},
{"omega_lab",
[this](Variant const &value) {
if (context()->get_comm().rank() == 0) {
set_particle_omega_lab(m_pid, get_value<Utils::Vector3d>(value));
auto const part = cell_structure.get_local_particle(m_pid);
if (not (part == nullptr or part->is_ghost())) {
auto const omega = convert_vector_space_to_body(*part, get_value<Utils::Vector3d>(value));
(part->omega)() = omega;
}
on_particle_change();
},
[this]() {
auto const &p = particle();
return convert_vector_body_to_space(p, p.omega());
auto const &part = cell_structure.get_local_particle(m_pid);
auto const omega = get_particle_property(&Particle::omega);
return convert_vector_body_to_space(*part, omega);
}},
{"torque_lab",
[this](Variant const &value) {
if (context()->get_comm().rank() == 0) {
set_particle_torque_lab(m_pid, get_value<Utils::Vector3d>(value));
auto const part = cell_structure.get_local_particle(m_pid);
if (not (part == nullptr or part->is_ghost())) {
auto const torque = convert_vector_space_to_body(*part, get_value<Utils::Vector3d>(value));
(part->torque)() = torque;
}
on_particle_change();
},
[this]() {
auto const &p = particle();
return convert_vector_body_to_space(p, p.torque());
auto const &part = cell_structure.get_local_particle(m_pid);
auto const torque = get_particle_property(&Particle::torque);
return convert_vector_body_to_space(*part, torque);
}},
#endif // ROTATION
#ifdef DIPOLES
{"dip",
[this](Variant const &value) {
if (context()->get_comm().rank() == 0) {
set_particle_dip(m_pid, get_value<Utils::Vector3d>(value));
auto const part = cell_structure.get_local_particle(m_pid);
if (not (part == nullptr or part->is_ghost())) {
auto const [quat, dipm] = convert_dip_to_quat(get_value<Utils::Vector3d>(value));
(part->quat)() = quat;
(part->dipm)() = dipm;
}
on_particle_change();
},
[this]() { return particle().calc_dip(); }},
{"dipm",
[this](Variant const &value) {
if (context()->get_comm().rank() == 0) {
set_particle_dipm(m_pid, get_value<double>(value));
}
set_particle_property(&Particle::dipm, value);
},
[this]() { return particle().dipm(); }},
[this]() { return get_particle_property(&Particle::dipm); }},
#endif // DIPOLES
#ifdef ROTATIONAL_INERTIA
{"rinertia",
[this](Variant const &value) {
if (context()->get_comm().rank() == 0) {
set_particle_rotational_inertia(m_pid,
get_value<Utils::Vector3d>(value));
}
set_particle_property(&Particle::rinertia, value);
},
[this]() { return particle().rinertia(); }},
[this]() { return get_particle_property(&Particle::rinertia); }},
#endif // ROTATIONAL_INERTIA
#ifdef LB_ELECTROHYDRODYNAMICS
{"mu_E",
Expand All @@ -275,15 +294,19 @@ ParticleHandle::ParticleHandle() {
#ifdef EXTERNAL_FORCES
{"fix",
[this](Variant const &value) {
if (context()->get_comm().rank() == 0) {
set_particle_fix(m_pid,
Utils::Vector3i{get_value<Utils::Vector3b>(value)});
auto const part = cell_structure.get_local_particle(m_pid);
if (not (part == nullptr or part->is_ghost())) {
auto const fix_flag = Utils::Vector3i{(get_value<Utils::Vector3b>(value))};
auto const bitfield = bitfield_from_flag(fix_flag);
(part->fixed)() = bitfield;
}
on_particle_change();
},
[this]() {
auto const &p = particle();
return Utils::Vector3b{
{p.is_fixed_along(0), p.is_fixed_along(1), p.is_fixed_along(2)}};
auto const fixed = get_particle_property(&Particle::fixed);
return Utils::Vector3b{{::detail::get_nth_bit(fixed, 0),
::detail::get_nth_bit(fixed, 1),
::detail::get_nth_bit(fixed, 2)}};
}},
{"ext_force",
[this](Variant const &value) {
Expand Down
10 changes: 5 additions & 5 deletions testsuite/python/particle.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,11 @@ def test_contradicting_properties_dip_quat(self):
self.system.part.add(pos=[0, 0, 0], dip=[1, 1, 1],
quat=[1.0, 1.0, 1.0, 1.0])

# @utx.skipIfMissingFeatures(["ROTATION"])
# def test_invalid_quat(self):
# system = self.system
# with self.assertRaisesRegex(ValueError, "attribute 'quat' of 'ParticleHandle' must be non-zero"):
# system.part.add(pos=[0., 0., 0.], quat=[0., 0., 0., 0.])
@utx.skipIfMissingFeatures(["ROTATION"])
def test_invalid_quat(self):
system = self.system
with self.assertRaisesRegex(ValueError, "attribute 'quat' of 'ParticleHandle' must be non-zero"):
system.part.add(pos=[0., 0., 0.], quat=[0., 0., 0., 0.])

@utx.skipIfMissingFeatures("ELECTROSTATICS")
def test_particle_selection(self):
Expand Down

0 comments on commit 9d144d6

Please sign in to comment.