1 /* This file is part of StepCore library.
2    Copyright (C) 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com>
3 
4    StepCore library is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8 
9    StepCore library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with StepCore; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18 
19 /** \file particle.h
20  *  \brief Particle and ChargedParticle classes
21  */
22 
23 #ifndef STEPCORE_PARTICLE_H
24 #define STEPCORE_PARTICLE_H
25 
26 #include "world.h"
27 #include "vector.h"
28 #include "object.h"
29 
30 namespace StepCore {
31 
32 class Particle;
33 class ChargedParticle;
34 
35 /** \ingroup errors
36  *  \brief Errors object for Particle
37  */
38 class ParticleErrors: public ObjectErrors
39 {
STEPCORE_OBJECT(ParticleErrors)40     STEPCORE_OBJECT(ParticleErrors)
41 
42 public:
43     /** Constructs ParticleErrors */
44     explicit ParticleErrors(Item* owner = 0)
45         : ObjectErrors(owner), _positionVariance(0,0), _velocityVariance(0,0),
46           _forceVariance(0,0), _massVariance(0) {}
47 
48     /** Get owner as Particle */
49     Particle* particle() const;
50 
51     /** Get position variance */
positionVariance()52     const Vector2d& positionVariance() const { return _positionVariance; }
53     /** Set position variance */
setPositionVariance(const Vector2d & positionVariance)54     void setPositionVariance(const Vector2d& positionVariance) {
55         _positionVariance = positionVariance; }
56 
57     /** Get velocity variance */
velocityVariance()58     const Vector2d& velocityVariance() const { return _velocityVariance; }
59     /** Set velocity variance */
setVelocityVariance(const Vector2d & velocityVariance)60     void setVelocityVariance(const Vector2d& velocityVariance) {
61         _velocityVariance = velocityVariance; }
62 
63     /** Get acceleration variance */
64     Vector2d accelerationVariance() const;
65 
66     /** Get force variance */
forceVariance()67     const Vector2d& forceVariance() const { return _forceVariance; }
68     /** Set force variance */
setForceVariance(const Vector2d & forceVariance)69     void setForceVariance(const Vector2d& forceVariance) {
70         _forceVariance = forceVariance; }
71 
72     /** Increment force variance */
applyForceVariance(const Vector2d & forceVariance)73     void applyForceVariance(const Vector2d& forceVariance) {
74         _forceVariance += forceVariance; }
75 
76     /** Get mass variance */
massVariance()77     double massVariance() const { return _massVariance; }
78     /** Set mass variance */
setMassVariance(double massVariance)79     void   setMassVariance(double massVariance) {
80         _massVariance = massVariance; }
81 
82     /** Get momentum variance */
83     Vector2d momentumVariance() const;
84     /** Set momentum variance (will modify velocity variance) */
85     void setMomentumVariance(const Vector2d& momentumVariance);
86 
87     /** Get kinetic energy variance */
88     double kineticEnergyVariance() const;
89     /** Set kinetic energy variance (will modify velocity variance) */
90     void setKineticEnergyVariance(double kineticEnergyVariance);
91 
92 protected:
93     Vector2d _positionVariance;
94     Vector2d _velocityVariance;
95     Vector2d _forceVariance;
96     double _massVariance;
97     friend class Particle;
98 };
99 
100 /** \ingroup bodies
101  *  \brief Particle with mass
102  */
103 class Particle: public Body
104 {
105     STEPCORE_OBJECT(Particle)
106 
107 public:
108     enum {
109         PositionOffset = 0 ///< Offset of particle position in variables array
110     };
111 
112     /** Constructs a particle */
113     explicit Particle(const Vector2d &position = Vector2d::Zero(),
114             const Vector2d &velocity = Vector2d::Zero(), double mass = 1);
115 
116     /** Get position of the particle */
position()117     const Vector2d& position() const { return _position; }
118     /** Set position of the particle */
setPosition(const Vector2d & position)119     void setPosition(const Vector2d& position) { _position = position; }
120 
121     /** Get velocity of the particle */
velocity()122     const Vector2d& velocity() const { return _velocity; }
123     /** Set velocity of the particle */
setVelocity(const Vector2d & velocity)124     void setVelocity(const Vector2d& velocity) { _velocity = velocity; }
125 
126     /** Get acceleration of the particle */
acceleration()127     Vector2d acceleration() const { return _force/_mass; }
128 
129     /** Get force that acts upon particle */
force()130     const Vector2d& force() const { return _force; }
131     /** Set force that acts upon particle */
setForce(const Vector2d & force)132     void setForce(const Vector2d& force) { _force = force; }
133 
134     /** Apply force to the body */
applyForce(const Vector2d & force)135     void applyForce(const Vector2d& force) { _force += force; }
136 
137     /** Get mass of the particle */
mass()138     double mass() const { return _mass; }
139     /** Set mass of the particle */
setMass(double mass)140     void   setMass(double mass) { _mass = mass; }
141 
142     /** Get momentum of the particle */
momentum()143     Vector2d momentum() const { return _velocity * _mass; }
144     /** Set momentum of the particle (will modify only velocity) */
setMomentum(const Vector2d & momentum)145     void setMomentum(const Vector2d& momentum) { _velocity = momentum / _mass; }
146 
147     /** Get kinetic energy of the particle */
kineticEnergy()148     double kineticEnergy() const { return _mass * _velocity.squaredNorm()/2; }
149     /** Set kinetic energy of the particle (will modify only velocity) */
150     void setKineticEnergy(double kineticEnergy);
151 
variablesCount()152     int  variablesCount() override { return 2; }
153     void getVariables(double* position, double* velocity,
154                           double* positionVariance, double* velocityVariance) override;
155     void setVariables(const double* position, const double* velocity,
156               const double* positionVariance, const double* velocityVariance) override;
157     void addForce(const double* force, const double* forceVariance) override;
158     void resetForce(bool resetVariance) override;
159     void getAccelerations(double* acceleration, double* accelerationVariance) override;
160     void getInverseMass(VectorXd* inverseMass,
161                         DynSparseRowMatrix* variance, int offset) override;
162 
163     /** Get (and possibly create) ParticleErrors object */
particleErrors()164     ParticleErrors* particleErrors() {
165         return static_cast<ParticleErrors*>(objectErrors()); }
166 
167 protected:
createObjectErrors()168     ObjectErrors* createObjectErrors() override { return new ParticleErrors(this); }
169 
170     Vector2d _position;
171     Vector2d _velocity;
172     Vector2d _force;
173     double _mass;
174 };
175 
176 /** \ingroup errors
177  *  \brief Errors object for ChargedParticle
178  */
179 class ChargedParticleErrors: public ParticleErrors
180 {
STEPCORE_OBJECT(ChargedParticleErrors)181     STEPCORE_OBJECT(ChargedParticleErrors)
182 
183 public:
184     /** Constructs ChargedParticleErrors */
185     explicit ChargedParticleErrors(Item* owner = 0)
186         : ParticleErrors(owner), _chargeVariance(0) {}
187 
188     /** Get owner as ChargedParticle */
189     ChargedParticle* chargedParticle() const;
190 
191     /** Get charge variance */
chargeVariance()192     double chargeVariance() const { return _chargeVariance; }
193     /** Set charge variance */
setChargeVariance(double chargeVariance)194     void   setChargeVariance(double chargeVariance) {
195         _chargeVariance = chargeVariance; }
196 
197 protected:
198     double _chargeVariance;
199     friend class ChargedParticle;
200 };
201 
202 
203 /** \ingroup bodies
204  *  \brief ChargedParticle with mass and charge
205  */
206 class ChargedParticle: public Particle
207 {
STEPCORE_OBJECT(ChargedParticle)208     STEPCORE_OBJECT(ChargedParticle)
209 
210 public:
211     /** Constructs a charged particle */
212     explicit ChargedParticle(const Vector2d &position = Vector2d::Zero(),
213             const Vector2d &velocity = Vector2d::Zero(), double mass = 1, double charge = 0)
214                 : Particle(position, velocity, mass), _charge(charge) {}
215 
216     /** Charge of the particle */
charge()217     double charge() const { return _charge; }
218     /** Charge of the particle */
setCharge(double charge)219     void setCharge(double charge) { _charge = charge; }
220 
221     /** Get (and possibly create) ChargedParticleErrors object */
chargedParticleErrors()222     ChargedParticleErrors* chargedParticleErrors() {
223         return static_cast<ChargedParticleErrors*>(objectErrors()); }
224 
225 protected:
createObjectErrors()226     ObjectErrors* createObjectErrors() override { return new ChargedParticleErrors(this); }
227 
228     double _charge;
229 };
230 
231 } // namespace StepCore
232 
233 #endif
234 
235