diff --git a/doc/src/dump_modify.txt b/doc/src/dump_modify.txt index b5daa6416e91912ab30eef406dec4d4078deb419..2ea1da3db3b6295531b913bc9e25665a9c4c7ba7 100644 --- a/doc/src/dump_modify.txt +++ b/doc/src/dump_modify.txt @@ -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 diff --git a/doc/src/dump_netcdf.txt b/doc/src/dump_netcdf.txt index 4e82656698a61860a9b376e2eac19e11f05ec1c8..63568137a65ec5d6891db69a9d7cf33d1be1a098 100644 --- a/doc/src/dump_netcdf.txt +++ b/doc/src/dump_netcdf.txt @@ -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/) diff --git a/src/USER-NETCDF/README b/src/USER-NETCDF/README index 57dec5e4c835fd41b4b5ac7a62ac8e96e75913e0..7d7874e5acaefc5bc0b785d5304252f5e7320ba4 100644 --- a/src/USER-NETCDF/README +++ b/src/USER-NETCDF/README @@ -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 diff --git a/src/USER-NETCDF/dump_netcdf.cpp b/src/USER-NETCDF/dump_netcdf.cpp index bad90bdef3d1affe541a93c27e69856a66c3f700..b45794126d8175e876d9764738f2d582bd0f3ae0 100644 --- a/src/USER-NETCDF/dump_netcdf.cpp +++ b/src/USER-NETCDF/dump_netcdf.cpp @@ -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) */ diff --git a/src/USER-NETCDF/dump_netcdf.h b/src/USER-NETCDF/dump_netcdf.h index daf4e9d0de2d94151c6f0bad6b9e348171e48b82..036df3f058398a53c9f55df4f1fab79f7a477b8e 100644 --- a/src/USER-NETCDF/dump_netcdf.h +++ b/src/USER-NETCDF/dump_netcdf.h @@ -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 *); }; } diff --git a/src/USER-NETCDF/dump_netcdf_mpiio.cpp b/src/USER-NETCDF/dump_netcdf_mpiio.cpp index 2e9ec274a5e07cc04bddb7644aa87d54353b09c6..c5b87b178e2a58bf2b195a81365ec4352f168613 100644 --- a/src/USER-NETCDF/dump_netcdf_mpiio.cpp +++ b/src/USER-NETCDF/dump_netcdf_mpiio.cpp @@ -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) */ diff --git a/src/USER-NETCDF/dump_netcdf_mpiio.h b/src/USER-NETCDF/dump_netcdf_mpiio.h index 6f5b00b03350f6a08c9c603a01cbae8c49f90e7b..10b0e800d2347d561d42073c1b3c196275fd9ca5 100644 --- a/src/USER-NETCDF/dump_netcdf_mpiio.h +++ b/src/USER-NETCDF/dump_netcdf_mpiio.h @@ -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 *); }; } diff --git a/src/thermo.cpp b/src/thermo.cpp index 18deecb1a8cb03ff619535f2c53f42dadc4e1d96..d4f7c5cc9e1434e86e8efb45dbcb7c0015ef8a25 100644 --- a/src/thermo.cpp +++ b/src/thermo.cpp @@ -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 ------------------------------------------------------------------------- */ diff --git a/src/thermo.h b/src/thermo.h index d87e8fce3d9e98cb26be277ea9aeeaf5e2f6984f..de2a46dec42f3a87c90c9fd7cac184a178c652ef 100644 --- a/src/thermo.h +++ b/src/thermo.h @@ -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