| 1 | //
 | 
|---|
| 2 | // sobasis.cc --- implementation of the Integral class
 | 
|---|
| 3 | //
 | 
|---|
| 4 | // Copyright (C) 1998 Limit Point Systems, Inc.
 | 
|---|
| 5 | //
 | 
|---|
| 6 | // Author: Curtis Janssen <cljanss@limitpt.com>
 | 
|---|
| 7 | // Maintainer: LPS
 | 
|---|
| 8 | //
 | 
|---|
| 9 | // This file is part of the SC Toolkit.
 | 
|---|
| 10 | //
 | 
|---|
| 11 | // The SC Toolkit is free software; you can redistribute it and/or modify
 | 
|---|
| 12 | // it under the terms of the GNU Library General Public License as published by
 | 
|---|
| 13 | // the Free Software Foundation; either version 2, or (at your option)
 | 
|---|
| 14 | // any later version.
 | 
|---|
| 15 | //
 | 
|---|
| 16 | // The SC Toolkit is distributed in the hope that it will be useful,
 | 
|---|
| 17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 19 | // GNU Library General Public License for more details.
 | 
|---|
| 20 | //
 | 
|---|
| 21 | // You should have received a copy of the GNU Library General Public License
 | 
|---|
| 22 | // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
 | 
|---|
| 23 | // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
|---|
| 24 | //
 | 
|---|
| 25 | // The U.S. Government is granted a limited license as per AL 91-7.
 | 
|---|
| 26 | //
 | 
|---|
| 27 | 
 | 
|---|
| 28 | #ifdef __GNUC__
 | 
|---|
| 29 | #pragma implementation
 | 
|---|
| 30 | #endif
 | 
|---|
| 31 | 
 | 
|---|
| 32 | #include <string.h>
 | 
|---|
| 33 | 
 | 
|---|
| 34 | #include <util/misc/formio.h>
 | 
|---|
| 35 | #include <math/symmetry/pointgrp.h>
 | 
|---|
| 36 | #include <chemistry/qc/basis/petite.h>
 | 
|---|
| 37 | #include <chemistry/qc/basis/sobasis.h>
 | 
|---|
| 38 | 
 | 
|---|
| 39 | using namespace std;
 | 
|---|
| 40 | using namespace sc;
 | 
|---|
| 41 | 
 | 
|---|
| 42 | SOBasis::SOBasis(const Ref<GaussianBasisSet> &basis, const Ref<Integral>&integral)
 | 
|---|
| 43 | {
 | 
|---|
| 44 |   int i,j,k;
 | 
|---|
| 45 | 
 | 
|---|
| 46 |   basis_ = basis;
 | 
|---|
| 47 | 
 | 
|---|
| 48 |   Ref<Molecule> mol = basis_->molecule();
 | 
|---|
| 49 | 
 | 
|---|
| 50 |   CharacterTable ct = mol->point_group()->char_table();
 | 
|---|
| 51 |   nirrep_ = ct.nirrep();
 | 
|---|
| 52 | 
 | 
|---|
| 53 |   // count the number of so shells
 | 
|---|
| 54 |   nshell_ = 0;
 | 
|---|
| 55 |   for (i=0; i<mol->nunique(); i++) {
 | 
|---|
| 56 |     nshell_ += basis_->nshell_on_center(mol->unique(i));
 | 
|---|
| 57 |     }
 | 
|---|
| 58 | 
 | 
|---|
| 59 |   // map each ao shell to an so shell
 | 
|---|
| 60 |   int *aoshell_to_soshell = new int[basis_->nshell()];
 | 
|---|
| 61 |   int soshell = 0;
 | 
|---|
| 62 |   for (i=0; i<mol->nunique(); i++) {
 | 
|---|
| 63 |     for (j=0; j<basis_->nshell_on_center(mol->unique(i)); j++) {
 | 
|---|
| 64 |       for (k=0; k<mol->nequivalent(i); k++) {
 | 
|---|
| 65 |         int aoshell = basis_->shell_on_center(mol->equivalent(i,k),j);
 | 
|---|
| 66 |         aoshell_to_soshell[aoshell] = soshell;
 | 
|---|
| 67 |         }
 | 
|---|
| 68 |       soshell++;
 | 
|---|
| 69 |       }
 | 
|---|
| 70 |     }
 | 
|---|
| 71 | 
 | 
|---|
| 72 |   ncomp_ = new int[nirrep_];
 | 
|---|
| 73 |   for (i=0; i<nirrep_; i++) {
 | 
|---|
| 74 |     ncomp_[i] = ct.gamma(i).degeneracy();
 | 
|---|
| 75 |     if (ncomp_[i] != 1) {
 | 
|---|
| 76 |       ExEnv::out0()
 | 
|---|
| 77 |            << "WARNING: SOBasis not tested for degenerate point groups"
 | 
|---|
| 78 |            << endl;
 | 
|---|
| 79 |       }
 | 
|---|
| 80 |     }
 | 
|---|
| 81 | 
 | 
|---|
| 82 |   naofunc_ = new int[nshell_];
 | 
|---|
| 83 |   memset(naofunc_, 0, sizeof(int)*nshell_);
 | 
|---|
| 84 | 
 | 
|---|
| 85 |   nfunc_ = new int*[nshell_];
 | 
|---|
| 86 |   funcoff_ = new int*[nshell_];
 | 
|---|
| 87 |   for (i=0; i<nshell_; i++) {
 | 
|---|
| 88 |     nfunc_[i] = new int[nirrep_];
 | 
|---|
| 89 |     funcoff_[i] = new int[nirrep_];
 | 
|---|
| 90 |     for (j=0; j<nirrep_; j++) {
 | 
|---|
| 91 |       nfunc_[i][j] = 0;
 | 
|---|
| 92 |       }
 | 
|---|
| 93 |     }
 | 
|---|
| 94 | 
 | 
|---|
| 95 |   Ref<PetiteList> petite = new PetiteList(basis_, integral);
 | 
|---|
| 96 | 
 | 
|---|
| 97 |   int nblocks = petite->nblocks();
 | 
|---|
| 98 |   SO_block *soblocks = petite->aotoso_info();
 | 
|---|
| 99 | 
 | 
|---|
| 100 |   trans_ = new SOTransform[nshell_];
 | 
|---|
| 101 |   for (i=0; i<nblocks; i++) {
 | 
|---|
| 102 |     for (j=0; j<soblocks[i].len; j++) {
 | 
|---|
| 103 |       if (soblocks[i].so[j].length == 0) continue;
 | 
|---|
| 104 |       int bfn0 = soblocks[i].so[j].cont[0].bfn;
 | 
|---|
| 105 |       int aoshell0 = basis_->function_to_shell(bfn0);
 | 
|---|
| 106 |       int soshell0 = aoshell_to_soshell[aoshell0];
 | 
|---|
| 107 |       int atom0 = basis_->shell_to_center(aoshell0);
 | 
|---|
| 108 |       int nequiv0 = mol->nequivalent(mol->atom_to_unique(atom0));
 | 
|---|
| 109 |       trans_[soshell0].set_naoshell(nequiv0);
 | 
|---|
| 110 |       }
 | 
|---|
| 111 |     }
 | 
|---|
| 112 | 
 | 
|---|
| 113 |   int nfuncall = 0;
 | 
|---|
| 114 |   for (i=0; i<nblocks; i++) {
 | 
|---|
| 115 |     int irrep = ct.which_irrep(i);
 | 
|---|
| 116 |     for (j=0; j<soblocks[i].len; j++) {
 | 
|---|
| 117 |       if (soblocks[i].so[j].length == 0) continue;
 | 
|---|
| 118 |       int bfn0 = soblocks[i].so[j].cont[0].bfn;
 | 
|---|
| 119 |       int aoshell0 = basis_->function_to_shell(bfn0);
 | 
|---|
| 120 |       int soshell0 = aoshell_to_soshell[aoshell0];
 | 
|---|
| 121 |       int sofunc = nfunc_[soshell0][irrep];
 | 
|---|
| 122 | 
 | 
|---|
| 123 |       int naofunc = basis_->shell(aoshell0).nfunction();
 | 
|---|
| 124 |       if (naofunc_[soshell0] && (naofunc_[soshell0] != naofunc)) {
 | 
|---|
| 125 |         ExEnv::errn() << "ERROR: SOBasis: mismatch in naofunc" << endl;
 | 
|---|
| 126 |         abort();
 | 
|---|
| 127 |         }
 | 
|---|
| 128 |       naofunc_[soshell0] = naofunc;
 | 
|---|
| 129 | 
 | 
|---|
| 130 |       nfunc_[soshell0][irrep]++;
 | 
|---|
| 131 |       nfuncall++;
 | 
|---|
| 132 | 
 | 
|---|
| 133 |       for (k=0; k<soblocks[i].so[j].length; k++) {
 | 
|---|
| 134 |         int bfn = soblocks[i].so[j].cont[k].bfn;
 | 
|---|
| 135 |         double coef = soblocks[i].so[j].cont[k].coef;
 | 
|---|
| 136 |         int aoshell = basis_->function_to_shell(bfn);
 | 
|---|
| 137 |         int aoshellfunc = bfn - basis_->shell_to_function(aoshell);
 | 
|---|
| 138 |         int soshell = aoshell_to_soshell[aoshell];
 | 
|---|
| 139 | 
 | 
|---|
| 140 |         if (soshell != soshell0) {
 | 
|---|
| 141 |           ExEnv::outn() << "ERROR: SOBasis: shell changed" << endl;
 | 
|---|
| 142 |           abort();
 | 
|---|
| 143 |           }
 | 
|---|
| 144 | 
 | 
|---|
| 145 |         trans_[soshell].add_transform(aoshell,irrep, coef,aoshellfunc,sofunc);
 | 
|---|
| 146 |         }
 | 
|---|
| 147 |       }
 | 
|---|
| 148 |     }
 | 
|---|
| 149 | 
 | 
|---|
| 150 |   if (nfuncall != basis_->nbasis()) {
 | 
|---|
| 151 |     ExEnv::out0() << "ERROR: SOBasis: miscounted number of functions"
 | 
|---|
| 152 |          << endl;
 | 
|---|
| 153 |     print();
 | 
|---|
| 154 |     abort();
 | 
|---|
| 155 |     }
 | 
|---|
| 156 | 
 | 
|---|
| 157 |   delete[] soblocks;
 | 
|---|
| 158 |   delete[] aoshell_to_soshell;
 | 
|---|
| 159 | 
 | 
|---|
| 160 |   for (i=0; i<nshell_; i++) {
 | 
|---|
| 161 |     funcoff_[i][0] = 0;
 | 
|---|
| 162 |     for (j=1; j<nirrep_; j++) {
 | 
|---|
| 163 |       funcoff_[i][j] = funcoff_[i][j-1] + nfunc_[i][j-1];
 | 
|---|
| 164 |       }
 | 
|---|
| 165 |     }
 | 
|---|
| 166 | 
 | 
|---|
| 167 |   func_ = new int[nshell_];
 | 
|---|
| 168 |   irrep_ = new int[basis_->nbasis()];
 | 
|---|
| 169 |   func_within_irrep_ = new int[basis_->nbasis()];
 | 
|---|
| 170 |   nfunc_in_irrep_ = new int[nirrep_];
 | 
|---|
| 171 | 
 | 
|---|
| 172 |   for (i=0; i<nirrep_; i++) nfunc_in_irrep_[i] = 0;
 | 
|---|
| 173 | 
 | 
|---|
| 174 |   if (nshell_) {
 | 
|---|
| 175 |     func_[0] = 0;
 | 
|---|
| 176 |     for (i=1; i<nshell_; i++) {
 | 
|---|
| 177 |       func_[i] = func_[i-1] + nfunction(i-1);
 | 
|---|
| 178 |       }
 | 
|---|
| 179 |     int ibasis_ = 0;
 | 
|---|
| 180 |     for (i=0; i<nshell_; i++) {
 | 
|---|
| 181 |       for (j=0; j<nirrep_; j++) {
 | 
|---|
| 182 |         for (k=0; k<nfunc_[i][j]; k++,ibasis_++) {
 | 
|---|
| 183 |           irrep_[ibasis_] = j;
 | 
|---|
| 184 |           func_within_irrep_[ibasis_] = nfunc_in_irrep_[j]++;
 | 
|---|
| 185 |           }
 | 
|---|
| 186 |         }
 | 
|---|
| 187 |       }
 | 
|---|
| 188 |     }
 | 
|---|
| 189 | }
 | 
|---|
| 190 | 
 | 
|---|
| 191 | SOBasis::~SOBasis()
 | 
|---|
| 192 | {
 | 
|---|
| 193 |   for (int i=0; i<nshell_; i++) {
 | 
|---|
| 194 |     delete[] nfunc_[i];
 | 
|---|
| 195 |     delete[] funcoff_[i];
 | 
|---|
| 196 |     }
 | 
|---|
| 197 |   delete[] nfunc_;
 | 
|---|
| 198 |   delete[] funcoff_;
 | 
|---|
| 199 |   delete[] naofunc_;
 | 
|---|
| 200 |   delete[] ncomp_;
 | 
|---|
| 201 |   delete[] trans_;
 | 
|---|
| 202 |   delete[] func_;
 | 
|---|
| 203 |   delete[] irrep_;
 | 
|---|
| 204 |   delete[] func_within_irrep_;
 | 
|---|
| 205 |   delete[] nfunc_in_irrep_;
 | 
|---|
| 206 | }
 | 
|---|
| 207 | 
 | 
|---|
| 208 | int
 | 
|---|
| 209 | SOBasis::max_nfunction_in_shell() const
 | 
|---|
| 210 | {
 | 
|---|
| 211 |   int maxn = 0;
 | 
|---|
| 212 |   for (int i=0; i<nshell_; i++) {
 | 
|---|
| 213 |     int n = nfunction(i);
 | 
|---|
| 214 |     if (n > maxn) maxn = n;
 | 
|---|
| 215 |     }
 | 
|---|
| 216 |   return maxn;
 | 
|---|
| 217 | }
 | 
|---|
| 218 | 
 | 
|---|
| 219 | int
 | 
|---|
| 220 | SOBasis::nfunction(int ishell) const
 | 
|---|
| 221 | {
 | 
|---|
| 222 |   int n=0;
 | 
|---|
| 223 |   for (int i=0; i<nirrep_; i++) {
 | 
|---|
| 224 |     n += nfunc_[ishell][i];
 | 
|---|
| 225 |     }
 | 
|---|
| 226 |   return n;
 | 
|---|
| 227 | }
 | 
|---|
| 228 | 
 | 
|---|
| 229 | void
 | 
|---|
| 230 | SOBasis::print(ostream &o) const
 | 
|---|
| 231 | {
 | 
|---|
| 232 |   int i,j,k;
 | 
|---|
| 233 | 
 | 
|---|
| 234 |   ExEnv::out0()
 | 
|---|
| 235 |        << indent << "SOBasis:" << endl
 | 
|---|
| 236 |        << incindent
 | 
|---|
| 237 |        << basis_
 | 
|---|
| 238 |        << indent << "nshell(SO) = " << nshell_ << endl
 | 
|---|
| 239 |        << indent << "nirrep = " << nirrep_ << endl;
 | 
|---|
| 240 | 
 | 
|---|
| 241 |   ExEnv::out0() << indent << "ncomp = [";
 | 
|---|
| 242 |   for (i=0; i<nirrep_; i++) ExEnv::out0() << " " << ncomp_[i];
 | 
|---|
| 243 |   ExEnv::out0() << " ]" << endl;
 | 
|---|
| 244 | 
 | 
|---|
| 245 |   ExEnv::out0() << indent << "nfunc:" << endl;
 | 
|---|
| 246 |   for (i=0; i<nshell_; i++) {
 | 
|---|
| 247 |     ExEnv::out0() << indent << "  " << i << ":";
 | 
|---|
| 248 |     for (j=0; j<nirrep_; j++) ExEnv::out0() << " " << nfunc_[i][j];
 | 
|---|
| 249 |     ExEnv::out0() << endl;
 | 
|---|
| 250 |     }
 | 
|---|
| 251 | 
 | 
|---|
| 252 |   ExEnv::out0() << indent << "transform:" << endl;
 | 
|---|
| 253 |   ExEnv::out0() << incindent;
 | 
|---|
| 254 |   for (i=0; i<nshell_; i++) {
 | 
|---|
| 255 |     if (i>0) ExEnv::out0() << endl;
 | 
|---|
| 256 |     for (j=0; j<trans_[i].naoshell; j++) {
 | 
|---|
| 257 |       for (k=0; k<trans_[i].aoshell[j].nfunc; k++) {
 | 
|---|
| 258 |         ExEnv::out0() << indent
 | 
|---|
| 259 |              << scprintf("SO(%3d %2d %d [%2d]) += % 12.8f * AO(%3d %2d)",
 | 
|---|
| 260 |                          i,
 | 
|---|
| 261 |                          trans_[i].aoshell[j].func[k].sofunc,
 | 
|---|
| 262 |                          trans_[i].aoshell[j].func[k].irrep,
 | 
|---|
| 263 |                          function_offset_within_shell(
 | 
|---|
| 264 |                            i, trans_[i].aoshell[j].func[k].irrep)
 | 
|---|
| 265 |                          + trans_[i].aoshell[j].func[k].sofunc,
 | 
|---|
| 266 |                          trans_[i].aoshell[j].func[k].coef,
 | 
|---|
| 267 |                          trans_[i].aoshell[j].aoshell,
 | 
|---|
| 268 |                          trans_[i].aoshell[j].func[k].aofunc
 | 
|---|
| 269 |                          )
 | 
|---|
| 270 |              << endl;
 | 
|---|
| 271 |         }
 | 
|---|
| 272 |       }
 | 
|---|
| 273 |     }
 | 
|---|
| 274 |   ExEnv::out0() << decindent;
 | 
|---|
| 275 | 
 | 
|---|
| 276 |   ExEnv::out0() << decindent;
 | 
|---|
| 277 | }
 | 
|---|
| 278 | 
 | 
|---|
| 279 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
| 280 | 
 | 
|---|
| 281 | SOTransform::SOTransform()
 | 
|---|
| 282 | {
 | 
|---|
| 283 |   naoshell_allocated = 0;
 | 
|---|
| 284 |   naoshell = 0;
 | 
|---|
| 285 |   aoshell = 0;
 | 
|---|
| 286 | }
 | 
|---|
| 287 | 
 | 
|---|
| 288 | SOTransform::~SOTransform()
 | 
|---|
| 289 | {
 | 
|---|
| 290 |   delete[] aoshell;
 | 
|---|
| 291 | }
 | 
|---|
| 292 | 
 | 
|---|
| 293 | void
 | 
|---|
| 294 | SOTransform::set_naoshell(int n)
 | 
|---|
| 295 | {
 | 
|---|
| 296 |   naoshell = 0;
 | 
|---|
| 297 |   delete[] aoshell;
 | 
|---|
| 298 |   naoshell_allocated = n;
 | 
|---|
| 299 |   aoshell = new SOTransformShell[n];
 | 
|---|
| 300 | }
 | 
|---|
| 301 | 
 | 
|---|
| 302 | void
 | 
|---|
| 303 | SOTransform::add_transform(int aoshellnum, int irrep,
 | 
|---|
| 304 |                            double coef, int aofunc, int sofunc)
 | 
|---|
| 305 | {
 | 
|---|
| 306 |   int i;
 | 
|---|
| 307 |   for (i=0; i<naoshell; i++) {
 | 
|---|
| 308 |     if (aoshell[i].aoshell == aoshellnum) break;
 | 
|---|
| 309 |     }
 | 
|---|
| 310 |   if (i>=naoshell_allocated) {
 | 
|---|
| 311 |     ExEnv::outn() << "ERROR: SOTransform: add_transform allocation too small"
 | 
|---|
| 312 |          << endl;
 | 
|---|
| 313 |     abort();
 | 
|---|
| 314 |     }
 | 
|---|
| 315 |   aoshell[i].add_func(irrep,coef,aofunc,sofunc);
 | 
|---|
| 316 |   aoshell[i].aoshell = aoshellnum;
 | 
|---|
| 317 |   if (i==naoshell) naoshell++;
 | 
|---|
| 318 | }
 | 
|---|
| 319 | 
 | 
|---|
| 320 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
| 321 | 
 | 
|---|
| 322 | SOTransformShell::SOTransformShell()
 | 
|---|
| 323 | {
 | 
|---|
| 324 |   nfunc = 0;
 | 
|---|
| 325 |   func = 0;
 | 
|---|
| 326 | }
 | 
|---|
| 327 | 
 | 
|---|
| 328 | SOTransformShell::~SOTransformShell()
 | 
|---|
| 329 | {
 | 
|---|
| 330 |   delete[] func;
 | 
|---|
| 331 | }
 | 
|---|
| 332 | 
 | 
|---|
| 333 | void
 | 
|---|
| 334 | SOTransformShell::add_func(int irrep, double coef, int aofunc, int sofunc)
 | 
|---|
| 335 | {
 | 
|---|
| 336 |   SOTransformFunction *newfunc = new SOTransformFunction[nfunc+1];
 | 
|---|
| 337 |   for (int i=0; i<nfunc; i++) newfunc[i] = func[i];
 | 
|---|
| 338 |   delete[] func;
 | 
|---|
| 339 |   func = newfunc;
 | 
|---|
| 340 |   func[nfunc].irrep = irrep;
 | 
|---|
| 341 |   func[nfunc].coef = coef;
 | 
|---|
| 342 |   func[nfunc].aofunc = aofunc;
 | 
|---|
| 343 |   func[nfunc].sofunc = sofunc;
 | 
|---|
| 344 |   nfunc++;
 | 
|---|
| 345 | }
 | 
|---|
| 346 | 
 | 
|---|
| 347 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
| 348 | 
 | 
|---|
| 349 | // Local Variables:
 | 
|---|
| 350 | // mode: c++
 | 
|---|
| 351 | // c-file-style: "CLJ-CONDENSED"
 | 
|---|
| 352 | // End:
 | 
|---|