Example #1
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
Example #2
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)
Example #3
0
import sys
import mdi

use_mpi4py = False
try:
    from mpi4py import MPI
    use_mpi4py = True
except:
    pass

# Initialize the MDI Library
mdi.MDI_Init(sys.argv[2])

# Connect to the engine
comm = mdi.MDI_Accept_communicator()

# Determine the name of the engine
mdi.MDI_Send_Command("<NAME", comm)
name = mdi.MDI_Recv(mdi.MDI_NAME_LENGTH, mdi.MDI_CHAR, comm)

print("Engine name: " + str(name))

# Send the "EXIT" command to the engine
mdi.MDI_Send_Command("EXIT", comm)
Example #4
0
import mdi as mdi

niterations = 10

# initialize the socket
mdi.MDI_Init(sys.argv[2], None)

# connect to the production codes
ncodes = 2
for icode in range(ncodes):
    comm = mdi.MDI_Accept_Communicator()

    # get the name of the code
    mdi.MDI_Send_Command("<NAME", comm)
    name = mdi.MDI_Recv(mdi.MDI_NAME_LENGTH, mdi.MDI_CHAR, comm)
    print('Received connection: ' + str(name))

    if name.strip() == 'QM':
        qm_comm = comm
    elif name.strip() == 'MM':
        mm_comm = comm
    else:
        raise ValueError('Production code name not recognized')

# 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)
Example #5
0
# LAMMPS engines are stand-alone codes
# world = MPI communicator for just this driver
# invoke perform_tasks() directly

if not plugin:
    mdi.MDI_Init(mdiarg)
    world = mdi.MDI_MPI_get_world_comm()

    # connect to 2 engines, determine which is MM vs QM

    mdicomm1 = mdi.MDI_Accept_Communicator()
    mdicomm2 = mdi.MDI_Accept_Communicator()

    mdi.MDI_Send_command("<NAME", mdicomm1)
    name1 = mdi.MDI_Recv(mdi.MDI_NAME_LENGTH, mdi.MDI_CHAR, mdicomm1)
    name1 = world.bcast(name1, root=0)
    mdi.MDI_Send_command("<NAME", mdicomm2)
    name2 = mdi.MDI_Recv(mdi.MDI_NAME_LENGTH, mdi.MDI_CHAR, mdicomm2)
    name2 = world.bcast(name2, root=0)

    if name1 == "MM" and name2 == "QM":
        mm_comm = mdicomm1
        qm_comm = mdicomm2
    elif name1 == "QM" and name2 == "MM":
        mm_comm = mdicomm2
        qm_comm = mdicomm1
    else:
        error("Two engines have invalid names")

    perform_aimd(world, mm_comm, qm_comm)
Example #6
0
import mdi as mdi

niterations = 10

# initialize the socket
mdi.MDI_Init(sys.argv[2],None)

# connect to the production codes
ncodes = 1
for icode in range(ncodes):
    comm = mdi.MDI_Accept_Communicator()

    # get the name of the code
    mdi.MDI_Send_Command("<NAME", comm)
    name = mdi.MDI_Recv(mdi.MDI_NAME_LENGTH, mdi.MDI_CHAR, comm)
    print('Received connection: ' + str(name))

    if name.strip() == 'MM':
        mm_comm = comm
    else:
        raise ValueError('Production code name not recognized')



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

for iiter in range(niterations):

    # get the MM energy
Example #7
0
        # Set the type of elements to receive
        if len(sys.argv) <= iarg+1:
            raise Exception("Argument to -stype option not found")
        stype = sys.argv[iarg+1]
        iarg += 1
    else:
        raise Exception("Unrecognized argument")

    iarg += 1

# Connect to the engine
comm = mdi.MDI_Accept_Communicator()

# Get the name of the engine, which will be checked and verified at the end
mdi.MDI_Send_Command("<NAME", comm)
initial_name = mdi.MDI_Recv(mdi.MDI_NAME_LENGTH, mdi.MDI_CHAR, comm)

recv_type = None
if nreceive is not None:
    # Get the number of elements to receive
    nreceive_split = re.split("\+|\-|\*\*|\*|\/\/|\/|\%| ",nreceive)
    print("NRECV: " + str(nreceive_split))
    for word in nreceive_split:
        if len(word) > 0 and word[0] == '<':
            print("Found command in nreceive_split")
            # This is a command, so send it to the engine
            # Assume that the command receives a single integer
            mdi.MDI_Send_Command(word, comm)
            value = mdi.MDI_Recv(1, mdi.MDI_INT, comm)
            print("count: " + str(value))
            
Example #8
0
        # Initialize MDI
        if len(sys.argv) <= iarg + 1:
            raise Exception("Argument to -mdi option not found")
        mdi.MDI_Init(sys.argv[iarg + 1], None)
        iarg += 1
    else:
        raise Exception("Unrecognized argument")

    iarg += 1

# Connect to the engine
comm = mdi.MDI_Accept_Communicator()

# Get the name of the engine, which will be checked and verified at the end
mdi.MDI_Send_Command("<NAME", comm)
initial_name = mdi.MDI_Recv(mdi.MDI_NAME_LENGTH, mdi.MDI_CHAR, comm)

##############
print("AAA")
#mdi.MDI_Send_Command("@INIT_OPTG", comm)
print("BBB")

# 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

mdi.MDI_Send_Command("@INIT_MD", comm)
for i in range(100):
    mdi.MDI_Send_Command("@", comm)
Example #9
0
world_comm = mdi.MDI_MPI_get_world_comm()

# Get the MPI rank of this process
if world_comm is not None:
    my_rank = world_comm.Get_rank()
else:
    my_rank = 0

# Accept a connection from an external driver
mdi_comm = mdi.MDI_Accept_Communicator()

# This is the part where you can use MDI
if my_rank == 0:
    # <NAME
    mdi.MDI_Send_Command("<NAME", mdi_comm)
    engine_name = mdi.MDI_Recv(mdi.MDI_NAME_LENGTH, mdi.MDI_CHAR, mdi_comm)
    print("ENGINE NAME: " + str(engine_name))

    # <ENERGY
    mdi.MDI_Send_Command("<ENERGY", mdi_comm)
    energy = mdi.MDI_Recv(1, mdi.MDI_DOUBLE, mdi_comm)
    print("ENERGY:  " + str(energy))

    # <KE
    mdi.MDI_Send_Command("<KE", mdi_comm)
    energy = mdi.MDI_Recv(1, mdi.MDI_DOUBLE, mdi_comm)
    print("KE:       " + str(energy))

    # <KE_ELEC
    mdi.MDI_Send_Command("<KE_ELEC", mdi_comm)
    energy = mdi.MDI_Recv(1, mdi.MDI_DOUBLE, mdi_comm)
Example #10
0
    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
Example #11
0
niterations = 10
for iiteration in range(niterations):

    # Create and connect to a library instance that spans the MPI task communicator
    MDIEngine("-role ENGINE -name MM -method LIBRARY -driver_name driver",
              mpi_task_comm)
    comm = mdi.MDI_Accept_Communicator()

    # Create and connect to a library instance that spans MPI_COMM_WORLD
    MDIEngine("-role ENGINE -name unsplit -method LIBRARY -driver_name driver",
              mpi_world)
    comm_unsplit = mdi.MDI_Accept_Communicator()

    # Communicate with the library instance that spans the MPI task communicator
    mdi.MDI_Send_Command("<NATOMS", comm)
    natoms = mdi.MDI_Recv(1, mdi.MDI_INT, comm)
    if world_rank == 0:
        print("NATOMS: " + str(natoms))
    mdi.MDI_Send_Command("EXIT", comm)

    # Communicate with the library instance that spans MPI_COMM_WORLD
    mdi.MDI_Send_Command("<NATOMS", comm_unsplit)
    natoms = mdi.MDI_Recv(1, mdi.MDI_INT, comm_unsplit)
    if world_rank == 0:
        print("NATOMS: " + str(natoms))
    mdi.MDI_Send_Command("EXIT", comm_unsplit)

if use_mpi4py:
    mpi_world.Barrier()
Example #12
0
import mdi as mdi

niterations = 1000

# initialize the socket
mdi.MDI_Init(sys.argv[2], None)

# connect to the production codes
ncodes = 1
for icode in range(ncodes):
    comm = mdi.MDI_Accept_Communicator()

    # get the name of the code
    mdi.MDI_Send_Command("<NAME", comm)
    name = mdi.MDI_Recv(mdi.MDI_NAME_LENGTH, mdi.MDI_CHAR, comm)
    print('Received connection: ' + str(name))

    if name.strip() == 'MM':
        mm_comm = comm
    else:
        raise ValueError('Production code name not recognized')

# receive the number of atoms
mdi.MDI_Send_Command("<NATOMS", mm_comm)
natoms = mdi.MDI_Recv(1, mdi.MDI_INT, mm_comm)

# receive the number of atom types
mdi.MDI_Send_Command("<NTYPES", mm_comm)
ntypes = mdi.MDI_Recv(1, mdi.MDI_INT, mm_comm)