diff --git a/doc/src/mdi.rst b/doc/src/mdi.rst index 9ba3ba82dd..830a0c5022 100644 --- a/doc/src/mdi.rst +++ b/doc/src/mdi.rst @@ -8,10 +8,19 @@ Syntax .. parsed-literal:: - mdi engine + mdi mode args -* engine = start operating as an MDI engine +* mode = *engine* or *plugin* + .. parsed-literal:: + + *engine* args = none + *plugin* args = keyword value keyword value ... + keywords = *mdi* or *infile* or *extra* or *command* + *mdi* value = args passed to MDI for driver to operate with plugins + *infile* value = filename the engine will read at start-up + *extra* value = aditional command-line args to pass to engine library when loaded + *command value = a LAMMPS input script command to execute Examples """""""" @@ -19,19 +28,33 @@ Examples .. code-block:: LAMMPS mdi engine + mdi plugin lammps mdi "-role ENGINE -name lammps -method LINK" & + infile in.aimd.engine extra "-log log.aimd.engine.plugin" & + command "run 5" Description """"""""""" -This command enables LAMMPS act as a server with another client code -to effectively couple the two codes together in client/server mode. +This command implements two high-level operations within LAMMPS to use +the `MDI Library +` for +coupling to another code. -More specifically, this command causes LAMMPS to begin using the `MDI -Library `_ -to run as an MDI engine (server), responding to MDI commands issued by -an external MDI driver code (client). See the :doc:`Howto mdi -` page for more information about how LAMMPS can operate as -either an MDI driver or engine. +The *engine* mode enables LAMMPS to act as a server, responding to +requests from another client code to effectively couple the two codes +together in client/server mode. In MDI lingo this means LAMMPS +operates as an MDI engine. + +The *plugin* mode enables LAMMPS to act as a client, and load the +server code as a library plugin. In MDI lingo this means LAMMPS +operates as an MDI driver, and the server is an MDI engine. In this +case the MDI engine is a library plugin. It can also be a stand-alone +code, lauched separately from LAMMPS. + +See the Howto MDI doc page for a discussion of all the different ways +2 or more codes can interact via MDI. The examples/mdi/README file +has example use cases and launch commands for using LAMMPS as both a +driver and engine in all these different ways. The examples/mdi directory contains input scripts for LAMMPS acting as an MDI engine to operate as a surrogate quantum mechanics (QM) code @@ -44,26 +67,30 @@ communicate using the MDI library via either MPI or sockets. ---------- -The mdi engine command should typically be used in an input script +The *mdi engine* command should typically be used in an input script after LAMMPS has setup the system it is going to model in collaboration with the driver code. Depending on how the driver code tells the LAMMPS engine to exit, other commands can be executed after -this command, but typically it should be used at the end of the LAMMPS -input script. +this command, but typically it should it is used at the end of a +LAMMPS input script. -To act as a MD-based MDI engine, this is the list of standard MDI -commands issued by a driver code which LAMMPS currently recognizes. -Using standard commands defined by the MDI library means that a driver -code can work interchangeably with LAMMPS or other MD codes which -support the MDI standard. See more details about these commands in -the `MDI library documentation + + +To act as an MDI engine operating as an MD code (or surrogate QM +code), this is the list of standard MDI commands issued by a driver +code which LAMMPS currently recognizes. Using standard commands +defined by the MDI library means that a driver code can work +interchangeably with LAMMPS or other MD codes which support the MDI +standard. See more details about these commands in the `MDI library +documentation `_ These commands are valid at the @DEFAULT node defined by MDI. Commands that start with ">" mean the driver is sending information to the engine (LAMMMPS). Commands that start with "<" are requests by -the driver for LAMMPS to send it information. Command that start with -"@" are MDI "node" commands, which are described further below. +the driver for LAMMPS to send it information. Commands that start +with a letter perform actions. Commands that start with "@" are MDI +"node" commands, which are described further below. .. list-table:: :widths: 20 80 @@ -89,18 +116,26 @@ the driver for LAMMPS to send it information. Command that start with - Request string label of each atom (N values) * - NSTEPS value) + * - OPTG + Perform an energy minimization to convergence (most recent >TOLERANCE values) * - >NATOMS or NSTEPS + - Send number of timesteps for next MD dynamics run via MD command * - TOLERANCE + - Send 4 tolerance parameters for next MD minimization via OPTG command * - >TYPES or VELOCITIES or NSTEPS +value. The OPTG command performs a minimization using the 4 +convergence paremeters from the most recent >TOLERANCE command. The 4 +parameters sent are those used by the :doc:`minimize ` +command in LAMMPS: etol, ftol, maxiter, and maxeval. + The mdi engine command also implements the following custom MDI commands which are LAMMPS-specific. These commands are also valid at the @DEFAULT node defined by MDI: @@ -143,24 +191,20 @@ sufficient to support what a user-written driver code needs. Code to support new commands can be added to the MDI package within LAMMPS, specifically to the src/MDI/mdi_engine.cpp file. -MDI also defines a standard mechanism for the driver to request that an -MD engine (LAMMPS) perform a dynamics simulation or an energy -minimization. This can be done one step (or iteration for -minimization) at a time, where the driver can (optionally) communicate -with LAMMPS at intermediate points of the timestep or iteration by -issuing MDI node commands which start with "@". LAMMPS also adds 2 -custom MDI commands to allow the driver to tell LAMMPS to perform an -entire N-step MD run or an entire minimization to convergence without -intermediate communication from the driver. +MDI also defines a standard mechanism for the driver to request that +an MD engine (LAMMPS) perform a dynamics simulation one step at a time +or an energy minimization one iteration at a time. This is so that +the driver can (optionally) communicate with LAMMPS at intermediate +points of the timestep or iteration by issuing MDI node commands which +start with "@". -To tell LAMMPS to run dynamics, the driver sends as @INIT_MD command -followed by the these commands. The >NITERATE command is a custom -command added by LAMMPS: +To tell LAMMPS to run dynamics in single-step mode, the driver sends +as @INIT_MD command followed by the these commands. The driver +can interact with LAMMPS at 3 node locations within each +timestep: @COORDS, @FORCES, @ENDSTEP: * - Command name - Action - * - >NITERATE - - Send # of timesteps for the MD simulation (1 value) * - @COORDS - Proceed to next @COORDS node = post-integrate location in LAMMPS timestep * - @FORCES @@ -172,14 +216,12 @@ command added by LAMMPS: * - EXIT - Driver tells LAMMPS to exit the MD simulation and engine mode -To tell LAMMPS to run an energy minimization, the driver sends as -@INIT_OPTG command followed by these commands. The >TOLERANCE command -is a custom command added by LAMMPS: +To tell LAMMPS to run an energy minimization in single-iteration mode. +The driver can interact with LAMMPS at 2 node locations within each +iteration of the minimizer: @COORDS, @FORCES: * - Command name - Action - * - >TOLERANCE - - Send tolerance parameters for the minimization (4 values) * - @COORDS - Proceed to next @COORDS node = min-pre-force location in LAMMPS min iteration * - @FORCES @@ -189,9 +231,6 @@ is a custom command added by LAMMPS: * - EXIT - Driver tells LAMMPS to exit the minimization and engine mode -The 4 tolerance parameters are those used by the :doc:`minimize -` command in LAMMPS: etol, ftol, maxiter, and maxeval. - While LAMMPS is at its @COORDS node, the following standard MDI commands are supported, as documented above: >COORDS or -#include - -enum { NONE, REAL, METAL }; // LAMMPS units which MDI supports - -using namespace LAMMPS_NS; -using namespace FixConst; - -/* ---------------------------------------------------------------------- */ - -FixMDIEngineOld::FixMDIEngineOld(LAMMPS *lmp, int narg, char **arg) : - Fix(lmp, narg, arg), id_pe(nullptr), id_ke(nullptr), pe(nullptr), ke(nullptr) -{ - if (narg != 3) error->all(FLERR, "Illegal fix mdi command"); - - // The 2 atomic-scale units LAMMPS has are: - // real: coords = Ang, eng = Kcal/mole, force = Kcal/mole/Ang - // metal: coords = Ang, eng = eV, force = eV/Ang - - lmpunits = NONE; - if (strcmp(update->unit_style, "real") == 0) lmpunits = REAL; - if (strcmp(update->unit_style, "metal") == 0) lmpunits = METAL; - if (lmpunits == NONE) error->all(FLERR, "MDI requires real or metal units"); - - // MDI setup - - most_recent_init = 0; - exit_flag = false; - local_exit_flag = false; - target_command = new char[MDI_COMMAND_LENGTH + 1]; - command = new char[MDI_COMMAND_LENGTH + 1]; - current_node = new char[MDI_COMMAND_LENGTH]; - target_node = new char[MDI_COMMAND_LENGTH]; - strncpy(target_node, "\0", MDI_COMMAND_LENGTH); - strncpy(current_node, "@DEFAULT", MDI_COMMAND_LENGTH); - - // register the execute_command function with MDI - - MDI_Set_execute_command_func(lammps_execute_mdi_command, this); - - // accept a communicator to the driver - // master = 1 for proc 0, otherwise 0 - - master = (comm->me == 0) ? 1 : 0; - - MDI_Accept_communicator(&driver_socket); - if (driver_socket <= 0) error->all(FLERR, "Unable to connect to driver"); - - // create computes for KE and PE - - id_pe = utils::strdup(std::string(id) + "_pe"); - modify->add_compute(fmt::format("{} all pe", id_pe)); - - id_ke = utils::strdup(std::string(id) + "_ke"); - modify->add_compute(fmt::format("{} all ke", id_ke)); - - // irregular class and data structs used by MDI - - irregular = new Irregular(lmp); - add_force = nullptr; -} - -/* ---------------------------------------------------------------------- */ - -FixMDIEngineOld::~FixMDIEngineOld() -{ - delete[] target_command; - delete[] command; - delete[] current_node; - delete[] target_node; - - modify->delete_compute(id_pe); - modify->delete_compute(id_ke); - delete irregular; - memory->destroy(add_force); -} - -/* ---------------------------------------------------------------------- */ - -int FixMDIEngineOld::setmask() -{ - int mask = 0; - - mask |= POST_INTEGRATE; - mask |= POST_FORCE; - mask |= MIN_PRE_FORCE; - mask |= MIN_POST_FORCE; - - return mask; -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::exchange_forces() -{ - double **f = atom->f; - const int *const mask = atom->mask; - const int nlocal = atom->nlocal; - - // add forces from the driver - - for (int i = 0; i < nlocal; ++i) { - if (mask[i] & groupbit) { - f[i][0] += add_force[3 * (atom->tag[i] - 1) + 0]; - f[i][1] += add_force[3 * (atom->tag[i] - 1) + 1]; - f[i][2] += add_force[3 * (atom->tag[i] - 1) + 2]; - } - } -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::init() -{ - // confirm that two required computes are still available - - int icompute_pe = modify->find_compute(id_pe); - if (icompute_pe < 0) error->all(FLERR, "Potential energy ID for fix mdi/engine does not exist"); - int icompute_ke = modify->find_compute(id_ke); - if (icompute_pe < 0) error->all(FLERR, "Kinetic energy ID for fix mdi/engine does not exist"); - - pe = modify->compute[icompute_pe]; - ke = modify->compute[icompute_ke]; - - // one-time allocation of add_force array - - if (!add_force) { - int64_t ncoords = 3 * atom->natoms; - memory->create(add_force, ncoords, "mdi/engine:add_force"); - for (int64_t i = 0; i < ncoords; i++) add_force[i] = 0.0; - } -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::min_setup(int /* vflag */) -{ - engine_mode("@FORCES"); -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::post_integrate() -{ - engine_mode("@COORDS"); -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::min_pre_force(int /* vflag */) -{ - engine_mode("@COORDS"); -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::min_post_force(int /* vflag */) -{ - engine_mode("@FORCES"); -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::post_force(int /* vflag */) -{ - if (most_recent_init == 1) - engine_mode("@FORCES"); - else if (most_recent_init == 2) - engine_mode("@FORCES"); -} - -// ---------------------------------------------------------------------- -// ---------------------------------------------------------------------- -// rest of file processes and responds to MDI driver commands -// ---------------------------------------------------------------------- -// ---------------------------------------------------------------------- - -/* ---------------------------------------------------------------------- - process a single command from driver ----------------------------------------------------------------------- */ - -int FixMDIEngineOld::execute_command(const char *command, MDI_Comm mdicomm) -{ - // confirm this command is supported at this node - - int command_exists = 1; - if (master) { - ierr = MDI_Check_command_exists(current_node, command, MDI_COMM_NULL, &command_exists); - } - if (ierr != 0) error->all(FLERR, "MDI: Unable to check whether current command is supported"); - if (command_exists != 1) - error->all(FLERR, "MDI: Received a command that is unsupported at current node"); - - // respond to any driver command - - if (strcmp(command, ">NATOMS") == 0) { - int64_t mdi_natoms = 0; - ierr = MDI_Recv((char *) &mdi_natoms, 1, MDI_INT64_T, mdicomm); - if (ierr != 0) error->all(FLERR, "MDI: Unable to receive number of atoms from driver"); - error->all(FLERR, "MDI: '>NATOMS' driver command not (yet) supported"); - // FIXME: to import the number of atoms, more steps than below are needed for LAMMPS. - // also a check for overflow is needed in case natoms is 32-bit - atom->natoms = mdi_natoms; - MPI_Bcast(&atom->natoms, 1, MPI_LMP_BIGINT, 0, world); - - } else if (strcmp(command, "natoms; - ierr = MDI_Send((char *) &mdi_natoms, 1, MDI_INT64_T, mdicomm); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send number of atoms to driver"); - - } else if (strcmp(command, "ntypes, 1, MDI_INT, mdicomm); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send number of atom types to driver"); - - } else if (strcmp(command, "CELL") == 0) { - receive_cell(error); - - } else if (strcmp(command, "CELL_DISPL") == 0) { - receive_celldispl(error); - - } else if (strcmp(command, ">COORDS") == 0) { - receive_coordinates(error); - - } else if (strcmp(command, "FORCES") == 0) { - receive_forces(error, 0); - - // add forces received from the driver to current forces - - } else if (strcmp(command, ">+FORCES") == 0) { - receive_forces(error, 1); - - // initialize new MD simulation or minimization - // return control to return to mdi/engine - - } else if (strcmp(command, "@INIT_MD") == 0) { - if (most_recent_init != 0) error->all(FLERR, "MDI: MDI is already performing a simulation"); - most_recent_init = 1; - local_exit_flag = true; - - // initialize new energy minimization - // return control to return to mdi/engine - - } else if (strcmp(command, "@INIT_OPTG") == 0) { - if (most_recent_init != 0) error->all(FLERR, "MDI: MDI is already performing a simulation"); - most_recent_init = 2; - local_exit_flag = true; - - } else if (strcmp(command, "@") == 0) { - strncpy(target_node, "\0", MDI_COMMAND_LENGTH); - local_exit_flag = true; - - } else if (strcmp(command, "<@") == 0) { - ierr = MDI_Send(current_node, MDI_NAME_LENGTH, MDI_CHAR, mdicomm); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send node to driver"); - - } else if (strcmp(command, "etol = std::numeric_limits::max(); - update->ftol = std::numeric_limits::max(); - - // set the maximum number of force evaluations to 0 - update->max_eval = 0; - } - - } else if (strcmp(command, "@COORDS") == 0) { - strncpy(target_node, "@COORDS", MDI_COMMAND_LENGTH); - local_exit_flag = true; - - } else if (strcmp(command, "@FORCES") == 0) { - strncpy(target_node, "@FORCES", MDI_COMMAND_LENGTH); - local_exit_flag = true; - - } else if (strcmp(command, "EXIT") == 0) { - // exit the driver code - exit_flag = true; - - // are we in the middle of a geometry optimization? - if (most_recent_init == 2) { - // ensure that the energy and force tolerances are met - update->etol = std::numeric_limits::max(); - update->ftol = std::numeric_limits::max(); - - // set the maximum number of force evaluations to 0 - update->max_eval = 0; - } - - } else { - error->all(FLERR, "MDI: Unknown command from driver"); - } - - return 0; -} - -/* ---------------------------------------------------------------------- */ - -char *FixMDIEngineOld::engine_mode(const char *node) -{ - /* - if (screen) - fprintf(screen,"MDI ENGINE MODE: %i\n",node); - if (logfile) - fprintf(logfile,"MDI ENGINE MODE: %i\n",node); - */ - - printf("ENG NODE ENTRY eng/driver %s %s %d %d\n", - node,target_node,strlen(node),strlen(target_node)); - - // do not process commands if engine and driver are not at same node - // target_node = node that driver has set via a @ command - // current_node = node that engine (LAMMPS) has set - - strncpy(current_node, node, MDI_COMMAND_LENGTH); - if (strcmp(target_node, "\0") != 0 && strcmp(target_node, current_node) != 0) - local_exit_flag = true; - - // respond to commands from the driver - - while (not exit_flag and not local_exit_flag) { - - // read the next command from the driver - // all procs call this, but only proc 0 receives the command - - ierr = MDI_Recv_command(command, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to receive command from driver"); - - // broadcast command to the other MPI tasks - - MPI_Bcast(command, MDI_COMMAND_LENGTH, MPI_CHAR, 0, world); - - // execute the command - - printf("RECV CMD %s\n",command); - this->execute_command(command, driver_socket); - - // check if the target node is something other than the current node - - printf("ENG NODES eng/driver %s %s %d %d\n", - node,target_node,strlen(node),strlen(target_node)); - - if (strcmp(target_node, "\0") != 0 && strcmp(target_node, current_node) != 0) - local_exit_flag = true; - } - - // local exit occured so turn off local exit flag - - local_exit_flag = false; - - return command; -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::receive_coordinates(Error *error) -{ - // get conversion factor to atomic units - double posconv; - - // real: coords = Ang, eng = Kcal/mole, force = Kcal/mole/Ang - // metal: coords = Ang, eng = eV, force = eV/Ang - - if (lmpunits == REAL) { - double angstrom_to_bohr; - MDI_Conversion_factor("angstrom", "bohr", &angstrom_to_bohr); - posconv = force->angstrom / angstrom_to_bohr; - } else if (lmpunits == METAL) { - double angstrom_to_bohr; - MDI_Conversion_factor("angstrom", "bohr", &angstrom_to_bohr); - posconv = force->angstrom / angstrom_to_bohr; - } - - // create buffer to hold all coords - - double *buffer; - buffer = new double[3 * atom->natoms]; - - ierr = MDI_Recv((char *) buffer, 3 * atom->natoms, MDI_DOUBLE, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to receive coordinates from driver"); - MPI_Bcast(buffer, 3 * atom->natoms, MPI_DOUBLE, 0, world); - - // pick local atoms from the buffer - - double **x = atom->x; - int nlocal = atom->nlocal; - for (int i = 0; i < nlocal; i++) { - x[i][0] = buffer[3 * (atom->tag[i] - 1) + 0] * posconv; - x[i][1] = buffer[3 * (atom->tag[i] - 1) + 1] * posconv; - x[i][2] = buffer[3 * (atom->tag[i] - 1) + 2] * posconv; - } - - // ensure atoms are in current box & update box via shrink-wrap - // has to be be done before invoking Irregular::migrate_atoms() - // since it requires atoms be inside simulation box - - if (domain->triclinic) domain->x2lamda(atom->nlocal); - domain->pbc(); - domain->reset_box(); - if (domain->triclinic) domain->lamda2x(atom->nlocal); - - // move atoms to new processors via irregular() only needed if - // migrate_check() says an atom moves too far - - if (domain->triclinic) domain->x2lamda(atom->nlocal); - if (irregular->migrate_check()) irregular->migrate_atoms(); - if (domain->triclinic) domain->lamda2x(atom->nlocal); - - delete[] buffer; -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::send_coordinates(Error *error) -{ - // get conversion factor to atomic units - double posconv; - if (lmpunits == REAL) { - double angstrom_to_bohr; - MDI_Conversion_factor("angstrom", "bohr", &angstrom_to_bohr); - posconv = force->angstrom / angstrom_to_bohr; - } else if (lmpunits == METAL) { - double angstrom_to_bohr; - MDI_Conversion_factor("angstrom", "bohr", &angstrom_to_bohr); - posconv = force->angstrom / angstrom_to_bohr; - } - - int64_t ncoords = 3 * atom->natoms; - double *coords; - double *coords_reduced; - memory->create(coords, ncoords, "mdi/engine:coords"); - memory->create(coords_reduced, ncoords, "mdi/engine:coords_reduced"); - - // zero coords - - for (int64_t icoord = 0; icoord < ncoords; icoord++) coords[icoord] = 0.0; - - // copy local atoms into buffer at correct locations - - double **x = atom->x; - int nlocal = atom->nlocal; - for (int i = 0; i < nlocal; i++) { - coords[3 * (atom->tag[i] - 1) + 0] = x[i][0] / posconv; - coords[3 * (atom->tag[i] - 1) + 1] = x[i][1] / posconv; - coords[3 * (atom->tag[i] - 1) + 2] = x[i][2] / posconv; - } - - MPI_Reduce(coords, coords_reduced, 3 * atom->natoms, MPI_DOUBLE, MPI_SUM, 0, world); - - ierr = MDI_Send((char *) coords_reduced, 3 * atom->natoms, MDI_DOUBLE, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send coordinates to driver"); - - memory->destroy(coords); - memory->destroy(coords_reduced); -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::send_charges(Error *error) -{ - double *charges; - double *charges_reduced; - - memory->create(charges, atom->natoms, "mdi/engine:charges"); - memory->create(charges_reduced, atom->natoms, "mdi/engine:charges_reduced"); - - // zero the charges array - - for (int icharge = 0; icharge < atom->natoms; icharge++) charges[icharge] = 0.0; - - // pick local atoms from the buffer - - double *charge = atom->q; - int nlocal = atom->nlocal; - for (int i = 0; i < nlocal; i++) { charges[atom->tag[i] - 1] = charge[i]; } - - MPI_Reduce(charges, charges_reduced, atom->natoms, MPI_DOUBLE, MPI_SUM, 0, world); - - ierr = MDI_Send((char *) charges_reduced, atom->natoms, MDI_DOUBLE, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send charges to driver"); - - memory->destroy(charges); - memory->destroy(charges_reduced); -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::send_energy(Error *error) -{ - // get conversion factor to atomic units - double energy_conv = 1.0; - if (lmpunits == REAL) { - double kelvin_to_hartree; - MDI_Conversion_factor("kelvin_energy", "hartree", &kelvin_to_hartree); - energy_conv = kelvin_to_hartree / force->boltz; - } else if (lmpunits == METAL) { - double ev_to_hartree; - MDI_Conversion_factor("electron_volt", "hartree", &ev_to_hartree); - energy_conv = ev_to_hartree; - } - - double kelvin_to_hartree; - MDI_Conversion_factor("kelvin_energy", "hartree", &kelvin_to_hartree); - - double potential_energy = pe->compute_scalar(); - double kinetic_energy = ke->compute_scalar(); - double total_energy; - double *send_energy = &total_energy; - - // convert the energy to atomic units - potential_energy *= energy_conv; - kinetic_energy *= energy_conv; - total_energy = potential_energy + kinetic_energy; - - ierr = MDI_Send((char *) send_energy, 1, MDI_DOUBLE, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send potential energy to driver"); -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::send_pe(Error *error) -{ - // get conversion factor to atomic units - double energy_conv; - if (lmpunits == REAL) { - double kelvin_to_hartree; - MDI_Conversion_factor("kelvin_energy", "hartree", &kelvin_to_hartree); - energy_conv = kelvin_to_hartree / force->boltz; - } else if (lmpunits == METAL) { - double ev_to_hartree; - MDI_Conversion_factor("electron_volt", "hartree", &ev_to_hartree); - energy_conv = ev_to_hartree; - } - - double potential_energy = pe->compute_scalar(); - double *send_energy = &potential_energy; - - // convert the energy to atomic units - potential_energy *= energy_conv; - - ierr = MDI_Send((char *) send_energy, 1, MDI_DOUBLE, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send potential energy to driver"); -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::send_ke(Error *error) -{ - // get conversion factor to atomic units - double energy_conv; - if (lmpunits == REAL) { - double kelvin_to_hartree; - MDI_Conversion_factor("kelvin_energy", "hartree", &kelvin_to_hartree); - energy_conv = kelvin_to_hartree / force->boltz; - } else if (lmpunits == METAL) { - double ev_to_hartree; - MDI_Conversion_factor("electron_volt", "hartree", &ev_to_hartree); - energy_conv = ev_to_hartree; - } - - double kinetic_energy = ke->compute_scalar(); - double *send_energy = &kinetic_energy; - - // convert the energy to atomic units - kinetic_energy *= energy_conv; - - ierr = MDI_Send((char *) send_energy, 1, MDI_DOUBLE, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send potential energy to driver"); -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::send_types(Error *error) -{ - int *const type = atom->type; - - ierr = MDI_Send((char *) type, atom->natoms, MDI_INT, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send atom types to driver"); -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::send_labels(Error *error) -{ - char *labels = new char[atom->natoms * MDI_LABEL_LENGTH]; - memset(labels, ' ', atom->natoms * MDI_LABEL_LENGTH); - - for (int iatom = 0; iatom < atom->natoms; iatom++) { - std::string label = std::to_string(atom->type[iatom]); - int label_len = std::min(int(label.length()), MDI_LABEL_LENGTH); - strncpy(&labels[iatom * MDI_LABEL_LENGTH], label.c_str(), label_len); - } - - ierr = MDI_Send(labels, atom->natoms * MDI_LABEL_LENGTH, MDI_CHAR, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send atom types to driver"); - - delete[] labels; -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::send_masses(Error *error) -{ - double *const rmass = atom->rmass; - double *const mass = atom->mass; - int *const type = atom->type; - int nlocal = atom->nlocal; - - double *mass_by_atom; - double *mass_by_atom_reduced; - memory->create(mass_by_atom, atom->natoms, "mdi/engine:mass_by_atom"); - memory->create(mass_by_atom_reduced, atom->natoms, "mdi/engine:mass_by_atom_reduced"); - for (int iatom = 0; iatom < atom->natoms; iatom++) { mass_by_atom[iatom] = 0.0; } - - // determine the atomic masses - - if (rmass) { - for (int iatom = 0; iatom < nlocal; iatom++) { - mass_by_atom[atom->tag[iatom] - 1] = rmass[iatom]; - } - } else { - for (int iatom = 0; iatom < nlocal; iatom++) { - mass_by_atom[atom->tag[iatom] - 1] = mass[type[iatom]]; - } - } - - MPI_Reduce(mass_by_atom, mass_by_atom_reduced, atom->natoms, MPI_DOUBLE, MPI_SUM, 0, world); - - // send the atomic masses to the driver - - ierr = MDI_Send((char *) mass_by_atom_reduced, atom->natoms, MDI_DOUBLE, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send atom masses to driver"); - - memory->destroy(mass_by_atom); - memory->destroy(mass_by_atom_reduced); -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::send_forces(Error *error) -{ - // get conversion factor to atomic units - double force_conv; - if (lmpunits == REAL) { - double kelvin_to_hartree; - double angstrom_to_bohr; - MDI_Conversion_factor("kelvin_energy", "hartree", &kelvin_to_hartree); - MDI_Conversion_factor("angstrom", "bohr", &angstrom_to_bohr); - force_conv = (kelvin_to_hartree / force->boltz) * (force->angstrom / angstrom_to_bohr); - } else if (lmpunits == METAL) { - double ev_to_hartree; - double angstrom_to_bohr; - MDI_Conversion_factor("electron_volt", "hartree", &ev_to_hartree); - MDI_Conversion_factor("angstrom", "bohr", &angstrom_to_bohr); - force_conv = ev_to_hartree / angstrom_to_bohr; - } - - double *forces; - double *forces_reduced; - double *x_buf; - - int nlocal = atom->nlocal; - int64_t ncoords = 3 * atom->natoms; - - memory->create(forces, ncoords, "mdi/engine:forces"); - memory->create(forces_reduced, ncoords, "mdi/engine:forces_reduced"); - x_buf = new double[3 * nlocal]; - - // zero the forces array - - for (int iforce = 0; iforce < 3 * atom->natoms; iforce++) forces[iforce] = 0.0; - - // if not at a node, calculate the forces - - if (strcmp(current_node, "@DEFAULT") == 0) { - // certain fixes, such as shake, move the coordinates - // to ensure that the coordinates do not change, store a copy - double **x = atom->x; - for (int i = 0; i < nlocal; i++) { - x_buf[3 * i + 0] = x[i][0]; - x_buf[3 * i + 1] = x[i][1]; - x_buf[3 * i + 2] = x[i][2]; - } - - // calculate the forces - update->whichflag = 1; // 1 for dynamics - update->nsteps = 1; - lmp->init(); - update->integrate->setup_minimal(1); - - if (strcmp(current_node, "@DEFAULT") == 0) { - // restore the original set of coordinates - double **x_new = atom->x; - for (int i = 0; i < nlocal; i++) { - x_new[i][0] = x_buf[3 * i + 0]; - x_new[i][1] = x_buf[3 * i + 1]; - x_new[i][2] = x_buf[3 * i + 2]; - } - } - } - - // pick local atoms from the buffer - double **f = atom->f; - for (int i = 0; i < nlocal; i++) { - forces[3 * (atom->tag[i] - 1) + 0] = f[i][0] * force_conv; - forces[3 * (atom->tag[i] - 1) + 1] = f[i][1] * force_conv; - forces[3 * (atom->tag[i] - 1) + 2] = f[i][2] * force_conv; - } - - // reduce the forces onto rank 0 - MPI_Reduce(forces, forces_reduced, 3 * atom->natoms, MPI_DOUBLE, MPI_SUM, 0, world); - - // send the forces through MDI - ierr = MDI_Send((char *) forces_reduced, 3 * atom->natoms, MDI_DOUBLE, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send atom forces to driver"); - - memory->destroy(forces); - memory->destroy(forces_reduced); - delete[] x_buf; -} - -/* ---------------------------------------------------------------------- */ - -// Receive forces from the driver -// mode = 0: replace current forces with forces from driver -// mode = 1: add forces from driver to current forces - -void FixMDIEngineOld::receive_forces(Error *error, int mode) -{ - // get conversion factor to atomic units - double force_conv; - if (lmpunits == REAL) { - double kelvin_to_hartree; - double angstrom_to_bohr; - MDI_Conversion_factor("kelvin_energy", "hartree", &kelvin_to_hartree); - MDI_Conversion_factor("angstrom", "bohr", &angstrom_to_bohr); - force_conv = (kelvin_to_hartree / force->boltz) * (force->angstrom / angstrom_to_bohr); - } else if (lmpunits == METAL) { - double ev_to_hartree; - double angstrom_to_bohr; - MDI_Conversion_factor("electron_volt", "hartree", &ev_to_hartree); - MDI_Conversion_factor("angstrom", "bohr", &angstrom_to_bohr); - force_conv = ev_to_hartree / angstrom_to_bohr; - } - - int64_t ncoords = 3 * atom->natoms; - double *forces; - memory->create(forces, ncoords, "mdi/engine:forces"); - - ierr = MDI_Recv((char *) forces, 3 * atom->natoms, MDI_DOUBLE, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to receive atom forces to driver"); - MPI_Bcast(forces, 3 * atom->natoms, MPI_DOUBLE, 0, world); - - // pick local atoms from the buffer - double **f = atom->f; - int nlocal = atom->nlocal; - - if (mode == 0) { // Replace - for (int i = 0; i < nlocal; i++) { - f[i][0] = forces[3 * (atom->tag[i] - 1) + 0] / force_conv; - f[i][1] = forces[3 * (atom->tag[i] - 1) + 1] / force_conv; - f[i][2] = forces[3 * (atom->tag[i] - 1) + 2] / force_conv; - } - } else { - for (int i = 0; i < nlocal; i++) { - f[i][0] += forces[3 * (atom->tag[i] - 1) + 0] / force_conv; - f[i][1] += forces[3 * (atom->tag[i] - 1) + 1] / force_conv; - f[i][2] += forces[3 * (atom->tag[i] - 1) + 2] / force_conv; - } - } - - memory->destroy(forces); -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::send_cell(Error *error) -{ - double angstrom_to_bohr; - MDI_Conversion_factor("angstrom", "bohr", &angstrom_to_bohr); - - double celldata[9]; - - celldata[0] = domain->boxhi[0] - domain->boxlo[0]; - celldata[1] = 0.0; - celldata[2] = 0.0; - celldata[3] = domain->xy; - celldata[4] = domain->boxhi[1] - domain->boxlo[1]; - celldata[5] = 0.0; - celldata[6] = domain->xz; - celldata[7] = domain->yz; - celldata[8] = domain->boxhi[2] - domain->boxlo[2]; - - // convert the units to bohr - - double unit_conv = force->angstrom * angstrom_to_bohr; - for (int icell = 0; icell < 9; icell++) { celldata[icell] *= unit_conv; } - - ierr = MDI_Send((char *) celldata, 9, MDI_DOUBLE, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send cell dimensions to driver"); -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::receive_cell(Error *error) -{ - double celldata[9]; - - // receive the new cell vector from the driver - ierr = MDI_Recv((char *) celldata, 9, MDI_DOUBLE, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send cell dimensions to driver"); - MPI_Bcast(&celldata[0], 9, MPI_DOUBLE, 0, world); - - double angstrom_to_bohr; - MDI_Conversion_factor("angstrom", "bohr", &angstrom_to_bohr); - double unit_conv = force->angstrom * angstrom_to_bohr; - for (int icell = 0; icell < 9; icell++) { celldata[icell] /= unit_conv; } - - // ensure that the new cell vector is orthogonal - double small = std::numeric_limits::min(); - if (fabs(celldata[1]) > small or fabs(celldata[2]) > small or fabs(celldata[3]) > small or - fabs(celldata[5]) > small or fabs(celldata[6]) > small or fabs(celldata[7]) > small) { - error->all(FLERR, - "MDI: LAMMPS currently only supports the >CELL command for orthogonal cell vectors"); - } - - // set the new LAMMPS cell dimensions - // This only works for orthogonal cell vectors. - // Supporting the more general case would be possible, - // but considerably more complex. - domain->boxhi[0] = celldata[0] + domain->boxlo[0]; - domain->boxhi[1] = celldata[4] + domain->boxlo[1]; - domain->boxhi[2] = celldata[8] + domain->boxlo[2]; - domain->xy = 0.0; - domain->xz = 0.0; - domain->yz = 0.0; -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::send_celldispl(Error *error) -{ - double angstrom_to_bohr; - MDI_Conversion_factor("angstrom", "bohr", &angstrom_to_bohr); - - double celldata[3]; - - celldata[0] = domain->boxlo[0]; - celldata[1] = domain->boxlo[1]; - celldata[2] = domain->boxlo[2]; - - // convert the units to bohr - - double unit_conv = force->angstrom * angstrom_to_bohr; - for (int icell = 0; icell < 3; icell++) { celldata[icell] *= unit_conv; } - - ierr = MDI_Send((char *) celldata, 3, MDI_DOUBLE, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to send cell displacement to driver"); -} - -/* ---------------------------------------------------------------------- */ - -void FixMDIEngineOld::receive_celldispl(Error *error) -{ - // receive the cell displacement from the driver - double celldata[3]; - ierr = MDI_Recv((char *) celldata, 3, MDI_DOUBLE, driver_socket); - if (ierr != 0) error->all(FLERR, "MDI: Unable to receive cell displacement from driver"); - MPI_Bcast(&celldata[0], 3, MPI_DOUBLE, 0, world); - - double angstrom_to_bohr; - MDI_Conversion_factor("angstrom", "bohr", &angstrom_to_bohr); - double unit_conv = force->angstrom * angstrom_to_bohr; - - double old_boxlo[3]; - old_boxlo[0] = domain->boxlo[0]; - old_boxlo[1] = domain->boxlo[1]; - old_boxlo[2] = domain->boxlo[2]; - - // adjust the values of boxlo and boxhi for the new cell displacement vector - domain->boxlo[0] = celldata[0] / unit_conv; - domain->boxlo[1] = celldata[1] / unit_conv; - domain->boxlo[2] = celldata[2] / unit_conv; - domain->boxhi[0] += domain->boxlo[0] - old_boxlo[0]; - domain->boxhi[1] += domain->boxlo[1] - old_boxlo[1]; - domain->boxhi[2] += domain->boxlo[2] - old_boxlo[2]; -} diff --git a/src/MDI/fix_mdi_engine_old.h b/src/MDI/fix_mdi_engine_old.h deleted file mode 100644 index 4fc87999a0..0000000000 --- a/src/MDI/fix_mdi_engine_old.h +++ /dev/null @@ -1,143 +0,0 @@ -/* -*- c++ -*- ---------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - https://www.lammps.org/ Sandia National Laboratories - Steve Plimpton, sjplimp@sandia.gov - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -#ifdef FIX_CLASS -// clang-format off -FixStyle(mdi/engine/old, FixMDIEngineOld); -// clang-format on -#else - -#ifndef LMP_FIX_MDI_ENGINE_OLD_H -#define LMP_FIX_MDI_ENGINE_OLD_H - -#include "fix.h" -#include "mdi.h" - -namespace LAMMPS_NS { - -class FixMDIEngineOld : public Fix { - public: - FixMDIEngineOld(class LAMMPS *, int, char **); - ~FixMDIEngineOld(); - int setmask(); - void init(); - - int execute_command(const char *command, MDI_Comm driver_socket); - char *engine_mode(const char *node); - - // receive and update forces - - //void setup(int); - void min_setup(int); - void post_integrate(); - void post_force(int); - void min_pre_force(int); //@COORDS - void min_post_force(int); //@FORCES - - double *add_force; // stores forces added using +FORCE command - double potential_energy; // stores potential energy - double kinetic_energy; // stores kinetic energy - - // current command - - char *command; - - protected: - void exchange_forces(); - - private: - int lmpunits; // REAL or METAL - int master, ierr; - int driver_socket; - int most_recent_init; // which MDI init command was most recently received? - // 0 - none - // 1 - MD - // 2 - OPTG - bool exit_flag; - bool local_exit_flag; - char *current_node; - char *target_node; // is the code supposed to advance to a particular node? - // 0 - none - // 1 - @COORDS (before pre-force calculation) - // 2 - @PRE-FORCES (before final force calculation) - // 3 - @FORCES (before time integration) - // -1 - after MD_INIT command - // -2 - after MD_INIT command followed by @PRE-FORCES (actually @INIT_OPTG?) - - // command to be executed at the target node - - char *target_command; - - char *id_pe; - char *id_ke; - class Irregular *irregular; - class Minimize *minimizer; - class Compute *pe; - class Compute *ke; - - void send_types(Error *); - void send_labels(Error *); - void send_masses(Error *); - void receive_coordinates(Error *); - void send_coordinates(Error *); - void send_charges(Error *); - void send_energy(Error *); - void send_forces(Error *); - void send_pe(Error *); - void send_ke(Error *); - void receive_forces(Error *, int); - void send_cell(Error *); - void receive_cell(Error *); - void send_celldispl(Error *); - void receive_celldispl(Error *); -}; - -} // namespace LAMMPS_NS - -#endif -#endif - -/* ERROR/WARNING messages: - -E: Illegal ... command - -Self-explanatory. - -E: Potential energy ID for fix mdi does not exist - -Self-explanatory. - -E: Cannot use MDI command without atom IDs - -Self-explanatory. - -E: MDI command requires consecutive atom IDs - -Self-explanatory. - -E: Unable to connect to driver - -Self-explanatory. - -E: Unable to ... driver - -Self-explanatory. - -E: Unknown command from driver - -The driver sent a command that is not supported by the LAMMPS -interface. In some cases this might be because a nonsensical -command was sent (i.e. "SCF"). In other cases, the LAMMPS -interface might benefit from being expanded. - -*/ diff --git a/src/MDI/mdi_engine_old.cpp b/src/MDI/mdi_engine_old.cpp deleted file mode 100644 index cb711c2780..0000000000 --- a/src/MDI/mdi_engine_old.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/* ---------------------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - https://www.lammps.org/ Sandia National Laboratories - Steve Plimpton, sjplimp@sandia.gov - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -/* ---------------------------------------------------------------------- - Contributing author: Taylor Barnes (MolSSI) - MolSSI Driver Interface (MDI) support for LAMMPS -------------------------------------------------------------------------- */ - -#include "mdi_engine_old.h" - -#include "atom.h" -#include "error.h" -#include "fix_mdi_engine_old.h" -#include "force.h" -#include "mdi.h" -#include "min.h" -#include "minimize.h" -#include "modify.h" -#include "output.h" -#include "timer.h" -#include "update.h" -#include "verlet.h" - -#include -#include - -using namespace LAMMPS_NS; - -/* ---------------------------------------------------------------------- - trigger LAMMPS to start acting as an MDI engine - endlessly loop over receiving commands from driver and responding - much of the logic for this is in FixMDIEngine - when EXIT command is received, mdi/engine command exits ----------------------------------------------------------------------- */ - -void MDIEngineOld::command(int narg, char ** /*arg*/) -{ - // list of nodes and commands that a MDI-compliant MD code should support - - // default node and its commands - - MDI_Register_node("@DEFAULT"); - MDI_Register_command("@DEFAULT", "<@"); - MDI_Register_command("@DEFAULT", "CELL"); - MDI_Register_command("@DEFAULT", ">CELL_DISPL"); - MDI_Register_command("@DEFAULT", ">COORDS"); - MDI_Register_command("@DEFAULT", "@INIT_MD"); - MDI_Register_command("@DEFAULT", "@INIT_OPTG"); - MDI_Register_command("@DEFAULT", "EXIT"); - - // node for setting up and running a dynamics simulation - - MDI_Register_node("@INIT_MD"); - MDI_Register_command("@INIT_MD", "<@"); - MDI_Register_command("@INIT_MD", "CELL"); - MDI_Register_command("@INIT_MD", ">CELL_DISPL"); - MDI_Register_command("@INIT_MD", ">COORDS"); - MDI_Register_command("@INIT_MD", ">FORCES"); - MDI_Register_command("@INIT_MD", ">+FORCES"); - MDI_Register_command("@INIT_MD", "@"); - MDI_Register_command("@INIT_MD", "@COORDS"); - MDI_Register_command("@INIT_MD", "@DEFAULT"); - MDI_Register_command("@INIT_MD", "@FORCES"); - MDI_Register_command("@INIT_MD", "EXIT"); - - // node for setting up and running a minimization - - MDI_Register_node("@INIT_OPTG"); - MDI_Register_command("@INIT_OPTG", "<@"); - MDI_Register_command("@INIT_OPTG", "CELL"); - MDI_Register_command("@INIT_OPTG", ">CELL_DISPL"); - MDI_Register_command("@INIT_OPTG", ">COORDS"); - MDI_Register_command("@INIT_OPTG", ">FORCES"); - MDI_Register_command("@INIT_OPTG", ">+FORCES"); - MDI_Register_command("@INIT_OPTG", "@"); - MDI_Register_command("@INIT_OPTG", "@COORDS"); - MDI_Register_command("@INIT_OPTG", "@DEFAULT"); - MDI_Register_command("@INIT_OPTG", "@FORCES"); - MDI_Register_command("@INIT_OPTG", "EXIT"); - - // node at POST_FORCE location in timestep - - MDI_Register_node("@FORCES"); - MDI_Register_callback("@FORCES", ">FORCES"); - MDI_Register_callback("@FORCES", ">+FORCES"); - MDI_Register_command("@FORCES", "<@"); - MDI_Register_command("@FORCES", "CELL"); - MDI_Register_command("@FORCES", ">CELL_DISPL"); - MDI_Register_command("@FORCES", ">COORDS"); - MDI_Register_command("@FORCES", ">FORCES"); - MDI_Register_command("@FORCES", ">+FORCES"); - MDI_Register_command("@FORCES", "@"); - MDI_Register_command("@FORCES", "@COORDS"); - MDI_Register_command("@FORCES", "@DEFAULT"); - MDI_Register_command("@FORCES", "@FORCES"); - MDI_Register_command("@FORCES", "EXIT"); - - // node at POST_INTEGRATE location in timestep - - MDI_Register_node("@COORDS"); - MDI_Register_command("@COORDS", "<@"); - MDI_Register_command("@COORDS", "CELL"); - MDI_Register_command("@COORDS", ">CELL_DISPL"); - MDI_Register_command("@COORDS", ">COORDS"); - MDI_Register_command("@COORDS", ">FORCES"); - MDI_Register_command("@COORDS", ">+FORCES"); - MDI_Register_command("@COORDS", "@"); - MDI_Register_command("@COORDS", "@COORDS"); - MDI_Register_command("@COORDS", "@DEFAULT"); - MDI_Register_command("@COORDS", "@FORCES"); - MDI_Register_command("@COORDS", "EXIT"); - - // if the mdi/engine fix is not already present, add it now - - std::vector matches = modify->get_fix_by_style("mdi/engine/old"); - bool added_mdi_engine_fix = false; - if (matches.size() == 0) { - modify->add_fix("MDI_ENGINE_INTERNAL all mdi/engine/old"); - added_mdi_engine_fix = true; - } - - // identify the mdi_engine fix - - matches = modify->get_fix_by_style("mdi/engine/old"); - mdi_fix = (FixMDIEngineOld *) matches[0]; - - // check that LAMMPS is setup as a compatible MDI engine - - if (narg > 0) error->all(FLERR, "Illegal mdi/engine command"); - - if (atom->tag_enable == 0) error->all(FLERR, "Cannot use mdi/engine without atom IDs"); - - if (atom->tag_consecutive() == 0) error->all(FLERR, "mdi/engine requires consecutive atom IDs"); - - // endless engine loop, responding to driver commands - - char *command; - - while (1) { - - // mdi/engine command only recognizes three nodes - // DEFAULT, INIT_MD, INIT_OPTG - - command = mdi_fix->engine_mode("@DEFAULT"); - - // MDI commands for dynamics or minimization - - if (strcmp(command, "@INIT_MD") == 0) { - command = mdi_md(); - if (strcmp(command, "EXIT")) break; - - } else if (strcmp(command, "@INIT_OPTG") == 0) { - command = mdi_optg(); - if (strcmp(command, "EXIT")) break; - - } else if (strcmp(command, "EXIT") == 0) { - break; - - } else - error->all(FLERR, "MDI node exited with invalid command: {}", command); - } - - // remove mdi/engine fix that mdi/engine instantiated - - if (added_mdi_engine_fix) modify->delete_fix("MDI_ENGINE_INTERNAL"); -} - -/* ---------------------------------------------------------------------- - run an MD simulation under control of driver ----------------------------------------------------------------------- */ - -char *MDIEngineOld::mdi_md() -{ - // initialize an MD simulation - - update->whichflag = 1; - timer->init_timeout(); - update->nsteps = 1; - update->ntimestep = 0; - update->firststep = update->ntimestep; - update->laststep = update->ntimestep + update->nsteps; - update->beginstep = update->firststep; - update->endstep = update->laststep; - - lmp->init(); - - // engine is now at @INIT_MD node - - char *command = nullptr; - command = mdi_fix->engine_mode("@INIT_MD"); - - if (strcmp(command, "@DEFAULT") == 0 || strcmp(command, "EXIT") == 0) return command; - - // setup the MD simulation - - update->integrate->setup(1); - - command = mdi_fix->engine_mode("@FORCES"); - - if (strcmp(command, "@DEFAULT") == 0 || strcmp(command, "EXIT") == 0) return command; - - // run MD one step at a time - - while (1) { - update->whichflag = 1; - timer->init_timeout(); - update->nsteps += 1; - update->laststep += 1; - update->endstep = update->laststep; - output->next = update->ntimestep + 1; - - // single MD timestep - - update->integrate->run(1); - - // done with MD if driver sends @DEFAULT or EXIT - - command = mdi_fix->command; - - if (strcmp(command, "@DEFAULT") == 0 || strcmp(command, "EXIT") == 0) return command; - } - - return nullptr; -} - -/* ---------------------------------------------------------------------- - perform minimization under control of driver ----------------------------------------------------------------------- */ - -char *MDIEngineOld::mdi_optg() -{ - - // setup the minimizer in a way that ensures optimization - // will continue until MDI driver exits - - update->etol = std::numeric_limits::min(); - update->ftol = std::numeric_limits::min(); - update->nsteps = std::numeric_limits::max(); - update->max_eval = std::numeric_limits::max(); - - update->whichflag = 2; - update->beginstep = update->firststep = update->ntimestep; - update->endstep = update->laststep = update->firststep + update->nsteps; - - lmp->init(); - - // engine is now at @INIT_OPTG node - - char *command = nullptr; - command = mdi_fix->engine_mode("@INIT_OPTG"); - - if (strcmp(command, "@DEFAULT") == 0 || strcmp(command, "EXIT") == 0) return command; - - // setup the minimization - - update->minimize->setup(); - - // get new command - - command = mdi_fix->command; - - if (strcmp(command, "@DEFAULT") == 0 || strcmp(command, "EXIT") == 0) return command; - - // Start a minimization, which is configured to run (essentially) - // infinite steps. When the driver sends the EXIT command, - // the minimizer's energy and force tolerances are set to - // extremely large values, causing the minimization to end. - - update->minimize->iterate(update->nsteps); - - // return if driver sends @DEFAULT or EXIT - - command = mdi_fix->command; - - if (strcmp(command, "@DEFAULT") == 0 || strcmp(command, "EXIT") == 0) return command; - - error->all(FLERR, "MDI reached end of OPTG simulation with invalid command: {}", command); - return nullptr; -} diff --git a/src/MDI/mdi_engine_old.h b/src/MDI/mdi_engine_old.h deleted file mode 100644 index bea4574e61..0000000000 --- a/src/MDI/mdi_engine_old.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- c++ -*- ---------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - https://www.lammps.org/ Sandia National Laboratories - Steve Plimpton, sjplimp@sandia.gov - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -#ifdef COMMAND_CLASS -// clang-format off -CommandStyle(mdi/engine, MDIEngineOld); -// clang-format on -#else - -#ifndef LMP_MDI_ENGINE_OLD_H -#define LMP_MDI_ENGINE_OLD_H - -#include "command.h" - -namespace LAMMPS_NS { - -class MDIEngineOld : public Command { - public: - MDIEngineOld(LAMMPS *lmp) : Command(lmp) {} - virtual ~MDIEngineOld() {} - void command(int, char **); - - private: - class FixMDIEngineOld *mdi_fix; - - char *mdi_md(); - char *mdi_optg(); -}; - -} // namespace LAMMPS_NS - -#endif -#endif - -/* ERROR/WARNING messages: - -E: Illegal ... command - -Self-explanatory. Check the input script syntax and compare to the -documentation for the command. You can use -echo screen as a -command-line option when running LAMMPS to see the offending line. - -*/ diff --git a/src/MDI/mdi_plugin.cpp b/src/MDI/mdi_plugin.cpp index 34402ee85b..9d2d2b6475 100644 --- a/src/MDI/mdi_plugin.cpp +++ b/src/MDI/mdi_plugin.cpp @@ -91,6 +91,7 @@ MDIPlugin::MDIPlugin(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) } // find FixMDIAimd instance so can reset its mdicomm + // NOTE: this is a kludge - need better way to handle this fixptr = modify->get_fix_by_style("mdi/aimd")[0]; @@ -98,11 +99,7 @@ MDIPlugin::MDIPlugin(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) // path for lib was specified in -mdi command-line arg when LAMMPS started // this calls back to plugin_wrapper, which must issue MDI EXIT at end - printf("PRE-LAUNCH\n"); - printf("NAME %s\n",plugin_name); - printf("ARGS %s\n",plugin_args); - - MDI_Launch_plugin(plugin_name,plugin_args,world,plugin_wrapper,(void *)this); + MDI_Launch_plugin(plugin_name,plugin_args,&world,plugin_wrapper,(void *)this); delete [] plugin_args; } @@ -116,14 +113,12 @@ MDIPlugin::MDIPlugin(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) int MDIPlugin::plugin_wrapper(void *pmpicomm, MDI_Comm mdicomm, void *vptr) { - printf("INSIDE CALLBACK\n"); - MPI_Comm mpicomm = *(MPI_Comm *) pmpicomm; MDIPlugin *ptr = (MDIPlugin *) vptr; LAMMPS *lammps = ptr->lmp; char *lammps_command = ptr->lammps_command; - // set FixMDIAimd mdicomm to this mdicomm + // set FixMDIAimd mdicomm to driver's mdicomm passed to this callback FixMDIAimd *aimdptr = (FixMDIAimd *) (ptr->fixptr); aimdptr->mdicomm = mdicomm; @@ -131,8 +126,6 @@ int MDIPlugin::plugin_wrapper(void *pmpicomm, MDI_Comm mdicomm, // invoke the specified LAMMPS command // that operation will issue MDI commands to the plugin engine - printf("PRE RUN command: %s\n",lammps_command); - lammps->input->one(lammps_command); delete [] lammps_command;