From 229651ef041277856db4c1947112b1e2c0454739 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 11 Oct 2023 13:12:45 -0400 Subject: [PATCH 01/25] add Magnetic Evaluator, first rough version --- hoomd/md/EvaluatorExternalMagneticField.h | 141 ++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 hoomd/md/EvaluatorExternalMagneticField.h diff --git a/hoomd/md/EvaluatorExternalMagneticField.h b/hoomd/md/EvaluatorExternalMagneticField.h new file mode 100644 index 0000000000..c001a8c5ec --- /dev/null +++ b/hoomd/md/EvaluatorExternalMagneticField.h @@ -0,0 +1,141 @@ +// Copyright (c) 2009-2023 The Regents of the University of Michigan. +// Part of HOOMD-blue, released under the BSD 3-Clause License. + +#ifndef __EVALUATOR_EXTERNAL_MAGNETIC_FIELD_H__ +#define __EVALUATOR_EXTERNAL_MAGNETIC_FIELD_H__ + +#ifndef __HIPCC__ +#include +#endif + +#include "hoomd/HOOMDMath.h" +#include + +/*! \file EvaluatorExternalMagneticField.h + \brief Defines the external potential evaluator to induce a magnetic field +*/ + +// need to declare these class methods with __device__ qualifiers when building in nvcc +// DEVICE is __host__ __device__ when included in nvcc and blank when included into the host +// compiler +#ifdef __HIPCC__ +#define DEVICE __device__ +#else +#define DEVICE +#endif + +namespace hoomd + { +namespace md + { +//! Class for evaluating an magnetic field +/*! General Overview + The external potential \f$V(\theta) \f$ is implemented using the following formula: + + \f[ + V(\theta}) = - \vec{B} \cdot \vec{n}_i(\theta) + \f] + + where \f$B\f$ is the strength of the magnetic field and \f$\vec{n}_i\f$ is the magnetic moment of particle i. +*/ +class EvaluatorExternalMagneticField + { + public: + //! type of parameters this external potential accepts + struct param_type + { + Scalar3 B; + Scalar3 mu; + +#ifndef __HIPCC__ + param_type() : B(make_scalar3(0, 0, 0)), mu(make_scalar3(0, 0, 0)) { } + + param_type(pybind11::dict params) + { + B = params["B"].cast(); + mu = params["mu"].cast(); + } + + param_type(Scalar3 B_, Scalar3 mu_) : B(B_), mu(mu_) { } + + + pybind11::dict toPython() + { + pybind11::dict d; + d["B"] = B; + d["mu"] = mu; + return d; + } +#endif // ifndef __HIPCC__ + } __attribute__((aligned(16))); + + typedef void* field_type; + + //! Constructs the constraint evaluator + /*! \param X position of particle + \param box box dimensions + \param params per-type parameters of external potential + */ + DEVICE EvaluatorExternalMagneticField(Scalar3 X, + const BoxDim& box, + const param_type& params, + const field_type& field) + : m_quat(X), m_B(params.B), m_mu(params.mu) + { + } + + //! ExternalMagneticField needs charges + DEVICE static bool needsCharge() + { + return false; + } + + //! Accept the optional charge value + /*! \param qi Charge of particle i + */ + DEVICE void setCharge(Scalar qi) { } + + //! Declares additional virial contributions are needed for the external field + /*! No contribution + */ + DEVICE static bool requestFieldVirialTerm() + { + return false; + } + + //! Evaluate the force, energy and virial + /*! \param F force vector + \param energy value of the energy + \param virial array of six scalars for the upper triangular virial tensor + */ + DEVICE void evalForceEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) + { + + Scalar3 dir = m_mu * u_i; + + T = cross(dir, m_B); + + energy = - dot(dir,m_B); + + } + +#ifndef __HIPCC__ + //! Get the name of this potential + /*! \returns The potential name. + */ + static std::string getName() + { + return std::string("b_field"); + } +#endif + + protected: + Scalar4 m_quat; //!< particle position + Scalar3 m_mu; //!< particle charge + Scalar3 m_B; //!< the field vector + }; + + } // end namespace md + } // end namespace hoomd + +#endif // __EVALUATOR_EXTERNAL_LAMELLAR_H__ From 08b8daef9c650661b74cabcddff8ace392436477 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 11 Oct 2023 15:22:33 -0400 Subject: [PATCH 02/25] add orientations and torques to external fields --- hoomd/md/EvaluatorExternalElectricField.h | 8 +++++++- hoomd/md/EvaluatorExternalMagneticField.h | 14 +++++++++---- hoomd/md/EvaluatorExternalPeriodic.h | 9 +++++++- hoomd/md/EvaluatorWalls.h | 9 ++++++-- hoomd/md/PotentialExternal.h | 21 ++++++++++++++++--- hoomd/md/PotentialExternalGPU.cuh | 25 +++++++++++++++++++---- hoomd/md/PotentialExternalGPU.h | 8 ++++++++ 7 files changed, 79 insertions(+), 15 deletions(-) diff --git a/hoomd/md/EvaluatorExternalElectricField.h b/hoomd/md/EvaluatorExternalElectricField.h index 46a649437d..e0286a3e13 100644 --- a/hoomd/md/EvaluatorExternalElectricField.h +++ b/hoomd/md/EvaluatorExternalElectricField.h @@ -10,6 +10,7 @@ #include "hoomd/BoxDim.h" #include "hoomd/HOOMDMath.h" +#include "hoomd/VectorMath.h" #include /*! \file EvaluatorExternalElectricField.h @@ -75,6 +76,7 @@ class EvaluatorExternalElectricField \param params per-type parameters of external potential */ DEVICE EvaluatorExternalElectricField(Scalar3 X, + quat q, const BoxDim& box, const param_type& params, const field_type& field) @@ -109,7 +111,7 @@ class EvaluatorExternalElectricField \param energy value of the energy \param virial array of six scalars for the upper triangular virial tensor */ - DEVICE void evalForceEnergyAndVirial(Scalar3& F, Scalar& energy, Scalar* virial) + DEVICE void evalForceEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) { F = m_qi * m_E; energy = -m_qi * dot(m_E, m_pos); @@ -120,6 +122,10 @@ class EvaluatorExternalElectricField virial[3] = F.y * m_pos.y; virial[4] = F.y * m_pos.z; virial[5] = F.z * m_pos.z; + + T.x = Scalar(0.0); + T.y = Scalar(0.0); + T.z = Scalar(0.0); } #ifndef __HIPCC__ diff --git a/hoomd/md/EvaluatorExternalMagneticField.h b/hoomd/md/EvaluatorExternalMagneticField.h index c001a8c5ec..dba3b80f17 100644 --- a/hoomd/md/EvaluatorExternalMagneticField.h +++ b/hoomd/md/EvaluatorExternalMagneticField.h @@ -8,7 +8,9 @@ #include #endif +#include "hoomd/BoxDim.h" #include "hoomd/HOOMDMath.h" +#include "hoomd/VectorMath.h" #include /*! \file EvaluatorExternalMagneticField.h @@ -77,10 +79,11 @@ class EvaluatorExternalMagneticField \param params per-type parameters of external potential */ DEVICE EvaluatorExternalMagneticField(Scalar3 X, + quat q, const BoxDim& box, const param_type& params, const field_type& field) - : m_quat(X), m_B(params.B), m_mu(params.mu) + : m_q(q), m_B(params.B), m_mu(params.mu) { } @@ -111,12 +114,15 @@ class EvaluatorExternalMagneticField DEVICE void evalForceEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) { - Scalar3 dir = m_mu * u_i; + Scalar3 dir = rotate(m_mu , m_q); T = cross(dir, m_B); - energy = - dot(dir,m_B); + energy = -dot(dir,m_B); + F.x = Scalar(0.0); + F.y = Scalar(0.0); + F.z = Scalar(0.0); } #ifndef __HIPCC__ @@ -130,7 +136,7 @@ class EvaluatorExternalMagneticField #endif protected: - Scalar4 m_quat; //!< particle position + quat m_q; //!< particle position Scalar3 m_mu; //!< particle charge Scalar3 m_B; //!< the field vector }; diff --git a/hoomd/md/EvaluatorExternalPeriodic.h b/hoomd/md/EvaluatorExternalPeriodic.h index 1d3a08688b..6358cfdbae 100644 --- a/hoomd/md/EvaluatorExternalPeriodic.h +++ b/hoomd/md/EvaluatorExternalPeriodic.h @@ -10,6 +10,7 @@ #include "hoomd/BoxDim.h" #include "hoomd/HOOMDMath.h" +#include "hoomd/VectorMath.h" #include /*! \file EvaluatorExternalPeriodic.h @@ -89,6 +90,7 @@ class EvaluatorExternalPeriodic \param params per-type parameters of external potential */ DEVICE EvaluatorExternalPeriodic(Scalar3 X, + quat q, const BoxDim& box, const param_type& params, const field_type& field) @@ -120,7 +122,7 @@ class EvaluatorExternalPeriodic \param energy value of the energy \param virial array of six scalars for the upper triangular virial tensor */ - DEVICE void evalForceEnergyAndVirial(Scalar3& F, Scalar& energy, Scalar* virial) + DEVICE void evalForceEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) { Scalar3 a2 = make_scalar3(0, 0, 0); Scalar3 a3 = make_scalar3(0, 0, 0); @@ -128,6 +130,11 @@ class EvaluatorExternalPeriodic F.x = Scalar(0.0); F.y = Scalar(0.0); F.z = Scalar(0.0); + + T.x = Scalar(0.0); + T.y = Scalar(0.0); + T.z = Scalar(0.0); + energy = Scalar(0.0); // For this potential, since it uses scaled positions, the virial is always zero. diff --git a/hoomd/md/EvaluatorWalls.h b/hoomd/md/EvaluatorWalls.h index 95b390caf8..1f7bd5a13b 100644 --- a/hoomd/md/EvaluatorWalls.h +++ b/hoomd/md/EvaluatorWalls.h @@ -134,7 +134,7 @@ template class EvaluatorWalls typedef wall_type field_type; //! Constructs the external wall potential evaluator - DEVICE EvaluatorWalls(Scalar3 pos, const BoxDim& box, const param_type& p, const field_type& f) + DEVICE EvaluatorWalls(Scalar3 pos, quat q, const BoxDim& box, const param_type& p, const field_type& f) : m_pos(pos), m_field(f), m_params(p) { } @@ -229,11 +229,16 @@ template class EvaluatorWalls } //! Generates force and energy from standard evaluators using wall geometry functions - DEVICE void evalForceEnergyAndVirial(Scalar3& F, Scalar& energy, Scalar* virial) + DEVICE void evalForceEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) { F.x = Scalar(0.0); F.y = Scalar(0.0); F.z = Scalar(0.0); + + T.x = Scalar(0.0); + T.y = Scalar(0.0); + T.z = Scalar(0.0); + energy = Scalar(0.0); // initialize virial for (unsigned int i = 0; i < 6; i++) diff --git a/hoomd/md/PotentialExternal.h b/hoomd/md/PotentialExternal.h index 82d181988c..659a6b224d 100644 --- a/hoomd/md/PotentialExternal.h +++ b/hoomd/md/PotentialExternal.h @@ -4,6 +4,7 @@ #include "hoomd/ForceCompute.h" #include "hoomd/GPUArray.h" #include "hoomd/GlobalArray.h" +#include "hoomd/VectorMath.h" #include "hoomd/managed_allocator.h" #include "hoomd/md/EvaluatorExternalPeriodic.h" #include @@ -99,8 +100,15 @@ template void PotentialExternal::computeForces(uint6 assert(m_pdata); // access the particle data arrays ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); + ArrayHandle h_orientation(m_pdata->getOrientationArray(), + access_location::host, + access_mode::read); ArrayHandle h_force(m_force, access_location::host, access_mode::overwrite); + ArrayHandle h_torque(m_pdata->getNetTorqueArray(), + access_location::host, + access_mode::overwrite); + ArrayHandle h_virial(m_virial, access_location::host, access_mode::overwrite); ArrayHandle h_charge(m_pdata->getCharges(), access_location::host, access_mode::read); @@ -112,10 +120,12 @@ template void PotentialExternal::computeForces(uint6 // Zero data for force calculation. memset((void*)h_force.data, 0, sizeof(Scalar4) * m_force.getNumElements()); + memset((void*)h_torque.data, 0, sizeof(Scalar4) * m_force.getNumElements()); memset((void*)h_virial.data, 0, sizeof(Scalar) * m_virial.getNumElements()); // there are enough other checks on the input data: but it doesn't hurt to be safe assert(h_force.data); + assert(h_torque.data); assert(h_virial.data); // for each of the particles @@ -124,18 +134,19 @@ template void PotentialExternal::computeForces(uint6 // get the current particle properties Scalar3 X = make_scalar3(h_pos.data[idx].x, h_pos.data[idx].y, h_pos.data[idx].z); unsigned int type = __scalar_as_int(h_pos.data[idx].w); - Scalar3 F; + quat q(h_orientation.data[idx]); + Scalar3 F, T; Scalar energy; Scalar virial[6]; - evaluator eval(X, box, h_params.data[type], *m_field); + evaluator eval(X, q, box, h_params.data[type], *m_field); if (evaluator::needsCharge()) { Scalar qi = h_charge.data[idx]; eval.setCharge(qi); } - eval.evalForceEnergyAndVirial(F, energy, virial); + eval.evalForceEnergyAndVirial(F, T, energy, virial); // apply the constraint force h_force.data[idx].x = F.x; @@ -144,6 +155,10 @@ template void PotentialExternal::computeForces(uint6 h_force.data[idx].w = energy; for (int k = 0; k < 6; k++) h_virial.data[k * m_virial_pitch + idx] = virial[k]; + + h_torque.data[idx].x = T.x; + h_torque.data[idx].y = T.y; + h_torque.data[idx].z = T.z; } } diff --git a/hoomd/md/PotentialExternalGPU.cuh b/hoomd/md/PotentialExternalGPU.cuh index 4ee4a7a108..59dd808249 100644 --- a/hoomd/md/PotentialExternalGPU.cuh +++ b/hoomd/md/PotentialExternalGPU.cuh @@ -28,23 +28,28 @@ struct external_potential_args_t { //! Construct a external_potential_args_t external_potential_args_t(Scalar4* _d_force, + Scalar4* _d_torque, Scalar* _d_virial, const size_t _virial_pitch, const unsigned int _N, const Scalar4* _d_pos, + const Scalar4* _d_orientation, const Scalar* _d_charge, const BoxDim& _box, const unsigned int _block_size, const hipDeviceProp_t& _devprop) - : d_force(_d_force), d_virial(_d_virial), virial_pitch(_virial_pitch), box(_box), N(_N), - d_pos(_d_pos), d_charge(_d_charge), block_size(_block_size), devprop(_devprop) {}; + : d_force(_d_force), d_torque(_d_torque), d_virial(_d_virial), virial_pitch(_virial_pitch), + box(_box), N(_N), d_pos(_d_pos), d_orientation(_d_orientation), d_charge(_d_charge), + block_size(_block_size), devprop(_devprop) {}; Scalar4* d_force; //!< Force to write out + Scalar4* d_torque; //!< Torque to write out Scalar* d_virial; //!< Virial to write out const size_t virial_pitch; //!< The pitch of the 2D array of virial matrix elements const BoxDim box; //!< Simulation box in GPU format const unsigned int N; //!< Number of particles const Scalar4* d_pos; //!< Device array of particle positions + const Scalar4* d_orientation; //!< Device array of particle orientations const Scalar* d_charge; //!< particle charges const unsigned int block_size; //!< Block size to execute const hipDeviceProp_t& devprop; //!< Device properties @@ -69,20 +74,24 @@ hipError_t __attribute__((visibility("default"))) gpu_compute_potential_external the potentials and forces for each particle is handled via the template class \a evaluator. \param d_force Device memory to write computed forces + \param d_torque Device memory to write computed torques \param d_virial Device memory to write computed virials \param virial_pitch pitch of 2D virial array \param N number of particles \param d_pos device array of particle positions + \param d_orientation device array of particle orientations \param box Box dimensions used to implement periodic boundary conditions \param params per-type array of parameters for the potential */ template __global__ void gpu_compute_external_forces_kernel(Scalar4* d_force, + Scalar4* d_torque, Scalar* d_virial, const size_t virial_pitch, const unsigned int N, const Scalar4* d_pos, + const Scalar4* d_orientation, const Scalar* d_charge, const BoxDim box, const typename evaluator::param_type* params, @@ -126,6 +135,7 @@ __global__ void gpu_compute_external_forces_kernel(Scalar4* d_force, // initialize the force to 0 Scalar3 force = make_scalar3(Scalar(0.0), Scalar(0.0), Scalar(0.0)); + Scalar3 torque = make_scalar3(Scalar(0.0), Scalar(0.0), Scalar(0.0)); Scalar virial[6]; for (unsigned int k = 0; k < 6; k++) virial[k] = Scalar(0.0); @@ -133,12 +143,13 @@ __global__ void gpu_compute_external_forces_kernel(Scalar4* d_force, unsigned int typei = __scalar_as_int(posi.w); Scalar3 Xi = make_scalar3(posi.x, posi.y, posi.z); - evaluator eval(Xi, box, params[typei], field); + quat q(d_orientation[idx]); + evaluator eval(Xi, q, box, params[typei], field); if (evaluator::needsCharge()) eval.setCharge(qi); - eval.evalForceEnergyAndVirial(force, energy, virial); + eval.evalForceEnergyAndVirial(force, torque, energy, virial); // now that the force calculation is complete, write out the result) d_force[idx].x = force.x; @@ -148,6 +159,10 @@ __global__ void gpu_compute_external_forces_kernel(Scalar4* d_force, for (unsigned int k = 0; k < 6; k++) d_virial[k * virial_pitch + idx] = virial[k]; + + d_torque[idx].x = torque.x; + d_torque[idx].y = torque.y; + d_torque[idx].z = torque.z; } /*! @@ -187,10 +202,12 @@ hipError_t gpu_compute_potential_external_forces( bytes, 0, external_potential_args.d_force, + external_potential_args.d_torque, external_potential_args.d_virial, external_potential_args.virial_pitch, external_potential_args.N, external_potential_args.d_pos, + external_potential_args.d_orientation, external_potential_args.d_charge, external_potential_args.box, d_params, diff --git a/hoomd/md/PotentialExternalGPU.h b/hoomd/md/PotentialExternalGPU.h index fd7c36f331..1beeb5ce74 100644 --- a/hoomd/md/PotentialExternalGPU.h +++ b/hoomd/md/PotentialExternalGPU.h @@ -61,6 +61,9 @@ template void PotentialExternalGPU::computeForces(ui ArrayHandle d_pos(this->m_pdata->getPositions(), access_location::device, access_mode::read); + ArrayHandle d_orientation(this->m_pdata->getOrientationArray(), + access_location::device, + access_mode::read); ArrayHandle d_charge(this->m_pdata->getCharges(), access_location::device, access_mode::read); @@ -68,6 +71,9 @@ template void PotentialExternalGPU::computeForces(ui const BoxDim box = this->m_pdata->getGlobalBox(); ArrayHandle d_force(this->m_force, access_location::device, access_mode::overwrite); + ArrayHandle d_torque(this->m_pdata->getNetTorqueArray(), + access_location::device, + access_mode::overwrite); ArrayHandle d_virial(this->m_virial, access_location::device, access_mode::overwrite); ArrayHandle d_params(this->m_params, access_location::device, @@ -76,10 +82,12 @@ template void PotentialExternalGPU::computeForces(ui m_tuner->begin(); kernel::gpu_compute_potential_external_forces( kernel::external_potential_args_t(d_force.data, + d_torque.data, d_virial.data, this->m_virial.getPitch(), this->m_pdata->getN(), d_pos.data, + d_orientation.data, d_charge.data, box, m_tuner->getParam()[0], From 8ecf59bbc944dabfc55d12b1afe2956a361aea29 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 11 Oct 2023 20:04:03 -0400 Subject: [PATCH 03/25] implement magnetic field (no pytests) --- hoomd/md/CMakeLists.txt | 3 +- hoomd/md/EvaluatorExternalElectricField.h | 5 ++++ hoomd/md/EvaluatorExternalMagneticField.h | 34 +++++++++++++++++------ hoomd/md/EvaluatorExternalPeriodic.h | 5 ++++ hoomd/md/EvaluatorWalls.h | 5 ++++ hoomd/md/PotentialExternal.h | 13 +++++++-- hoomd/md/PotentialExternalGPU.h | 2 +- hoomd/md/module-md.cc | 4 +++ 8 files changed, 59 insertions(+), 12 deletions(-) diff --git a/hoomd/md/CMakeLists.txt b/hoomd/md/CMakeLists.txt index 95f24e2214..aefbd22e69 100644 --- a/hoomd/md/CMakeLists.txt +++ b/hoomd/md/CMakeLists.txt @@ -87,6 +87,7 @@ set(_md_headers ActiveForceComputeGPU.h EvaluatorSpecialPairLJ.h EvaluatorSpecialPairCoulomb.h EvaluatorExternalElectricField.h + EvaluatorExternalMagneticField.h EvaluatorExternalPeriodic.h EvaluatorPairALJ.h EvaluatorPairBuckingham.h @@ -426,7 +427,7 @@ foreach(_evaluator ${_triplets}) endif() endforeach() -set(_external_evaluators Periodic ElectricField) +set(_external_evaluators Periodic ElectricField MagneticField) foreach(_evaluator ${_external_evaluators}) configure_file(export_PotentialExternal.cc.inc diff --git a/hoomd/md/EvaluatorExternalElectricField.h b/hoomd/md/EvaluatorExternalElectricField.h index e0286a3e13..b011ff31b8 100644 --- a/hoomd/md/EvaluatorExternalElectricField.h +++ b/hoomd/md/EvaluatorExternalElectricField.h @@ -84,6 +84,11 @@ class EvaluatorExternalElectricField { } + DEVICE static bool isAnisotropic() + { + return false; + } + //! ExternalElectricField needs charges DEVICE static bool needsCharge() { diff --git a/hoomd/md/EvaluatorExternalMagneticField.h b/hoomd/md/EvaluatorExternalMagneticField.h index dba3b80f17..cf798ac934 100644 --- a/hoomd/md/EvaluatorExternalMagneticField.h +++ b/hoomd/md/EvaluatorExternalMagneticField.h @@ -54,8 +54,14 @@ class EvaluatorExternalMagneticField param_type(pybind11::dict params) { - B = params["B"].cast(); - mu = params["mu"].cast(); + pybind11::tuple py_B = params["B"]; + B.x = pybind11::cast(py_B[0]); + B.y = pybind11::cast(py_B[1]); + B.z = pybind11::cast(py_B[2]); + pybind11::tuple py_mu = params["mu"]; + mu.x = pybind11::cast(py_mu[0]); + mu.y = pybind11::cast(py_mu[1]); + mu.z = pybind11::cast(py_mu[2]); } param_type(Scalar3 B_, Scalar3 mu_) : B(B_), mu(mu_) { } @@ -64,8 +70,8 @@ class EvaluatorExternalMagneticField pybind11::dict toPython() { pybind11::dict d; - d["B"] = B; - d["mu"] = mu; + d["B"] = pybind11::make_tuple(B.x, B.y, B.z);; + d["mu"] = pybind11::make_tuple(mu.x, mu.y, mu.z);; return d; } #endif // ifndef __HIPCC__ @@ -87,6 +93,11 @@ class EvaluatorExternalMagneticField { } + DEVICE static bool isAnisotropic() + { + return true; + } + //! ExternalMagneticField needs charges DEVICE static bool needsCharge() { @@ -114,15 +125,22 @@ class EvaluatorExternalMagneticField DEVICE void evalForceEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) { - Scalar3 dir = rotate(m_mu , m_q); + vec3 dir = rotate(m_q, m_mu); - T = cross(dir, m_B); + vec3 T_vec = cross(dir, m_B); + + T.x = T_vec.x; + T.y = T_vec.y; + T.z = T_vec.z; energy = -dot(dir,m_B); F.x = Scalar(0.0); F.y = Scalar(0.0); F.z = Scalar(0.0); + + for (unsigned int i = 0; i < 6; i++) + virial[i] = Scalar(0.0); } #ifndef __HIPCC__ @@ -137,8 +155,8 @@ class EvaluatorExternalMagneticField protected: quat m_q; //!< particle position - Scalar3 m_mu; //!< particle charge - Scalar3 m_B; //!< the field vector + vec3 m_B; //!< the field vector + vec3 m_mu; //!< particle charge }; } // end namespace md diff --git a/hoomd/md/EvaluatorExternalPeriodic.h b/hoomd/md/EvaluatorExternalPeriodic.h index 6358cfdbae..d5185fe40c 100644 --- a/hoomd/md/EvaluatorExternalPeriodic.h +++ b/hoomd/md/EvaluatorExternalPeriodic.h @@ -99,6 +99,11 @@ class EvaluatorExternalPeriodic { } + DEVICE static bool isAnisotropic() + { + return false; + } + //! External Periodic doesn't need charges DEVICE static bool needsCharge() { diff --git a/hoomd/md/EvaluatorWalls.h b/hoomd/md/EvaluatorWalls.h index 1f7bd5a13b..9af66da397 100644 --- a/hoomd/md/EvaluatorWalls.h +++ b/hoomd/md/EvaluatorWalls.h @@ -139,6 +139,11 @@ template class EvaluatorWalls { } + DEVICE static bool isAnisotropic() + { + return false; + } + //! Charges not supported by walls evals DEVICE static bool needsCharge() { diff --git a/hoomd/md/PotentialExternal.h b/hoomd/md/PotentialExternal.h index 659a6b224d..5582534ea0 100644 --- a/hoomd/md/PotentialExternal.h +++ b/hoomd/md/PotentialExternal.h @@ -44,6 +44,8 @@ template class PotentialExternal : public ForceCompute typedef typename evaluator::param_type param_type; typedef typename evaluator::field_type field_type; + bool isAnisotropic(); + //! Sets parameters of the evaluator pybind11::object getParams(std::string type); @@ -105,7 +107,7 @@ template void PotentialExternal::computeForces(uint6 access_mode::read); ArrayHandle h_force(m_force, access_location::host, access_mode::overwrite); - ArrayHandle h_torque(m_pdata->getNetTorqueArray(), + ArrayHandle h_torque(m_torque, access_location::host, access_mode::overwrite); @@ -120,7 +122,7 @@ template void PotentialExternal::computeForces(uint6 // Zero data for force calculation. memset((void*)h_force.data, 0, sizeof(Scalar4) * m_force.getNumElements()); - memset((void*)h_torque.data, 0, sizeof(Scalar4) * m_force.getNumElements()); + memset((void*)h_torque.data, 0, sizeof(Scalar4) * m_torque.getNumElements()); memset((void*)h_virial.data, 0, sizeof(Scalar) * m_virial.getNumElements()); // there are enough other checks on the input data: but it doesn't hurt to be safe @@ -171,6 +173,13 @@ void PotentialExternal::validateType(unsigned int type, std::string a } } +//! Returns true if this ForceCompute requires anisotropic integration +template bool PotentialExternal::isAnisotropic() + { + // by default, only translational degrees of freedom are integrated + return evaluator::isAnisotropic(); + } + //! Set the parameters for this potential /*! \param type type for which to set parameters \param params value of parameters diff --git a/hoomd/md/PotentialExternalGPU.h b/hoomd/md/PotentialExternalGPU.h index 1beeb5ce74..adb80ee5e6 100644 --- a/hoomd/md/PotentialExternalGPU.h +++ b/hoomd/md/PotentialExternalGPU.h @@ -71,7 +71,7 @@ template void PotentialExternalGPU::computeForces(ui const BoxDim box = this->m_pdata->getGlobalBox(); ArrayHandle d_force(this->m_force, access_location::device, access_mode::overwrite); - ArrayHandle d_torque(this->m_pdata->getNetTorqueArray(), + ArrayHandle d_torque(this->m_torque, access_location::device, access_mode::overwrite); ArrayHandle d_virial(this->m_virial, access_location::device, access_mode::overwrite); diff --git a/hoomd/md/module-md.cc b/hoomd/md/module-md.cc index f3e574ffed..ed9d3ea0d0 100644 --- a/hoomd/md/module-md.cc +++ b/hoomd/md/module-md.cc @@ -88,6 +88,7 @@ void export_PotentialRevCross(pybind11::module& m); void export_PotentialExternalPeriodic(pybind11::module& m); void export_PotentialExternalElectricField(pybind11::module& m); +void export_PotentialExternalMagneticField(pybind11::module& m); void export_PotentialExternalWallLJ(pybind11::module& m); void export_PotentialExternalWallYukawa(pybind11::module& m); @@ -230,6 +231,7 @@ void export_PotentialRevCrossGPU(pybind11::module& m); void export_PotentialExternalPeriodicGPU(pybind11::module& m); void export_PotentialExternalElectricFieldGPU(pybind11::module& m); +void export_PotentialExternalMagneticFieldGPU(pybind11::module& m); void export_PotentialExternalWallLJGPU(pybind11::module& m); void export_PotentialExternalWallYukawaGPU(pybind11::module& m); @@ -369,6 +371,7 @@ PYBIND11_MODULE(_md, m) export_PotentialExternalPeriodic(m); export_PotentialExternalElectricField(m); + export_PotentialExternalMagneticField(m); export_wall_data(m); export_wall_field(m); @@ -457,6 +460,7 @@ PYBIND11_MODULE(_md, m) export_ConstantForceComputeGPU(m); export_PotentialExternalPeriodicGPU(m); export_PotentialExternalElectricFieldGPU(m); + export_PotentialExternalMagneticFieldGPU(m); export_PotentialExternalWallLJGPU(m); export_PotentialExternalWallYukawaGPU(m); From 8f70b453e07f44ba165d73f6cecda18c85d453ef Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Wed, 11 Oct 2023 20:04:33 -0400 Subject: [PATCH 04/25] add py file --- hoomd/md/external/field.py | 41 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/hoomd/md/external/field.py b/hoomd/md/external/field.py index a2f4a68459..8cf316f24f 100644 --- a/hoomd/md/external/field.py +++ b/hoomd/md/external/field.py @@ -120,3 +120,44 @@ def __init__(self): 'E', 'particle_types', TypeParameterDict((float, float, float), len_keys=1)) self._add_typeparam(params) + +class Magnetic(Field): + """Magnetic field torque. + + `Magnetic` computes forces, and virials, and energies on all particles in + the in the simulation state with consistent with: + + .. math:: + + U_i = -\\vec{mu}_i \\cdot \\vec{B} + + + where :math:`\\vec{mu}_i` is the particle magnetic momentum and :math:`\\vec{B}` is the field + vector. The field vector :math:`\\vec{B}` must be set per unique particle + type. + + .. py:attribute:: params + + The `Magnetic` external potential parameters. The dictionary has the + following keys: + + * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic field vector + :math:`B [\\mathrm{energy}]`. + * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic moment of + the particles type :math:`mu [\\mathrm{energy}]`. + + Type: `TypeParameter` [``particle_type``, `dict`] + + Example:: + + # Apply an magnetic field in the x-direction + m_field = external.field.Magnetic() + m_field.params['A'] = dict(B=(1.0,0.0,0.0), mu=(1.0,0.0,0.0)) + """ + _cpp_class_name = "PotentialExternalMagneticField" + + def __init__(self): + params = TypeParameter( + 'params', 'particle_types', + TypeParameterDict(B=(float, float, float), mu=(float, float, float), len_keys=1)) + self._add_typeparam(params) From a40f5c71c627bf1e37e9651ff14de070f28105cc Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Thu, 12 Oct 2023 17:15:09 -0400 Subject: [PATCH 05/25] add pytests --- hoomd/md/pytest/test_external.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/hoomd/md/pytest/test_external.py b/hoomd/md/pytest/test_external.py index e4a655b26e..fbec5739dc 100644 --- a/hoomd/md/pytest/test_external.py +++ b/hoomd/md/pytest/test_external.py @@ -35,7 +35,8 @@ def _evaluate_periodic(snapshot, params): forces *= 1 - (np.tanh( np.cos(p * np.dot(positions, b)) / (2 * np.pi * p * w)))**2 forces = np.outer(forces, b) - return forces, energies + torques = [[0,0,0],]*len(positions) + return forces, torques, energies def _evaluate_electric(snapshot, params): @@ -45,7 +46,19 @@ def _evaluate_electric(snapshot, params): E_field = params energies = -charges * np.dot(positions, E_field) forces = np.outer(charges, E_field) - return forces, energies + torques = [[0,0,0],]*len(positions) + return forces, torques, energies + +def _evaluate_magnetic(snapshot, params): + """Evaluate force and energy in python for MagneticField.""" + positions = snapshot.particles.position + N = len(positions) + B_field = params['B'] + b_moment = params['mu'] + energies = np.repeat(-np.dot(b_moment, B_field),N) + torques = np.tile(np.cross(b_moment, B_field),(N,1)) + forces = [[0,0,0],]*N + return forces, torques, energies def _external_params(): @@ -60,6 +73,11 @@ def _external_params(): (1, 0, 0), (0, 2, 0), ]), _evaluate_electric)) + list_ext_params.append( + (hoomd.md.external.field.Magnetic, "params", list([ + dict( B=(0, 2, -11.5), mu=(1,2,3) ), + dict( B=(1, 0, 1), mu=(1,1,1) ) + ]), _evaluate_magnetic)) return list_ext_params @@ -131,19 +149,21 @@ def test_forces_and_energies(simulation_factory, lattice_snapshot_factory, # test energies new_snap = sim.state.get_snapshot() forces = sim.operations.integrator.forces[0].forces + torques = sim.operations.integrator.forces[0].torques energies = sim.operations.integrator.forces[0].energies if new_snap.communicator.rank == 0: - expected_forces, expected_energies = evaluator(new_snap, param) + expected_forces, expected_torques, expected_energies = evaluator(new_snap, param) # Set atol as the energies and forces very close to 0. # It would be better to run a test that applies appreciable forces # and energies. np.testing.assert_allclose(expected_forces, forces, atol=1e-5) + np.testing.assert_allclose(expected_torques, torques, atol=1e-5) np.testing.assert_allclose(expected_energies, energies, atol=1e-5) # Test Logging _potential_cls = (md.external.field.Field, md.external.field.Periodic, - md.external.field.Electric) + md.external.field.Electric, md.external.field.Magnetic) @pytest.mark.parametrize( From 778a8a9c60ea0d2f2775b7273894da9915de26dd Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Thu, 19 Oct 2023 17:51:30 -0400 Subject: [PATCH 06/25] improve docs --- hoomd/md/external/field.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/hoomd/md/external/field.py b/hoomd/md/external/field.py index 8cf316f24f..4dc499fea1 100644 --- a/hoomd/md/external/field.py +++ b/hoomd/md/external/field.py @@ -87,7 +87,7 @@ class Electric(Field): """Electric field force. `Electric` computes forces, and virials, and energies on all particles in - the in the simulation state with consistent with: + the simulation state which are consistent with: .. math:: @@ -122,19 +122,19 @@ def __init__(self): self._add_typeparam(params) class Magnetic(Field): - """Magnetic field torque. + """Magnetic field torque on a magnetic dipole. - `Magnetic` computes forces, and virials, and energies on all particles in - the in the simulation state with consistent with: + `Magnetic` computes torces and energies on all particles in + the simulation state which are consistent with: .. math:: U_i = -\\vec{mu}_i \\cdot \\vec{B} - where :math:`\\vec{mu}_i` is the particle magnetic momentum and :math:`\\vec{B}` is the field - vector. The field vector :math:`\\vec{B}` must be set per unique particle - type. + where :math:`\\vec{mu}_i` is the particle magnetic momentum and + :math:`\\vec{B}` is the field vector. The field vector :math:`\\vec{B}` + must be set per unique particle type. .. py:attribute:: params @@ -142,9 +142,11 @@ class Magnetic(Field): following keys: * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic field vector - :math:`B [\\mathrm{energy}]`. + :math:`[\mathrm{energy} \cdot \mathrm{time} \cdot \mathrm{charge}^{-1} \cdot + \mathrm{length}^{-2} ]`. * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic moment of - the particles type :math:`mu [\\mathrm{energy}]`. + the particles type :math:`[\mathrm{charge} \cdot \mathrm{length}^2 \cdot + \mathrm{time}^{-1}]`. Type: `TypeParameter` [``particle_type``, `dict`] From b4220148885926c2cf4e27024b85216eb7be64af Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Fri, 20 Oct 2023 09:29:22 -0400 Subject: [PATCH 07/25] fix docs --- hoomd/md/external/field.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hoomd/md/external/field.py b/hoomd/md/external/field.py index 4dc499fea1..35619cbadc 100644 --- a/hoomd/md/external/field.py +++ b/hoomd/md/external/field.py @@ -142,11 +142,11 @@ class Magnetic(Field): following keys: * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic field vector - :math:`[\mathrm{energy} \cdot \mathrm{time} \cdot \mathrm{charge}^{-1} \cdot - \mathrm{length}^{-2} ]`. + :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot + \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic moment of - the particles type :math:`[\mathrm{charge} \cdot \mathrm{length}^2 \cdot - \mathrm{time}^{-1}]`. + the particles type :math:`[\\mathrm{charge} \\cdot + \\mathrm{length}^2 \\cdot \\mathrm{time}^{-1}]`. Type: `TypeParameter` [``particle_type``, `dict`] From 48268c5f29b99c5fb48ae02d5e8614c6c48def80 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Fri, 20 Oct 2023 10:21:09 -0400 Subject: [PATCH 08/25] some more fixes to the docs --- hoomd/md/external/field.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hoomd/md/external/field.py b/hoomd/md/external/field.py index 35619cbadc..6e0899d96c 100644 --- a/hoomd/md/external/field.py +++ b/hoomd/md/external/field.py @@ -141,11 +141,11 @@ class Magnetic(Field): The `Magnetic` external potential parameters. The dictionary has the following keys: - * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic field vector - :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot + * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic + field vector :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. - * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic moment of - the particles type :math:`[\\mathrm{charge} \\cdot + * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic + moment of the particles type :math:`[\\mathrm{charge} \\cdot \\mathrm{length}^2 \\cdot \\mathrm{time}^{-1}]`. Type: `TypeParameter` [``particle_type``, `dict`] From 6f100bf87e2524d19a8289817d11d63593b3b626 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Fri, 20 Oct 2023 10:51:50 -0400 Subject: [PATCH 09/25] fix pre-commit issues --- hoomd/md/external/field.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hoomd/md/external/field.py b/hoomd/md/external/field.py index 6e0899d96c..2632ba91b4 100644 --- a/hoomd/md/external/field.py +++ b/hoomd/md/external/field.py @@ -142,10 +142,10 @@ class Magnetic(Field): following keys: * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic - field vector :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot + field vector :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot \ \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic - moment of the particles type :math:`[\\mathrm{charge} \\cdot + moment of the particles type :math:`[\\mathrm{charge} \\cdot \ \\mathrm{length}^2 \\cdot \\mathrm{time}^{-1}]`. Type: `TypeParameter` [``particle_type``, `dict`] From f9188ec576b7321a1bc7a3d7c427bf19f2eed2d3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 14 Nov 2023 15:24:30 +0000 Subject: [PATCH 10/25] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- hoomd/md/EvaluatorExternalElectricField.h | 8 ++--- hoomd/md/EvaluatorExternalMagneticField.h | 37 ++++++++++++----------- hoomd/md/EvaluatorExternalPeriodic.h | 8 ++--- hoomd/md/EvaluatorWalls.h | 6 +++- hoomd/md/PotentialExternal.h | 18 +++++------ hoomd/md/PotentialExternalGPU.cuh | 6 ++-- hoomd/md/PotentialExternalGPU.h | 4 +-- hoomd/md/external/field.py | 15 +++++---- hoomd/md/pytest/test_external.py | 30 +++++++++++------- 9 files changed, 72 insertions(+), 60 deletions(-) diff --git a/hoomd/md/EvaluatorExternalElectricField.h b/hoomd/md/EvaluatorExternalElectricField.h index b011ff31b8..e3a2cc850f 100644 --- a/hoomd/md/EvaluatorExternalElectricField.h +++ b/hoomd/md/EvaluatorExternalElectricField.h @@ -76,7 +76,7 @@ class EvaluatorExternalElectricField \param params per-type parameters of external potential */ DEVICE EvaluatorExternalElectricField(Scalar3 X, - quat q, + quat q, const BoxDim& box, const param_type& params, const field_type& field) @@ -128,9 +128,9 @@ class EvaluatorExternalElectricField virial[4] = F.y * m_pos.z; virial[5] = F.z * m_pos.z; - T.x = Scalar(0.0); - T.y = Scalar(0.0); - T.z = Scalar(0.0); + T.x = Scalar(0.0); + T.y = Scalar(0.0); + T.z = Scalar(0.0); } #ifndef __HIPCC__ diff --git a/hoomd/md/EvaluatorExternalMagneticField.h b/hoomd/md/EvaluatorExternalMagneticField.h index cf798ac934..c67851ae22 100644 --- a/hoomd/md/EvaluatorExternalMagneticField.h +++ b/hoomd/md/EvaluatorExternalMagneticField.h @@ -38,7 +38,8 @@ namespace md V(\theta}) = - \vec{B} \cdot \vec{n}_i(\theta) \f] - where \f$B\f$ is the strength of the magnetic field and \f$\vec{n}_i\f$ is the magnetic moment of particle i. + where \f$B\f$ is the strength of the magnetic field and \f$\vec{n}_i\f$ is the magnetic moment + of particle i. */ class EvaluatorExternalMagneticField { @@ -66,12 +67,13 @@ class EvaluatorExternalMagneticField param_type(Scalar3 B_, Scalar3 mu_) : B(B_), mu(mu_) { } - pybind11::dict toPython() { pybind11::dict d; - d["B"] = pybind11::make_tuple(B.x, B.y, B.z);; - d["mu"] = pybind11::make_tuple(mu.x, mu.y, mu.z);; + d["B"] = pybind11::make_tuple(B.x, B.y, B.z); + ; + d["mu"] = pybind11::make_tuple(mu.x, mu.y, mu.z); + ; return d; } #endif // ifndef __HIPCC__ @@ -85,7 +87,7 @@ class EvaluatorExternalMagneticField \param params per-type parameters of external potential */ DEVICE EvaluatorExternalMagneticField(Scalar3 X, - quat q, + quat q, const BoxDim& box, const param_type& params, const field_type& field) @@ -124,20 +126,19 @@ class EvaluatorExternalMagneticField */ DEVICE void evalForceEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) { - - vec3 dir = rotate(m_q, m_mu); + vec3 dir = rotate(m_q, m_mu); - vec3 T_vec = cross(dir, m_B); + vec3 T_vec = cross(dir, m_B); - T.x = T_vec.x; - T.y = T_vec.y; - T.z = T_vec.z; + T.x = T_vec.x; + T.y = T_vec.y; + T.z = T_vec.z; - energy = -dot(dir,m_B); + energy = -dot(dir, m_B); - F.x = Scalar(0.0); - F.y = Scalar(0.0); - F.z = Scalar(0.0); + F.x = Scalar(0.0); + F.y = Scalar(0.0); + F.z = Scalar(0.0); for (unsigned int i = 0; i < 6; i++) virial[i] = Scalar(0.0); @@ -154,9 +155,9 @@ class EvaluatorExternalMagneticField #endif protected: - quat m_q; //!< particle position - vec3 m_B; //!< the field vector - vec3 m_mu; //!< particle charge + quat m_q; //!< particle position + vec3 m_B; //!< the field vector + vec3 m_mu; //!< particle charge }; } // end namespace md diff --git a/hoomd/md/EvaluatorExternalPeriodic.h b/hoomd/md/EvaluatorExternalPeriodic.h index d5185fe40c..8028717ead 100644 --- a/hoomd/md/EvaluatorExternalPeriodic.h +++ b/hoomd/md/EvaluatorExternalPeriodic.h @@ -90,7 +90,7 @@ class EvaluatorExternalPeriodic \param params per-type parameters of external potential */ DEVICE EvaluatorExternalPeriodic(Scalar3 X, - quat q, + quat q, const BoxDim& box, const param_type& params, const field_type& field) @@ -136,9 +136,9 @@ class EvaluatorExternalPeriodic F.y = Scalar(0.0); F.z = Scalar(0.0); - T.x = Scalar(0.0); - T.y = Scalar(0.0); - T.z = Scalar(0.0); + T.x = Scalar(0.0); + T.y = Scalar(0.0); + T.z = Scalar(0.0); energy = Scalar(0.0); diff --git a/hoomd/md/EvaluatorWalls.h b/hoomd/md/EvaluatorWalls.h index 9af66da397..b4f924e0a6 100644 --- a/hoomd/md/EvaluatorWalls.h +++ b/hoomd/md/EvaluatorWalls.h @@ -134,7 +134,11 @@ template class EvaluatorWalls typedef wall_type field_type; //! Constructs the external wall potential evaluator - DEVICE EvaluatorWalls(Scalar3 pos, quat q, const BoxDim& box, const param_type& p, const field_type& f) + DEVICE EvaluatorWalls(Scalar3 pos, + quat q, + const BoxDim& box, + const param_type& p, + const field_type& f) : m_pos(pos), m_field(f), m_params(p) { } diff --git a/hoomd/md/PotentialExternal.h b/hoomd/md/PotentialExternal.h index 5582534ea0..0c585fb414 100644 --- a/hoomd/md/PotentialExternal.h +++ b/hoomd/md/PotentialExternal.h @@ -102,14 +102,12 @@ template void PotentialExternal::computeForces(uint6 assert(m_pdata); // access the particle data arrays ArrayHandle h_pos(m_pdata->getPositions(), access_location::host, access_mode::read); - ArrayHandle h_orientation(m_pdata->getOrientationArray(), - access_location::host, - access_mode::read); + ArrayHandle h_orientation(m_pdata->getOrientationArray(), + access_location::host, + access_mode::read); ArrayHandle h_force(m_force, access_location::host, access_mode::overwrite); - ArrayHandle h_torque(m_torque, - access_location::host, - access_mode::overwrite); + ArrayHandle h_torque(m_torque, access_location::host, access_mode::overwrite); ArrayHandle h_virial(m_virial, access_location::host, access_mode::overwrite); ArrayHandle h_charge(m_pdata->getCharges(), access_location::host, access_mode::read); @@ -175,10 +173,10 @@ void PotentialExternal::validateType(unsigned int type, std::string a //! Returns true if this ForceCompute requires anisotropic integration template bool PotentialExternal::isAnisotropic() - { - // by default, only translational degrees of freedom are integrated - return evaluator::isAnisotropic(); - } + { + // by default, only translational degrees of freedom are integrated + return evaluator::isAnisotropic(); + } //! Set the parameters for this potential /*! \param type type for which to set parameters diff --git a/hoomd/md/PotentialExternalGPU.cuh b/hoomd/md/PotentialExternalGPU.cuh index 59dd808249..89f9749b94 100644 --- a/hoomd/md/PotentialExternalGPU.cuh +++ b/hoomd/md/PotentialExternalGPU.cuh @@ -38,9 +38,9 @@ struct external_potential_args_t const BoxDim& _box, const unsigned int _block_size, const hipDeviceProp_t& _devprop) - : d_force(_d_force), d_torque(_d_torque), d_virial(_d_virial), virial_pitch(_virial_pitch), - box(_box), N(_N), d_pos(_d_pos), d_orientation(_d_orientation), d_charge(_d_charge), - block_size(_block_size), devprop(_devprop) {}; + : d_force(_d_force), d_torque(_d_torque), d_virial(_d_virial), virial_pitch(_virial_pitch), + box(_box), N(_N), d_pos(_d_pos), d_orientation(_d_orientation), d_charge(_d_charge), + block_size(_block_size), devprop(_devprop) {}; Scalar4* d_force; //!< Force to write out Scalar4* d_torque; //!< Torque to write out diff --git a/hoomd/md/PotentialExternalGPU.h b/hoomd/md/PotentialExternalGPU.h index adb80ee5e6..8d4ecf4c3c 100644 --- a/hoomd/md/PotentialExternalGPU.h +++ b/hoomd/md/PotentialExternalGPU.h @@ -71,9 +71,7 @@ template void PotentialExternalGPU::computeForces(ui const BoxDim box = this->m_pdata->getGlobalBox(); ArrayHandle d_force(this->m_force, access_location::device, access_mode::overwrite); - ArrayHandle d_torque(this->m_torque, - access_location::device, - access_mode::overwrite); + ArrayHandle d_torque(this->m_torque, access_location::device, access_mode::overwrite); ArrayHandle d_virial(this->m_virial, access_location::device, access_mode::overwrite); ArrayHandle d_params(this->m_params, access_location::device, diff --git a/hoomd/md/external/field.py b/hoomd/md/external/field.py index 2632ba91b4..6531d78d7b 100644 --- a/hoomd/md/external/field.py +++ b/hoomd/md/external/field.py @@ -87,7 +87,7 @@ class Electric(Field): """Electric field force. `Electric` computes forces, and virials, and energies on all particles in - the simulation state which are consistent with: + the simulation state which are consistent with: .. math:: @@ -121,19 +121,20 @@ def __init__(self): TypeParameterDict((float, float, float), len_keys=1)) self._add_typeparam(params) + class Magnetic(Field): """Magnetic field torque on a magnetic dipole. `Magnetic` computes torces and energies on all particles in - the simulation state which are consistent with: + the simulation state which are consistent with: .. math:: U_i = -\\vec{mu}_i \\cdot \\vec{B} - where :math:`\\vec{mu}_i` is the particle magnetic momentum and - :math:`\\vec{B}` is the field vector. The field vector :math:`\\vec{B}` + where :math:`\\vec{mu}_i` is the particle magnetic momentum and + :math:`\\vec{B}` is the field vector. The field vector :math:`\\vec{B}` must be set per unique particle type. .. py:attribute:: params @@ -141,7 +142,7 @@ class Magnetic(Field): The `Magnetic` external potential parameters. The dictionary has the following keys: - * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic + * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic field vector :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot \ \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic @@ -161,5 +162,7 @@ class Magnetic(Field): def __init__(self): params = TypeParameter( 'params', 'particle_types', - TypeParameterDict(B=(float, float, float), mu=(float, float, float), len_keys=1)) + TypeParameterDict(B=(float, float, float), + mu=(float, float, float), + len_keys=1)) self._add_typeparam(params) diff --git a/hoomd/md/pytest/test_external.py b/hoomd/md/pytest/test_external.py index fbec5739dc..cc980e7d58 100644 --- a/hoomd/md/pytest/test_external.py +++ b/hoomd/md/pytest/test_external.py @@ -35,7 +35,9 @@ def _evaluate_periodic(snapshot, params): forces *= 1 - (np.tanh( np.cos(p * np.dot(positions, b)) / (2 * np.pi * p * w)))**2 forces = np.outer(forces, b) - torques = [[0,0,0],]*len(positions) + torques = [ + [0, 0, 0], + ] * len(positions) return forces, torques, energies @@ -46,18 +48,23 @@ def _evaluate_electric(snapshot, params): E_field = params energies = -charges * np.dot(positions, E_field) forces = np.outer(charges, E_field) - torques = [[0,0,0],]*len(positions) + torques = [ + [0, 0, 0], + ] * len(positions) return forces, torques, energies + def _evaluate_magnetic(snapshot, params): """Evaluate force and energy in python for MagneticField.""" positions = snapshot.particles.position N = len(positions) B_field = params['B'] b_moment = params['mu'] - energies = np.repeat(-np.dot(b_moment, B_field),N) - torques = np.tile(np.cross(b_moment, B_field),(N,1)) - forces = [[0,0,0],]*N + energies = np.repeat(-np.dot(b_moment, B_field), N) + torques = np.tile(np.cross(b_moment, B_field), (N, 1)) + forces = [ + [0, 0, 0], + ] * N return forces, torques, energies @@ -73,11 +80,11 @@ def _external_params(): (1, 0, 0), (0, 2, 0), ]), _evaluate_electric)) - list_ext_params.append( - (hoomd.md.external.field.Magnetic, "params", list([ - dict( B=(0, 2, -11.5), mu=(1,2,3) ), - dict( B=(1, 0, 1), mu=(1,1,1) ) - ]), _evaluate_magnetic)) + list_ext_params.append((hoomd.md.external.field.Magnetic, "params", + list([ + dict(B=(0, 2, -11.5), mu=(1, 2, 3)), + dict(B=(1, 0, 1), mu=(1, 1, 1)) + ]), _evaluate_magnetic)) return list_ext_params @@ -152,7 +159,8 @@ def test_forces_and_energies(simulation_factory, lattice_snapshot_factory, torques = sim.operations.integrator.forces[0].torques energies = sim.operations.integrator.forces[0].energies if new_snap.communicator.rank == 0: - expected_forces, expected_torques, expected_energies = evaluator(new_snap, param) + expected_forces, expected_torques, expected_energies = evaluator( + new_snap, param) # Set atol as the energies and forces very close to 0. # It would be better to run a test that applies appreciable forces # and energies. From c03c6ac734efec8acf4728157b7983189b933f27 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 14 Nov 2023 12:14:02 -0500 Subject: [PATCH 11/25] add Tim's review comments --- hoomd/md/EvaluatorExternalMagneticField.h | 3 ++- hoomd/md/external/field.py | 15 ++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/hoomd/md/EvaluatorExternalMagneticField.h b/hoomd/md/EvaluatorExternalMagneticField.h index c67851ae22..e63dbd1211 100644 --- a/hoomd/md/EvaluatorExternalMagneticField.h +++ b/hoomd/md/EvaluatorExternalMagneticField.h @@ -81,7 +81,7 @@ class EvaluatorExternalMagneticField typedef void* field_type; - //! Constructs the constraint evaluator + //! Constructs the external field evaluator /*! \param X position of particle \param box box dimensions \param params per-type parameters of external potential @@ -121,6 +121,7 @@ class EvaluatorExternalMagneticField //! Evaluate the force, energy and virial /*! \param F force vector + \param T torque vector \param energy value of the energy \param virial array of six scalars for the upper triangular virial tensor */ diff --git a/hoomd/md/external/field.py b/hoomd/md/external/field.py index 6531d78d7b..7053f929cd 100644 --- a/hoomd/md/external/field.py +++ b/hoomd/md/external/field.py @@ -86,7 +86,7 @@ def __init__(self): class Electric(Field): """Electric field force. - `Electric` computes forces, and virials, and energies on all particles in + `Electric` computes forces, virials, and energies on all particles in the simulation state which are consistent with: .. math:: @@ -133,8 +133,8 @@ class Magnetic(Field): U_i = -\\vec{mu}_i \\cdot \\vec{B} - where :math:`\\vec{mu}_i` is the particle magnetic momentum and - :math:`\\vec{B}` is the field vector. The field vector :math:`\\vec{B}` + where :math:`\\vec{mu}_i` is the magnetic dipole moment of particle :math:`i` + and :math:`\\vec{B}` is the field vector. The field vector :math:`\\vec{B}` must be set per unique particle type. .. py:attribute:: params @@ -143,11 +143,12 @@ class Magnetic(Field): following keys: * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic - field vector :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot \ - \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. + field vector n the global reference frame :math:`[\\mathrm{energy} \\cdot \ + \\mathrm{time} \\cdot \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic - moment of the particles type :math:`[\\mathrm{charge} \\cdot \ - \\mathrm{length}^2 \\cdot \\mathrm{time}^{-1}]`. + dipole moment of the particles type in the particle reference frame + :math:`[\\mathrm{charge} \\cdot \\mathrm{length}^2 \\cdot \ + \\mathrm{time}^{-1}]`. Type: `TypeParameter` [``particle_type``, `dict`] From 0b8bb616fcdb528da8836df0c33a88c783647b77 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 14 Nov 2023 12:16:55 -0500 Subject: [PATCH 12/25] add Magnetic external field to sphinx --- sphinx-doc/module-md-external-field.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sphinx-doc/module-md-external-field.rst b/sphinx-doc/module-md-external-field.rst index ed27eeffbd..6d7ba6ff57 100644 --- a/sphinx-doc/module-md-external-field.rst +++ b/sphinx-doc/module-md-external-field.rst @@ -13,6 +13,7 @@ md.external.field Field Electric + Magnetic Periodic .. rubric:: Details @@ -21,4 +22,5 @@ md.external.field :synopsis: External field potentials. :members: Field, Electric, + Magnetic, Periodic From fde908ad0b488794b65b56a5543d56cc4ca3f208 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:20:11 +0000 Subject: [PATCH 13/25] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- hoomd/md/EvaluatorExternalMagneticField.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hoomd/md/EvaluatorExternalMagneticField.h b/hoomd/md/EvaluatorExternalMagneticField.h index e63dbd1211..042d9ed511 100644 --- a/hoomd/md/EvaluatorExternalMagneticField.h +++ b/hoomd/md/EvaluatorExternalMagneticField.h @@ -121,7 +121,7 @@ class EvaluatorExternalMagneticField //! Evaluate the force, energy and virial /*! \param F force vector - \param T torque vector + \param T torque vector \param energy value of the energy \param virial array of six scalars for the upper triangular virial tensor */ From 3012b15141fb45e380917da3c182140d3dd746e5 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 14 Nov 2023 12:24:36 -0500 Subject: [PATCH 14/25] fix precommit --- hoomd/md/external/field.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/hoomd/md/external/field.py b/hoomd/md/external/field.py index 7053f929cd..d9223cfee8 100644 --- a/hoomd/md/external/field.py +++ b/hoomd/md/external/field.py @@ -133,22 +133,23 @@ class Magnetic(Field): U_i = -\\vec{mu}_i \\cdot \\vec{B} - where :math:`\\vec{mu}_i` is the magnetic dipole moment of particle :math:`i` - and :math:`\\vec{B}` is the field vector. The field vector :math:`\\vec{B}` - must be set per unique particle type. + where :math:`\\vec{mu}_i` is the magnetic dipole moment of particle + :math:`i`and :math:`\\vec{B}` is the field vector. The field vector + :math:`\\vec{B}` must be set per unique particle type. .. py:attribute:: params The `Magnetic` external potential parameters. The dictionary has the following keys: - * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic - field vector n the global reference frame :math:`[\\mathrm{energy} \\cdot \ - \\mathrm{time} \\cdot \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. - * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic - dipole moment of the particles type in the particle reference frame - :math:`[\\mathrm{charge} \\cdot \\mathrm{length}^2 \\cdot \ - \\mathrm{time}^{-1}]`. + * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The + magnetic field vector n the global reference frame + :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot \ + \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. + * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The + magnetic dipole moment of the particles type in the particle + reference frame :math:`[\\mathrm{charge} \\cdot \\mathrm{length}^2 \ + \\cdot \\mathrm{time}^{-1}]`. Type: `TypeParameter` [``particle_type``, `dict`] From 3ca13cce2cdc11a095e6d5b7896da0ee531e3c93 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Tue, 14 Nov 2023 12:55:41 -0500 Subject: [PATCH 15/25] fix docs --- hoomd/md/external/field.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hoomd/md/external/field.py b/hoomd/md/external/field.py index d9223cfee8..652c6f14ef 100644 --- a/hoomd/md/external/field.py +++ b/hoomd/md/external/field.py @@ -144,7 +144,7 @@ class Magnetic(Field): * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic field vector n the global reference frame - :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot \ + :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot \ \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The magnetic dipole moment of the particles type in the particle From 0c524881bea5f2e115b6fc0c99de7b72edcad63d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 14 Nov 2023 18:24:40 +0000 Subject: [PATCH 16/25] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- hoomd/md/external/field.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hoomd/md/external/field.py b/hoomd/md/external/field.py index 652c6f14ef..87589c855b 100644 --- a/hoomd/md/external/field.py +++ b/hoomd/md/external/field.py @@ -133,8 +133,8 @@ class Magnetic(Field): U_i = -\\vec{mu}_i \\cdot \\vec{B} - where :math:`\\vec{mu}_i` is the magnetic dipole moment of particle - :math:`i`and :math:`\\vec{B}` is the field vector. The field vector + where :math:`\\vec{mu}_i` is the magnetic dipole moment of particle + :math:`i`and :math:`\\vec{B}` is the field vector. The field vector :math:`\\vec{B}` must be set per unique particle type. .. py:attribute:: params @@ -142,12 +142,12 @@ class Magnetic(Field): The `Magnetic` external potential parameters. The dictionary has the following keys: - * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The - magnetic field vector n the global reference frame + * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The + magnetic field vector n the global reference frame :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot \ \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. - * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The - magnetic dipole moment of the particles type in the particle + * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The + magnetic dipole moment of the particles type in the particle reference frame :math:`[\\mathrm{charge} \\cdot \\mathrm{length}^2 \ \\cdot \\mathrm{time}^{-1}]`. From e18c830fe8827b67138f3d0ef962e5cc5912c5af Mon Sep 17 00:00:00 2001 From: "Joshua A. Anderson" Date: Thu, 16 Nov 2023 11:01:16 -0500 Subject: [PATCH 17/25] Trigger CI. From 4409a949edd578cdbf10bcddd3843fd8cf4f5048 Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Thu, 16 Nov 2023 12:15:28 -0500 Subject: [PATCH 18/25] fix typo --- hoomd/md/external/field.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/hoomd/md/external/field.py b/hoomd/md/external/field.py index 652c6f14ef..dff42c7a99 100644 --- a/hoomd/md/external/field.py +++ b/hoomd/md/external/field.py @@ -132,7 +132,6 @@ class Magnetic(Field): U_i = -\\vec{mu}_i \\cdot \\vec{B} - where :math:`\\vec{mu}_i` is the magnetic dipole moment of particle :math:`i`and :math:`\\vec{B}` is the field vector. The field vector :math:`\\vec{B}` must be set per unique particle type. @@ -143,13 +142,13 @@ class Magnetic(Field): following keys: * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The - magnetic field vector n the global reference frame - :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot \ - \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. + magnetic field vector in the global reference frame + :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot \ + \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The - magnetic dipole moment of the particles type in the particle - reference frame :math:`[\\mathrm{charge} \\cdot \\mathrm{length}^2 \ - \\cdot \\mathrm{time}^{-1}]`. + magnetic dipole moment of the particles type in the particle + reference frame :math:`[\\mathrm{charge} \\cdot \\mathrm{length}^2 \ + \\cdot \\mathrm{time}^{-1}]`. Type: `TypeParameter` [``particle_type``, `dict`] From 30b1c97fdc599e8f3e37289eb25056f91b95a7dc Mon Sep 17 00:00:00 2001 From: SchoeniPhlippsn Date: Thu, 16 Nov 2023 12:29:03 -0500 Subject: [PATCH 19/25] execute pre-commit --- hoomd/md/external/field.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hoomd/md/external/field.py b/hoomd/md/external/field.py index 8cdfb7416b..7e4e1d1e8a 100644 --- a/hoomd/md/external/field.py +++ b/hoomd/md/external/field.py @@ -142,12 +142,12 @@ class Magnetic(Field): The `Magnetic` external potential parameters. The dictionary has the following keys: - * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The - magnetic field vector in the global reference frame + * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The + magnetic field vector in the global reference frame :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot \ \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. - * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The - magnetic dipole moment of the particles type in the particle + * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The + magnetic dipole moment of the particles type in the particle reference frame :math:`[\\mathrm{charge} \\cdot \\mathrm{length}^2 \ \\cdot \\mathrm{time}^{-1}]`. From 21270079a05105da632b6c6ab8564a96c8aa99f9 Mon Sep 17 00:00:00 2001 From: "Joshua A. Anderson" Date: Thu, 16 Nov 2023 13:32:04 -0500 Subject: [PATCH 20/25] Document torque in evaluators. --- hoomd/md/EvaluatorExternalElectricField.h | 3 ++- hoomd/md/EvaluatorExternalMagneticField.h | 2 +- hoomd/md/EvaluatorExternalPeriodic.h | 3 ++- hoomd/md/EvaluatorWalls.h | 2 +- hoomd/md/PotentialExternal.h | 2 +- hoomd/md/PotentialExternalGPU.cuh | 2 +- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/hoomd/md/EvaluatorExternalElectricField.h b/hoomd/md/EvaluatorExternalElectricField.h index e3a2cc850f..8c9d12a4c4 100644 --- a/hoomd/md/EvaluatorExternalElectricField.h +++ b/hoomd/md/EvaluatorExternalElectricField.h @@ -113,10 +113,11 @@ class EvaluatorExternalElectricField //! Evaluate the force, energy and virial /*! \param F force vector + \param T torque vector \param energy value of the energy \param virial array of six scalars for the upper triangular virial tensor */ - DEVICE void evalForceEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) + DEVICE void evalForceTorqueEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) { F = m_qi * m_E; energy = -m_qi * dot(m_E, m_pos); diff --git a/hoomd/md/EvaluatorExternalMagneticField.h b/hoomd/md/EvaluatorExternalMagneticField.h index 042d9ed511..9254d0cfc4 100644 --- a/hoomd/md/EvaluatorExternalMagneticField.h +++ b/hoomd/md/EvaluatorExternalMagneticField.h @@ -125,7 +125,7 @@ class EvaluatorExternalMagneticField \param energy value of the energy \param virial array of six scalars for the upper triangular virial tensor */ - DEVICE void evalForceEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) + DEVICE void evalForceTorqueEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) { vec3 dir = rotate(m_q, m_mu); diff --git a/hoomd/md/EvaluatorExternalPeriodic.h b/hoomd/md/EvaluatorExternalPeriodic.h index 8028717ead..0b6cd55f32 100644 --- a/hoomd/md/EvaluatorExternalPeriodic.h +++ b/hoomd/md/EvaluatorExternalPeriodic.h @@ -124,10 +124,11 @@ class EvaluatorExternalPeriodic //! Evaluate the force, energy and virial /*! \param F force vector + \param T torque vector \param energy value of the energy \param virial array of six scalars for the upper triangular virial tensor */ - DEVICE void evalForceEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) + DEVICE void evalForceTorqueEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) { Scalar3 a2 = make_scalar3(0, 0, 0); Scalar3 a3 = make_scalar3(0, 0, 0); diff --git a/hoomd/md/EvaluatorWalls.h b/hoomd/md/EvaluatorWalls.h index b4f924e0a6..87741271cc 100644 --- a/hoomd/md/EvaluatorWalls.h +++ b/hoomd/md/EvaluatorWalls.h @@ -238,7 +238,7 @@ template class EvaluatorWalls } //! Generates force and energy from standard evaluators using wall geometry functions - DEVICE void evalForceEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) + DEVICE void evalForceTorqueEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) { F.x = Scalar(0.0); F.y = Scalar(0.0); diff --git a/hoomd/md/PotentialExternal.h b/hoomd/md/PotentialExternal.h index 0c585fb414..aac631a0a3 100644 --- a/hoomd/md/PotentialExternal.h +++ b/hoomd/md/PotentialExternal.h @@ -146,7 +146,7 @@ template void PotentialExternal::computeForces(uint6 Scalar qi = h_charge.data[idx]; eval.setCharge(qi); } - eval.evalForceEnergyAndVirial(F, T, energy, virial); + eval.evalForceTorqueEnergyAndVirial(F, T, energy, virial); // apply the constraint force h_force.data[idx].x = F.x; diff --git a/hoomd/md/PotentialExternalGPU.cuh b/hoomd/md/PotentialExternalGPU.cuh index 89f9749b94..c33495c534 100644 --- a/hoomd/md/PotentialExternalGPU.cuh +++ b/hoomd/md/PotentialExternalGPU.cuh @@ -149,7 +149,7 @@ __global__ void gpu_compute_external_forces_kernel(Scalar4* d_force, if (evaluator::needsCharge()) eval.setCharge(qi); - eval.evalForceEnergyAndVirial(force, torque, energy, virial); + eval.evalForceTorqueEnergyAndVirial(force, torque, energy, virial); // now that the force calculation is complete, write out the result) d_force[idx].x = force.x; From 2df0ec6a269563fa80bff5afde17efa48f5e5f1a Mon Sep 17 00:00:00 2001 From: "Joshua A. Anderson" Date: Thu, 16 Nov 2023 13:44:43 -0500 Subject: [PATCH 21/25] Revise documentation formatting. Also test documentation code snippets. --- hoomd/md/external/field.py | 63 ++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/hoomd/md/external/field.py b/hoomd/md/external/field.py index 7e4e1d1e8a..b053588444 100644 --- a/hoomd/md/external/field.py +++ b/hoomd/md/external/field.py @@ -1,7 +1,13 @@ # Copyright (c) 2009-2023 The Regents of the University of Michigan. # Part of HOOMD-blue, released under the BSD 3-Clause License. -"""External field forces.""" +"""External field forces. + +.. invisible-code-block: python + + simulation = hoomd.util.make_example_simulation() + simulation.operations.integrator = hoomd.md.Integrator(dt=0.001) +""" import hoomd from hoomd.md import _md @@ -67,12 +73,14 @@ class Periodic(Field): Type: `TypeParameter` [``particle_type``, `dict`] - Example:: + .. rubric:: Example: + + .. code-block:: python - # Apply a periodic composition modulation along the first lattice vector - periodic = external.field.Periodic() + periodic = hoomd.md.external.field.Periodic() periodic.params['A'] = dict(A=1.0, i=0, w=0.02, p=3) periodic.params['B'] = dict(A=-1.0, i=0, w=0.02, p=3) + simulation.operations.integrator.forces = [periodic] """ _cpp_class_name = "PotentialExternalPeriodic" @@ -107,11 +115,13 @@ class Electric(Field): Type: `TypeParameter` [``particle_type``, `tuple` [`float`, `float`, `float`]] - Example:: + .. rubric:: Example: - # Apply an electric field in the x-direction - e_field = external.field.Electric() - e_field.E['A'] = (1, 0, 0) + .. code-block:: python + + electric = hoomd.md.external.field.Electric() + electric.E['A'] = (1, 0, 0) + simulation.operations.integrator.forces = [electric] """ _cpp_class_name = "PotentialExternalElectricField" @@ -125,39 +135,40 @@ def __init__(self): class Magnetic(Field): """Magnetic field torque on a magnetic dipole. - `Magnetic` computes torces and energies on all particles in - the simulation state which are consistent with: + `Magnetic` computes torques and energies on all particles in the simulation + state which are consistent with: .. math:: - U_i = -\\vec{mu}_i \\cdot \\vec{B} + U_i = -\\vec{\\mu}_i \\cdot \\vec{B} - where :math:`\\vec{mu}_i` is the magnetic dipole moment of particle - :math:`i`and :math:`\\vec{B}` is the field vector. The field vector - :math:`\\vec{B}` must be set per unique particle type. + where :math:`\\vec{\\mu}_i` is the magnetic dipole moment of particle + :math:`i` and :math:`\\vec{B}` is the field vector. .. py:attribute:: params The `Magnetic` external potential parameters. The dictionary has the following keys: - * ``B`` (`tuple` [`float`, `float`, `float`] ,**required**) - The - magnetic field vector in the global reference frame - :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot \ - \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. - * ``mu`` (`tuple` [`float`, `float`, `float`] ,**required**) - The - magnetic dipole moment of the particles type in the particle - reference frame :math:`[\\mathrm{charge} \\cdot \\mathrm{length}^2 \ - \\cdot \\mathrm{time}^{-1}]`. + * ``B`` (`tuple` [`float`, `float`, `float`], **required**) - The + magnetic field vector in the global reference frame + :math:`[\\mathrm{energy} \\cdot \\mathrm{time} \\cdot + \\mathrm{charge}^{-1} \\cdot \\mathrm{length}^{-2} ]`. + * ``mu`` (`tuple` [`float`, `float`, `float`], **required**) - The + magnetic dipole moment of the particles type in the particle + reference frame :math:`[\\mathrm{charge} \\cdot \\mathrm{length}^2 + \\cdot \\mathrm{time}^{-1}]`. Type: `TypeParameter` [``particle_type``, `dict`] - Example:: + .. rubric:: Example: + + .. code-block:: python - # Apply an magnetic field in the x-direction - m_field = external.field.Magnetic() - m_field.params['A'] = dict(B=(1.0,0.0,0.0), mu=(1.0,0.0,0.0)) + magnetic = hoomd.md.external.field.Magnetic() + magnetic.params['A'] = dict(B=(1.0,0.0,0.0), mu=(1.0,0.0,0.0)) + simulation.operations.integrator.forces = [magnetic] """ _cpp_class_name = "PotentialExternalMagneticField" From d2edb9f2c6230c96785e168472c9e6ceed6fd81e Mon Sep 17 00:00:00 2001 From: "Joshua A. Anderson" Date: Thu, 16 Nov 2023 13:46:41 -0500 Subject: [PATCH 22/25] Correctly describe the member variables in comments. --- hoomd/md/EvaluatorExternalMagneticField.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hoomd/md/EvaluatorExternalMagneticField.h b/hoomd/md/EvaluatorExternalMagneticField.h index 9254d0cfc4..d9521afa00 100644 --- a/hoomd/md/EvaluatorExternalMagneticField.h +++ b/hoomd/md/EvaluatorExternalMagneticField.h @@ -156,9 +156,9 @@ class EvaluatorExternalMagneticField #endif protected: - quat m_q; //!< particle position - vec3 m_B; //!< the field vector - vec3 m_mu; //!< particle charge + quat m_q; //!< Particle orientation + vec3 m_B; //!< Magnetic field vector (box frame). + vec3 m_mu; //!< Magnetic dipole moment (particle frame). }; } // end namespace md From 6f8052fe95024fda02ef92bed9e9545e6eacfb04 Mon Sep 17 00:00:00 2001 From: "Joshua A. Anderson" Date: Thu, 16 Nov 2023 13:48:05 -0500 Subject: [PATCH 23/25] Remove extra semicolons. --- hoomd/md/EvaluatorExternalMagneticField.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/hoomd/md/EvaluatorExternalMagneticField.h b/hoomd/md/EvaluatorExternalMagneticField.h index d9521afa00..88290dc911 100644 --- a/hoomd/md/EvaluatorExternalMagneticField.h +++ b/hoomd/md/EvaluatorExternalMagneticField.h @@ -71,9 +71,7 @@ class EvaluatorExternalMagneticField { pybind11::dict d; d["B"] = pybind11::make_tuple(B.x, B.y, B.z); - ; d["mu"] = pybind11::make_tuple(mu.x, mu.y, mu.z); - ; return d; } #endif // ifndef __HIPCC__ From 8ec87ec1d055854409988246ff7d3b2086f79226 Mon Sep 17 00:00:00 2001 From: "Joshua A. Anderson" Date: Thu, 16 Nov 2023 13:49:21 -0500 Subject: [PATCH 24/25] Remove unused code. --- hoomd/md/EvaluatorExternalMagneticField.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/hoomd/md/EvaluatorExternalMagneticField.h b/hoomd/md/EvaluatorExternalMagneticField.h index 88290dc911..cb1a244b47 100644 --- a/hoomd/md/EvaluatorExternalMagneticField.h +++ b/hoomd/md/EvaluatorExternalMagneticField.h @@ -65,8 +65,6 @@ class EvaluatorExternalMagneticField mu.z = pybind11::cast(py_mu[2]); } - param_type(Scalar3 B_, Scalar3 mu_) : B(B_), mu(mu_) { } - pybind11::dict toPython() { pybind11::dict d; From 0cb657c21c0a767a2563f98d656e1dc63a76e131 Mon Sep 17 00:00:00 2001 From: "Joshua A. Anderson" Date: Thu, 16 Nov 2023 13:53:12 -0500 Subject: [PATCH 25/25] Run pre-commit. --- hoomd/md/EvaluatorExternalElectricField.h | 3 ++- hoomd/md/EvaluatorExternalMagneticField.h | 3 ++- hoomd/md/EvaluatorExternalPeriodic.h | 3 ++- hoomd/md/EvaluatorWalls.h | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/hoomd/md/EvaluatorExternalElectricField.h b/hoomd/md/EvaluatorExternalElectricField.h index 8c9d12a4c4..c04688874c 100644 --- a/hoomd/md/EvaluatorExternalElectricField.h +++ b/hoomd/md/EvaluatorExternalElectricField.h @@ -117,7 +117,8 @@ class EvaluatorExternalElectricField \param energy value of the energy \param virial array of six scalars for the upper triangular virial tensor */ - DEVICE void evalForceTorqueEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) + DEVICE void + evalForceTorqueEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) { F = m_qi * m_E; energy = -m_qi * dot(m_E, m_pos); diff --git a/hoomd/md/EvaluatorExternalMagneticField.h b/hoomd/md/EvaluatorExternalMagneticField.h index cb1a244b47..d3fb39e211 100644 --- a/hoomd/md/EvaluatorExternalMagneticField.h +++ b/hoomd/md/EvaluatorExternalMagneticField.h @@ -121,7 +121,8 @@ class EvaluatorExternalMagneticField \param energy value of the energy \param virial array of six scalars for the upper triangular virial tensor */ - DEVICE void evalForceTorqueEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) + DEVICE void + evalForceTorqueEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) { vec3 dir = rotate(m_q, m_mu); diff --git a/hoomd/md/EvaluatorExternalPeriodic.h b/hoomd/md/EvaluatorExternalPeriodic.h index 0b6cd55f32..ddc4b24bc6 100644 --- a/hoomd/md/EvaluatorExternalPeriodic.h +++ b/hoomd/md/EvaluatorExternalPeriodic.h @@ -128,7 +128,8 @@ class EvaluatorExternalPeriodic \param energy value of the energy \param virial array of six scalars for the upper triangular virial tensor */ - DEVICE void evalForceTorqueEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) + DEVICE void + evalForceTorqueEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) { Scalar3 a2 = make_scalar3(0, 0, 0); Scalar3 a3 = make_scalar3(0, 0, 0); diff --git a/hoomd/md/EvaluatorWalls.h b/hoomd/md/EvaluatorWalls.h index 87741271cc..4535c54e92 100644 --- a/hoomd/md/EvaluatorWalls.h +++ b/hoomd/md/EvaluatorWalls.h @@ -238,7 +238,8 @@ template class EvaluatorWalls } //! Generates force and energy from standard evaluators using wall geometry functions - DEVICE void evalForceTorqueEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) + DEVICE void + evalForceTorqueEnergyAndVirial(Scalar3& F, Scalar3& T, Scalar& energy, Scalar* virial) { F.x = Scalar(0.0); F.y = Scalar(0.0);