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 __GNUG__
00029 #pragma interface
00030 #endif
00031
00032 #ifndef _chemistry_qc_mbptr12_orbitalspace_h
00033 #define _chemistry_qc_mbptr12_orbitalspace_h
00034
00035 #include <vector>
00036 #include <stdexcept>
00037 #include <algorithm>
00038 #include <util/ref/ref.h>
00039 #include <util/state/statein.h>
00040 #include <util/state/stateout.h>
00041 #include <util/group/thread.h>
00042 #include <math/scmat/abstract.h>
00043 #include <util/state/statein.h>
00044 #include <chemistry/qc/basis/basis.h>
00045 #include <chemistry/qc/mbptr12/spin.h>
00046 #include <chemistry/qc/mbptr12/registry.h>
00047
00048 using namespace std;
00049
00050 namespace sc {
00051
00053 template <typename Attributes>
00054 class DecoratedOrbital {
00055 public:
00056 DecoratedOrbital(size_t index, const Attributes& attr) : index_(index), attr_(attr) {}
00057
00058 size_t index() const { return index_; }
00059 const Attributes& attr() const { return attr_; }
00060
00061 private:
00062 size_t index_;
00063 Attributes attr_;
00064 };
00065
00067 typedef DecoratedOrbital< unsigned int > BlockedOrbital;
00068
00069 namespace detail {
00071 struct MolecularOrbitalAttributes {
00072 public:
00073 MolecularOrbitalAttributes(unsigned int irrep, double energy,
00074 double occnum) :
00075 irrep_(irrep), energy_(energy), occnum_(occnum) {
00076 }
00077
00078 unsigned int irrep() const {
00079 return irrep_;
00080 }
00081 double energy() const {
00082 return energy_;
00083 }
00084 double occnum() const {
00085 return occnum_;
00086 }
00087
00088 private:
00089 unsigned int irrep_;
00090 double energy_;
00091 double occnum_;
00092 };
00094 struct MolecularSpinOrbitalAttributes : public MolecularOrbitalAttributes {
00095 public:
00096 MolecularSpinOrbitalAttributes(unsigned int irrep,
00097 double energy,
00098 double occnum,
00099 SpinCase1 spin) :
00100 MolecularOrbitalAttributes(irrep, energy, occnum), spin_(spin)
00101 {}
00102
00103 SpinCase1 spin() const { return spin_; }
00104
00105 private:
00106 SpinCase1 spin_;
00107 };
00108 }
00109
00110 typedef DecoratedOrbital< detail::MolecularOrbitalAttributes > MolecularOrbital;
00111 typedef DecoratedOrbital< detail::MolecularSpinOrbitalAttributes > MolecularSpinOrbital;
00112
00114 struct SymmetryMOOrder {
00115 public:
00116 SymmetryMOOrder(unsigned int nirreps) : nirreps_(nirreps) {}
00117
00118 bool operator()(const MolecularOrbital& o1, const MolecularOrbital& o2) const {
00119 if (o1.attr().irrep() < o2.attr().irrep())
00120 return true;
00121 else if (o1.attr().irrep() == o2.attr().irrep()) {
00122 if (o1.attr().energy() < o2.attr().energy())
00123 return true;
00124 else if (o1.attr().energy() == o2.attr().energy()) {
00125 if (o1.attr().occnum() < o2.attr().occnum())
00126 return true;
00127 }
00128 }
00129 return false;
00130 }
00131 unsigned int block(const MolecularOrbital& o) const {
00132 return o.attr().irrep();
00133 }
00134 unsigned int nblocks() const {
00135 return nirreps_;
00136 }
00137
00138 private:
00139 unsigned int nirreps_;
00140 };
00141
00143 struct EnergyMOOrder {
00144 public:
00145 bool operator()(const MolecularOrbital& o1, const MolecularOrbital& o2) const {
00146 if (o1.attr().energy() < o2.attr().energy())
00147 return true;
00148 else if (o1.attr().energy() == o2.attr().energy()) {
00149 if (o1.attr().irrep() < o2.attr().irrep())
00150 return true;
00151 }
00152 return false;
00153 }
00154 unsigned int block(const MolecularOrbital& o) const {
00155 return 1;
00156 }
00157 unsigned int nblocks() const {
00158 return 1;
00159 }
00160 };
00161
00163 struct CorrelatedMOOrder {
00164 public:
00165 CorrelatedMOOrder(unsigned int nirreps) : nirreps_(nirreps) {}
00166
00167 bool operator()(const MolecularOrbital& o1, const MolecularOrbital& o2) const {
00168
00169 if (o1.attr().occnum() > o2.attr().occnum())
00170 return true;
00171 else if (o1.attr().occnum() == o2.attr().occnum()) {
00172 if (o1.attr().irrep() < o2.attr().irrep())
00173 return true;
00174 else if (o1.attr().irrep() == o2.attr().irrep()) {
00175 if (o1.attr().energy() < o2.attr().energy())
00176 return true;
00177 }
00178 }
00179 return false;
00180 }
00181
00182 unsigned int block(const MolecularOrbital& o) const {
00183 const unsigned int irrep = o.attr().irrep();
00184 const double occnum = o.attr().occnum();
00185
00186 const int occblock = (occnum == 1.0) ? 0 : 1;
00187 return occblock * nirreps_ + irrep;
00188 }
00189 unsigned int nblocks() const {
00190 return nirreps_ * 2;
00191 }
00192
00193 private:
00194 unsigned int nirreps_;
00195 };
00196
00198 struct CorrelatedSpinMOOrder {
00199 public:
00200 CorrelatedSpinMOOrder(unsigned int nirreps) : nirreps_(nirreps) {}
00201
00202 bool operator()(const MolecularSpinOrbital& o1, const MolecularSpinOrbital& o2) const {
00203
00204 if (o1.attr().occnum() > o2.attr().occnum())
00205 return true;
00206 else if (o1.attr().occnum() == o2.attr().occnum()) {
00207 if (o1.attr().spin() < o2.attr().spin())
00208 return true;
00209 else if (o1.attr().spin() == o2.attr().spin()) {
00210 if (o1.attr().irrep() < o2.attr().irrep())
00211 return true;
00212 else if (o1.attr().irrep() == o2.attr().irrep()) {
00213 if (o1.attr().energy() < o2.attr().energy())
00214 return true;
00215 }
00216 }
00217 }
00218 return false;
00219 }
00220
00221 unsigned int block(const MolecularSpinOrbital& o) const {
00222 const unsigned int irrep = o.attr().irrep();
00223 const SpinCase1 spin = o.attr().spin();
00224 const unsigned int spincase = (spin == Alpha) ? 0 : 1;
00225 const double occnum = o.attr().occnum();
00226 const unsigned int occblock = (occnum == 1.0) ? 0 : 1;
00227
00228 const unsigned int result = (occblock * 2 + spincase) * nirreps_ + irrep;
00229 return result;
00230 }
00231 unsigned int nblocks() const {
00232 return nirreps_ * 4;
00233 }
00234
00235 private:
00236 unsigned int nirreps_;
00237 };
00238
00239 namespace detail {
00240
00241 template <typename Container> struct ContainerAdaptor {
00242 public:
00243 typedef typename Container::value_type value_type;
00244 ContainerAdaptor(const Container& cont) : cont_(cont) {}
00245 size_t size() const { return cont_.size(); }
00246 value_type elem(size_t i) const { return cont_[i]; }
00247
00248 private:
00249 const Container& cont_;
00250 };
00251
00252 template<> struct ContainerAdaptor<RefDiagSCMatrix> {
00253 public:
00254 typedef RefDiagSCMatrix Container;
00255 typedef double value_type;
00256 ContainerAdaptor(const Container& cont) : cont_(cont) {}
00257 size_t size() const { return cont_.dim().n(); }
00258 value_type elem(size_t i) const { return cont_(i); }
00259
00260 private:
00261 const Container& cont_;
00262 };
00263
00264 }
00265
00267 template <typename Attribute,
00268 typename AttributeContainer,
00269 typename Compare = std::less<Attribute> >
00270 struct MolecularOrbitalMask {
00271 private:
00272 typedef DecoratedOrbital<Attribute> MO;
00273 struct _compare {
00274 bool operator()(const MO& mo1,
00275 const MO& mo2) const {
00276 Compare comp;
00277 return comp(mo1.attr(), mo2.attr());
00278 }
00279 };
00280
00281 public:
00282 MolecularOrbitalMask(unsigned int n,
00283 const AttributeContainer& attributes) :
00284 mask_(detail::ContainerAdaptor<AttributeContainer>(attributes).size(),true)
00285 {
00286
00287 if (n == 0) return;
00288 const size_t nmos = mask_.size();
00289 assert(n < nmos);
00290
00291
00292 std::vector<MO> mos;
00293 detail::ContainerAdaptor<AttributeContainer> contadaptor(attributes);
00294 for(size_t mo=0; mo<nmos; ++mo) {
00295 mos.push_back(MO(mo,contadaptor.elem(mo)));
00296 }
00297
00298
00299 _compare comp;
00300 std::stable_sort(mos.begin(), mos.end(), comp);
00301
00302
00303 for(unsigned int t=0; t<n; ++t) {
00304 mask_[ mos[t].index() ] = false;
00305 }
00306 }
00307
00308 const std::vector<bool>& mask() const { return mask_; }
00309
00310 private:
00311 std::vector<bool> mask_;
00312 };
00313
00314
00316
00325 class OrbitalSpace: virtual public SavableState {
00326
00327 public:
00328
00330 enum IndexOrder {
00331 symmetry = 0,
00332 energy = 1,
00333 correlated = 2,
00336 general = 3
00337 };
00338
00339 private:
00340
00341 static const unsigned int max_id_length = 30;
00342 std::string id_;
00343 std::string name_;
00344
00345 Ref<GaussianBasisSet> basis_;
00346 Ref<Integral> integral_;
00347 RefSCMatrix coefs_;
00348 RefDiagSCMatrix evals_;
00349 RefSCDimension dim_;
00350 std::vector<unsigned int> orbsym_;
00351 std::vector<unsigned int> block_offsets_;
00352 std::vector<unsigned int> block_sizes_;
00353
00354
00355 void check_orbsym() const;
00356
00357
00358 std::vector<unsigned int>
00359 frozen_to_blockinfo(unsigned int nfzc, unsigned int nfzv,
00360 const RefDiagSCMatrix& evals);
00361
00362
00363
00364 void full_coefs_to_coefs(const RefSCMatrix& full_coefs,
00365 const RefDiagSCMatrix& evals,
00366 const std::vector<unsigned int>& offsets,
00367 IndexOrder moorder);
00369 void init();
00370
00371
00372 static void dquicksort(double *item, unsigned int *index, unsigned int n);
00373
00374 protected:
00376 OrbitalSpace();
00378 void init(const std::string& id, const std::string& name,
00379 const Ref<GaussianBasisSet>& basis, const Ref<Integral>& integral,
00380 const RefSCMatrix& coefs,
00381 const RefDiagSCMatrix& evals,
00382 const std::vector<unsigned int>& orbsyms,
00383 unsigned int nblocks,
00384 const std::vector<BlockedOrbital>& indexmap);
00385
00386 public:
00387 OrbitalSpace(StateIn&);
00389 OrbitalSpace(const OrbitalSpace&);
00405 OrbitalSpace(const std::string& id, const std::string& name,
00406 const RefSCMatrix& full_coefs, const RefDiagSCMatrix& evals,
00407 const Ref<GaussianBasisSet>& basis,
00408 const Ref<Integral>& integral,
00409 const std::vector<unsigned int>& block_offsets,
00410 const std::vector<unsigned int>& block_sizes);
00411
00430 OrbitalSpace(const std::string& id, const std::string& name,
00431 const RefSCMatrix& full_coefs,
00432 const Ref<GaussianBasisSet>& basis,
00433 const Ref<Integral>& integral,
00434 const std::vector<unsigned int>& block_offsets,
00435 const std::vector<unsigned int>& block_sizes,
00436 const IndexOrder& moorder = symmetry,
00437 const RefDiagSCMatrix& evals = 0);
00443 OrbitalSpace(const std::string& id, const std::string& name,
00444 const RefSCMatrix& full_coefs,
00445 const Ref<GaussianBasisSet>& basis,
00446 const Ref<Integral>& integral, const RefDiagSCMatrix& evals,
00447 unsigned int nfzc, unsigned int nfzv,
00448 const IndexOrder& moorder = energy);
00451 OrbitalSpace(const std::string& id, const std::string& name,
00452 const RefSCMatrix& full_coefs,
00453 const Ref<GaussianBasisSet>& basis,
00454 const Ref<Integral>& integral);
00455
00458 OrbitalSpace(const std::string& id, const std::string& name,
00459 const Ref<OrbitalSpace>& orig_space,
00460 const RefSCMatrix& new_coefs,
00461 const Ref<GaussianBasisSet>& new_basis);
00462 ~OrbitalSpace();
00463
00464 void save_data_state(StateOut&);
00465
00466 OrbitalSpace& operator=(const OrbitalSpace& other);
00467
00469 const std::string& name() const;
00471
00479 const std::string& id() const;
00481 const RefSCDimension& dim() const;
00483 const Ref<GaussianBasisSet>& basis() const;
00485 const Ref<Integral>& integral() const;
00487 const RefSCMatrix& coefs() const;
00489 const RefDiagSCMatrix& evals() const;
00491 const vector<unsigned int>& orbsym() const;
00493 unsigned int rank() const;
00495 unsigned int nblocks() const;
00497 const vector<unsigned int>& block_sizes() const;
00498
00500 size_t memory_in_use() const;
00501
00503 void print(std::ostream&o = ExEnv::out0()) const;
00505 void print_summary(std::ostream& os) const;
00507 void print_detail(std::ostream&o = ExEnv::out0()) const;
00508
00509 };
00510
00511 bool operator==(const OrbitalSpace& space1, const OrbitalSpace& space2);
00512
00513 class CannotConstructMap: public std::logic_error {
00514 public:
00515 CannotConstructMap() :
00516 std::logic_error("Cannot map given OrbitalSpaces") {
00517 }
00518 };
00519
00527 typedef std::vector<unsigned int> MOIndexMap;
00528 MOIndexMap operator<<(const OrbitalSpace& space2, const OrbitalSpace& space1);
00529
00537 typedef std::vector<std::pair<unsigned int, double> > SparseMOIndexMap;
00538 SparseMOIndexMap sparsemap(const OrbitalSpace& space2,
00539 const OrbitalSpace& space1, double hardzero =
00540 1e-12);
00541
00551 RefSCMatrix transform(const OrbitalSpace& space2, const OrbitalSpace& space1,
00552 const Ref<SCMatrixKit>& kit =
00553 SCMatrixKit::default_matrixkit());
00554
00560 RefSCMatrix overlap(const OrbitalSpace& space2, const OrbitalSpace& space1,
00561 const Ref<SCMatrixKit>& kit =
00562 SCMatrixKit::default_matrixkit());
00563
00565 bool in(const OrbitalSpace& s1, const OrbitalSpace& s2);
00566
00575 class ParsedOrbitalSpaceKey {
00576 public:
00578 ParsedOrbitalSpaceKey(const std::string& key);
00579
00580 const std::string& key() const {
00581 return key_;
00582 }
00583 const std::string& label() const {
00584 return label_;
00585 }
00586 SpinCase1 spin() const {
00587 return spin_;
00588 }
00589
00590 static std::string key(const std::string& label, SpinCase1 spin);
00591
00592 private:
00593 std::string key_;
00594 std::string label_;
00595 SpinCase1 spin_;
00596 };
00597
00606 class ParsedTransformedOrbitalSpaceKey {
00607 public:
00608 typedef enum {
00609 Fock = 0,
00610 Coulomb = 1,
00611 Exchange = 2,
00612 KineticEnergy = 3,
00613 CoreHamiltonian = 4,
00614 CorePlusCoulomb = 5,
00615 InvalidOneBodyOperator = 6
00616 } OneBodyOperator;
00617 #define ParsedTransformedOrbitalSpaceKey_OneBodyOperatorLabelInitializer {"F", "J", "K", "T", "h", "h+J"}
00618 static const char* OneBodyOperatorLabel[];
00619
00621 ParsedTransformedOrbitalSpaceKey(const std::string& key);
00622
00623 const std::string& key() const {
00624 return key_;
00625 }
00626 const std::string& label() const {
00627 return label_;
00628 }
00629 SpinCase1 spin() const {
00630 return spin_;
00631 }
00632 const std::string& original_label() const {
00633 return original_label_;
00634 }
00635 SpinCase1 original_spin() const {
00636 return spin_;
00637 }
00638 OneBodyOperator transform_operator() const {
00639 return transform_operator_;
00640 }
00641
00642 static std::string key(const std::string& label, SpinCase1 spin,
00643 const std::string& original_label,
00644 SpinCase1 original_spin, OneBodyOperator oper);
00645
00646 private:
00647 std::string key_;
00648 std::string label_;
00649 SpinCase1 spin_;
00650 std::string original_label_;
00651 SpinCase1 original_spin_;
00652 OneBodyOperator transform_operator_;
00653 };
00654
00656 typedef Registry<std::string, Ref<OrbitalSpace> ,
00657 detail::SingletonCreationPolicy> OrbitalSpaceRegistry;
00659 std::pair<std::string, Ref<OrbitalSpace> > make_keyspace_pair(const Ref<
00660 OrbitalSpace>& space, SpinCase1 spin = AnySpinCase1);
00661
00663 typedef Registry<Ref<GaussianBasisSet> , Ref<OrbitalSpace> ,
00664 detail::SingletonCreationPolicy> AOSpaceRegistry;
00665
00667
00672 template <typename Order>
00673 class OrderedOrbitalSpace : public OrbitalSpace {
00674 public:
00675 OrderedOrbitalSpace(const std::string& id, const std::string& name,
00676 const Ref<GaussianBasisSet>& basis,
00677 const Ref<Integral>& integral,
00678 const RefSCMatrix& coefs, const RefDiagSCMatrix& evals,
00679 const RefDiagSCMatrix& occnums,
00680 const std::vector<unsigned int>& orbsyms,
00681 const Order& order);
00682
00683 OrderedOrbitalSpace(StateIn&);
00684 void save_data_state(StateOut&);
00685 ~OrderedOrbitalSpace();
00686
00687 private:
00688
00689 typedef OrderedOrbitalSpace this_type;
00690
00691 static ClassDesc class_desc_;
00692 };
00693
00696 template <typename Order>
00697 class OrderedSpinOrbitalSpace : public OrbitalSpace {
00698 public:
00699 OrderedSpinOrbitalSpace(const std::string& id, const std::string& name,
00700 const Ref<GaussianBasisSet>& basis,
00701 const Ref<Integral>& integral,
00702 const RefSCMatrix& coefs_alpha,
00703 const RefSCMatrix& coefs_beta,
00704 const RefDiagSCMatrix& evals_alpha,
00705 const RefDiagSCMatrix& evals_beta,
00706 const RefDiagSCMatrix& occnums_alpha,
00707 const RefDiagSCMatrix& occnums_beta,
00708 const std::vector<unsigned int>& orbsyms_alpha,
00709 const std::vector<unsigned int>& orbsyms_beta,
00710 const Order& order);
00711
00712 OrderedSpinOrbitalSpace(StateIn&);
00713 void save_data_state(StateOut&);
00714 ~OrderedSpinOrbitalSpace();
00715
00716 private:
00717
00718 typedef OrderedSpinOrbitalSpace this_type;
00719
00720 static ClassDesc class_desc_;
00721 };
00722
00724
00727 class MaskedOrbitalSpace : public OrbitalSpace {
00728 public:
00729 MaskedOrbitalSpace(const std::string& id, const std::string& name,
00730 const Ref<OrbitalSpace>& orig_space,
00731 const std::vector<bool>& mask);
00732
00733 MaskedOrbitalSpace(StateIn&);
00734 void save_data_state(StateOut&);
00735
00736 };
00737
00739
00743 class NonblockedOrbitalSpace : public OrbitalSpace {
00744 public:
00745 NonblockedOrbitalSpace(const std::string& id, const std::string& name,
00746 const Ref<OrbitalSpace>& orig_space);
00747
00748 NonblockedOrbitalSpace(StateIn&);
00749 void save_data_state(StateOut&);
00750
00751 };
00752
00753 }
00754
00755 #include <chemistry/qc/mbptr12/orbitalspace.timpl.h>
00756
00757 #endif
00758
00759
00760
00761
00762
00763
00764