faunus
molecule.h
1 #pragma once
2 
3 #include "auxiliary.h"
4 #include "particle.h"
5 #include "random.h"
6 #include <set>
7 
8 namespace Faunus {
9 
10 namespace pairpotential {
11 struct BondData;
12 }
13 
14 namespace Geometry {
15 struct GeometryBase;
16 }
17 
18 class QuaternionRotate;
19 class MoleculeData;
20 
33 {
34  virtual ParticleVector operator()(const Geometry::GeometryBase& geo, MoleculeData& mol,
35  const ParticleVector& other_particles) = 0;
36  virtual void from_json(const json& j);
37  virtual void to_json(json& j) const;
38  virtual ~MoleculeInserter() = default;
39 };
40 
41 void from_json(const json& j, MoleculeInserter& inserter);
42 void to_json(json& j, const MoleculeInserter& inserter);
43 
48 {
49  private:
50  void translateRotateAtomicGroup(const Geometry::GeometryBase& geo,
51  Faunus::QuaternionRotate& rotator,
52  ParticleVector& particles) const;
53  void translateRotateMolecularGroup(const Geometry::GeometryBase& geo, QuaternionRotate& rotator,
54  ParticleVector& particles) const;
55 
56  public:
57  Point dir = {1, 1, 1};
58  Point offset = {0, 0, 0};
59  bool rotate = true;
60  bool keep_positions = false;
61  bool allow_overlap = false;
62  int max_trials = 20'000; //!< Maximum number of container overlap checks
63 
64  ParticleVector
65  operator()(const Geometry::GeometryBase& geo, MoleculeData& molecule,
66  const ParticleVector& ignored_other_particles = ParticleVector()) override;
67  void from_json(const json& j) override;
68  void to_json(json& j) const override;
69 };
70 
74 struct Conformation
75 {
76  std::vector<Point> positions;
77  std::vector<double> charges;
78  bool empty() const;
79  void copyTo(ParticleVector& particles) const; //!< Copy conformation into particle vector
80 };
81 
89 class ExclusionsSimple
90 {
91  bool any_exclusions = false; //!< true if at least one excluded interaction is present
92  int size; //!< number of particles within the group; matrix = size × size
93  using char_bool =
94  unsigned char; //!< obs: std::vector<bool> uses packing with performance implications
95  std::shared_ptr<std::vector<char_bool>>
96  excluded_pairs; //!< 1D exclusion matrix; shared ptr saves copying
97 
98  public:
99  using AtomPair = std::pair<int, int>;
101  static ExclusionsSimple create(int atoms_cnt, const std::vector<std::pair<int, int>>& pairs);
102  explicit ExclusionsSimple(int size = 0);
104  void add(int i, int j);
105  void add(const std::vector<AtomPair>& pairs);
107  bool isExcluded(int i, int j) const;
108  bool empty() const; //!< true if no excluded interactions at all
109  friend void from_json(const json& j, ExclusionsSimple& exclusions);
110  friend void to_json(json& j, const ExclusionsSimple& exclusions);
111 };
112 
113 inline bool ExclusionsSimple::isExcluded(int i, int j) const
114 {
115  if (i > j) {
116  std::swap(i, j);
117  }
118  // use the bracket syntax to skip checks to speed-up reading
119  return any_exclusions && static_cast<bool>((*excluded_pairs)[i * size + j]);
120 }
121 
122 inline bool ExclusionsSimple::empty() const
123 {
124  return !any_exclusions;
125 }
126 
127 void from_json(const json& j, ExclusionsSimple& exclusions);
128 void to_json(json& j, const ExclusionsSimple& exclusions);
129 
140 class ExclusionsVicinity
141 {
142  public:
143  using char_bool =
144  unsigned char; //!< obs: std::vector<bool> uses packing with performance implications
145  using AtomPair = std::pair<int, int>;
146 
147  private:
148  int atoms_cnt = 0; //!< count of atoms in the molecule; unmutable
149  int max_bond_distance = 0; //!< max distance (difference) between indices of excluded particles
150  std::shared_ptr<std::vector<char_bool>>
151  excluded_pairs; //!< 1D exclusion matrix; shared ptr saves copying
152 
153  int toIndex(int i, int j) const;
154  AtomPair fromIndex(int n) const;
155 
156  public:
161  static ExclusionsVicinity create(int atoms_cnt, const std::vector<AtomPair>& pairs);
167  explicit ExclusionsVicinity(int atoms_cnt = 0, int max_difference = 0);
168 
170  void add(int i, int j);
171  void add(const std::vector<std::pair<int, int>>& pairs);
172  bool isExcluded(int i,
173  int j)
174  const; //!< @param i, j indices of atoms within molecule with excluded nonbonded interaction
175  bool empty() const; //!< true if no excluded interactions at all
176  friend void to_json(json& j, const ExclusionsVicinity& exclusions);
177 };
178 
179 inline bool ExclusionsVicinity::isExcluded(int i, int j) const
180 {
181  if (i > j) {
182  std::swap(i, j);
183  }
184  // use bracket syntax to skip checks to speed-up reading
185  return (j - i <= max_bond_distance && static_cast<bool>((*excluded_pairs)[toIndex(i, j)]));
186 }
187 
188 inline bool ExclusionsVicinity::empty() const
189 {
190  return max_bond_distance == 0;
191 }
192 
193 inline int ExclusionsVicinity::toIndex(int i, int j) const
194 {
195  return i * max_bond_distance + (j - i - 1);
196 }
197 
198 inline ExclusionsVicinity::AtomPair ExclusionsVicinity::fromIndex(const int n) const
199 {
200  auto i = n / max_bond_distance;
201  auto j = n % max_bond_distance + i + 1;
202  return {i, j};
203 }
204 
205 // void from_json(const json &j, ExclusionsVicinity &exclusions); // not implemented
206 void to_json(json& j, const ExclusionsVicinity& exclusions);
207 
211 class MoleculeData
212 {
213  public:
214  using index_type = int;
215 
216  private:
217  json json_cfg; //!< data useful only for to_json
218  index_type _id = 0;
219  bool implicit = false; //!< Is molecule implicit and explicitly absent from simulation cell?
220 
221  protected:
222  ExclusionsVicinity exclusions; //!< Implementation of isPairExcluded;
224  public:
225  std::shared_ptr<MoleculeInserter> inserter = nullptr; //!< Functor for insertion into space
226 
227  index_type& id(); //!< Type id
228  const index_type& id() const; //!< Type id
229  void createMolecularConformations(const json& j); //!< Add conformations if appropriate
230  void setConformationWeights(const json& j); //!< Add weights for conformations
231 
232  std::string name; //!< Molecule name
233  bool atomic = false; //!< True if atomic group (salt etc.)
234  bool compressible =
235  false; //!< True if compressible group (scales internally upon volume change)
236  bool rigid = false; //!< True if particle should be considered as rigid
237  double activity = 0.0; //!< Chemical activity (mol/l)
238 
239  std::vector<AtomData::index_type> atoms; //!< Sequence of atoms in molecule (atom id's)
242  size_t numConformations() const;
243 
244  MoleculeData();
245  MoleculeData(const std::string& name, const ParticleVector& particles,
247 
248  bool isImplicit() const;
249  bool isPairExcluded(int i, int j) const;
250  bool isMolecular() const;
251  bool isAtomic() const;
252 
258  void setInserter(std::shared_ptr<MoleculeInserter> ins);
259 
269  ParticleVector getRandomConformation(Geometry::GeometryBase& geo,
270  const ParticleVector& otherparticles = ParticleVector());
271 
272  friend class MoleculeBuilder;
273  friend void to_json(json& j, const MoleculeData& a);
274  friend void from_json(const json& j, MoleculeData& a);
275 }; // end of class
276 
277 inline bool MoleculeData::isPairExcluded(int i, int j) const
278 {
279  return exclusions.isExcluded(i, j);
280 }
281 
282 void to_json(json& j, const MoleculeData& a);
283 void from_json(const json& j, MoleculeData& a);
284 void from_json(const json& j, std::vector<MoleculeData>& v);
285 
286 // global instance of molecule vector
287 extern std::vector<MoleculeData> molecules;
288 
293 {
294  explicit UnknownMoleculeError(std::string_view molecule_name);
295 };
296 
306 MoleculeData& findMoleculeByName(std::string_view name);
307 
308 std::vector<MoleculeData::index_type> parseMolecules(const json& j);
309 
316 {
317  bool is_used = false;
318  std::string molecule_name;
319  ParticleVector particles;
320  decltype(MoleculeData::bonds) bonds;
321  std::vector<std::pair<int, int>> exclusion_pairs;
322 
323  protected:
324  static bool
325  isFasta(const json& j);
326  void readCompoundValues(
327  const json& j);
328  void readAtomic(const json& j);
329  void
330  readParticles(const json& j);
331  void readBonds(const json& j);
332  void readFastaBonds(const json& j);
333  void readExclusions(const json& j);
334  static std::shared_ptr<MoleculeInserter> createInserter(const json& j);
335 
336  public:
338  void from_json(const json& j, MoleculeData& molecule);
339 };
340 
345 {
346  bool read_charges;
347  protected:
349  static void readArray(ParticleVector& particles, const json& j_particles);
351  static void readFasta(ParticleVector& particles, const json& j);
352 
353  public:
354  MoleculeStructureReader(bool read_charges = true);
356  void readFile(ParticleVector& particles, const std::string& filename) const;
358  void readJson(ParticleVector& particles, const json& j) const;
359 };
360 
368 {
371  public:
372  using AtomList = std::vector<int>;
373  using AtomPair = std::pair<int, int>;
374  using AtomPairList = std::vector<AtomPair>;
375  using BondVector = decltype(MoleculeData::bonds);
376 
377  private:
378  std::map<int, AtomList>
379  bond_map;
380  std::vector<std::set<AtomList>> paths;
383 
384  void createBondMap(const BondVector& bonds);
385  void generatePaths(int bonded_distance);
386 
387  public:
389  NeighboursGenerator(const BondVector& bonds);
395  void generatePairs(AtomPairList& pairs, int bond_distance);
396 };
397 
421 {
422  public:
423  using StoichiometryMap = std::map<int, int>;
424  using AtomicAndMolecularPair = std::pair<const StoichiometryMap&, const StoichiometryMap&>;
425  using StoichiometryPair =
426  StoichiometryMap::value_type;
427  using MapFilter = std::function<bool(const ReactionData::StoichiometryPair&)>;
428  enum class Direction : char
429  {
430  LEFT = 0,
431  RIGHT = 1
432  };
433 
434  const static MapFilter is_implicit_group;
435  const static MapFilter not_implicit_group;
436  const static MapFilter not_implicit_atom;
437  const static MapFilter is_atomic_group;
438  const static MapFilter is_molecular_group;
439 
440  private:
441  friend void from_json(const json&, ReactionData&);
442  friend void to_json(json&, const ReactionData&);
443 
444  Direction direction = Direction::RIGHT;
445  std::vector<std::string> left_names, right_names;
446  StoichiometryMap left_molecules;
447  StoichiometryMap right_molecules;
448  StoichiometryMap left_atoms;
449  StoichiometryMap right_atoms;
450  double lnK = 0.0;
451  double lnK_unmodified = 0.0;
452  std::string reaction_str;
453 
460  static std::pair<decltype(Faunus::atoms)::const_iterator,
461  decltype(Faunus::molecules)::const_iterator>
462  findAtomOrMolecule(const std::string& atom_or_molecule_name);
463 
464  public:
465  void setDirection(Direction);
466  void setRandomDirection(Random& random);
467  Direction getDirection() const;
468  void reverseDirection();
469  AtomicAndMolecularPair getProducts() const;
470  AtomicAndMolecularPair getReactants() const;
471  double freeEnergy() const;
472  bool containsAtomicSwap() const;
473  const std::string& getReactionString() const;
474 
475  std::pair<std::set<int>, std::set<int>>
476  participatingAtomsAndMolecules() const;
477 
478  bool only_neutral_molecules = false;
479 };
480 
487 std::pair<std::vector<std::string>, std::vector<std::string>>
488 parseReactionString(const std::string& process_string);
489 
490 void from_json(const json&, ReactionData&);
491 void to_json(json&, const ReactionData&);
492 
493 extern std::vector<ReactionData> reactions; // global instance
494 
495 } // 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
StoichiometryMap::value_type StoichiometryPair
first = id; second = stoichiometic coeff.
Definition: molecule.h:426
Random random
global instance of Random
Definition: random.cpp:62
General properties of reactionsEnd of class.
Definition: molecule.h:420
Random number generator.
Definition: random.h:34
Rotation routine using the Eigen library.
Definition: rotate.h:12
MoleculeData & findMoleculeByName(std::string_view name)
Finds a molecule by its name in the global Faunus molecules lexicon.
Definition: molecule.cpp:1306
std::vector< int > AtomList
a path created from 1-2 bonds (e.g., harmonic or FENE) as an ordered list of atoms involved; atoms ar...
Definition: molecule.h:372
std::map< int, int > StoichiometryMap
key = id; value = stoichiometic coeff.
Definition: molecule.h:423
Common ancestor of Faunus specific runtime errors.
Definition: core.h:50
Constructs MoleculeData from JSON.
Definition: molecule.h:315
std::vector< Faunus::AtomData > atoms
Global instance of atom list.
Definition: atomdata.cpp:242
Random position and orientation - typical for rigid bodies.
Definition: molecule.h:32
An interface for all geometries.Base class for all geometries.
Definition: geometry.h:107
std::vector< Particle > ParticleVector
Storage type for collections of particles.
Definition: particle.h:253
General properties for molecules.
Definition: molecule.h:211
This file contains auxiliary functionality that have no dependencies other than STL and can hence be ...
Cell list class templates.
Definition: actions.cpp:11
std::pair< std::vector< std::string >, std::vector< std::string > > parseReactionString(const std::string &process_string)
This parses a string containing a reaction, e.g.
Definition: molecule.cpp:1321
std::vector< MoleculeData > molecules
List of molecule types.
Definition: molecule.cpp:22
Fills the particle vector from various sources, e.g., files or JSON array.
Definition: molecule.h:344
Generate all possible atom pairs within a given bond distance.
Definition: molecule.h:367
An exception to indicate an unknown molecule name in the input.
Definition: molecule.h:292
std::vector< ReactionData > reactions
List of reactions.
Definition: molecule.cpp:23
Inserts molecules into random positions in the container.
Definition: molecule.h:47
WeightedDistribution< ParticleVector > conformations
Conformations of molecule.
Definition: molecule.h:241
std::vector< MoleculeData::index_type > parseMolecules(const json &j)
Definition: molecule.cpp:1345