Codebase list votca-xtp / debian/latest src / libxtp / ecpaobasis.cc
debian/latest

Tree @debian/latest (Download .tar.gz)

ecpaobasis.cc @debian/latestraw · history · blame

/*
 *            Copyright 2009-2020 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      Licensed under the Apache License, Version 2.0 (the "License")
 *
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *              http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// Standard includes
#include <vector>

// Local VOTCA includes
#include "votca/xtp/ecpaobasis.h"
#include "votca/xtp/ecpbasisset.h"
#include "votca/xtp/qmmolecule.h"

namespace votca {
namespace xtp {

ECPAOShell& ECPAOBasis::addShell(const ECPShell& shell, const QMAtom& atom,
                                 Index startIndex, L Lmax) {
  _aoshells.push_back(ECPAOShell(shell, atom, startIndex, Lmax));
  return _aoshells.back();
}

std::vector<std::vector<const ECPAOShell*> > ECPAOBasis::ShellsPerAtom() const {
  std::vector<std::vector<const ECPAOShell*> > result(_ncore_perAtom.size());
  for (const ECPAOShell& shell : _aoshells) {
    result[shell.getAtomIndex()].push_back(&shell);
  }
  return result;
}

void ECPAOBasis::AddECPChargeToMolecule(QMMolecule& mol) const {
  for (Index i = 0; i < mol.size(); i++) {
    mol[i]._ecpcharge = _ncore_perAtom[i];
  }
}

void ECPAOBasis::clear() {
  _name = "";
  _aoshells.clear();
  _ncore_perAtom.clear();
  _AOBasisSize = 0;
}

void ECPAOBasis::UpdateShellPositions(const QMMolecule& mol) {
  for (ECPAOShell& shell : _aoshells) {
    shell._pos = mol[shell.getAtomIndex()].getPos();
  }
}

void ECPAOBasis::add(const ECPAOBasis& other) {
  Index atomindex_offset = Index(_ncore_perAtom.size());
  for (ECPAOShell shell : other) {
    shell._atomindex += atomindex_offset;
    shell._startIndex = _AOBasisSize;
    _AOBasisSize += shell.getNumFunc();
    _aoshells.push_back(shell);
  }

  _ncore_perAtom.insert(_ncore_perAtom.end(), other._ncore_perAtom.begin(),
                        other._ncore_perAtom.end());
}

std::vector<std::string> ECPAOBasis::Fill(const ECPBasisSet& bs,
                                          QMMolecule& atoms) {
  _AOBasisSize = 0;
  _aoshells.clear();
  _ncore_perAtom.clear();
  _name = bs.Name();
  std::vector<std::string> non_ecp_elements;
  Index index = 0;
  for (QMAtom& atom : atoms) {
    std::string name = atom.getElement();

    bool element_exists = true;

    try {
      bs.getElement(name);
    } catch (std::runtime_error& error) {
      element_exists = false;

      if (std::find(non_ecp_elements.begin(), non_ecp_elements.end(), name) !=
          non_ecp_elements.end()) {
        non_ecp_elements.push_back(name);
      }
    }

    if (element_exists) {
      const ECPElement& element = bs.getElement(name);
      _ncore_perAtom.push_back(element.getNcore());
      L lmax = element.getLmax();
      for (const ECPShell& shell : element) {
        ECPAOShell& aoshell = addShell(shell, atom, _AOBasisSize, lmax);
        index++;
        _AOBasisSize += NumFuncShell(shell.getL());
        for (const ECPGaussianPrimitive& gaussian : shell) {
          aoshell.addGaussian(gaussian);
        }
      }
    } else {
      _ncore_perAtom.push_back(0);
    }
  }

  AddECPChargeToMolecule(atoms);
  return non_ecp_elements;
}

void ECPAOBasis::WriteToCpt(CheckpointWriter& w) const {
  w(_name, "name");
  w(_AOBasisSize, "basissize");

  w(_ncore_perAtom, "atomic ecp charges");
  Index numofprimitives = 0;
  for (const auto& shell : _aoshells) {
    numofprimitives += shell.getSize();
  }

  // this is all to make dummy ECPAOGaussian
  ECPGaussianPrimitive d(2, 0.1, 0.1);
  ECPAOGaussianPrimitive dummy2(d);

  CptTable table = w.openTable("Contractions", dummy2, numofprimitives);

  std::vector<ECPAOGaussianPrimitive::data> dataVec(numofprimitives);
  Index i = 0;
  for (const auto& shell : _aoshells) {
    for (const auto& gaussian : shell) {
      gaussian.WriteData(dataVec[i], shell);
      i++;
    }
  }

  table.write(dataVec);
}

void ECPAOBasis::ReadFromCpt(CheckpointReader& r) {
  clear();
  r(_name, "name");
  r(_AOBasisSize, "basissize");

  if (_AOBasisSize > 0) {
    r(_ncore_perAtom, "atomic ecp charges");
    // this is all to make dummy ECPAOGaussian
    ECPGaussianPrimitive d(2, 0.1, 0.1);
    ECPAOGaussianPrimitive dummy2(d);

    CptTable table = r.openTable("Contractions", dummy2);
    std::vector<ECPAOGaussianPrimitive::data> dataVec(table.numRows());
    table.read(dataVec);
    Index laststartindex = -1;
    for (std::size_t i = 0; i < table.numRows(); ++i) {
      if (dataVec[i].startindex != laststartindex) {
        _aoshells.push_back(ECPAOShell(dataVec[i]));
        laststartindex = dataVec[i].startindex;
      } else {
        _aoshells.back()._gaussians.push_back(
            ECPAOGaussianPrimitive(dataVec[i]));
      }
    }
  }
}

std::ostream& operator<<(std::ostream& out, const ECPAOBasis& ecp) {

  out << "Name:" << ecp.Name() << "\n";
  out << " Functions:" << ecp.ECPAOBasisSize()
      << " Shells:" << ecp._aoshells.size() << "\n";
  for (const auto& shell : ecp) {
    out << shell;
  }
  out << "\n"
      << " Atomcharges:";
  for (Index i = 0; i < Index(ecp._ncore_perAtom.size()); i++) {
    out << i << " " << ecp._ncore_perAtom[i] << " ";
  }
  return out;
}

}  // namespace xtp
}  // namespace votca