コード例 #1
0
def propagate_bundle(master, dt):
    """Propagates the Bundle object with RK4."""
    ncrd = master.traj[0].dim
    ntraj = master.n_traj()
    kx = np.zeros((ntraj, rk_ordr, ncrd))
    kp = np.zeros((ntraj, rk_ordr, ncrd))
    kg = np.zeros((ntraj, rk_ordr, ncrd))

    for rk in range(rk_ordr):
        tmpbundle = master.copy()
        for i in range(ntraj):
            if tmpbundle.traj[i].active:
                propagate_rk(tmpbundle.traj[i], dt, rk, kx[i], kp[i], kg[i])

        # update the PES to evaluate new gradients
        if rk < rk_ordr - 1:
            surface.update_pes(tmpbundle, update_centroids=False)

    # update to the final position
    for i in range(ntraj):
        if master.traj[i].active:
            master.traj[i].update_x(master.traj[i].x() +
                                    np.sum(wgt[:,np.newaxis]*kx[i], axis=0))
            master.traj[i].update_p(master.traj[i].p() +
                                    np.sum(wgt[:,np.newaxis]*kp[i], axis=0))
            if propphase:
                master.traj[i].update_phase(master.traj[i].phase() +
                                            np.sum(wgt[:,np.newaxis]*kg[i], axis=0))
    surface.update_pes(master)
コード例 #2
0
ファイル: velocity_verlet.py プロジェクト: millskyle/nomad
def propagate_bundle(master, dt):
    """Propagates the Bundle object with VV."""
    # update position
    for i in range(master.n_traj()):
        if master.traj[i].active:
            propagate_position(master.traj[i], dt)

    # update electronic structure for all trajectories
    # and centroids (where necessary)
    surface.update_pes(master)

    # finish update of momentum and phase
    for i in range(master.n_traj()):
        if master.traj[i].active:
            propagate_momentum(master.traj[i], dt)
コード例 #3
0
ファイル: initialize.py プロジェクト: millskyle/nomad
def init_bundle(master):
    """Initializes the trajectories."""

    # initialize the interface we'll be using the determine the
    # the PES. There are some details here that trajectories
    # will want to know about
    glbl.pes.init_interface()

    # now load the initial trajectories into the bundle
    if glbl.sampling['restart']:
        init_restart(master)

    else:
        # first generate the initial nuclear coordinates and momenta
        # and add the resulting trajectories to the bundle
        glbl.distrib.set_initial_coords(master)

        # set the initial state of the trajectories in bundle. This may
        # require evaluation of electronic structure
        set_initial_state(master)

        # set the initial amplitudes of the basis functions
        set_initial_amplitudes(master)

        # add virtual basis functions, if desired (i.e. virtual basis = true)
        if glbl.sampling['virtual_basis'] and not glbl.sampling['restart']:
            virtual_basis(master)

    # update all pes info for all trajectories and centroids (where necessary)
    surface.update_pes(master)
    # compute the hamiltonian matrix...
    master.update_matrices()
    # so that we may appropriately renormalize to unity
    master.renormalize()

    # this is the bundle at time t=0.  Save in order to compute auto
    # correlation function
    set_initial_bundle(master)

    # write to the log files
    if glbl.mpi['rank'] == 0:
        master.update_logs()

    fileio.print_fms_logfile(
        't_step',
        [master.time, glbl.propagate['default_time_step'], master.nalive])

    return master.time
コード例 #4
0
ファイル: initialize.py プロジェクト: millskyle/nomad
def set_initial_amplitudes(master):
    """Sets the initial amplitudes."""

    # if init_amp_overlap is set, overwrite 'amplitudes' that was
    # set in nomad.input
    if glbl.nuclear_basis['init_amp_overlap']:

        origin = make_origin_traj()

        # update all pes info for all trajectories and centroids (where necessary)
        if glbl.integrals.overlap_requires_pes:
            surface.update_pes(master)

        # Calculate the initial expansion coefficients via projection onto
        # the initial wavefunction that we are sampling
        ovec = np.zeros(master.n_traj(), dtype=complex)
        for i in range(master.n_traj()):
            ovec[i] = glbl.integrals.traj_overlap(master.traj[i],
                                                  origin,
                                                  nuc_only=True)
        smat = np.zeros((master.n_traj(), master.n_traj()), dtype=complex)
        for i in range(master.n_traj()):
            for j in range(i + 1):
                smat[i,
                     j] = glbl.integrals.traj_overlap(master.traj[i],
                                                      master.traj[j])
                if i != j:
                    smat[j, i] = smat[i, j].conjugate()
        sinv = sp_linalg.pinvh(smat)
        glbl.nuclear_basis['amplitudes'] = np.dot(sinv, ovec)

    # if we don't have a sufficient number of amplitudes, append
    # amplitudes with "zeros" as necesary
    if len(glbl.nuclear_basis['amplitudes']) < master.n_traj():
        dif = master.n_traj() - len(glbl.nuclear_basis['amplitudes'])
        fileio.print_fms_logfile(
            'warning',
            ['appending ' + str(dif) + ' values of 0+0j to amplitudes'])
        glbl.nuclear_basis['amplitudes'].extend([0 + 0j for i in range(dif)])

    # finally -- update amplitudes in the bundle
    for i in range(master.n_traj()):
        master.traj[i].update_amplitude(glbl.nuclear_basis['amplitudes'][i])

    return
コード例 #5
0
ファイル: step.py プロジェクト: millskyle/nomad
def fms_step_bundle(master, dt):
    """Propagates the wave packet using a run-time selected propagator."""

    # save the bundle from previous step in case step rejected
    end_time = master.time + dt
    time_step = dt
    min_time_step = dt / 2.**5

    while not step_complete(master.time, end_time, dt):
        # save the bundle from previous step in case step rejected
        #try:
        #    del master0
        #except NameError:
        #    pass
        master0 = master.copy()

        # propagate each trajectory in the bundle
        time_step = min(time_step, end_time - master.time)
        # propagate amplitudes for 1/2 time step using x0
        master.update_amplitudes(0.5 * dt, update_ham=False)
        # the propagators update the potential energy surface as need be.
        glbl.integrator.propagate_bundle(master, time_step)
        # propagate amplitudes for 1/2 time step using x1
        master.update_amplitudes(0.5 * dt)

        # Renormalization
        if glbl.propagate['renorm'] == 1:
            master.renormalize()

        # check time_step is fine, energy/amplitude conserved
        accept, error_msg = check_step_bundle(master0, master, time_step)

        # if everything is ok..
        if accept:
            # update the bundle time
            master.time += time_step
            # spawn new basis functions if necessary
            basis_grown = glbl.spawn.spawn(master, time_step)
            # kill the dead trajectories
            basis_pruned = master.prune()

            # if a trajectory has been added, then call update_pes
            # to get the electronic structure information at the associated
            # centroids. This is necessary in order to propagate the amplitudes
            # at the start of the next time step.
            if basis_grown and glbl.integrals.require_centroids:
                surface.update_pes(master)

            # update the Hamiltonian and associated matrices
            if basis_grown or basis_pruned:
                master.update_matrices()

            # re-expression of the basis using the matching pursuit
            # algorithm
            if glbl.propagate['matching_pursuit'] == 1:
                mp.reexpress_basis(master)

            # update the running log
            fileio.print_fms_logfile('t_step',
                                     [master.time, time_step, master.nalive])
        else:
            # recall -- this time trying to propagate to the failed step
            time_step *= 0.5
            fileio.print_fms_logfile('new_step', [error_msg, time_step])

            if time_step < min_time_step:
                fileio.print_fms_logfile(
                    'general', ['minimum time step exceeded -- STOPPING.'])
                raise ValueError('Bundle minimum step exceeded.')

            # reset the beginning of the time step and go to beginning of loop
            #del master
            master = master0.copy()

    return master
コード例 #6
0
ファイル: bulirsch_stoer.py プロジェクト: millskyle/nomad
def propagate_bundle(master, dt):
    """Propagates the Bundle object with BS."""
    global h
    ncrd = master.traj[0].dim
    ntraj = master.n_traj()

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

        for k in range(kmax):
            tmpbundle = master.copy()

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

            # step through n modified midpoint steps
            for n in range(nstep[k]):
                for i in range(ntraj):
                    if tmpbundle.traj[i].active:
                        mm_step(tmpbundle.traj[i], hstep / nstep[k], x0[i],
                                x1[i], p0[i], p1[i], g0[i], g1[i], n)
                surface.update_pes(tmpbundle, update_centroids=False)

            # compute the modified midpoint estimate
            for i in range(ntraj):
                if master.traj[i].active:
                    x1[i] = 0.5 * (x1[i] + x0[i] + hstep / nstep[k] *
                                   tmpbundle.traj[i].velocity())
                    p1[i] = 0.5 * (p1[i] + p0[i] + hstep / nstep[k] *
                                   tmpbundle.traj[i].force())
                    if propphase:
                        g1[i] = 0.5 * (g1[i] + g0[i] + hstep / nstep[k] *
                                       tmpbundle.traj[i].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(reduced, 0.7))
                            h = sfac * hstep
                            break
                    else:
                        # scale the time step if possible
                        t += h
                        h = increase_tstep(k, err, reduced) * hstep

                        # update to the final position
                        xnew = np.sum(Tx, axis=0)
                        pnew = np.sum(Tp, axis=0)
                        gnew = np.sum(Tg, axis=0)
                        for i in range(ntraj):
                            if master.traj[i].active:
                                master.traj[i].update_x(xnew[i])
                                master.traj[i].update_p(pnew[i])
                                if propphase:
                                    master.traj[i].update_phase(gnew[i])
                        surface.update_pes(
                            master, update_centroids=(abs(t) >= abs(dt)))
                        break
コード例 #7
0
ファイル: rkf45.py プロジェクト: millskyle/nomad
def propagate_bundle(master, dt):
    """Propagates the Bundle object with RKF45."""
    global h
    ncrd = master.traj[0].dim
    ntraj = master.n_traj()
    kx = np.zeros((ntraj, rk_ordr, ncrd))
    kp = np.zeros((ntraj, rk_ordr, ncrd))
    kg = np.zeros((ntraj, rk_ordr))

    t = 0.
    if h is None:
        h = dt
    while abs(t) < abs(dt):
        hstep = np.sign(dt) * min(abs(h), abs(dt - t))
        for rk in range(rk_ordr):
            tmpbundle = master.copy()
            for i in range(ntraj):
                if tmpbundle.traj[i].active:
                    propagate_rk(tmpbundle.traj[i], hstep, rk, kx[i], kp[i],
                                 kg[i])

            # update the PES to evaluate new gradients
            if rk < rk_ordr - 1:
                surface.update_pes(tmpbundle, update_centroids=False)

        # calculate the 4th and 5th order changes and the error
        dx_lo = np.zeros((master.nalive, ncrd))
        dx_hi = np.zeros((master.nalive, ncrd))
        dp_lo = np.zeros((master.nalive, ncrd))
        dp_hi = np.zeros((master.nalive, ncrd))
        dg_lo = np.zeros((master.nalive))
        dg_hi = np.zeros((master.nalive))
        for i in range(ntraj):
            if master.traj[i].active:
                dx_lo[i] = np.sum(wgt_lo[:, np.newaxis] * kx[i], axis=0)
                dx_hi[i] = np.sum(wgt_hi[:, np.newaxis] * kx[i], axis=0)
                dp_lo[i] = np.sum(wgt_lo[:, np.newaxis] * kp[i], axis=0)
                dp_hi[i] = np.sum(wgt_hi[:, np.newaxis] * kp[i], axis=0)

        if propphase:
            for i in range(ntraj):
                if master.traj[i].active:
                    dg_lo[i] = np.sum(wgt_lo * kg[i])
                    dg_hi[i] = np.sum(wgt_hi * kg[i])


#            print("a="+str(np.abs(dx_hi-dx_lo).flatten()))
#            print("b="+str(np.abs(dp_hi-dp_lo).flatten()))
#            print("c="+str(np.abs(dg_hi-dg_lo)))

            err = np.max(
                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 = hstep * max(safety * (tol / err)**0.25, 0.1)
        else:
            # scale the time step and update the position
            t += h
            err = max(err, tol * 1e-5)
            h *= min(safety * (tol / err)**0.2, 5.)
            for i in range(ntraj):
                if master.traj[i].active:
                    master.traj[i].update_x(master.traj[i].x() + dx_lo[i])
                    master.traj[i].update_p(master.traj[i].p() + dp_lo[i])
                    if propphase:
                        master.traj[i].update_phase(master.traj[i].phase() +
                                                    dg_lo[i])
            surface.update_pes(master, update_centroids=(abs(t) >= abs(dt)))