File indexing completed on 2024-04-21 07:38:02

0001 /*
0002     SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 /** \file gas.h
0008  *  \brief Gas-related classes
0009  */
0010 
0011 #ifndef STEPCORE_GAS_H
0012 #define STEPCORE_GAS_H
0013 
0014 #include "particle.h"
0015 #include "world.h"
0016 #include <cmath>
0017 
0018 namespace StepCore {
0019 
0020 class GasParticle;
0021 class GasLJForce;
0022 class Gas;
0023 
0024 /** \ingroup bodies
0025  *  \brief Gas particle
0026  */
0027 class GasParticle: public Particle
0028 {
0029     STEPCORE_OBJECT(GasParticle)
0030 
0031 public:
0032     /** Constructs a GasParticle */
0033     explicit GasParticle(const Vector2d &position = Vector2d::Zero(), const Vector2d &velocity = Vector2d::Zero(), double mass = 1)
0034         : Particle(position, velocity, mass) {}
0035 };
0036 
0037 /** \ingroup errors
0038  *  \brief Errors object for GasLJForce
0039  */
0040 class GasLJForceErrors: public ObjectErrors
0041 {
0042     STEPCORE_OBJECT(GasLJForceErrors)
0043 
0044 public:
0045     /** Constructs GasLJForceErrors */
0046     explicit GasLJForceErrors(Item* owner = nullptr)
0047         : ObjectErrors(owner), _depthVariance(0), _rminVariance(0) {}
0048 
0049     /** Get owner as GasLJForce */
0050     GasLJForce* gasLJForce() const;
0051 
0052     /** Get depth variance */
0053     double depthVariance() const { return _depthVariance; }
0054     /** Set depth variance */
0055     void setDepthVariance(double depthVariance) { _depthVariance = depthVariance; }
0056 
0057     /** Get rmin variance */
0058     double rminVariance() const { return _rminVariance; }
0059     /** Set rmin variance */
0060     void setRminVariance(double rminVariance) { _rminVariance = rminVariance; }
0061 
0062 protected:
0063     double _depthVariance;
0064     double _rminVariance;
0065     friend class GasLJForce;
0066 };
0067 
0068 /** \ingroup forces
0069  *  \brief Lennard-Jones force with cut-off which acts between particles in the Gas
0070  *
0071  *  The force acts between pairs of GasParticle and equals:
0072  *  \f{eqnarray*}
0073  *      \overrightarrow{f} = & 12 \epsilon \left(
0074  *             \frac{ r_{min}^{12} }{ r^{13} } -
0075  *             \frac{ r_{min}^{6} }{ r^{7} }
0076  *         \right) \frac{\overrightarrow{r}}{r} & \mbox{  if  } r<\mbox{cutoff} \\
0077  *     \overrightarrow{f} = & 0 & \mbox{  if  } r \ge \mbox{cutoff}
0078  *  \f}
0079  *  where:\n
0080  *  \f$\epsilon\f$ is the depth of the potential\n
0081  *  \f$r_{min}\f$ is the distance at which the interparticle force is zero\n
0082  *  \f$\overrightarrow{r}\f$ is difference of GasParticle::position
0083                              of the first and second particle\n
0084  *  \f$\mbox{cutoff}\f$ is a cut-off distance (can be set to infinity)
0085  *
0086  */
0087 class GasLJForce : public Force
0088 {
0089     STEPCORE_OBJECT(GasLJForce)
0090 
0091 public:
0092     /** Constructs GasLJForce */
0093     explicit GasLJForce(double depth = 1, double rmin = 1, double cutoff = HUGE_VAL);
0094 
0095     void calcForce(bool calcVariances) override;
0096 
0097     /** Get depth of the potential */
0098     double depth() const { return _depth; }
0099     /** Set depth of the potential */
0100     void setDepth(double depth) { _depth = depth; calcABC(); }
0101 
0102     /** Get distance at which the interparticle force is zero */
0103     double rmin() const { return _rmin; }
0104     /** Set distance at which the interparticle force is zero */
0105     void setRmin(double rmin) { _rmin = rmin; calcABC(); }
0106 
0107     /** Get cut-off distance */
0108     double cutoff() const { return _cutoff; }
0109     /** Set cut-off distance */
0110     void setCutoff(double cutoff) { _cutoff = cutoff; calcABC(); }
0111 
0112     /** Get (and possibly create) GasLJForceErrors object */
0113     GasLJForceErrors* gasLJForceErrors() {
0114         return static_cast<GasLJForceErrors*>(objectErrors()); }
0115 
0116 protected:
0117     ObjectErrors* createObjectErrors() override { return new GasLJForceErrors(this); }
0118     void calcABC();
0119 
0120     double _depth;
0121     double _rmin;
0122     double _cutoff;
0123     double _a, _b, _c;
0124     double _rmin6, _rmin12;
0125 };
0126 
0127 typedef std::vector<GasParticle*> GasParticleList;
0128 
0129 /** \ingroup errors
0130  *  \brief Errors object for Gas
0131  */
0132 class GasErrors: public ObjectErrors
0133 {
0134     STEPCORE_OBJECT(GasErrors)
0135 
0136 public:
0137     /** Constructs GasErrors */
0138     explicit GasErrors(Item* owner = nullptr)
0139         : ObjectErrors(owner) {}
0140 
0141     /** Get owner as Gas */
0142     Gas* gas() const;
0143 
0144     double rectTemperatureVariance() const;
0145     double rectPressureVariance() const;
0146     Vector2d rectMeanVelocityVariance() const;
0147     double rectMeanKineticEnergyVariance() const;
0148     double rectMeanParticleMassVariance() const;
0149     double rectMassVariance() const;
0150 
0151 protected:
0152     friend class Gas;
0153 };
0154 
0155 /** \ingroup bodies
0156  *  \brief Gas - a group of several GasParticle and a force
0157  */
0158 class Gas: public ItemGroup
0159 {
0160     STEPCORE_OBJECT(Gas)
0161 
0162 public:
0163     Gas() : _measureRectCenter(0,0), _measureRectSize(1,1) {
0164         setColor(0xffff0000); objectErrors();
0165     }
0166 
0167     /** Creates particles with given temperature
0168      *  \todo XXX Normalize temperature after particle creation */
0169     GasParticleList rectCreateParticles(int count,
0170                                 double mass, double temperature,
0171                                 const Vector2d& meanVelocity);
0172 
0173     void addParticles(const GasParticleList& particles);
0174 
0175     double rectVolume() const;
0176     double rectParticleCount() const;
0177     double rectConcentration() const;
0178     double rectTemperature() const;
0179     double rectPressure() const;
0180     Vector2d rectMeanVelocity() const;
0181     double rectMeanKineticEnergy() const;
0182     double rectMeanParticleMass() const;
0183     double rectMass() const;
0184 
0185     const Vector2d& measureRectCenter() const { return _measureRectCenter; }
0186     void setMeasureRectCenter(const Vector2d& measureRectCenter) { _measureRectCenter = measureRectCenter; }
0187 
0188     const Vector2d& measureRectSize() const { return _measureRectSize; }
0189     void setMeasureRectSize(const Vector2d& measureRectSize) { _measureRectSize = measureRectSize.array().abs().matrix(); }
0190 
0191     /** Get (and possibly create) GasErrors object */
0192     GasErrors* gasErrors() {
0193         return static_cast<GasErrors*>(objectErrors()); }
0194 
0195 protected:
0196     ObjectErrors* createObjectErrors() override { return new GasErrors(this); }
0197 
0198     double randomUniform(double min=0, double max=1);
0199     double randomGauss(double mean=0, double deviation=1);
0200 
0201     Vector2d _measureRectCenter;
0202     Vector2d _measureRectSize;
0203 
0204     friend class GasErrors;
0205 };
0206 
0207 } // namespace StepCore
0208 
0209 #endif
0210