LCOV - code coverage report
Current view: top level - pairinteraction - SystemBase.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 32 40 80.0 %
Date: 2024-04-29 00:41:50 Functions: 19 66 28.8 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Sebastian Weber, Henri Menke. All rights reserved.
       3             :  *
       4             :  * This file is part of the pairinteraction library.
       5             :  *
       6             :  * The pairinteraction library is free software: you can redistribute it and/or modify
       7             :  * it under the terms of the GNU Lesser General Public License as published by
       8             :  * the Free Software Foundation, either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * The pairinteraction library is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public License
      17             :  * along with the pairinteraction library. If not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #ifndef SYSTEMBASE_H
      21             : #define SYSTEMBASE_H
      22             : 
      23             : #include "State.hpp"
      24             : #include "serialization_eigen.hpp"
      25             : #include "utils.hpp"
      26             : 
      27             : #include <boost/multi_index/hashed_index.hpp>
      28             : #include <boost/multi_index/member.hpp>
      29             : #include <boost/multi_index/random_access_index.hpp>
      30             : #include <boost/multi_index_container.hpp>
      31             : #include <cereal/types/complex.hpp>
      32             : #include <cereal/types/set.hpp>
      33             : #include <cereal/types/vector.hpp>
      34             : 
      35             : #include <algorithm>
      36             : #include <complex>
      37             : #include <functional>
      38             : #include <set>
      39             : #include <vector>
      40             : 
      41             : class MatrixElementCache;
      42             : 
      43             : template <class T>
      44             : class enumerated_state {
      45             : public:
      46       27699 :     enumerated_state(size_t idx, T state) : idx(idx), state(std::move(state)) {}
      47        1102 :     enumerated_state()
      48        1102 :         : state() { // TODO remove and use
      49             :                     // http://www.boost.org/doc/libs/1_46_1/libs/serialization/doc/serialization.html#constructors
      50             :                     // instead
      51        1102 :     }
      52             :     size_t idx{0};
      53             :     T state;
      54             : 
      55             : private:
      56             :     ////////////////////////////////////////////////////////////////////
      57             :     /// Method for serialization ///////////////////////////////////////
      58             :     ////////////////////////////////////////////////////////////////////
      59             : 
      60             :     friend class cereal::access;
      61             : 
      62             :     template <class Archive>
      63        1102 :     void serialize(Archive &ar, unsigned int /* version */) {
      64        1102 :         ar &CEREAL_NVP(idx) & CEREAL_NVP(state);
      65        1102 :     }
      66             : };
      67             : 
      68             : #ifndef SWIG
      69             : 
      70             : namespace utils {
      71             : template <class T>
      72             : struct hash<enumerated_state<T>> {
      73          48 :     size_t operator()(enumerated_state<T> const &s) const { return std::hash<T>{}(s.state); }
      74             : };
      75             : } // namespace utils
      76             : 
      77             : #endif
      78             : 
      79             : template <class T>
      80             : struct states_set {
      81             :     typedef typename boost::multi_index_container<
      82             :         enumerated_state<T>,
      83             :         boost::multi_index::indexed_by<
      84             :             boost::multi_index::random_access<>,
      85             :             boost::multi_index::hashed_unique<
      86             :                 boost::multi_index::member<enumerated_state<T>, T, &enumerated_state<T>::state>,
      87             :                 std::hash<T>>>>
      88             :         type;
      89             : };
      90             : 
      91             : namespace cereal {
      92             : 
      93             : template <class Archive, typename Value, typename IndexSpecifierList, typename Allocator>
      94           0 : void save(
      95             :     Archive &ar,
      96             :     boost::multi_index::multi_index_container<Value, IndexSpecifierList, Allocator> const &vector) {
      97           0 :     ar(make_size_tag(static_cast<size_type>(vector.size())));
      98           0 :     for (auto &&v : vector) {
      99           0 :         ar(v);
     100             :     }
     101           0 : }
     102             : 
     103             : template <class Archive, typename Value, typename IndexSpecifierList, typename Allocator>
     104          20 : void load(Archive &ar,
     105             :           boost::multi_index::multi_index_container<Value, IndexSpecifierList, Allocator> &vector) {
     106             :     size_type size;
     107          20 :     ar(make_size_tag(size));
     108          20 :     vector.reserve(static_cast<size_type>(size));
     109        1122 :     for (size_type i = 0; i < size; ++i) {
     110        2204 :         Value v;
     111        1102 :         ar(v);
     112        1102 :         vector.push_back(v);
     113             :     }
     114          20 : }
     115             : 
     116             : } // namespace cereal
     117             : 
     118             : template <class Scalar, class State>
     119             : class SystemBase {
     120             : public:
     121         385 :     virtual ~SystemBase() = default;
     122             : 
     123             :     void setMinimalNorm(const double &threshold);
     124             : 
     125             :     ////////////////////////////////////////////////////////////////////
     126             :     /// Methods to restrict the number of states inside the basis //////
     127             :     ////////////////////////////////////////////////////////////////////
     128             : 
     129             :     void restrictEnergy(double e_min, double e_max);
     130             : 
     131             :     void restrictN(int n_min, int n_max);
     132             : 
     133             :     void restrictN(std::set<int> n);
     134             : 
     135             :     void restrictL(int l_min, int l_max);
     136             : 
     137             :     void restrictL(std::set<int> l);
     138             : 
     139             :     void restrictJ(float j_min, float j_max);
     140             : 
     141             :     void restrictJ(std::set<float> j);
     142             : 
     143             :     void restrictM(float m_min, float m_max);
     144             : 
     145             :     void restrictM(std::set<float> m);
     146             : 
     147             :     ////////////////////////////////////////////////////////////////////
     148             :     /// Method for adding user-defined states //////////////////////////
     149             :     ////////////////////////////////////////////////////////////////////
     150             : 
     151             :     void addStates(const State &s);
     152             : 
     153             :     void addStates(const std::set<State> &s);
     154             : 
     155             :     // TODO make it possible to just use added states, i.e. use no restrictions on quantum numbers
     156             :     // and energies
     157             : 
     158             :     ////////////////////////////////////////////////////////////////////
     159             :     /// Methods to get overlaps ////////////////////////////////////////
     160             :     ////////////////////////////////////////////////////////////////////
     161             : 
     162             :     Eigen::VectorX<double> getOverlap(const State &generalizedstate);
     163             : 
     164             :     Eigen::VectorX<double> getOverlap(const std::vector<State> &generalizedstates);
     165             : 
     166             :     Eigen::VectorX<double> getOverlap(const size_t &state_index);
     167             : 
     168             :     Eigen::VectorX<double> getOverlap(const std::vector<size_t> &states_indices);
     169             : 
     170             :     Eigen::VectorX<double> getOverlap(const State &generalizedstate,
     171             :                                       std::array<double, 3> to_z_axis,
     172             :                                       std::array<double, 3> to_y_axis);
     173             : 
     174             :     Eigen::VectorX<double> getOverlap(const std::vector<State> &generalizedstates,
     175             :                                       std::array<double, 3> to_z_axis,
     176             :                                       std::array<double, 3> to_y_axis);
     177             : 
     178             :     Eigen::VectorX<double> getOverlap(const size_t &state_index, std::array<double, 3> to_z_axis,
     179             :                                       std::array<double, 3> to_y_axis);
     180             : 
     181             :     Eigen::VectorX<double> getOverlap(const std::vector<size_t> &states_indices,
     182             :                                       std::array<double, 3> to_z_axis,
     183             :                                       std::array<double, 3> to_y_axis);
     184             : 
     185             :     Eigen::VectorX<double> getOverlap(const State &generalizedstate, double alpha, double beta,
     186             :                                       double gamma);
     187             : 
     188             :     Eigen::VectorX<double> getOverlap(const size_t &state_index, double alpha, double beta,
     189             :                                       double gamma);
     190             : 
     191             :     Eigen::VectorX<double> getOverlap(const std::vector<State> &generalizedstates, double alpha,
     192             :                                       double beta, double gamma);
     193             : 
     194             :     Eigen::VectorX<double> getOverlap(const std::vector<size_t> &states_indices, double alpha,
     195             :                                       double beta, double gamma);
     196             : 
     197             :     ////////////////////////////////////////////////////////////////////
     198             :     /// Methods to get properties of the system ////////////////////////
     199             :     ////////////////////////////////////////////////////////////////////
     200             : 
     201             :     std::vector<State> getStates();
     202             : 
     203             :     const typename states_set<State>::type &getStatesMultiIndex();
     204             : 
     205             :     Eigen::SparseMatrix<Scalar> &getBasisvectors();
     206             : 
     207             :     Eigen::SparseMatrix<Scalar> &getHamiltonian();
     208             : 
     209             :     size_t getNumBasisvectors();
     210             : 
     211             :     size_t getNumStates();
     212             : 
     213             :     std::vector<State> getMainStates();
     214             : 
     215             :     std::array<std::vector<size_t>, 2> getConnections(SystemBase<Scalar, State> &system_to,
     216             :                                                       double threshold);
     217             : 
     218             :     ////////////////////////////////////////////////////////////////////
     219             :     /// Methods to build, transform, and destroy the system ////////////
     220             :     ////////////////////////////////////////////////////////////////////
     221             : 
     222             :     void buildHamiltonian();
     223             : 
     224             :     void buildInteraction();
     225             : 
     226             :     void buildBasis();
     227             : 
     228             :     void diagonalize(double energy_lower_bound, double energy_upper_bound);
     229             : 
     230             :     void diagonalize(double energy_lower_bound, double energy_upper_bound, double threshold);
     231             : 
     232             :     void diagonalize();
     233             : 
     234             :     void diagonalize(double threshold);
     235             : 
     236             :     void canonicalize();
     237             : 
     238             :     void unitarize();
     239             : 
     240             :     void rotate(std::array<double, 3> to_z_axis, std::array<double, 3> to_y_axis);
     241             : 
     242             :     void rotate(double alpha, double beta, double gamma);
     243             : 
     244             :     void add(SystemBase<Scalar, State> &system);
     245             : 
     246             :     void constrainBasisvectors(std::vector<size_t> indices_of_wanted_basisvectors);
     247             : 
     248             :     void applySchriefferWolffTransformation(SystemBase<Scalar, State> &system0);
     249             : 
     250             :     ////////////////////////////////////////////////////////////////////
     251             :     /// Methods to manipulate entries of the Hamiltonian ///////////////
     252             :     ////////////////////////////////////////////////////////////////////
     253             : 
     254             :     size_t getStateIndex(const State &searched_state);
     255             : 
     256             :     std::vector<size_t> getStateIndex(const std::vector<State> &searched_states);
     257             : 
     258             :     size_t getBasisvectorIndex(const State &searched_state);
     259             : 
     260             :     std::vector<size_t> getBasisvectorIndex(const std::vector<State> &searched_states);
     261             : 
     262             :     void forgetStatemixing();
     263             : 
     264             :     Scalar getHamiltonianEntry(const State &state_row, const State &state_col);
     265             : 
     266             :     void setHamiltonianEntry(const State &state_row, const State &state_col, Scalar value);
     267             : 
     268             :     void addHamiltonianEntry(const State &state_row, const State &state_col, Scalar value);
     269             : 
     270             : protected:
     271             :     SystemBase();
     272             : 
     273             :     SystemBase(MatrixElementCache &cache);
     274             : 
     275             :     SystemBase(MatrixElementCache &cache, bool memory_saving);
     276             : 
     277             :     virtual void initializeBasis() = 0;
     278             :     virtual void initializeInteraction() = 0;
     279             : 
     280             :     virtual void transformInteraction(const Eigen::SparseMatrix<Scalar> &transformator) = 0;
     281             :     virtual void addInteraction() = 0;
     282             :     virtual void deleteInteraction() = 0;
     283             : 
     284             :     virtual Eigen::SparseMatrix<Scalar> rotateStates(const std::vector<size_t> &states_indices,
     285             :                                                      double alpha, double beta, double gamma) = 0;
     286             :     virtual Eigen::SparseMatrix<Scalar> buildStaterotator(double alpha, double beta,
     287             :                                                           double gamma) = 0;
     288             :     virtual void incorporate(SystemBase<Scalar, State> &system) = 0;
     289             : 
     290           0 :     virtual void onStatesChange(){};
     291             : 
     292             :     MatrixElementCache *m_cache{nullptr};
     293             : 
     294             :     double threshold_for_sqnorm{0.05};
     295             : 
     296             :     double energy_min, energy_max;
     297             :     std::set<int> range_n, range_l;
     298             :     std::set<float> range_j, range_m;
     299             :     std::set<State> states_to_add;
     300             : 
     301             :     bool memory_saving{false};
     302             :     bool is_interaction_already_contained{false};
     303             :     bool is_new_hamiltonian_required{false};
     304             : 
     305             :     typename states_set<State>::type states;
     306             :     Eigen::SparseMatrix<Scalar> basisvectors;
     307             :     Eigen::SparseMatrix<Scalar> hamiltonian;
     308             :     Eigen::SparseMatrix<Scalar> basisvectors_unperturbed_cache;
     309             :     Eigen::SparseMatrix<Scalar> hamiltonian_unperturbed_cache;
     310             : 
     311             :     ////////////////////////////////////////////////////////////////////
     312             :     /// Helper method that shoul be called by the derived classes //////
     313             :     ////////////////////////////////////////////////////////////////////
     314             : 
     315             :     void onParameterChange();
     316             : 
     317             :     void onSymmetryChange();
     318             : 
     319             :     ////////////////////////////////////////////////////////////////////
     320             :     /// Helper methods to check diagonality and unitarity of a matrix //
     321             :     ////////////////////////////////////////////////////////////////////
     322             : 
     323             :     bool checkIsDiagonal(const Eigen::SparseMatrix<Scalar> &mat);
     324             : 
     325             :     bool checkIsUnitary(const Eigen::SparseMatrix<Scalar> &mat);
     326             : 
     327             :     ////////////////////////////////////////////////////////////////////
     328             :     /// Helper methods to check the validity of states /////////////////
     329             :     ////////////////////////////////////////////////////////////////////
     330             : 
     331             :     template <class V>
     332           0 :     bool checkIsQuantumnumberValid(V q, std::set<V> range_q) {
     333           0 :         return range_q.empty() || range_q.find(q) != range_q.end();
     334             :     }
     335             : 
     336             :     bool checkIsQuantumstateValid(const State &state);
     337             : 
     338             :     bool checkIsQuantumstateValid(const StateOne &state, bool a);
     339             : 
     340             :     bool checkIsQuantumstateValid(const StateTwo &state, std::array<bool, 2> a);
     341             : 
     342             :     bool checkIsEnergyValid(double e);
     343             : 
     344             :     ////////////////////////////////////////////////////////////////////
     345             :     /// Helper methods to change the set of basis vectors //////////////
     346             :     ////////////////////////////////////////////////////////////////////
     347             : 
     348             :     void applyLeftsideTransformator(std::vector<Eigen::Triplet<Scalar>> &triplets_transformator);
     349             : 
     350             :     void applyLeftsideTransformator(Eigen::SparseMatrix<Scalar> &transformator);
     351             : 
     352             :     void applyRightsideTransformator(std::vector<Eigen::Triplet<Scalar>> &triplets_transformator);
     353             : 
     354             :     void applyRightsideTransformator(Eigen::SparseMatrix<Scalar> &transformator);
     355             : 
     356             :     void
     357             :     removeRestrictedStates(std::function<bool(const enumerated_state<State> &)> checkIsValidEntry);
     358             : 
     359             :     ////////////////////////////////////////////////////////////////////
     360             :     /// Utility methods ////////////////////////////////////////////////
     361             :     ////////////////////////////////////////////////////////////////////
     362             : 
     363             :     template <class V>
     364        2428 :     void range(std::set<V> &rset, V rmin, V rmax) {
     365        2428 :         rset.clear();
     366        9535 :         for (V r = rmin; r <= rmax; ++r) {
     367        7107 :             rset.insert(r);
     368             :         }
     369        2428 :     }
     370             : 
     371             :     Eigen::Matrix<double, 3, 3> buildRotator(std::array<double, 3> to_z_axis,
     372             :                                              std::array<double, 3> to_y_axis);
     373             : 
     374             :     Eigen::Matrix<double, 3, 3> buildRotator(const double &alpha, const double &beta,
     375             :                                              const double &gamma);
     376             : 
     377             :     Eigen::Matrix<double, 3, 1> getEulerAngles(const std::array<double, 3> &to_z_axis,
     378             :                                                const std::array<double, 3> &to_y_axis);
     379             : 
     380             : private:
     381             :     void forgetRestrictions();
     382             : 
     383             :     ////////////////////////////////////////////////////////////////////
     384             :     /// Method to update the system ////////////////////////////////////
     385             :     ////////////////////////////////////////////////////////////////////
     386             : 
     387             :     void updateEverything();
     388             : 
     389             :     ////////////////////////////////////////////////////////////////////
     390             :     /// Method for serialization ///////////////////////////////////////
     391             :     ////////////////////////////////////////////////////////////////////
     392             : 
     393             :     friend class cereal::access;
     394             : 
     395             :     template <class Archive>
     396          20 :     void serialize(Archive &ar, unsigned int /*version*/) {
     397          20 :         ar &cereal::make_nvp("cache", *m_cache) & CEREAL_NVP(threshold_for_sqnorm);
     398          20 :         ar &CEREAL_NVP(energy_min) & CEREAL_NVP(energy_max) & CEREAL_NVP(range_n) &
     399          40 :             CEREAL_NVP(range_l) & CEREAL_NVP(range_j) & CEREAL_NVP(range_m) &
     400          20 :             CEREAL_NVP(states_to_add);
     401          20 :         ar &CEREAL_NVP(memory_saving) & CEREAL_NVP(is_interaction_already_contained) &
     402          20 :             CEREAL_NVP(is_new_hamiltonian_required);
     403          20 :         ar &CEREAL_NVP(states) & CEREAL_NVP(basisvectors) & CEREAL_NVP(hamiltonian);
     404          20 :         ar &CEREAL_NVP(basisvectors_unperturbed_cache) & CEREAL_NVP(hamiltonian_unperturbed_cache);
     405          20 :     }
     406             : };
     407             : 
     408             : extern template class SystemBase<std::complex<double>, StateOne>;
     409             : extern template class SystemBase<std::complex<double>, StateTwo>;
     410             : extern template class SystemBase<double, StateOne>;
     411             : extern template class SystemBase<double, StateTwo>;
     412             : 
     413             : #endif

Generated by: LCOV version 1.14