Source code for pyscf.geomopt.addons

#!/usr/bin/env python
# Copyright 2014-2019 The PySCF Developers. All Rights Reserved.
#
# 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.

'''
Helper functions for geometry optimizer
'''

import numpy
from pyscf import lib

[docs]def as_pyscf_method(mol, scan_function): '''Creat an wrapper for the given scan_function, to make it work as a pyscf gradients scanner. The wrapper can be passed to :func:`optimize`. Args: scan_function : [mol] => (e_tot, grad) Examples:: >>> mol = gto.M(atom='H; H 1 1.2', basis='ccpvdz') >>> scan_fn = scf.RHF(mol).nuc_grad_method().as_scanner() >>> m = as_pyscf_method(mol, scan_fn) >>> pyscf.geomopt.berny_solver.kernel(m) ''' from pyscf.grad.rhf import GradientsBasics class OmniGrad(lib.GradScanner): def __init__(self, g): self.__dict__.update(g.__dict__) self.base = g.base def __call__(self, mol): self.e_tot, grad = scan_function(mol) return self.e_tot, grad @property def converged(self): return True class Gradients(GradientsBasics): def as_scanner(self): return OmniGrad(self) class OmniMethod(object): def __init__(self, mol): self.mol = mol self.verbose = mol.verbose self.stdout = mol.stdout def Gradients(self): return Gradients(self) nuc_grad_method = Gradients return OmniMethod(mol)
[docs]def dump_mol_geometry(mol, new_coords, log=None): '''Dump the molecular geometry (new_coords) and the displacement wrt old geometry. Args: new_coords (ndarray) : Cartesian coordinates in Angstrom ''' if log is None: dump = mol.stdout.write else: dump = log.stdout.write old_coords = mol.atom_coords() * lib.param.BOHR new_coords = numpy.asarray(new_coords) dx = new_coords - old_coords dump('Cartesian coordinates (Angstrom)\n') dump(' Atom New coordinates dX dY dZ\n') for i in range(mol.natm): dump('%4s %10.6f %10.6f %10.6f %9.6f %9.6f %9.6f\n' % (mol.atom_symbol(i), new_coords[i,0], new_coords[i,1], new_coords[i,2], dx[i,0], dx[i,1], dx[i,2]))
[docs]def symmetrize(mol, coords): '''Symmetrize the structure of a molecule.''' from pyscf.grad.rhf import symmetrize # Symmetrizing coordinates is the same to the symmetrization of gradients. return symmetrize(mol, coords)