Merge pull request #521 from pastewka/17_dump_nc

Updated NetCDF dump style (dump netcdf)
This commit is contained in:
sjplimp 2017-06-15 08:47:29 -06:00 committed by GitHub
commit 30177c4eae
9 changed files with 227 additions and 586 deletions

View File

@ -16,7 +16,8 @@ dump-ID = ID of dump to modify :ulb,l
one or more keyword/value pairs may be appended :l
these keywords apply to various dump styles :l
keyword = {append} or {buffer} or {element} or {every} or {fileper} or {first} or {flush} or {format} or {image} or {label} or {nfile} or {pad} or {precision} or {region} or {scale} or {sort} or {thresh} or {unwrap} :l
{append} arg = {yes} or {no}
{append} arg = {yes} or {no} or {at} N
N = index of frame written upon first dump
{buffer} arg = {yes} or {no}
{element} args = E1 E2 ... EN, where N = # of atom types
E1,...,EN = element name, e.g. C or Fe or Ga
@ -41,6 +42,7 @@ keyword = {append} or {buffer} or {element} or {every} or {fileper} or {first} o
{region} arg = region-ID or "none"
{scale} arg = {yes} or {no}
{sfactor} arg = coordinate scaling factor (> 0.0)
{thermo} arg = {yes} or {no}
{tfactor} arg = time scaling factor (> 0.0)
{sort} arg = {off} or {id} or N or -N
off = no sorting of per-atom lines within a snapshot
@ -139,12 +141,13 @@ and {dcd}. It also applies only to text output files, not to binary
or gzipped or image/movie files. If specified as {yes}, then dump
snapshots are appended to the end of an existing dump file. If
specified as {no}, then a new dump file will be created which will
overwrite an existing file with the same name. This keyword can only
take effect if the dump_modify command is used after the
"dump"_dump.html command, but before the first command that causes
dump snapshots to be output, e.g. a "run"_run.html or
"minimize"_minimize.html command. Once the dump file has been opened,
this keyword has no further effect.
overwrite an existing file with the same name. If the {at} option is present
({netcdf} only), then the frame to append to can be specified. Negative values
are counted from the end of the file. This keyword can only take effect if the
dump_modify command is used after the "dump"_dump.html command, but before the
first command that causes dump snapshots to be output, e.g. a "run"_run.html or
"minimize"_minimize.html command. Once the dump file has been opened, this
keyword has no further effect.
:line
@ -413,6 +416,13 @@ most effective when the typical magnitude of position data is between
:line
The {thermo} keyword ({netcdf} only) triggers writing of "thermo"_thermo.html
information to the dump file alongside per-atom data. The data included in the
dump file is identical to the data specified by
"thermo_style"_thermo_style.html.
:line
The {region} keyword only applies to the dump {custom}, {cfg},
{image}, and {movie} styles. If specified, only atoms in the region
will be written to the dump file or included in the image/movie. Only

View File

@ -24,7 +24,7 @@ args = list of atom attributes, same as for "dump_style custom"_dump.html :l,ule
[Examples:]
dump 1 all netcdf 100 traj.nc type x y z vx vy vz
dump_modify 1 append yes at -1 global c_thermo_pe c_thermo_temp c_thermo_press
dump_modify 1 append yes at -1 thermo yes
dump 1 all netcdf/mpiio 1000 traj.nc id type x y z :pre
[Description:]
@ -44,7 +44,7 @@ rank.
NetCDF files can be directly visualized via the following tools:
Ovito (http://www.ovito.org/). Ovito supports the AMBER convention and
all of the above extensions. :ule,b
all extensions of this dump style. :ule,b
VMD (http://www.ks.uiuc.edu/Research/vmd/). :l
@ -52,15 +52,9 @@ AtomEye (http://www.libatoms.org/). The libAtoms version of AtomEye
contains a NetCDF reader that is not present in the standard
distribution of AtomEye. :l,ule
In addition to per-atom data, global data can be included in the dump
file, which are the kinds of values output by the
"thermo_style"_thermo_style.html command . See "Section howto
6.15"_Section_howto.html#howto_15 for an explanation of per-atom
versus global data. The global output written into the dump file can
be from computes, fixes, or variables, by prefixing the compute/fix ID
or variable name with "c_" or "f_" or "v_" respectively, as in the
example above. These global values are specified via the "dump_modify
global"_dump_modify.html command.
In addition to per-atom data, "thermo"_thermo.html data can be included in the
dump file. The data included in the dump file is identical to the data specified
by "thermo_style"_thermo_style.html.
:link(netcdf-home,http://www.unidata.ucar.edu/software/netcdf/)
:link(pnetcdf-home,http://trac.mcs.anl.gov/projects/parallel-netcdf/)

View File

@ -1,9 +1,9 @@
USER-NETCDF
============
This package provides the netcf and netcdf/mpiio dump styles.
See the doc page for dump nc or dump nc/mpiio command for how to use them.
Compiling these dump styles requires having the netCDF library installed
This package provides the netcdf and netcdf/mpiio dump styles.
See the doc page for dump netcdf or dump netcdf/mpiio command for how to use
them. Compiling these dump styles requires having the netCDF library installed
on your system. See lib/netcdf/README for additional details.
PACKAGE DESCRIPTION
@ -29,11 +29,11 @@ NetCDF files can be directly visualized with the following tools:
a NetCDF reader that is not present in the standard distribution of AtomEye.
The person who created these files is Lars Pastewka at
Karlsruhe Institute of Technology (lars.pastewka@kit.edu).
the University of Freiburg (lars.pastewka@imtek.uni-freiburg.de).
Contact him directly if you have questions.
Lars Pastewka
Institute for Applied Materials (IAM)
Karlsruhe Institute of Technology (KIT)
Kaiserstrasse 12, 76131 Karlsruhe
e-mail: lars.pastewka@kit.edu
University of Freiburg
Department of Microsystems Engineering
Georges-Köhler-Allee 103, 79110 Freiburg, Germany
e-mail: lars.pastewka@imtek.uni-freiburg.de

View File

@ -1,25 +1,3 @@
/* ======================================================================
LAMMPS NetCDF dump style
https://github.com/pastewka/lammps-netcdf
Lars Pastewka, lars.pastewka@kit.edu
Copyright (2011-2013) Fraunhofer IWM
Copyright (2014) Karlsruhe Institute of Technology
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
====================================================================== */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
@ -33,6 +11,10 @@
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Lars Pastewka (University of Freiburg)
------------------------------------------------------------------------- */
#if defined(LMP_HAS_NETCDF)
#include <unistd.h>
@ -55,11 +37,13 @@
#include "universe.h"
#include "variable.h"
#include "force.h"
#include "output.h"
#include "thermo.h"
using namespace LAMMPS_NS;
using namespace MathConst;
enum{INT,DOUBLE}; // same as in dump_custom.cpp
enum{INT,FLOAT,BIGINT}; // same as in thermo.cpp
const char NC_FRAME_STR[] = "frame";
const char NC_SPATIAL_STR[] = "spatial";
@ -208,15 +192,15 @@ DumpNetCDF::DumpNetCDF(LAMMPS *lmp, int narg, char **arg) :
perat[inc].field[idim] = i;
}
n_perframe = 0;
perframe = NULL;
n_buffer = 0;
int_buffer = NULL;
double_buffer = NULL;
double_precision = false;
thermo = false;
thermovar = NULL;
framei = 0;
}
@ -227,8 +211,7 @@ DumpNetCDF::~DumpNetCDF()
closefile();
delete [] perat;
if (n_perframe > 0)
delete [] perframe;
if (thermovar) delete [] thermovar;
if (int_buffer) memory->sfree(int_buffer);
if (double_buffer) memory->sfree(double_buffer);
@ -238,6 +221,11 @@ DumpNetCDF::~DumpNetCDF()
void DumpNetCDF::openfile()
{
if (thermo && !singlefile_opened) {
if (thermovar) delete [] thermovar;
thermovar = new int[output->thermo->nfield];
}
// now the computes and fixes have been initialized, so we can query
// for the size of vector quantities
for (int i = 0; i < n_perat; i++) {
@ -289,30 +277,30 @@ void DumpNetCDF::openfile()
// dimensions
NCERRX( nc_inq_dimid(ncid, NC_FRAME_STR, &frame_dim), NC_FRAME_STR );
NCERRX( nc_inq_dimid(ncid, NC_SPATIAL_STR, &spatial_dim),
NC_SPATIAL_STR );
NC_SPATIAL_STR );
NCERRX( nc_inq_dimid(ncid, NC_VOIGT_STR, &Voigt_dim), NC_VOIGT_STR );
NCERRX( nc_inq_dimid(ncid, NC_ATOM_STR, &atom_dim), NC_ATOM_STR );
NCERRX( nc_inq_dimid(ncid, NC_CELL_SPATIAL_STR, &cell_spatial_dim),
NC_CELL_SPATIAL_STR );
NC_CELL_SPATIAL_STR );
NCERRX( nc_inq_dimid(ncid, NC_CELL_ANGULAR_STR, &cell_angular_dim),
NC_CELL_ANGULAR_STR );
NC_CELL_ANGULAR_STR );
NCERRX( nc_inq_dimid(ncid, NC_LABEL_STR, &label_dim), NC_LABEL_STR );
// default variables
NCERRX( nc_inq_varid(ncid, NC_SPATIAL_STR, &spatial_var),
NC_SPATIAL_STR );
NC_SPATIAL_STR );
NCERRX( nc_inq_varid(ncid, NC_CELL_SPATIAL_STR, &cell_spatial_var),
NC_CELL_SPATIAL_STR);
NC_CELL_SPATIAL_STR);
NCERRX( nc_inq_varid(ncid, NC_CELL_ANGULAR_STR, &cell_angular_var),
NC_CELL_ANGULAR_STR);
NC_CELL_ANGULAR_STR);
NCERRX( nc_inq_varid(ncid, NC_TIME_STR, &time_var), NC_TIME_STR );
NCERRX( nc_inq_varid(ncid, NC_CELL_ORIGIN_STR, &cell_origin_var),
NC_CELL_ORIGIN_STR );
NC_CELL_ORIGIN_STR );
NCERRX( nc_inq_varid(ncid, NC_CELL_LENGTHS_STR, &cell_lengths_var),
NC_CELL_LENGTHS_STR);
NC_CELL_LENGTHS_STR);
NCERRX( nc_inq_varid(ncid, NC_CELL_ANGLES_STR, &cell_angles_var),
NC_CELL_ANGLES_STR);
NC_CELL_ANGLES_STR);
// variables specified in the input file
for (int i = 0; i < n_perat; i++) {
@ -334,9 +322,12 @@ void DumpNetCDF::openfile()
}
// perframe variables
for (int i = 0; i < n_perframe; i++) {
NCERRX( nc_inq_varid(ncid, perframe[i].name, &perframe[i].var),
perframe[i].name );
if (thermo) {
Thermo *th = output->thermo;
for (int i = 0; i < th->nfield; i++) {
NCERRX( nc_inq_varid(ncid, th->keyword[i], &thermovar[i]),
th->keyword[i] );
}
}
size_t nframes;
@ -354,49 +345,49 @@ void DumpNetCDF::openfile()
if (singlefile_opened) return;
singlefile_opened = 1;
NCERRX( nc_create(filename, NC_64BIT_OFFSET, &ncid),
filename );
NCERRX( nc_create(filename, NC_64BIT_DATA, &ncid),
filename );
// dimensions
NCERRX( nc_def_dim(ncid, NC_FRAME_STR, NC_UNLIMITED, &frame_dim),
NC_FRAME_STR );
NC_FRAME_STR );
NCERRX( nc_def_dim(ncid, NC_SPATIAL_STR, 3, &spatial_dim),
NC_SPATIAL_STR );
NC_SPATIAL_STR );
NCERRX( nc_def_dim(ncid, NC_VOIGT_STR, 6, &Voigt_dim),
NC_VOIGT_STR );
NC_VOIGT_STR );
NCERRX( nc_def_dim(ncid, NC_ATOM_STR, ntotalgr, &atom_dim),
NC_ATOM_STR );
NC_ATOM_STR );
NCERRX( nc_def_dim(ncid, NC_CELL_SPATIAL_STR, 3, &cell_spatial_dim),
NC_CELL_SPATIAL_STR );
NC_CELL_SPATIAL_STR );
NCERRX( nc_def_dim(ncid, NC_CELL_ANGULAR_STR, 3, &cell_angular_dim),
NC_CELL_ANGULAR_STR );
NC_CELL_ANGULAR_STR );
NCERRX( nc_def_dim(ncid, NC_LABEL_STR, 10, &label_dim),
NC_LABEL_STR );
NC_LABEL_STR );
// default variables
dims[0] = spatial_dim;
NCERRX( nc_def_var(ncid, NC_SPATIAL_STR, NC_CHAR, 1, dims, &spatial_var),
NC_SPATIAL_STR );
NC_SPATIAL_STR );
NCERRX( nc_def_var(ncid, NC_CELL_SPATIAL_STR, NC_CHAR, 1, dims,
&cell_spatial_var), NC_CELL_SPATIAL_STR );
&cell_spatial_var), NC_CELL_SPATIAL_STR );
dims[0] = spatial_dim;
dims[1] = label_dim;
NCERRX( nc_def_var(ncid, NC_CELL_ANGULAR_STR, NC_CHAR, 2, dims,
&cell_angular_var), NC_CELL_ANGULAR_STR );
&cell_angular_var), NC_CELL_ANGULAR_STR );
dims[0] = frame_dim;
NCERRX( nc_def_var(ncid, NC_TIME_STR, NC_DOUBLE, 1, dims, &time_var),
NC_TIME_STR);
NC_TIME_STR);
dims[0] = frame_dim;
dims[1] = cell_spatial_dim;
NCERRX( nc_def_var(ncid, NC_CELL_ORIGIN_STR, NC_DOUBLE, 2, dims,
&cell_origin_var), NC_CELL_ORIGIN_STR );
&cell_origin_var), NC_CELL_ORIGIN_STR );
NCERRX( nc_def_var(ncid, NC_CELL_LENGTHS_STR, NC_DOUBLE, 2, dims,
&cell_lengths_var), NC_CELL_LENGTHS_STR );
&cell_lengths_var), NC_CELL_LENGTHS_STR );
dims[0] = frame_dim;
dims[1] = cell_angular_dim;
NCERRX( nc_def_var(ncid, NC_CELL_ANGLES_STR, NC_DOUBLE, 2, dims,
&cell_angles_var), NC_CELL_ANGLES_STR );
&cell_angles_var), NC_CELL_ANGLES_STR );
// variables specified in the input file
dims[0] = frame_dim;
@ -423,17 +414,17 @@ void DumpNetCDF::openfile()
// this is a tensor in Voigt notation
dims[2] = Voigt_dim;
NCERRX( nc_def_var(ncid, perat[i].name, xtype, 2, dims+1,
&perat[i].var), perat[i].name );
&perat[i].var), perat[i].name );
}
else if (perat[i].dims == 3) {
// this is a vector, we need to store x-, y- and z-coordinates
dims[2] = spatial_dim;
NCERRX( nc_def_var(ncid, perat[i].name, xtype, 2, dims+1,
&perat[i].var), perat[i].name );
&perat[i].var), perat[i].name );
}
else if (perat[i].dims == 1) {
NCERRX( nc_def_var(ncid, perat[i].name, xtype, 1, dims+1,
&perat[i].var), perat[i].name );
&perat[i].var), perat[i].name );
}
else {
char errstr[1024];
@ -448,17 +439,17 @@ void DumpNetCDF::openfile()
// this is a tensor in Voigt notation
dims[2] = Voigt_dim;
NCERRX( nc_def_var(ncid, perat[i].name, xtype, 3, dims,
&perat[i].var), perat[i].name );
&perat[i].var), perat[i].name );
}
else if (perat[i].dims == 3) {
// this is a vector, we need to store x-, y- and z-coordinates
dims[2] = spatial_dim;
NCERRX( nc_def_var(ncid, perat[i].name, xtype, 3, dims,
&perat[i].var), perat[i].name );
&perat[i].var), perat[i].name );
}
else if (perat[i].dims == 1) {
NCERRX( nc_def_var(ncid, perat[i].name, xtype, 2, dims,
&perat[i].var), perat[i].name );
&perat[i].var), perat[i].name );
}
else {
char errstr[1024];
@ -471,14 +462,21 @@ void DumpNetCDF::openfile()
}
// perframe variables
for (int i = 0; i < n_perframe; i++) {
if (perframe[i].type == THIS_IS_A_BIGINT) {
NCERRX( nc_def_var(ncid, perframe[i].name, NC_LONG, 1, dims,
&perframe[i].var), perframe[i].name );
}
else {
NCERRX( nc_def_var(ncid, perframe[i].name, NC_DOUBLE, 1, dims,
&perframe[i].var), perframe[i].name );
if (thermo) {
Thermo *th = output->thermo;
for (int i = 0; i < th->nfield; i++) {
if (th->vtype[i] == FLOAT) {
NCERRX( nc_def_var(ncid, th->keyword[i], NC_DOUBLE, 1, dims,
&thermovar[i]), th->keyword[i] );
}
else if (th->vtype[i] == INT) {
NCERRX( nc_def_var(ncid, th->keyword[i], NC_INT, 1, dims,
&thermovar[i]), th->keyword[i] );
}
else if (th->vtype[i] == BIGINT) {
NCERRX( nc_def_var(ncid, th->keyword[i], NC_LONG, 1, dims,
&thermovar[i]), th->keyword[i] );
}
}
}
@ -622,46 +620,30 @@ void DumpNetCDF::write()
start[0] = framei-1;
start[1] = 0;
for (int i = 0; i < n_perframe; i++) {
if (perframe[i].type == THIS_IS_A_BIGINT) {
bigint data;
(this->*perframe[i].compute)((void*) &data);
if (filewriter)
if (thermo) {
Thermo *th = output->thermo;
for (int i = 0; i < th->nfield; i++) {
th->call_vfunc(i);
if (filewriter) {
if (th->vtype[i] == FLOAT) {
NCERRX( nc_put_var1_double(ncid, thermovar[i], start,
&th->dvalue),
th->keyword[i] );
}
else if (th->vtype[i] == INT) {
NCERRX( nc_put_var1_int(ncid, thermovar[i], start, &th->ivalue),
th->keyword[i] );
}
else if (th->vtype[i] == BIGINT) {
#if defined(LAMMPS_SMALLBIG) || defined(LAMMPS_BIGBIG)
NCERR( nc_put_var1_long(ncid, perframe[i].var, start, &data) );
NCERRX( nc_put_var1_long(ncid, thermovar[i], start, &th->bivalue),
th->keyword[i] );
#else
NCERR( nc_put_var1_int(ncid, perframe[i].var, start, &data) );
NCERRX( nc_put_var1_int(ncid, thermovar[i], start, &th->bivalue),
th->keyword[i] );
#endif
}
else {
double data;
int j = perframe[i].index;
int idim = perframe[i].dim;
if (perframe[i].type == THIS_IS_A_COMPUTE) {
if (idim >= 0) {
modify->compute[j]->compute_vector();
data = modify->compute[j]->vector[idim];
}
else
data = modify->compute[j]->compute_scalar();
}
else if (perframe[i].type == THIS_IS_A_FIX) {
if (idim >= 0) {
data = modify->fix[j]->compute_vector(idim);
}
else
data = modify->fix[j]->compute_scalar();
}
else if (perframe[i].type == THIS_IS_A_VARIABLE) {
j = input->variable->find(perframe[i].id);
data = input->variable->compute_equal(j);
}
if (filewriter)
NCERR( nc_put_var1_double(ncid, perframe[i].var, start, &data) );
}
}
@ -908,126 +890,19 @@ int DumpNetCDF::modify_param(int narg, char **arg)
iarg++;
return 2;
}
else if (strcmp(arg[iarg],"global") == 0) {
// "perframe" quantities, i.e. not per-atom stuff
else if (strcmp(arg[iarg],"thermo") == 0) {
iarg++;
n_perframe = narg-iarg;
perframe = new nc_perframe_t[n_perframe];
for (int i = 0; iarg < narg; iarg++, i++) {
int n;
char *suffix=NULL;
if (!strcmp(arg[iarg],"step")) {
perframe[i].type = THIS_IS_A_BIGINT;
perframe[i].compute = &DumpNetCDF::compute_step;
strcpy(perframe[i].name, arg[iarg]);
}
else if (!strcmp(arg[iarg],"elapsed")) {
perframe[i].type = THIS_IS_A_BIGINT;
perframe[i].compute = &DumpNetCDF::compute_elapsed;
strcpy(perframe[i].name, arg[iarg]);
}
else if (!strcmp(arg[iarg],"elaplong")) {
perframe[i].type = THIS_IS_A_BIGINT;
perframe[i].compute = &DumpNetCDF::compute_elapsed_long;
strcpy(perframe[i].name, arg[iarg]);
}
else {
n = strlen(arg[iarg]);
if (n > 2) {
suffix = new char[n-1];
strcpy(suffix, arg[iarg]+2);
}
else {
char errstr[1024];
sprintf(errstr, "perframe quantity '%s' must thermo quantity or "
"compute, fix or variable", arg[iarg]);
error->all(FLERR,errstr);
}
if (!strncmp(arg[iarg], "c_", 2)) {
int idim = -1;
char *ptr = strchr(suffix, '[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
error->all(FLERR,"Missing ']' in dump modify command");
*ptr = '\0';
idim = ptr[1] - '1';
}
n = modify->find_compute(suffix);
if (n < 0)
error->all(FLERR,"Could not find dump modify compute ID");
if (modify->compute[n]->peratom_flag != 0)
error->all(FLERR,"Dump modify compute ID computes per-atom info");
if (idim >= 0 && modify->compute[n]->vector_flag == 0)
error->all(FLERR,"Dump modify compute ID does not compute vector");
if (idim < 0 && modify->compute[n]->scalar_flag == 0)
error->all(FLERR,"Dump modify compute ID does not compute scalar");
perframe[i].type = THIS_IS_A_COMPUTE;
perframe[i].dim = idim;
perframe[i].index = n;
strcpy(perframe[i].name, arg[iarg]);
}
else if (!strncmp(arg[iarg], "f_", 2)) {
int idim = -1;
char *ptr = strchr(suffix, '[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
error->all(FLERR,"Missing ']' in dump modify command");
*ptr = '\0';
idim = ptr[1] - '1';
}
n = modify->find_fix(suffix);
if (n < 0)
error->all(FLERR,"Could not find dump modify fix ID");
if (modify->fix[n]->peratom_flag != 0)
error->all(FLERR,"Dump modify fix ID computes per-atom info");
if (idim >= 0 && modify->fix[n]->vector_flag == 0)
error->all(FLERR,"Dump modify fix ID does not compute vector");
if (idim < 0 && modify->fix[n]->scalar_flag == 0)
error->all(FLERR,"Dump modify fix ID does not compute vector");
perframe[i].type = THIS_IS_A_FIX;
perframe[i].dim = idim;
perframe[i].index = n;
strcpy(perframe[i].name, arg[iarg]);
}
else if (!strncmp(arg[iarg], "v_", 2)) {
n = input->variable->find(suffix);
if (n < 0)
error->all(FLERR,"Could not find dump modify variable ID");
if (!input->variable->equalstyle(n))
error->all(FLERR,"Dump modify variable must be of style equal");
perframe[i].type = THIS_IS_A_VARIABLE;
perframe[i].dim = 1;
perframe[i].index = n;
strcpy(perframe[i].name, arg[iarg]);
strcpy(perframe[i].id, suffix);
}
else {
char errstr[1024];
sprintf(errstr, "perframe quantity '%s' must be compute, fix or "
"variable", arg[iarg]);
error->all(FLERR,errstr);
}
delete [] suffix;
}
if (iarg >= narg)
error->all(FLERR,"expected 'yes' or 'no' after 'thermo' keyword.");
if (strcmp(arg[iarg],"yes") == 0) {
thermo = true;
}
return narg;
else if (strcmp(arg[iarg],"no") == 0) {
thermo = false;
}
else error->all(FLERR,"expected 'yes' or 'no' after 'thermo' keyword.");
iarg++;
return 2;
} else return 0;
}
@ -1101,41 +976,14 @@ void DumpNetCDF::ncerr(int err, const char *descr, int line)
char errstr[1024];
if (descr) {
sprintf(errstr, "NetCDF failed with error '%s' (while accessing '%s') "
" in line %i of %s.", nc_strerror(err), descr, line, __FILE__);
" in line %i of %s.", nc_strerror(err), descr, line, __FILE__);
}
else {
sprintf(errstr, "NetCDF failed with error '%s' in line %i of %s.",
nc_strerror(err), line, __FILE__);
nc_strerror(err), line, __FILE__);
}
error->one(FLERR,errstr);
}
}
/* ----------------------------------------------------------------------
one method for every keyword thermo can output
called by compute() or evaluate_keyword()
compute will have already been called
set ivalue/dvalue/bivalue if value is int/double/bigint
customize a new keyword by adding a method
------------------------------------------------------------------------- */
void DumpNetCDF::compute_step(void *r)
{
*((bigint *) r) = update->ntimestep;
}
/* ---------------------------------------------------------------------- */
void DumpNetCDF::compute_elapsed(void *r)
{
*((bigint *) r) = update->ntimestep - update->firststep;
}
/* ---------------------------------------------------------------------- */
void DumpNetCDF::compute_elapsed_long(void *r)
{
*((bigint *) r) = update->ntimestep - update->beginstep;
}
#endif /* defined(LMP_HAS_NETCDF) */

View File

@ -1,25 +1,3 @@
/* ======================================================================
LAMMPS NetCDF dump style
https://github.com/pastewka/lammps-netcdf
Lars Pastewka, lars.pastewka@kit.edu
Copyright (2011-2013) Fraunhofer IWM
Copyright (2014) Karlsruhe Institute of Technology
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
====================================================================== */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
@ -33,6 +11,10 @@
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Lars Pastewka (University of Freiburg)
------------------------------------------------------------------------- */
#if defined(LMP_HAS_NETCDF)
#ifdef DUMP_CLASS
@ -69,22 +51,6 @@ class DumpNetCDF : public DumpCustom {
int ndumped; // number of enties written for this prop.
};
typedef void (DumpNetCDF::*funcptr_t)(void *);
// per-frame quantities (variables, fixes or computes)
struct nc_perframe_t {
char name[NC_FIELD_NAME_MAX]; // field name
int var; // NetCDF variable
int type; // variable, fix, compute or callback
int index; // index in fix/compute list
funcptr_t compute; // compute function
int dim; // dimension
char id[NC_FIELD_NAME_MAX]; // variable id
bigint bigint_data; // actual data
double double_data; // actual data
};
int framei; // current frame index
int blocki; // current block index
int ndata; // number of data blocks to expect
@ -94,10 +60,10 @@ class DumpNetCDF : public DumpCustom {
int n_perat; // # of netcdf per-atom properties
nc_perat_t *perat; // per-atom properties
int n_perframe; // # of global netcdf (not per-atom) fix props
nc_perframe_t *perframe; // global properties
int *thermovar; // NetCDF variables for thermo output
bool double_precision; // write everything as double precision
bool thermo; // write thermo output to netcdf file
bigint n_buffer; // size of buffer
int *int_buffer; // buffer for passing data to netcdf
@ -131,10 +97,6 @@ class DumpNetCDF : public DumpCustom {
virtual int modify_param(int, char **);
void ncerr(int, const char *, int);
void compute_step(void *);
void compute_elapsed(void *);
void compute_elapsed_long(void *);
};
}

View File

@ -1,25 +1,3 @@
/* ======================================================================
LAMMPS NetCDF dump style
https://github.com/pastewka/lammps-netcdf
Lars Pastewka, lars.pastewka@kit.edu
Copyright (2011-2013) Fraunhofer IWM
Copyright (2014) Karlsruhe Institute of Technology
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
====================================================================== */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
@ -33,6 +11,10 @@
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Lars Pastewka (University of Freiburg)
------------------------------------------------------------------------- */
#if defined(LMP_HAS_PNETCDF)
#include <unistd.h>
@ -55,11 +37,13 @@
#include "universe.h"
#include "variable.h"
#include "force.h"
#include "output.h"
#include "thermo.h"
using namespace LAMMPS_NS;
using namespace MathConst;
enum{INT,DOUBLE}; // same as in dump_custom.cpp
enum{INT,FLOAT,BIGINT}; // same as in thermo.cpp
const char NC_FRAME_STR[] = "frame";
const char NC_SPATIAL_STR[] = "spatial";
@ -201,15 +185,15 @@ DumpNetCDFMPIIO::DumpNetCDFMPIIO(LAMMPS *lmp, int narg, char **arg) :
perat[inc].field[idim] = i;
}
n_perframe = 0;
perframe = NULL;
n_buffer = 0;
int_buffer = NULL;
double_buffer = NULL;
double_precision = false;
thermo = false;
thermovar = NULL;
framei = 0;
}
@ -220,8 +204,7 @@ DumpNetCDFMPIIO::~DumpNetCDFMPIIO()
closefile();
delete [] perat;
if (n_perframe > 0)
delete [] perframe;
if (thermovar) delete [] thermovar;
if (int_buffer) memory->sfree(int_buffer);
if (double_buffer) memory->sfree(double_buffer);
@ -231,6 +214,11 @@ DumpNetCDFMPIIO::~DumpNetCDFMPIIO()
void DumpNetCDFMPIIO::openfile()
{
if (thermo && !singlefile_opened) {
if (thermovar) delete [] thermovar;
thermovar = new int[output->thermo->nfield];
}
// now the computes and fixes have been initialized, so we can query
// for the size of vector quantities
for (int i = 0; i < n_perat; i++) {
@ -330,9 +318,12 @@ void DumpNetCDFMPIIO::openfile()
}
// perframe variables
for (int i = 0; i < n_perframe; i++) {
NCERRX( ncmpi_inq_varid(ncid, perframe[i].name, &perframe[i].var),
perframe[i].name );
if (thermo) {
Thermo *th = output->thermo;
for (int i = 0; i < th->nfield; i++) {
NCERRX( ncmpi_inq_varid(ncid, th->keyword[i], &thermovar[i]),
th->keyword[i] );
}
}
MPI_Offset nframes;
@ -350,7 +341,7 @@ void DumpNetCDFMPIIO::openfile()
if (singlefile_opened) return;
singlefile_opened = 1;
NCERRX( ncmpi_create(MPI_COMM_WORLD, filename, NC_64BIT_OFFSET,
NCERRX( ncmpi_create(MPI_COMM_WORLD, filename, NC_64BIT_DATA,
MPI_INFO_NULL, &ncid), filename );
// dimensions
@ -439,14 +430,21 @@ void DumpNetCDFMPIIO::openfile()
}
// perframe variables
for (int i = 0; i < n_perframe; i++) {
if (perframe[i].type == THIS_IS_A_BIGINT) {
NCERRX( ncmpi_def_var(ncid, perframe[i].name, NC_INT, 1, dims,
&perframe[i].var), perframe[i].name );
}
else {
NCERRX( ncmpi_def_var(ncid, perframe[i].name, NC_DOUBLE, 1, dims,
&perframe[i].var), perframe[i].name );
if (thermo) {
Thermo *th = output->thermo;
for (int i = 0; i < th->nfield; i++) {
if (th->vtype[i] == FLOAT) {
NCERRX( ncmpi_def_var(ncid, th->keyword[i], NC_DOUBLE, 1, dims,
&thermovar[i]), th->keyword[i] );
}
else if (th->vtype[i] == INT) {
NCERRX( ncmpi_def_var(ncid, th->keyword[i], NC_INT, 1, dims,
&thermovar[i]), th->keyword[i] );
}
else if (th->vtype[i] == BIGINT) {
NCERRX( ncmpi_def_var(ncid, th->keyword[i], NC_LONG, 1, dims,
&thermovar[i]), th->keyword[i] );
}
}
}
@ -600,50 +598,34 @@ void DumpNetCDFMPIIO::write()
NCERR( ncmpi_begin_indep_data(ncid) );
for (int i = 0; i < n_perframe; i++) {
if (perframe[i].type == THIS_IS_A_BIGINT) {
bigint data;
(this->*perframe[i].compute)((void*) &data);
if (filewriter)
if (thermo) {
Thermo *th = output->thermo;
for (int i = 0; i < th->nfield; i++) {
th->call_vfunc(i);
if (filewriter) {
if (th->vtype[i] == FLOAT) {
NCERRX( ncmpi_put_var1_double(ncid, thermovar[i], start,
&th->dvalue),
th->keyword[i] );
}
else if (th->vtype[i] == INT) {
NCERRX( ncmpi_put_var1_int(ncid, thermovar[i], start, &th->ivalue),
th->keyword[i] );
}
else if (th->vtype[i] == BIGINT) {
#if defined(LAMMPS_SMALLBIG) || defined(LAMMPS_BIGBIG)
NCERR( ncmpi_put_var1_long(ncid, perframe[i].var, start, &data) );
NCERRX( ncmpi_put_var1_long(ncid, thermovar[i], start, &th->bivalue),
th->keyword[i] );
#else
NCERR( ncmpi_put_var1_int(ncid, perframe[i].var, start, &data) );
NCERRX( ncmpi_put_var1_int(ncid, thermovar[i], start, &th->bivalue),
th->keyword[i] );
#endif
}
else {
double data;
int j = perframe[i].index;
int idim = perframe[i].dim;
if (perframe[i].type == THIS_IS_A_COMPUTE) {
if (idim >= 0) {
modify->compute[j]->compute_vector();
data = modify->compute[j]->vector[idim];
}
else
data = modify->compute[j]->compute_scalar();
}
else if (perframe[i].type == THIS_IS_A_FIX) {
if (idim >= 0) {
data = modify->fix[j]->compute_vector(idim);
}
else
data = modify->fix[j]->compute_scalar();
}
else if (perframe[i].type == THIS_IS_A_VARIABLE) {
j = input->variable->find(perframe[i].id);
data = input->variable->compute_equal(j);
}
if (filewriter)
NCERR( ncmpi_put_var1_double(ncid, perframe[i].var, start, &data) );
}
}
// write timestep header
// write timestep header
write_time_and_cell();
@ -903,126 +885,19 @@ int DumpNetCDFMPIIO::modify_param(int narg, char **arg)
iarg++;
return 2;
}
else if (strcmp(arg[iarg],"global") == 0) {
// "perframe" quantities, i.e. not per-atom stuff
else if (strcmp(arg[iarg],"thermo") == 0) {
iarg++;
n_perframe = narg-iarg;
perframe = new nc_perframe_t[n_perframe];
for (int i = 0; iarg < narg; iarg++, i++) {
int n;
char *suffix;
if (!strcmp(arg[iarg],"step")) {
perframe[i].type = THIS_IS_A_BIGINT;
perframe[i].compute = &DumpNetCDFMPIIO::compute_step;
strcpy(perframe[i].name, arg[iarg]);
}
else if (!strcmp(arg[iarg],"elapsed")) {
perframe[i].type = THIS_IS_A_BIGINT;
perframe[i].compute = &DumpNetCDFMPIIO::compute_elapsed;
strcpy(perframe[i].name, arg[iarg]);
}
else if (!strcmp(arg[iarg],"elaplong")) {
perframe[i].type = THIS_IS_A_BIGINT;
perframe[i].compute = &DumpNetCDFMPIIO::compute_elapsed_long;
strcpy(perframe[i].name, arg[iarg]);
}
else {
n = strlen(arg[iarg]);
if (n > 2) {
suffix = new char[n-1];
strcpy(suffix, arg[iarg]+2);
}
else {
char errstr[1024];
sprintf(errstr, "perframe quantity '%s' must thermo quantity or "
"compute, fix or variable", arg[iarg]);
error->all(FLERR,errstr);
}
if (!strncmp(arg[iarg], "c_", 2)) {
int idim = -1;
char *ptr = strchr(suffix, '[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
error->all(FLERR,"Missing ']' in dump modify command");
*ptr = '\0';
idim = ptr[1] - '1';
}
n = modify->find_compute(suffix);
if (n < 0)
error->all(FLERR,"Could not find dump modify compute ID");
if (modify->compute[n]->peratom_flag != 0)
error->all(FLERR,"Dump modify compute ID computes per-atom info");
if (idim >= 0 && modify->compute[n]->vector_flag == 0)
error->all(FLERR,"Dump modify compute ID does not compute vector");
if (idim < 0 && modify->compute[n]->scalar_flag == 0)
error->all(FLERR,"Dump modify compute ID does not compute scalar");
perframe[i].type = THIS_IS_A_COMPUTE;
perframe[i].dim = idim;
perframe[i].index = n;
strcpy(perframe[i].name, arg[iarg]);
}
else if (!strncmp(arg[iarg], "f_", 2)) {
int idim = -1;
char *ptr = strchr(suffix, '[');
if (ptr) {
if (suffix[strlen(suffix)-1] != ']')
error->all(FLERR,"Missing ']' in dump modify command");
*ptr = '\0';
idim = ptr[1] - '1';
}
n = modify->find_fix(suffix);
if (n < 0)
error->all(FLERR,"Could not find dump modify fix ID");
if (modify->fix[n]->peratom_flag != 0)
error->all(FLERR,"Dump modify fix ID computes per-atom info");
if (idim >= 0 && modify->fix[n]->vector_flag == 0)
error->all(FLERR,"Dump modify fix ID does not compute vector");
if (idim < 0 && modify->fix[n]->scalar_flag == 0)
error->all(FLERR,"Dump modify fix ID does not compute vector");
perframe[i].type = THIS_IS_A_FIX;
perframe[i].dim = idim;
perframe[i].index = n;
strcpy(perframe[i].name, arg[iarg]);
}
else if (!strncmp(arg[iarg], "v_", 2)) {
n = input->variable->find(suffix);
if (n < 0)
error->all(FLERR,"Could not find dump modify variable ID");
if (!input->variable->equalstyle(n))
error->all(FLERR,"Dump modify variable must be of style equal");
perframe[i].type = THIS_IS_A_VARIABLE;
perframe[i].dim = 1;
perframe[i].index = n;
strcpy(perframe[i].name, arg[iarg]);
strcpy(perframe[i].id, suffix);
}
else {
char errstr[1024];
sprintf(errstr, "perframe quantity '%s' must be compute, fix or "
"variable", arg[iarg]);
error->all(FLERR,errstr);
}
delete [] suffix;
}
if (iarg >= narg)
error->all(FLERR,"expected 'yes' or 'no' after 'thermo' keyword.");
if (strcmp(arg[iarg],"yes") == 0) {
thermo = true;
}
return narg;
else if (strcmp(arg[iarg],"no") == 0) {
thermo = false;
}
else error->all(FLERR,"expected 'yes' or 'no' after 'thermo' keyword.");
iarg++;
return 2;
} else return 0;
}
@ -1044,31 +919,4 @@ void DumpNetCDFMPIIO::ncerr(int err, const char *descr, int line)
}
}
/* ----------------------------------------------------------------------
one method for every keyword thermo can output
called by compute() or evaluate_keyword()
compute will have already been called
set ivalue/dvalue/bivalue if value is int/double/bigint
customize a new keyword by adding a method
------------------------------------------------------------------------- */
void DumpNetCDFMPIIO::compute_step(void *r)
{
*((bigint *) r) = update->ntimestep;
}
/* ---------------------------------------------------------------------- */
void DumpNetCDFMPIIO::compute_elapsed(void *r)
{
*((bigint *) r) = update->ntimestep - update->firststep;
}
/* ---------------------------------------------------------------------- */
void DumpNetCDFMPIIO::compute_elapsed_long(void *r)
{
*((bigint *) r) = update->ntimestep - update->beginstep;
}
#endif /* defined(LMP_HAS_PNETCDF) */

View File

@ -1,25 +1,3 @@
/* ======================================================================
LAMMPS NetCDF dump style
https://github.com/pastewka/lammps-netcdf
Lars Pastewka, lars.pastewka@kit.edu
Copyright (2011-2013) Fraunhofer IWM
Copyright (2014) Karlsruhe Institute of Technology
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
====================================================================== */
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
http://lammps.sandia.gov, Sandia National Laboratories
@ -33,6 +11,10 @@
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Lars Pastewka (University of Freiburg)
------------------------------------------------------------------------- */
#if defined(LMP_HAS_PNETCDF)
#ifdef DUMP_CLASS
@ -66,21 +48,7 @@ class DumpNetCDFMPIIO : public DumpCustom {
int var; // NetCDF variable
};
typedef void (DumpNCMPIIO::*funcptr_t)(void *);
// per-frame quantities (variables, fixes or computes)
struct nc_perframe_t {
char name[NC_MPIIO_FIELD_NAME_MAX]; // field name
int var; // NetCDF variable
int type; // variable, fix, compute or callback
int index; // index in fix/compute list
funcptr_t compute; // compute function
int dim; // dimension
char id[NC_MPIIO_FIELD_NAME_MAX]; // variable id
bigint bigint_data; // actual data
double double_data; // actual data
};
typedef void (DumpNetCDFMPIIO::*funcptr_t)(void *);
int framei; // current frame index
int blocki; // current block index
@ -91,10 +59,10 @@ class DumpNetCDFMPIIO : public DumpCustom {
int n_perat; // # of netcdf per-atom properties
nc_perat_t *perat; // per-atom properties
int n_perframe; // # of global netcdf (not per-atom) fix props
nc_perframe_t *perframe; // global properties
int *thermovar; // NetCDF variables for thermo output
bool double_precision; // write everything as double precision
bool thermo; // write thermo output to netcdf file
bigint n_buffer; // size of buffer
int *int_buffer; // buffer for passing data to netcdf
@ -128,10 +96,6 @@ class DumpNetCDFMPIIO : public DumpCustom {
virtual int modify_param(int, char **);
void ncerr(int, const char *, int);
void compute_step(void *);
void compute_elapsed(void *);
void compute_elapsed_long(void *);
};
}

View File

@ -402,6 +402,15 @@ void Thermo::compute(int flag)
firststep = 1;
}
/* ----------------------------------------------------------------------
call function to compute property
------------------------------------------------------------------------- */
void Thermo::call_vfunc(int ifield)
{
(this->*vfunc[ifield])();
}
/* ----------------------------------------------------------------------
check for lost atoms, return current number of atoms
------------------------------------------------------------------------- */

View File

@ -18,8 +18,13 @@
namespace LAMMPS_NS {
class DumpNetCDF;
class DumpNetCDFMPIIO;
class Thermo : protected Pointers {
friend class MinCG; // accesses compute_pe
friend class DumpNetCDF; // accesses thermo properties
friend class DumpNetCDFMPIIO; // accesses thermo properties
public:
char *style;
@ -112,6 +117,7 @@ class Thermo : protected Pointers {
typedef void (Thermo::*FnPtr)();
void addfield(const char *, FnPtr, int);
FnPtr *vfunc; // list of ptrs to functions
void call_vfunc(int ifield);
void compute_compute(); // functions that compute a single value
void compute_fix(); // via calls to Compute,Fix,Variable classes