netcdf: deduplicate gettings units as strings

This commit is contained in:
Luthaf
2021-12-17 17:13:29 +01:00
parent f8ee6dc680
commit 1c25c96aaa
6 changed files with 210 additions and 214 deletions

View File

@ -19,6 +19,7 @@
#if defined(LMP_HAS_NETCDF) #if defined(LMP_HAS_NETCDF)
#include "dump_netcdf.h" #include "dump_netcdf.h"
#include "netcdf_units.h"
#include "atom.h" #include "atom.h"
#include "comm.h" #include "comm.h"
@ -101,7 +102,7 @@ DumpNetCDF::DumpNetCDF(LAMMPS *lmp, int narg, char **arg) :
int idim = 0; int idim = 0;
int ndims = 1; int ndims = 1;
std::string mangled = earg[i]; std::string mangled = earg[i];
Quantity quantity = Quantity::Unknown; Quantity quantity = Quantity::UNKNOWN;
bool constant = false; bool constant = false;
// name mangling // name mangling
@ -110,12 +111,12 @@ DumpNetCDF::DumpNetCDF(LAMMPS *lmp, int narg, char **arg) :
idim = mangled[0] - 'x'; idim = mangled[0] - 'x';
ndims = 3; ndims = 3;
mangled = "coordinates"; mangled = "coordinates";
quantity = Quantity::Distance; quantity = Quantity::DISTANCE;
} else if ((mangled == "vx") || (mangled == "vy") || (mangled == "vz")) { } else if ((mangled == "vx") || (mangled == "vy") || (mangled == "vz")) {
idim = mangled[1] - 'x'; idim = mangled[1] - 'x';
ndims = 3; ndims = 3;
mangled = "velocities"; mangled = "velocities";
quantity = Quantity::Velocity; quantity = Quantity::VELOCITY;
} else if ((mangled == "xs") || (mangled == "ys") || (mangled == "zs")) { } else if ((mangled == "xs") || (mangled == "ys") || (mangled == "zs")) {
idim = mangled[0] - 'x'; idim = mangled[0] - 'x';
ndims = 3; ndims = 3;
@ -125,17 +126,17 @@ DumpNetCDF::DumpNetCDF(LAMMPS *lmp, int narg, char **arg) :
idim = mangled[0] - 'x'; idim = mangled[0] - 'x';
ndims = 3; ndims = 3;
mangled = "unwrapped_coordinates"; mangled = "unwrapped_coordinates";
quantity = Quantity::Distance; quantity = Quantity::DISTANCE;
} else if ((mangled == "fx") || (mangled == "fy") || (mangled == "fz")) { } else if ((mangled == "fx") || (mangled == "fy") || (mangled == "fz")) {
idim = mangled[1] - 'x'; idim = mangled[1] - 'x';
ndims = 3; ndims = 3;
mangled = "forces"; mangled = "forces";
quantity = Quantity::Force; quantity = Quantity::FORCE;
} else if ((mangled == "mux") || (mangled == "muy") || (mangled == "muz")) { } else if ((mangled == "mux") || (mangled == "muy") || (mangled == "muz")) {
idim = mangled[2] - 'x'; idim = mangled[2] - 'x';
ndims = 3; ndims = 3;
mangled = "mu"; mangled = "mu";
quantity = Quantity::DipoleMoment; quantity = Quantity::DIPOLE_MOMENT;
} else if (utils::strmatch(mangled, "^c_")) { } else if (utils::strmatch(mangled, "^c_")) {
std::size_t found = mangled.find('['); std::size_t found = mangled.find('[');
if (found != std::string::npos) { if (found != std::string::npos) {
@ -434,7 +435,7 @@ void DumpNetCDF::openfile()
} }
} }
std::string unit = this->unit_of(perat[i].quantity); std::string unit = get_unit_for(update->unit_style, perat[i].quantity, error);
if (!unit.empty()) { if (!unit.empty()) {
NCERR( nc_put_att_text(ncid, perat[i].var, NC_UNITS_STR, unit.size(), unit.c_str()) ); NCERR( nc_put_att_text(ncid, perat[i].var, NC_UNITS_STR, unit.size(), unit.c_str()) );
} }
@ -470,10 +471,10 @@ void DumpNetCDF::openfile()
NCERR( nc_put_att_text(ncid, NC_GLOBAL, "programVersion",strlen(lmp->version), lmp->version) ); NCERR( nc_put_att_text(ncid, NC_GLOBAL, "programVersion",strlen(lmp->version), lmp->version) );
// units & scale // units & scale
std::string unit = this->unit_of(Quantity::Time); std::string unit = get_unit_for(update->unit_style, Quantity::TIME, error);
NCERR( nc_put_att_text(ncid, time_var, NC_UNITS_STR, unit.size(), unit.c_str()) ); NCERR( nc_put_att_text(ncid, time_var, NC_UNITS_STR, unit.size(), unit.c_str()) );
unit = this->unit_of(Quantity::Distance); unit = get_unit_for(update->unit_style, Quantity::DISTANCE, error);
NCERR( nc_put_att_text(ncid, cell_origin_var, NC_UNITS_STR, unit.size(), unit.c_str()) ); NCERR( nc_put_att_text(ncid, cell_origin_var, NC_UNITS_STR, unit.size(), unit.c_str()) );
NCERR( nc_put_att_text(ncid, cell_lengths_var, NC_UNITS_STR, unit.size(), unit.c_str()) ); NCERR( nc_put_att_text(ncid, cell_lengths_var, NC_UNITS_STR, unit.size(), unit.c_str()) );
@ -892,94 +893,4 @@ void DumpNetCDF::ncerr(int err, const char *descr, int line)
} }
} }
/* ---------------------------------------------------------------------- */
std::string DumpNetCDF::unit_of(Quantity quantity) {
if (!strcmp(update->unit_style, "lj")) {
if (quantity == Quantity::Unknown) {
return "";
} else {
return "lj";
}
} else if (!strcmp(update->unit_style, "real")) {
switch (quantity) {
case Quantity::Unknown:
return "";
case Quantity::Time:
return "femtosecond";
case Quantity::Distance:
return "Angstrom";
case Quantity::Velocity:
return "Angstrom/femtosecond";
case Quantity::Force:
return "(Kcal/mol)/Angstrom)";
case Quantity::DipoleMoment:
return "e * Angstrom";
}
} else if (!strcmp(update->unit_style, "metal")) {
switch (quantity) {
case Quantity::Unknown:
return "";
case Quantity::Time:
return "picosecond";
case Quantity::Distance:
return "Angstrom";
case Quantity::Velocity:
return "Angstrom/picosecond";
case Quantity::Force:
return "eV/Angstrom";
case Quantity::DipoleMoment:
return "e * Angstrom";
}
} else if (!strcmp(update->unit_style, "si")) {
switch (quantity) {
case Quantity::Unknown:
return "";
case Quantity::Time:
return "second";
case Quantity::Distance:
return "meter";
case Quantity::Velocity:
return "meter/second";
case Quantity::Force:
return "Newton";
case Quantity::DipoleMoment:
return "Coulomb * meter";
}
} else if (!strcmp(update->unit_style, "cgs")) {
switch (quantity) {
case Quantity::Unknown:
return "";
case Quantity::Time:
return "second";
case Quantity::Distance:
return "centimeter";
case Quantity::Velocity:
return "centimeter/second";
case Quantity::Force:
return "dynes";
case Quantity::DipoleMoment:
return "statcoul * cm";
}
} else if (!strcmp(update->unit_style, "electron")) {
switch (quantity) {
case Quantity::Unknown:
return "";
case Quantity::Time:
return "second";
case Quantity::Distance:
return "centimeter";
case Quantity::Velocity:
return "centimeter/second";
case Quantity::Force:
return "Hartrees/Bohr";
case Quantity::DipoleMoment:
return "Debye";
}
}
error->all(FLERR, "Unsupported unit style: {}", update->unit_style);
return "";
}
#endif /* defined(LMP_HAS_NETCDF) */ #endif /* defined(LMP_HAS_NETCDF) */

View File

@ -29,6 +29,7 @@ DumpStyle(netcdf,DumpNetCDF);
#include "dump_custom.h" #include "dump_custom.h"
namespace LAMMPS_NS { namespace LAMMPS_NS {
enum class Quantity;
const int NC_FIELD_NAME_MAX = 100; const int NC_FIELD_NAME_MAX = 100;
const int DUMP_NC_MAX_DIMS = 100; const int DUMP_NC_MAX_DIMS = 100;
@ -40,19 +41,6 @@ class DumpNetCDF : public DumpCustom {
virtual void write(); virtual void write();
private: private:
// type of quantity for per-atom values (used to get the unit)
enum Quantity {
Unknown = 0,
Time,
Distance,
Velocity,
Force,
DipoleMoment,
};
// get the name of the unit for the given quantity
std::string unit_of(Quantity quantity);
// per-atoms quantities (positions, velocities, etc.) // per-atoms quantities (positions, velocities, etc.)
struct nc_perat_t { struct nc_perat_t {
int dims; // number of dimensions int dims; // number of dimensions

View File

@ -19,6 +19,7 @@
#if defined(LMP_HAS_PNETCDF) #if defined(LMP_HAS_PNETCDF)
#include "dump_netcdf_mpiio.h" #include "dump_netcdf_mpiio.h"
#include "netcdf_units.h"
#include "atom.h" #include "atom.h"
#include "comm.h" #include "comm.h"
@ -102,7 +103,7 @@ DumpNetCDFMPIIO::DumpNetCDFMPIIO(LAMMPS *lmp, int narg, char **arg) :
int ndims = 1; int ndims = 1;
std::string mangled = earg[i]; std::string mangled = earg[i];
bool constant = false; bool constant = false;
Quantity quantity = Quantity::Unknown; Quantity quantity = Quantity::UNKNOWN;
// name mangling // name mangling
// in the AMBER specification // in the AMBER specification
@ -110,12 +111,12 @@ DumpNetCDFMPIIO::DumpNetCDFMPIIO(LAMMPS *lmp, int narg, char **arg) :
idim = mangled[0] - 'x'; idim = mangled[0] - 'x';
ndims = 3; ndims = 3;
mangled = "coordinates"; mangled = "coordinates";
quantity = Quantity::Distance; quantity = Quantity::DISTANCE;
} else if ((mangled == "vx") || (mangled == "vy") || (mangled == "vz")) { } else if ((mangled == "vx") || (mangled == "vy") || (mangled == "vz")) {
idim = mangled[1] - 'x'; idim = mangled[1] - 'x';
ndims = 3; ndims = 3;
mangled = "velocities"; mangled = "velocities";
quantity = Quantity::Velocity; quantity = Quantity::VELOCITY;
} else if ((mangled == "xs") || (mangled == "ys") || (mangled == "zs")) { } else if ((mangled == "xs") || (mangled == "ys") || (mangled == "zs")) {
idim = mangled[0] - 'x'; idim = mangled[0] - 'x';
ndims = 3; ndims = 3;
@ -125,17 +126,17 @@ DumpNetCDFMPIIO::DumpNetCDFMPIIO(LAMMPS *lmp, int narg, char **arg) :
idim = mangled[0] - 'x'; idim = mangled[0] - 'x';
ndims = 3; ndims = 3;
mangled = "unwrapped_coordinates"; mangled = "unwrapped_coordinates";
quantity = Quantity::Distance; quantity = Quantity::DISTANCE;
} else if ((mangled == "fx") || (mangled == "fy") || (mangled == "fz")) { } else if ((mangled == "fx") || (mangled == "fy") || (mangled == "fz")) {
idim = mangled[1] - 'x'; idim = mangled[1] - 'x';
ndims = 3; ndims = 3;
mangled = "forces"; mangled = "forces";
quantity = Quantity::Force; quantity = Quantity::FORCE;
} else if ((mangled == "mux") || (mangled == "muy") || (mangled == "muz")) { } else if ((mangled == "mux") || (mangled == "muy") || (mangled == "muz")) {
idim = mangled[2] - 'x'; idim = mangled[2] - 'x';
ndims = 3; ndims = 3;
mangled = "mu"; mangled = "mu";
quantity = Quantity::DipoleMoment; quantity = Quantity::DIPOLE_MOMENT;
} else if (utils::strmatch(mangled, "^c_")) { } else if (utils::strmatch(mangled, "^c_")) {
std::size_t found = mangled.find('['); std::size_t found = mangled.find('[');
if (found != std::string::npos) { if (found != std::string::npos) {
@ -423,7 +424,7 @@ void DumpNetCDFMPIIO::openfile()
NCERRX( ncmpi_def_var(ncid, perat[i].name, xtype, 3, dims, &perat[i].var), perat[i].name ); NCERRX( ncmpi_def_var(ncid, perat[i].name, xtype, 3, dims, &perat[i].var), perat[i].name );
} }
std::string unit = this->unit_of(perat[i].quantity); std::string unit = get_unit_for(update->unit_style, perat[i].quantity, error);
if (!unit.empty()) { if (!unit.empty()) {
NCERR( ncmpi_put_att_text(ncid, perat[i].var, NC_UNITS_STR, unit.size(), unit.c_str()) ); NCERR( ncmpi_put_att_text(ncid, perat[i].var, NC_UNITS_STR, unit.size(), unit.c_str()) );
} }
@ -455,10 +456,10 @@ void DumpNetCDFMPIIO::openfile()
NCERR( ncmpi_put_att_text(ncid, NC_GLOBAL, "programVersion", strlen(lmp->version), lmp->version) ); NCERR( ncmpi_put_att_text(ncid, NC_GLOBAL, "programVersion", strlen(lmp->version), lmp->version) );
// units & scale // units & scale
std::string unit = this->unit_of(Quantity::Time); std::string unit = get_unit_for(update->unit_style, Quantity::TIME, error);
NCERR( ncmpi_put_att_text(ncid, time_var, NC_UNITS_STR, unit.size(), unit.c_str()) ); NCERR( ncmpi_put_att_text(ncid, time_var, NC_UNITS_STR, unit.size(), unit.c_str()) );
unit = this->unit_of(Quantity::Distance); unit = get_unit_for(update->unit_style, Quantity::DISTANCE, error);
NCERR( ncmpi_put_att_text(ncid, cell_origin_var, NC_UNITS_STR, unit.size(), unit.c_str()) ); NCERR( ncmpi_put_att_text(ncid, cell_origin_var, NC_UNITS_STR, unit.size(), unit.c_str()) );
NCERR( ncmpi_put_att_text(ncid, cell_lengths_var, NC_UNITS_STR, unit.size(), unit.c_str()) ); NCERR( ncmpi_put_att_text(ncid, cell_lengths_var, NC_UNITS_STR, unit.size(), unit.c_str()) );
@ -888,84 +889,4 @@ void DumpNetCDFMPIIO::ncerr(int err, const char *descr, int line)
} }
} }
/* ---------------------------------------------------------------------- */
std::string DumpNetCDF::unit_of(Quantity quantity) {
if (quantity == Quantity::Unknown) {
return "";
}
if (!strcmp(update->unit_style, "lj")) {
return "lj";
} else if (!strcmp(update->unit_style, "real")) {
switch (quantity) {
case Quantity::Time:
return "femtosecond";
case Quantity::Distance:
return "Angstrom";
case Quantity::Velocity:
return "Angstrom/femtosecond";
case Quantity::Force:
return "(Kcal/mol)/Angstrom)";
case Quantity::DipoleMoment:
return "e * Angstrom";
}
} else if (!strcmp(update->unit_style, "metal")) {
switch (quantity) {
case Quantity::Time:
return "picosecond";
case Quantity::Distance:
return "Angstrom";
case Quantity::Velocity:
return "Angstrom/picosecond";
case Quantity::Force:
return "eV/Angstrom";
case Quantity::DipoleMoment:
return "e * Angstrom";
}
} else if (!strcmp(update->unit_style, "si")) {
switch (quantity) {
case Quantity::Time:
return "second";
case Quantity::Distance:
return "meter";
case Quantity::Velocity:
return "meter/second";
case Quantity::Force:
return "Newton";
case Quantity::DipoleMoment:
return "Coulomb * meter";
}
} else if (!strcmp(update->unit_style, "cgs")) {
switch (quantity) {
case Quantity::Time:
return "second";
case Quantity::Distance:
return "centimeter";
case Quantity::Velocity:
return "centimeter/second";
case Quantity::Force:
return "dynes";
case Quantity::DipoleMoment:
return "statcoul * cm";
}
} else if (!strcmp(update->unit_style, "electron")) {
switch (quantity) {
case Quantity::Time:
return "second";
case Quantity::Distance:
return "centimeter";
case Quantity::Velocity:
return "centimeter/second";
case Quantity::Force:
return "Hartrees/Bohr";
case Quantity::DipoleMoment:
return "Debye";
}
}
error->all(FLERR, "Unsupported unit style: {}", update->unit_style);
return "";
}
#endif /* defined(LMP_HAS_PNETCDF) */ #endif /* defined(LMP_HAS_PNETCDF) */

View File

@ -29,6 +29,7 @@ DumpStyle(netcdf/mpiio,DumpNetCDFMPIIO);
#include "dump_custom.h" #include "dump_custom.h"
namespace LAMMPS_NS { namespace LAMMPS_NS {
enum class Quantity;
const int NC_MPIIO_FIELD_NAME_MAX = 100; const int NC_MPIIO_FIELD_NAME_MAX = 100;
const int DUMP_NC_MPIIO_MAX_DIMS = 100; const int DUMP_NC_MPIIO_MAX_DIMS = 100;
@ -40,19 +41,6 @@ class DumpNetCDFMPIIO : public DumpCustom {
virtual void write(); virtual void write();
private: private:
// type of quantity for per-atom values (used to get the unit)
enum Quantity {
Unknown = 0,
Time,
Distance,
Velocity,
Force,
DipoleMoment,
};
// get the name of the unit for the given quantity
std::string unit_of(Quantity quantity);
// per-atoms quantities (positions, velocities, etc.) // per-atoms quantities (positions, velocities, etc.)
struct nc_perat_t { struct nc_perat_t {
int dims; // number of dimensions int dims; // number of dimensions

143
src/NETCDF/netcdf_units.cpp Normal file
View File

@ -0,0 +1,143 @@
// clang-format off
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing author: Lars Pastewka (University of Freiburg)
------------------------------------------------------------------------- */
#if defined(LMP_HAS_NETCDF) || defined(LMP_HAS_PNETCDF)
#include "netcdf_units.h"
#include "error.h"
std::string LAMMPS_NS::get_unit_for(const char* unit_style, Quantity quantity, Error* error) {
if (!strcmp(unit_style, "lj")) {
if (quantity == Quantity::UNKNOWN) {
return "";
} else {
return "lj";
}
} else if (!strcmp(unit_style, "real")) {
switch (quantity) {
case Quantity::UNKNOWN:
return "";
case Quantity::TIME:
return "femtosecond";
case Quantity::DISTANCE:
return "angstrom";
case Quantity::VELOCITY:
return "angstrom/femtosecond";
case Quantity::FORCE:
return "(Kcal/mol)/angstrom)";
case Quantity::DIPOLE_MOMENT:
return "e * angstrom";
}
} else if (!strcmp(unit_style, "metal")) {
switch (quantity) {
case Quantity::UNKNOWN:
return "";
case Quantity::TIME:
return "picosecond";
case Quantity::DISTANCE:
return "angstrom";
case Quantity::VELOCITY:
return "angstrom/picosecond";
case Quantity::FORCE:
return "eV/angstrom";
case Quantity::DIPOLE_MOMENT:
return "e * angstrom";
}
} else if (!strcmp(unit_style, "si")) {
switch (quantity) {
case Quantity::UNKNOWN:
return "";
case Quantity::TIME:
return "second";
case Quantity::DISTANCE:
return "meter";
case Quantity::VELOCITY:
return "meter/second";
case Quantity::FORCE:
return "Newton";
case Quantity::DIPOLE_MOMENT:
return "Coulomb * meter";
}
} else if (!strcmp(unit_style, "cgs")) {
switch (quantity) {
case Quantity::UNKNOWN:
return "";
case Quantity::TIME:
return "second";
case Quantity::DISTANCE:
return "centimeter";
case Quantity::VELOCITY:
return "centimeter/second";
case Quantity::FORCE:
return "dynes";
case Quantity::DIPOLE_MOMENT:
return "statcoul * cm";
}
} else if (!strcmp(unit_style, "electron")) {
switch (quantity) {
case Quantity::UNKNOWN:
return "";
case Quantity::TIME:
return "femtoseconds";
case Quantity::DISTANCE:
return "Bohr";
case Quantity::VELOCITY:
return "Bohr/atomic time units";
case Quantity::FORCE:
return "Hartree/Bohr";
case Quantity::DIPOLE_MOMENT:
return "Debye";
}
} else if (!strcmp(unit_style, "micro")) {
switch (quantity) {
case Quantity::UNKNOWN:
return "";
case Quantity::TIME:
return "microseconds";
case Quantity::DISTANCE:
return "micrometers";
case Quantity::VELOCITY:
return "micrometers/microsecond";
case Quantity::FORCE:
return "picogram * micrometer/microsecond^2";
case Quantity::DIPOLE_MOMENT:
return "picocoulomb * micrometer";
}
} else if (!strcmp(unit_style, "nano")) {
switch (quantity) {
case Quantity::UNKNOWN:
return "";
case Quantity::TIME:
return "nanoseconds";
case Quantity::DISTANCE:
return "nanometers";
case Quantity::VELOCITY:
return "nanometers/nanosecond";
case Quantity::FORCE:
return "attogram * nanometer/nanosecond^2";
case Quantity::DIPOLE_MOMENT:
return "e * nanometer";
}
}
error->all(FLERR, "Unsupported unit style: {}", unit_style);
return "";
}
#endif

45
src/NETCDF/netcdf_units.h Normal file
View File

@ -0,0 +1,45 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
Steve Plimpton, sjplimp@sandia.gov
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Lars Pastewka (University of Freiburg), Guillaume Fraux (EPFL)
------------------------------------------------------------------------- */
#ifndef LMP_NETCDF_UNITS_H
#define LMP_NETCDF_UNITS_H
#if defined(LMP_HAS_NETCDF) || defined(LMP_HAS_PNETCDF)
#include <string>
namespace LAMMPS_NS {
class Error;
// type of quantity for per-atom values (used to get the unit)
enum class Quantity {
UNKNOWN = 0,
TIME,
DISTANCE,
VELOCITY,
FORCE,
DIPOLE_MOMENT,
};
// get the name of the unit for the given `quantity` in the given LAMMPS
// `unit_style` any error will be reported through `error`
std::string get_unit_for(const char* unit_style, Quantity quantity, Error* error);
}
#endif
#endif