def test_uniformgrid_from_molecule_o2_uhf(): with path('chemtools.data', 'o2_uhf.fchk') as fpath: mol = Molecule.from_file(str(fpath)) # create cube file from molecule: cube = UniformGrid.from_molecule(mol) # test the cube gives the right result: origin_result = [-5.0, -5.0, -6.1] axes_result = [[0.0, 0.0, 0.2], [0.0, 0.2, 0.0], [0.2, 0.0, 0.0]] shape_result = [61, 50, 50] weight_result = np.full(cube.npoints, 0.0080) np.testing.assert_array_almost_equal(cube.origin, origin_result, decimal=7) np.testing.assert_array_almost_equal(cube.axes, axes_result, decimal=7) np.testing.assert_array_equal(cube.shape, shape_result) np.testing.assert_array_almost_equal(cube.weights(), weight_result, decimal=7) np.testing.assert_array_almost_equal(cube.weights(method='R0'), weight_result, decimal=7) np.testing.assert_array_almost_equal(cube.weights(method='R'), weight_result, decimal=7) # test integration of Fukui functions: tool = LocalConceptualDFT.from_file(str(fpath), model='linear', points=cube.points) ffm_default = cube.integrate(tool.ff_minus) ffm_r = cube.integrate(tool.ff_minus, method='R') ffm_r0 = cube.integrate(tool.ff_minus, method='R0') np.testing.assert_almost_equal(ffm_default, ffm_r, decimal=7) np.testing.assert_almost_equal(ffm_r, ffm_r0, decimal=7) np.testing.assert_almost_equal(ffm_default, 1.000, decimal=2) np.testing.assert_almost_equal(ffm_default, 1.000, decimal=2) np.testing.assert_almost_equal(ffm_default, 1.000, decimal=2)
def test_critical_point_h2o(): # test against multiwfn 3.6 dev src with path("chemtools.data", "data_multiwfn36_fchk_h2o_q+0_ub3lyp_ccpvtz.npz") as fname: data = np.load(str(fname)) nna, bcp = data["nna_coords"], data["bcp_coords"] # find critical points with path("chemtools.data", "h2o_q+0_ub3lyp_ccpvtz.fchk") as fpath: mol = Molecule.from_file(fpath) cub = UniformGrid.from_molecule(mol, spacing=0.15, extension=0.1, rotate=False) top = TopologicalTool.from_molecule(mol, points=cub.points) # check NA assert len(top.nna) == 3 assert sum([np.allclose(top.nna[0].coordinate, c, rtol=0.0) for c in nna]) == 1 assert sum([np.allclose(top.nna[1].coordinate, c, rtol=0.0) for c in nna]) == 1 assert sum([np.allclose(top.nna[2].coordinate, c, rtol=0.0) for c in nna]) == 1 # check BCP assert len(top.bcp) == 2 assert sum([np.allclose(top.bcp[0].coordinate, c, rtol=0.0) for c in bcp]) == 1 assert sum([np.allclose(top.bcp[1].coordinate, c, rtol=0.0) for c in bcp]) == 1 # check total number of CP assert len(top.rcp) == 0 assert len(top.ccp) == 0 assert len(top.cps) == 5 assert top.poincare_hopf_equation
def from_molecule(cls, molecule, spin="ab", index=None, points=None): """Initialize class from ``Molecule`` object. Parameters ---------- molecule : instance of `Molecule` class. Instance of `Molecular` class. spin : str, optional The type of occupied spin orbitals; options are "a", "b" & "ab". index : int or Sequence of int, optional Sequence of integers representing the index of spin orbitals. If None, all occupied spin orbitals are included. points : np.ndarray, optional Cartesian coordinates of points used for critical point search. If None, cubic grid points with spacing=0.1 & extension=0.1 are used. """ if points is None: points = UniformGrid.from_molecule(molecule, spacing=0.1, extension=0.1).points func_dens = cls._wrapper_compute_density(molecule, spin=spin, index=index) func_grad = cls._wrapper_compute_gradient(molecule, spin=spin, index=index) func_hess = cls._wrapper_compute_hessian(molecule, spin=spin, index=index) return cls(func_dens, func_grad, func_hess, points, molecule.coordinates)
def _check_grid(molecule, grid): if grid is None: grid = UniformGrid.from_molecule(molecule, spacing=0.1, extension=2.0) elif not hasattr(grid, 'points'): raise ValueError('Argument grid should have "points" attribute!') return grid
def load_molecule_and_grid(fname, cube): """Return instances of molecule and uniform cubic grid. Parameters ---------- fname : str Path to wave-function file. cube : str Uniform cubic grid specifications. """ # load molecule mol = Molecule.from_file(fname) if cube.endswith(".cube"): # load & check cube file cube = UniformGrid.from_cube(cube) if np.allclose(mol.numbers, cube.numbers): raise ValueError( "Atomic number in {0} & {1} should be the same!".format( fname, cube)) if np.allclose(mol.coordinates, cube.coordinates): raise ValueError( "Atomic coordinates in {0} & {1} should be the same!".format( cube.fname, cube.cube)) elif len(cube.split(",")) == 2: # make a cubic grid spacing, extension = [float(item) for item in cube.split(",")] cube = UniformGrid.from_molecule(mol, spacing=spacing, extension=extension, rotate=True) else: raise ValueError("Argument cube={0} is not recognized!".format(cube)) return mol, cube
def generate_scripts(self, fname, spin='a', index=None, isosurf=0.05, grid=None): """Generate VMD script(s) and cube file(s) to visualize MO iso-surface of given orbitals. Parameters ---------- fname : str A string representing the path to a fname of generated files. The VMD script and cube file will be named fname_mo{index}.vmd and fname_mo{index}.cube, respectively. spin : str, optional The type of occupied spin orbitals. Choose either 'a' or 'b'. index : int, optional Integer representing the index of spin orbital to visualize. Spin orbitals are each indexed from 1 to :attr:`nbasis`. If None, files for visualizing all orbitals are generated. isosurf : float, optional Value of MO iso-surface used in VMD script. grid : UniformGrid, optional Instance of UniformGrid used for computation and generating cube file(s). If None, a cubic grid is constructed from molecule with spacing=0.2 & extension=5.0. """ if spin not in ['a', 'b']: raise ValueError('Argument spin can only be "a" or "b".') if index is not None and not isinstance(index, int): raise ValueError('Argument index is either None or an integer for visualization. ' 'Given index={0}'.format(index)) if grid is None: grid = UniformGrid.from_molecule(self._molecule, spacing=0.2, extension=5.0, rotate=True) elif not isinstance(grid, UniformGrid): raise ValueError('Argument grid should be a UniformGrid to generate cube files.') if index is None: spin_index = {'a': 0, 'b': 1} index = range(1, self._molecule.mo.homo_index[spin_index[spin]] + 1) else: index = [index] for mo_index in index: vmdname = fname + '_mo{0}.vmd'.format(mo_index) cubname = fname + '_mo{0}.cube'.format(mo_index) mo_value = self.compute_orbital_expression(grid.points, spin=spin, index=mo_index) grid.generate_cube(cubname, mo_value) print_vmd_script_isosurface(vmdname, cubname, isosurf=isosurf, negative=True, material='BlownGlass')
def test_uniformgrid_o2_raises(): with path('chemtools.data', 'o2_uhf.fchk') as fpath: mol = Molecule.from_file(str(fpath)) cube = UniformGrid.from_molecule(mol) tool = LocalConceptualDFT.from_file(str(fpath), model='linear', points=cube.points) o = np.array([-3.0, -3.0, -3.0]) a = np.array([[2.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]]) s = np.array([3, 3, 3]) # check ValueError assert_raises(ValueError, UniformGrid, mol.numbers, mol.pseudo_numbers, mol.coordinates, np.array([0.]), a, s) assert_raises(ValueError, UniformGrid, mol.numbers, mol.pseudo_numbers, mol.coordinates, o, np.array([0.]), s) assert_raises(ValueError, UniformGrid, mol.numbers, mol.pseudo_numbers, mol.coordinates, o, a, np.array([0.])) assert_raises(ValueError, UniformGrid.from_cube, 'test.wrong_end') assert_raises(ValueError, cube.generate_cube, 'test.wrong_end', tool.ff_minus) assert_raises(ValueError, cube.generate_cube, 'test.cube', np.array([0.])) assert_raises(ValueError, cube.weights, method='erroneous') assert_raises(ValueError, cube.integrate, np.array([0.]))
def test_uniformgrid_points_h2o(): # replace this test with a better one later with path('chemtools.data', 'h2o_dimer_pbe_sto3g.fchk') as fpath: cube = UniformGrid.from_file(fpath, spacing=2.0, extension=0.0, rotate=True) expected = np.array([[-2.31329824e+00, -2.00000000e+00, 3.82735565e+00], [-2.31329824e+00, -4.99999997e-09, 3.82735565e+00], [-3.19696330e-01, -2.00000000e+00, 3.98720381e+00], [-3.19696330e-01, -4.99999997e-09, 3.98720381e+00], [-2.15345008e+00, -2.00000000e+00, 1.83375375e+00], [-2.15345008e+00, -4.99999997e-09, 1.83375375e+00], [-1.59848169e-01, -2.00000000e+00, 1.99360191e+00], [-1.59848169e-01, -4.99999997e-09, 1.99360191e+00], [-1.99360191e+00, -2.00000000e+00, -1.59848162e-01], [-1.99360191e+00, -4.99999997e-09, -1.59848162e-01], [-6.77400003e-09, -2.00000000e+00, 0.00000000e+00], [-6.77400003e-09, -4.99999997e-09, 0.00000000e+00], [-1.83375375e+00, -2.00000000e+00, -2.15345007e+00], [-1.83375375e+00, -4.99999997e-09, -2.15345007e+00], [ 1.59848155e-01, -2.00000000e+00, -1.99360191e+00], [ 1.59848155e-01, -4.99999997e-09, -1.99360191e+00]]) assert_allclose(cube.points, expected, rtol=1.e-7, atol=1.e-7)
def test_cube_h2o_dimer(): # test against previous generated .cube files with path('chemtools.data', 'h2o_dimer_pbe_sto3g-dens.cube') as file_path: cube = UniformGrid.from_cube(file_path) mol1 = Molecule.from_file(str(file_path)) with tmpdir('chemtools.test.test_base.test_cube_h2o_dimer') as dn: cube2 = '%s/%s' % (dn, 'h2o_dimer_pbe_sto3g-dens.cube') cube.generate_cube(cube2, mol1.cube_data) cube2 = '%s/%s' % (dn, 'h2o_dimer_pbe_sto3g-dens.cube') mol2 = Molecule.from_file(cube2) # Check coordinates np.testing.assert_array_almost_equal(mol1.coordinates, mol2.coordinates, decimal=6) np.testing.assert_equal(mol1.numbers, mol2.numbers) # Check grid data ugrid1 = mol1.grid ugrid2 = mol2.grid np.testing.assert_array_almost_equal(ugrid1.grid_rvecs, ugrid2.grid_rvecs, decimal=6) np.testing.assert_equal(ugrid1.shape, ugrid2.shape) data1 = mol1.cube_data / mol1.cube_data data2 = mol2.cube_data / mol1.cube_data np.testing.assert_array_almost_equal(data1, data2, decimal=4) np.testing.assert_equal(mol1.pseudo_numbers, mol2.pseudo_numbers)
def test_uniformgrid_from_file_o2_uhf(): with path('chemtools.data', 'o2_uhf.fchk') as fpath: mol = Molecule.from_file(str(fpath)) # create cube file from file: cube = UniformGrid.from_file(fpath, spacing=0.5, extension=6.0, rotate=False) # test the cube gives the right result: origin_result = [-6.0, -6.0, -7.25] axes_result = [[0.5, 0.0, 0.0], [0.0, 0.5, 0.0], [0.0, 0.0, 0.5]] shape_result = [24, 24, 29] weight_result = np.full(cube.npoints, 0.125) np.testing.assert_array_almost_equal(cube.origin, origin_result, decimal=7) np.testing.assert_array_almost_equal(cube.axes, axes_result, decimal=7) np.testing.assert_array_equal(cube.shape, shape_result) np.testing.assert_array_equal(cube.numbers, mol.numbers) np.testing.assert_array_almost_equal(cube.coordinates, mol.coordinates, decimal=10) np.testing.assert_array_almost_equal(cube.pseudo_numbers, mol.pseudo_numbers, decimal=10) np.testing.assert_array_almost_equal(cube.weights(), weight_result, decimal=7) np.testing.assert_array_almost_equal(cube.weights(method='R0'), weight_result, decimal=7) np.testing.assert_array_almost_equal(cube.weights(method='R'), weight_result, decimal=7)
def test_critical_point_c4h4(): # test against multiwfn 3.6 dev src with path("chemtools.data", "data_multiwfn36_fchk_c4h4_ub3lyp_ccpvdz.npz") as fname: data = np.load(str(fname)) nna, bcp = data["nna_coords"], data["bcp_coords"] rcp, ccp = data["rcp_coords"], data["ccp_coords"] # find critical points with path("chemtools.data", "c4h4_ub3lyp_ccpvdz.fchk") as fpath: mol = Molecule.from_file(fpath) cub = UniformGrid.from_molecule(mol, spacing=0.25, extension=0.1, rotate=False) top = TopologicalTool.from_molecule(mol, points=cub.points) # check NA assert len(top.nna) == 8 assert sum([ np.allclose(top.nna[0].coordinate, c, rtol=0.0, atol=1.0e-5) for c in nna ]) == 1 assert sum([ np.allclose(top.nna[1].coordinate, c, rtol=0.0, atol=1.0e-5) for c in nna ]) == 1 assert sum([ np.allclose(top.nna[2].coordinate, c, rtol=0.0, atol=1.0e-5) for c in nna ]) == 1 assert sum([ np.allclose(top.nna[3].coordinate, c, rtol=0.0, atol=1.0e-5) for c in nna ]) == 1 assert sum([ np.allclose(top.nna[4].coordinate, c, rtol=0.0, atol=1.0e-5) for c in nna ]) == 1 assert sum([ np.allclose(top.nna[5].coordinate, c, rtol=0.0, atol=1.0e-5) for c in nna ]) == 1 assert sum([ np.allclose(top.nna[6].coordinate, c, rtol=0.0, atol=1.0e-5) for c in nna ]) == 1 assert sum([ np.allclose(top.nna[7].coordinate, c, rtol=0.0, atol=1.0e-5) for c in nna ]) == 1 # check BCP assert len(top.bcp) == 10 assert sum([ np.allclose(top.bcp[0].coordinate, c, rtol=0.0, atol=1.0e-5) for c in bcp ]) == 1 assert sum([ np.allclose(top.bcp[2].coordinate, c, rtol=0.0, atol=1.0e-5) for c in bcp ]) == 1 assert sum([ np.allclose(top.bcp[3].coordinate, c, rtol=0.0, atol=1.0e-5) for c in bcp ]) == 1 assert sum([ np.allclose(top.bcp[4].coordinate, c, rtol=0.0, atol=1.0e-5) for c in bcp ]) == 1 assert sum([ np.allclose(top.bcp[5].coordinate, c, rtol=0.0, atol=1.0e-5) for c in bcp ]) == 1 assert sum([ np.allclose(top.bcp[6].coordinate, c, rtol=0.0, atol=1.0e-5) for c in bcp ]) == 1 assert sum([ np.allclose(top.bcp[7].coordinate, c, rtol=0.0, atol=1.0e-5) for c in bcp ]) == 1 assert sum([ np.allclose(top.bcp[8].coordinate, c, rtol=0.0, atol=1.0e-5) for c in bcp ]) == 1 assert sum([ np.allclose(top.bcp[9].coordinate, c, rtol=0.0, atol=1.0e-5) for c in bcp ]) == 1 # check RCP assert len(top.rcp) == 4 assert sum([ np.allclose(top.rcp[0].coordinate, c, rtol=0.0, atol=1.0e-5) for c in rcp ]) == 1 assert sum([ np.allclose(top.rcp[1].coordinate, c, rtol=0.0, atol=1.0e-5) for c in rcp ]) == 1 assert sum([ np.allclose(top.rcp[2].coordinate, c, rtol=0.0, atol=1.0e-5) for c in rcp ]) == 1 assert sum([ np.allclose(top.rcp[3].coordinate, c, rtol=0.0, atol=1.0e-5) for c in rcp ]) == 1 # check CCP assert len(top.ccp) == 1 assert sum([ np.allclose(top.ccp[0].coordinate, c, rtol=0.0, atol=1.0e-5) for c in ccp ]) == 1 # check total number of CP assert len(top.cps) == 23 assert top.poincare_hopf_equation