Revision | 4c222a5c90c2b3cd72c9585170a8b1973f3e9cd8 (tree) |
---|---|
Zeit | 2011-07-16 20:49:31 |
Autor | Mikiya Fujii <mikiya.fujii@gmai...> |
Commiter | Mikiya Fujii |
Speed up of ZindoS::CalcCISMatrix is carried out.
git-svn-id: https://svn.sourceforge.jp/svnroot/molds/MolDS/trunk@119 1136aad2-a195-0410-b898-f5ea1d11b9d8
@@ -75,6 +75,7 @@ private: | ||
75 | 75 | string errorMessageDavidsonNotConverged; |
76 | 76 | string errorMessageDavidsonMaxIter; |
77 | 77 | string errorMessageDavidsonMaxDim; |
78 | + string errorMessageCalcCISMatrix; | |
78 | 79 | string messageStartCalcCISMatrix; |
79 | 80 | string messageConsumedCalcCISMatrix; |
80 | 81 | string messageDoneCalcCISMatrix; |
@@ -129,6 +130,8 @@ void ZindoS::SetMessages(){ | ||
129 | 130 | this->errorMessageNishimotoMataga = "Error in base_zindo::ZindoS::GetNishimotoMatagaTwoEleInt: Invalid orbitalType.\n"; |
130 | 131 | this->errorMessageMolecularIntegralElement |
131 | 132 | = "Error in zindo::ZindoS::GetMolecularIntegralElement: Non available orbital is contained.\n"; |
133 | + this->errorMessageCalcCISMatrix | |
134 | + = "Error in zindo::ZindoS::CalcCISMatrix: Non available orbital is contained.\n"; | |
132 | 135 | this->errorMessageDavidsonNotConverged = "Error in zindo::ZindoS::DoesCISDavidson: Davidson did not met convergence criterion. \n"; |
133 | 136 | this->errorMessageDavidsonMaxIter = "Davidson roop reaches max_iter="; |
134 | 137 | this->errorMessageDavidsonMaxDim = "Dimension of the expansion vectors reaches max_dim="; |
@@ -618,7 +621,7 @@ double ZindoS::GetMolecularIntegralElement(int moI, int moJ, int moK, int moL, | ||
618 | 621 | orbitalMu = atomA->GetValence()[mu-firstAOIndexA]; |
619 | 622 | |
620 | 623 | // CNDO term |
621 | - for(int B=0; B<molecule->GetAtomVect()->size(); B++){ | |
624 | + for(int B=A; B<molecule->GetAtomVect()->size(); B++){ | |
622 | 625 | atomB = (*molecule->GetAtomVect())[B]; |
623 | 626 | firstAOIndexB = atomB->GetFirstAOIndex(); |
624 | 627 | numberAOsB = atomB->GetValence().size(); |
@@ -626,14 +629,16 @@ double ZindoS::GetMolecularIntegralElement(int moI, int moJ, int moK, int moL, | ||
626 | 629 | for(int nu=firstAOIndexB; nu<firstAOIndexB+numberAOsB; nu++){ |
627 | 630 | orbitalNu = atomB->GetValence()[nu-firstAOIndexB]; |
628 | 631 | |
629 | - if(A==B){ | |
630 | - gamma = atomA->GetZindoF0ss(); | |
632 | + if(A<B){ | |
633 | + gamma = this->GetNishimotoMatagaTwoEleInt(atomA, orbitalMu, atomB, orbitalNu); | |
634 | + value += gamma*fockMatrix[moI][mu]*fockMatrix[moJ][mu]*fockMatrix[moK][nu]*fockMatrix[moL][nu]; | |
635 | + value += gamma*fockMatrix[moI][nu]*fockMatrix[moJ][nu]*fockMatrix[moK][mu]*fockMatrix[moL][mu]; | |
631 | 636 | } |
632 | 637 | else{ |
633 | - gamma = this->GetNishimotoMatagaTwoEleInt(atomA, orbitalMu, atomB, orbitalNu); | |
638 | + gamma = atomA->GetZindoF0ss(); | |
639 | + value += gamma*fockMatrix[moI][mu]*fockMatrix[moJ][mu]*fockMatrix[moK][nu]*fockMatrix[moL][nu]; | |
634 | 640 | } |
635 | 641 | |
636 | - value += gamma*fockMatrix[moI][mu]*fockMatrix[moJ][mu]*fockMatrix[moK][nu]*fockMatrix[moL][nu]; | |
637 | 642 | } |
638 | 643 | } |
639 | 644 |
@@ -1044,12 +1049,235 @@ void ZindoS::CalcCISMatrix(double** matrixCIS, int numberOcc, int numberVir){ | ||
1044 | 1049 | int moI = this->molecule->GetTotalNumberValenceElectrons()/2 - (k/numberVir) -1; |
1045 | 1050 | int moA = this->molecule->GetTotalNumberValenceElectrons()/2 + (k%numberVir); |
1046 | 1051 | |
1047 | - for(int l=0; l<numberOcc*numberVir; l++){ | |
1052 | + for(int l=k; l<numberOcc*numberVir; l++){ | |
1048 | 1053 | // single excitation from J-th (occupied)MO to B-th (virtual)MO |
1049 | 1054 | int moJ = this->molecule->GetTotalNumberValenceElectrons()/2 - (l/numberVir) -1; |
1050 | 1055 | int moB = this->molecule->GetTotalNumberValenceElectrons()/2 + (l%numberVir); |
1051 | - | |
1052 | 1056 | double value=0.0; |
1057 | + | |
1058 | + // Fast algorith, but this is not easy to read. Slow algorithm is alos written below. | |
1059 | + Atom* atomA = NULL; | |
1060 | + Atom* atomB = NULL; | |
1061 | + int firstAOIndexA; | |
1062 | + int firstAOIndexB; | |
1063 | + int numberAOsA; | |
1064 | + int numberAOsB; | |
1065 | + double gamma; | |
1066 | + double exchange; | |
1067 | + double coulomb; | |
1068 | + OrbitalType orbitalMu; | |
1069 | + OrbitalType orbitalNu; | |
1070 | + // Off diagonal term (right upper) | |
1071 | + if(k<l){ | |
1072 | + for(int A=0; A<molecule->GetAtomVect()->size(); A++){ | |
1073 | + atomA = (*molecule->GetAtomVect())[A]; | |
1074 | + firstAOIndexA = atomA->GetFirstAOIndex(); | |
1075 | + numberAOsA = atomA->GetValence().size(); | |
1076 | + | |
1077 | + for(int mu=firstAOIndexA; mu<firstAOIndexA+numberAOsA; mu++){ | |
1078 | + orbitalMu = atomA->GetValence()[mu-firstAOIndexA]; | |
1079 | + | |
1080 | + // CNDO term | |
1081 | + for(int B=A; B<molecule->GetAtomVect()->size(); B++){ | |
1082 | + atomB = (*molecule->GetAtomVect())[B]; | |
1083 | + firstAOIndexB = atomB->GetFirstAOIndex(); | |
1084 | + numberAOsB = atomB->GetValence().size(); | |
1085 | + | |
1086 | + for(int nu=firstAOIndexB; nu<firstAOIndexB+numberAOsB; nu++){ | |
1087 | + orbitalNu = atomB->GetValence()[nu-firstAOIndexB]; | |
1088 | + | |
1089 | + if(A<B){ | |
1090 | + gamma = this->GetNishimotoMatagaTwoEleInt(atomA, orbitalMu, atomB, orbitalNu); | |
1091 | + value += 2.0*gamma*fockMatrix[moA][mu] | |
1092 | + *fockMatrix[moI][mu] | |
1093 | + *fockMatrix[moJ][nu] | |
1094 | + *fockMatrix[moB][nu]; | |
1095 | + value -= gamma*fockMatrix[moA][mu] | |
1096 | + *fockMatrix[moB][mu] | |
1097 | + *fockMatrix[moI][nu] | |
1098 | + *fockMatrix[moJ][nu]; | |
1099 | + value += 2.0*gamma*fockMatrix[moA][nu] | |
1100 | + *fockMatrix[moI][nu] | |
1101 | + *fockMatrix[moJ][mu] | |
1102 | + *fockMatrix[moB][mu]; | |
1103 | + value -= gamma*fockMatrix[moA][nu] | |
1104 | + *fockMatrix[moB][nu] | |
1105 | + *fockMatrix[moI][mu] | |
1106 | + *fockMatrix[moJ][mu]; | |
1107 | + } | |
1108 | + else{ | |
1109 | + gamma = atomA->GetZindoF0ss(); | |
1110 | + value += 2.0*gamma*fockMatrix[moA][mu] | |
1111 | + *fockMatrix[moI][mu] | |
1112 | + *fockMatrix[moJ][nu] | |
1113 | + *fockMatrix[moB][nu]; | |
1114 | + value -= gamma*fockMatrix[moA][mu] | |
1115 | + *fockMatrix[moB][mu] | |
1116 | + *fockMatrix[moI][nu] | |
1117 | + *fockMatrix[moJ][nu]; | |
1118 | + } | |
1119 | + } | |
1120 | + } | |
1121 | + | |
1122 | + // Aditional term for INDO or ZIND/S, see Eq. (10) in [RZ_1973] | |
1123 | + for(int nu=firstAOIndexA; nu<firstAOIndexA+numberAOsA; nu++){ | |
1124 | + orbitalNu = atomA->GetValence()[nu-firstAOIndexA]; | |
1125 | + | |
1126 | + if(mu!=nu){ | |
1127 | + exchange = this->GetExchangeInt(orbitalMu, orbitalNu, atomA); | |
1128 | + value += 2.0*exchange*fockMatrix[moA][mu] | |
1129 | + *fockMatrix[moI][nu] | |
1130 | + *fockMatrix[moJ][nu] | |
1131 | + *fockMatrix[moB][mu]; | |
1132 | + value += 2.0*exchange*fockMatrix[moA][mu] | |
1133 | + *fockMatrix[moI][nu] | |
1134 | + *fockMatrix[moJ][mu] | |
1135 | + *fockMatrix[moB][nu]; | |
1136 | + value -= exchange*fockMatrix[moA][mu] | |
1137 | + *fockMatrix[moB][nu] | |
1138 | + *fockMatrix[moI][nu] | |
1139 | + *fockMatrix[moJ][mu]; | |
1140 | + value -= exchange*fockMatrix[moA][mu] | |
1141 | + *fockMatrix[moB][nu] | |
1142 | + *fockMatrix[moI][mu] | |
1143 | + *fockMatrix[moJ][nu]; | |
1144 | + } | |
1145 | + | |
1146 | + coulomb = this->GetCoulombInt(orbitalMu, orbitalNu, atomA); | |
1147 | + | |
1148 | + if( (orbitalMu == s || orbitalMu == px || orbitalMu == py || orbitalMu == pz) && | |
1149 | + (orbitalNu == s || orbitalNu == px || orbitalNu == py || orbitalNu == pz) ){ | |
1150 | + gamma = atomA->GetZindoF0ss(); | |
1151 | + } | |
1152 | + else{ | |
1153 | + stringstream ss; | |
1154 | + ss << this->errorMessageCalcCISMatrix; | |
1155 | + ss << this->errorMessageAtomType << AtomTypeStr(atomA->GetAtomType()) << "\n"; | |
1156 | + ss << this->errorMessageOrbitalType << OrbitalTypeStr(orbitalMu) << "\n"; | |
1157 | + ss << this->errorMessageOrbitalType << OrbitalTypeStr(orbitalNu) << "\n"; | |
1158 | + throw MolDSException(ss.str()); | |
1159 | + } | |
1160 | + | |
1161 | + value += 2.0*(coulomb-gamma)*fockMatrix[moA][mu] | |
1162 | + *fockMatrix[moI][mu] | |
1163 | + *fockMatrix[moJ][nu] | |
1164 | + *fockMatrix[moB][nu]; | |
1165 | + value -= (coulomb-gamma)*fockMatrix[moA][mu] | |
1166 | + *fockMatrix[moB][mu] | |
1167 | + *fockMatrix[moI][nu] | |
1168 | + *fockMatrix[moJ][nu]; | |
1169 | + } | |
1170 | + } | |
1171 | + } | |
1172 | + } | |
1173 | + // Diagonal term | |
1174 | + else if(k==l){ | |
1175 | + value = this->energiesMO[moA] - this->energiesMO[moI]; | |
1176 | + for(int A=0; A<molecule->GetAtomVect()->size(); A++){ | |
1177 | + atomA = (*molecule->GetAtomVect())[A]; | |
1178 | + firstAOIndexA = atomA->GetFirstAOIndex(); | |
1179 | + numberAOsA = atomA->GetValence().size(); | |
1180 | + | |
1181 | + for(int mu=firstAOIndexA; mu<firstAOIndexA+numberAOsA; mu++){ | |
1182 | + orbitalMu = atomA->GetValence()[mu-firstAOIndexA]; | |
1183 | + | |
1184 | + // CNDO term | |
1185 | + for(int B=A; B<molecule->GetAtomVect()->size(); B++){ | |
1186 | + atomB = (*molecule->GetAtomVect())[B]; | |
1187 | + firstAOIndexB = atomB->GetFirstAOIndex(); | |
1188 | + numberAOsB = atomB->GetValence().size(); | |
1189 | + | |
1190 | + for(int nu=firstAOIndexB; nu<firstAOIndexB+numberAOsB; nu++){ | |
1191 | + orbitalNu = atomB->GetValence()[nu-firstAOIndexB]; | |
1192 | + | |
1193 | + if(A<B){ | |
1194 | + gamma = this->GetNishimotoMatagaTwoEleInt(atomA, orbitalMu, atomB, orbitalNu); | |
1195 | + value += 2.0*gamma*fockMatrix[moI][mu] | |
1196 | + *fockMatrix[moA][mu] | |
1197 | + *fockMatrix[moA][nu] | |
1198 | + *fockMatrix[moI][nu]; | |
1199 | + value -= gamma*fockMatrix[moI][mu] | |
1200 | + *fockMatrix[moI][mu] | |
1201 | + *fockMatrix[moA][nu] | |
1202 | + *fockMatrix[moA][nu]; | |
1203 | + value += 2.0*gamma*fockMatrix[moI][nu] | |
1204 | + *fockMatrix[moA][nu] | |
1205 | + *fockMatrix[moA][mu] | |
1206 | + *fockMatrix[moI][mu]; | |
1207 | + value -= gamma*fockMatrix[moI][nu] | |
1208 | + *fockMatrix[moI][nu] | |
1209 | + *fockMatrix[moA][mu] | |
1210 | + *fockMatrix[moA][mu]; | |
1211 | + } | |
1212 | + else{ | |
1213 | + gamma = atomA->GetZindoF0ss(); | |
1214 | + value += 2.0*gamma*fockMatrix[moI][mu] | |
1215 | + *fockMatrix[moA][mu] | |
1216 | + *fockMatrix[moA][nu] | |
1217 | + *fockMatrix[moI][nu]; | |
1218 | + value -= gamma*fockMatrix[moI][mu] | |
1219 | + *fockMatrix[moI][mu] | |
1220 | + *fockMatrix[moA][nu] | |
1221 | + *fockMatrix[moA][nu]; | |
1222 | + } | |
1223 | + } | |
1224 | + } | |
1225 | + | |
1226 | + // Aditional term for INDO or ZIND/S, see Eq. (10) in [RZ_1973] | |
1227 | + for(int nu=firstAOIndexA; nu<firstAOIndexA+numberAOsA; nu++){ | |
1228 | + orbitalNu = atomA->GetValence()[nu-firstAOIndexA]; | |
1229 | + | |
1230 | + if(mu!=nu){ | |
1231 | + exchange = this->GetExchangeInt(orbitalMu, orbitalNu, atomA); | |
1232 | + value += 2.0*exchange*fockMatrix[moI][mu] | |
1233 | + *fockMatrix[moA][nu] | |
1234 | + *fockMatrix[moA][nu] | |
1235 | + *fockMatrix[moI][mu]; | |
1236 | + value += 2.0*exchange*fockMatrix[moI][mu] | |
1237 | + *fockMatrix[moA][nu] | |
1238 | + *fockMatrix[moA][mu] | |
1239 | + *fockMatrix[moI][nu]; | |
1240 | + value -= exchange*fockMatrix[moI][mu] | |
1241 | + *fockMatrix[moI][nu] | |
1242 | + *fockMatrix[moA][nu] | |
1243 | + *fockMatrix[moA][mu]; | |
1244 | + value -= exchange*fockMatrix[moI][mu] | |
1245 | + *fockMatrix[moI][nu] | |
1246 | + *fockMatrix[moA][mu] | |
1247 | + *fockMatrix[moA][nu]; | |
1248 | + } | |
1249 | + | |
1250 | + coulomb = this->GetCoulombInt(orbitalMu, orbitalNu, atomA); | |
1251 | + | |
1252 | + if( (orbitalMu == s || orbitalMu == px || orbitalMu == py || orbitalMu == pz) && | |
1253 | + (orbitalNu == s || orbitalNu == px || orbitalNu == py || orbitalNu == pz) ){ | |
1254 | + gamma = atomA->GetZindoF0ss(); | |
1255 | + } | |
1256 | + else{ | |
1257 | + stringstream ss; | |
1258 | + ss << this->errorMessageCalcCISMatrix; | |
1259 | + ss << this->errorMessageAtomType << AtomTypeStr(atomA->GetAtomType()) << "\n"; | |
1260 | + ss << this->errorMessageOrbitalType << OrbitalTypeStr(orbitalMu) << "\n"; | |
1261 | + ss << this->errorMessageOrbitalType << OrbitalTypeStr(orbitalNu) << "\n"; | |
1262 | + throw MolDSException(ss.str()); | |
1263 | + } | |
1264 | + | |
1265 | + value += 2.0*(coulomb-gamma)*fockMatrix[moI][mu] | |
1266 | + *fockMatrix[moA][mu] | |
1267 | + *fockMatrix[moA][nu] | |
1268 | + *fockMatrix[moI][nu]; | |
1269 | + value -= (coulomb-gamma)*fockMatrix[moI][mu] | |
1270 | + *fockMatrix[moI][mu] | |
1271 | + *fockMatrix[moA][nu] | |
1272 | + *fockMatrix[moA][nu]; | |
1273 | + } | |
1274 | + } | |
1275 | + } | |
1276 | + } | |
1277 | + // End of the fast algorith. | |
1278 | + | |
1279 | + /* | |
1280 | + // Slow algorith, but this is easy to read. Fast altorithm is also written above. | |
1053 | 1281 | // diagonal term |
1054 | 1282 | if(k==l){ |
1055 | 1283 | value = this->energiesMO[moA] - this->energiesMO[moI] |
@@ -1059,14 +1287,16 @@ void ZindoS::CalcCISMatrix(double** matrixCIS, int numberOcc, int numberVir){ | ||
1059 | 1287 | this->molecule, this->fockMatrix, NULL); |
1060 | 1288 | |
1061 | 1289 | } |
1062 | - // off diagonal term (right upper) | |
1290 | + // Off diagonal term (right upper) | |
1063 | 1291 | else if(k<l){ |
1064 | 1292 | value = 2.0*this->GetMolecularIntegralElement(moA, moI, moJ, moB, |
1065 | 1293 | this->molecule, this->fockMatrix, NULL) |
1066 | 1294 | - this->GetMolecularIntegralElement(moA, moB, moI, moJ, |
1067 | 1295 | this->molecule, this->fockMatrix, NULL); |
1068 | 1296 | } |
1069 | - | |
1297 | + // End of the slow algorith. | |
1298 | + */ | |
1299 | + | |
1070 | 1300 | matrixCIS[k][l] = value; |
1071 | 1301 | } |
1072 | 1302 | } |