16#include <Eigen/SparseCore>
20template <
typename Derived>
22 this->
matrix = Eigen::SparseMatrix<scalar_t, Eigen::RowMajor>(
23 this->basis->get_number_of_states(), this->basis->get_number_of_states());
26template <
typename Derived>
28 Eigen::SparseMatrix<scalar_t, Eigen::RowMajor> tmp(this->basis->get_number_of_kets(),
29 this->basis->get_number_of_kets());
30 tmp.reserve(Eigen::VectorXi::Constant(this->basis->get_number_of_kets(), 1));
32 for (
const auto &ket : this->basis->get_kets()) {
33 tmp.insert(idx, idx) = ket->get_energy();
39 this->basis->get_coefficients().adjoint() * tmp * this->basis->get_coefficients();
42template <
typename Derived>
44 Eigen::SparseMatrix<scalar_t, Eigen::RowMajor> &&matrix) {
45 if (
static_cast<size_t>(matrix.rows()) != this->basis->get_number_of_states() ||
46 static_cast<size_t>(matrix.cols()) != this->basis->get_number_of_states()) {
47 throw std::invalid_argument(
"The matrix has the wrong dimensions.");
49 this->matrix = std::move(matrix);
52template <
typename Derived>
54 return static_cast<const Derived &
>(*this);
57template <
typename Derived>
59 return static_cast<Derived &
>(*this);
62template <
typename Derived>
67template <
typename Derived>
72template <
typename Derived>
73const Eigen::SparseMatrix<typename Operator<Derived>::scalar_t, Eigen::RowMajor> &
78template <
typename Derived>
79Eigen::SparseMatrix<typename Operator<Derived>::scalar_t, Eigen::RowMajor> &
84template <
typename Derived>
87 return basis->get_transformation();
90template <
typename Derived>
93 return basis->get_rotator(alpha, beta, gamma);
96template <
typename Derived>
98 basis->perform_sorter_checks(labels);
103 std::vector<TransformationType> before_energy(labels.begin(), it);
104 bool contains_energy = (it != labels.end());
105 std::vector<TransformationType> after_energy(contains_energy ? it + 1 : labels.end(),
110 transformation.
matrix.resize(matrix.rows());
111 transformation.
matrix.setIdentity();
114 if (!before_energy.empty()) {
115 basis->get_sorter_without_checks(before_energy, transformation);
119 if (contains_energy) {
120 std::vector<real_t> energies_of_states;
121 energies_of_states.reserve(matrix.rows());
122 for (
int i = 0; i < matrix.rows(); ++i) {
123 energies_of_states.push_back(std::real(matrix.coeff(i, i)));
127 transformation.
matrix.indices().data(),
128 transformation.
matrix.indices().data() + transformation.
matrix.indices().size(),
129 [&](
int i,
int j) { return energies_of_states[i] < energies_of_states[j]; });
135 if (!after_energy.empty()) {
136 basis->get_sorter_without_checks(after_energy, transformation);
141 throw std::invalid_argument(
"The states could not be sorted by all the requested labels.");
144 return transformation;
147template <
typename Derived>
148std::vector<IndicesOfBlock>
150 basis->perform_sorter_checks(labels);
152 std::set<TransformationType> unique_labels(labels.begin(), labels.end());
153 basis->perform_blocks_checks(unique_labels);
157 bool contains_energy = (it != unique_labels.end());
158 if (contains_energy) {
159 unique_labels.erase(it);
166 if (!unique_labels.empty()) {
167 basis->get_indices_of_blocks_without_checks(unique_labels, blocks_creator);
171 if (contains_energy) {
172 scalar_t last_energy = std::real(matrix.coeff(0, 0));
173 for (
int i = 0; i < matrix.rows(); ++i) {
174 if (std::real(matrix.coeff(i, i)) != last_energy) {
175 blocks_creator.add(i);
176 last_energy = std::real(matrix.coeff(i, i));
181 return blocks_creator.create();
184template <
typename Derived>
187 auto transformed = derived();
188 if (matrix.cols() == 0) {
191 transformed.matrix = transformation.matrix.adjoint() * matrix * transformation.matrix;
192 transformed.basis = basis->transformed(transformation);
196template <
typename Derived>
198 auto transformed = derived();
199 if (matrix.cols() == 0) {
202 transformed.matrix = matrix.twistedBy(transformation.
matrix.inverse());
203 transformed.basis = basis->transformed(transformation);
208template <
typename Derived>
210 Derived result = rhs.derived();
211 result.matrix *= lhs;
215template <
typename Derived>
217 Derived result = lhs.derived();
218 result.matrix *= rhs;
222template <
typename Derived>
224 Derived result = lhs.derived();
225 result.matrix /= rhs;
229template <
typename Derived>
232 throw std::invalid_argument(
"The basis of the operators is not the same.");
235 return lhs.derived_mutable();
238template <
typename Derived>
241 throw std::invalid_argument(
"The basis of the operators is not the same.");
244 return lhs.derived_mutable();
247template <
typename Derived>
250 throw std::invalid_argument(
"The basis of the operators is not the same.");
252 Derived result = lhs.derived();
253 result.matrix += rhs.
matrix;
257template <
typename Derived>
260 throw std::invalid_argument(
"The basis of the operators is not the same.");
262 Derived result = lhs.derived();
263 result.matrix -= rhs.
matrix;
269#define INSTANTIATE_OPERATOR_HELPER(SCALAR, TYPE) \
270 template class Operator<TYPE<SCALAR>>; \
271 template TYPE<SCALAR> operator*(const SCALAR &lhs, const Operator<TYPE<SCALAR>> &rhs); \
272 template TYPE<SCALAR> operator*(const Operator<TYPE<SCALAR>> &lhs, const SCALAR &rhs); \
273 template TYPE<SCALAR> operator/(const Operator<TYPE<SCALAR>> &lhs, const SCALAR &rhs); \
274 template TYPE<SCALAR> &operator+=(Operator<TYPE<SCALAR>> &lhs, \
275 const Operator<TYPE<SCALAR>> &rhs); \
276 template TYPE<SCALAR> &operator-=(Operator<TYPE<SCALAR>> &lhs, \
277 const Operator<TYPE<SCALAR>> &rhs); \
278 template TYPE<SCALAR> operator+(const Operator<TYPE<SCALAR>> &lhs, \
279 const Operator<TYPE<SCALAR>> &rhs); \
280 template TYPE<SCALAR> operator-(const Operator<TYPE<SCALAR>> &lhs, \
281 const Operator<TYPE<SCALAR>> &rhs);
282#define INSTANTIATE_OPERATOR(SCALAR) \
283 INSTANTIATE_OPERATOR_HELPER(SCALAR, OperatorAtom) \
284 INSTANTIATE_OPERATOR_HELPER(SCALAR, OperatorPair)
290#undef INSTANTIATE_OPERATOR_HELPER
291#undef INSTANTIATE_OPERATOR
#define INSTANTIATE_OPERATOR(SCALAR)
const Transformation< scalar_t > & get_transformation() const override
typename traits::CrtpTraits< Derived >::real_t real_t
void initialize_as_energy_operator()
std::shared_ptr< const basis_t > basis
Operator(std::shared_ptr< const basis_t > basis)
std::shared_ptr< const basis_t > get_basis() const
Eigen::SparseMatrix< scalar_t, Eigen::RowMajor > matrix
typename traits::CrtpTraits< Derived >::scalar_t scalar_t
Derived transformed(const Transformation< scalar_t > &transformation) const
const Eigen::SparseMatrix< scalar_t, Eigen::RowMajor > & get_matrix() const
std::vector< IndicesOfBlock > get_indices_of_blocks(const std::vector< TransformationType > &labels) const override
Transformation< scalar_t > get_rotator(real_t alpha, real_t beta, real_t gamma) const override
void initialize_from_matrix(Eigen::SparseMatrix< scalar_t, Eigen::RowMajor > &&matrix)
Sorting get_sorter(const std::vector< TransformationType > &labels) const override
Derived operator+(const Operator< Derived > &lhs, const Operator< Derived > &rhs)
Derived & operator-=(Operator< Derived > &lhs, const Operator< Derived > &rhs)
Derived operator*(const typename Operator< Derived >::scalar_t &lhs, const Operator< Derived > &rhs)
Derived & operator+=(Operator< Derived > &lhs, const Operator< Derived > &rhs)
Derived operator/(const Operator< Derived > &lhs, const typename Operator< Derived >::scalar_t &rhs)
Derived operator-(const Operator< Derived > &lhs, const Operator< Derived > &rhs)
Eigen::PermutationMatrix< Eigen::Dynamic, Eigen::Dynamic > matrix
std::vector< TransformationType > transformation_type