new library functions
This commit is contained in:
238
src/library.cpp
238
src/library.cpp
@ -18,9 +18,11 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "library.h"
|
||||
#include "lmptype.h"
|
||||
#include "lammps.h"
|
||||
#include "universe.h"
|
||||
#include "input.h"
|
||||
#include "atom_vec.h"
|
||||
#include "atom.h"
|
||||
#include "domain.h"
|
||||
#include "update.h"
|
||||
@ -38,8 +40,12 @@
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// utility macros
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Utility macros for optional code path which captures all exceptions
|
||||
macros for optional code path which captures all exceptions
|
||||
and stores the last error message. These assume there is a variable lmp
|
||||
which is a pointer to the current LAMMPS instance.
|
||||
|
||||
@ -76,6 +82,37 @@ using namespace LAMMPS_NS;
|
||||
#define END_CAPTURE
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// helper functions, not in library API
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
concatenate one or more LAMMPS input lines starting at ptr
|
||||
removes NULL terminator when last printable char of line = '&'
|
||||
by replacing both NULL and '&' with space character
|
||||
repeat as many times as needed
|
||||
on return, ptr now points to longer line
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void concatenate_lines(char *ptr)
|
||||
{
|
||||
int nend = strlen(ptr);
|
||||
int n = nend-1;
|
||||
while (n && isspace(ptr[n])) n--;
|
||||
while (ptr[n] == '&') {
|
||||
ptr[nend] = ' ';
|
||||
ptr[n] = ' ';
|
||||
strtok(ptr,"\n");
|
||||
nend = strlen(ptr);
|
||||
n = nend-1;
|
||||
while (n && isspace(ptr[n])) n--;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// library API functions to create/destroy an instance of LAMMPS
|
||||
// and communicate commands to it
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
create an instance of LAMMPS and return pointer to it
|
||||
@ -172,12 +209,14 @@ void lammps_file(void *ptr, char *str)
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
process a single input command in str
|
||||
does not matter if str ends in newline
|
||||
return command name to caller
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
char *lammps_command(void *ptr, char *str)
|
||||
{
|
||||
LAMMPS *lmp = (LAMMPS *) ptr;
|
||||
char * result = NULL;
|
||||
char *result = NULL;
|
||||
|
||||
BEGIN_CAPTURE
|
||||
{
|
||||
@ -188,6 +227,69 @@ char *lammps_command(void *ptr, char *str)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
process multiple input commands in cmds = list of strings
|
||||
does not matter if each string ends in newline
|
||||
create long contatentated string for processing by commands_string()
|
||||
insert newlines in concatenated string as needed
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void lammps_commands_list(void *ptr, int ncmd, char **cmds)
|
||||
{
|
||||
LAMMPS *lmp = (LAMMPS *) ptr;
|
||||
|
||||
int n = ncmd+1;
|
||||
for (int i = 0; i < ncmd; i++) n += strlen(cmds[i]);
|
||||
|
||||
char *str = (char *) lmp->memory->smalloc(n,"lib/commands/list:str");
|
||||
str[0] = '\0';
|
||||
n = 0;
|
||||
|
||||
for (int i = 0; i < ncmd; i++) {
|
||||
strcpy(&str[n],cmds[i]);
|
||||
n += strlen(cmds[i]);
|
||||
if (str[n-1] != '\n') {
|
||||
str[n] = '\n';
|
||||
str[n+1] = '\0';
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
lammps_commands_string(ptr,str);
|
||||
lmp->memory->sfree(str);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
process multiple input commands in single long str, separated by newlines
|
||||
single command can span multiple lines via continuation characters
|
||||
multi-line commands enabled by triple quotes will not work
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void lammps_commands_string(void *ptr, char *str)
|
||||
{
|
||||
LAMMPS *lmp = (LAMMPS *) ptr;
|
||||
|
||||
// make copy of str so can strtok() it
|
||||
|
||||
int n = strlen(str) + 1;
|
||||
char *copy = new char[n];
|
||||
strcpy(copy,str);
|
||||
|
||||
BEGIN_CAPTURE
|
||||
{
|
||||
char *ptr = strtok(copy,"\n");
|
||||
if (ptr) concatenate_lines(ptr);
|
||||
while (ptr) {
|
||||
lmp->input->one(ptr);
|
||||
ptr = strtok(NULL,"\n");
|
||||
if (ptr) concatenate_lines(ptr);
|
||||
}
|
||||
}
|
||||
END_CAPTURE
|
||||
|
||||
delete [] copy;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
clean-up function to free memory allocated by lib and returned to caller
|
||||
------------------------------------------------------------------------- */
|
||||
@ -197,6 +299,10 @@ void lammps_free(void *ptr)
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// library API functions to extract info from LAMMPS or set info in LAMMPS
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
add LAMMPS-specific library functions
|
||||
all must receive LAMMPS pointer as argument
|
||||
@ -209,6 +315,8 @@ void lammps_free(void *ptr)
|
||||
returns a void pointer to the entity
|
||||
which the caller can cast to the proper data type
|
||||
returns a NULL if name not listed below
|
||||
this function need only be invoked once
|
||||
the returned pointer is a permanent valid reference to the quantity
|
||||
customize by adding names
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
@ -232,14 +340,16 @@ void *lammps_extract_global(void *ptr, char *name)
|
||||
if (strcmp(name,"ndihedrals") == 0) return (void *) &lmp->atom->ndihedrals;
|
||||
if (strcmp(name,"nimpropers") == 0) return (void *) &lmp->atom->nimpropers;
|
||||
if (strcmp(name,"nlocal") == 0) return (void *) &lmp->atom->nlocal;
|
||||
if (strcmp(name,"nghost") == 0) return (void *) &lmp->atom->nghost;
|
||||
if (strcmp(name,"nmax") == 0) return (void *) &lmp->atom->nmax;
|
||||
if (strcmp(name,"ntimestep") == 0) return (void *) &lmp->update->ntimestep;
|
||||
|
||||
// NOTE: we cannot give access to the thermo "time" data by reference,
|
||||
// as that is a recomputed property. Only "atime" can be provided as pointer.
|
||||
// please use lammps_get_thermo() defined below to access all supported
|
||||
// thermo keywords by value.
|
||||
// update atime can be referenced as a pointer
|
||||
// thermo "timer" data cannot be, since it is computed on request
|
||||
// lammps_get_thermo() can access all thermo keywords by value
|
||||
|
||||
if (strcmp(name,"atime") == 0) return (void *) &lmp->update->atime;
|
||||
if (strcmp(name,"atimestep") == 0) return (void *) &lmp->update->atimestep;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -250,6 +360,8 @@ void *lammps_extract_global(void *ptr, char *name)
|
||||
returns a void pointer to the entity
|
||||
which the caller can cast to the proper data type
|
||||
returns a NULL if Atom::extract() does not recognize the name
|
||||
the returned pointer is not a permanent valid reference to the
|
||||
per-atom quantity, since LAMMPS may reallocate per-atom data
|
||||
customize by adding names to Atom::extract()
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
@ -261,6 +373,7 @@ void *lammps_extract_atom(void *ptr, char *name)
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
extract a pointer to an internal LAMMPS compute-based entity
|
||||
the compute is invoked if its value(s) is not current
|
||||
id = compute ID
|
||||
style = 0 for global data, 1 for per-atom data, 2 for local data
|
||||
type = 0 for scalar, 1 for vector, 2 for array
|
||||
@ -275,6 +388,8 @@ void *lammps_extract_atom(void *ptr, char *name)
|
||||
returns a void pointer to the compute's internal data structure
|
||||
for the entity which the caller can cast to the proper data type
|
||||
returns a NULL if id is not recognized or style/type not supported
|
||||
the returned pointer is not a permanent valid reference to the
|
||||
compute data, this function should be re-invoked
|
||||
IMPORTANT: if the compute is not current it will be invoked
|
||||
LAMMPS cannot easily check here if it is valid to invoke the compute,
|
||||
so caller must insure that it is OK
|
||||
@ -492,11 +607,11 @@ int lammps_set_variable(void *ptr, char *name, char *str)
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
return the current value of a thermo keyword as double.
|
||||
return the current value of a thermo keyword as a double
|
||||
unlike lammps_extract_global() this does not give access to the
|
||||
storage of the data in question, and thus needs to be called
|
||||
again to retrieve an updated value. The upshot is that it allows
|
||||
accessing information that is only computed on-the-fly.
|
||||
storage of the data in question
|
||||
instead it triggers the Thermo class to compute the current value
|
||||
and returns it
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
double lammps_get_thermo(void *ptr, char *name)
|
||||
@ -529,12 +644,13 @@ int lammps_get_natoms(void *ptr)
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
gather the named atom-based entity across all processors
|
||||
atom IDs must be consecutive from 1 to N
|
||||
name = desired quantity, e.g. x or charge
|
||||
type = 0 for integer values, 1 for double values
|
||||
count = # of per-atom values, e.g. 1 for type or charge, 3 for x or f
|
||||
return atom-based values in data, ordered by count, then by atom ID
|
||||
e.g. x[0][0],x[0][1],x[0][2],x[1][0],x[1][1],x[1][2],x[2][0],...
|
||||
data must be pre-allocated by caller to correct length
|
||||
data must be pre-allocated by caller to correct length
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void lammps_gather_atoms(void *ptr, char *name,
|
||||
@ -547,7 +663,8 @@ void lammps_gather_atoms(void *ptr, char *name,
|
||||
// error if tags are not defined or not consecutive
|
||||
|
||||
int flag = 0;
|
||||
if (lmp->atom->tag_enable == 0 || lmp->atom->tag_consecutive() == 0) flag = 1;
|
||||
if (lmp->atom->tag_enable == 0 || lmp->atom->tag_consecutive() == 0)
|
||||
flag = 1;
|
||||
if (lmp->atom->natoms > MAXSMALLINT) flag = 1;
|
||||
if (flag) {
|
||||
if (lmp->comm->me == 0)
|
||||
@ -586,7 +703,7 @@ void lammps_gather_atoms(void *ptr, char *name,
|
||||
for (j = 0; j < count; j++)
|
||||
copy[offset++] = array[i][0];
|
||||
}
|
||||
|
||||
|
||||
MPI_Allreduce(copy,data,count*natoms,MPI_INT,MPI_SUM,lmp->world);
|
||||
lmp->memory->destroy(copy);
|
||||
|
||||
@ -623,6 +740,7 @@ void lammps_gather_atoms(void *ptr, char *name,
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
scatter the named atom-based entity across all processors
|
||||
atom IDs must be consecutive from 1 to N
|
||||
name = desired quantity, e.g. x or charge
|
||||
type = 0 for integer values, 1 for double values
|
||||
count = # of per-atom values, e.g. 1 for type or charge, 3 for x or f
|
||||
@ -640,7 +758,8 @@ void lammps_scatter_atoms(void *ptr, char *name,
|
||||
// error if tags are not defined or not consecutive or no atom map
|
||||
|
||||
int flag = 0;
|
||||
if (lmp->atom->tag_enable == 0 || lmp->atom->tag_consecutive() == 0) flag = 1;
|
||||
if (lmp->atom->tag_enable == 0 || lmp->atom->tag_consecutive() == 0)
|
||||
flag = 1;
|
||||
if (lmp->atom->natoms > MAXSMALLINT) flag = 1;
|
||||
if (lmp->atom->map_style == 0) flag = 1;
|
||||
if (flag) {
|
||||
@ -702,9 +821,91 @@ void lammps_scatter_atoms(void *ptr, char *name,
|
||||
END_CAPTURE
|
||||
}
|
||||
|
||||
#ifdef LAMMPS_EXCEPTIONS
|
||||
/* ----------------------------------------------------------------------
|
||||
Check if a new error message
|
||||
create N atoms and assign them to procs based on coords
|
||||
id = atom IDs (optional, NULL if just use 1 to N)
|
||||
type = N-length vector of atom types (required)
|
||||
x = 3N-length vector of atom coords (required)
|
||||
v = 3N-length vector of atom velocities (optional, NULL if just 0.0)
|
||||
x,v = ordered by xyz, then by atom
|
||||
e.g. x[0][0],x[0][1],x[0][2],x[1][0],x[1][1],x[1][2],x[2][0],...
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
void lammps_create_atoms(void *ptr, int n, tagint *id, int *type,
|
||||
double *x, double *v)
|
||||
{
|
||||
LAMMPS *lmp = (LAMMPS *) ptr;
|
||||
|
||||
BEGIN_CAPTURE
|
||||
{
|
||||
// error if box does not exist or tags not defined
|
||||
|
||||
int flag = 0;
|
||||
if (lmp->domain->box_exist == 0) flag = 1;
|
||||
if (lmp->atom->tag_enable == 0) flag = 1;
|
||||
if (flag) {
|
||||
if (lmp->comm->me == 0)
|
||||
lmp->error->warning(FLERR,"Library error in lammps_create_atoms");
|
||||
return;
|
||||
}
|
||||
|
||||
// loop over N atoms of entire system
|
||||
// if this proc owns it based on coords, invoke create_atom()
|
||||
// optionally set atom tags and velocities
|
||||
|
||||
Atom *atom = lmp->atom;
|
||||
Domain *domain = lmp->domain;
|
||||
int nlocal = atom->nlocal;
|
||||
|
||||
int nprev = nlocal;
|
||||
double xdata[3];
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
xdata[0] = x[3*i];
|
||||
xdata[1] = x[3*i+1];
|
||||
xdata[2] = x[3*i+2];
|
||||
if (!domain->ownatom(xdata)) continue;
|
||||
|
||||
atom->avec->create_atom(type[i],xdata);
|
||||
if (id) atom->tag[nlocal] = id[i];
|
||||
else atom->tag[nlocal] = i+1;
|
||||
if (v) {
|
||||
atom->v[nlocal][0] = v[3*i];
|
||||
atom->v[nlocal][1] = v[3*i+1];
|
||||
atom->v[nlocal][2] = v[3*i+2];
|
||||
}
|
||||
nlocal++;
|
||||
}
|
||||
|
||||
// need to reset atom->natoms inside LAMMPS
|
||||
|
||||
bigint ncurrent = nlocal;
|
||||
MPI_Allreduce(&ncurrent,&lmp->atom->natoms,1,MPI_LMP_BIGINT,
|
||||
MPI_SUM,lmp->world);
|
||||
|
||||
// init per-atom fix/compute/variable values for created atoms
|
||||
|
||||
atom->data_fix_compute_variable(nprev,nlocal);
|
||||
|
||||
// if global map exists, reset it
|
||||
// invoke map_init() b/c atom count has grown
|
||||
|
||||
if (lmp->atom->map_style) {
|
||||
lmp->atom->map_init();
|
||||
lmp->atom->map_set();
|
||||
}
|
||||
}
|
||||
END_CAPTURE
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// library API functions for error handling
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
#ifdef LAMMPS_EXCEPTIONS
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
check if a new error message
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
int lammps_has_error(void *ptr) {
|
||||
@ -714,8 +915,8 @@ int lammps_has_error(void *ptr) {
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
Copy the last error message of LAMMPS into a character buffer
|
||||
The return value encodes which type of error it is.
|
||||
copy the last error message of LAMMPS into a character buffer
|
||||
return value encodes which type of error:
|
||||
1 = normal error (recoverable)
|
||||
2 = abort error (non-recoverable)
|
||||
------------------------------------------------------------------------- */
|
||||
@ -732,4 +933,5 @@ int lammps_get_last_error_message(void *ptr, char * buffer, int buffer_size) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user