/* * @BEGIN LICENSE * * aointegrals by Psi4 Developer, a plugin to: * * Psi4: an open-source quantum chemistry software package * * Copyright (c) 2007-2018 The Psi4 Developers. * * The copyrights for code used from other parties are included in * the corresponding files. * * This file is part of Psi4. * * Psi4 is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, version 3. * * Psi4 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with Psi4; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * @END LICENSE */ #include "psi4/psi4-dec.h" #include "psi4/libpsi4util/PsiOutStream.h" #include "psi4/liboptions/liboptions.h" #include "psi4/libmints/wavefunction.h" #include "psi4/libmints/molecule.h" #include "psi4/libmints/basisset.h" #include "psi4/libmints/matrix.h" #include "psi4/libmints/mintshelper.h" #include "psi4/libmints/factory.h" #include "psi4/libmints/integral.h" #include "psi4/libpsi4util/process.h" #include #include #include #include #include #include #include #include #include #ifdef _OPENMP #include "omp.h" #endif using namespace std; namespace psi{ namespace aointegrals { extern "C" PSI_API int read_options(std::string name, Options &options) { if (name == "AOINTEGRALS"|| options.read_globals()) { /*- The amount of information printed to the output file -*/ options.add_int("PRINT", 1); /*- Whether to compute two-electron integrals -*/ options.add_bool("DO_TEI", true); } return true; } extern "C" PSI_API SharedWavefunction aointegrals(SharedWavefunction ref_wfn, Options& options) { // Grab options from the options object int print = options.get_int("PRINT"); int doTei = options.get_bool("DO_TEI"); time_t start, end; // Have the Wavefunction from python-side // Molecule is a member of the wavefunction option // Lets print out some molecule information here std::shared_ptr molecule = ref_wfn->molecule(); //Form basis object std::shared_ptr aoBasis = ref_wfn->basisset(); MintsHelper mints(MintsHelper(ref_wfn->basisset(), options, 0)); // The integral factory oversees the creation of integral objects auto integral = std::make_shared(aoBasis, aoBasis, aoBasis, aoBasis); std::shared_ptr ints(integral->eri()); int nbf = {aoBasis->nbf()}; srand(time(NULL)); // We can build the two-electron integrals in a similar manner if(doTei){ // As a note building the ERI's in this way is typically for debugging purposes and not normally recommended outfile->Printf("\nTwo-electron Integrals\n\n"); // Now, the two-electron integrals // The buffer will hold the integrals for each shell, as they're computed const double *buffer = ints->buffer(); // The iterator conveniently lets us iterate over functions within shells AOShellCombinationsIterator shellIter = integral->shells_iterator(); long long unsigned int num_ao=0; double num = 0.0; start = time(NULL); string ao_eri_value_filename = "ao_eri_value"; ofstream ao_eri_file_write(ao_eri_value_filename, ios::binary); string ao_eri_index1_filename = "ao_eri_index1"; ofstream ao_index1_file_write(ao_eri_index1_filename, ios::binary); string ao_eri_index2_filename = "ao_eri_index2"; ofstream ao_index2_file_write(ao_eri_index2_filename, ios::binary); string ao_eri_index3_filename = "ao_eri_index3"; ofstream ao_index3_file_write(ao_eri_index3_filename, ios::binary); string ao_eri_index4_filename = "ao_eri_index4"; ofstream ao_index4_file_write(ao_eri_index4_filename, ios::binary); printf("\tStart computing AO two-electron integrals...\n"); fflush(stdout); // This for loop generates AO two electron integrals // Iterate over shell for (int M = 0; M < aoBasis->nshell(); M++) { for (int N = 0; N < aoBasis->nshell(); N++) { for (int P = 0; P < aoBasis->nshell(); P++) { for (int Q = 0; Q < aoBasis->nshell(); Q++) { ints->compute_shell(M, N, P, Q); // Iterate over basis functions in each shell for (int m = 0, index = 0; m < aoBasis->shell(M).nfunction(); m++) { for (int n = 0; n < aoBasis->shell(N).nfunction(); n++) { for (int p = 0; p < aoBasis->shell(P).nfunction(); p++) { for (int q = 0; q < aoBasis->shell(Q).nfunction(); q++, index++) { if (fabs(buffer[index]) > 1e-6) { int a = aoBasis->shell(M).function_index() + m; int b = aoBasis->shell(N).function_index() + n; int c = aoBasis->shell(P).function_index() + p; int d = aoBasis->shell(Q).function_index() + q; // psi::outfile->Printf("\t(%2d %2d | %2d %2d) =:\t%20.10lf\n", a, b, c, d, buffer[index]); // Saving AO eri ao_eri_file_write.write((char*)&buffer[index], sizeof(double)); ao_index1_file_write.write((char*)&a, sizeof(int)); ao_index2_file_write.write((char*)&b, sizeof(int)); ao_index3_file_write.write((char*)&c, sizeof(int)); ao_index4_file_write.write((char*)&d, sizeof(int)); num_ao++; } } } } } } } } } ao_eri_file_write.close(); ao_index1_file_write.close(); ao_index2_file_write.close(); ao_index3_file_write.close(); ao_index4_file_write.close(); string num_ao_filename = "num_ao"; ofstream num_ao_file(num_ao_filename); num_ao_file.write((char*)&num_ao, sizeof(long long int)); num_ao_file.close(); end = time(NULL); double diff_time_ao_sec = difftime(end, start); double diff_time_ao = diff_time_ao_sec/3600; printf("\tAO two-electron integrals are completed!!\n"); printf("\tThere are %llu effective integrals\n", num_ao); printf("\tTotal time taken for generating AO two-electron integrals: %.1f hr\n", diff_time_ao); fflush(stdout); } return ref_wfn; } }} // End Namespaces