forked from sanshar/Block
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathBaseOperator.h
295 lines (276 loc) · 14.1 KB
/
BaseOperator.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
/*
Developed by Sandeep Sharma and Garnet K.-L. Chan, 2012
Copyright (c) 2012, Garnet K.-L. Chan
This program is integrated in Molpro with the permission of
Sandeep Sharma and Garnet K.-L. Chan
*/
#ifndef SPIN_BASEOPERATOR_HEADER
#define SPIN_BASEOPERATOR_HEADER
#include <cmath>
#include <boost/function.hpp>
#include <boost/functional.hpp>
#include <boost/bind.hpp>
#include <boostutils.h>
#include "SpinQuantum.h"
#include "ObjectMatrix.h"
#include "csf.h"
#include "StateInfo.h"
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/base_object.hpp>
//FIXME
#include <boost/serialization/map.hpp>
#include <boost/serialization/string.hpp>
//<<
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
class TensorOp;
namespace SpinAdapted{
class SpinBlock;
//when bra and ket states are different then DES cannot be made by just taking the transpose of
//CRE. In such a case we need to explicitly make the operators in the second row.
enum opTypes{ HAM, CRE, CRE_CRE, DES_DESCOMP, CRE_DES, CRE_DESCOMP, CRE_CRE_DESCOMP,
DES, DES_DES, CRE_CRECOMP, DES_CRE, DES_CRECOMP, CRE_DES_DESCOMP, OVERLAP,
// Extra (empty) operator classes for RI-approx NPDM
RI_3INDEX, RI_4INDEX,
// Extra 3PDM operators
CRE_CRE_CRE, CRE_CRE_DES, CRE_DES_DES, CRE_DES_CRE,
// Extra 4PDM operators
DES_CRE_DES, DES_DES_CRE, DES_CRE_CRE, DES_DES_DES,
CRE_CRE_DES_DES, CRE_DES_CRE_DES, CRE_DES_DES_CRE, CRE_DES_DES_DES,
CRE_CRE_CRE_DES, CRE_CRE_DES_CRE, CRE_DES_CRE_CRE, CRE_CRE_CRE_CRE };
enum CompType{CD, DD, CCD, C, CDD};
template<class T> class Baseoperator // The abstract class of an operator
{
public:
virtual bool get_fermion() const = 0;
virtual int nrows() const = 0;
virtual int ncols() const = 0;
virtual bool get_initialised() const = 0;
virtual const std::vector<int>& get_orbs() const = 0;
virtual int get_orbs(int i) const = 0;
virtual const char& allowed(int i, int j) const = 0;
virtual char& allowed(int i, int j) = 0;
virtual T& operator_element(int i, int j) = 0;
virtual const T& operator_element(int i, int j) const = 0;
virtual T& operator()(int i, int j) = 0;
virtual const T& operator()(int i, int j) const = 0;
virtual int get_deltaQuantum_size() const = 0;
virtual std::vector<SpinQuantum> get_deltaQuantum() const = 0;
virtual SpinQuantum get_deltaQuantum(int i) const = 0;
virtual char conjugacy() const = 0;
virtual ~Baseoperator() {};
virtual SpinSpace get_spin(int i=0) const = 0;
virtual IrrepSpace get_symm(int i=0) const = 0;
virtual double get_scaling(SpinQuantum leftq, SpinQuantum rightq) const = 0;
Baseoperator() {};
};
class SparseMatrix : public Baseoperator<Matrix> // the sparse matrix representation of the operator
{
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & orbs \
& deltaQuantum \
& quantum_ladder \
& build_pattern \
& fermion \
& initialised \
& built \
& built_on_disk \
& allowedQuantaMatrix \
& quantum_ladder \
& build_pattern \
& operatorMatrix \
& Sign;
}
protected:
std::vector<int> orbs;
bool fermion;
ObjectMatrix<char> allowedQuantaMatrix; // some whether it is allowed?
bool initialised;
bool built;
bool built_on_disk;
ObjectMatrix<Matrix> operatorMatrix; // put the dense block in the place it should be
std::vector<SpinQuantum> deltaQuantum; // allowed quantum
int Sign;
// With N-index ops (N>2), there are several ways to build them...
std::string build_pattern;
// ...and for each way we record the spin ladder components
std::map< std::string, std::vector<SpinQuantum> > quantum_ladder;
public:
SparseMatrix() : fermion(false), orbs(2), initialised(false), built(false), built_on_disk(false), Sign(1){};
virtual ~SparseMatrix(){};
int nrows() const { return allowedQuantaMatrix.nrows(); }
int ncols() const { return allowedQuantaMatrix.ncols(); }
int nrows(char conj) const { return allowedQuantaMatrix.Nrows(conj); }
char conjugacy() const { return 'n'; }
int get_sign() const {return Sign;}
int ncols(char conj) const { return allowedQuantaMatrix.Ncols(conj); }
bool get_initialised() const { return initialised; }
bool &set_initialised() { return initialised; }
bool get_fermion() const { return fermion; }
bool &set_fermion() { return fermion; }
const char& allowed(int i, int j) const { return allowedQuantaMatrix(i, j); }
char& allowed(int i, int j) { return allowedQuantaMatrix(i, j); }
std::vector<SpinQuantum> &set_deltaQuantum() { return deltaQuantum; }
SpinQuantum &set_deltaQuantum(int i) { return deltaQuantum[i]; }
void resize_deltaQuantum(int i) { deltaQuantum.resize(i); }
void set_deltaQuantum(int i, const SpinQuantum s) { deltaQuantum.assign(i, s); }
int get_deltaQuantum_size() const { return deltaQuantum.size(); }
SpinSpace get_spin(int i=0) const { return deltaQuantum[i].get_s();}
IrrepSpace get_symm(int i=0) const { return deltaQuantum[i].get_symm();}
std::vector<SpinQuantum> get_deltaQuantum() const { return deltaQuantum; }
std::map< std::string, std::vector<SpinQuantum> > get_quantum_ladder() const { return quantum_ladder; }
std::map< std::string, std::vector<SpinQuantum> >& set_quantum_ladder() { return quantum_ladder; }
std::string get_build_pattern() const { return build_pattern; }
std::string& set_build_pattern() { return build_pattern; }
SpinQuantum get_deltaQuantum(int i) const { return deltaQuantum[i]; }
int get_orbs(int i) const
{
if(i >= orbs.size())
return -1;
else
return orbs[i];
}
double memoryUsed(const SpinBlock& b);
const std::vector<int>& get_orbs() const { return orbs; }
std::vector<int>& set_orbs() { return orbs; }
const bool& get_built() const { return built; }
bool& set_built() { return built; }
const bool& get_built_on_disk() const { return built_on_disk; }
bool& set_built_on_disk() { return built_on_disk; }
double get_scaling(SpinQuantum leftq, SpinQuantum rightq) const {return 1.0;}
void resize(int n, int c) { operatorMatrix.ReSize(n, c); allowedQuantaMatrix.ReSize(n, c); }
const Matrix& operator_element(int i, int j) const { return operatorMatrix(i, j); }
const Matrix& operator()(int i, int j) const { return operatorMatrix(i, j); }
Matrix& operator_element(int i, int j) { return operatorMatrix(i, j); }
Matrix& operator()(int i, int j) { return operatorMatrix(i, j); }
void allocate(const StateInfo& s);
void allocate(const StateInfo& sr, const StateInfo& sc);
void allocate(const SpinBlock& b);
void makeIdentity(const StateInfo& s);
virtual boost::shared_ptr<SparseMatrix> getworkingrepresentation(const SpinBlock* block) =0;
virtual void build(const SpinBlock& b) =0;
void buildUsingCsf(const SpinBlock& b, vector< vector<Csf> >& ladders, std::vector< Csf >& s) ;
virtual double redMatrixElement(Csf c1, vector<Csf>& ladder, const SpinBlock* b=0)=0;
double calcCompfactor(TensorOp& Top1, TensorOp& op2, CompType comp, const TwoElectronArray& v_2, int integralIndex);
double calcCompfactor(TensorOp& Top1, TensorOp& op2, CompType comp, const CCCCArray& vcccc);
double calcCompfactor(TensorOp& Top1, TensorOp& op2, CompType comp, const CCCDArray& vcccd);
double calcCompfactor(TensorOp& Top1, TensorOp& op2, CompType comp, int op2index, const TwoElectronArray& v_2, int integralIndex);
double calcCompfactor(TensorOp& Top1, TensorOp& op2, CompType comp, int op2index, const CCCCArray& vcccc);
double calcCompfactor(TensorOp& Top1, TensorOp& op2, CompType comp, int op2index, const CCCDArray& vcccd);
bool nonZeroTensorComponent(Csf& c1, SpinQuantum& opsym, Csf& ladder, int& nonzeroindex, double& cleb);
std::vector<double> calcMatrixElements(Csf& c1, TensorOp& Top, Csf& c2);
friend ostream& operator<<(ostream& os, const SparseMatrix& a);
void Randomise();
void SymmetricRandomise();
void Normalise(int* success);
void Clear();
void CleanUp();
void Save(std::ofstream &ofs) const
{
boost::archive::binary_oarchive save_op(ofs);
save_op << *this;
}
void Load(std::istream &ifs)
{
boost::archive::binary_iarchive load_op(ifs);
load_op >> *this;
}
void OperatorMatrixReference(ObjectMatrix<Matrix*>& m, const std::vector<int>& oldToNewStateI, const std::vector<int>& oldToNewStateJ);
void renormalise_transform(const std::vector<Matrix>& rotate_matrix, const StateInfo *stateinfo);
void build_and_renormalise_transform(SpinBlock *big, const opTypes &ot, const std::vector<Matrix>& rotate_matrix,
const StateInfo *newStateInfo);
void renormalise_transform(const std::vector<Matrix>& leftrotate_matrix, const StateInfo* leftstateinfo, const std::vector<Matrix>& rightrotate_matrix, const StateInfo *rightstateinfo);
void build_and_renormalise_transform(SpinBlock *big, const opTypes &ot, const std::vector<Matrix>& leftrotate_matrix, const StateInfo *leftstateinfo,
const std::vector<Matrix>& rightrotate_matrix, const StateInfo *newStateInfo);
SparseMatrix& operator+=(const SparseMatrix& other);
};
class Transposeview : public SparseMatrix
{
private:
boost::shared_ptr<SparseMatrix> opdata;
public:
Transposeview(const boost::shared_ptr<SparseMatrix>& opptr) : opdata(opptr) {}
Transposeview(SparseMatrix& op) { opdata = boost::shared_ptr<SparseMatrix>(&op, boostutils::null_deleter());}
int get_deltaQuantum_size() const { return opdata->get_deltaQuantum_size(); }
SpinQuantum get_deltaQuantum(int i) const {return -opdata->get_deltaQuantum(i);}
std::vector<SpinQuantum> get_deltaQuantum() const {
std::vector<SpinQuantum> q;
for (int i = 0; i < opdata->get_deltaQuantum_size(); ++i) {
q.push_back(-opdata->get_deltaQuantum(i));
}
return q;
}
bool get_fermion() const { return opdata->get_fermion(); }
bool get_initialised() const { return opdata->get_initialised(); }
int nrows() const { return opdata->ncols(); }
int ncols() const { return opdata->nrows(); }
const char &allowed(int i, int j) const { return opdata->allowed(j, i); }
char &allowed(int i, int j) { return opdata->allowed(j, i); }
const Matrix& operator_element(int i, int j) const { return opdata->operator_element(j, i); }
Matrix& operator_element(int i, int j) { return opdata->operator_element(j, i); }
SpinSpace get_spin(int i=0) const { return opdata->get_deltaQuantum(i).get_s();}
IrrepSpace get_symm(int i=0) const { return -opdata->get_deltaQuantum(i).get_symm();}
int get_orbs(int i) const {return opdata->get_orbs(i);}
const std::vector<int>& get_orbs() const { return opdata->get_orbs(); }
const Matrix& operator()(int i, int j) const { return opdata->operator()(j, i); }
Matrix& operator()(int i, int j) { return opdata->operator()(j, i); }
char conjugacy() const { if (opdata->conjugacy() == 'n') return 't'; else return 'n';}
double get_scaling(SpinQuantum leftq, SpinQuantum rightq) const ;
boost::shared_ptr<SparseMatrix> getworkingrepresentation(const SpinBlock* block) {return opdata;}
void build(const SpinBlock& b){};
double redMatrixElement(Csf c1, vector<Csf>& ladder, const SpinBlock* b){return 0.0;}
};
class SubSparseMatrix : public SparseMatrix
{
private:
boost::shared_ptr<SparseMatrix> opdata;
int section;
ObjectMatrix<char> SuballowedQuantaMatrix;
public:
SubSparseMatrix(SparseMatrix& op, int sec, const StateInfo& s);
SubSparseMatrix(const boost::shared_ptr<SparseMatrix>& opptr, int sec, const StateInfo& s);
SubSparseMatrix(const boost::shared_ptr<SparseMatrix>& opptr, int sec, const StateInfo& sr, const StateInfo& sc);
std::vector<SpinQuantum> get_deltaQuantum() const {
std::vector<SpinQuantum> deltaQuantum(1, opdata->get_deltaQuantum(section));
return deltaQuantum;
}
int get_deltaQuantum_size() const {return 1;}
SpinQuantum get_deltaQuantum(int i) const {
return get_deltaQuantum()[0]; // this i is dummy
}
bool get_fermion() const { return opdata->get_fermion(); }
bool get_initialised() const { return opdata->get_initialised(); }
int nrows() const { return opdata->nrows(); }
int ncols() const { return opdata->ncols(); }
const char &allowed(int i, int j) const { return SuballowedQuantaMatrix(i, j); }
char &allowed(int i, int j) { return SuballowedQuantaMatrix(i, j); }
const Matrix& operator_element(int i, int j) const { return opdata->operator_element(i, j); }
Matrix& operator_element(int i, int j) { return opdata->operator_element(i, j); }
SpinSpace get_spin(int i=0) const { return opdata->get_deltaQuantum(section).get_s();}
IrrepSpace get_symm(int i=0) const { return -opdata->get_deltaQuantum(section).get_symm();}
int get_orbs(int i) const {return opdata->get_orbs(i);}
const std::vector<int>& get_orbs() const { return opdata->get_orbs(); }
const Matrix& operator()(int i, int j) const { return opdata->operator()(i, j); }
Matrix& operator()(int i, int j) { return opdata->operator()(i, j); }
char conjugacy() const { return opdata->conjugacy(); }
double get_scaling(SpinQuantum leftq, SpinQuantum rightq) const { return 1.0; }
boost::shared_ptr<SparseMatrix> getworkingrepresentation(const SpinBlock* block) {return opdata;}
void build(const SpinBlock& b){};
double redMatrixElement(Csf c1, vector<Csf>& ladder, const SpinBlock* b){return 0.0;}
};
const Transposeview Transpose(SparseMatrix& op);
double getCommuteParity(SpinQuantum a, SpinQuantum b, SpinQuantum c);
void Normalise(SparseMatrix& a, int* success = 0);
void ScaleAdd(double d, const SparseMatrix& a, SparseMatrix& b);
double DotProduct(const SparseMatrix& lhs, const SparseMatrix& rhs);
double trace(const SparseMatrix& lhs);
void Scale(double d, SparseMatrix& a);
void assignloopblock(SpinBlock*& loopblock, SpinBlock*& otherblock, SpinBlock* leftSpinBlock, SpinBlock* rightSpinBlock);
void copy(const ObjectMatrix<Matrix>& a, ObjectMatrix<Matrix>& b);
void copy(const Matrix& a, Matrix& b);
}
#endif