faunus
analysis.h
1 #pragma once
2 
3 #include "space.h"
4 #include "io.h"
5 #include "scatter.h"
6 #include "reactioncoordinate.h"
7 #include "aux/timers.h"
8 #include "aux/table_2d.h"
9 #include "aux/equidistant_table.h"
10 #include "aux/sparsehistogram.h"
11 #include <Eigen/SparseCore>
12 #include <limits>
13 #include <memory>
14 #include <set>
15 #include <string_view>
16 #include <string>
17 
19 class NewCoulombGalore;
20 }
21 
22 namespace Faunus::Energy {
23 class Hamiltonian;
24 class EnergyTerm;
25 class Penalty;
26 } // namespace Faunus::Energy
27 
28 namespace Faunus::SASA {
29 class SASABase;
30 }
31 
40 namespace Faunus::analysis {
41 
51 class Analysis
52 {
53  private:
54  virtual void _to_json(json&) const;
55  virtual void _from_json(const json&);
56  virtual void _sample() = 0;
57  virtual void _to_disk();
58  int number_of_steps = 0;
59  int number_of_skipped_steps = 0;
61 
62  protected:
63  const Space& spc;
64  int sample_interval = 0;
65  int number_of_samples = 0;
66 
67  public:
68  const std::string name;
69  std::string cite;
70  void to_json(json& j) const;
71  void from_json(const json& j);
72  void to_disk();
73  void sample();
74  [[nodiscard]] int getNumberOfSteps() const;
75  Analysis(const Space& spc, std::string_view name);
76  Analysis(const Space& spc, std::string_view name, int sample_interval,
77  int number_of_skipped_steps);
78  virtual ~Analysis() = default;
79 };
80 
81 void to_json(json& j, const Analysis& base);
82 
94 std::unique_ptr<Analysis> createAnalysis(const std::string& name, const json& j, Space& spc,
95  Energy::Hamiltonian& pot);
96 
104 class CombinedAnalysis : public BasePointerVector<Analysis>
105 {
106  public:
107  CombinedAnalysis(const json& json_array, Space& spc, Energy::Hamiltonian& pot);
108  void sample();
109  void to_disk();
110 };
111 
122 {
123  private:
124  void _to_disk() override;
125 
126  protected:
128  Energy::EnergyTerm& pot;
129  std::string filename;
130  std::unique_ptr<std::ostream> stream = nullptr;
133  bool collectWidomAverage(double energy_change);
134  PerturbationAnalysis(const std::string& name, Energy::EnergyTerm& pot, Space& spc,
135  const std::string& filename = ""s);
136  [[nodiscard]] double
137  meanFreeEnergy() const;
138 };
139 
144 {
145  private:
146  Average<double> mean_reaction_coordinate;
147  const std::string filename;
148  std::unique_ptr<std::ostream> stream = nullptr;
149  const std::unique_ptr<ReactionCoordinate::ReactionCoordinateBase> reaction_coordinate;
150 
151  void _to_json(json& j) const override;
152  void _sample() override;
153  void _to_disk() override;
155  const Space& spc, const std::string& filename,
156  std::unique_ptr<ReactionCoordinate::ReactionCoordinateBase> reaction_coordinate);
157 
158  public:
159  FileReactionCoordinate(const json& j, const Space& spc);
160 };
161 
173 {
174  protected:
175  MoleculeData::index_type molid;
176 
177  private:
179  std::unique_ptr<std::ostream>
180  single_position_stream;
181  std::vector<Point> reference_positions;
182  std::vector<Point> previous_positions;
183  std::vector<Eigen::Vector3i> cell_indices;
184  std::vector<average_type>
185  mean_squared_displacement;
186  double max_possible_displacement;
187 
189  SparseHistogram<double> displacement_histogram;
190  std::string displacement_histogram_filename;
191  int reference_reset_interval =
192  std::numeric_limits<int>::max();
193 
194  [[nodiscard]] virtual PointVector
195  getPositions() const;
196  void resetReferencePosition(const Point& position,
197  int index);
198  Point getOffset(const Point& diff, Eigen::Vector3i& cell) const;
199  void sampleDisplacementFromReference(const Point& position, int index);
200  void _sample() override;
201  void _to_json(json& j) const override;
202  void _to_disk() override;
203 
204  public:
205  AtomicDisplacement(const json& j, const Space& spc, std::string_view name = "displacement");
206 };
207 
214 {
215  private:
216  [[nodiscard]] PointVector
217  getPositions() const override;
218  public:
219  MassCenterDisplacement(const json& j, const Space& spc,
220  std::string_view name = "displacement_com");
221 };
222 
229 {
230  std::shared_ptr<MoleculeInserter> inserter;
231  int number_of_insertions;
232  MoleculeData::index_type molid;
233  bool absolute_z_coords = false;
234 
235  void selectGhostGroup();
236  void updateGroup(Space::GroupType& group, const ParticleVector& particles);
237  void _sample() override;
238  void _to_json(json& j) const override;
239  void _from_json(const json& j) override;
240 
241  public:
242  WidomInsertion(const json& j, Space& spc, Energy::Hamiltonian& pot);
243 };
244 
248 class [[maybe_unused]] PotentialCorrelation : public Analysis
249 {
250  private:
251  std::unique_ptr<pairpotential::NewCoulombGalore>
252  coulomb;
254  std::string filename;
255  std::pair<double, double> range;
256  double dr = 0;
257  unsigned int calculations_per_sample_event = 1;
258  void _to_json(json& j) const override;
259  void _sample() override;
260  void _to_disk() override;
261 
262  public:
263  PotentialCorrelation(const json& j, const Space& spc);
264 };
265 
270 {
271  public:
272  enum class Policies
273  {
274  FIXED,
275  RANDOM_WALK,
276  RANDOM_WALK_NO_OVERLAP,
277  INVALID
278  };
279 
280  private:
281  unsigned int max_overlap_trials = 100;
282  double histogram_resolution = 0.01;
283  unsigned int calculations_per_sample_event = 1;
284  std::string file_prefix;
285 
286  struct Target
287  {
288  Point position;
289  Average<double> mean_potential;
290  std::unique_ptr<SparseHistogram<double>>
291  potential_histogram;
292  };
293 
294  std::vector<Target> targets;
295  Policies policy;
296  std::unique_ptr<pairpotential::NewCoulombGalore>
297  coulomb;
299  mean_potential_correlation;
301  potential_correlation_histogram;
302  void getTargets(const json& j);
303  void setPolicy(const json& j);
304  double
305  calcPotentialOnTarget(const Target& target);
306  [[nodiscard]] bool overlapWithParticles(
307  const Point& position) const;
308  std::function<void()> applyPolicy;
309  json output_information;
310  void _to_json(json& j) const override;
311  void _sample() override;
312  void _to_disk() override;
313 
314  public:
315  ElectricPotential(const json& j, const Space& spc);
316 };
317 
318 NLOHMANN_JSON_SERIALIZE_ENUM(ElectricPotential::Policies,
319  {
320  {ElectricPotential::Policies::INVALID, nullptr},
321  {ElectricPotential::Policies::FIXED, "fixed"},
322  {ElectricPotential::Policies::RANDOM_WALK_NO_OVERLAP,
323  "no_overlap"},
324  {ElectricPotential::Policies::RANDOM_WALK, "random_walk"},
325  })
326 
333 class AtomProfile : public Analysis
334 {
336  double dr;
337  std::vector<std::string> names;
338  std::set<AtomData::index_type> atom_id_selection;
339  std::string file;
340  Point origin = {0.0, 0.0, 0.0};
341  Eigen::Vector3i dir = {1, 1, 1};
342  bool count_charge = false;
343  int center_of_mass_atom_id = -1; // center at COM of id_com atoms?
344 
345  [[nodiscard]] double distanceToOrigin(const Point& position) const;
346  void _from_json(const json& j) override;
347  void _to_json(json& j) const override;
348  void _to_disk() override;
349  void _sample() override;
350 
351  public:
352  AtomProfile(const json& j, const Space& spc);
353 };
354 
358 class SlicedDensity : public Analysis
359 {
360  double dz = 0.0;
361  Table2D<double, unsigned int> histogram; // N(z)
362  std::vector<std::string> atom_names;
363  std::vector<AtomData::index_type> atom_ids;
364  std::string file;
365  int center_of_mass_atom_id = -1; // center at COM of id_com atoms?
366 
367  void _from_json(const json& j) override;
368  void _to_json(json& j) const override;
369  void _sample() override;
370  void _to_disk() override;
371 
372  public:
373  SlicedDensity(const json& j, const Space& spc);
374 };
375 
379 class Density : public Analysis
380 {
381  protected:
383  using id_type = size_t;
384  std::map<id_type, Average<double>> mean_density;
385  std::map<id_type, std::string_view> names; // id <-> name database
386  void _to_disk() override;
387  void _sample() override;
388  void _to_json(json& j) const override;
389  static void writeTable(std::string_view name, Table& table);
390 
391  private:
392  [[nodiscard]] virtual std::map<id_type, int> count() const = 0;
393  std::map<MoleculeData::index_type, Table> probability_density;
394  Average<double> mean_cubic_root_of_volume;
395  Average<double> mean_volume;
396  Average<double> mean_inverse_volume;
397  double updateVolumeStatistics();
398 
399  public:
400  template <RequireNamedElements Range>
401  Density(const Space& spc, const Range& atoms_or_molecules, const std::string_view name)
402  : Analysis(spc, name)
403  {
404  for (const auto& data : atoms_or_molecules) {
405  names[data.id()] = data.name;
406  probability_density[data.id()].setResolution(1, 0);
407  }
408  }
409 };
410 
414 class MoleculeDensity final : public Density
415 {
416  private:
417  [[nodiscard]] std::map<id_type, int> count() const override;
418 
419  public:
420  MoleculeDensity(const json& j, const Space& spc);
421 };
422 
426 class AtomDensity final : public Density
427 {
428  private:
429  std::map<id_type, Table> atomswap_probability_density;
430  void _sample() override;
431  void _to_disk() override;
432  [[nodiscard]] std::map<id_type, int> count() const override;
433 
434  public:
435  AtomDensity(const json& j, const Space& spc);
436 };
437 
444 std::function<double(const Group&, const Group&)>
445 createGroupGroupProperty(const json& j, const Space& spc, Energy::Hamiltonian& hamiltonian);
446 
447 std::function<bool(double)> createValueFilter(const std::string& name, const json& j,
448  bool throw_on_error);
449 
460 {
461  private:
462  std::unique_ptr<std::ostream> matrix_stream;
463  std::string filename;
464  virtual void setPairMatrix() = 0;
465  void _to_json(json& j) const override;
466  void _from_json(const json& j) override;
467  void _sample() override;
468  void _to_disk() override;
469 
470  protected:
471  const Space& spc;
472  std::function<bool(double)> value_filter;
473  Eigen::SparseMatrix<double> pair_matrix;
474 
475  public:
476  PairMatrixAnalysis(const json& j, const Space& spc);
477 };
478 
486 {
487  private:
488  std::function<double(const Group&, const Group&)>
489  property;
490  std::vector<int> group_indices;
491  void setPairMatrix() override;
492  public:
493  GroupMatrixAnalysis(const json& j, const Space& spc, Energy::Hamiltonian& pot);
494 };
495 
500 {
501  private:
502  typename decltype(Faunus::molecules)::const_iterator mol_iter;
503  using AtomHistogram = std::map<AtomData::index_type, int>;
504  std::vector<AtomHistogram> atom_histograms;
505  std::vector<AverageStdev<double>> atom_mean_charges;
506  std::string filename;
507  bool verbose = true;
508 
509  ParticleVector averageChargeParticles(const Space::GroupType& group);
510  [[nodiscard]] std::vector<double> getMeanCharges() const;
511  [[nodiscard]] std::vector<double> getChargeStandardDeviation() const;
512  [[nodiscard]] std::vector<std::string> getPredominantParticleNames() const;
513 
514  void _sample() override;
515  void _to_json(json& j) const override;
516  void _to_disk() override;
517 
518  public:
519  ChargeFluctuations(const json& j, const Space& spc);
520 }; // Fluctuations of atomic charges
521 
525 class Multipole : public Analysis
526 {
527  struct Data
528  {
529  Average<double> charge;
530  Average<double> charge_squared;
531  Average<double> dipole_moment;
532  Average<double> dipole_moment_squared;
533  }; // Average sample moment for a molecule
534 
535  std::map<MoleculeData::index_type, Data>
536  average_moments;
537  void _sample() override;
538  void _to_json(json& j) const override;
539 
540  public:
541  Multipole(const json& j, const Space& spc);
542 };
543 
547 class SystemEnergy : public Analysis
548 {
549  private:
550  Energy::Hamiltonian& hamiltonian;
551  std::string file_name;
552  std::string separator;
553  std::unique_ptr<std::ostream> output_stream;
554  [[nodiscard]] std::vector<double> calculateEnergies() const;
555  Average<double> mean_energy;
556  Average<double> mean_squared_energy;
557  Table2D<double, double> energy_histogram; // Density histograms
558  double initial_energy = 0.0;
559  double minimum_energy = std::numeric_limits<double>::infinity();
560  bool dump_minimum_energy_configuration = false;
561 
562  bool updateMinimumEnergy(double current_energy);
563  void createOutputStream();
564  [[maybe_unused]] void normalize();
565  void _sample() override;
566  void _to_json(json& j) const override;
567  void _from_json(const json& j) override;
568  void _to_disk() override;
569 
570  public:
571  SystemEnergy(const json& j, const Space& spc, Energy::Hamiltonian& hamiltonian);
572 };
573 
577 class SanityCheck : public Analysis
578 {
579  private:
580  const double mass_center_tolerance = 1.0e-3;
581  void _sample() override;
582  void checkGroupsCoverParticles();
583  void
584  checkMassCenter(const Space::GroupType& group);
585  void checkWithinContainer(
586  const Space::GroupType& group);
587 
588  public:
589  SanityCheck(const json& j, const Space& spc);
590 };
591 
604 class SaveState : public Analysis
605 {
606  private:
607  std::function<void(const std::string&)> writeFunc = nullptr;
608  bool save_random_number_generator_state = false;
609  bool use_numbered_files = true;
610  bool convert_hexagonal_prism_to_cuboid = false;
611  std::string filename;
612 
613  void _to_json(json& j) const override;
614  void _sample() override;
615  static void saveAsCuboid(const std::string& filename, const Space& spc,
616  StructureFileWriter& writer);
617  void saveJsonStateFile(const std::string& filename, const Space& spc) const;
618  void saveBinaryJsonStateFile(const std::string& filename, const Space& spc) const;
619 
620  public:
621  SaveState(json j, const Space& spc);
622  ~SaveState() override;
623  void setWriteFunction(const Space& spc);
624 };
625 
629 class PairFunction : public Analysis
630 {
631  protected:
632  using index_type = size_t;
633  int dimensions = 3;
634  index_type id1 = 0;
635  index_type id2 = 0;
636  double dr = 0;
637  std::string name1;
638  std::string name2;
639  std::string file;
642  Eigen::Vector3i slicedir = {0, 0, 0};
643  double thickness = 0;
644 
645  private:
646  void _from_json(const json& j) override;
647  void _to_json(json& j) const override;
648  void _to_disk() override;
649  [[nodiscard]] double volumeElement(double r) const;
650 
651  public:
652  PairFunction(const Space& spc, const json& j, std::string_view name);
653 };
654 
658 class AtomRDF : public PairFunction
659 {
660  private:
661  void _sample() override;
662  void sampleDistance(const Particle& particle1, const Particle& particle2);
663  void sampleDifferent();
664  void sampleIdentical();
665 
666  public:
667  AtomRDF(const json& j, const Space& spc);
668 };
669 
673 class MoleculeRDF : public PairFunction
674 {
675  private:
676  void _sample() override;
677  void sampleDistance(const Group& group_i, const Group& group_j);
678  void sampleDifferent();
679  void sampleIdentical();
680 
681  public:
682  MoleculeRDF(const json& j, const Space& spc);
683 };
684 
689 {
690  private:
691  std::string correlation_filename;
692 
693  protected:
694  Equidistant2DTable<double, Average<double>> average_correlation_vs_distance;
695 
696  private:
697  void _from_json(const json& j) override;
698  void _to_disk() override;
699 
700  public:
701  PairAngleFunction(const Space& spc, const json& j, const std::string& name);
702 };
703 
706 {
707  void _sample() override;
708 
709  public:
710  AtomDipDipCorr(const json& j, const Space& spc);
711 };
712 
720 class XTCtraj : public Analysis
721 {
722  private:
723  using index_type = MoleculeData::index_type;
724  std::vector<index_type> group_ids;
725  std::vector<std::size_t> group_indices;
726  std::unique_ptr<XTCWriter> writer;
727  void _to_json(json& j) const override;
728  void _sample() override;
729  XTCtraj(const Space& spc, const std::string& filename,
730  const std::vector<std::string>& molecule_names);
731 
732  public:
733  XTCtraj(const json& j, const Space& spc);
734 };
735 
740 {
741  Geometry::VolumeMethod volume_scaling_method = Geometry::VolumeMethod::ISOTROPIC;
742  double volume_displacement = 0.0;
743  void _sample() override;
744  void _from_json(const json& j) override;
745  void _to_json(json& j) const override;
746  void sanityCheck(double old_energy);
747  void writeToFileStream(const Point& scale, double energy_change) const;
748 
749  public:
750  VirtualVolumeMove(const json& j, Space& spc, Energy::EnergyTerm& pot);
751 };
752 
757 {
758  MoleculeData::index_type molid;
759  std::map<int, unsigned int> histogram;
760  void _sample() override;
761  void _to_json(json& j) const override;
762 
763  public:
764  MolecularConformationID(const json& j, const Space& spc);
765 };
766 
777 {
778  MoleculeData::index_type molid;
779  Point perturbation_direction = {0.0, 0.0, 1.0};
780  double perturbation_distance = 0.0;
781 
782  void _sample() override;
783  void _from_json(const json& j) override;
784  void _to_json(json& j) const override;
785  double momentarilyPerturb(Space::GroupType& group);
786  void writeToFileStream(double energy_change) const;
787 
788  public:
789  VirtualTranslate(const json& j, Space& spc, Energy::EnergyTerm& pot);
790 };
791 
798 {
799  struct Data
800  {
801  using average_type = Average<double>;
802  average_type exact;
803  average_type ion_ion;
804  average_type ion_dipole;
805  average_type ion_quadrupole;
806  average_type dipole_dipole;
807  average_type dipole_dipole_correlation;
808  };
809 
810  std::map<MoleculeData::index_type, Data> mean_energy;
811  std::vector<std::string> names;
812  std::vector<MoleculeData::index_type> ids;
813  std::string filename;
814  double dr = 0.0;
815 
816  void _sample() override;
817  void _to_json(json& j) const override;
818  void _to_disk() override;
819  void sampleGroupGroup(const Space::GroupType& group1, const Space::GroupType& group2);
820  [[nodiscard]] double groupGroupExactEnergy(
821  const Space::GroupType& group1,
822  const Space::GroupType& group2) const; //<! exact ion-ion energy between particles
823 
824  public:
825  MultipoleDistribution(const json& j, const Space& spc);
826 }; // end of multipole distribution
827 
832 {
833  private:
834  enum class Schemes
835  {
836  DEBYE,
837  EXPLICIT_PBC,
838  EXPLICIT_IPBC
839  }; // three different schemes
840  Schemes scheme = Schemes::DEBYE;
841  bool mass_center_scattering;
842  bool save_after_sample = false;
843  std::string filename;
844  std::vector<Scatter::Scatterer> scatter_positions;
845  std::vector<MoleculeData::index_type> molecule_ids;
846  std::vector<std::string> molecule_names;
848 
849  std::unique_ptr<Scatter::DebyeFormula<Tformfactor>> debye;
850  std::unique_ptr<Scatter::StructureFactorPBC<Tformfactor>> explicit_average_pbc;
851  std::unique_ptr<Scatter::StructureFactorIPBC<Tformfactor, float>> explicit_average_ipbc;
852  void _sample() override;
853  void _to_disk() override;
854  void _to_json(json& j) const override;
855 
856  public:
857  ScatteringFunction(const json& j, const Space& spc);
858 };
859 
860 /*
861  * @brief Sample and save gyration eigenvalues of all particles having the same id
862  */
863 class AtomInertia : public Analysis
864 {
865  private:
866  std::string filename;
867  AtomData::index_type atom_id;
868  std::ofstream output_stream;
869 
870  Point compute();
871  void _to_json(json& j) const override;
872  void _sample() override;
873  void _to_disk() override;
874 
875  public:
876  AtomInertia(const json& j, const Space& spc);
877 };
878 
883 class InertiaTensor : public Analysis
884 {
885  private:
886  std::string filename;
887  std::unique_ptr<std::ostream> stream;
888  MoleculeData::index_type group_index;
889  std::vector<size_t> particle_range;
890  [[nodiscard]] std::pair<Point, Point>
891  compute() const;
892  void _to_json(json& j) const override;
893  void _sample() override;
894  void _to_disk() override;
895 
896  public:
897  InertiaTensor(const json& j, const Space& spc);
898 };
899 
900 /*
901  * @brief Sample and save charge, dipole, and quadrupole moments for a range of indexes within a
902  * molecule
903  */
905 {
906  private:
907  std::string filename;
908  std::vector<AtomData::index_type> particle_range;
909  MoleculeData::index_type group_index;
910  bool use_molecular_mass_center =
911  true;
912  std::ofstream output_stream;
913 
914  struct Data
915  {
916  double charge = 0.0; // total charge
917  Point dipole_moment{0.0, 0.0, 0.0}; // dipole vector
918  Point eivals, eivec, center; // quadrupole eigenvalues and major axis
919  } __attribute__((aligned(128)));
920 
921  Data calculateMultipoleMoment() const;
922  void _to_json(json& j) const override;
923  void _sample() override;
924  void _to_disk() override;
925 
926  public:
927  MultipoleMoments(const json& j, const Space& spc);
928 };
929 
940 class PolymerShape : public Analysis
941 {
942  struct AverageData
943  {
944  using average_type = Average<double>;
945  average_type gyration_radius_squared;
946  average_type gyration_radius;
947  average_type end_to_end_squared;
948  average_type shape_factor_squared;
949  average_type aspherity;
950  average_type acylindricity;
951  average_type relative_shape_anisotropy;
952  };
953 
954  AverageData data;
955  MoleculeData::index_type molid;
956  std::unique_ptr<std::ostream> tensor_output_stream = nullptr;
957  Equidistant2DTable<double, unsigned int> gyration_radius_histogram;
958 
959  void _to_json(json& j) const override;
960  void _sample() override;
961  void _to_disk() override;
962 
963  public:
964  PolymerShape(const json& j, const Space& spc);
965 };
966 
974 class QRtraj : public Analysis
975 {
976  protected:
977  std::function<void()> write_to_file;
978  std::unique_ptr<std::ostream> stream = nullptr;
979 
980  private:
981  std::string filename;
982  void _sample() override;
983  void _to_json(json& j) const override;
984  void _to_disk() override;
985 
986  public:
987  QRtraj(const json& j, const Space& spc, const std::string& name = "qrtraj");
988 };
989 
1001 {
1002  public:
1003  PatchySpheroCylinderTrajectory(const json& j, const Space& spc);
1004 };
1005 
1006 class AreaSamplingPolicy;
1007 
1014 class SASAAnalysis : public Analysis
1015 {
1016  using index_type = Faunus::AtomData::index_type;
1017  using count_type = size_t;
1019 
1020  public:
1021  enum class Policies
1022  {
1023  ATOMIC,
1024  MOLECULAR,
1025  ATOMS_IN_MOLECULE,
1026  INVALID
1027  };
1028 
1029  private:
1030  struct Averages
1031  {
1032  using average_type = Average<double>;
1033  average_type area;
1034  average_type area_squared;
1035  };
1036 
1037  Averages average_data;
1038 
1039  std::unique_ptr<std::ostream> output_stream;
1040 
1041  double probe_radius;
1042  int slices_per_atom;
1043 
1044  std::string filename;
1045  table_type sasa_histogram;
1046  std::unique_ptr<Faunus::SASA::SASABase> sasa;
1047  std::unique_ptr<AreaSamplingPolicy> policy;
1048 
1049  void _to_json(json& j) const override;
1050  void _from_json(const json& input) override;
1051  void _to_disk() override;
1052  void _sample() override;
1053 
1054  void setPolicy(Policies);
1055  void takeSample(double area);
1056 
1057  friend class AreaSamplingPolicy;
1058 
1059  public:
1060  SASAAnalysis(const json& j, const Space& spc);
1061  SASAAnalysis(double probe_radius, int slices_per_atom, double resolution, Policies policy,
1062  const Space& spc);
1063 };
1064 
1065 NLOHMANN_JSON_SERIALIZE_ENUM(SASAAnalysis::Policies,
1066  {{SASAAnalysis::Policies::ATOMIC, "atomic"},
1067  {SASAAnalysis::Policies::MOLECULAR, "molecular"},
1068  {SASAAnalysis::Policies::ATOMS_IN_MOLECULE, "atoms_in_molecule"},
1069  {SASAAnalysis::Policies::INVALID, nullptr}})
1070 
1072 class AreaSamplingPolicy
1073 {
1074  protected:
1075  template <typename TBegin, typename TEnd>
1076  void sampleIndividualSASA(TBegin first, TEnd last, SASAAnalysis& analysis);
1077  template <typename TBegin, typename TEnd>
1078  void sampleTotalSASA(TBegin first, TEnd last, SASAAnalysis& analysis);
1079 
1080  public:
1081  virtual void sample(const Space& spc, SASAAnalysis& analysis) = 0;
1082  virtual void to_json(json& input) const = 0;
1083  virtual void from_json(const json& input) = 0;
1084 
1085  inline AreaSamplingPolicy() = default;
1086  inline virtual ~AreaSamplingPolicy() = default;
1087 };
1088 
1090 class AtomicPolicy final : public AreaSamplingPolicy
1091 {
1092 
1093  AtomData::index_type atom_id;
1094  std::string atom_name;
1095 
1096  void sample(const Space& spc, SASAAnalysis& analysis) override;
1097  void to_json(json& input) const override;
1098  void from_json(const json& input) override;
1099 
1100  public:
1101  inline AtomicPolicy() = default;
1102 };
1103 
1105 class MolecularPolicy final : public AreaSamplingPolicy
1106 {
1107 
1108  MoleculeData::index_type molecule_id;
1109  std::string molecule_name;
1110 
1111  void sample(const Space& spc, SASAAnalysis& analysis) override;
1112  void to_json(json& input) const override;
1113  void from_json(const json& input) override;
1114 
1115  public:
1116  inline MolecularPolicy() = default;
1117 };
1118 
1124 class AtomsInMoleculePolicy final : public AreaSamplingPolicy
1125 {
1126 
1127  MoleculeData::index_type molecule_id;
1128  std::set<size_t> selected_indices;
1129  std::string molecule_name;
1130  std::set<std::string> atom_names;
1131 
1132  void sample(const Space& spc, SASAAnalysis& analysis) override;
1133  void to_json(json& input) const override;
1134  void from_json(const json& input) override;
1135 
1136  public:
1137  inline AtomsInMoleculePolicy() = default;
1138 };
1139 
1141 template <class T, class Enable = void> struct [[maybe_unused]] _analyse
1142 {
1143  void sample(T&) { std::cout << "not a dipole!" << std::endl; }
1144 }; // primary template
1145 
1147 template <class T>
1148 struct [[maybe_unused]] _analyse<T,
1149  typename std::enable_if<std::is_base_of<Dipole, T>::value>::type>
1150 {
1151  void sample(T&) { std::cout << "dipole!" << std::endl; }
1152 }; // specialized template
1153 
1155 {
1156  private:
1157  const std::string filename;
1158  int filenumber = 0;
1159  std::shared_ptr<Energy::Penalty> penalty_energy;
1160  void _sample() override;
1161 
1162  public:
1163  SavePenaltyEnergy(const json& j, const Space& spc, const Energy::Hamiltonian& pot);
1164 };
1165 
1173 class Voronota : public Analysis
1174 {
1175  public:
1176  enum class Modes
1177  {
1178  FULL,
1179  INTERCHAIN,
1180  UPDATEABLE,
1181  INVALID
1182  };
1183 
1184  private:
1185  struct Averages
1186  {
1187  Average<double> area_of_contacts;
1188  Average<double> volume_inside_sas;
1189  Average<double> area_of_sas;
1190  Average<double> area_of_sas_per_chain;
1191  };
1192 
1193  Modes mode = Modes::FULL;
1194  double probe_radius;
1195  bool use_pbc = false;
1196  Averages average_data;
1197  std::unique_ptr<std::ostream> output_stream;
1198  std::string filename;
1199 
1200  class Impl;
1201  std::unique_ptr<Impl> pimpl;
1202 
1203  void _to_json(json& json_output) const override;
1204  void _from_json(const json& input) override;
1205  void _to_disk() override;
1206  void _sample() override;
1207 
1208  public:
1209  Voronota(const json& j, const Space& spc);
1210  Voronota(Modes mode, double probe_radius, const Space& spc);
1211  ~Voronota();
1212 };
1213 
1214 } // namespace Faunus::analysis
Virtual translation move to calculate force.
Definition: analysis.h:776
SASA sampling policy which samples as a whole atom in a selected molecule if multiple atoms are selec...
Definition: analysis.h:1124
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 distribution functions etc.
Definition: analysis.h:629
Average< double > mean_exponentiated_energy_change
< exp(-du/kT) >
Definition: analysis.h:132
std::unique_ptr< Analysis > createAnalysis(const std::string &name, const json &j, Space &spc, Energy::Hamiltonian &pot)
Factory function for generating analysis based on name.
Definition: analysis.cpp:153
Definition: voronota.cpp:46
std::function< bool(double)> createValueFilter(const std::string &name, const json &j, bool throw_on_error)
Generate lambda to filter values.
Definition: analysis.cpp:476
Eigen::SparseMatrix< double > pair_matrix
Matrix of pair properties.
Definition: analysis.h:473
std::vector< Point > PointVector
Vector of 3D vectors.
Definition: core.h:24
Save system energy to disk.
Definition: analysis.h:547
double T
floating point size
Definition: units.h:73
Equidistant2DTable< double, double > histogram
distance histogram
Definition: analysis.h:640
Base class for all analysis functions.
Definition: analysis.h:51
Base class to writeKeyValuePairs simple structure files such as XYZ, AAM, PQR etc.
Definition: io.h:208
Same as AtomRDF but for molecules.
Definition: analysis.h:673
Example analysis.
Definition: analysis.h:1141
Space & mutable_space
This reference to space can be changed.
Definition: analysis.h:127
Analysis of single atom densities.
Definition: analysis.h:426
std::string file
output filename
Definition: analysis.h:639
Abstract base class for analysing atomic and molecular densities.
Definition: analysis.h:379
Samples the electric potential at arbitrary positions in the simulation box.
Definition: analysis.h:269
std::string filename
output filename (optional)
Definition: analysis.h:129
std::function< void()> write_to_file
Write a single frame to stream.
Definition: analysis.h:977
Definition: actions.h:8
Definition: table.py:1
Definition: analysis.h:499
Analysis of molecular group densities.
Definition: analysis.h:414
Tracks displacements of molecular group mass centers.
Definition: analysis.h:213
Excess pressure using virtual volume move.
Definition: analysis.h:739
Atomic radial distribution function, g(r)
Definition: analysis.h:658
Definition: equidistant_table.h:25
std::vector< Particle > ParticleVector
Storage type for collections of particles.
Definition: particle.h:253
Create histogram of molecule conformation id.
Definition: analysis.h:756
Write XTC trajectory file.
Definition: analysis.h:720
Definition: analysis.h:904
Sample scattering intensity.
Definition: analysis.h:831
Definition: analysis.h:1154
std::string name2
atom or molecule name
Definition: analysis.h:638
Particle class for storing positions, id, and other properties.
Definition: particle.h:220
Excess chemical potential of molecules.
Definition: analysis.h:228
Samples the electric potential correlation as a function of distance, < Φ₁Φ₂>="">(r) ...
Definition: analysis.h:248
Trajectory with charge and radius, only, for all (active, inactive) particles.
Definition: analysis.h:974
Base class for streaming pair properties to a sparse matrix.
Definition: analysis.h:459
Adding a new analysis requires the following steps:
Definition: analysis.cpp:36
End of Group class.
Definition: group.h:177
Change change
Change object to describe perturbation.
Definition: analysis.h:131
Namespace for particle pair-potentials.
Definition: analysis.h:18
Dipole-dipole correlation function, <{}(0){}(r)>
Definition: analysis.h:705
Aggregate and sum energy terms.
Definition: energy.h:1954
Definition: analysis.h:863
std::function< bool(double)> value_filter
Used to filter values generated by property
Definition: analysis.h:472
Definition: analysis.h:28
All energies inherit from this class.
Definition: externalpotential.h:21
Definition: analysis.h:688
const std::string name
descriptive name
Definition: analysis.h:68
Molecular multipole moments and their fluctuations.
Definition: analysis.h:525
SASA sampling policy which samples individually atoms selected by atom type name. ...
Definition: analysis.h:1090
Analysis of Vorononoi tessellation using the Voronota-LT library.
Definition: analysis.h:1173
SASA sampling policy which samples individually molecules selected by molecules name.
Definition: analysis.h:1105
NLOHMANN_JSON_SERIALIZE_ENUM(SpheroCylinderData::PatchType, {{SpheroCylinderData::PatchType::Invalid, nullptr}, {SpheroCylinderData::PatchType::Full, "full"}, {SpheroCylinderData::PatchType::Capped, "capped"}, {SpheroCylinderData::PatchType::None, "none"}}) class AtomData
General properties for atoms.
Definition: atomdata.h:61
Aggregator class for storing and selecting multiple analysis instances.
Definition: analysis.h:104
std::vector< MoleculeData > molecules
List of molecule types.
Definition: molecule.cpp:22
Specify changes made to a system.
Definition: space.h:29
Atom-specific constant form factor (q independent).
Definition: scatter.h:95
Sample and save the eigenvalues of the inertia tensor for a range of indexes within a molecule...
Definition: analysis.h:883
std::function< double(const Group &, const Group &)> createGroupGroupProperty(const json &j, const Space &spc, Energy::Hamiltonian &hamiltonian)
Generates lambda to calculate properties between groups.
Definition: analysis.h:445
std::string cite
url, doi etc. describing the analysis
Definition: analysis.h:69
Checks if system is sane.
Definition: analysis.h:577
std::string name1
atom or molecule
Definition: analysis.h:637
Samples a matrix of group properties.
Definition: analysis.h:485
Placeholder for atoms and molecules.
Definition: space.h:92
Density of atom along axis.
Definition: analysis.h:358
Wrapper for external CoulombGalore library.
Definition: potentials.h:581
Helper class for storing vectors of base pointers.
Definition: auxiliary.h:237
Average< double > mean_volume
average volume (angstrom^3)
Definition: analysis.h:641
Save simulation state and particle coordinates to disk.
Definition: analysis.h:604
Tracks displacements of particle positions.
Definition: analysis.h:172
Analysis of polymer shape - radius of gyration, shape etc.
Definition: analysis.h:940
void sample(T &)
Sample.
Definition: analysis.h:1143
Multipolar decomposition between groups as a function of separation.
Definition: analysis.h:797
Generate PSCs text trajectory containing.
Definition: analysis.h:1000
const Space & spc
Instance of Space to analyse.
Definition: analysis.h:63
Sample and save reaction coordinates to a file.
Definition: analysis.h:143
Analysis class for sasa calculations.
Definition: analysis.h:1014
VolumeMethod
Various methods of volume scaling,.
Definition: geometry.h:52
Base class for perturbation analysis.
Definition: analysis.h:121