50 cerr <<
"Too few arguments." << endl;
51 cerr <<
"Usage: hartree-fock <config.yaml>" << endl;
54 string outputPath =
"";
58 cout <<
"Output will be written to " << outputPath << endl;
60 ifstream fin(argv[1]);
62 cerr <<
"Could not open the configuration file " << argv[1] << endl;
68 parser.GetNextDocument(rootNode);
69 unsigned int nAtoms = rootNode[
"atoms"].size();
70 string defaultBasis =
"3-21G";
72 rootNode[
"basis"] >> defaultBasis;
73 cout <<
"Using basis " << defaultBasis << endl;
74 }
catch( YAML::TypedKeyNotFound<std::string> ) {
75 cout <<
"Default basis not found, expecting atom to have basis name or assuming " << defaultBasis << endl;
85 H5::CompType atomCompound(
sizeof(AtomData) );
86 atomCompound.insertMember(
"x", HOFFSET(AtomData, x), H5::PredType::NATIVE_DOUBLE);
87 atomCompound.insertMember(
"y", HOFFSET(AtomData, y), H5::PredType::NATIVE_DOUBLE);
88 atomCompound.insertMember(
"z", HOFFSET(AtomData, z), H5::PredType::NATIVE_DOUBLE);
95 H5::CompType atomMetaCompound(
sizeof(AtomMetaData) );
96 atomMetaCompound.insertMember(
"type", HOFFSET(AtomMetaData, type), H5::PredType::NATIVE_INT);
97 atomMetaCompound.insertMember(
"basisName", HOFFSET(AtomMetaData, basisName), H5::StrType(H5::PredType::C_S1, 64));
99 H5::H5File outFile(outputPath +
"results.h5", H5F_ACC_TRUNC);
100 hsize_t dim[] = {nAtoms};
101 H5::DataSet stateDataSet = outFile.createDataSet(
"state", atomCompound, H5::DataSpace(1, dim));
102 H5::DataSet atomMetaDataSet(outFile.createDataSet(
"atomMeta", atomMetaCompound, H5::DataSpace(1, dim)));
104 AtomData
atoms[nAtoms];
109 vector<Output::OutputName> outputs;
110 for(YAML::Iterator it=rootNode.begin();it!=rootNode.end();++it) {
112 it.first() >> rootKey;
113 if(rootKey ==
"atoms") {
115 const YAML::Node &atomsNode = it.second();
116 for(YAML::Iterator it2=atomsNode.begin();it2!=atomsNode.end();++it2) {
117 const YAML::Node &atomNode = *it2;
118 string typeAbbreviation;
119 atomNode[
"type"] >> typeAbbreviation;
121 atomNode[
"position"] >> position;
124 atomNode[
"basis"] >> basis;
125 }
catch( YAML::TypedKeyNotFound<std::string> ) {
126 basis = defaultBasis;
131 strncpy(atomsMeta[atomCounter].basisName, basis.c_str(), 63);
134 atoms[atomCounter].x = position.x();
135 atoms[atomCounter].y = position.y();
136 atoms[atomCounter].z = position.z();
139 }
else if(rootKey ==
"method") {
141 it.second() >> methodName;
142 if(methodName ==
"unrestricted") {
144 }
else if(methodName ==
"restricted") {
147 cerr <<
"Error: Unknown method name " << methodName << endl;
150 }
else if(rootKey ==
"electronsDown" || rootKey ==
"electronsUp") {
152 it.second() >> electronsDown;
154 }
else if(rootKey ==
"output") {
155 const YAML::Node &outputNode = it.second();
156 for(YAML::Iterator it2=outputNode.begin();it2!=outputNode.end();++it2) {
159 if(outputName ==
"energy") {
161 }
else if(outputName ==
"density") {
163 }
else if(outputName ==
"electrostatic_potential") {
169 stateDataSet.write(atoms, atomCompound);
170 atomMetaDataSet.write(atomsMeta, atomMetaCompound);
174 mat coefficientsDown;
176 cout <<
"Setting up the unrestricted Hartree-Fock solver..." << endl;
178 solver.setConvergenceTreshold(1e-10);
179 solver.setDensityMixFactor(0.95);
180 solver.setNIterationsMax(1e4);
181 cout <<
"Solving..." << endl;
183 energy = solver.energy();
184 cout <<
"Energy: " << setprecision(16) << solver.energy() << endl;
186 coefficientsUp = solver.coeffcientMatrixUp();
187 coefficientsDown = solver.coeffcientMatrixDown();
190 cout <<
"Setting up the restricted Hartree-Fock solver..." << endl;
192 solver.setConvergenceTreshold(1e-12);
193 solver.setDensityMixFactor(0.95);
194 solver.setNIterationsMax(1e4);
195 cout <<
"Solving..." << endl;
197 energy = solver.energy();
198 cout <<
"Energy: " << setprecision(16) << solver.energy() << endl;
200 coefficientsUp = solver.coefficientMatrix();
202 cout <<
"Writing requested output to file:" << endl;
205 cout <<
"Writing energy..." << endl;
206 H5::Attribute energyAttribute(stateDataSet.createAttribute(
"energy", H5::PredType::NATIVE_DOUBLE, H5S_SCALAR));
207 energyAttribute.write(H5::PredType::NATIVE_DOUBLE, &energy);
209 cout <<
"Calculating density..." << endl;
213 coefficientsAll = join_rows(coefficientsUp, coefficientsDown);
215 coefficientsAll = coefficientsUp;
217 vec x = linspace(-3, 3, 100);
218 vec y = linspace(-3, 3, 100);
219 vec z = linspace(-3, 3, 100);
220 cube totalDensity = zeros(x.n_elem, y.n_elem, z.n_elem);
221 field<cube> orbitalDensities;
222 orbitalDensities.set_size(system.
nParticles());
223 for(cube& orbitalDensity : orbitalDensities) {
224 orbitalDensity = zeros(x.n_elem, y.n_elem, z.n_elem);
226 for(uint i = 0; i < x.n_elem; i++) {
227 for(uint j = 0; j < y.n_elem; j++) {
228 for(uint k = 0; k < z.n_elem; k++) {
229 Vector3 position(x(i), y(j), z(k));
231 for(uint orbital = 0; orbital < orbitalDensities.size(); orbital++) {
232 cube &orbitalDensity = orbitalDensities(orbital);
233 orbitalDensity(k,j,i) = density(orbital);
235 totalDensity(k,j,i) = sum(density);
239 for(uint orbital = 0; orbital < orbitalDensities.size(); orbital++) {
240 cube &orbitalDensity = orbitalDensities(orbital);
241 orbitalDensity.save(outputPath +
"orbital_density_" + to_string(orbital) +
".h5", hdf5_binary);
243 totalDensity.save(outputPath +
"density.h5", hdf5_binary);
245 cout <<
"Calculating electrostatic potential..." << endl;
248 vec x = linspace(-5, 5, 50);
249 vec y = linspace(-5, 5, 50);
250 vec z = linspace(-5, 5, 50);
251 cube electrostaticPotential = zeros(x.n_elem, y.n_elem, z.n_elem);
252 mat coefficientsAll = join_rows(coefficientsUp, coefficientsDown);
253 for(uint i = 0; i < x.n_elem; i++) {
254 for(uint j = 0; j < y.n_elem; j++) {
255 for(uint k = 0; k < z.n_elem; k++) {
256 Vector3 position(x(i), y(j), z(k));
261 electrostaticPotential.save(outputPath +
"electrostatic_potential.h5", hdf5_binary);
266 cout <<
"Done." << endl;