diff --git a/doc/dump_h5md.html b/doc/dump_h5md.html new file mode 100644 index 0000000000..f21c93f5a7 --- /dev/null +++ b/doc/dump_h5md.html @@ -0,0 +1,138 @@ + +
LAMMPS WWW Site - LAMMPS Documentation - LAMMPS Commands +
+ + + + + + +
+ +

dump h5md command +

+

Syntax: +

+
dump ID group-ID h5md N file.h5 args 
+
+ +

Examples: +

+
dump h5md1 all h5md 100 dump_h5md.h5 position image
+dump h5md1 all h5md 100 dump_h5md.h5 position velocity every 10 
+
+
dump h5md1 all h5md 100 dump_h5md.h5 velocity author "L. Ammps" 
+
+

Description: +

+

Dump a snapshot of atom coordinates every N timesteps in the HDF5 +based H5MD file format (de Buyl et al.). +HDF5 files are binary, portable and self-describing. +This dump style will write only one file, on the root node. +

+

Several dumps may write to the same file, by using file_from and referring to a +previously defined dump. +Several groups may also be stored within the same file by defining several dumps. +A dump that refers (via file_from) to an already open dump ID and that +concerns another particle group must specify create_group yes. +

+ + +

Each data element is written every N*N_element steps. For image, no +subinterval is needed as it must be present at the same interval as position. +image must be given after position in any case. +The box information (edges in each dimension) is stored at the same interval +than the position element, if present. Else it is stored every N steps. +

+

IMPORTANT NOTE: Because periodic boundary conditions are enforced only +on timesteps when neighbor lists are rebuilt, the coordinates of an +atom written to a dump file may be slightly outside the simulation +box. +

+

Use from write_dump: +

+

It is possible to use this dump style with the write_dump command. +In this case, the subintervals must not be set at all. +write_dump can be used either alone or in conjunction with file_from so that +fixed-in-time data can be stored in the same file as time-dependent data. +

+

Typically, the species data is fixed. The following two commands store the +position data every 100 timesteps, with the image data, and store once the +species data in the same file. +

+
dump h5md1 all h5md 100 dump.h5 position image
+write_dump all h5md dump.h5 file_from h5md1 species 
+
+
+ +

Restrictions: +

+ +

The h5md dump style is part of the USER-H5MD package. It is only enabled if +LAMMPS was built with that package. See the Making +LAMMPS section for more info. It also requires +(i) building the ch5md library provided with LAMMPS (See the Making +LAMMPS section for more info.) and +(ii) having the HDF5 library installed (C bindings are sufficient). +The library ch5md is compiled with the h5cc wrapper provided by the HDF5 library. +

+ + +
+ +

Related commands: +

+

dump, dump_modify, undump +

+
+ + + +

(de Buyl et al.) de Buyl, Colberg and Hofling, H5MD: A structured, efficient, +and portable file format for molecular data, Comp. Phys. Comm. 185(6), +1546-1553 (2014) - [arXiv:1308.6382]. +

+ diff --git a/doc/dump_h5md.txt b/doc/dump_h5md.txt new file mode 100644 index 0000000000..58b504b972 --- /dev/null +++ b/doc/dump_h5md.txt @@ -0,0 +1,121 @@ +"LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c + +:link(lws,http://lammps.sandia.gov) +:link(ld,Manual.html) +:link(lc,Section_commands.html#comm) + +:line + +dump h5md command :h3 + +[Syntax:] + +dump ID group-ID h5md N file.h5 args :pre + +ID = user-assigned name for the dump :ulb,l +group-ID = ID of the group of atoms to be imaged :l +h5md = style of dump command (other styles {atom} or {cfg} or {dcd} or {xtc} or {xyz} or {local} or {custom} are discussed on the "dump"_dump.html doc page) :l +N = dump every this many timesteps :l +file.h5 = name of file to write to :l +args = list of data elements to dump, with their dump "subintervals". +At least one element must be given and image may only be present if +position is specified first. :l + position options + image + velocity options + force options + species options + file_from ID: do not open a new file, re-use the already opened file from dump ID + box value = {yes} or {no} + create_group value = {yes} or {no} + author value = quoted string :pre + +For the elements {position}, {velocity}, {force} and {species}, one may specify +a sub-interval to write the data only every N_element iterations of the dump +(i.e. every N*N_element time steps). This is specified by the option + + every N_element :pre + +that follows directly the element declaration. + +:ule + +[Examples:] + +dump h5md1 all h5md 100 dump_h5md.h5 position image +dump h5md1 all h5md 100 dump_h5md.h5 position velocity every 10 :pre +dump h5md1 all h5md 100 dump_h5md.h5 velocity author "L. Ammps" :pre + +[Description:] + +Dump a snapshot of atom coordinates every N timesteps in the "HDF5"_HDF5_ws +based "H5MD"_h5md file format "(de Buyl et al.)"_#h5md_cpc. +HDF5 files are binary, portable and self-describing. +This dump style will write only one file, on the root node. + +Several dumps may write to the same file, by using file_from and referring to a +previously defined dump. +Several groups may also be stored within the same file by defining several dumps. +A dump that refers (via {file_from}) to an already open dump ID and that +concerns another particle group must specify {create_group yes}. + +:link(h5md,http://nongnu.org/h5md/) + +Each data element is written every N*N_element steps. For {image}, no +subinterval is needed as it must be present at the same interval as {position}. +{image} must be given after {position} in any case. +The box information (edges in each dimension) is stored at the same interval +than the {position} element, if present. Else it is stored every N steps. + +IMPORTANT NOTE: Because periodic boundary conditions are enforced only +on timesteps when neighbor lists are rebuilt, the coordinates of an +atom written to a dump file may be slightly outside the simulation +box. + +[Use from write_dump:] + +It is possible to use this dump style with the "write_dump"_write_dump.html command. +In this case, the subintervals must not be set at all. +{write_dump} can be used either alone or in conjunction with {file_from} so that +fixed-in-time data can be stored in the same file as time-dependent data. + +Typically, the {species} data is fixed. The following two commands store the +position data every 100 timesteps, with the image data, and store once the +species data in the same file. + +dump h5md1 all h5md 100 dump.h5 position image +write_dump all h5md dump.h5 file_from h5md1 species :pre + +:line + +[Restrictions:] + +:ulb +The number of atoms per snapshot cannot change with the h5md style. :l +The position data is stored wrapped (box boundaries not enforced, see note above). :l +Only orthogonal domains are currently supported. This is a limitation of the +present package and not of H5MD itself. :l +:ule + +The {h5md} dump style is part of the USER-H5MD package. It is only enabled if +LAMMPS was built with that package. See the "Making +LAMMPS"_Section_start.html#start_3 section for more info. It also requires +(i) building the ch5md library provided with LAMMPS (See the "Making +LAMMPS"_Section_start.html#start_3 section for more info.) and +(ii) having the "HDF5"_HDF5_ws library installed (C bindings are sufficient). +The library ch5md is compiled with the h5cc wrapper provided by the HDF5 library. + +:link(HDF5_ws,http://www.hdfgroup.org/HDF5/) + +:line + +[Related commands:] + +"dump"_dump.html, "dump_modify"_dump_modify.html, "undump"_undump.html + +:line + +:link(h5md_cpc) +[(de Buyl et al.)] de Buyl, Colberg and Hofling, H5MD: A structured, efficient, +and portable file format for molecular data, Comp. Phys. Comm. 185(6), +1546-1553 (2014) - "\[arXiv:1308.6382\]"_http://arxiv.org/abs/1308.6382/. diff --git a/lib/ch5md/LICENSE b/lib/ch5md/LICENSE new file mode 100644 index 0000000000..ad4d36e885 --- /dev/null +++ b/lib/ch5md/LICENSE @@ -0,0 +1,25 @@ +Copyright (C) 2013-2014 Pierre de Buyl + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + a. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + b. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + c. Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/ch5md/Makefile b/lib/ch5md/Makefile new file mode 100644 index 0000000000..12c473bb03 --- /dev/null +++ b/lib/ch5md/Makefile @@ -0,0 +1,32 @@ +EXTRAMAKE=Makefile.lammps.empty + +CC=h5cc +HDF5_PATH=/usr +INC=-I include +AR=ar +ARFLAGS=rc +LIB=libch5md.a + +all: lib Makefile.lammps + +build: + mkdir -p build +build/ch5md.o: src/ch5md.c | build + $(CC) $(INC) -c $< -o $@ + +.PHONY: Makefile.lammps +Makefile.lammps: + @echo "# Settings that the LAMMPS build will import when this package library is used" > Makefile.lammps +ifneq "$(HDF5_PATH)" "/usr" + @echo "ch5md_SYSINC = -I${HDF5_PATH}/include" >> Makefile.lammps + @echo "ch5md_SYSLIB = -L${HDF5_PATH}/lib" >> Makefile.lammps +endif + +$(LIB): build/ch5md.o + $(AR) $(ARFLAGS) $(LIB) build/ch5md.o + +lib: $(LIB) Makefile.lammps + +clean: + rm -f build/*.o $(LIB) Makefile.lammps + diff --git a/lib/ch5md/README b/lib/ch5md/README new file mode 100644 index 0000000000..78a175323d --- /dev/null +++ b/lib/ch5md/README @@ -0,0 +1,20 @@ +ch5md : Read and write H5MD files in C +====================================== + +Copyright (C) 2013-2014 Pierre de Buyl + +ch5md is a set of C routines to manipulate H5MD files. H5MD is a file format +specification based on [HDF5](http://www.hdfgroup.org/HDF5/) for storing +molecular data, whose development is found at . + +ch5md is developped by Pierre de Buyl and is released under the 3-clause BSD +license that can be found in the file LICENSE. + +To use the h5md dump style in lammps, execute make in this directory then 'make +yes-user-h5md' in the src directory of lammps. Rebuild lammps. + +If HDF5 is not in a standard system location, use `make HDF5_PATH=/path/to/hdf5`. + +In the case of 2015 and more recent debian and ubuntu systems where concurrent +serial and mpi are possible, use the full platform depedent path, i.e. +`HDF5_PATH=/usr/lib/x86_64-linux-gnu/hdf5/serial` diff --git a/lib/ch5md/include/ch5md.h b/lib/ch5md/include/ch5md.h new file mode 100644 index 0000000000..7710f0f065 --- /dev/null +++ b/lib/ch5md/include/ch5md.h @@ -0,0 +1,73 @@ +/* This file is part of ch5md + * Copyright (C) 2013-2015 Pierre de Buyl + * All rights reserved. + * + * This software may be modified and distributed under the terms + * of the BSD license. See the LICENSE file for details. + */ + +#ifndef CH5MD_H +#define CH5MD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "hdf5.h" +#include + +#define CH5MD_RANK_ERROR -10 + +typedef struct h5md_element_struct { + hid_t group; + hid_t step; + hid_t time; + hid_t value; + hid_t datatype; + int is_time; + int current_step; + struct h5md_element_struct *link; + struct h5md_particles_group_struct *particles_group; +} h5md_element; + +typedef struct h5md_particles_group_struct { + hid_t group; + h5md_element position; + hid_t box; + h5md_element box_edges; + h5md_element image; + h5md_element velocity; + h5md_element force; + h5md_element mass; + h5md_element species; + h5md_element id; + h5md_element charge; + int local_size_max; +} h5md_particles_group; + +typedef struct { + hid_t id; + int version[2]; + hid_t particles; + hid_t observables; + hid_t parameters; +} h5md_file; + +h5md_file h5md_create_file (const char *filename, const char *author, const char *author_email, const char *creator, const char *creator_version); +int h5md_close_file(h5md_file file); +hid_t h5md_open_file (const char *filename); +h5md_particles_group h5md_create_particles_group(h5md_file file, const char *name); +h5md_element h5md_create_time_data(hid_t loc, const char *name, int rank, int int_dims[], hid_t datatype, h5md_element *link); +int h5md_close_element(h5md_element e); +h5md_element h5md_create_fixed_data_simple(hid_t loc, const char *name, int rank, int int_dims[], hid_t datatype, void *data); +h5md_element h5md_create_fixed_data_scalar(hid_t loc, const char *name, hid_t datatype, void *data); +int h5md_append(h5md_element e, void *data, int step, double time); +int h5md_create_box(h5md_particles_group *group, int dim, char *boundary[], bool is_time, double value[], h5md_element *link); +int h5md_write_string_attribute(hid_t loc, const char *obj_name, + const char *att_name, const char *value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/ch5md/src/ch5md.c b/lib/ch5md/src/ch5md.c new file mode 100644 index 0000000000..1b3dd295f6 --- /dev/null +++ b/lib/ch5md/src/ch5md.c @@ -0,0 +1,444 @@ +/* This file is part of ch5md + * Copyright (C) 2013-2015 Pierre de Buyl + * All rights reserved. + * + * This software may be modified and distributed under the terms + * of the BSD license. See the LICENSE file for details. + */ + +#include "hdf5.h" +#include "ch5md.h" +#include +#include + +#define MIN_CHUNK 10 +#define MAX_CHUNK 256 +#define MAX_RANK 5 + +h5md_file h5md_create_file (const char *filename, const char *author, const char *author_email, const char *creator, const char *creator_version) +{ + h5md_file file; + hid_t g, g1; + hid_t a, s, t; + hsize_t dims[1]; + herr_t status; + + file.version[0] = 1; + file.version[1] = 0; + + file.id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + g = H5Gcreate(file.id, "h5md", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + + dims[0] = 2; + s = H5Screate_simple(1, dims, NULL); + a = H5Acreate(g, "version", H5T_NATIVE_INT, s, H5P_DEFAULT, H5P_DEFAULT); + status = H5Awrite(a, H5T_NATIVE_INT, file.version); + status = H5Aclose(a); + status = H5Sclose(s); + + s = H5Screate(H5S_SCALAR); + + g1 = H5Gcreate(g, "author", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + t = H5Tcopy(H5T_C_S1); + status = H5Tset_size(t, strlen(author)); + a = H5Acreate(g1, "name", t, s, H5P_DEFAULT, H5P_DEFAULT); + status = H5Awrite(a, t, author); + status = H5Aclose(a); + status = H5Tclose(t); + if (NULL!=author_email) { + t = H5Tcopy(H5T_C_S1); + status = H5Tset_size(t, strlen(author_email)); + a = H5Acreate(g1, "author_email", t, s, H5P_DEFAULT, H5P_DEFAULT); + status = H5Awrite(a, t, author_email); + status = H5Aclose(a); + status = H5Tclose(t); + } + status = H5Gclose(g1); + + g1 = H5Gcreate(g, "creator", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + t = H5Tcopy(H5T_C_S1); + status = H5Tset_size(t, strlen(creator)); + a = H5Acreate(g1, "name", t, s, H5P_DEFAULT, H5P_DEFAULT); + status = H5Awrite(a, t, creator); + status = H5Aclose(a); + status = H5Tclose(t); + t = H5Tcopy(H5T_C_S1); + status = H5Tset_size(t, strlen(creator_version)); + a = H5Acreate(g1, "version", t, s, H5P_DEFAULT, H5P_DEFAULT); + status = H5Awrite(a, t, creator_version); + status = H5Aclose(a); + status = H5Tclose(t); + status = H5Gclose(g1); + + file.particles = H5Gcreate(file.id, "particles", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + file.observables = H5Gcreate(file.id, "observables", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + file.parameters = H5Gcreate(file.id, "parameters", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + + return file; +} + +int h5md_close_file(h5md_file file) { + H5Gclose(file.particles); + H5Gclose(file.observables); + H5Gclose(file.parameters); + H5Fclose(file.id); + + return 0; +} + +hid_t h5md_open_file (const char *filename) +{ + hid_t file; + hid_t g; + hid_t a, s; + hsize_t dims[1]; + int version[2]; + int version_ok; + + file = H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT); + + g = H5Gopen(file, "h5md", H5P_DEFAULT); + + version_ok = false; + dims[0] = 2; + a = H5Aopen(g, "version", H5P_DEFAULT); + s = H5Aget_space(a); + if (!(H5Sis_simple(s)>0)) { + printf("H5MD version is not a simple dataspace"); + H5Sclose(s); + H5Aclose(a); + H5Gclose(g); + H5Fclose(file); + } else { + if (H5Sget_simple_extent_ndims(s)==1) { + H5Sget_simple_extent_dims(s, dims, NULL); + if (dims[0]==2) { + H5Aread(a, H5T_NATIVE_INT, version); + if ( (version[0]==1) && (version[1]==0) ) {version_ok = true;} + } + } + } + + H5Aclose(a); + H5Sclose(s); + H5Gclose(g); + + if (!version_ok) H5Fclose(file); + + return file; + +} + +h5md_particles_group h5md_create_particles_group(h5md_file file, const char *name) +{ + h5md_particles_group group; + + group.group = H5Gcreate(file.particles, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + + return group; +} + +h5md_element h5md_create_time_data(hid_t loc, const char *name, int rank, int int_dims[], hid_t datatype, h5md_element *link) +{ + + h5md_element td; + + hid_t spc, plist; + hsize_t dims[MAX_RANK], max_dims[MAX_RANK], chunks[MAX_RANK]; + herr_t status; + + int i; + + dims[0] = 0 ; + max_dims[0] = H5S_UNLIMITED ; + for (i=0; igroup, "step", td.group, "step", H5P_DEFAULT, H5P_DEFAULT); + status = H5Lcreate_hard(link->group, "time", td.group, "time", H5P_DEFAULT, H5P_DEFAULT); + } + + spc = H5Screate_simple( rank+1 , dims, max_dims) ; + plist = H5Pcreate(H5P_DATASET_CREATE); + status = H5Pset_chunk(plist, rank+1, chunks); + td.value = H5Dcreate(td.group, "value", datatype, spc, H5P_DEFAULT, plist, H5P_DEFAULT); + H5Pclose(plist); + status = H5Sclose(spc); + + td.datatype = datatype; + td.is_time = true; + + return td; + +} + +int h5md_close_element(h5md_element e) +{ + herr_t status; + + if (!e.is_time) return 0; + + if (e.link==NULL) { + status = H5Dclose(e.step); + status = H5Dclose(e.time); + } + status = H5Dclose(e.value); + status = H5Gclose(e.group); + + return 0; + +} + +h5md_element h5md_create_fixed_data_simple(hid_t loc, const char *name, int rank, int int_dims[], hid_t datatype, void *data) +{ + + h5md_element fd; + + hid_t spc; + hsize_t dims[H5S_MAX_RANK]; + herr_t status; + int i; + + for (i=0; i H5S_MAX_RANK) { + return CH5MD_RANK_ERROR; + } + H5Sget_simple_extent_dims(file_space, dims, maxdims); + H5Sclose(file_space); + + // Extend dimensions by one + dims[0] = dims[0]+1; + H5Dset_extent(dset, dims); + + return 0; + +} + +int h5md_append(h5md_element e, void *data, int step, double time) { + + hid_t mem_space, file_space; + int i, rank; + hsize_t dims[H5S_MAX_RANK]; + hsize_t start[H5S_MAX_RANK], count[H5S_MAX_RANK]; + + // If not a time-dependent H5MD element, do nothing + if (!e.is_time) return 0; + + if (NULL==e.link) { + h5md_extend_by_one(e.step, dims); + + // Define hyperslab selection + start[0] = dims[0]-1; + count[0] = 1; + + // Select the hyperslab + file_space = H5Dget_space(e.step); + rank = H5Sget_simple_extent_ndims(file_space); + mem_space = H5Screate_simple(rank-1, dims+1, NULL); + // Define hyperslab selection + start[0] = dims[0]-1; + count[0] = 1; + for (i=1 ; ibox = H5Gcreate(group->group, "box", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + + // Create dimension attribute + spc = H5Screate(H5S_SCALAR); + att = H5Acreate(group->box, "dimension", H5T_NATIVE_INT, spc, H5P_DEFAULT, H5P_DEFAULT); + status = H5Awrite(att, H5T_NATIVE_INT, &dim); + status = H5Aclose(att); + status = H5Sclose(spc); + + // Compute the size of the string type for boundary + dims[0] = dim; + boundary_length=0; + for (i=0; iboundary_length) { + boundary_length=tmp; + } + } + char *tmp_boundary = malloc(dim*sizeof(char)*boundary_length); + for (i=0; ibox, "boundary", t, spc, H5P_DEFAULT, H5P_DEFAULT); + status = H5Awrite(att, t, tmp_boundary); + free(tmp_boundary); + status = H5Aclose(att); + status = H5Sclose(spc); + status = H5Tclose(t); + + // Create edges + // Check if the box is time-dependent or not + int_dims[0]=dim; + if (is_time) { + group->box_edges = h5md_create_time_data(group->box, "edges", 1, int_dims, H5T_NATIVE_DOUBLE, link); + } else { + if (NULL!=value) { + group->box_edges = h5md_create_fixed_data_simple(group->box, "edges", 1, int_dims, H5T_NATIVE_DOUBLE, value); + } + } + + status = H5Gclose(group->box); + + return 0; +} + +int h5md_write_string_attribute(hid_t loc, const char *obj_name, + const char *att_name, const char *value) +{ + hid_t obj; + hid_t s, t, a; + herr_t status; + + obj = H5Oopen(loc, obj_name, H5P_DEFAULT); + + t = H5Tcopy(H5T_C_S1); + status = H5Tset_size(t, strlen(value)); + s = H5Screate(H5S_SCALAR); + a = H5Acreate(obj, att_name, t, s, H5P_DEFAULT, H5P_DEFAULT); + status = H5Awrite(a, t, value); + status = H5Aclose(a); + status = H5Sclose(s); + status = H5Tclose(t); + + status = H5Oclose(obj); + + return 0; +} diff --git a/src/USER-H5MD/Install.sh b/src/USER-H5MD/Install.sh new file mode 100644 index 0000000000..7b6e7bbc20 --- /dev/null +++ b/src/USER-H5MD/Install.sh @@ -0,0 +1,64 @@ +# Install/unInstall package files in LAMMPS +# mode = 0/1/2 for uninstall/install/update + +mode=$1 + +# arg1 = file, arg2 = file it depends on + +action () { + if (test $mode = 0) then + rm -f ../$1 + elif (! cmp -s $1 ../$1) then + if (test -z "$2" || test -e ../$2) then + cp $1 .. + if (test $mode = 2) then + echo " updating src/$1" + fi + fi + elif (test -n "$2") then + if (test ! -e ../$2) then + rm -f ../$1 + fi + fi +} + +for file in *.cpp *.h; do + action $file +done + +# edit 2 Makefile.package files to include/exclude package info + +if (test $1 = 1) then + + if (test -e ../Makefile.package) then + sed -i -e 's/[^ \t]*ch5md[^ \t]* //g' ../Makefile.package + sed -i -e 's|^PKG_INC =[ \t]*|&-I..\/..\/lib\/ch5md\/include |' ../Makefile.package + sed -i -e 's|^PKG_PATH =[ \t]*|&-L..\/..\/lib\/ch5md |' ../Makefile.package + sed -i -e 's|^PKG_LIB =[ \t]*|&-lch5md |' ../Makefile.package + sed -i -e 's|^PKG_LIB =[ \t]*|&-lhdf5 |' ../Makefile.package + sed -i -e 's|^PKG_SYSINC =[ \t]*|&$(ch5md_SYSINC) |' ../Makefile.package + sed -i -e 's|^PKG_SYSLIB =[ \t]*|&$(ch5md_SYSLIB) |' ../Makefile.package + sed -i -e 's|^PKG_SYSPATH =[ \t]*|&$(ch5md_SYSPATH) |' ../Makefile.package + fi + + if (test -e ../Makefile.package.settings) then + sed -i -e '/^include.*ch5md.*$/d' ../Makefile.package.settings + # multiline form needed for BSD sed on Macs + sed -i -e '4 i \ +include ..\/..\/lib\/ch5md\/Makefile.lammps +' ../Makefile.package.settings + + fi + +elif (test $1 = 0) then + + if (test -e ../Makefile.package) then + sed -i -e 's/[^ \t]*ch5md[^ \t]* //g' ../Makefile.package + sed -i -e 's/[^ \t]*hdf5[^ \t]* //g' ../Makefile.package + fi + + if (test -e ../Makefile.package.settings) then + sed -i -e '/^include.*ch5md.*$/d' ../Makefile.package.settings + fi + +fi diff --git a/src/USER-H5MD/README b/src/USER-H5MD/README new file mode 100644 index 0000000000..e67708dbc7 --- /dev/null +++ b/src/USER-H5MD/README @@ -0,0 +1,8 @@ +This package provides the h5md dump style. + +See the doc page for dump_h5md. This dump style requires building the bundled +ch5md library and HDF5 (see lib/ch5md/README). + +The person who created this package is Pierre de Buyl (KU Leuven), see +http://pdebuyl.be/ for contact information. Contact him directly if you have +questions. diff --git a/src/USER-H5MD/dump_h5md.cpp b/src/USER-H5MD/dump_h5md.cpp new file mode 100644 index 0000000000..8c8175b4d2 --- /dev/null +++ b/src/USER-H5MD/dump_h5md.cpp @@ -0,0 +1,557 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, 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: Pierre de Buyl (KU Leuven) +------------------------------------------------------------------------- */ + +#include "math.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "limits.h" +#include "ch5md.h" +#include "dump_h5md.h" +#include "domain.h" +#include "atom.h" +#include "update.h" +#include "group.h" +#include "output.h" +#include "error.h" +#include "force.h" +#include "memory.h" +#include "version.h" + +using namespace LAMMPS_NS; + +#define MYMIN(a,b) ((a) < (b) ? (a) : (b)) +#define MYMAX(a,b) ((a) > (b) ? (a) : (b)) + +/** Scan common options for the dump elements + */ +int element_args(int narg, char **arg, int *every) +{ + int iarg=0; + while (iargall(FLERR,"Illegal dump h5md command"); + if (binary || compressed || multifile || multiproc) + error->all(FLERR,"Invalid dump h5md filename"); + + if (domain->triclinic!=0) + error->all(FLERR,"Invalid domain for dump h5md. Only triclinic domains supported."); + + size_one = 6; + sort_flag = 1; + sortcol = 0; + format_default = NULL; + flush_flag = 0; + unwrap_flag = 0; + datafile_from_dump = -1; + author_name=NULL; + + every_dump = force->inumeric(FLERR,arg[3]); + every_position = every_image = -1; + every_velocity = every_force = every_species = -1; + every_charge = -1; + + do_box=true; + create_group=true; + + bool box_is_set, create_group_is_set; + box_is_set = create_group_is_set = false; + int iarg=5; + int n_parsed, default_every; + size_one=0; + if (every_dump==0) default_every=0; else default_every=1; + + while (iargall(FLERR, "Illegal dump h5md command"); + iarg += n_parsed; + size_one+=domain->dimension; + } else if (strcmp(arg[iarg], "image")==0) { + if (every_position<0) error->all(FLERR, "Illegal dump h5md command"); + iarg+=1; + size_one+=domain->dimension; + every_image = every_position; + } else if (strcmp(arg[iarg], "velocity")==0) { + every_velocity = default_every; + iarg+=1; + n_parsed = element_args(narg-iarg, &arg[iarg], &every_velocity); + if (n_parsed<0) error->all(FLERR, "Illegal dump h5md command"); + iarg += n_parsed; + size_one+=domain->dimension; + } else if (strcmp(arg[iarg], "force")==0) { + every_force = default_every; + iarg+=1; + n_parsed = element_args(narg-iarg, &arg[iarg], &every_force); + if (n_parsed<0) error->all(FLERR, "Illegal dump h5md command"); + iarg += n_parsed; + size_one+=domain->dimension; + } else if (strcmp(arg[iarg], "species")==0) { + every_species=default_every; + iarg+=1; + n_parsed = element_args(narg-iarg, &arg[iarg], &every_species); + if (n_parsed<0) error->all(FLERR, "Illegal dump h5md command"); + iarg += n_parsed; + size_one+=1; + } else if (strcmp(arg[iarg], "charge")==0) { + if (!atom->q_flag) + error->all(FLERR, "Requesting non-allocated quantity q in dump_h5md"); + every_charge = default_every; + iarg+=1; + n_parsed = element_args(narg-iarg, &arg[iarg], &every_charge); + if (n_parsed<0) error->all(FLERR, "Illegal dump h5md command"); + iarg += n_parsed; + size_one+=1; + } else if (strcmp(arg[iarg], "file_from")==0) { + if (iarg+1>=narg) { + error->all(FLERR, "Invalid number of arguments in dump h5md"); + } + if (box_is_set||create_group_is_set) + error->all(FLERR, "Cannot set file_from in dump h5md after box or create_group"); + int idump; + for (idump = 0; idump < output->ndump; idump++) + if (strcmp(arg[iarg+1],output->dump[idump]->id) == 0) break; + if (idump == output->ndump) error->all(FLERR,"Cound not find dump_modify ID"); + datafile_from_dump = idump; + do_box=false; + create_group=false; + iarg+=2; + } else if (strcmp(arg[iarg], "box")==0) { + if (iarg+1>=narg) { + error->all(FLERR, "Invalid number of arguments in dump h5md"); + } + box_is_set = true; + if (strcmp(arg[iarg+1], "yes")==0) + do_box=true; + else if (strcmp(arg[iarg+1], "no")==0) + do_box=false; + else + error->all(FLERR, "Illegal dump h5md command"); + iarg+=2; + } else if (strcmp(arg[iarg], "create_group")==0) { + if (iarg+1>=narg) { + error->all(FLERR, "Invalid number of arguments in dump h5md"); + } + create_group_is_set = true; + if (strcmp(arg[iarg+1], "yes")==0) + create_group=true; + else if (strcmp(arg[iarg+1], "no")==0) { + create_group=false; + } + else + error->all(FLERR, "Illegal dump h5md command"); + iarg+=2; + } else if (strcmp(arg[iarg], "author")==0) { + if (iarg+1>=narg) { + error->all(FLERR, "Invalid number of arguments in dump h5md"); + } + if (author_name==NULL) { + author_name = new char[strlen(arg[iarg]+1)]; + strcpy(author_name, arg[iarg+1]); + } else { + error->all(FLERR, "Illegal dump h5md command: author argument repeated"); + } + iarg+=2; + } else { + error->all(FLERR, "Invalid argument to dump h5md"); + } + } + + // allocate global array for atom coords + + bigint n = group->count(igroup); + natoms = static_cast (n); + + if (every_position>=0) + memory->create(dump_position,domain->dimension*natoms,"dump:position"); + if (every_image>=0) + memory->create(dump_image,domain->dimension*natoms,"dump:image"); + if (every_velocity>=0) + memory->create(dump_velocity,domain->dimension*natoms,"dump:velocity"); + if (every_force>=0) + memory->create(dump_force,domain->dimension*natoms,"dump:force"); + if (every_species>=0) + memory->create(dump_species,natoms,"dump:species"); + if (every_charge>=0) + memory->create(dump_charge,natoms,"dump:charge"); + + openfile(); + ntotal = 0; +} + +/* ---------------------------------------------------------------------- */ + +DumpH5MD::~DumpH5MD() +{ + if (every_position>=0) { + memory->destroy(dump_position); + if (me==0) { + h5md_close_element(particles_data.position); + if (do_box) + h5md_close_element(particles_data.box_edges); + } + } + if (every_image>=0) { + memory->destroy(dump_image); + if (me==0) h5md_close_element(particles_data.image); + } + if (every_velocity>=0) { + memory->destroy(dump_velocity); + if (me==0) h5md_close_element(particles_data.velocity); + } + if (every_force>=0) { + memory->destroy(dump_force); + if (me==0) h5md_close_element(particles_data.force); + } + if (every_species>=0) { + memory->destroy(dump_species); + if (me==0) h5md_close_element(particles_data.species); + } + if (every_charge>=0) { + memory->destroy(dump_charge); + if (me==0) h5md_close_element(particles_data.charge); + } + +} + +/* ---------------------------------------------------------------------- */ + +void DumpH5MD::init_style() +{ + if (sort_flag == 0 || sortcol != 0) + error->all(FLERR,"Dump h5md requires sorting by atom ID"); +} + +/* ---------------------------------------------------------------------- */ + +void DumpH5MD::openfile() +{ + char *group_name; + int group_name_length; + int dims[2]; + char *boundary[3]; + for (int i=0; i<3; i++) { + boundary[i] = new char[9]; + if (domain->periodicity[i]==1) { + strcpy(boundary[i], "periodic"); + } else { + strcpy(boundary[i], "none"); + } + } + + if (me == 0) { + if (datafile_from_dump<0) { + if (author_name==NULL) { + datafile = h5md_create_file(filename, "N/A", NULL, "lammps", LAMMPS_VERSION); + } else { + datafile = h5md_create_file(filename, author_name, NULL, "lammps", LAMMPS_VERSION); + } + group_name_length = strlen(group->names[igroup]); + group_name = new char[group_name_length]; + strcpy(group_name, group->names[igroup]); + if (create_group) { + particles_data = h5md_create_particles_group(datafile, group_name); + } else { + particles_data.group = H5Gopen(datafile.particles, group_name, H5P_DEFAULT); + } + delete [] group_name; + dims[0] = natoms; + dims[1] = domain->dimension; + if (every_position>0) { + particles_data.position = h5md_create_time_data(particles_data.group, "position", 2, dims, H5T_NATIVE_DOUBLE, NULL); + h5md_create_box(&particles_data, dims[1], boundary, true, NULL, &particles_data.position); + } + if (every_image>0) + particles_data.image = h5md_create_time_data(particles_data.group, "image", 2, dims, H5T_NATIVE_INT, &particles_data.position); + if (every_velocity>0) + particles_data.velocity = h5md_create_time_data(particles_data.group, "velocity", 2, dims, H5T_NATIVE_DOUBLE, NULL); + if (every_force>0) + particles_data.force = h5md_create_time_data(particles_data.group, "force", 2, dims, H5T_NATIVE_DOUBLE, NULL); + if (every_species>0) + particles_data.species = h5md_create_time_data(particles_data.group, "species", 1, dims, H5T_NATIVE_INT, NULL); + if (every_charge>0) { + particles_data.charge = h5md_create_time_data(particles_data.group, "charge", 1, dims, H5T_NATIVE_DOUBLE, NULL); + h5md_write_string_attribute(particles_data.group, "charge", "type", "effective"); + } + } else { + DumpH5MD* other_dump; + other_dump=(DumpH5MD*)output->dump[datafile_from_dump]; + datafile = other_dump->datafile; + group_name_length = strlen(group->names[igroup]); + group_name = new char[group_name_length]; + strcpy(group_name, group->names[igroup]); + if (create_group) { + particles_data = h5md_create_particles_group(datafile, group_name); + } else { + particles_data = other_dump->particles_data; + } + dims[0] = natoms; + dims[1] = domain->dimension; + if (every_position>0) { + particles_data.position = h5md_create_time_data(particles_data.group, "position", 2, dims, H5T_NATIVE_DOUBLE, NULL); + h5md_create_box(&particles_data, dims[1], boundary, true, NULL, &particles_data.position); + } + if (every_image>0) + particles_data.image = h5md_create_time_data(particles_data.group, "image", 2, dims, H5T_NATIVE_INT, &particles_data.position); + if (every_velocity>0) + particles_data.velocity = h5md_create_time_data(particles_data.group, "velocity", 2, dims, H5T_NATIVE_DOUBLE, NULL); + if (every_force>0) + particles_data.force = h5md_create_time_data(particles_data.group, "force", 2, dims, H5T_NATIVE_DOUBLE, NULL); + if (every_species>0) + particles_data.species = h5md_create_time_data(particles_data.group, "species", 1, dims, H5T_NATIVE_INT, NULL); + if (every_charge>0) { + particles_data.charge = h5md_create_time_data(particles_data.group, "charge", 1, dims, H5T_NATIVE_DOUBLE, NULL); + h5md_write_string_attribute(particles_data.group, "charge", "type", "effective"); + } + + } + } + + if (author_name!=NULL) delete [] author_name; + for (int i=0; i<3; i++) { + delete [] boundary[i]; + } + +} + +/* ---------------------------------------------------------------------- */ + +void DumpH5MD::write_header(bigint nbig) +{ + return; +} + +/* ---------------------------------------------------------------------- */ + +void DumpH5MD::pack(tagint *ids) +{ + int m,n; + + tagint *tag = atom->tag; + double **x = atom->x; + double **v = atom->v; + double **f = atom->f; + int *species = atom->type; + double *q = atom->q; + imageint *image = atom->image; + int *mask = atom->mask; + int nlocal = atom->nlocal; + int dim=domain->dimension; + + double xprd = domain->xprd; + double yprd = domain->yprd; + double zprd = domain->zprd; + + m = n = 0; + for (int i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + if (every_position>=0) { + int ix = (image[i] & IMGMASK) - IMGMAX; + int iy = (image[i] >> IMGBITS & IMGMASK) - IMGMAX; + int iz = (image[i] >> IMG2BITS) - IMGMAX; + if (unwrap_flag == 1) { + buf[m++] = (x[i][0] + ix * xprd); + buf[m++] = (x[i][1] + iy * yprd); + if (dim>2) buf[m++] = (x[i][2] + iz * zprd); + } else { + buf[m++] = x[i][0]; + buf[m++] = x[i][1]; + if (dim>2) buf[m++] = x[i][2]; + } + if (every_image>=0) { + buf[m++] = ix; + buf[m++] = iy; + if (dim>2) buf[m++] = iz; + } + } + if (every_velocity>=0) { + buf[m++] = v[i][0]; + buf[m++] = v[i][1]; + if (dim>2) buf[m++] = v[i][2]; + } + if (every_force>=0) { + buf[m++] = f[i][0]; + buf[m++] = f[i][1]; + if (dim>2) buf[m++] = f[i][2]; + } + if (every_species>=0) + buf[m++] = species[i]; + if (every_charge>=0) + buf[m++] = q[i]; + ids[n++] = tag[i]; + } +} + +/* ---------------------------------------------------------------------- */ + +void DumpH5MD::write_data(int n, double *mybuf) +{ + // copy buf atom coords into global array + + int m = 0; + int dim = domain->dimension; + int k = dim*ntotal; + int k_image = dim*ntotal; + int k_velocity = dim*ntotal; + int k_force = dim*ntotal; + int k_species = ntotal; + int k_charge = ntotal; + for (int i = 0; i < n; i++) { + if (every_position>=0) { + for (int j=0; j=0) + for (int j=0; j=0) + for (int j=0; j=0) + for (int j=0; j=0) + dump_species[k_species++] = mybuf[m++]; + if (every_charge>=0) + dump_charge[k_charge++] = mybuf[m++]; + ntotal++; + } + + // if last chunk of atoms in this snapshot, write global arrays to file + + if (ntotal == natoms) { + if (every_dump>0) { + write_frame(); + ntotal = 0; + } else { + write_fixed_frame(); + } + } +} + +/* ---------------------------------------------------------------------- */ + +int DumpH5MD::modify_param(int narg, char **arg) +{ + if (strcmp(arg[0],"unwrap") == 0) { + if (narg < 2) error->all(FLERR,"Illegal dump_modify command"); + if (strcmp(arg[1],"yes") == 0) unwrap_flag = 1; + else if (strcmp(arg[1],"no") == 0) unwrap_flag = 0; + else error->all(FLERR,"Illegal dump_modify command"); + return 2; + } + return 0; +} + +/* ---------------------------------------------------------------------- */ + +void DumpH5MD::write_frame() +{ + int local_step; + double local_time; + double edges[3]; + local_step = update->ntimestep; + local_time = local_step * update->dt; + edges[0] = boxxhi - boxxlo; + edges[1] = boxyhi - boxylo; + edges[2] = boxzhi - boxzlo; + if (every_position>0) { + if (local_step % (every_position*every_dump) == 0) { + h5md_append(particles_data.position, dump_position, local_step, local_time); + h5md_append(particles_data.box_edges, edges, local_step, local_time); + if (every_image>0) + h5md_append(particles_data.image, dump_image, local_step, local_time); + } + } else { + if (do_box) h5md_append(particles_data.box_edges, edges, local_step, local_time); + } + if (every_velocity>0 && local_step % (every_velocity*every_dump) == 0) { + h5md_append(particles_data.velocity, dump_velocity, local_step, local_time); + } + if (every_force>0 && local_step % (every_force*every_dump) == 0) { + h5md_append(particles_data.force, dump_force, local_step, local_time); + } + if (every_species>0 && local_step % (every_species*every_dump) == 0) { + h5md_append(particles_data.species, dump_species, local_step, local_time); + } + if (every_charge>0 && local_step % (every_charge*every_dump) == 0) { + h5md_append(particles_data.charge, dump_charge, local_step, local_time); + } +} + +void DumpH5MD::write_fixed_frame() +{ + double edges[3]; + int dims[2]; + char *boundary[3]; + hid_t a, s, t; + herr_t status; + + for (int i=0; i<3; i++) { + boundary[i] = new char[9]; + if (domain->periodicity[i]==1) { + strcpy(boundary[i], "periodic"); + } else { + strcpy(boundary[i], "none"); + } + } + + dims[0] = natoms; + dims[1] = domain->dimension; + + edges[0] = boxxhi - boxxlo; + edges[1] = boxyhi - boxylo; + edges[2] = boxzhi - boxzlo; + if (every_position==0) { + particles_data.position = h5md_create_fixed_data_simple(particles_data.group, "position", 2, dims, H5T_NATIVE_DOUBLE, dump_position); + h5md_create_box(&particles_data, dims[1], boundary, false, edges, NULL); + if (every_image==0) + particles_data.image = h5md_create_fixed_data_simple(particles_data.group, "image", 2, dims, H5T_NATIVE_INT, dump_image); + } + if (every_velocity==0) + particles_data.velocity = h5md_create_fixed_data_simple(particles_data.group, "velocity", 2, dims, H5T_NATIVE_DOUBLE, dump_velocity); + if (every_force==0) + particles_data.force = h5md_create_fixed_data_simple(particles_data.group, "force", 2, dims, H5T_NATIVE_DOUBLE, dump_force); + if (every_species==0) + particles_data.species = h5md_create_fixed_data_simple(particles_data.group, "species", 1, dims, H5T_NATIVE_INT, dump_species); + if (every_charge==0) { + particles_data.charge = h5md_create_fixed_data_simple(particles_data.group, "charge", 1, dims, H5T_NATIVE_INT, dump_charge); + h5md_write_string_attribute(particles_data.group, "charge", "type", "effective"); + } + + for (int i=0; i<3; i++) { + delete [] boundary[i]; + } +} + diff --git a/src/USER-H5MD/dump_h5md.h b/src/USER-H5MD/dump_h5md.h new file mode 100644 index 0000000000..464733419b --- /dev/null +++ b/src/USER-H5MD/dump_h5md.h @@ -0,0 +1,107 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, 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: Pierre de Buyl (KU Leuven) +------------------------------------------------------------------------- */ + +#ifdef DUMP_CLASS + +DumpStyle(h5md,DumpH5MD) + +#else + +#ifndef LMP_DUMP_H5MD_H +#define LMP_DUMP_H5MD_H + +#include "dump.h" +#include "ch5md.h" + +namespace LAMMPS_NS { + +class DumpH5MD : public Dump { + public: + DumpH5MD(class LAMMPS *, int, char**); + virtual ~DumpH5MD(); + + private: + int natoms,ntotal; + int nevery_save; + int unwrap_flag; // 1 if atom coords are unwrapped, 0 if no + h5md_file datafile; + int datafile_from_dump; + h5md_particles_group particles_data; + char *author_name; + + bool do_box; + bool create_group; + + // data arrays and intervals + int every_dump; + double *dump_position; + int every_position; + int *dump_image; + int every_image; + double *dump_velocity; + int every_velocity; + double *dump_force; + int every_force; + int *dump_species; + int every_species; + int *dump_charge; + int every_charge; + + void init_style(); + int modify_param(int, char **); + void openfile(); + void write_header(bigint); + void pack(tagint *); + void write_data(int, double *); + + void write_frame(); + void write_fixed_frame(); +}; + +} + +#endif +#endif + +/* ERROR/WARNING messages: + +E: Illegal ... command + +Self-explanatory. Check the input script syntax and compare to the +documentation for the command. You can use -echo screen as a +command-line option when running LAMMPS to see the offending line. + +E: Invalid number of arguments in dump h5md + +Make sure that each data item (position, etc.) is followed by a dump +interval. + +E: Dump h5md requires sorting by atom ID + +Use the dump_modify sort command to enable this. + +E: Cannot use variable every setting for dump xtc + +The format of this file requires snapshots at regular intervals. + +E: Cannot change dump_modify every for dump xtc + +The frequency of writing dump xtc snapshots cannot be changed. + +E: Cannot set file_from in dump h5md after box or create_group + +The file_from option modifies the box and create_group options and +they must appear after file_from if used. + +*/