示例#1
0
def get_surface_charge_adf(mol: Molecule, job: Type[Job],
                           s: Settings) -> Settings:
    """Perform a gas-phase ADF single point and return settings for a COSMO-ADF single point.

    The previous gas-phase calculation as moleculair fragment.

    Parameters
    ----------
    mol : |plams.Molecule|_
        A PLAMS Molecule.

    job : |Callable|_
        A type Callable of a class derived from :class:`Job`, e.g. :class:`AMSJob`
        or :class:`Cp2kJob`.

    s : |plams.Settings|_
        The settings for **job**.

    Returns
    -------
    |plams.Settings|_
        A new Settings intance, constructed from **s**, suitable for DFT COSMO-RS calculations.

    """
    s.input.allpoints = ''
    results = mol.job_single_point(job, s, ret_results=True)
    coskf = get_coskf(results)

    for at in mol:
        at.properties.adf.fragment = 'gas'
    s.update(get_template('qd.yaml')['COSMO-ADF'])
    s.input.fragments.gas = coskf

    return s
示例#2
0
def get_surface_charge(mol: Molecule, job: Type[Job],
                       s: Settings) -> Optional[str]:
    """Construct the COSMO surface of the **mol**.

    Parameters
    ----------
    mol : |plams.Molecule|_
        A PLAMS Molecule.

    job : |Callable|_
        A type Callable of a class derived from :class:`Job`, e.g. :class:`AMSJob`
        or :class:`Cp2kJob`.

    s : |plams.Settings|_
        The settings for **job**.

    Returns
    -------
    |plams.Settings|_
        Optional: The path+filename of a file containing COSMO surface charges.

    """
    s = Settings(s)
    # Special procedure for ADF jobs
    # Use the gas-phase electronic structure as a fragment for the COSMO single point
    if job is ADFJob:
        s = get_surface_charge_adf(mol, job, s)

    s.runscript.post = '$ADFBIN/cosmo2kf "mopac.cos" "mopac.coskf"'
    results = mol.job_single_point(job, s, ret_results=True)
    return get_coskf(results)
示例#3
0
def run_cdft_job(mol: Molecule, job: Type[ADFJob], s: Settings) -> pd.Series:
    """Run a conceptual DFT job and extract & return all global descriptors."""
    results = mol.job_single_point(job,
                                   s.copy(),
                                   name='CDFT',
                                   ret_results=True,
                                   read_template=False)

    if results.job.status in {'crashed', 'failed'}:
        return _BACKUP

    ret = get_global_descriptors(results)
    ret.index = pd.MultiIndex.from_product([['cdft'], ret.index],
                                           names=['index', 'sub index'])
    return ret
示例#4
0
def _asa_plams(mol_complete: Molecule, ligands: Iterable[Molecule],
               core: Molecule, read_template: bool, job: Type[Job],
               settings: Settings) -> Tuple[float, float, float, float, int]:
    """Perform an activation strain analyses with custom Job and Settings.

    Parameters
    ----------
    mol_complete : |plams.Molecule|
        A Molecule representing the (unfragmented) relaxed structure of the system of interest.

    ligands : :class:`Iterable<collections.abc.Iterable>` [|plams.Molecule|]
        An iterable of Molecules containing all ligands in mol_complete.

    core : |plams.Molecule|, optional
        The core molecule from **mol_complete**.

    job : :class:`type` [|plams.Job|]
        The Job type for the ASA calculations.

    settings : |plams.Settings|
        The Job Settings for the ASA calculations.

    Returns
    -------
    :class:`float`, :class:`float`, :class:`float`, :class:`float` and :class:`int`
        The energy of **mol_complete**,
        the energy of **ligands**,
        the energy of **core**,
        the energy of an optimized fragment within **ligands** and
        the total number of fragments within **ligands**.

    """
    s = settings

    # Calculate the energy of the total system
    mol_complete.round_coords()
    mol_complete.properties.name += '_frags'
    mol_complete.job_single_point(job, s)
    E_complete = mol_complete.properties.energy.E

    # Calculate the (summed) energy of each individual fragment in the total system
    E_ligands = 0.0
    E_min = np.inf
    mol_min = None
    for ligand_count, mol in enumerate(ligands, 1):
        mol.round_coords()
        mol.job_single_point(job, s)
        E = mol.properties.energy.E
        E_ligands += E
        if E < E_min:
            E_min, mol_min = E, mol

    # One of the calculations failed; better stop now
    if np.isnan(E_ligands):
        return np.nan, np.nan, np.nan, np.nan, ligand_count

    # Calculate the energy of the core
    core.job_single_point(job, s)
    E_core = mol.properties.energy.E

    # Calculate the energy of an optimizes fragment
    mol_min.job_geometry_opt(job, s)
    E_ligand_opt = mol_min.properties.energy.E

    return E_complete, E_ligands, E_core, E_ligand_opt, ligand_count
示例#5
0
def get_bde_dE(tot: Molecule,
               lig: Molecule,
               core: Iterable[Molecule],
               job: Type[Job],
               s: Settings,
               forcefield: bool = False) -> np.ndarray:
    """Calculate the bond dissociation energy: dE = dE(mopac) + (dG(uff) - dE(uff)).

    Parameters
    ----------
    tot : |plams.Molecule|_
        The complete intact quantum dot.

    lig : |plams.Molecule|_
        A ligand dissociated from the surface of the quantum dot

    core : |list|_ [|plams.Molecule|_]
        A list with one or more quantum dots (*i.e.* **tot**) with **lig** removed.

    job : |plams.Job|_
        A :class:`.Job` subclass.

    s : |plams.Settings|_
        The settings for **job**.

    """
    # Optimize XYn
    len_core = len(core)
    if job is AMSJob:
        s_cp = Settings(s)
        s_cp.input.ams.GeometryOptimization.coordinatetype = 'Cartesian'
        lig.job_geometry_opt(job, s_cp, name='E_XYn_opt')
    elif forcefield:
        qd_opt_ff(lig, Settings({'job1': Cp2kJob, 's1': s}), name='E_XYn_opt')
    else:
        lig.job_geometry_opt(job, s, name='E_XYn_opt')

    E_lig = lig.properties.energy.E
    if E_lig in (None, np.nan):
        logger.error(
            'The BDE XYn geometry optimization failed, skipping further jobs')
        return np.full(len_core, np.nan)

    # Perform a single point on the full quantum dot
    if forcefield:
        qd_opt_ff(tot, Settings({'job1': Cp2kJob, 's1': s}), name='E_QD_opt')
    else:
        tot.job_single_point(job, s, name='E_QD_sp')

    E_tot = tot.properties.energy.E
    if E_tot in (None, np.nan):
        logger.error(
            'The BDE quantum dot single point failed, skipping further jobs')
        return np.full(len_core, np.nan)

    # Perform a single point on the quantum dot(s) - XYn
    for mol in core:
        if forcefield:
            qd_opt_ff(mol,
                      Settings({
                          'job1': Cp2kJob,
                          's1': s
                      }),
                      name='E_QD-XYn_opt')
        else:
            mol.job_single_point(job, s, name='E_QD-XYn_sp')
    E_core = np.fromiter([mol.properties.energy.E for mol in core],
                         count=len_core,
                         dtype=float)

    # Calculate and return dE
    dE = (E_lig + E_core) - E_tot
    return dE