00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef __GNUC__
00029 #pragma interface
00030 #endif
00031
00032 #include <stdexcept>
00033 #include <chemistry/qc/mbptr12/orbitalspace.h>
00034 #include <chemistry/qc/mbptr12/spin.h>
00035
00036 #ifndef _chemistry_qc_mbptr12_pairiter_h
00037 #define _chemistry_qc_mbptr12_pairiter_h
00038
00039 namespace sc {
00040
00042 class MOPairIter : public RefCount {
00043 private:
00045 static const int classdebug_ = 0;
00046
00047 protected:
00048 bool i_eq_j_;
00049 int ni_;
00050 int nj_;
00051 int i_;
00052 int j_;
00053 int nij_;
00054 int ij_;
00055
00056 int classdebug() const {
00057 return classdebug_;
00058 }
00059
00060 public:
00062 MOPairIter(const Ref<OrbitalSpace>& space_i, const Ref<OrbitalSpace>& space_j);
00063 virtual ~MOPairIter();
00064
00066 virtual void start(const int first_ij =0) =0;
00068 virtual void next() =0;
00070 virtual operator int() const =0;
00071
00073 int ni() const { return ni_; }
00075 int nj() const { return nj_; }
00077 int i() const { return i_; }
00079 int j() const { return j_; }
00081 int nij() const { return nij_; }
00083 int ij() const { return ij_; }
00084 };
00085
00086
00089 class SpatialMOPairIter : public MOPairIter {
00090
00091 public:
00093 SpatialMOPairIter(const Ref<OrbitalSpace>& space_i, const Ref<OrbitalSpace>& space_j) :
00094 MOPairIter(space_i,space_j) {};
00095 ~SpatialMOPairIter() {};
00096
00098 virtual int nij_aa() const =0;
00100 virtual int nij_ab() const =0;
00103 virtual int ij_aa() const =0;
00105 virtual int ij_ab() const =0;
00107 virtual int ij_ba() const =0;
00108 };
00109
00113 class SpatialMOPairIter_eq : public SpatialMOPairIter {
00114
00115 int nij_aa_;
00116 int nij_ab_;
00117 int ij_aa_;
00118 int ij_ab_;
00119 int ji_ab_;
00120
00121 void init_ij(const int ij) {
00122
00123 if (ij<0)
00124 throw std::runtime_error("SpatialMOPairIter_eq::start() -- argument ij out of range");
00125
00126 ij_ = 0;
00127 const int renorm_ij = ij%nij_;
00128
00129 i_ = (int)floor((sqrt(1.0+8.0*renorm_ij) - 1.0)/2.0);
00130 const int i_off = i_*(i_+1)/2;
00131 j_ = renorm_ij - i_off;
00132
00133 ij_ab_ = i_*nj_ + j_;
00134 ji_ab_ = j_*ni_ + i_;
00135
00136 if (i_ != 0) {
00137 const int i_off = i_*(i_-1)/2;
00138 ij_aa_ = i_off + j_;
00139 if (i_ == j_)
00140 ij_aa_--;
00141 }
00142 else {
00143 ij_aa_ = -1;
00144 }
00145 };
00146
00147 void inc_ij() {
00148 ij_++;
00149 if (ij_ab_ == nij_ab_-1) {
00150 i_ = 0;
00151 j_ = 0;
00152 ij_ab_ = 0;
00153 ji_ab_ = 0;
00154 ij_aa_ = -1;
00155 }
00156 else {
00157 if (i_ == j_) {
00158 i_++;
00159 j_ = 0;
00160 ji_ab_ = i_;
00161 ij_ab_ = i_*nj_;
00162 ij_aa_ += (i_ == j_) ? 0 : 1;
00163 }
00164 else {
00165 j_++;
00166 ji_ab_ += ni_;
00167 ij_ab_++;
00168 ij_aa_ += (i_ == j_) ? 0 : 1;
00169 }
00170 }
00171 };
00172
00173 public:
00175 SpatialMOPairIter_eq(const Ref<OrbitalSpace>& space1);
00176 ~SpatialMOPairIter_eq();
00177
00179 void start(const int ij_offset=0)
00180 {
00181 ij_ = 0;
00182 init_ij(ij_offset);
00183 };
00184
00186 void next() {
00187 inc_ij();
00188 };
00190 operator int() const { return (nij_ > ij_);};
00191
00193 int nij_aa() const { return nij_aa_; }
00195 int nij_ab() const { return nij_ab_; }
00198 int ij_aa() const { return (i_ == j_) ? -1 : ij_aa_; }
00200 int ij_ab() const { return ij_ab_; }
00202 int ij_ba() const { return ji_ab_; }
00203 };
00204
00205
00208 class SpatialMOPairIter_neq : public SpatialMOPairIter {
00209
00210 int IJ_;
00211
00212 void init_ij(const int ij) {
00213
00214 if (ij<0)
00215 throw std::runtime_error("SpatialMOPairIter_neq::start() -- argument ij out of range");
00216
00217 IJ_ = 0;
00218 const int renorm_ij = ij%nij_;
00219
00220 i_ = renorm_ij/nj_;
00221 j_ = renorm_ij - i_*nj_;
00222
00223 IJ_ = i_*nj_ + j_;
00224
00225 };
00226
00227 void inc_ij() {
00228 ij_++;
00229 IJ_++;
00230 if (IJ_ == nij_) {
00231 i_ = 0;
00232 j_ = 0;
00233 IJ_ = 0;
00234 }
00235 else {
00236 if (j_ == nj_-1) {
00237 i_++;
00238 j_ = 0;
00239 }
00240 else {
00241 j_++;
00242 }
00243 }
00244 };
00245
00246 public:
00248 SpatialMOPairIter_neq(const Ref<OrbitalSpace>& space1, const Ref<OrbitalSpace>& space2);
00249 ~SpatialMOPairIter_neq();
00250
00252 void start(const int ij_offset=0)
00253 {
00254 ij_ = 0;
00255 init_ij(ij_offset);
00256 };
00257
00259 void next() {
00260 inc_ij();
00261 };
00263 operator int() const { return (nij_ > ij_);};
00264
00266 int nij_aa() const { return nij_; }
00268 int nij_ab() const { return nij_; }
00270 int ij_aa() const { return IJ_; }
00272 int ij_ab() const { return IJ_; }
00274 int ij_ba() const { return IJ_; }
00275 };
00276
00277
00281 class SpinMOPairIter : public MOPairIter
00282 {
00283 public:
00285 SpinMOPairIter(const Ref<OrbitalSpace>& space1, const Ref<OrbitalSpace>& space2,
00286 const SpinCase2& S);
00287 ~SpinMOPairIter();
00288
00290 void start(const int first_ij=0);
00292 void next();
00294 operator int() const;
00295
00296 private:
00297 int IJ_;
00298 };
00299
00304 class PureSpinPairIter : public MOPairIter
00305 {
00306 public:
00308 PureSpinPairIter(const Ref<OrbitalSpace>& space,
00309 const PureSpinCase2& S);
00310 ~PureSpinPairIter();
00311
00313 void start(const int first_ij=0);
00315 void next();
00317 operator int() const;
00318
00319 private:
00320 PureSpinCase2 spin_;
00321 int IJ_;
00322 };
00323
00324 namespace fastpairiter {
00325 enum PairSymm { Symm = 1, AntiSymm = -1, ASymm = 0};
00332 template <PairSymm PSymm>
00333 class MOPairIter
00334 {
00335 public:
00336 MOPairIter(int nI, int nJ);
00337 ~MOPairIter();
00338
00340 void start();
00342 void next();
00344 operator int() const;
00346 int ij() const { return IJ_; }
00348 int i() const { return I_; }
00350 int j() const { return J_; }
00354 int ij(int i, int j) const;
00355 int nij() const { return nIJ_; }
00356
00357 private:
00358 int nIJ_;
00359 int IJ_;
00360 int nI_;
00361 int nJ_;
00362 int I_;
00363 int J_;
00364 void init();
00365 };
00366
00368 template <PairSymm PSymm>
00369 RefSCDimension pairdim(int nI, int nJ);
00370
00371 }
00372
00374 class MOPairIterFactory {
00375
00376 public:
00377 MOPairIterFactory() {}
00378 ~MOPairIterFactory() {}
00379
00381 Ref<SpatialMOPairIter> mopairiter(const Ref<OrbitalSpace>& space1, const Ref<OrbitalSpace>& space2);
00383 RefSCDimension scdim_aa(const Ref<OrbitalSpace>& space1, const Ref<OrbitalSpace>& space2);
00385 RefSCDimension scdim_ab(const Ref<OrbitalSpace>& space1, const Ref<OrbitalSpace>& space2);
00386 };
00387
00388 }
00389
00390 #endif
00391
00392
00393
00394
00395