예제 #1
0
def psi4_esp(method, basis, molecule):
    """ Computes QM electrostatic potential

    Parameters
    ----------
    method : str 
        QM method
    basis : str
        basis set
    molecule : psi4.Molecule instance

    Returns
    -------
    np.array
        QM electrostatic potential.

    Note
    -----
    Psi4 read grid information from grid.dat file
    """
    import psi4
    mol = psi4.geometry(molecule.create_psi4_string_from_molecule())
    psi4.set_options({'basis': basis})
    e, wfn = psi4.prop(method, properties=['GRID_ESP'], return_wfn=True)
    psi4.core.clean()
    return np.loadtxt('grid_esp.dat')   
예제 #2
0
파일: psi4_wrapper.py 프로젝트: CCQC/janus
 def compute_energy_and_charges(self, charge_method='MULLIKEN_CHARGES'):
     """
     Calls Psi4 to obtain the self.energy, self.wavefunction, 
     and self.charges on each atom. This method for correlated methods.
     
     Note
     ----
     Think about passing in wavefunction instead of calling for energy and wavefunction
     """
     self.set_up_psi4()
     self.energy, self.wavefunction = psi4.prop(self.method,
                                                properties=[charge_method],
                                                return_wfn=True)
     self.charges = np.asarray(self.wavefunction.atomic_point_charges())
예제 #3
0
def get_elpot(xs,ys,zs,Dnew=None,wfn=None,update=False):
  if (update):
    Dreal = Dnew.real
    wfn.oeprop.set_Da_ao(psi4.core.Matrix.from_array(Dreal))
    wfn.oeprop.compute()
    Vvals = wfn.oeprop.Vvals()
  else: 
    with open('grid.dat', 'w') as fout:
        for i in range(xs.np.shape[0]):
            fout.write("{: 21.18e} {: 21.18e} {: 21.18e}\n".format(xs.np[i], ys.np[i], zs.np[i]))
    fout.close() 
    ene,wfn = psi4.prop('blyp', properties=['GRID_ESP'], return_wfn=True) 
    #ene,wfn = psi4.energy('blyp',return_wfn=True)
 
    Vvals = wfn.oeprop.Vvals()
  return Vvals, wfn
예제 #4
0
파일: GRID.py 프로젝트: CFEL-CMI/PECD
def CALC_ESP_PSI4(dir, params):
    os.chdir(dir)
    psi4.core.be_quiet()
    properties_origin = ["COM"]
    #psi4.core.set_output_file(dir, False)
    ang_au = CONSTANTS.angstrom_to_au
    xS = 0.0 * ang_au
    yS = 0.0 * ang_au
    zS = 0.0 * ang_au

    xH1 = 0.0 * ang_au
    yH1 = 0.1 * ang_au
    zH1 = 1.2 * ang_au

    xH2 = 0.1 * ang_au
    yH2 = 1.4 * ang_au
    zH2 = -0.1 * ang_au

    mol = psi4.geometry("""
    1 2
    noreorient
    units au
    
    S	{0} {1} {2}
    H1	{3} {4} {5}
    H2	{6} {7} {8}

    """.format(xS, yS, zS, xH1, yH1, zH1, xH2, yH2, zH2))

    psi4.set_options({
        'basis': params['scf_basis'],
        'e_convergence': params['scf_enr_conv'],
        'reference': params['scf_method']
    })
    E, wfn = psi4.prop('scf', properties=["GRID_ESP"], return_wfn=True)
    Vvals = wfn.oeprop.Vvals()
    os.chdir("../")
    return Vvals
예제 #5
0
파일: GRID.py 프로젝트: CFEL-CMI/PECD
def CALC_ESP_PSI4_ROT(dir, params, mol_xyz):
    os.chdir(dir)
    psi4.core.be_quiet()
    properties_origin = [
        "COM"
    ]  #[“NUCLEAR_CHARGE”] or ["COM"] #here might be the shift!
    ang_au = CONSTANTS.angstrom_to_au

    if params['molec_name'] == "d2s":
        mol = psi4.geometry("""
        1 2
        noreorient
        units au
        nocom
        S	{0} {1} {2}
        H	{3} {4} {5}
        H	{6} {7} {8}

        """.format(
            mol_xyz[0, 0],
            mol_xyz[1, 0],
            mol_xyz[2, 0],
            mol_xyz[0, 1],
            mol_xyz[1, 1],
            mol_xyz[2, 1],
            mol_xyz[0, 2],
            mol_xyz[1, 2],
            mol_xyz[2, 2],
        ))

    if params['molec_name'] == "cmethane":
        mol = psi4.geometry("""
        1 2
        units au
        C
        H  1 CH1
        H  1 CH2  2 HCH
        H  1 CH3  2 HCH    3  120.0
        H  1 CH4  2 HCH    3  240.0

        CH1    = {0}
        CH2    = {1}
        CH3    = {2}
        CH4    = {3}
        HCH    = 109.471209
        """.format(params['mol_geometry']['r1'], params['mol_geometry']['r2'],
                   params['mol_geometry']['r3'], params['mol_geometry']['r4']))

    elif params['molec_name'] == "n2":
        mol = psi4.geometry("""
        1 2
        noreorient
        units au
        nocom
        N	{0} {1} {2}
        N	{3} {4} {5}

        """.format(mol_xyz[0, 0], mol_xyz[1, 0], mol_xyz[2, 0], mol_xyz[0, 1],
                   mol_xyz[1, 1], mol_xyz[2, 1]))

    elif params['molec_name'] == "co":
        mol = psi4.geometry("""
        1 2
        noreorient
        units au
        nocom
        C	{0} {1} {2}
        O	{3} {4} {5}

        """.format(mol_xyz[0, 0], mol_xyz[1, 0], mol_xyz[2, 0], mol_xyz[0, 1],
                   mol_xyz[1, 1], mol_xyz[2, 1]))

    elif params['molec_name'] == "ocs":
        mol = psi4.geometry("""
        1 2
        noreorient
        units au
        
        O	{0} {1} {2}
        C	{3} {4} {5}
        S	{6} {7} {8}

        """.format(
            mol_xyz[0, 0],
            mol_xyz[1, 0],
            mol_xyz[2, 0],
            mol_xyz[0, 1],
            mol_xyz[1, 1],
            mol_xyz[2, 1],
            mol_xyz[0, 2],
            mol_xyz[1, 2],
            mol_xyz[2, 2],
        ))

    elif params['molec_name'] == "h2o":
        mol = psi4.geometry("""
        1 2
        noreorient
        units au
        
        O	{0} {1} {2}
        H	{3} {4} {5}
        H	{6} {7} {8}

        """.format(
            0.0,
            0.0,
            0.0,
            0.0,
            1.0,
            1.0,
            0.0,
            -2.0,
            2.0,
        ))

    elif params['molec_name'] == "h":
        mol = psi4.geometry("""
        1 1
        noreorient
        units au
        nocom
        H	{0} {1} {2}

        """.format(0.0, 0.0, 1.0))

    elif params['molec_name'] == "c":
        mol = psi4.geometry("""
        1 2
        noreorient
        units au
        
        C	{0} {1} {2}

        """.format(0.0, 0.0, 0.0))

    psi4.set_options({
        'basis': params['scf_basis'],
        'e_convergence': params['scf_enr_conv'],
        'reference': params['scf_method']
    })
    E, wfn = psi4.prop('scf', properties=["GRID_ESP"], return_wfn=True)
    Vvals = wfn.oeprop.Vvals()
    os.chdir("../")
    return Vvals

    #h2o = psi4.geometry("""
    #1 2
    #noreorient
    #O            0.0     0.0    0.000000000000
    #H            0.757    0.586     0.000000000000
    #H            -0.757    0.586     0.000000000000
    #""")

    #D2S geometry (NIST)
    # r(S-D) = 1.336 ang
    #angle = 92.06
    """
예제 #6
0
파일: driver.py 프로젝트: qize/resp
def resp(molecules, options_list=None, intermol_constraints=None):
    """RESP code driver.

    Parameters
    ---------- 
    molecules : list
        list of psi4.Molecule instances
    options_list : list, optional
        list of dictionaries of user's defined options
    intermol_constraints : dict, optional
        dictionary of options for multi-molecules fitting

    Returns
    -------
    charges : list
        list of charges

    Note
    ----
    output files : mol_results.dat: fitting results
                   mol_grid.dat: grid points in molecule.units
                   mol_grid_esp.dat: QM esp valuese in a.u. 
    """
    if intermol_constraints is None:
        intermol_constraints = {}
    if options_list is None:
        options_list = []

    # Check options
    # Large case keys: resp options
    # Small case key: internal data
    intermol_constraints = {
        k.upper(): v
        for k, v in intermol_constraints.items()
    }

    if 'CHARGE' not in intermol_constraints:
        intermol_constraints['CHARGE'] = []
    if 'EQUAL' not in intermol_constraints:
        intermol_constraints['EQUAL'] = []

    # Check options for first molecule
    options = {k.upper(): v for k, v in sorted(options_list[0].items())}

    # VDW surface options
    if 'ESP' not in options:
        options['ESP'] = []
    if 'GRID' not in options:
        options['GRID'] = []
    if 'N_VDW_LAYERS' not in options:
        options['N_VDW_LAYERS'] = 4
    if 'VDW_SCALE_FACTOR' not in options:
        options['VDW_SCALE_FACTOR'] = 1.4
    if 'VDW_INCREMENT' not in options:
        options['VDW_INCREMENT'] = 0.2
    if 'VDW_POINT_DENSITY' not in options:
        options['VDW_POINT_DENSITY'] = 1.0
    # Hyperbolic restraint options
    if 'WEIGHT' not in options:
        options['WEIGHT'] = 1
    if 'RESTRAINT' not in options:
        options['RESTRAINT'] = True
    if options['RESTRAINT']:
        if 'RESP_A' not in options:
            options['RESP_A'] = 0.0005
        if 'RESP_B' not in options:
            options['RESP_B'] = 0.1
        if 'IHFREE' not in options:
            options['IHFREE'] = True
        if 'TOLER' not in options:
            options['TOLER'] = 1e-5
        if 'MAX_IT' not in options:
            options['MAX_IT'] = 25

    # QM options
    if 'METHOD_ESP' not in options:
        options['METHOD_ESP'] = 'scf'
    if 'BASIS_ESP' not in options:
        options['BASIS_ESP'] = '6-31g*'

    options_list[0] = options

    final_options_list = []
    n_atoms = []
    symbols_list = []
    for imol in range(len(molecules)):
        options = {k.upper(): v for k, v in options_list[imol].items()}
        # VDW surface options
        if 'RADIUS' not in options:
            options['RADIUS'] = {}
        radii = {}
        for i in options['RADIUS']:
            radii[i.upper()] = options['RADIUS'][i]
        options['RADIUS'] = radii

        # Constraint options
        if 'CONSTRAINT_CHARGE' not in options:
            options['CONSTRAINT_CHARGE'] = []
        if 'CONSTRAINT_GROUP' not in options:
            options['CONSTRAINT_GROUP'] = []
        if 'CONSTRAINT_EQUAL' not in options:
            options['CONSTRAINT_EQUAL'] = []

        if imol > 0:
            for i in final_options_list[0]:
                if i not in options and i.isupper():
                    options[i] = final_options_list[0][i]

        options['mol_charge'] = molecules[imol].molecular_charge()
        n_atoms.append(molecules[imol].natom())
        coordinates = molecules[imol].geometry()
        coordinates = coordinates.np.astype('float') * bohr_to_angstrom
        options['coordinates'] = coordinates
        symbols = []
        for i in range(n_atoms[-1]):
            symbols.append(molecules[imol].symbol(i))
        options['symbols'] = symbols
        symbols_list.append(symbols)

        if options['GRID']:
            # Read grid points
            points = np.loadtxt(options['GRID'])
            np.savetxt('grid.dat', points, fmt='%15.10f')
            if 'Bohr' in str(molecules[imol].units):
                points *= bohr_to_angstrom

        else:
            # Get the points at which we're going to calculate the ESP surface
            points = []
            surface = vdw_surface_helper.vdw_surface_helper()
            for i in range(options['N_VDW_LAYERS']):
                scale_factor = options[
                    'VDW_SCALE_FACTOR'] + i * options['VDW_INCREMENT']
                surface.vdw_surface(coordinates, symbols, scale_factor,
                                    options['VDW_POINT_DENSITY'],
                                    options['RADIUS'])
                points.append(surface.shell)
            radii = surface.radii
            points = np.concatenate(points)
            if 'Bohr' in str(molecules[imol].units):
                points /= bohr_to_angstrom
                np.savetxt('grid.dat', points, fmt='%15.10f')
                points *= bohr_to_angstrom
            else:
                np.savetxt('grid.dat', points, fmt='%15.10f')

        # Calculate ESP values at the grid
        if options['ESP']:
            # Read electrostatic potential values
            options['esp_values'] = np.loadtxt(options['ESP'])
            np.savetxt('grid_esp.dat', options['esp_values'], fmt='%15.10f')
        else:
            import psi4
            psi4.core.set_active_molecule(molecules[imol])
            psi4.set_options({'basis': options['BASIS_ESP']})
            psi4.set_options(options.get('PSI4_OPTIONS', {}))
            psi4.prop(options['METHOD_ESP'], properties=['GRID_ESP'])
            options['esp_values'] = np.loadtxt('grid_esp.dat')
            psi4.core.clean()

        os.system("mv grid.dat %i_%s_grid.dat" %
                  (imol + 1, molecules[imol].name()))
        os.system("mv grid_esp.dat %i_%s_grid_esp.dat" %
                  (imol + 1, molecules[imol].name()))
        # Build a matrix of the inverse distance from each ESP point to each nucleus
        invr = np.zeros((len(points), len(coordinates)))
        for i in range(invr.shape[0]):
            for j in range(invr.shape[1]):
                invr[i, j] = 1 / np.linalg.norm(points[i] - coordinates[j])
        options['invr'] = invr * bohr_to_angstrom  # convert to atomic units
        options['coordinates'] /= bohr_to_angstrom  # convert to angstroms

        final_options_list.append(options)
    # Calculate charges
    qf, labelf, notes = espfit.fit(final_options_list, intermol_constraints)
    index = 0
    charges = []

    # Extract the charges
    for imol in range(len(molecules)):
        q = [i[index:index + n_atoms[imol]] for i in qf]
        index += n_atoms[imol]
        charges.append(q)

    for imol in range(len(molecules)):
        options = final_options_list[imol]
        # Write the results to disk
        with open(
                str(imol + 1) + '_' + molecules[imol].name() + "_results.out",
                "w") as f:
            f.write("\n Electrostatic potential parameters\n")
            f.write("\n Grid information (see %i_%s_grid.dat in %s)\n" %
                    (imol + 1, molecules[imol].name(),
                     str(molecules[imol].units).split('.')[1]))
            f.write("     van der Waals radii (Angstrom):\n")
            for i, j in radii.items():
                f.write("                                %8s%8.3f\n" %
                        (i, j / scale_factor))
            f.write("     Number of VDW layers:             %d\n" %
                    (options["N_VDW_LAYERS"]))
            f.write("     VDW scale facotr:                 %.3f\n" %
                    (options["VDW_SCALE_FACTOR"]))
            f.write("     VDW increment:                    %.3f\n" %
                    (options["VDW_INCREMENT"]))
            f.write("     VDW point density:                %.3f\n" %
                    (options["VDW_POINT_DENSITY"]))
            f.write("     Number of grid points:            %d\n" %
                    len(options['esp_values']))

            f.write(
                "\n Quantum electrostatic potential (see %i_%s_grid_esp.dat)\n"
                % (imol + 1, molecules[imol].name()))
            f.write("     ESP method:                       %s\n" %
                    options['METHOD_ESP'])
            f.write("     ESP basis set:                    %s\n" %
                    options['BASIS_ESP'])

            f.write("\n Constraints\n")
            if options['CONSTRAINT_CHARGE']:
                f.write("     Charge constraints\n")
                for i in options['CONSTRAINT_CHARGE']:
                    f.write("         Total charge of %8.5f on the set" % i[0])
                    for j in i[1]:
                        f.write("%4d" % j)
                    f.write("\n")
            if options['CONSTRAINT_GROUP'] or options['CONSTRAINT_EQUAL']:
                f.write("     Equality constraints\n")
                f.write("         Equal charges on atoms\n")
                for i in options['CONSTRAINT_GROUP']:
                    f.write("                              ")
                    for j in i:
                        f.write("%4d" % j)
                    f.write("\n")
                for i in options['CONSTRAINT_EQUAL']:
                    for j in range(len(i)):
                        f.write("                              ")
                        f.write("%4d%4d" % (i[0][j], i[1][j]))
                        f.write("\n")
            if intermol_constraints['CHARGE'] or intermol_constraints['EQUAL']:
                f.write('\n     Intermolecular constraints\n')
                if intermol_constraints['CHARGE']:
                    f.write('         Charge constraints\n')
                    for i in intermol_constraints['CHARGE']:
                        f.write(
                            '             Total charge of %8.5f on the set:' %
                            i[0])
                        for j in i[1]:
                            f.write('\n                 molecule %4d, atoms' %
                                    j[0])
                            for k in j[1]:
                                f.write('%4d' % k)
                        f.write('\n')
                if intermol_constraints['EQUAL']:
                    f.write('         Equality constraints\n')
                    f.write('             Equal charges on\n')
                    for i in intermol_constraints['EQUAL']:
                        f.write('                 ')
                        f.write('molecule %4d, atoms' % i[0][0])
                        for j in i[0][1]:
                            f.write('%4d' % j)
                        f.write('\n                 molecule %4d, atoms' %
                                i[1][0])
                        for j in i[1][1]:
                            f.write('%4d' % j)
                        f.write('\n\n')
            f.write("\n Restraint\n")
            if options['RESTRAINT']:
                f.write("     Hyperbolic restraint to a charge of zero\n")
                if options['IHFREE']:
                    f.write("     Hydrogen atoms are not restrained\n")
                f.write("     resp_a:                           %.4f\n" %
                        (options["RESP_A"]))
                f.write("     resp_b:                           %.4f\n" %
                        (options["RESP_B"]))
            f.write("\n Fit\n")
            for i in notes:
                if i:
                    f.write(i + '\n')
            f.write("\n Electrostatic Potential Charges\n")
            f.write("   Center  Symbol")
            for i in labelf:
                f.write("%10s" % i)
            f.write("\n")
            for i in range(n_atoms[imol]):
                f.write("   %5d    %s     " % (i + 1, symbols_list[imol][i]))
                for j in charges[imol]:
                    f.write("%10.5f" % j[i])
                f.write("\n")
            f.write(" Total Charge:    ")
            for i in charges[imol]:
                f.write("%10.5f" % np.sum(i))
            f.write('\n')

    return charges
예제 #7
0
def resp(wfn, options={}):
    mol = wfn.molecule()
    n_atoms = mol.natom()
    # Check options
    check_options = {}
    for i in options.keys():
        check_options[i.upper()] = options[i]
    options = check_options
    if not ('N_VDW_LAYERS' in options.keys()):
        options['N_VDW_LAYERS'] = 4
    if not ('VDW_SCALE_FACTOR' in options.keys()):
        options['VDW_SCALE_FACTOR'] = 1.4
    if not ('VDW_INCREMENT' in options.keys()):
        options['VDW_INCREMENT'] = 0.2
    if not ('VDW_POINT_DENSITY' in options.keys()):
        options['VDW_POINT_DENSITY'] = 1.0
    if not ('RESP_A' in options.keys()):
        options['RESP_A'] = 0.0005
    if not ('RESP_B' in options.keys()):
        options['RESP_B'] = 0.1
    if not ('METHOD' in options.keys()):
        options['METHOD'] = 'scf'
    if not ('CHARGE_GROUPS' in options.keys()):
        options['CHARGE_GROUPS'] = range(n_atoms)
    if not ('TWO_STAGE_FIT' in options.keys()):
        options['TWO_STAGE_FIT'] = False
    if options['TWO_STAGE_FIT']:
        if not ('RESP_A2' in options.keys()):
            options['RESP_A2'] = 0.001
        if not ('FIT2' in options.keys()):
            options['FIT2'] = range(n_atoms)
        if not ('CHARGE_GROUPS2' in options.keys()):
            options['CHARGE_GROUPS2'] = range(n_atoms)

    options['mol_charge'] = mol.molecular_charge()
    # Get the coordinates of the nuclei in Angstroms
    symbols = []
    coordinates = np.asarray(mol.geometry())
    # the vdwsurface code expects coordinates in angstroms
    coordinates *= bohr_to_angstrom
    for i in range(n_atoms):
        symbols.append(mol.symbol(i))
    # Get the points at which we're going to calculate the ESP surface
    points = []
    for i in range(options['N_VDW_LAYERS']):
        scale_factor = options[
            'VDW_SCALE_FACTOR'] + i * options['VDW_INCREMENT']
        this_shell = vdw_surface(coordinates, symbols, scale_factor,
                                 options['VDW_POINT_DENSITY'])
        points.append(this_shell)
    points = np.concatenate(points)
    if 'Bohr' in str(mol.units):
        points /= bohr_to_angstrom
        np.savetxt('grid.dat', points, fmt='%.9f', delimiter='\t')
        points *= bohr_to_angstrom
    else:
        np.savetxt('grid.dat', points, fmt='%.9f', delimiter='\t')
    # Calculate ESP values at the grid
    e, wfn = psi4.prop(options['METHOD'],
                       properties=['GRID_ESP', 'MULLIKEN_CHARGES'],
                       molecule=wfn.molecule(),
                       return_wfn=True)
    options['esp_values'] = wfn.oeprop.Vvals()
    options['charges'] = np.asarray(wfn.atomic_point_charges())
    # Build a matrix of the inverse distance from each ESP point to each nucleus
    options['invr'] = 1.0 / scipy.spatial.distance_matrix(points, coordinates)
    options['invr'] *= bohr_to_angstrom
    # Run the optimization using SciPy
    charges = scipy.optimize.minimize(
        resp_objective,
        options['charges'],
        args=(options),
        jac=True,
        method='SLSQP',
        tol=1e-8,
        options={'ftol': 1e-8},
        constraints={
            'type': 'eq',
            'fun': resp_constraint,
            'args': [options['mol_charge'], options['CHARGE_GROUPS'], False]
        })
    charges = charges.x
    if options['TWO_STAGE_FIT']:
        a = options['RESP_A']
        options['RESP_A'] = options['RESP_A2']
        options['charges'] = charges
        charges2 = scipy.optimize.minimize(resp_objective,
                                           charges[options['FIT2']],
                                           args=(options, True),
                                           jac=True,
                                           method='SLSQP',
                                           tol=1e-8,
                                           options={'ftol': 1e-8},
                                           constraints={
                                               'type':
                                               'eq',
                                               'fun':
                                               resp_constraint,
                                               'args': [
                                                   options['mol_charge'],
                                                   options['CHARGE_GROUPS2'],
                                                   True, options['charges'],
                                                   options['FIT2']
                                               ]
                                           })
        charges[options['FIT2']] = charges2.x
        options['RESP_A'] = a
    np.savetxt('charges', charges)
    # Print the parameters to disk
    psi4.core.print_out(
        "\n ---------------------------------------------------\n")
    psi4.core.print_out(" RESTRAINED ELECTROSTATIC POTENTIAL PARAMETERS\n")
    psi4.core.print_out(
        " ---------------------------------------------------\n")
    psi4.core.print_out(" N_VDW_LAYERS:       %d\n" %
                        (options["N_VDW_LAYERS"]))
    psi4.core.print_out(" VDW_SCALE_FACTOR:   %.3f\n" %
                        (options["VDW_SCALE_FACTOR"]))
    psi4.core.print_out(" VDW_INCREMENT:      %.3f\n" %
                        (options["VDW_INCREMENT"]))
    psi4.core.print_out(" VDW_POINT_DENSITY:  %.3f\n" %
                        (options["VDW_POINT_DENSITY"]))
    psi4.core.print_out(" RESP_A:             %.4f\n" % (options["RESP_A"]))
    psi4.core.print_out(" RESP_B:             %.4f\n" % (options["RESP_B"]))
    psi4.core.print_out(" CHARGE_GROUPS:      [")
    for i in options['CHARGE_GROUPS'][:-1]:
        psi4.core.print_out('%d, ' % i)
    psi4.core.print_out('%d]\n' % options['CHARGE_GROUPS'][-1])
    psi4.core.print_out(" TWO_STAGE_FIT:      %s\n" %
                        (options["TWO_STAGE_FIT"]))
    if options["TWO_STAGE_FIT"]:
        psi4.core.print_out(" RESP_A2:            %.4f\n" %
                            (options["RESP_A2"]))
        psi4.core.print_out(" FIT2:               [")
        for i in options["FIT2"][:-1]:
            psi4.core.print_out('%d, ' % i)
        psi4.core.print_out('%d]\n' % options["FIT2"][-1])
        psi4.core.print_out(" CHARGE_GROUPS2:     [")
        for i in options['CHARGE_GROUPS2'][:-1]:
            psi4.core.print_out('%d, ' % i)
        psi4.core.print_out('%d]\n' % options['CHARGE_GROUPS2'][-1])

    psi4.core.print_out(" METHOD:             %s\n" % (options["METHOD"]))
    psi4.core.print_out(
        " ---------------------------------------------------\n")

    # Print the results to disk
    psi4.core.print_out("\n ----------------------------------------------\n")
    psi4.core.print_out(" RESTRAINED ELECTROSTATIC POTENTIAL CHARGES\n")
    psi4.core.print_out("   Center  Symbol  RESP Charge (a.u.)\n")
    psi4.core.print_out(" ----------------------------------------------\n")
    for i in range(len(charges)):
        psi4.core.print_out("   %5d    %s     %8.5f\n" %
                            (i, symbols[i], charges[i]))
예제 #8
0
파일: driver.py 프로젝트: rsdefever/resp
def resp(molecules, options=None):
    """RESP code driver.

    Parameters
    ---------- 
    molecules : list
        list of psi4.Molecule instances
    options_list : dict, optional
        a dictionary of user's defined options

    Returns
    -------
    charges : list
        list of charges

    Note
    ----
    output files : mol_results.dat: fitting results
                   mol_grid.dat: grid points in molecule.units
                   mol_grid_esp.dat: QM esp valuese in a.u. 
    """
    if options is None:
        options = {}

    # Check options
    # RESP options have large case keys
    options = {k.upper(): v for k, v in sorted(options.items())}

    # VDW surface options
    if 'ESP' not in options:
        options['ESP'] = []
    if 'GRID' not in options:
        options['GRID'] = []
    if 'VDW_SCALE_FACTORS' not in options:
        options['VDW_SCALE_FACTORS'] = [1.4, 1.6, 1.8, 2.0]
    if 'VDW_POINT_DENSITY' not in options:
        options['VDW_POINT_DENSITY'] = 1.0
    # Hyperbolic restraint options
    if 'WEIGHT' not in options:
        options['WEIGHT'] = [1] * len(molecules)
    if 'RESTRAINT' not in options:
        options['RESTRAINT'] = True
    if options['RESTRAINT']:
        if 'RESP_A' not in options:
            options['RESP_A'] = 0.0005
        if 'RESP_B' not in options:
            options['RESP_B'] = 0.1
        if 'IHFREE' not in options:
            options['IHFREE'] = True
        if 'TOLER' not in options:
            options['TOLER'] = 1e-5
        if 'MAX_IT' not in options:
            options['MAX_IT'] = 25

    # QM options
    if 'METHOD_ESP' not in options:
        options['METHOD_ESP'] = 'scf'
    if 'BASIS_ESP' not in options:
        options['BASIS_ESP'] = '6-31g*'

    # VDW surface options
    if 'VDW_RADII' not in options:
        options['VDW_RADII'] = {}
    radii = {}
    for i in options['VDW_RADII']:
        radii[i.upper()] = options['VDW_RADII'][i]
    options['VDW_RADII'] = radii

    # Constraint options
    if 'CONSTRAINT_CHARGE' not in options:
        options['CONSTRAINT_CHARGE'] = []
    if 'CONSTRAINT_GROUP' not in options:
        options['CONSTRAINT_GROUP'] = []

    data = {}
    # Same data for all conformer
    data['natoms'] = molecules[0].natom()
    data['symbols'] = []
    for i in range(data['natoms']):
        data['symbols'].append(molecules[0].symbol(i))
    data['mol_charge'] = molecules[0].molecular_charge()

    # Data for each conformer
    data['coordinates'] = []
    data['esp_values'] = []
    data['invr'] = []

    for imol in range(len(molecules)):
        coordinates = molecules[imol].geometry()
        coordinates = coordinates.np.astype('float') * bohr_to_angstrom
        data['coordinates'].append(coordinates)

        if options['GRID']:
            # Read grid points
            points = np.loadtxt(options['GRID'][imol])
            np.savetxt('grid.dat', points, fmt='%15.10f')
            if 'Bohr' in str(molecules[imol].units()):
                points *= bohr_to_angstrom

        else:
            # Get the points at which we're going to calculate the ESP
            points = []
            for scale_factor in options['VDW_SCALE_FACTORS']:
                shell, radii = vdw_surface.vdw_surface(
                    coordinates, data['symbols'], scale_factor,
                    options['VDW_POINT_DENSITY'], options['VDW_RADII'])
                points.append(shell)
            points = np.concatenate(points)
            if 'Bohr' in str(molecules[imol].units()):
                points /= bohr_to_angstrom
                np.savetxt('grid.dat', points, fmt='%15.10f')
                points *= bohr_to_angstrom
            else:
                np.savetxt('grid.dat', points, fmt='%15.10f')

        # Calculate ESP values at the grid
        if options['ESP']:
            # Read electrostatic potential values
            data['esp_values'].append(np.loadtxt(options['ESP'][imol]))
            np.savetxt('grid_esp.dat', data['esp_values'][-1], fmt='%15.10f')
        else:
            import psi4
            psi4.core.set_active_molecule(molecules[imol])
            psi4.set_options({'basis': options['BASIS_ESP']})
            psi4.set_options(options.get('PSI4_OPTIONS', {}))
            psi4.prop(options['METHOD_ESP'], properties=['GRID_ESP'])
            data['esp_values'].append(np.loadtxt('grid_esp.dat'))
            psi4.core.clean()

        os.system("mv grid.dat %i_%s_grid.dat" %
                  (imol + 1, molecules[imol].name()))
        os.system("mv grid_esp.dat %i_%s_grid_esp.dat" %
                  (imol + 1, molecules[imol].name()))
        # Build a matrix of the inverse distance from each ESP point to each nucleus
        invr = np.zeros((len(points), len(coordinates)))
        for i in range(invr.shape[0]):
            for j in range(invr.shape[1]):
                invr[i, j] = 1 / np.linalg.norm(points[i] - coordinates[j])
        data['invr'].append(invr * bohr_to_angstrom)  # convert to atomic units
        data['coordinates'][-1] /= bohr_to_angstrom  # convert to angstroms

    # Calculate charges
    qf, labelf, notes = espfit.fit(options, data)

    # Write the results to disk
    with open("results.out", "w") as f:
        f.write("Electrostatic potential parameters\n")
        if not options['GRID']:
            f.write("    van der Waals radii (Angstrom):\n")
            for i, j in radii.items():
                f.write("                               %8s%8.3f\n" %
                        (i, j / scale_factor))
            f.write("    VDW scale factors:              ")
            for i in options["VDW_SCALE_FACTORS"]:
                f.write('%6.2f' % i)
            f.write('\n')
            f.write("    VDW point density:                %.3f\n" %
                    (options["VDW_POINT_DENSITY"]))
        if not options['ESP']:
            f.write("    ESP method:                       %s\n" %
                    options['METHOD_ESP'])
            f.write("    ESP basis set:                    %s\n" %
                    options['BASIS_ESP'])

        for imol in range(len(molecules)):
            f.write(
                "\nGrid information (see %i_%s_grid.dat in %s)\n" %
                (imol + 1, molecules[imol].name(), molecules[imol].units()))
            f.write("    Number of grid points:            %d\n" %
                    len(data['esp_values'][imol]))
            f.write(
                "\nQuantum electrostatic potential (see %i_%s_grid_esp.dat)\n"
                % (imol + 1, molecules[imol].name()))

        f.write("\nConstraints\n")
        if options['CONSTRAINT_CHARGE']:
            f.write("    Charge constraints\n")
            for i in options['CONSTRAINT_CHARGE']:
                f.write("        Total charge of %12.8f on the set" % i[0])
                for j in i[1]:
                    f.write("%4d" % j)
                f.write("\n")
        if options['CONSTRAINT_GROUP']:
            f.write("    Equality constraints\n")
            f.write("        Equal charges on atoms\n")
            for i in options['CONSTRAINT_GROUP']:
                f.write("                               ")
                for j in i:
                    f.write("%4d" % j)
                f.write("\n")

        f.write("\nRestraint\n")
        if options['RESTRAINT']:
            f.write("    Hyperbolic restraint to a charge of zero\n")
            if options['IHFREE']:
                f.write("    Hydrogen atoms are not restrained\n")
            f.write("    resp_a:                           %.4f\n" %
                    (options["RESP_A"]))
            f.write("    resp_b:                           %.4f\n" %
                    (options["RESP_B"]))

        f.write("\nFit\n")
        f.write(notes)
        f.write("\nElectrostatic Potential Charges\n")
        f.write("   Center  Symbol")
        for i in labelf:
            f.write("%10s" % i)
        f.write("\n")
        for i in range(data['natoms']):
            f.write("  %5d    %s     " % (i + 1, data['symbols'][i]))
            for j in qf:
                f.write("%12.8f" % j[i])
            f.write("\n")
        f.write("Total Charge:    ")
        for i in qf:
            f.write("%12.8f" % np.sum(i))
        f.write('\n')

    return qf