Exemple #1
0
    def execute_command(self, command, comm):
        global exit_flag

        if command == "EXIT":
            exit_flag = True
        elif command == "<NATOMS":
            mdi.MDI_Send(self.natoms, 1, mdi.MDI_INT, comm)
        else:
            raise Exception(
                "Error in engine_py.py: MDI command not recognized")

        return 0
Exemple #2
0
def perform_tasks(world, mdicomm, dummy):

    me = world.Get_rank()
    nprocs = world.Get_size()

    # allocate vectors for per-atom types, coords, vels, forces

    natoms = nx * ny * nz
    atypes = np.zeros(natoms, dtype=np.int)
    coords = np.zeros(3 * natoms, dtype=np.float64)
    vels = np.zeros(3 * natoms, dtype=np.float64)
    forces = np.zeros(3 * natoms, dtype=np.float64)

    atypes[:] = 1

    # initialize RN generator

    random.seed(seed)

    # loop over sequence of calculations

    for icalc in range(ncalc):

        # define simulation box

        onerho = rho + (random.random() - 0.5) * rhodelta
        sigma = pow(1.0 / onerho, 1.0 / 3.0)

        xlo = ylo = zlo = 0.0
        xhi = nx * sigma
        yhi = ny * sigma
        zhi = nz * sigma

        # send simulation box to engine

        vec = [xhi - xlo, 0.0, 0.0] + [0.0, yhi - ylo, 0.0
                                       ] + [0.0, 0.0, zhi - zlo]
        mdi.MDI_Send_command(">CELL", mdicomm)
        mdi.MDI_Send(vec, 9, mdi.MDI_DOUBLE, mdicomm)

        # create atoms on perfect lattice

        m = 0
        for k in range(nz):
            for j in range(ny):
                for i in range(nx):
                    coords[m] = i * sigma
                    coords[m + 1] = j * sigma
                    coords[m + 2] = k * sigma
                    m += 3

        # perturb lattice

        for m in range(3 * natoms):
            coords[m] += 2.0 * random.random() * delta - delta

        # define initial velocities

        for m in range(3 * natoms):
            vels[m] = random.random() - 0.5

        tcurrent = 0.0
        for m in range(3 * natoms):
            tcurrent += vels[m] * vels[m]
        tcurrent /= 3 * (natoms - 1)

        factor = math.sqrt(tinitial / tcurrent)

        for m in range(3 * natoms):
            vels[m] *= factor

        # send atoms and their properties to engine

        mdi.MDI_Send_command(">NATOMS", mdicomm)
        mdi.MDI_Send(natoms, 1, mdi.MDI_INT, mdicomm)
        mdi.MDI_Send_command(">TYPES", mdicomm)
        mdi.MDI_Send(atypes, natoms, mdi.MDI_INT, mdicomm)
        mdi.MDI_Send_command(">COORDS", mdicomm)
        mdi.MDI_Send(coords, 3 * natoms, mdi.MDI_DOUBLE, mdicomm)
        mdi.MDI_Send_command(">VELOCITIES", mdicomm)
        mdi.MDI_Send(vels, 3 * natoms, mdi.MDI_DOUBLE, mdicomm)

        # eval or run or minimize

        if mode == "eval":
            pass
        elif mode == "run":
            mdi.MDI_Send_command(">NSTEPS", mdicomm)
            mdi.MDI_Send(nsteps, 1, mdi.MDI_INT, mdicomm)
            mdi.MDI_Send_command("MD", mdicomm)
        elif mode == "min":
            mdi.MDI_Send_command(">TOLERANCE", mdicomm)
            params = [tol, tol, 1000.0, 1000.0]
            mdi.MDI_Send(params, 4, mdi.MDI_DOUBLE, mdicomm)
            mdi.MDI_Send_command("OPTG", mdicomm)

        # request potential energy

        mdi.MDI_Send_command("<PE", mdicomm)
        pe = mdi.MDI_Recv(1, mdi.MDI_DOUBLE, mdicomm)
        pe = world.bcast(pe, root=0)

        # request virial tensor

        mdi.MDI_Send_command("<STRESS", mdicomm)
        virial = mdi.MDI_Recv(9, mdi.MDI_DOUBLE, mdicomm)
        virial = world.bcast(virial, root=0)

        # request forces

        mdi.MDI_Send_command("<FORCES", mdicomm)
        mdi.MDI_Recv(3 * natoms, mdi.MDI_DOUBLE, mdicomm, buf=forces)
        world.Bcast(forces, root=0)

        # final output from each calculation
        # pressure = trace of virial tensor, no kinetic component

        aveeng = pe / natoms
        pressure = (virial[0] + virial[4] + virial[8]) / 3.0

        m = 0
        fx = fy = fz = 0.0
        for i in range(natoms):
            fx += forces[m]
            fy += forces[m + 1]
            fz += forces[m + 2]
            m += 3

        fx /= natoms
        fy /= natoms
        fz /= natoms

        line = "Calc %d: eng %7.5g pressure %7.5g aveForce %7.5g %7.5g %7.5g" % \
               (icalc+1,aveeng,pressure,fx,fy,fz)
        if me == 0: print(line)

    # send EXIT command to engine
    # in plugin mode, removes the plugin library

    mdi.MDI_Send_command("EXIT", mdicomm)

    # return needed for plugin mode

    return 0
Exemple #3
0
def perform_aimd(world, mm_comm, qm_comm):

    me = world.Get_rank()

    # receive number of atoms from the MM engine

    mdi.MDI_Send_command("<NATOMS", mm_comm)
    natoms = mdi.MDI_Recv(1, mdi.MDI_INT, mm_comm)
    natoms = world.bcast(natoms, root=0)

    # allocate arrays for coordinates and forces

    coords = np.zeros(3 * natoms, dtype=np.float64)
    forces = np.zeros(3 * natoms, dtype=np.float64)

    # MM engine initializes a new MD simulation

    mdi.MDI_Send_command("@INIT_MD", mm_comm)

    # -----------------
    # compute initial forces for Verlet timestepping
    #   and initial energy for output on step 0
    # -----------------

    # MM engine proceeds to @FORCES node in setup()

    mdi.MDI_Send_command("@FORCES", mm_comm)

    # get coords from MM engine

    mdi.MDI_Send_command("<COORDS", mm_comm)
    mdi.MDI_Recv(3 * natoms, mdi.MDI_DOUBLE, mm_comm, buf=coords)
    world.Bcast(coords, root=0)

    # send coords to QM engine

    mdi.MDI_Send_command(">COORDS", qm_comm)
    mdi.MDI_Send(coords, 3 * natoms, mdi.MDI_DOUBLE, qm_comm)

    # get QM potential energy

    mdi.MDI_Send_command("<PE", qm_comm)
    qm_pe = mdi.MDI_Recv(1, mdi.MDI_DOUBLE, qm_comm)
    qm_pe = world.bcast(qm_pe, root=0)

    # get forces from QM engine

    mdi.MDI_Send_command("<FORCES", qm_comm)
    mdi.MDI_Recv(3 * natoms, mdi.MDI_DOUBLE, qm_comm, buf=forces)
    world.Bcast(forces, root=0)

    # send forces to MM engine

    mdi.MDI_Send_command(">FORCES", mm_comm)
    mdi.MDI_Send(forces, 3 * natoms, mdi.MDI_DOUBLE, mm_comm)

    # get MM kinetic energy

    mdi.MDI_Send_command("<KE", mm_comm)
    mm_ke = mdi.MDI_Recv(1, mdi.MDI_DOUBLE, mm_comm)
    mm_ke = world.bcast(mm_ke, root=0)

    # output by driver
    # normalize energies by atom count

    if me == 0:
        print("Step %d: MM energy %g, QM energy %g, Total energy %g" % \
              (0,mm_ke/natoms,qm_pe/natoms,(mm_ke+qm_pe)/natoms))

    # -----------------
    # timestepping loop
    # -----------------

    for istep in range(nsteps):

        # MM engine proceeds to @FORCES node

        mdi.MDI_Send_command("@FORCES", mm_comm)

        # get coords from MM engine

        mdi.MDI_Send_command("<COORDS", mm_comm)
        mdi.MDI_Recv(3 * natoms, mdi.MDI_DOUBLE, mm_comm, buf=coords)
        world.Bcast(coords, root=0)

        # send coords to QM engine

        mdi.MDI_Send_command(">COORDS", qm_comm)
        mdi.MDI_Send(coords, 3 * natoms, mdi.MDI_DOUBLE, qm_comm)

        # get QM potential energy

        mdi.MDI_Send_command("<PE", qm_comm)
        qm_pe = mdi.MDI_Recv(1, mdi.MDI_DOUBLE, qm_comm)
        qm_pe = world.bcast(qm_pe, root=0)

        # get forces from QM engine

        mdi.MDI_Send_command("<FORCES", qm_comm)
        mdi.MDI_Recv(3 * natoms, mdi.MDI_DOUBLE, qm_comm, buf=forces)
        world.Bcast(forces, root=0)

        # send forces to MM engine

        mdi.MDI_Send_command(">FORCES", mm_comm)
        mdi.MDI_Send(forces, 3 * natoms, mdi.MDI_DOUBLE, mm_comm)

        # MM engine proceeds to @ENDSTEP node
        # so that KE will be for fully updated velocity

        mdi.MDI_Send_command("@ENDSTEP", mm_comm)

        # get MM kinetic energy

        mdi.MDI_Send_command("<KE", mm_comm)
        mm_ke = mdi.MDI_Recv(1, mdi.MDI_DOUBLE, mm_comm)
        mm_ke = world.bcast(mm_ke, root=0)

        # output by driver
        # normalize energies by atom count

        if me == 0:
            print("Step %d: MM energy %g, QM energy %g, Total energy %g" % \
                  (istep+1,mm_ke/natoms,qm_pe/natoms,(mm_ke+qm_pe)/natoms))

    #  send EXIT to each engine

    mdi.MDI_Send_command("EXIT", mm_comm)
    mdi.MDI_Send_command("EXIT", qm_comm)
Exemple #4
0
# receive the number of atoms from the MM code
mdi.MDI_Send_Command("<NATOMS", mm_comm)
natom = mdi.MDI_Recv(1, mdi.MDI_INT, mm_comm)

# have the MD code initialize a new MD simulation
mdi.MDI_Send_Command("MD_INIT", mm_comm)

for iiter in range(niterations):

    # receive the coordinates from the MM code
    mdi.MDI_Send_Command("<COORDS", mm_comm)
    coords = mdi.MDI_Recv(3 * natom, mdi.MDI_DOUBLE, mm_comm)

    # send the coordinates to the QM code
    mdi.MDI_Send_Command(">COORDS", qm_comm)
    mdi.MDI_Send(coords, 3 * natom, mdi.MDI_DOUBLE, qm_comm)

    # run an SCF calculation
    mdi.MDI_Send_Command("SCF", qm_comm)

    # get the QM energy
    mdi.MDI_Send_Command("<ENERGY", qm_comm)
    qm_energy = mdi.MDI_Recv(1, mdi.MDI_DOUBLE, qm_comm)

    # get the MM energy
    mdi.MDI_Send_Command("<ENERGY", mm_comm)
    mm_energy = mdi.MDI_Recv(1, mdi.MDI_DOUBLE, mm_comm)

    # get the QM forces
    mdi.MDI_Send_Command("<FORCES", qm_comm)
    forces = mdi.MDI_Recv(3 * natom, mdi.MDI_DOUBLE, qm_comm)
Exemple #5
0
    # Write the received data to a file 
    f = open("min_driver.dat", "w")
    f.write(str(recv_data))
    f.close()
if nsend is not None:
    if send_type == mdi.MDI_INT:
        data = [ 0 for i in range(send_num) ]
    elif send_type == mdi.MDI_DOUBLE:
        data = [ 0.0 for i in range(send_num) ]
    elif send_type == mdi.MDI_CHAR:
        data = ""
        for i in range(send_num):
            data += " "
    else:
        raise Exception("Invalid send type")
    mdi.MDI_Send(data, send_num, send_type, comm)

# Verify that the engine is still responsive
mdi.MDI_Send_Command("<NAME", comm)
final_name = mdi.MDI_Recv(mdi.MDI_NAME_LENGTH, mdi.MDI_CHAR, comm)
assert initial_name == final_name

# Some nodes might not support the "EXIT" command, so write a file indicating success now
# Write the received data to a file 
f = open("min_driver.err", "w")
f.write("0")
f.close()

mdi.MDI_Send_Command("EXIT", comm)
print("    Completed testing command")
Exemple #6
0
    print("DIMENSIONS: " + str(dimensions))

    # <NATOMS
    mdi.MDI_Send_Command("<NATOMS", mdi_comm)
    natoms = mdi.MDI_Recv(1, mdi.MDI_INT, mdi_comm)
    print("NATOMS: " + str(natoms))

    # <COORDS
    mdi.MDI_Send_Command("<COORDS", mdi_comm)
    coords = mdi.MDI_Recv(3 * natoms, mdi.MDI_DOUBLE, mdi_comm)
    print("COORDS: " + str(coords))

    # >COORDS
    coords[0] += 0.1
    mdi.MDI_Send_Command(">COORDS", mdi_comm)
    mdi.MDI_Send(coords, 3 * natoms, mdi.MDI_DOUBLE, mdi_comm)
    mdi.MDI_Send_Command("<ENERGY", mdi_comm)
    energy = mdi.MDI_Recv(1, mdi.MDI_DOUBLE, mdi_comm)
    print("ENERGY:  " + str(energy))

    # <CHARGES
    mdi.MDI_Send_Command("<CHARGES", mdi_comm)
    charges = mdi.MDI_Recv(natoms, mdi.MDI_DOUBLE, mdi_comm)
    print("CHARGES: " + str(charges))

    # <ELEMENTS
    mdi.MDI_Send_Command("<ELEMENTS", mdi_comm)
    elements = mdi.MDI_Recv(natoms, mdi.MDI_INT, mdi_comm)
    print("ELEMENTS: " + str(elements))

    # <FORCES
    def callback(self, mpi_comm, mdi_comm):

        my_rank = mpi_comm.Get_rank()

        print("PRE MDI SEND <NAME")
        mdi.MDI_Send_Command("<NAME", mdi_comm)
        print("POST MDI SEND <NAME")
        name = mdi.MDI_Recv(mdi.MDI_NAME_LENGTH, mdi.MDI_CHAR, mdi_comm)
        if my_rank == 0:
            print("Engine name: " + str(name))

        # Send the cell dimensions to the plugin
        mdi.MDI_Send_Command(">CELL", mdi_comm)
        mdi.MDI_Send(self.cell, 9, mdi.MDI_DOUBLE, mdi_comm)

        # Find out if the plugin supports the >NATOMS command
        natoms_supported = 0
        natoms_supported = mdi.MDI_Check_command_exists("@DEFAULT", ">NATOMS", mdi_comm)
        natoms_supported = mpi_comm.bcast(natoms_supported, root=0)

        if natoms_supported:

            # Send the number of atoms to the plugin
            mdi.MDI_Send_Command(">NATOMS", mdi_comm)
            mdi.MDI_Send(self.natoms, 1, mdi.MDI_INT, mdi_comm)

        else:

            # We will assume the plugin has read the correct number
            #    of atoms from an input file.
            pass

        # Find out if the plugin supports the >ELEMENTS command
        elem_supported = 0
        elem_supported = mdi.MDI_Check_command_exists("@DEFAULT", ">ELEMENTS", mdi_comm)
        elem_supported = mpi_comm.bcast(elem_supported, root=0)

        if elem_supported:

            # Send the number of elements to the plugin
            mdi.MDI_Send_Command(">ELEMENTS", mdi_comm)
            mdi.MDI_Send(self.elements, self.natoms, mdi.MDI_INT, mdi_comm)

        else:

            # We will assume the plugin has read the correct element
            #    of each atom from an input file.
            pass

        # Send the nuclear coordinates to the plugin
        mdi.MDI_Send_Command(">COORDS", mdi_comm)
        mdi.MDI_Send(self.coords, 3*self.natoms, mdi.MDI_DOUBLE, mdi_comm)

        # Receive the energy of the system from the plugin
        mdi.MDI_Send_Command("<ENERGY", mdi_comm)
        energy = mdi.MDI_Recv(1, mdi.MDI_DOUBLE, mdi_comm)
        if my_rank == 0:
            print("ENERGY: " + str(energy))
        
        # Receive the nuclear forces from the plugin
        mdi.MDI_Send_Command("<FORCES", mdi_comm)
        forces = mdi.MDI_Recv(3*self.natoms, mdi.MDI_DOUBLE, mdi_comm)
        if my_rank == 0:
            print("FORCES: " + str(forces))

        # Send the "EXIT" command to the plugin
        mdi.MDI_Send_Command("EXIT", mdi_comm)

        return 0
Exemple #8
0
    # receive the coordinates
    mdi.MDI_Send_Command("<COORDS", mm_comm)
    coords = mdi.MDI_Recv(3 * natoms, mdi.MDI_DOUBLE, mm_comm)

    # receive the charges
    mdi.MDI_Send_Command("<CHARGES", mm_comm)
    charges = mdi.MDI_Recv(natoms, mdi.MDI_DOUBLE, mm_comm)

    # receive the charges
    mdi.MDI_Send_Command("<MASSES", mm_comm)
    masses = mdi.MDI_Recv(ntypes + 1, mdi.MDI_DOUBLE, mm_comm)

    # get the MM energy
    mdi.MDI_Send_Command("<ENERGY", mm_comm)
    mm_energy = mdi.MDI_Recv(1, mdi.MDI_DOUBLE, mm_comm)

    # send a set of updated forces
    mdi.MDI_Send_Command("+PRE-FORCES", mm_comm)
    mdi.MDI_Send(update_forces, 3 * natoms, mdi.MDI_DOUBLE, mm_comm)

    # do an MD timestep
    mdi.MDI_Send_Command("TIMESTEP", mm_comm)

    print("-------------------------------------")
    print("timestep: " + str(iiter))
    print("   MM Energy: " + str(mm_energy))

# close the production codes
mdi.MDI_Send_Command("EXIT", mm_comm)