/* * This source code is part of * * E R K A L E * - * HF/DFT from Hel * * Copyright © 2015 The Regents of the University of California * All Rights Reserved * * Written by Susi Lehtola, Lawrence Berkeley National Laboratory * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. */ #include "erifit.h" #include "basis.h" #include "linalg.h" #include "mathf.h" #include "settings.h" #include "eriworker.h" extern Settings settings; namespace ERIfit { bool operator<(const bf_pair_t & lhs, const bf_pair_t & rhs) { return lhs.idx < rhs.idx; } void get_basis(BasisSet & basis, const BasisSetLibrary & blib, const ElementBasisSet & orbel) { // Settings needed to form basis set Settings settings0(settings); settings.add_scf_settings(); settings.set_bool("BasisRotate", false); settings.set_string("Decontract", ""); settings.set_bool("UseLM", true); // Atoms std::vector atoms(1); atoms[0].el=orbel.get_symbol(); atoms[0].num=0; atoms[0].x=atoms[0].y=atoms[0].z=0.0; atoms[0].Q=0; // Form basis set construct_basis(basis,atoms,blib); } void orthonormal_ERI_trans(const ElementBasisSet & orbel, double linthr, arma::mat & trans) { // Form basis set library BasisSetLibrary blib; blib.add_element(orbel); // Form basis set BasisSet basis; get_basis(basis,blib,orbel); // Get orthonormal orbitals arma::mat S(basis.overlap()); arma::mat Sinvh(CanonicalOrth(S,linthr)); // Sizes size_t Nbf(Sinvh.n_rows); size_t Nmo(Sinvh.n_cols); // Fill matrix trans.zeros(Nbf*Nbf,Nmo*Nmo); printf("Size of orthogonal transformation matrix is %i x %i\n",(int) trans.n_rows,(int) trans.n_cols); for(size_t iao=0;iao shells(basis.get_shells()); // Get list of shell pairs std::vector shpairs(basis.get_unique_shellpairs()); // Print basis // basis.print(true); // Allocate memory for the integrals eris.zeros(Nbf*Nbf,Nbf*Nbf); printf("Size of integral matrix is %i x %i\n",(int) eris.n_rows,(int) eris.n_cols); #ifdef _OPENMP #pragma omp parallel #endif { // Integral worker ERIWorker *eri=new ERIWorker(basis.get_max_am(),basis.get_max_Ncontr()); #ifdef _OPENMP #pragma omp for schedule(dynamic,1) #endif for(size_t ip=0;ipcompute(&shells[is],&shells[js],&shells[ks],&shells[ls]); // Get array const std::vector *erip=eri->getp(); // Store integrals for(size_t ii=0;ii shells(basis.get_shells()); // Get list of shell pairs std::vector shpairs(basis.get_unique_shellpairs()); // Print basis // basis.print(true); // Allocate memory for the integrals eris.zeros(Nbf,Nbf); printf("Size of integral matrix is %i x %i\n",(int) eris.n_rows,(int) eris.n_cols); #ifdef _OPENMP #pragma omp parallel #endif { // Integral worker ERIWorker *eri=new ERIWorker(basis.get_max_am(),basis.get_max_Ncontr()); #ifdef _OPENMP #pragma omp for schedule(dynamic,1) #endif for(size_t ip=0;ipcompute(&shells[is],&shells[js],&shells[is],&shells[js]); // Get array const std::vector *erip=eri->getp(); // Store integrals for(size_t ii=0;ii > & pairs, std::vector & exps) { // Form orbital basis set library BasisSetLibrary orblib; orblib.add_element(orbel); // Form orbital basis set BasisSet basis; get_basis(basis,orblib,orbel); // Get shells std::vector shells(basis.get_shells()); // and list of unique shell pairs std::vector shpairs(basis.get_unique_shellpairs()); // Create the exponent list exps.clear(); for(size_t ip=0;ip(exps,zeta); } // Create the pair list pairs.resize(exps.size()); for(size_t ip=0;ip(exps,zeta); // Insert pair pairs[pos].push_back(shpairs[ip]); } } void compute_cholesky_T(const ElementBasisSet & orbel, int am1, int am2, arma::mat & eris, arma::vec & exps_) { // Form basis set library BasisSetLibrary blib; blib.add_element(orbel); // Decontract the basis set blib.decontract(); // Form basis set BasisSet basis; get_basis(basis,blib,orbel); // Get shells in basis sets std::vector shells(basis.get_shells()); // Get list of unique exponent pairs std::vector< std::vector > upairs; std::vector exps; unique_exponent_pairs(orbel,am1,am2,upairs,exps); // Store exponents exps_=arma::conv_to::from(exps); // Allocate memory for the integrals eris.zeros(exps.size(),exps.size()); #ifdef _OPENMP #pragma omp parallel #endif { // Integral worker ERIWorker *eri=new ERIWorker(basis.get_max_am(),basis.get_max_Ncontr()); #ifdef _OPENMP #pragma omp for schedule(dynamic,1) #endif // Loop over unique exponent pairs for(size_t iip=0;iipcompute(&shells[is],&shells[js],&shells[ks],&shells[ls]); // Get array const std::vector *erip=eri->getp(); // Store integrals for(size_t ii=0;ii orbsh(orbbas.get_shells()); std::vector fitsh(fitbas.get_shells()); // Get list of shell pairs std::vector orbpairs(orbbas.get_unique_shellpairs()); // Dummy shell GaussianShell dummy(dummyshell()); // Problem sizes const size_t Norb(orbbas.get_Nbf()); const size_t Nfit(fitbas.get_Nbf()); // Allocate memory fitint.zeros(Norb*Norb,Nfit); #ifdef _OPENMP #pragma omp parallel #endif { // Integral worker int maxam=std::max(orbbas.get_max_am(),fitbas.get_max_am()); ERIWorker *eri=new ERIWorker(maxam,orbbas.get_max_Ncontr()); #ifdef _OPENMP #pragma omp for schedule(dynamic) #endif for(size_t ip=0;ipcompute(&orbsh[is],&orbsh[js],&dummy,&fitsh[as]); // Get array const std::vector *erip=eri->getp(); // Store integrals for(size_t ii=0;ii orbsh(orbbas.get_shells()); std::vector fitsh(fitbas.get_shells()); // Get list of shell pairs std::vector orbpairs(orbbas.get_unique_shellpairs()); // Dummy shell GaussianShell dummy(dummyshell()); // Problem size size_t Nfit(fitbas.get_Nbf()); // Overlap matrix arma::mat S(Nfit,Nfit); #ifdef _OPENMP #pragma omp parallel #endif { // Integral worker int maxam=std::max(orbbas.get_max_am(),fitbas.get_max_am()); ERIWorker *eri=new ERIWorker(maxam,orbbas.get_max_Ncontr()); // Compute the fitting basis overlap #ifdef _OPENMP #pragma omp for #endif for(size_t i=0;icompute(&fitsh[i],&dummy,&fitsh[j],&dummy); // Get array const std::vector *erip=eri->getp(); // Store integrals size_t i0=fitsh[i].get_first_ind(); size_t j0=fitsh[j].get_first_ind(); size_t Ni=fitsh[i].get_Nbf(); size_t Nj=fitsh[j].get_Nbf(); for(size_t ii=0;ii=linthr) Nind++; // and drop the linearly dependent ones Sval=Sval.subvec(Sval.n_elem-Nind,Sval.n_elem-1); Svec=Svec.cols(Svec.n_cols-Nind,Svec.n_cols-1); // Form inverse overlap matrix arma::mat S_inv; S_inv.zeros(Svec.n_rows,Svec.n_rows); for(size_t i=0;i orbsh(orbbas.get_shells()); std::vector fitsh(fitbas.get_shells()); // Get list of shell pairs std::vector orbpairs(orbbas.get_unique_shellpairs()); // Dummy shell GaussianShell dummy(dummyshell()); // Problem size size_t Nfit(fitbas.get_Nbf()); // Overlap matrix arma::mat S(Nfit,Nfit); #ifdef _OPENMP #pragma omp parallel #endif { // Integral worker int maxam=std::max(orbbas.get_max_am(),fitbas.get_max_am()); ERIWorker *eri=new ERIWorker(maxam,orbbas.get_max_Ncontr()); // Compute the fitting basis overlap #ifdef _OPENMP #pragma omp for #endif for(size_t i=0;icompute(&fitsh[i],&dummy,&fitsh[j],&dummy); // Get array const std::vector *erip=eri->getp(); // Store integrals size_t i0=fitsh[i].get_first_ind(); size_t j0=fitsh[j].get_first_ind(); size_t Ni=fitsh[i].get_Nbf(); size_t Nj=fitsh[j].get_Nbf(); for(size_t ii=0;ii=linthr) Nind++; // and drop the linearly dependent ones Sval=Sval.subvec(Sval.n_elem-Nind,Sval.n_elem-1); Svec=Svec.cols(Svec.n_cols-Nind,Svec.n_cols-1); // Form inverse overlap matrix arma::mat S_inv; S_inv.zeros(Svec.n_rows,Svec.n_rows); for(size_t i=0;i