// // nao.cc // // Copyright (C) 1997 Limit Point Systems, Inc. // // Author: Curtis Janssen // Maintainer: LPS // // This file is part of the SC Toolkit. // // The SC Toolkit is free software; you can redistribute it and/or modify // it under the terms of the GNU Library General Public License as published by // the Free Software Foundation; either version 2, or (at your option) // any later version. // // The SC Toolkit 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 Library General Public License for more details. // // You should have received a copy of the GNU Library General Public License // along with the SC Toolkit; see the file COPYING.LIB. If not, write to // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. // // The U.S. Government is granted a limited license as per AL 91-7. // #include #include #include #include using namespace std; using namespace sc; #undef DEBUG namespace sc { static RefSCMatrix operator *(const RefDiagSCMatrix &d, const RefSymmSCMatrix &s) { RefSCMatrix ret(s.dim(), s.dim(), s.kit()); int n = s.dim()->n(); for (int i=0; in(); for (int i=0; i kit = S.kit(); // find a symmetric orthogonalization transform RefSCMatrix trans(tdim,tdim,kit); RefDiagSCMatrix eigval(tdim,kit); S.diagonalize(eigval,trans); Ref squareroot = new SCElementSquareRoot; eigval.element_op(squareroot); Ref invert = new SCElementInvert(1.0e-12); eigval.element_op(invert); RefSymmSCMatrix OL(tdim,kit); OL.assign(0.0); // OL = trans * eigval * trans.t(); OL.accumulate_transform(trans, eigval); return OL; } static void delete_partition_info(int natom, int *maxam_on_atom, int **nam_on_atom, int ***amoff_on_atom) { int i, j; for (i=0; i= nb) { ExEnv::errn() << "assemble: bad Nm_map" << endl; abort(); } N.assign_column(Nm.get_column(i), Nm_map[i]); } for (i=0; i= nb) { ExEnv::errn() << "assemble: bad Nr1_map" << endl; abort(); } N.assign_column(Nr1.get_column(i), Nr1_map[i]); } for (i=0; i= nb) { ExEnv::errn() << "assemble: bad Nr2_map" << endl; abort(); } N.assign_column(Nr2.get_column(i), Nr2_map[i]); } return N; } // form symmetry average NAO for each atom static void form_nao(const RefSymmSCMatrix &P, const RefSymmSCMatrix &S, const RefSCMatrix &N, const RefDiagSCMatrix &W, int natom, int *maxam_on_atom, int **nam_on_atom, int ***amoff_on_atom, const Ref& kit) { int i,j,k,l,m; N.assign(0.0); W.assign(0.0); for (i=0; i b = basis(); Ref pl = integral()->petite_list(); // compute S, the ao basis overlap RefSymmSCMatrix blockedS = pl->to_AO_basis(overlap()); RefSymmSCMatrix S = dynamic_cast(blockedS.pointer())->block(0); blockedS = 0; # ifdef DEBUG S.print("S"); # endif // compute P, the ao basis density RefSymmSCMatrix P = dynamic_cast(ao_density().pointer())->block(0); // why? good question. RefSymmSCMatrix Ptmp = P->clone(); Ptmp.assign(0.0); Ptmp->accumulate_transform(S, P); # ifdef DEBUG P.print("P"); ExEnv::out0() << "nelec = " << (mhalf(S) * Ptmp * mhalf(S)).trace() << endl; ExEnv::out0() << "nelec(2) = " << (P * S).trace() << endl; # endif P = Ptmp; Ptmp = 0; int i,j,k,l; int nb = b->nbasis(); int nsh = b->nshell(); int natom = molecule()->natom(); # ifdef DEBUG ExEnv::out0() << "nb = " << nb << endl; ExEnv::out0() << "nsh = " << nsh << endl; ExEnv::out0() << "natom = " << natom << endl; # endif // Step 2a. Transform to solid harmonics. // -- for now program will abort if basis does not use only S.H and cart d. RefSCDimension aodim = P.dim(); RefSCMatrix Tdfg(aodim, aodim, matrixkit()); Tdfg->unit(); for (i=0; ishell(i); int off = b->shell_to_function(i); for (j=0; jnew_spherical_transform_iter(2,0,0); for (sti->begin(); sti->ready(); sti->next()) { Tdfg->set_element(off + sti->pureindex(), off + sti->cartindex(), sti->coef()); } delete sti; // now for the pure d part of the cartesian d shell sti = integral()->new_spherical_transform_iter(2,0,2); for (sti->begin(); sti->ready(); sti->next()) { Tdfg->set_element(off + sti->pureindex() + 1, off + sti->cartindex(), sti->coef()); } delete sti; } else if (shell.am(j) > 2 && ! shell.is_pure(j)) { ExEnv::errn() << "NAOs can only be computed for puream if am > 2" << endl; abort(); } off += shell.nfunction(j); } } // Tdfg should already be orthogonal, normalize them // RefSCMatrix Tdfgo = Tdfg*Tdfg.t(); // RefDiagSCMatrix Tdfg_norm(Tdfg.rowdim(), matrixkit()); // for (i=0; iZ(i); r_maxam_on_atom[i] = maxam_on_atom[i]; r_nam_on_atom[i] = new int[r_maxam_on_atom[i]+1]; for (j=0; j<=r_maxam_on_atom[i]; j++) { r_nam_on_atom[i][j] = nam_on_atom[i][j] - nnmb_atom(z,j); if (r_nam_on_atom[i][j] < 0) { ExEnv::errn() << "NAO: < 0 rydberg orbitals of a given type" << endl; abort(); } } r_amoff_on_atom[i] = new int*[r_maxam_on_atom[i]+1]; for (j=0; j<=r_maxam_on_atom[i]; j++) { r_amoff_on_atom[i][j] = new int[r_nam_on_atom[i][j]]; for (k=0; k6) index = 6; else index = i; ExEnv::out0() << " ne(" << am[index] << ") "; } ExEnv::out0() << endl; for (i=0; iatom_symbol(i)); ExEnv::out0() << indent << scprintf("%3d %2s % 8.6f",i + 1, symbol.c_str(), double(molecule()->Z(i)) - e); if (atom_charges) { atom_charges[i] = molecule()->Z(i) - e; } for (j=0; j<=maxam_on_atom[i]; j++) { e = 0.0; for (k=0; k