summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Lundborg <magnus.lundborg@scilifelab.se>2013-01-10 10:16:46 (GMT)
committerMagnus Lundborg <magnus.lundborg@scilifelab.se>2013-01-10 10:16:46 (GMT)
commit7b3daed952505700792baa58d418fc138475f883 (patch)
tree10fba88e54a959c4d7d9c0162564ddb58de24215
parent8adf800968b78afecbc9ddbb8e87f97f476a7bb5 (diff)
Added fortran version of md example (not working fully yet). Added an example for getting positions from file. Minor fixes.
-rw-r--r--src/lib/tng_io.c24
-rw-r--r--src/lib/tng_io.h120
-rw-r--r--src/tests/CMakeLists.txt15
-rw-r--r--src/tests/md_openmp.c7
-rw-r--r--src/tests/md_openmp.f817
-rw-r--r--src/tests/tng_io_read_pos.c97
6 files changed, 1062 insertions, 18 deletions
diff --git a/src/lib/tng_io.c b/src/lib/tng_io.c
index 099d88c..ddf3e0d 100644
--- a/src/lib/tng_io.c
+++ b/src/lib/tng_io.c
@@ -2201,7 +2201,10 @@ static tng_function_status tng_frame_set_block_read
}
}
- file_pos = ftell(tng_data->input_file);
+ file_pos = ftell(tng_data->input_file) -
+ (block->block_contents_size + block->header_contents_size);
+
+ tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
if(frame_set->n_mapping_blocks && frame_set->mappings)
{
@@ -6084,8 +6087,7 @@ tng_function_status tng_frame_set_find(tng_trajectory_t tng_data,
tng_block_init(&block);
/* Is this the right frame set? */
- if(first_frame <= frame &&
- frame <= last_frame)
+ if(first_frame <= frame && frame <= last_frame)
{
tng_block_destroy(&block);
return(TNG_SUCCESS);
@@ -6119,6 +6121,7 @@ tng_function_status tng_frame_set_find(tng_trajectory_t tng_data,
fseek(tng_data->input_file,
file_pos,
SEEK_SET);
+ tng_data->current_trajectory_frame_set_input_file_pos = file_pos;
/* Read block headers first to see what block is found. */
stat = tng_block_header_read(tng_data, block);
if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
@@ -6140,6 +6143,12 @@ tng_function_status tng_frame_set_find(tng_trajectory_t tng_data,
last_frame = first_frame + frame_set->n_frames - 1;
file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
+ if(frame >= first_frame && frame <= last_frame)
+ {
+ tng_block_destroy(&block);
+ return(TNG_SUCCESS);
+ }
+
while(file_pos > 0 && first_frame + long_stride_length *
n_frames_per_frame_set < frame)
{
@@ -6669,6 +6678,11 @@ tng_function_status tng_frame_set_write(tng_trajectory_t tng_data,
tng_data->last_trajectory_frame_set_output_file_pos =
ftell(tng_data->output_file);
+ if(tng_data->current_trajectory_frame_set_output_file_pos <= 0)
+ {
+ return(TNG_FAILURE);
+ }
+
tng_block_init(&block);
if(tng_frame_set_block_write(tng_data, block, hash_mode) != TNG_SUCCESS)
@@ -6918,7 +6932,7 @@ tng_function_status tng_frame_set_new(tng_trajectory_t tng_data,
tng_function_status tng_data_block_add(tng_trajectory_t tng_data,
const int64_t id,
const char *block_name,
- const char datatype,
+ const tng_data_type datatype,
const tng_block_type block_type_flag,
int64_t n_frames,
const int64_t n_values_per_frame,
@@ -7118,7 +7132,7 @@ tng_function_status tng_data_block_add(tng_trajectory_t tng_data,
tng_function_status tng_particle_data_block_add(tng_trajectory_t tng_data,
const int64_t id,
const char *block_name,
- const char datatype,
+ const tng_data_type datatype,
const tng_block_type block_type_flag,
int64_t n_frames,
const int64_t n_values_per_frame,
diff --git a/src/lib/tng_io.h b/src/lib/tng_io.h
index 4f9c260..33af0c1 100644
--- a/src/lib/tng_io.h
+++ b/src/lib/tng_io.h
@@ -40,11 +40,112 @@
* cmake ..
*
* make
- *
*
* Test by running:
- *
+ *
* bin/tng_testing
+ *
+ * @section examples_sec Examples
+ *
+ * @subsection C
+ *
+ * #include <stdlib.h>
+ * #include <stdio.h>
+ * #include <tng_io.h>
+ *
+ * int main(int argc, char **argv)
+ * {
+ * tng_trajectory_t traj;
+ * union data_values ***positions = 0; // A 3-dimensional array to be populated
+ * int64_t n_particles, n_values_per_frame, n_frames;
+ * tng_data_type data_type;
+ * int i, j;
+ * int64_t particle = 0;
+ * // Set a default frame range
+ * int first_frame = 0, last_frame = 50;
+ *
+ * if(argc <= 1)
+ * {
+ * printf("No file specified\n");
+ * printf("Usage:\n");
+ * printf("tng_io_read_pos <tng_file> [particle number = %"PRId64"] "
+ * "[first_frame = %d] [last_frame = %d]\n",
+ * particle, first_frame, last_frame);
+ * exit(1);
+ * }
+ *
+ * // A reference must be passed to allocate memory
+ * if(tng_trajectory_init(&traj) != TNG_SUCCESS)
+ * {
+ * tng_trajectory_destroy(&traj);
+ * exit(1);
+ * }
+ * tng_input_file_set(traj, argv[1]);
+ *
+ * // Read the file headers
+ * tng_file_headers_read(traj, TNG_USE_HASH);
+ *
+ * if(argc >= 3)
+ * {
+ * particle = strtoll(argv[2], 0, 10);
+ * if(argc >= 4)
+ * {
+ * first_frame = strtoll(argv[3], 0, 10);
+ * if(argc >= 5)
+ * {
+ * last_frame = strtoll(argv[4], 0, 10);
+ * }
+ * }
+ * }
+ *
+ * n_frames = last_frame - first_frame + 1;
+ *
+ * // Get the positions of all particles in the requested frame range.
+ * // The positions are stored in the positions array.
+ * // N.B. No proper error checks.
+ * if(tng_particle_data_interval_get(traj, TNG_TRAJ_POSITIONS, first_frame,
+ * last_frame, TNG_USE_HASH, &positions, &n_particles, &n_values_per_frame,
+ * &data_type) != TNG_SUCCESS)
+ * {
+ * printf("Cannot read positions\n");
+ * }
+ * else
+ * {
+ * // Print the positions of the wanted particle (zero based)
+ * for(i=first_frame; i<=last_frame; i++)
+ * {
+ * printf("%d", i);
+ * for(j=0; j<n_values_per_frame; j++)
+ * {
+ * switch(data_type)
+ * {
+ * case TNG_INT_DATA:
+ * printf("\t%"PRId64"", positions[i][particle][j].i);
+ * break;
+ * case TNG_FLOAT_DATA:
+ * printf("\t%f", positions[i][particle][j].f);
+ * break;
+ * case TNG_DOUBLE_DATA:
+ * printf("\t%f", positions[i][particle][j].d);
+ * break;
+ * default:
+ * break;
+ * }
+ * printf("\n");
+ * }
+ * }
+ * }
+ *
+ * // Free memory
+ * if(positions)
+ * {
+ * tng_particle_data_values_free(positions, n_frames, n_particles,
+ * n_values_per_frame, data_type);
+ * }
+ * tng_trajectory_destroy(&traj);
+ *
+ * return(0);
+ * }
*
*/
@@ -52,6 +153,7 @@
#define _TNGIO_H 1
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
@@ -101,10 +203,8 @@ typedef enum {TNG_UNCOMPRESSED,
typedef enum {TNG_NON_TRAJECTORY_BLOCK, TNG_TRAJECTORY_BLOCK} tng_block_type;
-typedef enum {TNG_ENDIANNESS_AND_STRING_LENGTH,
- TNG_GENERAL_INFO,
+typedef enum {TNG_GENERAL_INFO,
TNG_MOLECULES,
- TNG_TRAJECTORY_IDS_AND_NAMES,
TNG_TRAJECTORY_FRAME_SET,
TNG_PARTICLE_MAPPING} tng_non_trajectory_block_ids;
@@ -165,7 +265,7 @@ typedef struct tng_non_particle_data *tng_non_particle_data_t;
union data_values {
double d;
float f;
- int i;
+ int64_t i;
char *c;
};
@@ -1158,7 +1258,7 @@ tng_function_status tng_frame_set_new_(tng_trajectory_t tng_data,
tng_function_status tng_data_block_add(tng_trajectory_t tng_data,
const int64_t id,
const char *block_name,
- const char datatype,
+ const tng_data_type datatype,
const tng_block_type block_type_flag,
int64_t n_frames,
const int64_t n_values_per_frame,
@@ -1168,7 +1268,7 @@ tng_function_status tng_data_block_add(tng_trajectory_t tng_data,
tng_function_status tng_data_block_add_(tng_trajectory_t tng_data,
const int64_t *id,
const char *block_name,
- const char *datatype,
+ const tng_data_type *datatype,
const tng_block_type *block_type_flag,
int64_t *n_frames,
const int64_t *n_values_per_frame,
@@ -1217,7 +1317,7 @@ tng_function_status tng_data_block_add_(tng_trajectory_t tng_data,
tng_function_status tng_particle_data_block_add(tng_trajectory_t tng_data,
const int64_t id,
const char *block_name,
- const char datatype,
+ const tng_data_type datatype,
const tng_block_type block_type_flag,
int64_t n_frames,
const int64_t n_values_per_frame,
@@ -1230,7 +1330,7 @@ tng_function_status tng_particle_data_block_add_
(tng_trajectory_t tng_data,
const int64_t *id,
const char *block_name,
- const char *datatype,
+ const tng_data_type *datatype,
const tng_block_type *block_type_flag,
int64_t *n_frames,
const int64_t *n_values_per_frame,
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 92c580d..5ab5a55 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -14,4 +14,17 @@ add_executable(tng_testing tng_io_testing.c)
target_link_libraries(tng_testing tng_io)
add_executable(md_openmp md_openmp.c)
-target_link_libraries(md_openmp tng_io ${OpenMP_LIBS} m) \ No newline at end of file
+target_link_libraries(md_openmp tng_io ${OpenMP_LIBS} m)
+
+add_executable(tng_io_read_pos tng_io_read_pos.c)
+target_link_libraries(tng_io_read_pos tng_io)
+
+# enable_language(Fortran OPTIONAL)
+# if(${CMAKE_Fortran_COMPILER_WORKS})
+# get_filename_component (Fortran_COMPILER_NAME ${CMAKE_Fortran_COMPILER} NAME)
+# if (Fortran_COMPILER_NAME STREQUAL "gfortran")
+# set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fcray-pointer ${OpenMP_C_FLAGS} -std=legacy")
+# endif()
+# add_executable(md_openmp_f md_openmp.f)
+# target_link_libraries(md_openmp_f tng_io ${OpenMP_LIBS})
+# endif()
diff --git a/src/tests/md_openmp.c b/src/tests/md_openmp.c
index 8c96d5a..198755b 100644
--- a/src/tests/md_openmp.c
+++ b/src/tests/md_openmp.c
@@ -159,6 +159,7 @@ int main ( int argc, char *argv[] )
}
+ /* Add the box shape data block and write the file headers */
if(tng_data_block_add(traj, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE", TNG_DOUBLE_DATA,
TNG_NON_TRAJECTORY_BLOCK, 1, 9, 1, TNG_UNCOMPRESSED,
box_shape) == TNG_CRITICAL ||
@@ -216,8 +217,6 @@ int main ( int argc, char *argv[] )
step_print_index++;
step_print = ( step_print_index * step_num ) / step_print_num;
- wtime = omp_get_wtime ( );
-
/* Create a frame set for writing data */
tng_num_frames_per_frame_set_get(traj, &n_frames_per_frame_set);
if(tng_frame_set_new(traj, 0,
@@ -274,6 +273,8 @@ int main ( int argc, char *argv[] )
exit(1);
}
+ wtime = omp_get_wtime ( );
+
for ( step = 1; step <= step_num; step++ )
{
compute ( np, nd, pos, vel, mass, force, &potential, &kinetic );
@@ -327,6 +328,8 @@ int main ( int argc, char *argv[] )
/*
Terminate.
*/
+ tng_trajectory_destroy(&traj);
+
printf ( "\n" );
printf ( "MD_OPENMP\n" );
printf ( " Normal end of execution.\n" );
diff --git a/src/tests/md_openmp.f b/src/tests/md_openmp.f
new file mode 100644
index 0000000..31a92cc
--- /dev/null
+++ b/src/tests/md_openmp.f
@@ -0,0 +1,817 @@
+ program main
+
+c*********************************************************************72
+c
+cc MAIN is the main program for MD_OPENMP.
+c
+c Discussion:
+c
+c The program implements a simple molecular dynamics simulation.
+c
+c The program uses Open MP directives to allow parallel computation.
+c
+c The velocity Verlet time integration scheme is used.
+c
+c The particles interact with a central pair potential.
+c
+c Licensing:
+c
+c This code is distributed under the GNU LGPL license.
+c
+c Modified:
+c
+c 8 Jan 2013
+c
+c Author:
+c
+c Original FORTRAN90 version by Bill Magro.
+c FORTRAN77 version by John Burkardt.
+c TNG trajectory output by Magnus Lundborg.
+c
+c Parameters:
+c
+c None
+c
+ implicit none
+
+ include 'omp_lib.h'
+
+ integer nd
+ parameter ( nd = 3 )
+ integer np
+ parameter ( np = 250 )
+ integer step_num
+ parameter ( step_num = 1000 )
+
+ double precision acc(nd,np)
+ double precision box(nd)
+ double precision box_shape(9)
+ double precision dt
+ parameter ( dt = 0.0001D+00 )
+ double precision e0
+ double precision force(nd,np)
+ integer i
+ integer id
+ double precision kinetic
+ double precision mass
+ parameter ( mass = 1.0D+00 )
+ double precision pos(nd,np)
+ double precision potential
+ integer proc_num
+ integer seed
+ integer step
+ integer step_print
+ integer step_print_index
+ integer step_print_num
+ integer step_save
+ integer thread_num
+ double precision vel(nd,np)
+ double precision wtime
+
+c
+c Cray pointers are not standard fortran, but must be used to allocate
+c memory properly.
+c
+ pointer (traj_p, traj)
+ pointer (molecule_p, molecule)
+ pointer (chain_p, chain)
+ pointer (residue_p, residue)
+ pointer (atom_p, atom)
+ byte traj
+ byte molecule
+ byte chain
+ byte residue
+ byte atom
+
+c
+c The TNG functions expect 8 bit integers
+c
+ integer*8 n_frames_per_frame_set
+ integer*8 frames_saved_cnt
+ integer*8 frame_set_cnt
+ integer*8 tng_n_particles
+
+c
+c These constants are also defined in tng_io.h, but need to
+c set in fortran as well. This can be copied to any fortran
+c source code using the tng_io library.
+c
+ integer*8 TNG_UNCOMPRESSED
+ parameter ( TNG_UNCOMPRESSED = 0)
+ integer TNG_NON_TRAJECTORY_BLOCK
+ parameter ( TNG_NON_TRAJECTORY_BLOCK = 0)
+ integer TNG_TRAJECTORY_BLOCK
+ parameter ( TNG_TRAJECTORY_BLOCK = 1)
+ integer*8 TNG_GENERAL_INFO
+ parameter ( TNG_GENERAL_INFO = 0 )
+ integer*8 TNG_MOLECULES
+ parameter ( TNG_MOLECULES = 1 )
+ integer*8 TNG_TRAJECTORY_FRAME_SET
+ parameter ( TNG_TRAJECTORY_FRAME_SET = 2 )
+ integer*8 TNG_PARTICLE_MAPPING
+ parameter ( TNG_PARTICLE_MAPPING = 3 )
+ integer*8 TNG_TRAJ_BOX_SHAPE
+ parameter ( TNG_TRAJ_BOX_SHAPE = 10000 )
+ integer*8 TNG_TRAJ_POSITIONS
+ parameter ( TNG_TRAJ_POSITIONS = 10001 )
+ integer*8 TNG_TRAJ_VELOCITIES
+ parameter ( TNG_TRAJ_VELOCITIES = 10002 )
+ integer*8 TNG_TRAJ_FORCES
+ parameter ( TNG_TRAJ_FORCES = 10003 )
+ integer TNG_SKIP_HASH
+ parameter ( TNG_SKIP_HASH = 0 )
+ integer TNG_USE_HASH
+ parameter ( TNG_USE_HASH = 1 )
+ integer TNG_CHAR_DATA
+ parameter ( TNG_CHAR_DATA = 0 )
+ integer TNG_INT_DATA
+ parameter ( TNG_INT_DATA = 1 )
+ integer TNG_FLOAT_DATA
+ parameter ( TNG_FLOAT_DATA = 2 )
+ integer TNG_DOUBLE_DATA
+ parameter ( TNG_DOUBLE_DATA = 3 )
+
+ call timestamp ( )
+
+ write ( *, '(a)' ) ' '
+ write ( *, '(a)' ) 'MD_OPENMP'
+ write ( *, '(a)' ) ' FORTRAN77/OpenMP version'
+ write ( *, '(a)' ) ' '
+ write ( *, '(a)' ) ' A molecular dynamics program.'
+ write ( *, '(a)' ) ' '
+ write ( *, '(a,i8)' )
+ & ' NP, the number of particles in the simulation is ', np
+ write ( *, '(a,i8)' )
+ & ' STEP_NUM, the number of time steps, is ', step_num
+ write ( *, '(a,g14.6)' )
+ & ' DT, the size of each time step, is ', dt
+ write ( *, '(a)' ) ' '
+ write ( *, '(a,i8)' )
+ & ' The number of processors = ', omp_get_num_procs ( )
+ write ( *, '(a,i8)' )
+ & ' The number of threads = ', omp_get_max_threads ( )
+
+ write ( *, '(a)' ) ' '
+ write ( *, '(a)' ) ' Initializing trajectory storage.'
+ call tng_trajectory_init(traj_p)
+
+ call tng_output_file_set(traj, "/tmp/tng_md_out_f77.tng")
+
+ write ( *, '(a)' ) ' Creating molecules in trajectory.'
+ tng_n_particles = np
+ call tng_molecule_add(traj, "water", molecule_p)
+ call tng_molecule_chain_add(traj, molecule, "W", chain_p)
+ call tng_chain_residue_add(traj, chain, "WAT", residue_p)
+ call tng_residue_atom_add(traj, residue, "O", "O", atom_p)
+ call tng_molecule_cnt_set(traj, molecule, tng_n_particles)
+c
+c Set the dimensions of the box.
+c
+ do i = 1, 9
+ box_shape(i) = 0.0
+ end do
+ do i = 1, nd
+ box(i) = 10.0D+00
+ box_shape(i*nd + i) = box(i)
+ end do
+
+c
+c Add the box shape data block
+c
+ call tng_data_block_add(traj, TNG_TRAJ_BOX_SHAPE, "BOX SHAPE",
+ & TNG_DOUBLE_DATA, TNG_NON_TRAJECTORY_BLOCK, int(1, 8),
+ & int(9, 8), int(1, 8), TNG_UNCOMPRESSED, box_shape)
+
+c
+c Write the file headers
+c
+ call tng_file_headers_write(traj, TNG_USE_HASH)
+
+c
+c Set initial positions, velocities, and accelerations.
+c
+ write ( *, '(a)' )
+ & ' Initializing positions, velocities, and accelerations.'
+ seed = 123456789
+ call initialize ( np, nd, box, seed, pos, vel, acc )
+c
+c Compute the forces and energies.
+c
+ write ( *, '(a)' ) ' '
+ write ( *, '(a)' ) ' Computing initial forces and energies.'
+
+ call compute ( np, nd, pos, vel, mass, force, potential,
+ & kinetic )
+
+ e0 = potential + kinetic
+
+c
+c Saving frequency
+c
+ step_save = 5
+
+ step_print = 0
+ step_print_index = 0
+ step_print_num = 10
+
+ frames_saved_cnt = 0
+
+c
+c This is the main time stepping loop.
+c
+ write ( *, '(a,i16)' ) ' Every', step_save,
+ & ' steps particle positions, velocities and forces are'
+ write ( *, '(a)' ) 'saved to a TNG trajectory file.'
+ write ( *, '(a)' )
+ write ( *, '(a)' )
+ & ' At each step, we report the potential and kinetic energies.'
+ write ( *, '(a)' )
+ & ' The sum of these energies should be a constant.'
+ write ( *, '(a)' )
+ & ' As an accuracy check, we also print the relative error'
+ write ( *, '(a)' ) ' in the total energy.'
+ write ( *, '(a)' ) ' '
+ write ( *, '(a)' )
+ & ' Step Potential Kinetic (P+K-E0)/E0'
+ write ( *, '(a)' )
+ & ' Energy P Energy K ' //
+ & 'Relative Energy Error'
+ write ( *, '(a)' ) ' '
+
+ step = 0
+ write ( *, '(2x,i8,2x,g14.6,2x,g14.6,2x,g14.6)' )
+ & step, potential, kinetic, ( potential + kinetic - e0 ) / e0
+ step_print_index = step_print_index + 1
+ step_print = ( step_print_index * step_num ) / step_print_num
+
+c
+c Create a frame set for writing data
+c
+ call tng_num_frames_per_frame_set_get(traj,
+ & n_frames_per_frame_set)
+ call tng_frame_set_new(traj, int(0, 8), n_frames_per_frame_set)
+ frame_set_cnt = frame_set_cnt + 1
+
+c
+c Add empty data blocks
+c
+ call tng_particle_data_block_add(traj, TNG_TRAJ_POSITIONS,
+ & "POSITIONS", TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
+ & n_frames_per_frame_set, int(3, 8), int(1, 8), int(0, 8),
+ & tng_n_particles, TNG_UNCOMPRESSED, %VAL(0))
+
+ call tng_particle_data_block_add(traj, TNG_TRAJ_VELOCITIES,
+ & "VELOCITIES", TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
+ & n_frames_per_frame_set, int(3, 8), int(1, 8), int(0, 8),
+ & tng_n_particles, TNG_UNCOMPRESSED, %VAL(0))
+
+ call tng_particle_data_block_add(traj, TNG_TRAJ_FORCES,
+ & "FORCES", TNG_DOUBLE_DATA, TNG_TRAJECTORY_BLOCK,
+ & n_frames_per_frame_set, int(3, 8), int(1, 8), int(0, 8),
+ & tng_n_particles, TNG_UNCOMPRESSED, %VAL(0))
+
+c
+c Write the frame set to disk
+c
+ call tng_frame_set_write(traj, TNG_SKIP_HASH)
+
+ wtime = omp_get_wtime ( )
+
+ do step = 1, step_num
+
+ call compute ( np, nd, pos, vel, mass, force, potential,
+ & kinetic )
+
+ if ( step .eq. step_print ) then
+
+ write ( *, '(2x,i8,2x,g14.6,2x,g14.6,2x,g14.6)' )
+ & step, potential, kinetic, ( potential + kinetic - e0 ) / e0
+
+ step_print_index = step_print_index + 1
+ step_print = ( step_print_index * step_num ) / step_print_num
+
+ end if
+
+ if ( step_save .EQ. 0 .OR. mod(step, step_save) .EQ. 0 ) then
+ call tng_frame_particle_data_write(traj, frames_saved_cnt,
+ & TNG_TRAJ_POSITIONS, int(0, 8), tng_n_particles, pos,
+ & TNG_USE_HASH)
+ call tng_frame_particle_data_write(traj, frames_saved_cnt,
+ & TNG_TRAJ_VELOCITIES, int(0, 8), tng_n_particles, vel,
+ & TNG_USE_HASH)
+ call tng_frame_particle_data_write(traj, frames_saved_cnt,
+ & TNG_TRAJ_FORCES, int(0, 8), tng_n_particles, force,
+ & TNG_USE_HASH)
+ frames_saved_cnt = frame_set_cnt + 1
+ end if
+
+ call update ( np, nd, pos, vel, force, acc, mass, dt )
+
+ end do
+
+ wtime = omp_get_wtime ( ) - wtime
+
+ write ( *, '(a)' ) ' '
+ write ( *, '(a)' )
+ & ' Elapsed time for main computation:'
+ write ( *, '(2x,g14.6,a)' ) wtime, ' seconds'
+c
+c Terminate.
+c
+ call tng_trajectory_destroy(traj_p)
+
+ write ( *, '(a)' ) ' '
+ write ( *, '(a)' ) 'MD_OPENMP'
+ write ( *, '(a)' ) ' Normal end of execution.'
+
+ write ( *, '(a)' ) ' '
+ call timestamp ( )
+
+ stop
+ end
+ subroutine compute ( np, nd, pos, vel, mass, f, pot, kin )
+
+c*********************************************************************72
+c
+cc COMPUTE computes the forces and energies.
+c
+c Discussion:
+c
+c The computation of forces and energies is fully parallel.
+c
+c Licensing:
+c
+c This code is distributed under the GNU LGPL license.
+c
+c Modified:
+c
+c 31 July 2009
+c
+c Author:
+c
+c Original FORTRAN90 version by Bill Magro.
+c FORTRAN77 version by John Burkardt.
+c
+c Parameters:
+c
+c Input, integer NP, the number of particles.
+c
+c Input, integer ND, the number of spatial dimensions.
+c
+c Input, double precision POS(ND,NP), the position of each particle.
+c
+c Input, double precision VEL(ND,NP), the velocity of each particle.
+c
+c Input, double precision MASS, the mass of each particle.
+c
+ implicit none
+
+ integer np
+ integer nd
+
+ double precision d
+ double precision d2
+ double precision dv
+ double precision f(nd,np)
+ integer i
+ integer j
+ integer k
+ double precision kin
+ double precision mass
+ double precision PI2
+ parameter ( PI2 = 3.141592653589793D+00 / 2.0D+00 )
+ double precision pos(nd,np)
+ double precision pot
+ double precision rij(nd)
+ double precision v
+ double precision vel(nd,np)
+
+ pot = 0.0D+00
+ kin = 0.0D+00
+
+c$omp parallel
+c$omp& shared ( f, nd, np, pos, vel )
+c$omp& private ( d, d2, i, j, k, rij )
+
+c$omp do reduction ( + : pot, kin )
+ do i = 1, np
+c
+c Compute the potential energy and forces.
+c
+ do k = 1, nd
+ f(k,i) = 0.0D+00
+ end do
+
+ do j = 1, np
+
+ if ( i .ne. j ) then
+
+ call dist ( nd, pos(1,i), pos(1,j), rij, d )
+c
+c Attribute half of the potential energy to particle J.
+c
+ d2 = min ( d, pi2 )
+
+ pot = pot + 0.5D+00 * ( sin ( d2 ) )**2
+
+ do k = 1, nd
+ f(k,i) = f(k,i) - rij(k) * sin ( 2.0D+00 * d2 ) / d
+ end do
+
+ end if
+
+ end do
+c
+c Compute the kinetic energy.
+c
+ do k = 1, nd
+ kin = kin + vel(k,i)**2
+ end do
+
+ end do
+c$omp end do
+
+c$omp end parallel
+
+ kin = kin * 0.5D+00 * mass
+
+ return
+ end
+ subroutine dist ( nd, r1, r2, dr, d )
+
+c*********************************************************************72
+c
+cc DIST computes the displacement (and its norm) between two particles.
+c
+c Licensing:
+c
+c This code is distributed under the GNU LGPL license.
+c
+c Modified:
+c
+c 13 November 2007
+c
+c Author:
+c
+c Original FORTRAN90 version by Bill Magro.
+c FORTRAN77 version by John Burkardt.
+c
+c Parameters:
+c
+c Input, integer ND, the number of spatial dimensions.
+c
+c Input, double precision R1(ND), R2(ND), the positions of the particles.
+c
+c Output, double precision DR(ND), the displacement vector.
+c
+c Output, double precision D, the Euclidean norm of the displacement.
+c
+ implicit none
+
+ integer nd
+
+ double precision d
+ double precision dr(nd)
+ integer i
+ double precision r1(nd)
+ double precision r2(nd)
+
+ do i = 1, nd
+ dr(i) = r1(i) - r2(i)
+ end do
+
+ d = 0.0D+00
+ do i = 1, nd
+ d = d + dr(i)**2
+ end do
+ d = sqrt ( d )
+
+ return
+ end
+ subroutine initialize ( np, nd, box, seed, pos, vel, acc )
+
+c*********************************************************************72
+c
+cc INITIALIZE initializes the positions, velocities, and accelerations.
+c
+c Licensing:
+c
+c This code is distributed under the GNU LGPL license.
+c
+c Modified:
+c
+c 13 November 2007
+c
+c Author:
+c
+c Original FORTRAN90 version by Bill Magro.
+c FORTRAN77 version by John Burkardt.
+c
+c Parameters:
+c
+c Input, integer NP, the number of particles.
+c
+c Input, integer ND, the number of spatial dimensions.
+c
+c Input, double precision BOX(ND), specifies the maximum position
+c of particles in each dimension.
+c
+c Input/output, integer SEED, a seed for the random number generator.
+c
+c Output, double precision POS(ND,NP), the position of each particle.
+c
+c Output, double precision VEL(ND,NP), the velocity of each particle.
+c
+c Output, double precision ACC(ND,NP), the acceleration of each particle.
+c
+ implicit none
+
+ integer np
+ integer nd
+
+ double precision acc(nd,np)
+ double precision box(nd)
+ integer i
+ integer j
+ double precision pos(nd,np)
+ double precision r8_uniform_01
+ integer seed
+ double precision vel(nd,np)
+c
+c Give the particles random positions within the box.
+c
+ do i = 1, nd
+ do j = 1, np
+ pos(i,j) = r8_uniform_01 ( seed )
+ end do
+ end do
+
+c$omp parallel
+c$omp& shared ( acc, box, nd, np, pos, vel )
+c$omp& private ( i, j )
+
+c$omp do
+ do j = 1, np
+ do i = 1, nd
+ pos(i,j) = box(i) * pos(i,j)
+ vel(i,j) = 0.0D+00
+ acc(i,j) = 0.0D+00
+ end do
+ end do
+c$omp end do
+
+c$omp end parallel
+
+ return
+ end
+ function r8_uniform_01 ( seed )
+
+c*********************************************************************72
+c
+cc R8_UNIFORM_01 returns a unit pseudorandom R8.
+c
+c Discussion:
+c
+c This routine implements the recursion
+c
+c seed = 16807 * seed mod ( 2**31 - 1 )
+c r8_uniform_01 = seed / ( 2**31 - 1 )
+c
+c The integer arithmetic never requires more than 32 bits,
+c including a sign bit.
+c
+c If the initial seed is 12345, then the first three computations are
+c
+c Input Output R8_UNIFORM_01
+c SEED SEED
+c
+c 12345 207482415 0.096616
+c 207482415 1790989824 0.833995
+c 1790989824 2035175616 0.947702
+c
+c Licensing:
+c
+c This code is distributed under the GNU LGPL license.
+c
+c Modified:
+c
+c 11 August 2004
+c
+c Author:
+c
+c John Burkardt
+c
+c Reference:
+c
+c Paul Bratley, Bennett Fox, Linus Schrage,
+c A Guide to Simulation,
+c Springer Verlag, pages 201-202, 1983.
+c
+c Pierre L'Ecuyer,
+c Random Number Generation,
+c in Handbook of Simulation,
+c edited by Jerry Banks,
+c Wiley Interscience, page 95, 1998.
+c
+c Bennett Fox,
+c Algorithm 647:
+c Implementation and Relative Efficiency of Quasirandom
+c Sequence Generators,
+c ACM Transactions on Mathematical Software,
+c Volume 12, Number 4, pages 362-376, 1986.
+c
+c Peter Lewis, Allen Goodman, James Miller,
+c A Pseudo-Random Number Generator for the System/360,
+c IBM Systems Journal,
+c Volume 8, pages 136-143, 1969.
+c
+c Parameters:
+c
+c Input/output, integer SEED, the "seed" value, which should NOT be 0.
+c On output, SEED has been updated.
+c
+c Output, double precision R8_UNIFORM_01, a new pseudorandom variate,
+c strictly between 0 and 1.
+c
+ implicit none
+
+ double precision r8_uniform_01
+ integer k
+ integer seed
+
+ if ( seed .eq. 0 ) then
+ write ( *, '(a)' ) ' '
+ write ( *, '(a)' ) 'R8_UNIFORM_01 - Fatal error!'
+ write ( *, '(a)' ) ' Input value of SEED = 0.'
+ stop
+ end if
+
+ k = seed / 127773
+
+ seed = 16807 * ( seed - k * 127773 ) - k * 2836
+
+ if ( seed .lt. 0 ) then
+ seed = seed + 2147483647
+ end if
+c
+c Although SEED can be represented exactly as a 32 bit integer,
+c it generally cannot be represented exactly as a 32 bit real number!
+c
+ r8_uniform_01 = dble ( seed ) * 4.656612875D-10
+
+ return
+ end
+ subroutine timestamp ( )
+
+c*********************************************************************72
+c
+cc TIMESTAMP prints out the current YMDHMS date as a timestamp.
+c
+c Licensing:
+c
+c This code is distributed under the GNU LGPL license.
+c
+c Modified:
+c
+c 12 January 2007
+c
+c Author:
+c
+c John Burkardt
+c
+c Parameters:
+c
+c None
+c
+ implicit none
+
+ character * ( 8 ) ampm
+ integer d
+ character * ( 8 ) date
+ integer h
+ integer m
+ integer mm
+ character * ( 9 ) month(12)
+ integer n
+ integer s
+ character * ( 10 ) time
+ integer y
+
+ save month
+
+ data month /
+ & 'January ', 'February ', 'March ', 'April ',
+ & 'May ', 'June ', 'July ', 'August ',
+ & 'September', 'October ', 'November ', 'December ' /
+
+ call date_and_time ( date, time )
+
+ read ( date, '(i4,i2,i2)' ) y, m, d
+ read ( time, '(i2,i2,i2,1x,i3)' ) h, n, s, mm
+
+ if ( h .lt. 12 ) then
+ ampm = 'AM'
+ else if ( h .eq. 12 ) then
+ if ( n .eq. 0 .and. s .eq. 0 ) then
+ ampm = 'Noon'
+ else
+ ampm = 'PM'
+ end if
+ else
+ h = h - 12
+ if ( h .lt. 12 ) then
+ ampm = 'PM'
+ else if ( h .eq. 12 ) then
+ if ( n .eq. 0 .and. s .eq. 0 ) then
+ ampm = 'Midnight'
+ else
+ ampm = 'AM'
+ end if
+ end if
+ end if
+
+ write ( *,
+ & '(i2,1x,a,1x,i4,2x,i2,a1,i2.2,a1,i2.2,a1,i3.3,1x,a)' )
+ & d, month(m), y, h, ':', n, ':', s, '.', mm, ampm
+
+ return
+ end
+ subroutine update ( np, nd, pos, vel, f, acc, mass, dt )
+
+c*********************************************************************72
+c
+cc UPDATE performs the time integration, using a velocity Verlet algorithm.
+c
+c Discussion:
+c
+c The time integration is fully parallel.
+c
+c Licensing:
+c
+c This code is distributed under the GNU LGPL license.
+c
+c Modified:
+c
+c 13 November 2007
+c
+c Author:
+c
+c Original FORTRAN90 version by Bill Magro.
+c FORTRAN77 version by John Burkardt.
+c
+c Parameters:
+c
+c Input, integer NP, the number of particles.
+c
+c Input, integer ND, the number of spatial dimensions.
+c
+c Input/output, double precision POS(ND,NP), the position of each particle.
+c
+c Input/output, double precision VEL(ND,NP), the velocity of each particle.
+c
+c Input, double precision MASS, the mass of each particle.
+c
+c Input/output, double precision ACC(ND,NP), the acceleration of each
+c particle.
+c
+ implicit none
+
+ integer np
+ integer nd
+
+ double precision acc(nd,np)
+ double precision dt
+ double precision f(nd,np)
+ integer i
+ integer j
+ double precision mass
+ double precision pos(nd,np)
+ double precision rmass
+ double precision vel(nd,np)
+
+ rmass = 1.0D+00 / mass
+
+c$omp parallel
+c$omp& shared ( acc, dt, f, nd, np, pos, rmass, vel )
+c$omp& private ( i, j )
+
+c$omp do
+ do j = 1, np
+ do i = 1, nd
+
+ pos(i,j) = pos(i,j)
+ & + vel(i,j) * dt + 0.5D+00 * acc(i,j) * dt * dt
+
+ vel(i,j) = vel(i,j)
+ & + 0.5D+00 * dt * ( f(i,j) * rmass + acc(i,j) )
+
+ acc(i,j) = f(i,j) * rmass
+
+ end do
+ end do
+c$omp end do
+
+c$omp end parallel
+
+ return
+ end
diff --git a/src/tests/tng_io_read_pos.c b/src/tests/tng_io_read_pos.c
new file mode 100644
index 0000000..4ab27da
--- /dev/null
+++ b/src/tests/tng_io_read_pos.c
@@ -0,0 +1,97 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <tng_io.h>
+
+int main(int argc, char **argv)
+{
+ tng_trajectory_t traj;
+ union data_values ***positions = 0; // A 3-dimensional array to be populated
+ int64_t n_particles, n_values_per_frame, n_frames;
+ tng_data_type data_type;
+ int i, j;
+ int64_t particle = 0;
+ // Set a default frame range
+ int first_frame = 0, last_frame = 50;
+
+ if(argc <= 1)
+ {
+ printf("No file specified\n");
+ printf("Usage:\n");
+ printf("tng_io_read_pos <tng_file> [particle number = %"PRId64"] "
+ "[first_frame = %d] [last_frame = %d]\n",
+ particle, first_frame, last_frame);
+ exit(1);
+ }
+
+ // A reference must be passed to allocate memory
+ if(tng_trajectory_init(&traj) != TNG_SUCCESS)
+ {
+ tng_trajectory_destroy(&traj);
+ exit(1);
+ }
+ tng_input_file_set(traj, argv[1]);
+
+ // Read the file headers
+ tng_file_headers_read(traj, TNG_USE_HASH);
+
+ if(argc >= 3)
+ {
+ particle = strtoll(argv[2], 0, 10);
+ if(argc >= 4)
+ {
+ first_frame = strtoll(argv[3], 0, 10);
+ if(argc >= 5)
+ {
+ last_frame = strtoll(argv[4], 0, 10);
+ }
+ }
+ }
+
+ n_frames = last_frame - first_frame + 1;
+
+ // Get the positions of all particles in the requested frame range.
+ // The positions are stored in the positions array.
+ // N.B. No proper error checks.
+ if(tng_particle_data_interval_get(traj, TNG_TRAJ_POSITIONS, first_frame,
+ last_frame, TNG_USE_HASH, &positions, &n_particles, &n_values_per_frame,
+ &data_type) != TNG_SUCCESS)
+ {
+ printf("Cannot read positions\n");
+ }
+ else
+ {
+ // Print the positions of the wanted particle (zero based)
+ for(i=first_frame; i<=last_frame; i++)
+ {
+ printf("%d", i);
+ for(j=0; j<n_values_per_frame; j++)
+ {
+ switch(data_type)
+ {
+ case TNG_INT_DATA:
+ printf("\t%"PRId64"", positions[i][particle][j].i);
+ break;
+ case TNG_FLOAT_DATA:
+ printf("\t%f", positions[i][particle][j].f);
+ break;
+ case TNG_DOUBLE_DATA:
+ printf("\t%f", positions[i][particle][j].d);
+ break;
+ default:
+ break;
+ }
+ printf("\n");
+ }
+ }
+ }
+
+ // Free memory
+ if(positions)
+ {
+ tng_particle_data_values_free(positions, n_frames, n_particles,
+ n_values_per_frame, data_type);
+ }
+ tng_trajectory_destroy(&traj);
+
+ return(0);
+}
contact: Jan Huwald // Impressum