Exemple #1
0
def propagate_trajectory(traj, dt):
    """Propagates a single trajectory with VV."""
    # position update
    propagate_position(traj, dt)

    # update electronic structure
    surface.update_pes_traj(traj)

    # momentum/phase update
    propagate_momentum(traj, dt)
Exemple #2
0
def propagate_trajectory(traj, dt):
    """Propagates a single trajectory with RKF45."""
    global h_traj
    ncrd = traj.dim
    kx = np.zeros((rk_ordr, ncrd))
    kp = np.zeros((rk_ordr, ncrd))
    kg = np.zeros((rk_ordr))

    t = 0.
    if h_traj is None:
        h_traj = dt
    while abs(t) < abs(dt):
        hstep = np.sign(dt) * min(abs(h_traj), abs(dt - t))
        for rk in range(rk_ordr):
            tmptraj = traj.copy()
            propagate_rk(tmptraj, hstep, rk, kx, kp, kg)

            # update the PES to evaluate new gradients
            if rk < rk_ordr - 1:
                surface.update_pes_traj(tmptraj)

        # calculate the 4th and 5th order changes and the error
        dx_lo = np.sum(wgt_lo[:, np.newaxis] * kx, axis=0)
        dx_hi = np.sum(wgt_hi[:, np.newaxis] * kx, axis=0)
        dp_lo = np.sum(wgt_lo[:, np.newaxis] * kp, axis=0)
        dp_hi = np.sum(wgt_hi[:, np.newaxis] * kp, axis=0)

        if propphase:
            dg_lo = np.sum(wgt_lo * kg)
            dg_hi = np.sum(wgt_hi * kg)
            #            err = np.max((np.abs(dx_hi-dx_lo), np.abs(dp_hi-dp_lo),
            #                          np.abs(dg_hi-dg_lo)))
            err = np.max(
                np.abs(dg_hi - dg_lo),
                np.max((np.abs(dx_hi - dx_lo).flatten(),
                        np.abs(dp_hi - dp_lo).flatten())))

        else:
            err = np.max((np.abs(dx_hi - dx_lo), np.abs(dp_hi - dp_lo)))

        if err > tol:
            # scale the time step and try again
            h_traj = hstep * max(safety * (tol / err)**0.25, 0.1)
        else:
            # scale the time step and update the position
            t += h_traj
            err = max(err, tol * 1e-5)
            h_traj *= min(safety * (tol / err)**0.2, 5.)
            traj.update_x(traj.x() + dx_lo)
            traj.update_p(traj.p() + dp_lo)
            if propphase:
                traj.update_phase(traj.phase() + dg_lo)
            surface.update_pes_traj(traj)
Exemple #3
0
def propagate_trajectory(traj, dt):
    """Propagates a single trajectory with RK4."""
    ncrd = traj.dim
    kx = np.zeros((rk_ordr, ncrd))
    kp = np.zeros((rk_ordr, ncrd))
    kg = np.zeros((rk_ordr, ncrd))

    for rk in range(rk_ordr):
        tmptraj = traj.copy()
        propagate_rk(tmptraj, dt, rk, kx, kp, kg)

        # update the PES to evaluate new gradients
        if rk < rk_ordr - 1:
            surface.update_pes_traj(tmptraj)

    # update to the final position
    traj.update_x(traj.x() + np.sum(wgt[:,np.newaxis]*kx, axis=0))
    traj.update_p(traj.p() + np.sum(wgt[:,np.newaxis]*kp, axis=0))
    if propphase:
        traj.update_phase(traj.phase() + np.sum(wgt[:,np.newaxis]*kg, axis=0))
    surface.update_pes_traj(traj)
Exemple #4
0
def set_initial_state(master):
    """Sets the initial state of the trajectories in the bundle."""

    # initialize to the state with largest transition dipole moment
    if glbl.sampling['init_brightest']:

        # set all states to the ground state
        for i in range(master.n_traj()):
            master.traj[i].state = 0
            # compute transition dipoles
            surface.update_pes_traj(master.traj[i])

        # set the initial state to the one with largest t. dip.
        for i in range(master.n_traj()):
            if 'tr_dipole' not in master.traj[i].pes_data.data_keys:
                raise KeyError('ERROR, trajectory ' + str(i) +
                               ': Cannot set state by transition moments - ' +
                               'tr_dipole not in pes_data.data_keys')
            tdip = np.array([
                np.linalg.norm(master.traj[i].pes_data.dipoles[:, 0, j])
                for j in range(1, glbl.propagate['n_states'])
            ])
            fileio.print_fms_logfile('general',
                                    ['Initializing trajectory '+str(i)+
                                     ' to state '+str(np.argmax(tdip)+1)+
                                     ' | tr. dipople array='+np.array2string(tdip, \
                                       formatter={'float_kind':lambda x: "%.4f" % x})])
            master.traj[i].state = np.argmax(tdip) + 1

    # use "init_state" to set the initial state
    elif len(glbl.sampling['init_states']) == master.n_traj():
        for i in range(master.n_traj()):
            master.traj[i].state = glbl.sampling['init_states'][i]

    else:
        raise ValueError('Ambiguous initial state assignment.')

    return
Exemple #5
0
def make_origin_traj():
    """Construct a trajectory basis function at the origin
    specified in the input files"""

    ndim = len(glbl.nuclear_basis['geometries'][0])
    m_vec = np.array(glbl.nuclear_basis['masses'])
    w_vec = np.array(glbl.nuclear_basis['widths'])
    x_vec = np.array(glbl.nuclear_basis['geometries'][0])
    p_vec = np.array(glbl.nuclear_basis['momenta'][0])

    origin = trajectory.Trajectory(glbl.propagate['n_states'],
                                   ndim,
                                   width=w_vec,
                                   mass=m_vec,
                                   parent=0)

    origin.update_x(x_vec)
    origin.update_p(p_vec)
    origin.state = 0
    # if we need pes data to evaluate overlaps, determine that now
    if glbl.integrals.overlap_requires_pes:
        surface.update_pes_traj(origin)

    return origin
Exemple #6
0
def propagate_trajectory(traj, dt):
    """Propagates a single trajectory with BS."""
    global h_traj
    ncrd = traj.dim

    t = 0.
    if h_traj is None:
        h_traj = dt
    while abs(t) < abs(dt):
        hstep = np.sign(dt) * min(abs(h_traj), abs(dt - t))
        reduced = False
        tsav = np.zeros(kmax_traj)
        err = np.zeros(kmax_traj)
        Tx = np.zeros((kmax_traj, ncrd))
        Tp = np.zeros((kmax_traj, ncrd))
        Tg = np.zeros((kmax_traj, ncrd))

        for k in range(kmax):
            tmptraj = traj.copy()

            x0 = np.zeros(ncrd)
            p0 = np.zeros(ncrd)
            g0 = np.zeros(ncrd)
            x1 = np.zeros(ncrd)
            p1 = np.zeros(ncrd)
            g1 = np.zeros(ncrd)

            # step through n modified midpoint steps
            for n in range(nstep[k]):
                mm_step(tmptraj, hstep/nstep[k], x0, x1, p0, p1, g0, g1, n)
                surface.update_pes_traj(tmptraj)

            # compute the modified midpoint estimate
            x1 = 0.5*(x1 + x0 + hstep/nstep[k]*tmptraj.velocity())
            p1 = 0.5*(p1 + p0 + hstep/nstep[k]*tmptraj.force())
            if propphase:
                g1 = 0.5*(g1 + g0 + hstep/nstep[k]*tmptraj.phase_dot())

            # extrapolate from modified midpoint results
            poly_extrapolate(k, (hstep/nstep[k])**2, tsav, x1, p1, g1, Tx, Tp, Tg)
            if k > 0:
                errmax = np.amax((abs(Tx[k]), abs(Tp[k]), abs(Tg[k]))) / tol
                err[k-1] = (errmax / 0.25) ** (1. / (2*k + 1))
                if k >= kopt - 2:
                    if errmax > 1:
                        # scale the time step and try again
                        sfac, reduced = reduce_tstep(k, err)
                        if reduced:
                            red = max(1e-5, min(red, 0.7))
                            h_traj = sfac * hstep
                            break
                    else:
                        # scale the time step if possible
                        t += h_traj
                        h_traj = increase_tstep(k, err, reduced) * hstep

                        # update to the final position
                        xnew = np.sum(Tx, axis=0)
                        pnew = np.sum(Tp, axis=0)
                        traj.update_x(xnew)
                        traj.update_p(pnew)
                        if propphase:
                            gnew = np.sum(Tg, axis=0)
                            traj.update_phase(gnew)
                        surface.update_pes_traj(traj)
                        break
def spawn(master, dt):
    """Propagates to the point of maximum coupling, spawns a new
    basis function, then propagates the function to the current time."""
    global coup_hist

    basis_grown = False
    current_time = master.time
    # list of added trajectories

    # we want to know the history of the coupling for each trajectory
    # in order to assess spawning criteria -- make sure coup_hist has a slot
    # for every trajectory
    if len(coup_hist) < master.n_traj():
        n_add = master.n_traj() - len(coup_hist)
        for i in range(n_add):
            coup_hist.append(np.zeros((master.nstates, 3)))

    #--------------- iterate over all trajectories in bundle ---------------------
    for i in range(master.n_traj()):
        # only live trajectories can spawn
        if not master.traj[i].alive:
            continue

        for st in range(master.nstates):
            # can only spawn to different electronic states
            if master.traj[i].state == st:
                continue

            # compute magnitude of coupling to state j
            coup = master.traj[i].eff_coup(st)
            coup_hist[i][st, :] = np.roll(coup_hist[i][st, :], 1)
            coup_hist[i][st, 0] = coup

            # if we satisfy spawning conditions, begin spawn process
            if spawn_trajectory(master, i, st, coup_hist[i][st, :],
                                current_time):
                # we're going to messing with this trajectory -- mess with a copy
                parent = master.traj[i].copy()

                # propagate the parent forward in time until coupling maximized
                [success, child, parent_spawn, spawn_time,
                 exit_time] = spawn_forward(parent, st, current_time, dt)

                # set the spawn attempt in master, even if spawn failed (avoid repeated fails)
                master.traj[i].last_spawn[st] = spawn_time
                master.traj[i].exit_time[st] = exit_time

                if success:
                    # at this point, child is at the spawn point. Propagate
                    # backwards in time until we reach the current time
                    child_spawn = child.copy()
                    # need electronic structure at current geometry -- on correct state
                    surface.update_pes_traj(child)
                    spawn_backward(child, spawn_time, current_time, -dt)
                    bundle_overlap = utils.overlap_with_bundle(child, master)
                    if not bundle_overlap:
                        basis_grown = True
                        master.add_trajectory(child)
                        child_spawn.label = master.traj[
                            -1].label  # a little hacky...
                        utils.write_spawn_log(current_time, spawn_time,
                                              exit_time, parent_spawn,
                                              child_spawn)
                    else:
                        fileio.print_fms_logfile(
                            'spawn_bad_step',
                            ['overlap with bundle too large'])

    # let caller known if the basis has been changed
    return basis_grown