Merge pull request #2998 from akohlmey/collected_small_changes

Collected small changes and bugfixes
This commit is contained in:
Axel Kohlmeyer
2021-10-19 10:33:51 -04:00
committed by GitHub
25 changed files with 519 additions and 446 deletions

View File

@ -7,8 +7,8 @@ else()
endif() endif()
include(ExternalProject) include(ExternalProject)
set(GTEST_URL "https://github.com/google/googletest/archive/release-1.10.0.tar.gz" CACHE STRING "URL for GTest tarball") set(GTEST_URL "https://github.com/google/googletest/archive/release-1.11.0.tar.gz" CACHE STRING "URL of googletest source")
set(GTEST_MD5 "ecd1fa65e7de707cd5c00bdac56022cd" CACHE STRING "MD5 checksum of GTest tarball") set(GTEST_MD5 "e8a8df240b6938bb6384155d4c37d937" CACHE STRING "MD5 sum for googletest source")
mark_as_advanced(GTEST_URL) mark_as_advanced(GTEST_URL)
mark_as_advanced(GTEST_MD5) mark_as_advanced(GTEST_MD5)
ExternalProject_Add(googletest ExternalProject_Add(googletest

View File

@ -29,7 +29,9 @@ of code in the header before include guards:
.. code-block:: c .. code-block:: c
#ifdef FIX_CLASS #ifdef FIX_CLASS
FixStyle(print/vel,FixPrintVel) // clang-format off
FixStyle(print/vel,FixPrintVel);
// clang-format on
#else #else
/* the definition of the FixPrintVel class comes here */ /* the definition of the FixPrintVel class comes here */
... ...

View File

@ -80,7 +80,7 @@ Lowercase directories
+-------------+------------------------------------------------------------------+ +-------------+------------------------------------------------------------------+
| friction | frictional contact of spherical asperities between 2d surfaces | | friction | frictional contact of spherical asperities between 2d surfaces |
+-------------+------------------------------------------------------------------+ +-------------+------------------------------------------------------------------+
| gcmc | Grand Canonical Monte Carlo (GCMC) via the fix gcmc command | | mc | Monte Carlo features via fix gcmc, widom and other commands |
+-------------+------------------------------------------------------------------+ +-------------+------------------------------------------------------------------+
| granregion | use of fix wall/region/gran as boundary on granular particles | | granregion | use of fix wall/region/gran as boundary on granular particles |
+-------------+------------------------------------------------------------------+ +-------------+------------------------------------------------------------------+
@ -205,7 +205,7 @@ Uppercase directories
+------------+--------------------------------------------------------------------------------------------------+ +------------+--------------------------------------------------------------------------------------------------+
| KAPPA | compute thermal conductivity via several methods | | KAPPA | compute thermal conductivity via several methods |
+------------+--------------------------------------------------------------------------------------------------+ +------------+--------------------------------------------------------------------------------------------------+
| MC | using LAMMPS in a Monte Carlo mode to relax the energy of a system | | MC-LOOP | using LAMMPS in a Monte Carlo mode to relax the energy of a system in a input script loop |
+------------+--------------------------------------------------------------------------------------------------+ +------------+--------------------------------------------------------------------------------------------------+
| PACKAGES | examples for specific packages and contributed commands | | PACKAGES | examples for specific packages and contributed commands |
+------------+--------------------------------------------------------------------------------------------------+ +------------+--------------------------------------------------------------------------------------------------+

View File

@ -167,7 +167,7 @@ The KAPPA directory has example scripts for computing the thermal
conductivity (kappa) of a LJ liquid using 5 different methods. See conductivity (kappa) of a LJ liquid using 5 different methods. See
the KAPPA/README file for more info. the KAPPA/README file for more info.
The MC directory has an example script for using LAMMPS as an The MC-LOOP directory has an example script for using LAMMPS as an
energy-evaluation engine in a iterative Monte Carlo energy-relaxation energy-evaluation engine in a iterative Monte Carlo energy-relaxation
loop. loop.

View File

@ -88,7 +88,7 @@ struct OCLProperties {
cl_uint clock; cl_uint clock;
size_t work_group_size; size_t work_group_size;
size_t work_item_size[3]; size_t work_item_size[3];
bool double_precision; bool has_double_precision;
int preferred_vector_width32, preferred_vector_width64; int preferred_vector_width32, preferred_vector_width64;
int alignment; int alignment;
size_t timer_resolution; size_t timer_resolution;
@ -226,7 +226,7 @@ class UCL_Device {
inline bool double_precision() { return double_precision(_device); } inline bool double_precision() { return double_precision(_device); }
/// Returns true if double precision is support for the device /// Returns true if double precision is support for the device
inline bool double_precision(const int i) inline bool double_precision(const int i)
{return _properties[i].double_precision;} {return _properties[i].has_double_precision;}
/// Get the number of compute units on the current device /// Get the number of compute units on the current device
inline unsigned cus() { return cus(_device); } inline unsigned cus() { return cus(_device); }
@ -569,9 +569,9 @@ void UCL_Device::add_properties(cl_device_id device_list) {
CL_SAFE_CALL(clGetDeviceInfo(device_list,CL_DEVICE_DOUBLE_FP_CONFIG, CL_SAFE_CALL(clGetDeviceInfo(device_list,CL_DEVICE_DOUBLE_FP_CONFIG,
sizeof(double_avail),&double_avail,nullptr)); sizeof(double_avail),&double_avail,nullptr));
if ((double_avail & double_mask) == double_mask) if ((double_avail & double_mask) == double_mask)
op.double_precision=true; op.has_double_precision=true;
else else
op.double_precision=false; op.has_double_precision=false;
CL_SAFE_CALL(clGetDeviceInfo(device_list, CL_SAFE_CALL(clGetDeviceInfo(device_list,
CL_DEVICE_PROFILING_TIMER_RESOLUTION, CL_DEVICE_PROFILING_TIMER_RESOLUTION,

View File

@ -1047,7 +1047,7 @@ bool lmp_has_compatible_gpu_device()
UCL_Device gpu; UCL_Device gpu;
bool compatible_gpu = gpu.num_platforms() > 0; bool compatible_gpu = gpu.num_platforms() > 0;
#if defined(_SINGLE_DOUBLE) || defined(_DOUBLE_DOUBLE) #if defined(_SINGLE_DOUBLE) || defined(_DOUBLE_DOUBLE)
if (!gpu.double_precision(0)) if (compatible_gpu && !gpu.double_precision(0))
compatible_gpu = false; compatible_gpu = false;
#endif #endif
return compatible_gpu; return compatible_gpu;

View File

@ -84,7 +84,7 @@ FixRX::FixRX(LAMMPS *lmp, int narg, char **arg) :
id_fix_species = nullptr; id_fix_species = nullptr;
id_fix_species_old = nullptr; id_fix_species_old = nullptr;
const int Verbosity = 1; constexpr int Verbosity = 1;
// Keep track of the argument list. // Keep track of the argument list.
int iarg = 3; int iarg = 3;
@ -101,13 +101,10 @@ FixRX::FixRX(LAMMPS *lmp, int narg, char **arg) :
if (strcmp(word,"none") == 0) { if (strcmp(word,"none") == 0) {
wtFlag = 0; wtFlag = 0;
localTempFlag = NONE; localTempFlag = NONE;
} } else if (strcmp(word,"lucy") == 0) {
else if (strcmp(word,"lucy") == 0) {
wtFlag = LUCY; wtFlag = LUCY;
localTempFlag = HARMONIC; localTempFlag = HARMONIC;
} } else error->all(FLERR,"Illegal fix rx local temperature weighting technique");
else
error->all(FLERR,"Illegal fix rx local temperature weighting technique");
} }
// Select either sparse and dense matrix // Select either sparse and dense matrix
@ -120,21 +117,11 @@ FixRX::FixRX(LAMMPS *lmp, int narg, char **arg) :
useSparseKinetics = true; useSparseKinetics = true;
else if (strcmp(word,"dense") == 0) else if (strcmp(word,"dense") == 0)
useSparseKinetics = false; useSparseKinetics = false;
else { else error->all(FLERR, "Illegal command " + std::string(word)
std::string errmsg = "Illegal command " + std::string(word) + " expected \"sparse\" or \"dense\"\n");
+ " expected \"sparse\" or \"dense\"\n";
error->all(FLERR, errmsg);
}
if (comm->me == 0 && Verbosity > 1) { if (comm->me == 0 && Verbosity > 1)
std::string msg = "FixRX: matrix format is "; error->message(FLERR, fmt::format("FixRX: matrix format is {}",word));
if (useSparseKinetics)
msg += std::string("sparse");
else
msg += std::string("dense");
error->message(FLERR, msg);
}
} }
// Determine the ODE solver/stepper strategy in arg[6]. // Determine the ODE solver/stepper strategy in arg[6].
@ -169,40 +156,32 @@ FixRX::FixRX(LAMMPS *lmp, int narg, char **arg) :
} }
if (odeIntegrationFlag == ODE_LAMMPS_RK4 && narg==8) { if (odeIntegrationFlag == ODE_LAMMPS_RK4 && narg==8) {
char *word = arg[iarg++]; minSteps = utils::inumeric(FLERR,arg[iarg++],false,lmp);
minSteps = atoi( word );
if (comm->me == 0 && Verbosity > 1) { if (comm->me == 0 && Verbosity > 1)
char msg[128]; error->message(FLERR,fmt::format("FixRX: RK4 numSteps= {}", minSteps));
sprintf(msg, "FixRX: RK4 numSteps= %d", minSteps); } else if (odeIntegrationFlag == ODE_LAMMPS_RK4 && narg>8) {
error->message(FLERR, msg);
}
}
else if (odeIntegrationFlag == ODE_LAMMPS_RK4 && narg>8) {
error->all(FLERR,"Illegal fix rx command. Too many arguments for RK4 solver."); error->all(FLERR,"Illegal fix rx command. Too many arguments for RK4 solver.");
} } else if (odeIntegrationFlag == ODE_LAMMPS_RKF45) {
else if (odeIntegrationFlag == ODE_LAMMPS_RKF45) {
// Must have four options. // Must have four options.
if (narg < 11) if (narg < 11)
error->all(FLERR,"Illegal fix rx command. Too few arguments for RKF45 solver."); error->all(FLERR,"Illegal fix rx command. Too few arguments for RKF45 solver.");
minSteps = atoi( arg[iarg++] ); minSteps = utils::inumeric(FLERR,arg[iarg++],false,lmp);
maxIters = atoi( arg[iarg++] ); maxIters = utils::inumeric(FLERR,arg[iarg++],false,lmp);
relTol = strtod( arg[iarg++], nullptr); relTol = utils::numeric(FLERR,arg[iarg++],false,lmp);
absTol = strtod( arg[iarg++], nullptr); absTol = utils::numeric(FLERR,arg[iarg++],false,lmp);
if (iarg < narg) if (iarg < narg)
diagnosticFrequency = atoi( arg[iarg++] ); diagnosticFrequency = utils::inumeric(FLERR,arg[iarg++],false,lmp);
// maxIters must be at least minSteps. // maxIters must be at least minSteps.
maxIters = std::max( minSteps, maxIters ); maxIters = std::max( minSteps, maxIters );
if (comm->me == 0 && Verbosity > 1) { if (comm->me == 0 && Verbosity > 1)
//printf("FixRX: RKF45 minSteps= %d maxIters= %d absTol= %e relTol= %e\n", minSteps, maxIters, absTol, relTol); error->message(FLERR, fmt::format("FixRX: RKF45 minSteps= {} maxIters= {} "
char msg[128]; "relTol= {:.1e} absTol= {:.1e} diagnosticFrequency= {}",
sprintf(msg, "FixRX: RKF45 minSteps= %d maxIters= %d relTol= %.1e absTol= %.1e diagnosticFrequency= %d", minSteps, maxIters, relTol, absTol, diagnosticFrequency); minSteps, maxIters, relTol, absTol, diagnosticFrequency));
error->message(FLERR, msg);
}
} }
// Initialize/Create the sparse matrix database. // Initialize/Create the sparse matrix database.
@ -265,11 +244,8 @@ void FixRX::post_constructor()
fp = nullptr; fp = nullptr;
if (comm->me == 0) { if (comm->me == 0) {
fp = utils::open_potential(kineticsFile,lmp,nullptr); fp = utils::open_potential(kineticsFile,lmp,nullptr);
if (fp == nullptr) { if (fp == nullptr)
char str[128]; error->one(FLERR,"Cannot open rx file {}: {}",kineticsFile,utils::getsyserror());
snprintf(str,128,"Cannot open rx file %s",kineticsFile);
error->one(FLERR,str);
}
} }
// Assign species names to tmpspecies array and determine the number of unique species // Assign species names to tmpspecies array and determine the number of unique species
@ -358,7 +334,7 @@ void FixRX::post_constructor()
read_file( kineticsFile ); read_file( kineticsFile );
if (useSparseKinetics) if (useSparseKinetics)
this->initSparse(); initSparse();
// set comm size needed by this Pair // set comm size needed by this Pair
comm_forward = nspecies*2; comm_forward = nspecies*2;
@ -369,7 +345,7 @@ void FixRX::post_constructor()
void FixRX::initSparse() void FixRX::initSparse()
{ {
const int Verbosity = 1; constexpr int Verbosity = 1;
if (comm->me == 0 && Verbosity > 1) { if (comm->me == 0 && Verbosity > 1) {
for (int k = 0; k < nspecies; ++k) for (int k = 0; k < nspecies; ++k)
@ -449,7 +425,8 @@ void FixRX::initSparse()
} }
} }
if (comm->me == 0 && Verbosity > 1) if (comm->me == 0 && Verbosity > 1)
printf("rx%3d: %d %d %d ... %s %s %s\n", i, nreac_i, nprod_i, allAreIntegral, rstr.c_str(), /*reversible[i]*/ (false) ? "<=>" : "=", pstr.c_str()); utils::logmesg(lmp,"rx{:3d}: {} {} {} ... {} = {}\n",
i, nreac_i, nprod_i, allAreIntegral, rstr, pstr);
mxreac = std::max( mxreac, nreac_i ); mxreac = std::max( mxreac, nreac_i );
mxprod = std::max( mxprod, nprod_i ); mxprod = std::max( mxprod, nprod_i );
@ -458,8 +435,12 @@ void FixRX::initSparse()
} }
if (comm->me == 0 && Verbosity > 1) { if (comm->me == 0 && Verbosity > 1) {
char msg[256]; auto msg = fmt::format("FixRX: Sparsity of Stoichiometric Matrix= {:.1f}% non-zeros= {} "
sprintf(msg, "FixRX: Sparsity of Stoichiometric Matrix= %.1f%% non-zeros= %d nspecies= %d nreactions= %d maxReactants= %d maxProducts= %d maxSpecies= %d integralReactions= %d", 100*(double(nzeros) / (nspecies * nreactions)), nzeros, nspecies, nreactions, mxreac, mxprod, (mxreac + mxprod), SparseKinetics_enableIntegralReactions); "nspecies= {} nreactions= {} maxReactants= {} maxProducts= {} "
"maxSpecies= {} integralReactions= {}",
100*(double(nzeros) / (nspecies * nreactions)), nzeros, nspecies,
nreactions, mxreac, mxprod, (mxreac + mxprod),
SparseKinetics_enableIntegralReactions);
error->message(FLERR, msg); error->message(FLERR, msg);
} }
@ -774,18 +755,9 @@ void FixRX::pre_force(int /*vflag*/)
double time_ODE = getElapsedTime(timer_localTemperature, timer_ODE); double time_ODE = getElapsedTime(timer_localTemperature, timer_ODE);
//printf("me= %d total= %g temp= %g ode= %g comm= %g nlocal= %d nfc= %d %d\n", comm->me,
// getElapsedTime(timer_start, timer_stop),
// getElapsedTime(timer_start, timer_localTemperature),
// getElapsedTime(timer_localTemperature, timer_ODE),
// getElapsedTime(timer_ODE, timer_stop), nlocal, nFuncs, nSteps);
// Warn the user if a failure was detected in the ODE solver. // Warn the user if a failure was detected in the ODE solver.
if (nFails > 0) { if (nFails > 0)
char sbuf[128]; error->warning(FLERR, fmt::format("FixRX::pre_force ODE solver failed for {} atoms.", nFails));
sprintf(sbuf,"in FixRX::pre_force, ODE solver failed for %d atoms.", nFails);
error->warning(FLERR, sbuf);
}
// Compute and report ODE diagnostics, if requested. // Compute and report ODE diagnostics, if requested.
if (odeIntegrationFlag == ODE_LAMMPS_RKF45 && diagnosticFrequency != 0) { if (odeIntegrationFlag == ODE_LAMMPS_RKF45 && diagnosticFrequency != 0) {
@ -1422,17 +1394,9 @@ void FixRX::odeDiagnostics()
double time_local = getElapsedTime( timer_start, timer_stop ); double time_local = getElapsedTime( timer_start, timer_stop );
if (comm->me == 0) { if (comm->me == 0) {
char smesg[128]; utils::logmesg(lmp,"FixRX::ODE Diagnostics: # of iters |# of rhs evals| run-time (sec) | # atoms\n");
utils::logmesg(lmp," AVG per ODE : {:>12.5g} | {:>12.5g} | {:>12.5g}\n",
#define print_mesg(smesg) {\ avg_per_atom[0], avg_per_atom[1], avg_per_atom[2]);
if (screen) fprintf(screen,"%s\n", smesg); \
if (logfile) fprintf(logfile,"%s\n", smesg); }
sprintf(smesg, "FixRX::ODE Diagnostics: # of iters |# of rhs evals| run-time (sec) | # atoms");
print_mesg(smesg);
sprintf(smesg, " AVG per ODE : %-12.5g | %-12.5g | %-12.5g", avg_per_atom[0], avg_per_atom[1], avg_per_atom[2]);
print_mesg(smesg);
// only valid for single time-step! // only valid for single time-step!
if (diagnosticFrequency == 1) { if (diagnosticFrequency == 1) {
@ -1440,41 +1404,32 @@ void FixRX::odeDiagnostics()
for (int i = 0; i < numCounters; ++i) for (int i = 0; i < numCounters; ++i)
rms_per_ODE[i] = sqrt( sum_sq[i+numCounters] / nODEs ); rms_per_ODE[i] = sqrt( sum_sq[i+numCounters] / nODEs );
sprintf(smesg, " RMS per ODE : %-12.5g | %-12.5g ", rms_per_ODE[0], rms_per_ODE[1]); utils::logmesg(lmp, " RMS per ODE : {:>12.5g} | {:>12.5g}\n",
print_mesg(smesg); rms_per_ODE[0], rms_per_ODE[1]);
utils::logmesg(lmp, " MAX per ODE : {:>12.5g} | {:>12.5g}\n",
sprintf(smesg, " MAX per ODE : %-12.5g | %-12.5g ", max_per_ODE[0], max_per_ODE[1]); max_per_ODE[0], max_per_ODE[1]);
print_mesg(smesg); utils::logmesg(lmp, " MIN per ODE : {:>12.5g} | {:>12.5g}\n",
min_per_ODE[0], min_per_ODE[1]);
sprintf(smesg, " MIN per ODE : %-12.5g | %-12.5g ", min_per_ODE[0], min_per_ODE[1]);
print_mesg(smesg);
} }
sprintf(smesg, " AVG per Proc : %-12.5g | %-12.5g | %-12.5g | %-12.5g", avg_per_proc[StepSum], avg_per_proc[FuncSum], avg_per_proc[TimeSum], avg_per_proc[AtomSum]); utils::logmesg(lmp," AVG per Proc : {:>12.5g} | {:>12.5g} | {:>12.5g} | {:>12.5g}\n",
print_mesg(smesg); avg_per_proc[StepSum], avg_per_proc[FuncSum], avg_per_proc[TimeSum], avg_per_proc[AtomSum]);
if (comm->nprocs > 1) { if (comm->nprocs > 1) {
double rms_per_proc[numCounters]; double rms_per_proc[numCounters];
for (int i = 0; i < numCounters; ++i) for (int i = 0; i < numCounters; ++i)
rms_per_proc[i] = sqrt( sum_sq[i] / comm->nprocs ); rms_per_proc[i] = sqrt( sum_sq[i] / comm->nprocs );
sprintf(smesg, " RMS per Proc : %-12.5g | %-12.5g | %-12.5g | %-12.5g", rms_per_proc[0], rms_per_proc[1], rms_per_proc[2], rms_per_proc[AtomSum]); utils::logmesg(lmp," RMS per Proc : {:>12.5g} | {:>12.5g} | {:>12.5g} | {:>12.5g}\n",
print_mesg(smesg); rms_per_proc[0], rms_per_proc[1], rms_per_proc[2], rms_per_proc[AtomSum]);
utils::logmesg(lmp," MAX per Proc : {:>12.5g} | {:>12.5g} | {:>12.5g} | {:>12.5g}\n",
sprintf(smesg, " MAX per Proc : %-12.5g | %-12.5g | %-12.5g | %-12.5g", max_per_proc[0], max_per_proc[1], max_per_proc[2], max_per_proc[AtomSum]); max_per_proc[0], max_per_proc[1], max_per_proc[2], max_per_proc[AtomSum]);
print_mesg(smesg); utils::logmesg(lmp," MIN per Proc : {:>12.5g} | {:>12.5g} | {:>12.5g} | {:>12.5g}\n",
min_per_proc[0], min_per_proc[1], min_per_proc[2], min_per_proc[AtomSum]);
sprintf(smesg, " MIN per Proc : %-12.5g | %-12.5g | %-12.5g | %-12.5g", min_per_proc[0], min_per_proc[1], min_per_proc[2], min_per_proc[AtomSum]);
print_mesg(smesg);
} }
sprintf(smesg, " AVG'd over %d time-steps", nTimes); utils::logmesg(lmp, " AVG'd over {} time-steps\n", nTimes);
print_mesg(smesg); utils::logmesg(lmp, " AVG'ing took {} sec", time_local);
sprintf(smesg, " AVG'ing took %g sec", time_local);
print_mesg(smesg);
#undef print_mesg
} }
// Reset the counters. // Reset the counters.

View File

@ -549,12 +549,9 @@ void FixShardlow::initial_integrate(int /*vflag*/)
error->all(FLERR,"Fix shardlow does not yet support triclinic geometries"); error->all(FLERR,"Fix shardlow does not yet support triclinic geometries");
if (rcut >= bbx || rcut >= bby || rcut>= bbz ) if (rcut >= bbx || rcut >= bby || rcut>= bbz )
{ error->one(FLERR,"Shardlow algorithm requires sub-domain length > 2*(rcut+skin). "
char fmt[] = {"Shardlow algorithm requires sub-domain length > 2*(rcut+skin). Either reduce the number of processors requested, or change the cutoff/skin: rcut= %e bbx= %e bby= %e bbz= %e\n"}; "Either reduce the number of processors requested, or change the cutoff/skin: "
char *msg = (char *) malloc(sizeof(fmt) + 4*15); "rcut= {} bbx= {} bby= {} bbz= {}\n", rcut, bbx, bby, bbz);
sprintf(msg, fmt, rcut, bbx, bby, bbz);
error->one(FLERR, msg);
}
NPairHalfBinNewtonSSA *np_ssa = dynamic_cast<NPairHalfBinNewtonSSA*>(list->np); NPairHalfBinNewtonSSA *np_ssa = dynamic_cast<NPairHalfBinNewtonSSA*>(list->np);
if (!np_ssa) error->one(FLERR, "NPair wasn't a NPairHalfBinNewtonSSA object"); if (!np_ssa) error->one(FLERR, "NPair wasn't a NPairHalfBinNewtonSSA object");

View File

@ -268,16 +268,9 @@ FixPour::FixPour(LAMMPS *lmp, int narg, char **arg) :
// print stats // print stats
if (me == 0) { if (me == 0)
if (screen) utils::logmesg(lmp, "Particle insertion: {} every {} steps, {} by step {}\n",
fprintf(screen, nper,nfreq,ninsert,nfinal);
"Particle insertion: %d every %d steps, %d by step %d\n",
nper,nfreq,ninsert,nfinal);
if (logfile)
fprintf(logfile,
"Particle insertion: %d every %d steps, %d by step %d\n",
nper,nfreq,ninsert,nfinal);
}
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */

View File

@ -640,9 +640,10 @@ void FixACKS2ReaxFF::sparse_matvec_acks2(sparse_matrix *H, sparse_matrix *X, dou
for (ii = nn; ii < NN; ++ii) { for (ii = nn; ii < NN; ++ii) {
i = ilist[ii]; i = ilist[ii];
if (atom->mask[i] & groupbit) if (atom->mask[i] & groupbit) {
b[i] = 0; b[i] = 0;
b[NN + i] = 0; b[NN + i] = 0;
}
} }
// last two rows // last two rows
b[2*NN] = 0; b[2*NN] = 0;

View File

@ -676,16 +676,11 @@ void FixPIMD::comm_exec(double **ptr)
int index = atom->map(tag_send[i]); int index = atom->map(tag_send[i]);
if (index < 0) { if (index < 0) {
char error_line[256]; auto mesg = fmt::format("Atom {} is missing at world [{}] rank [{}] "
"required by rank [{}] ({}, {}, {}).\n",
sprintf(error_line, tag_send[i], universe->iworld, comm->me,
"Atom " TAGINT_FORMAT " is missing at world [%d] " plan_recv[iplan], atom->tag[0], atom->tag[1], atom->tag[2]);
"rank [%d] required by rank [%d] (" TAGINT_FORMAT ", " TAGINT_FORMAT error->universe_one(FLERR, mesg);
", " TAGINT_FORMAT ").\n",
tag_send[i], universe->iworld, comm->me, plan_recv[iplan], atom->tag[0],
atom->tag[1], atom->tag[2]);
error->universe_one(FLERR, error_line);
} }
memcpy(wrap_ptr, ptr[index], ncpy); memcpy(wrap_ptr, ptr[index], ncpy);

View File

@ -840,11 +840,9 @@ void TAD::initialize_event_list() {
void TAD::delete_event_list() { void TAD::delete_event_list() {
for (int i = 0; i < n_event_list; i++) { for (int i = 0; i < n_event_list; i++)
char str[128]; modify->delete_fix(fmt::format("tad_event_{}",i));
sprintf(str,"tad_event_%d",i);
modify->delete_fix(str);
}
memory->sfree(fix_event_list); memory->sfree(fix_event_list);
fix_event_list = nullptr; fix_event_list = nullptr;
n_event_list = 0; n_event_list = 0;

View File

@ -31,6 +31,7 @@
#include "domain.h" #include "domain.h"
#include "error.h" #include "error.h"
#include "fix.h" #include "fix.h"
#include "fix_store.h"
#include "force.h" #include "force.h"
#include "group.h" #include "group.h"
#include "input.h" #include "input.h"
@ -87,9 +88,9 @@ enum{X,Y,Z, // required for vtk, must come first
Q,MUX,MUY,MUZ,MU,RADIUS,DIAMETER, Q,MUX,MUY,MUZ,MU,RADIUS,DIAMETER,
OMEGAX,OMEGAY,OMEGAZ,ANGMOMX,ANGMOMY,ANGMOMZ, OMEGAX,OMEGAY,OMEGAZ,ANGMOMX,ANGMOMY,ANGMOMZ,
TQX,TQY,TQZ, TQX,TQY,TQZ,
VARIABLE,COMPUTE,FIX,INAME,DNAME, COMPUTE,FIX,VARIABLE,IVEC,DVEC,IARRAY,DARRAY,
ATTRIBUTES}; // must come last ATTRIBUTES}; // must come last
enum{LT,LE,GT,GE,EQ,NEQ}; enum{LT,LE,GT,GE,EQ,NEQ,XOR};
enum{VTK,VTP,VTU,PVTP,PVTU}; // file formats enum{VTK,VTP,VTU,PVTP,PVTU}; // file formats
#define ONEFIELD 32 #define ONEFIELD 32
@ -119,11 +120,10 @@ DumpVTK::DumpVTK(LAMMPS *lmp, int narg, char **arg) :
// ioptional = start of additional optional args // ioptional = start of additional optional args
// only dump image and dump movie styles process optional args // only dump image and dump movie styles process optional args
ioptional = parse_fields(narg,arg); ioptional = parse_fields(nargnew,earg);
if (ioptional < narg && if (ioptional < nargnew)
strcmp(style,"image") != 0 && strcmp(style,"movie") != 0) error->all(FLERR,"Invalid attribute {} in dump vtk command", earg[ioptional]);
error->all(FLERR,"Invalid attribute in dump vtk command");
size_one = pack_choice.size(); size_one = pack_choice.size();
current_pack_choice_key = -1; current_pack_choice_key = -1;
@ -210,38 +210,40 @@ void DumpVTK::init_style()
else else
write_choice = &DumpVTK::write_vtk; write_choice = &DumpVTK::write_vtk;
// find current ptr for each compute,fix,variable // find current ptr for each compute,fix,variable and custom atom property
// check that fix frequency is acceptable // check that fix frequency is acceptable
int icompute;
for (int i = 0; i < ncompute; i++) { for (int i = 0; i < ncompute; i++) {
icompute = modify->find_compute(id_compute[i]); int icompute = modify->find_compute(id_compute[i]);
if (icompute < 0) error->all(FLERR,"Could not find dump vtk compute ID"); if (icompute < 0) error->all(FLERR,"Could not find dump vtk compute ID");
compute[i] = modify->compute[icompute]; compute[i] = modify->compute[icompute];
} }
int ifix;
for (int i = 0; i < nfix; i++) { for (int i = 0; i < nfix; i++) {
ifix = modify->find_fix(id_fix[i]); int ifix = modify->find_fix(id_fix[i]);
if (ifix < 0) error->all(FLERR,"Could not find dump vtk fix ID"); if (ifix < 0) error->all(FLERR,"Could not find dump vtk fix ID");
fix[i] = modify->fix[ifix]; fix[i] = modify->fix[ifix];
if (nevery % modify->fix[ifix]->peratom_freq) if (nevery % modify->fix[ifix]->peratom_freq)
error->all(FLERR,"Dump vtk and fix not computed at compatible times"); error->all(FLERR,"Dump vtk and fix not computed at compatible times");
} }
int ivariable;
for (int i = 0; i < nvariable; i++) { for (int i = 0; i < nvariable; i++) {
ivariable = input->variable->find(id_variable[i]); int ivariable = input->variable->find(id_variable[i]);
if (ivariable < 0) if (ivariable < 0)
error->all(FLERR,"Could not find dump vtk variable name"); error->all(FLERR,"Could not find dump vtk variable name");
variable[i] = ivariable; variable[i] = ivariable;
} }
int icustom; int icustom,flag,cols;
for (int i = 0; i < ncustom; i++) { for (int i = 0; i < ncustom; i++) {
icustom = atom->find_custom(id_custom[i],flag_custom[i]); icustom = atom->find_custom(id_custom[i],flag,cols);
if (icustom < 0) if (icustom < 0)
error->all(FLERR,"Could not find custom per-atom property ID"); error->all(FLERR,"Could not find custom per-atom property ID");
custom[i] = icustom;
if (!flag && !cols) custom_flag[i] = IVEC;
else if (flag && !cols) custom_flag[i] = DVEC;
else if (!flag && cols) custom_flag[i] = IARRAY;
else if (flag && cols) custom_flag[i] = DARRAY;
} }
// set index and check validity of region // set index and check validity of region
@ -275,7 +277,7 @@ int DumpVTK::count()
// grow choose and variable vbuf arrays if needed // grow choose and variable vbuf arrays if needed
int nlocal = atom->nlocal; const int nlocal = atom->nlocal;
if (atom->nmax > maxlocal) { if (atom->nmax > maxlocal) {
maxlocal = atom->nmax; maxlocal = atom->nmax;
@ -345,10 +347,10 @@ int DumpVTK::count()
// un-choose if any threshold criterion isn't met // un-choose if any threshold criterion isn't met
if (nthresh) { if (nthresh) {
double *ptr; double *ptr,*ptrhold;
double *values;
double value; double value;
int nstride; int nstride,lastflag;
int nlocal = atom->nlocal;
for (int ithresh = 0; ithresh < nthresh; ithresh++) { for (int ithresh = 0; ithresh < nthresh; ithresh++) {
@ -635,26 +637,22 @@ int DumpVTK::count()
nstride = 1; nstride = 1;
} else if (thresh_array[ithresh] == MUX) { } else if (thresh_array[ithresh] == MUX) {
if (!atom->mu_flag) if (!atom->mu_flag)
error->all(FLERR, error->all(FLERR,"Threshold for an atom property that isn't allocated");
"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][0]; ptr = &atom->mu[0][0];
nstride = 4; nstride = 4;
} else if (thresh_array[ithresh] == MUY) { } else if (thresh_array[ithresh] == MUY) {
if (!atom->mu_flag) if (!atom->mu_flag)
error->all(FLERR, error->all(FLERR,"Threshold for an atom property that isn't allocated");
"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][1]; ptr = &atom->mu[0][1];
nstride = 4; nstride = 4;
} else if (thresh_array[ithresh] == MUZ) { } else if (thresh_array[ithresh] == MUZ) {
if (!atom->mu_flag) if (!atom->mu_flag)
error->all(FLERR, error->all(FLERR,"Threshold for an atom property that isn't allocated");
"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][2]; ptr = &atom->mu[0][2];
nstride = 4; nstride = 4;
} else if (thresh_array[ithresh] == MU) { } else if (thresh_array[ithresh] == MU) {
if (!atom->mu_flag) if (!atom->mu_flag)
error->all(FLERR, error->all(FLERR,"Threshold for an atom property that isn't allocated");
"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][3]; ptr = &atom->mu[0][3];
nstride = 4; nstride = 4;
@ -753,9 +751,8 @@ int DumpVTK::count()
nstride = 1; nstride = 1;
} else if (thresh_array[ithresh] == IVEC) { } else if (thresh_array[ithresh] == IVEC) {
int iwhich,flag,cols
i = ATTRIBUTES + nfield + ithresh; i = ATTRIBUTES + nfield + ithresh;
iwhich = atom->find_custom(id_custom[field2index[i]],flag,cols); int iwhich = custom[field2index[i]];
int *ivector = atom->ivector[iwhich]; int *ivector = atom->ivector[iwhich];
for (i = 0; i < nlocal; i++) for (i = 0; i < nlocal; i++)
dchoose[i] = ivector[i]; dchoose[i] = ivector[i];
@ -763,16 +760,14 @@ int DumpVTK::count()
nstride = 1; nstride = 1;
} else if (thresh_array[ithresh] == DVEC) { } else if (thresh_array[ithresh] == DVEC) {
int iwhich,flag,cols;
i = ATTRIBUTES + nfield + ithresh; i = ATTRIBUTES + nfield + ithresh;
iwhich = atom->find_custom(id_custom[field2index[i]],flag,cols); int iwhich = custom[field2index[i]];
ptr = atom->dvector[iwhich]; ptr = atom->dvector[iwhich];
nstride = 1; nstride = 1;
} else if (thresh_array[ithresh] == IARRAY) { } else if (thresh_array[ithresh] == IARRAY) {
int iwhich,flag,cols;
i = ATTRIBUTES + nfield + ithresh; i = ATTRIBUTES + nfield + ithresh;
iwhich = atom->find_custom(id_custom[field2index[i]],flag,cols); int iwhich = custom[field2index[i]];
int **iarray = atom->iarray[iwhich]; int **iarray = atom->iarray[iwhich];
int icol = argindex[i] - 1; int icol = argindex[i] - 1;
for (i = 0; i < nlocal; i++) for (i = 0; i < nlocal; i++)
@ -781,43 +776,99 @@ int DumpVTK::count()
nstride = 1; nstride = 1;
} else if (thresh_array[ithresh] == DARRAY) { } else if (thresh_array[ithresh] == DARRAY) {
int iwhich,flag,cols;
i = ATTRIBUTES + nfield + ithresh; i = ATTRIBUTES + nfield + ithresh;
iwhich = atom->find_custom(id_custom[field2index[i]],flag,cols) int iwhich = custom[field2index[i]];
double **darray = atom->darray[iwhich]; double **darray = atom->darray[iwhich];
ptr = &darray[0][argindex[i]-1]; ptr = &darray[0][argindex[i]-1];
nstride = atom->dcols[iwhich]; nstride = atom->dcols[iwhich];
} }
// unselect atoms that don't meet threshold criterion // unselect atoms that don't meet threshold criterion
// compare to single value or values stored in threshfix
// copy ptr attribute into thresh_fix if this is first comparison
value = thresh_value[ithresh]; if (thresh_last[ithresh] < 0) {
lastflag = 0;
value = thresh_value[ithresh];
} else {
lastflag = 1;
int ilast = thresh_last[ithresh];
values = thresh_fix[ilast]->vstore;
ptrhold = ptr;
if (thresh_first[ilast]) {
thresh_first[ilast] = 0;
for (i = 0; i < nlocal; i++, ptr += nstride) values[i] = *ptr;
ptr = ptrhold;
}
}
switch (thresh_op[ithresh]) { if (thresh_op[ithresh] == LT) {
case LT: if (lastflag) {
for (i = 0; i < nlocal; i++, ptr += nstride) for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr >= value) choose[i] = 0; if (choose[i] && *ptr >= values[i]) choose[i] = 0;
break; } else {
case LE: for (i = 0; i < nlocal; i++, ptr += nstride)
for (i = 0; i < nlocal; i++, ptr += nstride) if (choose[i] && *ptr >= value) choose[i] = 0;
if (choose[i] && *ptr > value) choose[i] = 0; }
break; } else if (thresh_op[ithresh] == LE) {
case GT: if (lastflag) {
for (i = 0; i < nlocal; i++, ptr += nstride) for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr <= value) choose[i] = 0; if (choose[i] && *ptr > values[i]) choose[i] = 0;
break; } else {
case GE: for (i = 0; i < nlocal; i++, ptr += nstride)
for (i = 0; i < nlocal; i++, ptr += nstride) if (choose[i] && *ptr > value) choose[i] = 0;
if (choose[i] && *ptr < value) choose[i] = 0; }
break; } else if (thresh_op[ithresh] == GT) {
case EQ: if (lastflag) {
for (i = 0; i < nlocal; i++, ptr += nstride) for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr != value) choose[i] = 0; if (choose[i] && *ptr <= values[i]) choose[i] = 0;
break; } else {
case NEQ: for (i = 0; i < nlocal; i++, ptr += nstride)
for (i = 0; i < nlocal; i++, ptr += nstride) if (choose[i] && *ptr <= value) choose[i] = 0;
if (choose[i] && *ptr == value) choose[i] = 0; }
break; } else if (thresh_op[ithresh] == GE) {
if (lastflag) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr < values[i]) choose[i] = 0;
} else {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr < value) choose[i] = 0;
}
} else if (thresh_op[ithresh] == EQ) {
if (lastflag) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr != values[i]) choose[i] = 0;
} else {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr != value) choose[i] = 0;
}
} else if (thresh_op[ithresh] == NEQ) {
if (lastflag) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr == values[i]) choose[i] = 0;
} else {
for (i = 0; i < nlocal; i++, ptr += nstride)
if (choose[i] && *ptr == value) choose[i] = 0;
}
} else if (thresh_op[ithresh] == XOR) {
if (lastflag) {
for (i = 0; i < nlocal; i++, ptr += nstride)
if ((choose[i] && *ptr == 0.0 && values[i] == 0.0) ||
(*ptr != 0.0 && values[i] != 0.0))
choose[i] = 0;
} else {
for (i = 0; i < nlocal; i++, ptr += nstride)
if ((choose[i] && *ptr == 0.0 && value == 0.0) ||
(*ptr != 0.0 && value != 0.0))
choose[i] = 0;
}
}
// update values stored in threshfix
if (lastflag) {
ptr = ptrhold;
for (i = 0; i < nlocal; i++, ptr += nstride) values[i] = *ptr;
} }
} }
} }
@ -1754,15 +1805,16 @@ int DumpVTK::parse_fields(int narg, char **arg)
} else { } else {
int n,tmp; int n,flag,cols;
ArgInfo argi(arg[iarg],ArgInfo::COMPUTE|ArgInfo::FIX|ArgInfo::VARIABLE ArgInfo argi(arg[iarg],ArgInfo::COMPUTE|ArgInfo::FIX|ArgInfo::VARIABLE
|ArgInfo::DVEC|ArgInfo::IVEC); |ArgInfo::DNAME|ArgInfo::INAME);
argindex[ATTRIBUTES+i] = argi.get_index1(); argindex[ATTRIBUTES+i] = argi.get_index1();
auto aname = argi.get_name();
switch (argi.get_type()) { switch (argi.get_type()) {
case ArgInfo::UNKNOWN: case ArgInfo::UNKNOWN:
error->all(FLERR,"Invalid attribute in dump vtk command"); error->all(FLERR,"Invalid attribute in dump vtk command: {}",arg[iarg]);
break; break;
// compute value = c_ID // compute value = c_ID
@ -1772,21 +1824,19 @@ int DumpVTK::parse_fields(int narg, char **arg)
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_compute; pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_compute;
vtype[ATTRIBUTES+i] = Dump::DOUBLE; vtype[ATTRIBUTES+i] = Dump::DOUBLE;
n = modify->find_compute(argi.get_name()); n = modify->find_compute(aname);
if (n < 0) error->all(FLERR,"Could not find dump vtk compute ID"); if (n < 0) error->all(FLERR,"Could not find dump vtk compute ID: {}",aname);
if (modify->compute[n]->peratom_flag == 0) if (modify->compute[n]->peratom_flag == 0)
error->all(FLERR,"Dump vtk compute does not compute per-atom info"); error->all(FLERR,"Dump vtk compute {} does not compute per-atom info",aname);
if (argi.get_dim() == 0 && modify->compute[n]->size_peratom_cols > 0) if (argi.get_dim() == 0 && modify->compute[n]->size_peratom_cols > 0)
error->all(FLERR, error->all(FLERR,"Dump vtk compute {} does not calculate per-atom vector",aname);
"Dump vtk compute does not calculate per-atom vector");
if (argi.get_dim() > 0 && modify->compute[n]->size_peratom_cols == 0) if (argi.get_dim() > 0 && modify->compute[n]->size_peratom_cols == 0)
error->all(FLERR, error->all(FLERR,"Dump vtk compute {} does not calculate per-atom array",aname);
"Dump vtk compute does not calculate per-atom array");
if (argi.get_dim() > 0 && if (argi.get_dim() > 0 &&
argi.get_index1() > modify->compute[n]->size_peratom_cols) argi.get_index1() > modify->compute[n]->size_peratom_cols)
error->all(FLERR,"Dump vtk compute vector is accessed out-of-range"); error->all(FLERR,"Dump vtk compute {} vector is accessed out-of-range",aname);
field2index[ATTRIBUTES+i] = add_compute(argi.get_name()); field2index[ATTRIBUTES+i] = add_compute(aname);
name[ATTRIBUTES+i] = arg[iarg]; name[ATTRIBUTES+i] = arg[iarg];
break; break;
@ -1797,19 +1847,19 @@ int DumpVTK::parse_fields(int narg, char **arg)
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_fix; pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_fix;
vtype[ATTRIBUTES+i] = Dump::DOUBLE; vtype[ATTRIBUTES+i] = Dump::DOUBLE;
n = modify->find_fix(argi.get_name()); n = modify->find_fix(aname);
if (n < 0) error->all(FLERR,"Could not find dump vtk fix ID"); if (n < 0) error->all(FLERR,"Could not find dump vtk fix ID: {}",aname);
if (modify->fix[n]->peratom_flag == 0) if (modify->fix[n]->peratom_flag == 0)
error->all(FLERR,"Dump vtk fix does not compute per-atom info"); error->all(FLERR,"Dump vtk fix {} does not compute per-atom info",aname);
if (argi.get_dim() == 0 && modify->fix[n]->size_peratom_cols > 0) if (argi.get_dim() == 0 && modify->fix[n]->size_peratom_cols > 0)
error->all(FLERR,"Dump vtk fix does not compute per-atom vector"); error->all(FLERR,"Dump vtk fix {} does not compute per-atom vector",aname);
if (argi.get_dim() > 0 && modify->fix[n]->size_peratom_cols == 0) if (argi.get_dim() > 0 && modify->fix[n]->size_peratom_cols == 0)
error->all(FLERR,"Dump vtk fix does not compute per-atom array"); error->all(FLERR,"Dump vtk fix {} does not compute per-atom array",aname);
if (argi.get_dim() > 0 && if (argi.get_dim() > 0 &&
argi.get_index1() > modify->fix[n]->size_peratom_cols) argi.get_index1() > modify->fix[n]->size_peratom_cols)
error->all(FLERR,"Dump vtk fix vector is accessed out-of-range"); error->all(FLERR,"Dump vtk fix {} vector is accessed out-of-range",aname);
field2index[ATTRIBUTES+i] = add_fix(argi.get_name()); field2index[ATTRIBUTES+i] = add_fix(aname);
name[ATTRIBUTES+i] = arg[iarg]; name[ATTRIBUTES+i] = arg[iarg];
break; break;
@ -1819,61 +1869,62 @@ int DumpVTK::parse_fields(int narg, char **arg)
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_variable; pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_variable;
vtype[ATTRIBUTES+i] = Dump::DOUBLE; vtype[ATTRIBUTES+i] = Dump::DOUBLE;
n = input->variable->find(argi.get_name()); n = input->variable->find(aname);
if (n < 0) error->all(FLERR,"Could not find dump vtk variable name"); if (n < 0) error->all(FLERR,"Could not find dump vtk variable name {}",aname);
if (input->variable->atomstyle(n) == 0) if (input->variable->atomstyle(n) == 0)
error->all(FLERR,"Dump vtk variable is not atom-style variable"); error->all(FLERR,"Dump vtk variable {} is not atom-style variable",aname);
field2index[ATTRIBUTES+i] = add_variable(argi.get_name()); field2index[ATTRIBUTES+i] = add_variable(aname);
name[ATTRIBUTES+i] = arg[iarg]; name[ATTRIBUTES+i] = arg[iarg];
break; break;
// custom per-atom integer vector = i_ID // custom per-atom floating point vector or array = d_ID d2_ID
case ArgInfo::INAME:
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_custom;
vtype[ATTRIBUTES+i] = Dump::INT;
tmp = -1;
n = atom->find_custom(argi.get_name(),tmp);
if (n < 0)
error->all(FLERR,"Could not find custom per-atom property ID");
if (tmp != 0)
error->all(FLERR,"Custom per-atom property ID is not integer");
field2index[ATTRIBUTES+i] = add_custom(argi.get_name(),0);
name[ATTRIBUTES+i] = arg[iarg];
break;
// custom per-atom floating point vector = d_ID
case ArgInfo::DNAME: case ArgInfo::DNAME:
pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_custom; pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_custom;
vtype[ATTRIBUTES+i] = Dump::DOUBLE; vtype[ATTRIBUTES+i] = Dump::DOUBLE;
tmp = -1; n = atom->find_custom(aname,flag,cols);
n = atom->find_custom(argi.get_name(),tmp);
if (n < 0) if (n < 0)
error->all(FLERR,"Could not find custom per-atom property ID"); error->all(FLERR,"Could not find custom per-atom property ID: {}", aname);
if (argindex[ATTRIBUTES+i] == 0) {
if (tmp != 1) if (!flag || cols)
error->all(FLERR,"Custom per-atom property ID is not floating point"); error->all(FLERR,"Property double vector {} for dump vtk does not exist",aname);
} else {
field2index[ATTRIBUTES+i] = add_custom(argi.get_name(),1); if (!flag || !cols)
error->all(FLERR,"Property double array {} for dump vtk does not exist",aname);
if (argindex[ATTRIBUTES+i] > atom->dcols[n])
error->all(FLERR,"Dump vtk property array {} is accessed out-of-range",aname);
}
field2index[ATTRIBUTES+i] = add_custom(aname,1);
name[ATTRIBUTES+i] = arg[iarg]; name[ATTRIBUTES+i] = arg[iarg];
break; break;
// NEWSTYLE // custom per-atom integer vector or array = i_ID or i2_ID
// custom per-atom integer array = i2_ID
case ArgInfo::IARRAY: case ArgInfo::INAME:
return iarg; pack_choice[ATTRIBUTES+i] = &DumpVTK::pack_custom;
vtype[ATTRIBUTES+i] = Dump::INT;
// custom per-atom floating point array = d2_ID n = atom->find_custom(aname,flag,cols);
case ArgInfo::DARRAY: if (n < 0)
return iarg; error->all(FLERR,"Could not find custom per-atom property ID: {}", aname);
if (argindex[ATTRIBUTES+i] == 0) {
if (flag || cols)
error->all(FLERR,"Property integer vector {} for dump vtk does not exist",aname);
} else {
if (flag || !cols)
error->all(FLERR,"Property integer array {} for dump vtk does not exist",aname);
if (argindex[ATTRIBUTES+i] > atom->icols[n])
error->all(FLERR,"Dump vtk property array {} is accessed out-of-range",aname);
}
field2index[ATTRIBUTES+i] = add_custom(aname,0);
name[ATTRIBUTES+i] = arg[iarg];
break;
// no match
default: default:
return iarg; return iarg;
@ -1948,12 +1999,10 @@ int DumpVTK::add_compute(const char *id)
id_compute = (char **) id_compute = (char **)
memory->srealloc(id_compute,(ncompute+1)*sizeof(char *),"dump:id_compute"); memory->srealloc(id_compute,(ncompute+1)*sizeof(char *),"dump:id_compute");
delete [] compute; delete[] compute;
compute = new Compute*[ncompute+1]; compute = new Compute*[ncompute+1];
int n = strlen(id) + 1; id_compute[ncompute] = utils::strdup(id);
id_compute[ncompute] = new char[n];
strcpy(id_compute[ncompute],id);
ncompute++; ncompute++;
return ncompute-1; return ncompute-1;
} }
@ -1973,12 +2022,10 @@ int DumpVTK::add_fix(const char *id)
id_fix = (char **) id_fix = (char **)
memory->srealloc(id_fix,(nfix+1)*sizeof(char *),"dump:id_fix"); memory->srealloc(id_fix,(nfix+1)*sizeof(char *),"dump:id_fix");
delete [] fix; delete[] fix;
fix = new Fix*[nfix+1]; fix = new Fix*[nfix+1];
int n = strlen(id) + 1; id_fix[nfix] = utils::strdup(id);
id_fix[nfix] = new char[n];
strcpy(id_fix[nfix],id);
nfix++; nfix++;
return nfix-1; return nfix-1;
} }
@ -1999,22 +2046,20 @@ int DumpVTK::add_variable(const char *id)
id_variable = (char **) id_variable = (char **)
memory->srealloc(id_variable,(nvariable+1)*sizeof(char *), memory->srealloc(id_variable,(nvariable+1)*sizeof(char *),
"dump:id_variable"); "dump:id_variable");
delete [] variable; delete[] variable;
variable = new int[nvariable+1]; variable = new int[nvariable+1];
delete [] vbuf; delete[] vbuf;
vbuf = new double*[nvariable+1]; vbuf = new double*[nvariable+1];
for (int i = 0; i <= nvariable; i++) vbuf[i] = nullptr; for (int i = 0; i <= nvariable; i++) vbuf[i] = nullptr;
int n = strlen(id) + 1; id_variable[nvariable] = utils::strdup(id);
id_variable[nvariable] = new char[n];
strcpy(id_variable[nvariable],id);
nvariable++; nvariable++;
return nvariable-1; return nvariable-1;
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
add custom atom property to list used by dump add custom atom property to list used by dump
return index of where this property is in list return index of where this property is in Atom class custom lists
if already in list, do not add, just return index, else add to list if already in list, do not add, just return index, else add to list
------------------------------------------------------------------------- */ ------------------------------------------------------------------------- */
@ -2022,21 +2067,17 @@ int DumpVTK::add_custom(const char *id, int flag)
{ {
int icustom; int icustom;
for (icustom = 0; icustom < ncustom; icustom++) for (icustom = 0; icustom < ncustom; icustom++)
if ((strcmp(id,id_custom[icustom]) == 0) if (strcmp(id,id_custom[icustom]) == 0) break;
&& (flag == flag_custom[icustom])) break;
if (icustom < ncustom) return icustom; if (icustom < ncustom) return icustom;
id_custom = (char **) id_custom = (char **) memory->srealloc(id_custom,(ncustom+1)*sizeof(char *),"dump:id_custom");
memory->srealloc(id_custom,(ncustom+1)*sizeof(char *),"dump:id_custom"); custom = (int *) memory->srealloc(custom,(ncustom+1)*sizeof(int),"dump:custom");
flag_custom = (int *) custom_flag = (int *) memory->srealloc(custom_flag,(ncustom+1)*sizeof(int),"dump:custom_flag");
memory->srealloc(flag_custom,(ncustom+1)*sizeof(int),"dump:flag_custom");
int n = strlen(id) + 1;
id_custom[ncustom] = new char[n];
strcpy(id_custom[ncustom],id);
flag_custom[ncustom] = flag;
id_custom[ncustom] = utils::strdup(id);
custom_flag[ncustom] = flag;
ncustom++; ncustom++;
return ncustom-1; return ncustom-1;
} }
@ -2050,21 +2091,17 @@ int DumpVTK::modify_param(int narg, char **arg)
else { else {
iregion = domain->find_region(arg[1]); iregion = domain->find_region(arg[1]);
if (iregion == -1) if (iregion == -1)
error->all(FLERR,"Dump_modify region ID does not exist"); error->all(FLERR,"Dump_modify region ID {} does not exist",arg[1]);
delete [] idregion; delete[] idregion;
int n = strlen(arg[1]) + 1; idregion = utils::strdup(arg[1]);
idregion = new char[n];
strcpy(idregion,arg[1]);
} }
return 2; return 2;
} }
if (strcmp(arg[0],"label") == 0) { if (strcmp(arg[0],"label") == 0) {
if (narg < 2) error->all(FLERR,"Illegal dump_modify command [label]"); if (narg < 2) error->all(FLERR,"Illegal dump_modify command [label]");
delete [] label; delete[] label;
int n = strlen(arg[1]) + 1; label = utils::strdup(arg[1]);
label = new char[n];
strcpy(label,arg[1]);
return 2; return 2;
} }
@ -2076,23 +2113,29 @@ int DumpVTK::modify_param(int narg, char **arg)
if (strcmp(arg[0],"element") == 0) { if (strcmp(arg[0],"element") == 0) {
if (narg < ntypes+1) if (narg < ntypes+1)
error->all(FLERR,"Dump modify: number of element names do not match atom types"); error->all(FLERR,"Number of dump_modify element names does not match number of atom types");
if (typenames) {
for (int i = 1; i <= ntypes; i++) delete [] typenames[i];
delete [] typenames;
typenames = nullptr;
}
for (int i = 1; i <= ntypes; i++) delete[] typenames[i];
delete[] typenames;
typenames = new char*[ntypes+1]; typenames = new char*[ntypes+1];
for (int itype = 1; itype <= ntypes; itype++) { for (int itype = 1; itype <= ntypes; itype++) {
int n = strlen(arg[itype]) + 1; typenames[itype] = utils::strdup(arg[itype]);
typenames[itype] = new char[n];
strcpy(typenames[itype],arg[itype]);
} }
return ntypes+1; return ntypes+1;
} }
if (strcmp(arg[0],"refresh") == 0) {
if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
ArgInfo argi(arg[1],ArgInfo::COMPUTE);
if ((argi.get_type() != ArgInfo::COMPUTE) || (argi.get_dim() != 0))
error->all(FLERR,"Illegal dump_modify command");
if (refreshflag) error->all(FLERR,"Dump_modify can only have one refresh");
refreshflag = 1;
refresh = argi.copy_name();
return 2;
}
if (strcmp(arg[0],"thresh") == 0) { if (strcmp(arg[0],"thresh") == 0) {
if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); if (narg < 2) error->all(FLERR,"Illegal dump_modify command");
if (strcmp(arg[1],"none") == 0) { if (strcmp(arg[1],"none") == 0) {
@ -2103,8 +2146,16 @@ int DumpVTK::modify_param(int narg, char **arg)
thresh_array = nullptr; thresh_array = nullptr;
thresh_op = nullptr; thresh_op = nullptr;
thresh_value = nullptr; thresh_value = nullptr;
thresh_last = nullptr;
for (int i = 0; i < nthreshlast; i++) {
modify->delete_fix(thresh_fixID[i]);
delete[] thresh_fixID[i];
}
thresh_fix = nullptr;
thresh_fixID = nullptr;
thresh_first = nullptr;
} }
nthresh = 0; nthresh = nthreshlast = 0;
return 2; return 2;
} }
@ -2115,6 +2166,7 @@ int DumpVTK::modify_param(int narg, char **arg)
memory->grow(thresh_array,nthresh+1,"dump:thresh_array"); memory->grow(thresh_array,nthresh+1,"dump:thresh_array");
memory->grow(thresh_op,(nthresh+1),"dump:thresh_op"); memory->grow(thresh_op,(nthresh+1),"dump:thresh_op");
memory->grow(thresh_value,(nthresh+1),"dump:thresh_value"); memory->grow(thresh_value,(nthresh+1),"dump:thresh_value");
memory->grow(thresh_last,(nthresh+1),"dump:thresh_last");
// set attribute type of threshold // set attribute type of threshold
// customize by adding to if statement // customize by adding to if statement
@ -2197,98 +2249,125 @@ int DumpVTK::modify_param(int narg, char **arg)
else if (strcmp(arg[1],"tqy") == 0) thresh_array[nthresh] = TQY; else if (strcmp(arg[1],"tqy") == 0) thresh_array[nthresh] = TQY;
else if (strcmp(arg[1],"tqz") == 0) thresh_array[nthresh] = TQZ; else if (strcmp(arg[1],"tqz") == 0) thresh_array[nthresh] = TQZ;
// compute value = c_ID // compute or fix or variable or custom vector/array
// if no trailing [], then arg is set to 0, else arg is between []
else if (strncmp(arg[1],"c_",2) == 0) { else {
thresh_array[nthresh] = COMPUTE; int n,flag,cols;
int n = strlen(arg[1]); ArgInfo argi(arg[1],ArgInfo::COMPUTE|ArgInfo::FIX|ArgInfo::VARIABLE
char *suffix = new char[n]; |ArgInfo::DNAME|ArgInfo::INAME);
strcpy(suffix,&arg[1][2]); argindex[ATTRIBUTES+nfield+nthresh] = argi.get_index1();
auto aname = argi.get_name();
char *ptr = strchr(suffix,'['); switch (argi.get_type()) {
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
error->all(FLERR,"Invalid attribute in dump modify command");
argindex[ATTRIBUTES+nfield+nthresh] = atoi(ptr+1);
*ptr = '\0';
} else argindex[ATTRIBUTES+nfield+nthresh] = 0;
n = modify->find_compute(suffix); case ArgInfo::UNKNOWN:
if (n < 0) error->all(FLERR,"Could not find dump modify compute ID"); error->all(FLERR,"Invalid attribute in dump modify command");
break;
if (modify->compute[n]->peratom_flag == 0) // compute value = c_ID
error->all(FLERR, // if no trailing [], then arg is set to 0, else arg is between []
"Dump modify compute ID does not compute per-atom info");
if (argindex[ATTRIBUTES+nfield+nthresh] == 0 &&
modify->compute[n]->size_peratom_cols > 0)
error->all(FLERR,
"Dump modify compute ID does not compute per-atom vector");
if (argindex[ATTRIBUTES+nfield+nthresh] > 0 &&
modify->compute[n]->size_peratom_cols == 0)
error->all(FLERR,
"Dump modify compute ID does not compute per-atom array");
if (argindex[ATTRIBUTES+nfield+nthresh] > 0 &&
argindex[ATTRIBUTES+nfield+nthresh] > modify->compute[n]->size_peratom_cols)
error->all(FLERR,"Dump modify compute ID vector is not large enough");
field2index[ATTRIBUTES+nfield+nthresh] = add_compute(suffix); case ArgInfo::COMPUTE:
delete [] suffix; thresh_array[nthresh] = COMPUTE;
n = modify->find_compute(aname);
if (n < 0) error->all(FLERR,"Could not find dump modify compute ID: {}",aname);
// fix value = f_ID if (modify->compute[n]->peratom_flag == 0)
// if no trailing [], then arg is set to 0, else arg is between [] error->all(FLERR,"Dump modify compute ID {} does not compute per-atom info",aname);
if (argi.get_dim() == 0 && modify->compute[n]->size_peratom_cols > 0)
error->all(FLERR,"Dump modify compute ID {} does not compute per-atom vector",aname);
if (argi.get_index1() > 0 && modify->compute[n]->size_peratom_cols == 0)
error->all(FLERR,"Dump modify compute ID {} does not compute per-atom array",aname);
if (argi.get_index1() > 0 &&
argi.get_index1() > modify->compute[n]->size_peratom_cols)
error->all(FLERR,"Dump modify compute ID {} vector is not large enough",aname);
} else if (strncmp(arg[1],"f_",2) == 0) { field2index[ATTRIBUTES+nfield+nthresh] = add_compute(aname);
thresh_array[nthresh] = FIX; break;
int n = strlen(arg[1]);
char *suffix = new char[n];
strcpy(suffix,&arg[1][2]);
char *ptr = strchr(suffix,'['); // fix value = f_ID
if (ptr) { // if no trailing [], then arg is set to 0, else arg is between []
if (suffix[strlen(suffix)-1] != ']')
error->all(FLERR,"Invalid attribute in dump modify command");
argindex[ATTRIBUTES+nfield+nthresh] = atoi(ptr+1);
*ptr = '\0';
} else argindex[ATTRIBUTES+nfield+nthresh] = 0;
n = modify->find_fix(suffix); case ArgInfo::FIX:
if (n < 0) error->all(FLERR,"Could not find dump modify fix ID"); thresh_array[nthresh] = FIX;
n = modify->find_fix(aname);
if (n < 0) error->all(FLERR,"Could not find dump modify fix ID: {}",aname);
if (modify->fix[n]->peratom_flag == 0) if (modify->fix[n]->peratom_flag == 0)
error->all(FLERR,"Dump modify fix ID does not compute per-atom info"); error->all(FLERR,"Dump modify fix ID {} does not compute per-atom info",aname);
if (argindex[ATTRIBUTES+nfield+nthresh] == 0 && if (argi.get_dim() == 0 && modify->fix[n]->size_peratom_cols > 0)
modify->fix[n]->size_peratom_cols > 0) error->all(FLERR,"Dump modify fix ID {} does not compute per-atom vector",aname);
error->all(FLERR,"Dump modify fix ID does not compute per-atom vector"); if (argi.get_index1() > 0 && modify->fix[n]->size_peratom_cols == 0)
if (argindex[ATTRIBUTES+nfield+nthresh] > 0 && error->all(FLERR,"Dump modify fix ID {} does not compute per-atom array",aname);
modify->fix[n]->size_peratom_cols == 0) if (argi.get_index1() > 0 && argi.get_index1() > modify->fix[n]->size_peratom_cols)
error->all(FLERR,"Dump modify fix ID does not compute per-atom array"); error->all(FLERR,"Dump modify fix ID {} vector is not large enough",aname);
if (argindex[ATTRIBUTES+nfield+nthresh] > 0 &&
argindex[ATTRIBUTES+nfield+nthresh] > modify->fix[n]->size_peratom_cols)
error->all(FLERR,"Dump modify fix ID vector is not large enough");
field2index[ATTRIBUTES+nfield+nthresh] = add_fix(suffix); field2index[ATTRIBUTES+nfield+nthresh] = add_fix(aname);
delete [] suffix; break;
// variable value = v_ID // variable value = v_ID
} else if (strncmp(arg[1],"v_",2) == 0) { case ArgInfo::VARIABLE:
thresh_array[nthresh] = VARIABLE; thresh_array[nthresh] = VARIABLE;
int n = strlen(arg[1]); n = input->variable->find(aname);
char *suffix = new char[n]; if (n < 0) error->all(FLERR,"Could not find dump modify variable name: {}",aname);
strcpy(suffix,&arg[1][2]); if (input->variable->atomstyle(n) == 0)
error->all(FLERR,"Dump modify variable {} is not atom-style variable",aname);
argindex[ATTRIBUTES+nfield+nthresh] = 0; field2index[ATTRIBUTES+nfield+nthresh] = add_variable(aname);
break;
n = input->variable->find(suffix); // custom per atom floating point vector or array
if (n < 0) error->all(FLERR,"Could not find dump modify variable name");
if (input->variable->atomstyle(n) == 0)
error->all(FLERR,"Dump modify variable is not atom-style variable");
field2index[ATTRIBUTES+nfield+nthresh] = add_variable(suffix); case ArgInfo::DNAME:
delete [] suffix; n = atom->find_custom(aname,flag,cols);
} else error->all(FLERR,"Invalid dump_modify threshold operator"); if (n < 0)
error->all(FLERR,"Could not find custom per-atom property ID: {}", aname);
if (argindex[ATTRIBUTES+nfield+nthresh] == 0) {
if (!flag || cols)
error->all(FLERR,"Property double vector for dump custom does not exist");
thresh_array[nthresh] = DVEC;
} else {
if (!flag || !cols)
error->all(FLERR,"Property double array for dump custom does not exist");
if (argindex[ATTRIBUTES+nfield+nthresh] > atom->dcols[n])
error->all(FLERR,"Dump custom property array is accessed out-of-range");
thresh_array[nthresh] = DARRAY;
}
field2index[ATTRIBUTES+nfield+nthresh] = add_custom(aname,thresh_array[nthresh]);
break;
// custom per atom integer vector or array
case ArgInfo::INAME:
n = atom->find_custom(aname,flag,cols);
if (n < 0)
error->all(FLERR,"Could not find custom per-atom property ID: {}", aname);
if (argindex[ATTRIBUTES+nfield+nthresh] == 0) {
if (flag || cols)
error->all(FLERR,"Property integer vector for dump custom does not exist");
thresh_array[nthresh] = IVEC;
} else {
if (flag || !cols)
error->all(FLERR,"Property integer array for dump custom does not exist");
if (argindex[ATTRIBUTES+nfield+nthresh] > atom->icols[n])
error->all(FLERR,"Dump custom property array is accessed out-of-range");
thresh_array[nthresh] = IARRAY;
}
field2index[ATTRIBUTES+nfield+nthresh] = add_custom(aname,thresh_array[nthresh]);
break;
// no match
default:
error->all(FLERR,"Invalid dump_modify thresh attribute: {}",aname);
break;
}
}
// set operation type of threshold // set operation type of threshold
@ -2298,11 +2377,32 @@ int DumpVTK::modify_param(int narg, char **arg)
else if (strcmp(arg[2],">=") == 0) thresh_op[nthresh] = GE; else if (strcmp(arg[2],">=") == 0) thresh_op[nthresh] = GE;
else if (strcmp(arg[2],"==") == 0) thresh_op[nthresh] = EQ; else if (strcmp(arg[2],"==") == 0) thresh_op[nthresh] = EQ;
else if (strcmp(arg[2],"!=") == 0) thresh_op[nthresh] = NEQ; else if (strcmp(arg[2],"!=") == 0) thresh_op[nthresh] = NEQ;
else error->all(FLERR,"Invalid dump_modify threshold operator"); else if (strcmp(arg[2],"|^") == 0) thresh_op[nthresh] = XOR;
else error->all(FLERR,"Invalid dump_modify thresh operator");
// set threshold value // set threshold value as number or special LAST keyword
// create FixStore to hold LAST values, should work with restart
// id = dump-ID + nthreshlast + DUMP_STORE, fix group = dump group
thresh_value[nthresh] = utils::numeric(FLERR,arg[3],false,lmp); if (strcmp(arg[3],"LAST") != 0) {
thresh_value[nthresh] = utils::numeric(FLERR,arg[3],false,lmp);
thresh_last[nthresh] = -1;
} else {
thresh_fix = (FixStore **)
memory->srealloc(thresh_fix,(nthreshlast+1)*sizeof(FixStore *),"dump:thresh_fix");
thresh_fixID = (char **)
memory->srealloc(thresh_fixID,(nthreshlast+1)*sizeof(char *),"dump:thresh_fixID");
memory->grow(thresh_first,(nthreshlast+1),"dump:thresh_first");
std::string threshid = fmt::format("{}{}_DUMP_STORE",id,nthreshlast);
thresh_fixID[nthreshlast] = utils::strdup(threshid);
threshid += fmt::format(" {} STORE peratom 1 1", group->names[igroup]);
thresh_fix[nthreshlast] = (FixStore *) modify->add_fix(threshid);
thresh_last[nthreshlast] = nthreshlast;
thresh_first[nthreshlast] = 1;
nthreshlast++;
}
nthresh++; nthresh++;
return 4; return 4;
@ -2387,25 +2487,35 @@ void DumpVTK::pack_variable(int n)
void DumpVTK::pack_custom(int n) void DumpVTK::pack_custom(int n)
{ {
int index = field2index[n]; int flag = custom_flag[field2index[current_pack_choice_key]];
int iwhich = custom[field2index[current_pack_choice_key]];
if (flag_custom[index] == 0) { // integer int index = argindex[current_pack_choice_key];
int iwhich,tmp;
iwhich = atom->find_custom(id_custom[index],tmp);
if (flag == IVEC) {
int *ivector = atom->ivector[iwhich]; int *ivector = atom->ivector[iwhich];
for (int i = 0; i < nchoose; i++) { for (int i = 0; i < nchoose; i++) {
buf[n] = ivector[clist[i]]; buf[n] = ivector[clist[i]];
n += size_one; n += size_one;
} }
} else if (flag_custom[index] == 1) { // double } else if (flag == DVEC) {
int iwhich,tmp;
iwhich = atom->find_custom(id_custom[index],tmp);
double *dvector = atom->dvector[iwhich]; double *dvector = atom->dvector[iwhich];
for (int i = 0; i < nchoose; i++) { for (int i = 0; i < nchoose; i++) {
buf[n] = dvector[clist[i]]; buf[n] = dvector[clist[i]];
n += size_one; n += size_one;
} }
} else if (flag == IARRAY) {
index--;
int **iarray = atom->iarray[iwhich];
for (int i = 0; i < nchoose; i++) {
buf[n] = iarray[clist[i]][index];
n += size_one;
}
} else if (flag == DARRAY) {
index--;
double **darray = atom->darray[iwhich];
for (int i = 0; i < nchoose; i++) {
buf[n] = darray[clist[i]][index];
n += size_one;
}
} }
} }

View File

@ -181,6 +181,8 @@ void ComputeOrientOrderAtom::init()
error->all(FLERR,"Compute orientorder/atom cutoff is " error->all(FLERR,"Compute orientorder/atom cutoff is "
"longer than pairwise cutoff"); "longer than pairwise cutoff");
memory->destroy(qnm_r);
memory->destroy(qnm_i);
memory->create(qnm_r,nqlist,2*qmax+1,"orientorder/atom:qnm_r"); memory->create(qnm_r,nqlist,2*qmax+1,"orientorder/atom:qnm_r");
memory->create(qnm_i,nqlist,2*qmax+1,"orientorder/atom:qnm_i"); memory->create(qnm_i,nqlist,2*qmax+1,"orientorder/atom:qnm_i");
@ -652,6 +654,7 @@ void ComputeOrientOrderAtom::init_clebsch_gordan()
idxcg_count++; idxcg_count++;
} }
idxcg_max = idxcg_count; idxcg_max = idxcg_count;
memory->destroy(cglist);
memory->create(cglist, idxcg_max, "computeorientorderatom:cglist"); memory->create(cglist, idxcg_max, "computeorientorderatom:cglist");
idxcg_count = 0; idxcg_count = 0;

View File

@ -131,7 +131,7 @@ DumpCustom::DumpCustom(LAMMPS *lmp, int narg, char **arg) :
if (ioptional < nfield && if (ioptional < nfield &&
strcmp(style,"image") != 0 && strcmp(style,"movie") != 0) strcmp(style,"image") != 0 && strcmp(style,"movie") != 0)
error->all(FLERR,"Invalid attribute in dump custom command"); error->all(FLERR,"Invalid attribute {} in dump {} command",earg[ioptional],style);
// noptional = # of optional args // noptional = # of optional args
// reset nfield to subtract off optional args // reset nfield to subtract off optional args
@ -238,9 +238,8 @@ DumpCustom::~DumpCustom()
for (int i = 0; i < ncustom; i++) delete[] id_custom[i]; for (int i = 0; i < ncustom; i++) delete[] id_custom[i];
memory->sfree(id_custom); memory->sfree(id_custom);
delete [] custom; memory->sfree(custom);
delete [] custom_flag; memory->sfree(custom_flag);
memory->destroy(choose); memory->destroy(choose);
memory->destroy(dchoose); memory->destroy(dchoose);
memory->destroy(clist); memory->destroy(clist);
@ -909,32 +908,27 @@ int DumpCustom::count()
} else if (thresh_array[ithresh] == Q) { } else if (thresh_array[ithresh] == Q) {
if (!atom->q_flag) if (!atom->q_flag)
error->all(FLERR, error->all(FLERR,"Threshold for an atom property that isn't allocated");
"Threshold for an atom property that isn't allocated");
ptr = atom->q; ptr = atom->q;
nstride = 1; nstride = 1;
} else if (thresh_array[ithresh] == MUX) { } else if (thresh_array[ithresh] == MUX) {
if (!atom->mu_flag) if (!atom->mu_flag)
error->all(FLERR, error->all(FLERR,"Threshold for an atom property that isn't allocated");
"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][0]; ptr = &atom->mu[0][0];
nstride = 4; nstride = 4;
} else if (thresh_array[ithresh] == MUY) { } else if (thresh_array[ithresh] == MUY) {
if (!atom->mu_flag) if (!atom->mu_flag)
error->all(FLERR, error->all(FLERR,"Threshold for an atom property that isn't allocated");
"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][1]; ptr = &atom->mu[0][1];
nstride = 4; nstride = 4;
} else if (thresh_array[ithresh] == MUZ) { } else if (thresh_array[ithresh] == MUZ) {
if (!atom->mu_flag) if (!atom->mu_flag)
error->all(FLERR, error->all(FLERR,"Threshold for an atom property that isn't allocated");
"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][2]; ptr = &atom->mu[0][2];
nstride = 4; nstride = 4;
} else if (thresh_array[ithresh] == MU) { } else if (thresh_array[ithresh] == MU) {
if (!atom->mu_flag) if (!atom->mu_flag)
error->all(FLERR, error->all(FLERR,"Threshold for an atom property that isn't allocated");
"Threshold for an atom property that isn't allocated");
ptr = &atom->mu[0][3]; ptr = &atom->mu[0][3];
nstride = 4; nstride = 4;
@ -1521,7 +1515,7 @@ int DumpCustom::parse_fields(int narg, char **arg)
field2index[iarg] = add_variable(name); field2index[iarg] = add_variable(name);
break; break;
// custom per-atom floating point vector or array // custom per-atom floating point vector or array = d_ID d2_ID
case ArgInfo::DNAME: case ArgInfo::DNAME:
pack_choice[iarg] = &DumpCustom::pack_custom; pack_choice[iarg] = &DumpCustom::pack_custom;
@ -1533,18 +1527,18 @@ int DumpCustom::parse_fields(int narg, char **arg)
error->all(FLERR,"Could not find custom per-atom property ID: {}", name); error->all(FLERR,"Could not find custom per-atom property ID: {}", name);
if (argindex[iarg] == 0) { if (argindex[iarg] == 0) {
if (!flag || cols) if (!flag || cols)
error->all(FLERR,"Property double vector for dump custom does not exist"); error->all(FLERR,"Property double vector {} for dump custom does not exist",name);
} else { } else {
if (!flag || !cols) if (!flag || !cols)
error->all(FLERR,"Property double array for dump custom does not exist"); error->all(FLERR,"Property double array {} for dump custom does not exist",name);
if (argindex[iarg] > atom->dcols[n]) if (argindex[iarg] > atom->dcols[n])
error->all(FLERR,"Dump custom property array is accessed out-of-range"); error->all(FLERR,"Dump custom property array {} is accessed out-of-range",name);
} }
field2index[iarg] = add_custom(name,1); field2index[iarg] = add_custom(name,1);
break; break;
// custom per-atom integer vector or array // custom per-atom integer vector or array = i_ID or i2_ID
case ArgInfo::INAME: case ArgInfo::INAME:
pack_choice[iarg] = &DumpCustom::pack_custom; pack_choice[iarg] = &DumpCustom::pack_custom;
@ -1556,15 +1550,12 @@ int DumpCustom::parse_fields(int narg, char **arg)
error->all(FLERR,"Could not find custom per-atom property ID: {}", name); error->all(FLERR,"Could not find custom per-atom property ID: {}", name);
if (argindex[iarg] == 0) { if (argindex[iarg] == 0) {
if (flag || cols) if (flag || cols)
error->all(FLERR, error->all(FLERR,"Property integer vector {} for dump custom does not exist",name);
"Property integer vector for dump custom does not exist");
} else { } else {
if (flag || !cols) if (flag || !cols)
error->all(FLERR, error->all(FLERR,"Property integer array {} for dump custom does not exist",name);
"Property integer array for dump custom does not exist");
if (argindex[iarg] > atom->icols[n]) if (argindex[iarg] > atom->icols[n])
error->all(FLERR, error->all(FLERR,"Dump custom property array {} is accessed out-of-range",name);
"Dump custom property array is accessed out-of-range");
} }
field2index[iarg] = add_custom(name,0); field2index[iarg] = add_custom(name,0);
@ -1574,6 +1565,7 @@ int DumpCustom::parse_fields(int narg, char **arg)
default: default:
return iarg; return iarg;
break;
} }
} }
} }
@ -1667,13 +1659,9 @@ int DumpCustom::add_custom(const char *id, int flag)
if (strcmp(id,id_custom[icustom]) == 0) break; if (strcmp(id,id_custom[icustom]) == 0) break;
if (icustom < ncustom) return icustom; if (icustom < ncustom) return icustom;
id_custom = (char **) id_custom = (char **) memory->srealloc(id_custom,(ncustom+1)*sizeof(char *),"dump:id_custom");
memory->srealloc(id_custom,(ncustom+1)*sizeof(char *),"dump:id_custom"); custom = (int *) memory->srealloc(custom,(ncustom+1)*sizeof(int),"dump:custom");
custom_flag = (int *) memory->srealloc(custom_flag,(ncustom+1)*sizeof(int),"dump:custom_flag");
delete [] custom;
custom = new int[ncustom+1];
delete [] custom_flag;
custom_flag = new int[ncustom+1];
id_custom[ncustom] = utils::strdup(id); id_custom[ncustom] = utils::strdup(id);
custom_flag[ncustom] = flag; custom_flag[ncustom] = flag;
@ -1962,21 +1950,18 @@ int DumpCustom::modify_param(int narg, char **arg)
if (n < 0) if (n < 0)
error->all(FLERR,"Could not find custom per-atom property ID: {}", name); error->all(FLERR,"Could not find custom per-atom property ID: {}", name);
if (argindex[nfield+nthresh] == 0) { if (argindex[nfield+nthresh] == 0) {
if (flag || cols) if (!flag || cols)
error->all(FLERR, error->all(FLERR,"Property double vector for dump custom does not exist");
"Property double vector for dump custom does not exist");
thresh_array[nthresh] = DVEC; thresh_array[nthresh] = DVEC;
} else { } else {
if (flag || !cols) if (!flag || !cols)
error->all(FLERR, error->all(FLERR,"Property double array for dump custom does not exist");
"Property double array for dump custom does not exist");
if (argindex[nfield+nthresh] > atom->dcols[n]) if (argindex[nfield+nthresh] > atom->dcols[n])
error->all(FLERR, error->all(FLERR,"Dump custom property array is accessed out-of-range");
"Dump custom property array is accessed out-of-range");
thresh_array[nthresh] = DARRAY; thresh_array[nthresh] = DARRAY;
} }
field2index[nfield+nthresh] = add_custom(name,0); field2index[nfield+nthresh] = add_custom(name,thresh_array[nthresh]);
break; break;
// custom per atom integer vector or array // custom per atom integer vector or array
@ -1988,20 +1973,17 @@ int DumpCustom::modify_param(int narg, char **arg)
error->all(FLERR,"Could not find custom per-atom property ID: {}", name); error->all(FLERR,"Could not find custom per-atom property ID: {}", name);
if (argindex[nfield+nthresh] == 0) { if (argindex[nfield+nthresh] == 0) {
if (flag || cols) if (flag || cols)
error->all(FLERR, error->all(FLERR,"Property integer vector for dump custom does not exist");
"Property integer vector for dump custom does not exist");
thresh_array[nthresh] = IVEC; thresh_array[nthresh] = IVEC;
} else { } else {
if (flag || !cols) if (flag || !cols)
error->all(FLERR, error->all(FLERR,"Property integer array for dump custom does not exist");
"Property integer array for dump custom does not exist");
if (argindex[nfield+nthresh] > atom->icols[n]) if (argindex[nfield+nthresh] > atom->icols[n])
error->all(FLERR, error->all(FLERR,"Dump custom property array is accessed out-of-range");
"Dump custom property array is accessed out-of-range");
thresh_array[nthresh] = IARRAY; thresh_array[nthresh] = IARRAY;
} }
field2index[nfield+nthresh] = add_custom(name,0); field2index[nfield+nthresh] = add_custom(name,thresh_array[nthresh]);
break; break;
// no match // no match

View File

@ -299,6 +299,7 @@ void Info::command(int narg, char **arg)
if (has_png_support()) fputs("-DLAMMPS_PNG\n",out); if (has_png_support()) fputs("-DLAMMPS_PNG\n",out);
if (has_jpeg_support()) fputs("-DLAMMPS_JPEG\n",out); if (has_jpeg_support()) fputs("-DLAMMPS_JPEG\n",out);
if (has_ffmpeg_support()) fputs("-DLAMMPS_FFMPEG\n",out); if (has_ffmpeg_support()) fputs("-DLAMMPS_FFMPEG\n",out);
if (has_fft_single_support()) fputs("-DFFT_SINGLE\n",out);
if (has_exceptions()) fputs("-DLAMMPS_EXCEPTIONS\n",out); if (has_exceptions()) fputs("-DLAMMPS_EXCEPTIONS\n",out);
#if defined(LAMMPS_BIGBIG) #if defined(LAMMPS_BIGBIG)
@ -879,6 +880,8 @@ bool Info::is_available(const char *category, const char *name)
return has_jpeg_support(); return has_jpeg_support();
} else if (strcmp(name,"ffmpeg") == 0) { } else if (strcmp(name,"ffmpeg") == 0) {
return has_ffmpeg_support(); return has_ffmpeg_support();
} else if (strcmp(name,"fft_single") == 0) {
return has_fft_single_support();
} else if (strcmp(name,"exceptions") == 0) { } else if (strcmp(name,"exceptions") == 0) {
return has_exceptions(); return has_exceptions();
} }
@ -1127,6 +1130,14 @@ bool Info::has_ffmpeg_support() {
#endif #endif
} }
bool Info::has_fft_single_support() {
#ifdef FFT_SINGLE
return true;
#else
return false;
#endif
}
bool Info::has_exceptions() { bool Info::has_exceptions() {
#ifdef LAMMPS_EXCEPTIONS #ifdef LAMMPS_EXCEPTIONS
return true; return true;

View File

@ -42,6 +42,7 @@ class Info : public Command {
static bool has_png_support(); static bool has_png_support();
static bool has_jpeg_support(); static bool has_jpeg_support();
static bool has_ffmpeg_support(); static bool has_ffmpeg_support();
static bool has_fft_single_support();
static bool has_exceptions(); static bool has_exceptions();
static bool has_package(const std::string &); static bool has_package(const std::string &);
static bool has_accelerator_feature(const std::string &, const std::string &, static bool has_accelerator_feature(const std::string &, const std::string &,

View File

@ -51,6 +51,10 @@
#include "update.h" #include "update.h"
#include "version.h" #include "version.h"
#if defined(LMP_PLUGIN)
#include "plugin.h"
#endif
#include <cctype> #include <cctype>
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
@ -59,6 +63,12 @@
#include "lmpinstalledpkgs.h" #include "lmpinstalledpkgs.h"
#include "lmpgitversion.h" #include "lmpgitversion.h"
#if defined(LAMMPS_UPDATE)
#define UPDATE_STRING " - " LAMMPS_UPDATE
#else
#define UPDATE_STRING ""
#endif
static void print_style(FILE *fp, const char *str, int &pos); static void print_style(FILE *fp, const char *str, int &pos);
struct LAMMPS_NS::package_styles_lists { struct LAMMPS_NS::package_styles_lists {
@ -509,7 +519,7 @@ LAMMPS::LAMMPS(int narg, char **arg, MPI_Comm communicator) :
} }
if ((universe->me == 0) && !helpflag) if ((universe->me == 0) && !helpflag)
utils::logmesg(this,fmt::format("LAMMPS ({})\n",version)); utils::logmesg(this,fmt::format("LAMMPS ({}{})\n",version,UPDATE_STRING));
// universe is one or more worlds, as setup by partition switch // universe is one or more worlds, as setup by partition switch
// split universe communicator into separate world communicators // split universe communicator into separate world communicators
@ -903,6 +913,10 @@ void LAMMPS::init()
void LAMMPS::destroy() void LAMMPS::destroy()
{ {
// must wipe out all plugins first, if configured
#if defined(LMP_PLUGIN)
plugin_clear(this);
#endif
delete update; delete update;
update = nullptr; update = nullptr;
@ -1137,10 +1151,10 @@ void _noopt LAMMPS::help()
if (has_git_info) { if (has_git_info) {
fprintf(fp,"\nLarge-scale Atomic/Molecular Massively Parallel Simulator - " fprintf(fp,"\nLarge-scale Atomic/Molecular Massively Parallel Simulator - "
LAMMPS_VERSION "\nGit info (%s / %s)\n\n",git_branch, git_descriptor); LAMMPS_VERSION UPDATE_STRING "\nGit info (%s / %s)\n\n",git_branch, git_descriptor);
} else { } else {
fprintf(fp,"\nLarge-scale Atomic/Molecular Massively Parallel Simulator - " fprintf(fp,"\nLarge-scale Atomic/Molecular Massively Parallel Simulator - "
LAMMPS_VERSION "\n\n"); LAMMPS_VERSION UPDATE_STRING "\n\n");
} }
fprintf(fp, fprintf(fp,
"Usage example: %s -var t 300 -echo screen -in in.alloy\n\n" "Usage example: %s -var t 300 -echo screen -in in.alloy\n\n"
@ -1348,6 +1362,7 @@ void LAMMPS::print_config(FILE *fp)
if (Info::has_png_support()) fputs("-DLAMMPS_PNG\n",fp); if (Info::has_png_support()) fputs("-DLAMMPS_PNG\n",fp);
if (Info::has_jpeg_support()) fputs("-DLAMMPS_JPEG\n",fp); if (Info::has_jpeg_support()) fputs("-DLAMMPS_JPEG\n",fp);
if (Info::has_ffmpeg_support()) fputs("-DLAMMPS_FFMPEG\n",fp); if (Info::has_ffmpeg_support()) fputs("-DLAMMPS_FFMPEG\n",fp);
if (Info::has_fft_single_support()) fputs("-DFFT_SINGLE\n",fp);
if (Info::has_exceptions()) fputs("-DLAMMPS_EXCEPTIONS\n",fp); if (Info::has_exceptions()) fputs("-DLAMMPS_EXCEPTIONS\n",fp);
#if defined(LAMMPS_BIGBIG) #if defined(LAMMPS_BIGBIG)
fputs("-DLAMMPS_BIGBIG\n",fp); fputs("-DLAMMPS_BIGBIG\n",fp);

View File

@ -661,7 +661,10 @@ int utils::expand_args(const char *file, int line, int narg, char **arg, int mod
} }
for (int index = nlo; index <= nhi; index++) { for (int index = nlo; index <= nhi; index++) {
earg[newarg] = utils::strdup(fmt::format("{}2_{}[{}]{}", word[0], id, index, tail)); if (word[1] == '2')
earg[newarg] = utils::strdup(fmt::format("{}2_{}[{}]{}", word[0], id, index, tail));
else
earg[newarg] = utils::strdup(fmt::format("{}_{}[{}]{}", word[0], id, index, tail));
newarg++; newarg++;
} }
} else { } else {

View File

@ -8,7 +8,7 @@ add_test(NAME RunLammps
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
set_tests_properties(RunLammps PROPERTIES set_tests_properties(RunLammps PROPERTIES
ENVIRONMENT "TSAN_OPTIONS=ignore_noninstrumented_modules=1;HWLOC_HIDE_ERRORS=1" ENVIRONMENT "TSAN_OPTIONS=ignore_noninstrumented_modules=1;HWLOC_HIDE_ERRORS=1"
PASS_REGULAR_EXPRESSION "^LAMMPS \\([0-9]+ [A-Za-z]+ 2[0-9][0-9][0-9]\\)") PASS_REGULAR_EXPRESSION "LAMMPS \\([0-9]+ [A-Za-z]+ 2[0-9][0-9][0-9]( - Update [0-9]+)?\\)")
# check if the compiled executable will print the help message # check if the compiled executable will print the help message
add_test(NAME HelpMessage add_test(NAME HelpMessage

View File

@ -858,6 +858,13 @@ TEST(PairStyle, gpu)
if (!Info::has_gpu_device()) GTEST_SKIP(); if (!Info::has_gpu_device()) GTEST_SKIP();
if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP(); if (test_config.skip_tests.count(test_info_->name())) GTEST_SKIP();
// when testing PPPM styles with GPUs and GPU support is compiled with single precision
// we also must have single precision FFTs; otherwise skip since the test would abort
if (utils::strmatch(test_config.basename, ".*pppm.*") &&
(Info::has_accelerator_feature("GPU", "precision", "single")) &&
(!Info::has_fft_single_support()))
GTEST_SKIP();
const char *args_neigh[] = {"PairStyle", "-log", "none", "-echo", const char *args_neigh[] = {"PairStyle", "-log", "none", "-echo",
"screen", "-nocite", "-sf", "gpu"}; "screen", "-nocite", "-sf", "gpu"};
const char *args_noneigh[] = {"PairStyle", "-log", "none", "-echo", "screen", "-nocite", "-sf", const char *args_noneigh[] = {"PairStyle", "-log", "none", "-echo", "screen", "-nocite", "-sf",

View File

@ -1,7 +1,7 @@
--- ---
lammps_version: 10 Feb 2021 lammps_version: 10 Feb 2021
date_generated: Fri Feb 26 23:08:42 2021 date_generated: Fri Feb 26 23:08:42 2021
epsilon: 1.5e-13 epsilon: 2.0e-13
prerequisites: ! | prerequisites: ! |
atom full atom full
pair coul/long pair coul/long