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 #include <util/class/scexception.h>
00033 #include <chemistry/qc/mbptr12/orbitalspace.h>
00034 #include <chemistry/qc/mbptr12/pairiter.h>
00035
00036 #ifndef _chemistry_qc_mbptr12_utilsimpl_h
00037 #define _chemistry_qc_mbptr12_utilsimpl_h
00038
00039 namespace sc {
00040
00041 template <PureSpinCase2 spin>
00042 RefSCMatrix spinadapt(const RefSCMatrix &A,
00043 const Ref<OrbitalSpace> &bra,
00044 const Ref<OrbitalSpace> &ket){
00045 SpatialMOPairIter_eq ij_iter(bra);
00046 SpatialMOPairIter_eq kl_iter(ket);
00047 const unsigned int brablock_size_ab = ij_iter.nij_ab();
00048 const unsigned int ketblock_size_ab = kl_iter.nij_ab();
00049 if (A.rowdim().n()%brablock_size_ab)
00050 throw ProgrammingError("sc::spinadapt() -- row dimension is not integer multiple of bra-space rank",__FILE__,__LINE__);
00051 if (A.coldim().n()%ketblock_size_ab)
00052 throw ProgrammingError("sc::spinadapt() -- col dimension is not integer multiple of ket-space rank",__FILE__,__LINE__);
00053 const unsigned int nbra_blocks = A.rowdim().n() / brablock_size_ab;
00054 const unsigned int nket_blocks = A.coldim().n() / ketblock_size_ab;
00055 const unsigned int brablock_size_aa = ij_iter.nij_aa();
00056 const unsigned int ketblock_size_aa = kl_iter.nij_aa();
00057 RefSCMatrix Aspinadapted(A.rowdim(),A.coldim(),A->kit());
00058 const double one_divby_sqrt_two=1.0/sqrt(2.0);
00059 unsigned int bra_offset_ab = 0;
00060 unsigned int bra_offset_aa = 0;
00061 for(int brablock=0; brablock<nbra_blocks; brablock++, bra_offset_ab += brablock_size_ab, bra_offset_aa += brablock_size_aa) {
00062 for(ij_iter.start();int(ij_iter);ij_iter.next()) {
00063
00064 const int ij_ab = ij_iter.ij_ab();
00065
00066 unsigned int ket_offset_ab = 0;
00067 unsigned int ket_offset_aa = 0;
00068 for(int ketblock=0; ketblock<nket_blocks; ketblock++, ket_offset_ab += ketblock_size_ab, ket_offset_aa += ketblock_size_aa) {
00069 for(kl_iter.start();int(kl_iter);kl_iter.next()) {
00070
00071 const int kl_ab = kl_iter.ij_ab();
00072 const int lk_ab = kl_iter.ij_ba();
00073 double Aspinadapted_element;
00074
00075 if(spin==Singlet){
00076 double prefactor=1.0;
00077 if(ij_iter.i()==ij_iter.j()) {
00078 prefactor*=one_divby_sqrt_two;
00079 }
00080 if(kl_iter.i()==kl_iter.j()) {
00081 prefactor*=one_divby_sqrt_two;
00082 }
00083
00084 Aspinadapted_element=prefactor*(A.get_element(ij_ab+bra_offset_ab,kl_ab+ket_offset_ab)+A.get_element(ij_ab+bra_offset_ab,lk_ab+ket_offset_ab));
00085 }
00086 else if(spin==Triplet){
00087 Aspinadapted_element=A.get_element(ij_ab+bra_offset_ab,kl_ab+ket_offset_ab)-A.get_element(ij_ab+bra_offset_ab,lk_ab+ket_offset_ab);
00088 }
00089 else {
00090 throw ProgrammingError("sc::spinadapt() -- PureSpinCase2 spin is not adeqate",__FILE__,__LINE__);
00091 }
00092
00093 Aspinadapted.set_element(ij_ab+bra_offset_ab,kl_ab+ket_offset_ab,Aspinadapted_element);
00094 }
00095 }
00096 }
00097 }
00098
00099 return(Aspinadapted);
00100 }
00101
00102 template <bool accumulate>
00103 void
00104 antisymmetrize(RefSCMatrix& Aanti, const RefSCMatrix& A,
00105 const Ref<OrbitalSpace>& bra1,
00106 const Ref<OrbitalSpace>& bra2,
00107 const Ref<OrbitalSpace>& ket1,
00108 const Ref<OrbitalSpace>& ket2)
00109 {
00110 const bool bra1_eq_bra2 = (bra1 == bra2);
00111 const bool ket1_eq_ket2 = (ket1 == ket2);
00112 if (!bra1_eq_bra2 && !ket1_eq_ket2)
00113 throw ProgrammingError("sc::antisymmetrize() -- the operation does not make sense: bra1!=bra2, ket1!=ket2",__FILE__,__LINE__);
00114
00115 SpatialMOPairIter* ij_iter;
00116 SpatialMOPairIter* kl_iter;
00117 if (!bra1_eq_bra2)
00118 ij_iter = new SpatialMOPairIter_neq(bra1,bra2);
00119 else
00120 ij_iter = new SpatialMOPairIter_eq(bra1);
00121 if (!ket1_eq_ket2)
00122 kl_iter = new SpatialMOPairIter_neq(ket1,ket2);
00123 else
00124 kl_iter = new SpatialMOPairIter_eq(ket1);
00125
00126 const unsigned int brablock_size_ab = ij_iter->nij_ab();
00127 const unsigned int ketblock_size_ab = kl_iter->nij_ab();
00128 const unsigned int brablock_size_aa = ij_iter->nij_aa();
00129 const unsigned int ketblock_size_aa = kl_iter->nij_aa();
00130 if (brablock_size_ab==0 || ketblock_size_ab==0)
00131 return;
00132 if (A.rowdim().n()%brablock_size_ab)
00133 throw ProgrammingError("sc::antisymmetrize() -- row dimension of Source is not integer multiple of bra-space rank",__FILE__,__LINE__);
00134 if (A.coldim().n()%ketblock_size_ab)
00135 throw ProgrammingError("sc::antisymmetrize() -- col dimension of Source is not integer multiple of ket-space rank",__FILE__,__LINE__);
00136 if (Aanti.rowdim().n()%brablock_size_aa)
00137 throw ProgrammingError("sc::antisymmetrize() -- row dimension of Result is not integer multiple of bra-space rank",__FILE__,__LINE__);
00138 if (Aanti.coldim().n()%ketblock_size_aa)
00139 throw ProgrammingError("sc::antisymmetrize() -- col dimension of Result is not integer multiple of ket-space rank",__FILE__,__LINE__);
00140 const unsigned int nbra_blocks = A.rowdim().n() / brablock_size_ab;
00141 const unsigned int nket_blocks = A.coldim().n() / ketblock_size_ab;
00142 if (Aanti.rowdim().n() / brablock_size_aa != nbra_blocks)
00143 throw ProgrammingError("sc::antisymmetrize() -- bra dimensions of Source and Result do not match",__FILE__,__LINE__);
00144 if (Aanti.coldim().n() / ketblock_size_aa != nket_blocks)
00145 throw ProgrammingError("sc::antisymmetrize() -- ket dimensions of Source and Result do not match",__FILE__,__LINE__);
00146
00147 unsigned int bra_offset_ab = 0;
00148 unsigned int bra_offset_aa = 0;
00149 for(int brablock=0; brablock<nbra_blocks; brablock++, bra_offset_ab += brablock_size_ab, bra_offset_aa += brablock_size_aa) {
00150 for(ij_iter->start();int(*ij_iter);ij_iter->next()) {
00151
00152 const int ij_aa = ij_iter->ij_aa();
00153 if (ij_aa == -1)
00154 continue;
00155 const int ij_ab = ij_iter->ij_ab();
00156 const int ji_ab = ij_iter->ij_ba();
00157
00158 unsigned int ket_offset_ab = 0;
00159 unsigned int ket_offset_aa = 0;
00160 for(int ketblock=0; ketblock<nket_blocks; ketblock++, ket_offset_ab += ketblock_size_ab, ket_offset_aa += ketblock_size_aa) {
00161 for(kl_iter->start();int(*kl_iter);kl_iter->next()) {
00162
00163 const int kl_aa = kl_iter->ij_aa();
00164 if (kl_aa == -1)
00165 continue;
00166 const int kl_ab = kl_iter->ij_ab();
00167 const int lk_ab = kl_iter->ij_ba();
00168
00169 double Aanti_ijkl = (ket1_eq_ket2) ?
00170 A.get_element(ij_ab+bra_offset_ab,kl_ab+ket_offset_ab) -
00171 A.get_element(ij_ab+bra_offset_ab,lk_ab+ket_offset_ab)
00172 :
00173 A.get_element(ij_ab+bra_offset_ab,kl_ab+ket_offset_ab) -
00174 A.get_element(ji_ab+bra_offset_ab,kl_ab+ket_offset_ab);
00175 if (accumulate)
00176 Aanti.accumulate_element(ij_aa+bra_offset_aa,kl_aa+ket_offset_aa,Aanti_ijkl);
00177 else
00178 Aanti.set_element(ij_aa+bra_offset_aa,kl_aa+ket_offset_aa,Aanti_ijkl);
00179 }
00180 }
00181 }
00182 }
00183
00184 delete ij_iter;
00185 delete kl_iter;
00186 }
00187
00188 template <bool accumulate>
00189 void
00190 antisymmetrize(RefSymmSCMatrix& Aanti, const RefSymmSCMatrix& A,
00191 const Ref<OrbitalSpace>& bra1)
00192 {
00193 SpatialMOPairIter* ij_iter = new SpatialMOPairIter_eq(bra1);
00194 SpatialMOPairIter* kl_iter = new SpatialMOPairIter_eq(bra1);
00195
00196 const unsigned int block_size_ab = ij_iter->nij_ab();
00197 const unsigned int block_size_aa = ij_iter->nij_aa();
00198 if (block_size_ab==0)
00199 return;
00200 if (A.dim().n()%block_size_ab)
00201 throw ProgrammingError("sc::antisymmetrize() -- dimension of Source is not integer multiple of (bra1->rank)^2",__FILE__,__LINE__);
00202 if (Aanti.dim().n()%block_size_aa)
00203 throw ProgrammingError("sc::antisymmetrize() -- dimension of Result is not integer multiple of (bra1->rank * (bra1->rank-1)/2)",__FILE__,__LINE__);
00204 const unsigned int nblocks = A.dim().n() / block_size_ab;
00205 if (Aanti.dim().n() / block_size_aa != nblocks)
00206 throw ProgrammingError("sc::antisymmetrize() -- dimensions of Source and Result do not match",__FILE__,__LINE__);
00207
00208 unsigned int bra_offset_ab = 0;
00209 unsigned int bra_offset_aa = 0;
00210 for(unsigned int brablock=0; brablock<nblocks; brablock++, bra_offset_ab += block_size_ab, bra_offset_aa += block_size_aa) {
00211 for(ij_iter->start();int(*ij_iter);ij_iter->next()) {
00212
00213 const int ij_aa = ij_iter->ij_aa();
00214 if (ij_aa == -1)
00215 continue;
00216 const int ij_ab = ij_iter->ij_ab();
00217 const int ji_ab = ij_iter->ij_ba();
00218
00219 unsigned int ket_offset_ab = 0;
00220 unsigned int ket_offset_aa = 0;
00221 for(unsigned int ketblock=0; ketblock<nblocks; ketblock++, ket_offset_ab += block_size_ab, ket_offset_aa += block_size_aa) {
00222 for(kl_iter->start();int(*kl_iter);kl_iter->next()) {
00223
00224 const int kl_aa = kl_iter->ij_aa();
00225 if (kl_aa == -1)
00226 continue;
00227 const int kl_ab = kl_iter->ij_ab();
00228 const int lk_ab = kl_iter->ij_ba();
00229
00230 double Aanti_ijkl = A.get_element(ij_ab+bra_offset_ab,kl_ab+ket_offset_ab) -
00231 A.get_element(ij_ab+bra_offset_ab,lk_ab+ket_offset_ab);
00232 if (accumulate)
00233 Aanti.accumulate_element(ij_aa+bra_offset_aa,kl_aa+ket_offset_aa,Aanti_ijkl);
00234 else
00235 Aanti.set_element(ij_aa+bra_offset_aa,kl_aa+ket_offset_aa,Aanti_ijkl);
00236 }
00237 }
00238 }
00239 }
00240
00241 delete ij_iter;
00242 delete kl_iter;
00243 }
00244
00245 template <bool Accumulate>
00246 void symmetrize(RefSCMatrix& Asymm, const RefSCMatrix& A,
00247 const Ref<OrbitalSpace>& bra,
00248 const Ref<OrbitalSpace>& ket)
00249 {
00250 if (A.rowdim().n() != Asymm.rowdim().n())
00251 throw ProgrammingError("sc::symmetrize() -- source and target matrices have different row dimensions",__FILE__,__LINE__);
00252 if (A.coldim().n() != Asymm.coldim().n())
00253 throw ProgrammingError("sc::symmetrize() -- source and target matrices have different column dimensions",__FILE__,__LINE__);
00254 SpatialMOPairIter_eq ij_iter(bra);
00255 SpatialMOPairIter_eq kl_iter(ket);
00256 const unsigned int brablock_size_ab = ij_iter.nij_ab();
00257 const unsigned int ketblock_size_ab = kl_iter.nij_ab();
00258 if (A.rowdim().n()%brablock_size_ab)
00259 throw ProgrammingError("sc::symmetrize() -- row dimension is not integer multiple of bra-space rank",__FILE__,__LINE__);
00260 if (A.coldim().n()%ketblock_size_ab)
00261 throw ProgrammingError("sc::symmetrize() -- col dimension is not integer multiple of ket-space rank",__FILE__,__LINE__);
00262 const unsigned int nbra_blocks = A.rowdim().n() / brablock_size_ab;
00263 const unsigned int nket_blocks = A.coldim().n() / ketblock_size_ab;
00264
00265 unsigned int bra_offset_ab = 0;
00266 for(int brablock=0; brablock<nbra_blocks; brablock++, bra_offset_ab += brablock_size_ab) {
00267 for(ij_iter.start();int(ij_iter);ij_iter.next()) {
00268
00269 const unsigned int IJ_ab = ij_iter.ij_ab() + bra_offset_ab;
00270 const unsigned int JI_ab = ij_iter.ij_ba() + bra_offset_ab;
00271
00272 unsigned int ket_offset_ab = 0;
00273 for(int ketblock=0; ketblock<nket_blocks; ketblock++, ket_offset_ab += ketblock_size_ab) {
00274 for(kl_iter.start();int(kl_iter);kl_iter.next()) {
00275
00276 const unsigned int KL_ab = kl_iter.ij_ab() + ket_offset_ab;
00277 const unsigned int LK_ab = kl_iter.ij_ba() + ket_offset_ab;
00278
00279 const double A_ijkl = A.get_element(IJ_ab,KL_ab);
00280 const double A_ijlk = A.get_element(IJ_ab,LK_ab);
00281 const double A_jikl = A.get_element(JI_ab,KL_ab);
00282 const double A_jilk = A.get_element(JI_ab,LK_ab);
00283
00284 {
00285 const double Asymm_ijkl = 0.5 * (A_ijkl + A_jilk);
00286 if (Accumulate) {
00287 Asymm.accumulate_element(IJ_ab,KL_ab,Asymm_ijkl);
00288 Asymm.accumulate_element(JI_ab,LK_ab,Asymm_ijkl);
00289 }
00290 else {
00291 Asymm.set_element(IJ_ab,KL_ab,Asymm_ijkl);
00292 Asymm.set_element(JI_ab,LK_ab,Asymm_ijkl);
00293 }
00294 }
00295 {
00296 const double Asymm_ijlk = 0.5 * (A_ijlk + A_jikl);
00297 if (Accumulate) {
00298 Asymm.accumulate_element(IJ_ab,LK_ab,Asymm_ijlk);
00299 Asymm.accumulate_element(JI_ab,KL_ab,Asymm_ijlk);
00300 }
00301 else {
00302 Asymm.set_element(IJ_ab,LK_ab,Asymm_ijlk);
00303 Asymm.set_element(JI_ab,KL_ab,Asymm_ijlk);
00304 }
00305 }
00306
00307 }
00308 }
00309 }
00310 }
00311
00312 }
00313
00314 template <bool Accumulate, sc::fastpairiter::PairSymm BraSymm, sc::fastpairiter::PairSymm KetSymm>
00315 void symmetrize12(RefSCMatrix& Asymm, const RefSCMatrix& A,
00316 const Ref<OrbitalSpace>& bra1,
00317 const Ref<OrbitalSpace>& bra2,
00318 const Ref<OrbitalSpace>& ket1,
00319 const Ref<OrbitalSpace>& ket2)
00320 {
00321 using namespace sc::fastpairiter;
00322 using sc::fastpairiter::MOPairIter;
00323
00324
00325 if ( (BraSymm == AntiSymm && KetSymm == AntiSymm) ||
00326 (BraSymm == Symm && KetSymm == Symm) )
00327 throw ProgrammingError("sc::symmetrize12() -- the matrix is already symmetric",__FILE__,__LINE__);
00328 if ( (BraSymm == AntiSymm || BraSymm == Symm) && bra1 != bra2)
00329 throw ProgrammingError("sc::symmetrize12() -- bra dimension is anti/symmetrized, but bra1!=bra2",__FILE__,__LINE__);
00330 if ( (KetSymm == AntiSymm || KetSymm == Symm) && ket1 != ket2)
00331 throw ProgrammingError("sc::symmetrize12() -- ket dimension is anti/symmetrized, but ket1!=ket2",__FILE__,__LINE__);
00332
00333 if (A.rowdim().n() != Asymm.rowdim().n())
00334 throw ProgrammingError("sc::symmetrize() -- source and target matrices have different row dimensions",__FILE__,__LINE__);
00335 if (A.coldim().n() != Asymm.coldim().n())
00336 throw ProgrammingError("sc::symmetrize() -- source and target matrices have different column dimensions",__FILE__,__LINE__);
00337 MOPairIter<BraSymm> ij_iter(bra1->rank(),bra2->rank());
00338 MOPairIter<KetSymm> kl_iter(ket1->rank(),ket2->rank());
00339 const unsigned int brablock_size = ij_iter.nij();
00340 const unsigned int ketblock_size = kl_iter.nij();
00341 if (A.rowdim().n()%brablock_size)
00342 throw ProgrammingError("sc::symmetrize() -- row dimension is not integer multiple of bra-space rank",__FILE__,__LINE__);
00343 if (A.coldim().n()%ketblock_size)
00344 throw ProgrammingError("sc::symmetrize() -- col dimension is not integer multiple of ket-space rank",__FILE__,__LINE__);
00345 const unsigned int nbra_blocks = A.rowdim().n() / brablock_size;
00346 const unsigned int nket_blocks = A.coldim().n() / ketblock_size;
00347
00348 unsigned int bra_offset = 0;
00349 for(int brablock=0; brablock<nbra_blocks; brablock++, bra_offset += brablock_size) {
00350 for(ij_iter.start();int(ij_iter);ij_iter.next()) {
00351
00352 const unsigned int IJ = ij_iter.ij() + bra_offset;
00353 const unsigned int JI = (BraSymm == ASymm) ? ij_iter.ij(ij_iter.j(),ij_iter.i()) + bra_offset
00354 : IJ;
00355 const double ij_permfac = (BraSymm == AntiSymm) ? -1.0 : 1.0;
00356
00357 unsigned int ket_offset = 0;
00358 for(int ketblock=0; ketblock<nket_blocks; ketblock++, ket_offset += ketblock_size) {
00359 for(kl_iter.start();int(kl_iter);kl_iter.next()) {
00360
00361 const unsigned int KL = kl_iter.ij() + ket_offset;
00362 const unsigned int LK = (KetSymm == ASymm) ? kl_iter.ij(kl_iter.j(),kl_iter.i()) + ket_offset
00363 : KL;
00364 const double kl_permfac = (KetSymm == AntiSymm) ? -1.0 : 1.0;
00365
00366 const double A_ijkl = A.get_element(IJ,KL);
00367 const double A_jilk = A.get_element(JI,LK);
00368 const double Asymm_ijkl = 0.5 * (A_ijkl + ij_permfac*kl_permfac*A_jilk);
00369
00370 if (Accumulate)
00371 Asymm.accumulate_element(IJ,KL,Asymm_ijkl);
00372 else
00373 Asymm.set_element(IJ,KL,Asymm_ijkl);
00374
00375 }
00376 }
00377 }
00378 }
00379
00380 }
00381
00382 template <bool Accumulate,
00383 sc::fastpairiter::PairSymm SrcBraSymm, sc::fastpairiter::PairSymm SrcKetSymm,
00384 sc::fastpairiter::PairSymm DstBraSymm, sc::fastpairiter::PairSymm DstKetSymm
00385 >
00386 void symmetrize(RefSCMatrix& Asymm, const RefSCMatrix& A,
00387 const Ref<OrbitalSpace>& bra1,
00388 const Ref<OrbitalSpace>& bra2,
00389 const Ref<OrbitalSpace>& ket1,
00390 const Ref<OrbitalSpace>& ket2)
00391 {
00392 using namespace sc::fastpairiter;
00393 using sc::fastpairiter::MOPairIter;
00394
00395
00396 if (SrcBraSymm == DstBraSymm && SrcKetSymm == DstKetSymm)
00397 throw ProgrammingError("sc::symmetrize() -- nothing to be done",__FILE__,__LINE__);
00398 if ( (SrcBraSymm != ASymm && SrcKetSymm != ASymm) )
00399 throw ProgrammingError("sc::symmetrize() -- either bra of ket must be asymmetric",__FILE__,__LINE__);
00400 if ( (SrcBraSymm != ASymm && SrcBraSymm != DstBraSymm) )
00401 throw ProgrammingError("sc::symmetrize() -- can only change bra that is asymmetric",__FILE__,__LINE__);
00402 if ( (SrcKetSymm != ASymm && SrcKetSymm != DstKetSymm) )
00403 throw ProgrammingError("sc::symmetrize() -- can only change ket that is asymmetric",__FILE__,__LINE__);
00404 if (DstBraSymm!=ASymm && bra1 != bra2)
00405 throw ProgrammingError("sc::symmetrize12() -- bra is to be anti/symmetrized, but bra1!=bra2",__FILE__,__LINE__);
00406 if (DstKetSymm!=ASymm && ket1 != ket2)
00407 throw ProgrammingError("sc::symmetrize12() -- ket is to be anti/symmetrized, but ket1!=ket2",__FILE__,__LINE__);
00408 const bool transform_bra = DstBraSymm != ASymm && DstBraSymm != SrcBraSymm;
00409 const bool transform_ket = DstKetSymm != ASymm && DstKetSymm != SrcKetSymm;
00410
00411 MOPairIter<SrcBraSymm> ij_srciter(bra1->rank(),bra2->rank());
00412 MOPairIter<SrcKetSymm> kl_srciter(ket1->rank(),ket2->rank());
00413 MOPairIter<DstBraSymm> ij_dstiter(bra1->rank(),bra2->rank());
00414 MOPairIter<DstKetSymm> kl_dstiter(ket1->rank(),ket2->rank());
00415 const unsigned int brablock_size_src = ij_srciter.nij();
00416 const unsigned int ketblock_size_src = kl_srciter.nij();
00417 const unsigned int brablock_size_dst = ij_dstiter.nij();
00418 const unsigned int ketblock_size_dst = kl_dstiter.nij();
00419 if (A.rowdim().n()%brablock_size_src)
00420 throw ProgrammingError("sc::symmetrize() -- row dimension of Source is not integer multiple of bra-space rank",__FILE__,__LINE__);
00421 if (A.coldim().n()%ketblock_size_src)
00422 throw ProgrammingError("sc::symmetrize() -- col dimension of Source is not integer multiple of ket-space rank",__FILE__,__LINE__);
00423 if (Asymm.rowdim().n()%brablock_size_dst)
00424 throw ProgrammingError("sc::symmetrize() -- row dimension of Result is not integer multiple of bra-space rank",__FILE__,__LINE__);
00425 if (Asymm.coldim().n()%ketblock_size_dst)
00426 throw ProgrammingError("sc::symmetrize() -- col dimension of Result is not integer multiple of ket-space rank",__FILE__,__LINE__);
00427 const unsigned int nbra_blocks = A.rowdim().n() / brablock_size_src;
00428 const unsigned int nket_blocks = A.coldim().n() / ketblock_size_src;
00429 if (nbra_blocks != Asymm.rowdim().n() / brablock_size_dst)
00430 throw ProgrammingError("sc::symmetrize() -- # of bra blocks in Source and Result do not match",__FILE__,__LINE__);
00431 if (nket_blocks != Asymm.coldim().n() / ketblock_size_dst)
00432 throw ProgrammingError("sc::symmetrize() -- # of bra blocks in Source and Result do not match",__FILE__,__LINE__);
00433
00434 unsigned int bra_offset_src = 0;
00435 unsigned int bra_offset_dst = 0;
00436 for(int brablock=0; brablock<nbra_blocks;
00437 brablock++, bra_offset_src += brablock_size_src, bra_offset_dst += brablock_size_dst) {
00438 for(ij_dstiter.start();int(ij_dstiter);ij_dstiter.next()) {
00439
00440 const unsigned int IJ_dst = ij_dstiter.ij() + bra_offset_dst;
00441
00442 const unsigned int I = ij_srciter.i();
00443 const unsigned int J = ij_srciter.j();
00444 const unsigned IJ = ij_srciter.ij(I,J) + bra_offset_src;
00445 unsigned int JI;
00446 double ij_permfac;
00447 if (transform_bra) {
00448 JI = ij_srciter.ij(J,I) + bra_offset_src;
00449 ij_permfac = (DstBraSymm == AntiSymm) ? -1.0 : 1.0;
00450 }
00451
00452 unsigned int ket_offset_src = 0;
00453 unsigned int ket_offset_dst = 0;
00454 for(int ketblock=0; ketblock<nket_blocks;
00455 ketblock++, ket_offset_src += ketblock_size_src, ket_offset_dst += ketblock_size_dst) {
00456 for(kl_dstiter.start();int(kl_dstiter);kl_dstiter.next()) {
00457
00458 const unsigned int KL_dst = kl_dstiter.ij() + ket_offset_dst;
00459
00460 const unsigned int K = kl_srciter.i();
00461 const unsigned int L = kl_srciter.j();
00462 const unsigned int KL = kl_srciter.ij(K,L) + ket_offset_src;
00463 unsigned int LK;
00464 double kl_permfac;
00465 if (transform_ket) {
00466 LK = kl_srciter.ij(L,K) + ket_offset_src;
00467 kl_permfac = (DstKetSymm == AntiSymm) ? -1.0 : 1.0;
00468 }
00469
00470 double Asymm_ijkl;
00471 if (transform_bra) {
00472 const double A_ijkl = A.get_element(IJ,KL);
00473 const double A_jikl = A.get_element(JI,KL);
00474 Asymm_ijkl = A_ijkl + ij_permfac*A_jikl;
00475 }
00476 if (transform_ket) {
00477 const double A_ijkl = A.get_element(IJ,KL);
00478 const double A_ijlk = A.get_element(IJ,LK);
00479 Asymm_ijkl = A_ijkl + kl_permfac*A_ijlk;
00480 }
00481 if (transform_bra && transform_ket) {
00482 const double A_ijkl = A.get_element(IJ,KL);
00483 const double A_jikl = A.get_element(JI,KL);
00484 const double A_ijlk = A.get_element(IJ,LK);
00485 const double A_jilk = A.get_element(JI,LK);
00486 Asymm_ijkl = A_ijkl + ij_permfac*A_jikl + kl_permfac*A_ijlk + ij_permfac*kl_permfac*A_jilk;
00487 }
00488
00489 if (Accumulate)
00490 Asymm.accumulate_element(IJ_dst,KL_dst,Asymm_ijkl);
00491 else
00492 Asymm.set_element(IJ_dst,KL_dst,Asymm_ijkl);
00493
00494 }
00495 }
00496 }
00497 }
00498
00499 }
00500
00501 }
00502
00503 #endif
00504