Exemplo n.º 1
0
    def __init__(self,
                 nstates,
                 dim,
                 width=None,
                 mass=None,
                 label=0,
                 parent=0,
                 kecoef=None):
        # total number of states
        self.nstates = int(nstates)
        # dimensionality of the trajectory
        self.dim = int(dim)
        # widths of gaussians for each dimension
        if width is None:
            self.width = np.zeros(dim)
        else:
            self.width = np.asarray(width)
        # masses associated with each dimension
        if mass is None:
            self.mass = np.zeros(dim)
        else:
            self.mass = np.array(mass)

    # the prefactor on the kinetic energy term: default to 1/2M
        if len(np.nonzero(self.mass)) == len(self.mass) and kecoef is None:
            self.kecoef = 0.5 / self.mass
        else:
            self.kecoef = kecoef

        # unique identifier for trajectory
        self.label = label
        # trajectory that spawned this one:
        self.parent = parent

        # current position of the trajectory
        self.pos = np.zeros(self.dim)
        # current momentum of the trajectory
        self.mom = np.zeros(self.dim)
        # state trajectory exists on
        self.state = 0
        # whether the trajectory is alive (i.e. contributes to the wavefunction)
        self.alive = True
        # whether the trajectory is active (i.e. is being propagated)
        self.active = True
        # amplitude of trajectory
        self.amplitude = 0j
        # phase of the trajectory
        self.gamma = 0.
        # time from which the death watch begini as
        self.deadtime = -1.
        # time of last spawn
        self.last_spawn = np.zeros(self.nstates)
        # time trajectory last left coupling region
        self.exit_time = np.zeros(self.nstates)
        # data structure to hold the pes data from the interface
        self.pes = surface.Surface()
Exemplo n.º 2
0
def evaluate_centroid(cent, t=None):
    """Evaluates all requested electronic structure information at a
    centroid."""
    global n_cart

    label   = cent.label
    nstates = cent.nstates

    if label >= 0:
        print('evaluate_centroid called with ' +
              'id associated with trajectory, label=' + str(label))

    state_i = min(cent.states)
    state_j = max(cent.states)

    # create surface object to hold potential information
    col_surf = surface.Surface()

    col_surf.add_data('geom', cent.x())

    # write geometry to file
    write_col_geom(cent.x())

    mo_restart, ci_restart = get_col_restart(cent)
    if not mo_restart:
        raise IOError('cannot find starting orbitals for mcscf')

    # generate integrals
    generate_integrals(label, t)

    # run mcscf
    run_col_mcscf(cent, t)
    col_surf.add_data('mo',pack_mocoef())

    # run mrci, if necessary
    potential, atom_pop = run_col_mrci(cent, ci_restart, t)
    col_surf.add_data('potential', potential + glbl.properties['pot_shift'])
    col_surf.add_data('atom_pop', atom_pop)

    deriv = np.zeros((cent.dim, nstates, nstates))
    if state_i != state_j:
        # run coupling between states
        nad_coup = run_col_coupling(cent, potential, t)
        deriv[:,state_i, state_j] =  nad_coup[:,state_j]
        deriv[:,state_j, state_i] = -nad_coup[:,state_j]

    col_surf.add_data('derivative', deriv)

    # save restart files
    make_col_restart(cent)

    # always return to current working directory
    os.chdir(glbl.paths['cwd'])

    return col_surf
Exemplo n.º 3
0
    def __init__(self,
                 traj_i=None,
                 traj_j=None,
                 nstates=0,
                 states=[-1, -1],
                 dim=0,
                 width=None,
                 label=None):
        if traj_i is None or traj_j is None:
            # total number of states
            self.nstates = int(nstates)
            # parent states
            self.states = states
            # dimensionality of the centroid
            self.dim = int(dim)
            # widths of gaussians for each dimension
            if width is None:
                self.width = np.zeros(dim)
            else:
                self.width = np.asarray(width)
            # unique identifier for centroid
            self.label = label
            # current position of the centroid
            self.pos = np.zeros(self.dim)
            # current momentum of the centroid
            self.mom = np.zeros(self.dim)
            # labels of parent trajectories
            self.parents = np.zeros(2, dtype=int)
        else:
            idi = max(traj_i.label, traj_j.label)
            idj = min(traj_i.label, traj_j.label)
            self.parents = np.array([idj, idi], dtype=int)
            self.nstates = max(traj_i.nstates, traj_j.nstates)
            self.states = [traj_i.state, traj_j.state]
            self.dim = max(traj_i.dim, traj_j.dim)
            self.label = cent_label(idi, idj)
            # now update the position in phase space of the centroid
            # if wid_i == wid_j, this is clearly just the simply mean
            # position.
            wid_i = traj_i.widths()
            wid_j = traj_j.widths()
            self.width = 0.5 * (wid_i + wid_j)
            self.pos = (wid_i * traj_i.x() + wid_j * traj_j.x()) / (wid_i +
                                                                    wid_j)
            self.mom = (wid_i * traj_i.p() + wid_j * traj_j.p()) / (wid_i +
                                                                    wid_j)

        # data structure to hold the data from the interface
        self.pes = surface.Surface()
Exemplo n.º 4
0
def evaluate_trajectory(traj, t=None):
    """Evaluates all reaqusted electronic structure  information
    for a single trajectory."""
    global libsurf

    n_atoms = int(traj.dim/3.)
    n_states = traj.nstates

    na = c_longlong(n_atoms)
    ns = c_longlong(n_states)

    na3 = 3 * n_atoms
    ns2 = n_states * n_states

    # convert to c_types for interfacing with surfgen shared
    # library.
    cgeom  = traj.x()
    energy = [0.0 for i in range(n_states)]
    cgrads = [0.0 for i in range(ns2*na3)]
    hmat   = [0.0 for i in range(ns2)]
    dgrads = [0.0 for i in range(ns2*na3)]

    cgeom = (c_double * na3)(*cgeom)
    energy= (c_double * n_states)(*energy)
    cgrads= (c_double * (ns2 * na3)) (*cgrads)
    hmat  = (c_double * ns2) (*hmat)
    dgrads= (c_double * (ns2 * na3)) (*dgrads)

    libsurf.evaluatesurfgen77_(byref(na), byref(ns), cgeom,
                               energy, cgrads, hmat, dgrads)
    cartgrd = np.array(np.reshape(cgrads,(na3,n_states,n_states),order='F'))
    potential = np.array(energy)

    # populate the surface object
    surf_gen = surface.Surface()
    surf_gen.add_data('geom', traj.x())
    surf_gen.add_data('potential', potential + glbl.properties['pot_shift'])

    # make sure the phase of Fij is consistent from one point to the next
    cgrad_phase = set_phase(traj, cartgrd)

    # add to the derivative object
    surf_gen.add_data('derivative', cgrad_phase)

    return surf_gen
Exemplo n.º 5
0
def read_centroid(chkpt, new_cent, c_grp, c_row):
    """Documentation to come"""
    # if this time step doesn't exist, return null centroid
    if c_row > len(chkpt[c_grp + '/glbl']) - 1:
        new_cent = None
    else:
        # set information about the trajectory itself
        parent = [0., 0.]
        states = [0., 0.]
        [parent[0], parent[1], states[0],
         states[1]] = chkpt[c_grp + '/glbl'][c_row]

        # populate the surface object in the trajectory
        pes = surface.Surface()
        for data_label in chkpt[c_grp].keys():
            if pes.valid_data(data_label):
                dset = chkpt[c_grp + '/' + data_label]
                pes.add_data(data_label, dset[c_row])

        # if MOs are present as an attribute, read them in
        if 'mo' in chkpt[c_grp].attrs.keys():
            mo_decode = [
                mo_i.decode("utf-8", "ignore")
                for mo_i in chkpt[c_grp].attrs['mo']
            ]
            pes.add_data('mo', mo_decode)

        # currently, momentum has to be read in separately
        momt = chkpt[c_grp + '/momentum'][c_row]

        new_cent.parents = [int(i) for i in parent]
        new_cent.states = [int(i) for i in states]

        idi = max(new_cent.parents)
        idj = min(new_cent.parents)
        new_cent.label = -((idi * (idi - 1) // 2) + idj + 1)

        new_cent.update_pes_info(pes)
        new_cent.pos = new_cent.pes.get_data('geom')
        new_cent.mom = momt
Exemplo n.º 6
0
def read_trajectory(chkpt, new_traj, t_grp, t_row):
    """Documentation to come"""
    # populate the surface object in the trajectory

    # if this time step doesn't exist, return null trajectory
    if t_row > len(chkpt[t_grp + '/glbl']) - 1:
        new_traj = None
    else:
        # set information about the trajectory itself
        data_row = chkpt[t_grp + '/glbl'][t_row]
        [parent, state, new_traj.gamma, amp_real, amp_imag] = data_row[0:5]

        pes = surface.Surface()
        for data_label in chkpt[t_grp].keys():
            if pes.valid_data(data_label):
                dset = chkpt[t_grp + '/' + data_label]
                pes.add_data(data_label, dset[t_row])

        # if MOs are present as an attribute, read them in
        if 'mo' in chkpt[t_grp].attrs.keys():
            mo_decode = [
                mo_i.decode("utf-8", "ignore")
                for mo_i in chkpt[t_grp].attrs['mo']
            ]
            pes.add_data('mo', mo_decode)

        # currently, momentum has to be read in separately
        momt = chkpt[t_grp + '/momentum'][t_row]

        new_traj.state = int(state)
        new_traj.parent = int(parent)
        new_traj.update_amplitude(amp_real + 1.j * amp_imag)
        new_traj.last_spawn = data_row[5:]

        new_traj.update_pes_info(pes)
        new_traj.update_x(new_traj.pes.get_data('geom'))
        new_traj.update_p(momt)
Exemplo n.º 7
0
def evaluate_trajectory(traj, t=None):
    """Computes MCSCF/MRCI energy and computes all couplings.

    For the columbus module, since gradients are not particularly
    time consuming, it's easier (and probably faster) to compute
    EVERYTHING at once (i.e. all energies, all gradients, all properties)
    Thus, if electronic structure information is not up2date, all methods
    call the same routine: run_single_point.
    """
    global n_cart

    label   = traj.label
    state   = traj.state
    nstates = traj.nstates

    if label < 0:
        print('evaluate_trajectory called with ' +
              'id associated with centroid, label=' + str(label))

    # create surface object to hold potential information
    col_surf = surface.Surface()
    col_surf.add_data('geom', traj.x())

    # write geometry to file
    write_col_geom(traj.x())

    mo_restart, ci_restart = get_col_restart(traj)
    if not mo_restart:
        raise IOError('cannot find starting orbitals for mcscf')

    # generate integrals
    generate_integrals(label, t)

    # run mcscf
    run_col_mcscf(traj, t)
    col_surf.add_data('mo', pack_mocoef())

    # run mrci, if necessary
    potential, atom_pop = run_col_mrci(traj, ci_restart, t)
    col_surf.add_data('potential', potential + glbl.properties['pot_shift'])
    col_surf.add_data('atom_pop', atom_pop)

    # run properties, dipoles, etc.
    [perm_dipoles, sec_moms] = run_col_multipole(traj)
    col_surf.add_data('sec_mom', sec_moms)
    dipoles = np.zeros((3, nstates, nstates))
    for i in range(nstates):
        dipoles[:,i,i] = perm_dipoles[:,i]

    # run transition dipoles
    init_states = [0, state]
    for i in init_states:
        for j in range(nstates):
            if i != j or (j in init_states and j < i):
                tr_dip = run_col_tdipole(label, i, j)
                dipoles[:,i,j] = tr_dip
                dipoles[:,j,i] = tr_dip
    col_surf.add_data('dipole',dipoles)

    # compute gradient on current state
    deriv = np.zeros((n_cart, nstates, nstates))
    grads = run_col_gradient(traj, t)
    deriv[:,state,state] = grads

    # run coupling to other states
    nad_coup = run_col_coupling(traj, potential, t)
    for i in range(nstates):
        if i != state:
            state_i = min(i,state)
            state_j = max(i,state)
            deriv[:, state_i, state_j] =  nad_coup[:, i]
            deriv[:, state_j, state_i] = -nad_coup[:, i]
    col_surf.add_data('derivative', deriv)

    # save restart files
    make_col_restart(traj)

    # always return to current working directory
    os.chdir(glbl.paths['cwd'])

    return col_surf
Exemplo n.º 8
0
def evaluate_trajectory(traj, t=None):
    """Evaluates the trajectory."""
    global nsta, data_cache

    label = traj.label
    geom  = traj.x()

    # Calculation of the diabatic potential matrix
    diabpot = calc_diabpot(geom)

    # Calculation of the nuclear derivatives of the diabatic potential
    diabderiv1 = calc_diabderiv1(geom)

    # Calculatoin of the hessian matrix for each sub-block of the diabatic potential
    # matrix
    diabderiv2 = calc_diabderiv2(geom)

    # Calculation of the Laplacian of the diabatic potential wrt the
    # nuclear DOFs
    diablap = calc_diablap(geom)

    # load the data into the pes object to pass to trajectory
    t_data = surface.Surface()
    t_data.add_data('geom',geom)

    t_data.add_data('diabat_pot',diabpot)
    t_data.add_data('diabat_deriv',diabderiv1)
    t_data.add_data('diabat_hessian',diabderiv2)

    if glbl.methods['surface'] == 'adiabatic':
        # Calculation of the adiabatic potential vector and ADT matrix
        adiabpot, datmat = calc_dat(label, diabpot)

        # Calculation of the NACT matrix
        nactmat = calc_nacts(adiabpot, datmat, diabderiv1)

        # Calculation of the gradients (for diagonal elements) and derivative
        # couplings (off-diagonal elements)
        adiabderiv1 = calc_adiabderiv1(datmat, diabderiv1)

        # Calculation of the hessians (for diagonal elements) and derivative of
        # derivative couplings (off-diagonal elements)
        adiabderiv2 = calc_adiabderiv2(datmat, diabderiv2)

        # Calculation of the scalar couplings terms (SCTs)
        # Note that in order to calculate the SCTs, we get the gradients of the
        # diagonal Born-Oppenheimer corrections (DBOCs). Consequently, we
        # save these as a matter of course.
        sctmat, dbocderiv1 = calc_scts(adiabpot, datmat, diabderiv1,
                                   nactmat, adiabderiv1, diablap)

        t_data.add_data('potential',adiabpot)
        t_data.add_data('derivative', np.array([np.diag(adiabderiv1[m]) for m in
                                      range(ham.nmode_total)] + nactmat))
        t_data.add_data('hessian',adiabderiv2)

        # non-standard items
        t_data.add_data('nac',nactmat)
        t_data.add_data('scalar_coup',0.5*sctmat) #account for the 1/2 prefactor in the EOMs
        t_data.add_data('dat_mat',datmat)
        t_data.add_data('adt_mat',datmat.T)

    else:
        # determine the effective diabatic coupling: Hij / (Ei - Ej)
        diab_effcoup     = calc_diabeffcoup(diabpot)

        t_data.add_data('potential',np.array([diabpot[i,i] for i in range(nsta)]))
        t_data.add_data('derivative',diabderiv1)
        t_data.add_data('hessian',diabderiv2)

    data_cache[label] = t_data
    return t_data
Exemplo n.º 9
0
def evaluate_trajectory(traj, t=None):
    global model_potentials, data_cache

    label = traj.label
    geom = traj.x()
    nd = len(geom)
    ns = traj.nstates

    # Calculation of the diabatic potential matrix and derivatives
    [diabpot, diabderiv1, diabderiv2, diablap] =\
     model_potentials[glbl.models['model_name']](geom)

    if ns != diabpot.shape[0]:
        sys.exit('Wrong number of states expected in model: ' + str(ns) +
                 ' != ' + str(diabpot.shape[0]))

    if nd != diabderiv1.shape[0]:
        sys.exit('Wrong number of coordinates expected in model: ' + str(nd) +
                 ' != ' + str(diabderiv1.shape[0]))

    # load the data into the pes object to pass to trajectory
    t_data = surface.Surface()
    t_data.add_data('geom', geom)

    t_data.add_data('diabat_pot', diabpot)
    t_data.add_data('diabat_deriv', diabderiv1)
    t_data.add_data('diabat_hessian', diabderiv2)

    if glbl.methods['surface'] == 'adiabatic':

        datmat_prev = None
        if traj.label in data_cache:
            datmat_prev = data_cache[traj.label].get_data('dat_mat')

        # Calculation of the adiabatic potential vector and ADT matrix
        adiabpot, datmat = adt.calc_dat(label,
                                        diabpot,
                                        previous_datmat=datmat_prev)

        # Calculation of the NACT matrix
        nactmat = adt.calc_nacts(adiabpot, datmat, diabderiv1)

        # Calculation of the gradients (for diagonal elements) and derivative
        # couplings (off-diagonal elements)
        adiabderiv1 = adt.calc_adiabderiv1(datmat, diabderiv1)

        # Calculation of the hessians (for diagonal elements) and derivative of
        # derivative couplings (off-diagonal elements)
        adiabderiv2 = adt.calc_adiabderiv2(datmat, diabderiv2)

        t_data.add_data('potential', adiabpot)
        t_data.add_data(
            'derivative',
            np.array([np.diag(adiabderiv1[m]) for m in range(nd)] + nactmat))
        t_data.add_data('hessian', adiabderiv2)

        # non-standard items
        t_data.add_data('nac', nactmat)
        t_data.add_data('dat_mat', datmat)
        t_data.add_data('adt_mat', datmat.T)

    else:
        # determine the effective diabatic coupling: Hij / (Ei - Ej)
        diab_effcoup = adt.calc_diabeffcoup(diabpot)

        t_data.add_data('potential',
                        np.array([diabpot[i, i] for i in range(ns)]))
        t_data.add_data('derivative', diabderiv1)
        t_data.add_data('hessian', diabderiv2)

    data_cache[traj.label] = t_data

    return t_data