1#ifndef PHYTH_MAGNETIC_DIPOLE_HPP
2#define PHYTH_MAGNETIC_DIPOLE_HPP
103 const auto dist =
r.Length();
106 throw std::runtime_error(
"MagneticDipole: field diverges at dipole location");
123 const auto R_mag =
R.Length();
125 throw std::runtime_error(
"MagneticDipole: field diverges at dipole location");
136 }
catch (
const std::runtime_error &) {
161 const auto dist =
r.Length();
164 throw std::runtime_error(
"MagneticDipole: field diverges at dipole location");
170 const auto hat_r =
r.Normalized();
183 const auto R_mag =
R.Length();
185 throw std::runtime_error(
"MagneticDipole: field diverges at dipole location");
196 }
catch (
const std::runtime_error &) {
198 const auto hat_r =
r.Normalized();
221 throw std::runtime_error(
"MagneticDipole: potential diverges at dipole location");
236 const auto R =
R_vec.Length();
243 throw std::runtime_error(
"MagneticDipole: line-of-sight aligns with velocity at light speed");
247 }
catch (
const std::runtime_error &) {
371 Particle::Integrate();
632 if (size < 2)
return {};
639 if (
idx >= size - 1) {
657 if (size < 3)
return {};
665 if (
idx >= size - 1) {
685 if (size < 2)
return {};
692 if (
idx >= size - 1) {
710 if (size < 3)
return {};
718 if (
idx >= size - 1) {
738 if (size < 2)
return {};
745 if (
idx >= size - 1) {
Abstract base class for all charge distributions.
Magnetic dipole with full electromagnetic field and dynamics.
Vector3< Quantity< Newton > > ComputeMagneticGradientForce(const MagneticSource &field_source) const
Compute magnetic gradient force using finite differences.
void ApplyElectricGradientForce(const ChargeSource &field_source)
Apply force from electric field gradient.
const Vector3< Quantity< RadianPerSecond > > & GetAngularVelocity() const
Vector3< decltype(1_Cm/1_s/1_s)> ComputeElectricDipoleSecondDerivative(const Quantity< Second > &retarded_dt) const
Compute second time derivative of electric dipole moment at retarded time.
TimeHistory< Vector3< Quantity< Meter > > > position_history_
TimeHistory< Vector3< Quantity< MeterPerSecondSquared > > > acceleration_history_
void ApplyElectricTorque(const ChargeSource &field_source)
Apply torque from electric field.
Quantity< Second > SolveRetardedTimeOffsetBisection(const Vector3< Quantity< Meter > > &point, Quantity< Second > dt_low, Quantity< Second > dt_high) const
Solve for the retarded time offset using bisection method.
Vector3< decltype(1_mps2/1_s)> ComputeAccelerationFirstDerivative(const Quantity< Second > &retarded_dt) const
Compute first time derivative of acceleration at retarded time.
Vector3< Quantity< MeterPerSecondSquared > > GetAccelerationAtOffset(const Quantity< Second > &offset) const
Get acceleration at a time offset in the past.
void SetMoment(const Vector3< Quantity< AmpereMeterSquared > > &m)
Set the magnetic dipole moment.
Vector3< Quantity< CoulombMeter > > GetElectricDipoleAtOffset(const Quantity< Second > &offset) const
Get electric dipole moment at a time offset in the past.
void ApplyMagneticTorque(const MagneticSource &field_source)
Apply torque from magnetic field.
static Vector3< Quantity< CoulombMeter > > ComputeRelativisticDipoleMoment(const Vector3< Quantity< MeterPerSecond > > &v, const Vector3< Quantity< AmpereMeterSquared > > &m)
Compute the relativistic electric dipole moment.
Vector3< decltype(0_Am2/1_s/1_s)> ComputeMomentSecondDerivative(const Quantity< Second > &retarded_dt) const
Compute second time derivative of magnetic moment at retarded time.
Vector3< Quantity< RadianPerSecond > > angular_velocity_
Vector3< Quantity< NewtonPerCoulomb > > GetElectricFieldAt(const Vector3< Quantity< Meter > > &point) const override
Get the electric field at a point.
Quantity< Meter > GetMinimumDistanceTo(const Vector3< Quantity< Meter > > &point) const override
Get the minimum distance from a point to the dipole location.
void ApplyElectromagneticForce(const MagneticSource &magnetic_source, const ChargeSource &electric_source)
Apply both magnetic and electric forces.
void ApplyTorque(const Vector3< Quantity< NewtonMeter > > &torque)
Apply a torque to the dipole.
void ApplyMagneticGradientForce(const MagneticSource &field_source)
Apply force from magnetic field gradient.
void SetMomentOfInertia(const Quantity< KilogramMeterSquared > &I)
Set the moment of inertia.
Quantity< KilogramMeterSquared > moment_of_inertia_
Vector3< Quantity< AmpereMeterSquared > > moment_
Quantity< Volt > GetElectricPotentialAt(const Vector3< Quantity< Meter > > &point) const override
Get the electric potential at a point.
Quaternion< Scalar > orientation_
Vector3< Quantity< AmpereMeterSquared > > initial_moment_
TimeHistory< Vector3< Quantity< CoulombMeter > > > electric_dipole_history_
Vector3< Quantity< CoulombMeter > > GetElectricDipoleMoment() const
TimeHistory< Vector3< Quantity< MeterPerSecond > > > velocity_history_
Vector3< Quantity< Tesla > > GetMagneticFieldAt(const Vector3< Quantity< Meter > > &point) const override
Get the magnetic field at a point.
Quantity< Coulomb > GetTotalChargeValue() const override
Get the total charge of the dipole.
MagneticDipole(const Quantity< Kilogram > mass, const Vector3< Quantity< Meter > > &position, const Vector3< Quantity< AmpereMeterSquared > > &moment, const Quantity< KilogramMeterSquared > &moment_of_inertia=0_kgm2)
Construct a magnetic dipole.
Vector3< decltype(0_Am2/1_s)> ComputeMomentFirstDerivative(const Quantity< Second > &retarded_dt) const
Compute first time derivative of magnetic moment at retarded time.
void ApplyMagneticForce(const MagneticSource &field_source)
Apply all magnetic forces (gradient + torque)
const Vector3< Quantity< AmpereMeterSquared > > & GetMoment() const
Quantity< Second > SolveRetardedTimeOffset(const Vector3< Quantity< Meter > > &point) const
Solve for the retarded time offset using Newton's method.
Vector3< Quantity< NewtonMeter > > external_torque_
Vector3< decltype(1_Cm/1_s)> ComputeElectricDipoleFirstDerivative(const Quantity< Second > &retarded_dt) const
Compute first time derivative of electric dipole moment at retarded time.
Vector3< Quantity< MeterPerSecond > > GetVelocityAtOffset(const Quantity< Second > &offset) const
Get velocity at a time offset in the past.
Vector3< Quantity< AmpereMeterSquared > > GetMomentAtOffset(const Quantity< Second > &offset) const
Get magnetic moment at a time offset in the past.
TimeHistory< Vector3< Quantity< AmpereMeterSquared > > > moment_history_
Vector3< Quantity< Newton > > ComputeElectricGradientForce(const ChargeSource &field_source) const
Compute electric gradient force using finite differences.
void Integrate() noexcept override
Integrate dynamics using velocity Verlet.
Quantity< KilogramMeterSquared > GetMomentOfInertia() const
void SetComputeForcesFunction(const std::function< void(MagneticDipole *)> &func) noexcept
Set the force computation function.
Vector3< Quantity< Meter > > GetPositionAtOffset(const Quantity< Second > &offset) const
Get position at a time offset in the past.
Vector3< Quantity< CoulombMeter > > GetRelativisticDipoleMomentCurrent() const
void SetOrientation(const Quaternion< Scalar > &q)
Set the orientation quaternion.
void SetAngularVelocity(const Vector3< Quantity< RadianPerSecond > > &omega)
Set the angular velocity.
void ApplyElectricForce(const ChargeSource &field_source)
Apply all electric forces (gradient + torque)
const Quaternion< Scalar > & GetOrientation() const
Abstract base class for all magnetic field sources.
Physical particle with mass, position, velocity, and force accumulation.
Quantity< Kilogram > mass_
Vector3< Quantity< MeterPerSecond > > velocity_
Vector3< Quantity< Meter > > position_
Vector3< Quantity< Newton > > external_force_
Particle(const Quantity< Kilogram > &mass, const Vector3< Quantity< Meter > > &position) noexcept
Construct a particle with mass and initial position.
void ApplyForce(const Vector3< Quantity< Newton > > &force)
Accumulate an external force on the particle.
Time-based history with linear interpolation.
auto sqrt(Quantity< UnitT > q)
Square root of a quantity.
auto cube(Quantity< UnitT > q)
Cube of a quantity.
auto abs(Quantity< UnitT > q)
Absolute value of a quantity.
Quantity< ScalarUnit > Scalar
Dimension< std::ratio< 1 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 >, std::ratio< 0 > > Length
Physical quantity with a value and a compile-time unit.
Quaternion with Quantity components.
static Quaternion FromAxisAngle(const Vector3< T > &axis, const Scalar theta)
Create a unit quaternion from axis and angle.
3D vector with Quantity components
Vector3< Scalar > Normalized() const
Normalized vector (unit vector in the same direction)