4 #include <libconfig.h++>
11 #include <boost/mpi.hpp>
12 #include <yaml-cpp/yaml.h>
18 namespace mpi = boost::mpi;
43 int main(
int argc,
char* argv[])
46 mpi::communicator world;
50 cout <<
"Error: No file provided." << endl;
51 cout <<
"Usage: programname <infile> [outfile]" << endl;
55 string inFileName = argv[1];
57 stringstream outFileName;
59 outFileName <<
"states";
61 outFileName << argv[2];
71 CompType atomCompound(
sizeof(AtomData) );
72 atomCompound.insertMember(
"x", HOFFSET(AtomData, x), PredType::NATIVE_DOUBLE);
73 atomCompound.insertMember(
"y", HOFFSET(AtomData, y), PredType::NATIVE_DOUBLE);
74 atomCompound.insertMember(
"z", HOFFSET(AtomData, z), PredType::NATIVE_DOUBLE);
81 H5::StrType string_type(H5::PredType::C_S1, 64);
82 CompType atomMetaCompound(
sizeof(AtomMetaData) );
83 atomMetaCompound.insertMember(
"type", HOFFSET(AtomMetaData, type), PredType::NATIVE_INT);
84 atomMetaCompound.insertMember(
"basisName", HOFFSET(AtomMetaData, basisName), string_type);
87 if(world.rank() == 0) {
88 H5File inFile(inFileName, H5F_ACC_RDONLY );
91 vector<int> allStates;
92 allStates.reserve(nStates);
93 for(
int i = 0; i < nStates; i++) {
94 allStates.push_back(i);
96 random_shuffle(allStates.begin(), allStates.end());
97 for(
int p = 0; p < world.size(); p++) {
99 for(
int i =
blockLow(p, world.size(), allStates.size());
100 i <=
blockHigh(p, world.size(), allStates.size());
103 states.push_back(allStates.at(i));
109 world.send(p, 0, states);
114 world.recv(0, 0, stateIDs);
116 cout <<
"Rank " << world.rank() <<
": I have " << stateIDs.size() <<
" states to dig!" << endl;
119 outFileName <<
"." << setfill(
'0') << setw(4) << world.rank() <<
".h5";
122 H5File outFile(outFileName.str(), H5F_ACC_TRUNC);
123 for(
int p = 0; p < world.size(); p++) {
125 if(p != world.rank()) {
129 H5File inFile(inFileName, H5F_ACC_RDONLY);
133 for(
int i = 0; i < int(inFile.getNumObjs()); i++) {
134 string objectName = inFile.getObjnameByIdx(i);
135 if(objectName ==
string(
"states")) {
136 H5::Group
statesGroup(inFile.openGroup(
"/states"));
137 H5::Group statesGroupOut(outFile.createGroup(
"/states"));
138 for(
int stateID : stateIDs) {
139 string stateName =
statesGroup.getObjnameByIdx(stateID);
140 H5Ocopy(
statesGroup.getId(), stateName.c_str(), statesGroupOut.getId(), stateName.c_str(), H5Pcreate(H5P_OBJECT_COPY), H5P_DEFAULT);
143 H5Ocopy(inFile.getId(), objectName.c_str(), outFile.getId(), objectName.c_str(), H5Pcreate(H5P_OBJECT_COPY), H5P_DEFAULT);
149 H5::Group rootGroup(outFile.openGroup(
"/"));
150 string metaInformationName =
"atomMeta";
151 DataSet
atomMeta(rootGroup.openDataSet(metaInformationName));
153 atomMeta.getSpace().getSimpleExtentDims(dims);
154 int nAtoms = dims[0];
156 AtomMetaData atomMetaData[nAtoms];
157 atomMeta.read(atomMetaData, atomMetaCompound);
160 Attribute hartreeFockMethodAttribute =
atomMeta.openAttribute(
"method");
161 hartreeFockMethodAttribute.read(hartreeFockMethodAttribute.getDataType(), method);
163 mat coefficientMatrixUp;
164 mat coefficientMatrixDown;
167 cout <<
"Calculating energy offset..." << endl;
168 Attribute energyOffsetAttribute =
atomMeta.createAttribute(
"energyOffset", PredType::NATIVE_DOUBLE, H5S_SCALAR);
170 for(
int i = 0; i < nAtoms; i++) {
182 energyOffset += solver.
energy();
184 energyOffsetAttribute.write(PredType::NATIVE_DOUBLE, &energyOffset);
185 cout <<
"Energy offset: " << energyOffset << endl;
189 cout <<
"Calculating ground state to get coefficients..." << endl;
191 bool foundGroundState =
false;
192 DataSet groundStateDataSet;
194 groundStateDataSet = rootGroup.openDataSet(
"groundState");
195 foundGroundState =
true;
196 }
catch (GroupIException exception) {
197 cout <<
"Did not find ground state data set, skipping initialization of coefficient matrices." << endl;
200 if(foundGroundState) {
202 groundStateDataSet.getSpace().getSimpleExtentDims(dims2);
203 int groundStateNAtoms2 = dims2[0];
205 if(nAtoms != groundStateNAtoms2) {
206 cerr <<
"Error! The number of atoms in the ground state (nAtoms = " << groundStateNAtoms2 <<
") does not match "
207 <<
"the number of atoms in the metadata (= " << nAtoms <<
")" << endl;
208 cerr <<
"Cannot continue" << endl;
209 throw std::logic_error(
"Mismatching number of atoms");
212 AtomData *groundStateAtoms =
new AtomData[groundStateNAtoms2];
213 groundStateDataSet.read(groundStateAtoms, atomCompound);
216 for(
int i = 0; i < groundStateNAtoms2; i++) {
217 stringstream basisFile;
218 basisFile <<
"atom_" << atomMetaData[i].type <<
"_basis_" << atomMetaData[i].basisName <<
".tm";
219 string fileName = basisFile.str();
220 groundStateSystem.
addCore(
GaussianCore({ groundStateAtoms[i].x, groundStateAtoms[i].y, groundStateAtoms[i].z}, fileName));
222 if(method ==
"unrestricted") {
228 groundStateSolver.
solve();
232 cout <<
"Ground state energy: " << groundStateSolver.
energy() << endl;
238 groundStateSolver.
solve();
241 cout <<
"Ground state energy: " << groundStateSolver.
energy() << endl;
244 delete groundStateAtoms;
248 H5::Group
statesGroup(outFile.openGroup(
"/states"));
251 int currentState = 0;
252 for(
int stateID = 0; stateID < nTotal; stateID++) {
253 if(world.rank() == 0) {
254 cout <<
"Progress: " << fixed << setprecision(2) << double(currentState) / nTotal * 100 <<
" %"
255 <<
", time: " << timer.elapsed() <<
" s"
258 string stateName =
statesGroup.getObjnameByIdx(stateID);
259 DataSet stateDataSet(
statesGroup.openDataSet(stateName));
261 stateDataSet.getSpace().getSimpleExtentDims(dims2);
262 int nAtoms2 = dims2[0];
264 if(nAtoms != nAtoms2) {
265 cerr <<
"Error! The number of atoms in " << stateName <<
" (nAtoms = " << nAtoms2 <<
") does not match "
266 <<
"the number of atoms in the metadata (= " << nAtoms <<
")" << endl;
267 cerr <<
"Cannot continue" << endl;
268 throw std::logic_error(
"Mismatching number of atoms");
271 AtomData *
atoms =
new AtomData[nAtoms2];
272 stateDataSet.read(atoms, atomCompound);
275 for(
int i = 0; i < nAtoms2; i++) {
276 stringstream basisFile;
277 basisFile <<
"atom_" << atomMetaData[i].type <<
"_basis_" << atomMetaData[i].basisName <<
".tm";
278 string fileName = basisFile.str();
282 if(method ==
"unrestricted") {
300 Attribute energyAttribute(stateDataSet.createAttribute(
"energy", PredType::NATIVE_DOUBLE, H5S_SCALAR));
301 energyAttribute.write(PredType::NATIVE_DOUBLE, &energy);
302 outFile.flush(H5F_SCOPE_GLOBAL);
309 if(world.rank() == 0) {
310 cout <<
"Progress: 100 %, time " << fixed << setprecision(2) << timer.elapsed() <<
" s" << endl;
311 cout <<
"Done!" << endl;