faunus
particle.h
1 #pragma once
2 #include "core.h"
3 #include "atomdata.h"
4 #include "tensor.h"
5 #include <spdlog/spdlog.h>
6 
7 namespace Eigen {
8 using Matrix3d = Matrix<double, 3, 3>;
9 using Quaterniond = Quaternion<double>;
10 } // namespace Eigen
11 
12 namespace Faunus {
13 
19 {
20  virtual void to_json(json& j) const = 0;
21  virtual void from_json(const json& j) = 0;
22  void rotate(const Eigen::Quaterniond& q, const Eigen::Matrix3d&);
23  virtual ~ParticlePropertyBase() = default;
24 };
25 
26 template <typename... Ts> auto to_json(json&) -> typename std::enable_if<sizeof...(Ts) == 0>::type
27 {
28 }
29 
30 template <typename T, typename... Ts>
31 void to_json(json& j, const ParticlePropertyBase& a, const Ts&... rest)
32 {
33  a.to_json(j);
34  to_json<Ts...>(j, rest...);
35 }
36 
37 // JSON --> Particle
38 template <typename... Ts>
39 auto from_json(const json&) -> typename std::enable_if<sizeof...(Ts) == 0>::type
40 {
41 }
42 
43 template <typename T, typename... Ts>
44 void from_json(const json& j, ParticlePropertyBase& a, Ts&... rest)
45 {
46  a.from_json(j);
47  from_json<Ts...>(j, rest...);
48 }
49 
51 {
52  double radius = 0.0;
53  void to_json(json& j) const override;
54  void from_json(const json& j) override;
55 
56  template <class Archive> void serialize(Archive& archive) { archive(radius); }
57 
58  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
59 };
60 
62 {
63  double charge = 0.0;
64  void to_json(json& j) const override;
65  void from_json(const json& j) override;
66 
67  template <class Archive> void serialize(Archive& archive) { archive(charge); }
68 
69  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
70 };
71 
76 {
77  Point mu = {0.0, 0.0, 0.0};
78  double mulen = 0.0;
79  void rotate(const Eigen::Quaterniond& q, const Eigen::Matrix3d&);
80  void to_json(json& j) const override;
81  void from_json(const json& j) override;
82  bool isDipolar() const;
83 
84  template <class Archive> void serialize(Archive& archive) { archive(mu, mulen); }
85 
86  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
87 };
88 
90 {
91  Point mui = {1.0, 0.0, 0.0};
92  double muilen = 0.0;
93  Tensor alpha = Tensor::Zero();
94  void rotate(const Eigen::Quaterniond& q,
95  const Eigen::Matrix3d& m);
96  void to_json(json& j) const override;
97  void from_json(const json& j) override;
98  bool isPolarizable() const;
99 
100  template <class Archive> void serialize(Archive& archive) { archive(mui, muilen, alpha); }
101 
102  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
103 };
104 
106 {
107  Tensor Q = Tensor::Zero();
108  void rotate(const Eigen::Quaterniond& q,
109  const Eigen::Matrix3d& m);
110  void to_json(json& j) const override;
111  void from_json(const json& j) override;
112  bool isQuadrupolar() const;
113 
114  template <class Archive> void serialize(Archive& archive) { archive(Q); }
115 
116  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
117 }; // Quadrupole property
118 
123 {
124  private:
125  public:
126  using string_t = nlohmann::basic_json<>::string_t;
127  Point scdir = {1.0, 0.0, 0.0};
128  Point patchdir = {0.0, 1.0, 0.0};
129  std::array<Point, 2> patchsides;
130  double half_length = 0.0;
131  double pcanglsw = 0.0;
132  double pcangl = 0.0;
133  void rotate(const Eigen::Quaterniond& quaternion,
134  const Eigen::Matrix3d& rotation_matrix);
135  void to_json(json& j) const override;
136  void from_json(const json& j) override;
137  void setDirections(
138  const SpheroCylinderData& psc_data, const Point& new_direction,
139  const Point& new_patch_direction); // initialize; run at start and after patch changes
140 
141  template <class Archive> void serialize(Archive& archive)
142  {
143  archive(scdir, patchdir, patchsides.at(0), patchsides.at(1));
144  }
145 
146  bool isCylindrical() const;
147 
148  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
149 };
150 
160 template <typename... Properties> class ParticleTemplate : public Properties...
161 {
162  private:
163  // rotate internal coordinates
164  template <typename... Ts>
165  auto _rotate(const Eigen::Quaterniond&, const Eigen::Matrix3d&) ->
166  typename std::enable_if<sizeof...(Ts) == 0>::type
167  {
168  }
169 
170  template <typename T, typename... Ts>
171  void _rotate(const Eigen::Quaterniond& q, const Eigen::Matrix3d& m, T& a, Ts&... rest)
172  {
173  a.rotate(q, m);
174  _rotate<Ts...>(q, m, rest...);
175  }
176 
177  public:
179  : Properties()... {};
180 
181  explicit ParticleTemplate(const AtomData& a)
182  : Properties()...
183  {
184  *this = json(a).front();
185  }
186 
187  void rotate(const Eigen::Quaterniond& q, const Eigen::Matrix3d& m)
188  {
189  _rotate<Properties...>(q, m, dynamic_cast<Properties&>(*this)...);
190  }
191 
192  template <class Archive> void serialize(Archive& archive)
193  {
194  __serialize<Properties...>(archive, dynamic_cast<Properties&>(*this)...);
195  }
196 
197  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
198 };
199 
200 template <typename... Properties> void to_json(json& j, const ParticleTemplate<Properties...>& a)
201 {
202  to_json<Properties...>(j, Properties(a)...);
203 }
204 
205 template <typename... Properties> void from_json(const json& j, ParticleTemplate<Properties...>& a)
206 {
207  from_json<Properties...>(j, dynamic_cast<Properties&>(a)...);
208 }
209 
220 class Particle
221 {
222  public:
224  std::unique_ptr<ParticleExtension> ext;
225  int id = -1;
226  double charge = 0.0;
227  Point pos = {0.0, 0.0, 0.0};
228 
229  Particle() = default;
230  Particle(const AtomData& a, const Point& pos);
231  Particle(const AtomData& a);
232  Particle(const Particle&);
233  Particle& operator=(const Particle&);
234  const AtomData& traits() const;
235  void rotate(const Eigen::Quaterniond& quaternion,
236  const Eigen::Matrix3d& rotation_matrix);
237  bool hasExtension() const;
238  ParticleExtension& createExtension();
239 
241  {
242  return ext ? *ext : createExtension();
243  }
244 
245  inline const ParticleExtension& getExt() const
246  {
247  assert(ext);
248  return *ext;
249  }
250 };
251 
253 using ParticleVector = std::vector<Particle>;
254 
256 template <class T>
258  std::ranges::range<T> && std::is_convertible_v<std::ranges::range_value_t<T>, Particle>;
259 
260 template <class T>
261 concept RequireParticleIterator = std::is_convertible_v<std::iter_value_t<T>, Particle>;
262 
263 void from_json(const json&, Particle&);
264 void to_json(json&, const Particle&);
265 
272 template <RequireParticleIterator Iterator>
273 void applyAtomDataCharges(Iterator first, Iterator last, const double max_difference = 1e-9)
274 {
275  size_t mismatch_counter = 0;
276  std::for_each(first, last, [&](Particle& particle) {
277  const auto topology_charge = Faunus::atoms.at(particle.id).charge;
278  if (std::fabs(topology_charge - particle.charge) > max_difference) {
279  particle.charge = topology_charge;
280  mismatch_counter++;
281  }
282  });
283  if (mismatch_counter > 0) {
284  faunus_logger->debug("{} charge(s) reset with topology values (from atomlist)",
285  mismatch_counter);
286  }
287 }
288 
289 } // namespace Faunus
nlohmann::json json
JSON object.
Definition: json_support.h:10
Eigen::Vector3d Point
3D vector used for positions, velocities, forces etc.
Definition: coordinates.h:7
Base class for particle properties.
Definition: particle.h:18
Tensor class Tensor class.
Definition: tensor.h:10
Radius property.
Definition: particle.h:50
double T
floating point size
Definition: units.h:73
void rotate(const Eigen::Quaterniond &q, const Eigen::Matrix3d &m)
Rotate all internal coordinates if needed.
Definition: particle.h:187
concept RequireParticles
Concept for a range of particles.
Definition: particle.h:257
ParticleExtension & getExt()
get/create extension
Definition: particle.h:240
Static properties for patchy sphero cylinders (PSC)
Definition: atomdata.h:36
Definition: eigensupport.h:8
virtual void to_json(json &j) const =0
Convert to JSON object.
virtual void from_json(const json &j)=0
Convert from JSON object.
std::vector< Faunus::AtomData > atoms
Global instance of atom list.
Definition: atomdata.cpp:242
Patchy sphero cylinder a.k.a.Sphero-cylinder properties.
Definition: particle.h:122
Particle template.
Definition: particle.h:160
std::unique_ptr< ParticleExtension > ext
Point to extended properties.
Definition: particle.h:224
std::vector< Particle > ParticleVector
Storage type for collections of particles.
Definition: particle.h:253
int id
Particle id/type.
Definition: particle.h:225
Charge (monopole) property.
Definition: particle.h:61
const ParticleExtension & getExt() const
Get extended particle properties;.
Definition: particle.h:245
Particle class for storing positions, id, and other properties.
Definition: particle.h:220
Definition: particle.h:105
Cell list class templates.
Definition: actions.cpp:11
double charge
Particle charge.
Definition: particle.h:226
Dipole properties.
Definition: particle.h:75
Definition: particle.h:89
void applyAtomDataCharges(Iterator first, Iterator last, const double max_difference=1e-9)
Reset all charges in particle range to those found in Faunus::atoms.
Definition: particle.h:273