Commit 30177c4e authored by sjplimp's avatar sjplimp Committed by GitHub
Browse files

Merge pull request #521 from pastewka/17_dump_nc

Updated NetCDF dump style (dump netcdf)
parents 178eff23 bdf03757
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -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
+5 −11
Original line number Diff line number Diff line
@@ -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/)
+8 −8
Original line number Diff line number Diff line
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
+100 −252
Original line number Diff line number Diff line
/* ======================================================================
   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++) {
@@ -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,7 +345,7 @@ void DumpNetCDF::openfile()
      if (singlefile_opened) return;
      singlefile_opened = 1;

      NCERRX( nc_create(filename, NC_64BIT_OFFSET, &ncid),
      NCERRX( nc_create(filename, NC_64BIT_DATA, &ncid),
          filename );

      // dimensions
@@ -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 );
      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] );
          }
        else {
          NCERRX( nc_def_var(ncid, perframe[i].name, NC_DOUBLE, 1, dims,
			     &perframe[i].var), perframe[i].name );
        }
      }

@@ -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;
    }
    else if (strcmp(arg[iarg],"no") == 0) {
      thermo = false;
    }

    return narg;
    else error->all(FLERR,"expected 'yes' or 'no' after 'thermo' keyword.");
    iarg++;
    return 2;
  } else return 0;
}

@@ -1111,31 +986,4 @@ void DumpNetCDF::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 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) */
+6 −44
Original line number Diff line number Diff line
/* ======================================================================
   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 *);
};

}
Loading