static void *open_tng_write(const char *filename, const char*, int natoms) { tngdata *tng; tng_function_status stat; // int64_t n, exp; tng = new tngdata; stat = tng_util_trajectory_open(filename, 'w', &tng->tng_traj); if(stat != TNG_SUCCESS) { fprintf(stderr, "tngplugin) Cannot open file '%s'\n", filename); return NULL; } tng->natoms = natoms; tng->step = 0; tng->coord_exponential = -10; tng_distance_unit_exponential_set(tng->tng_traj, -10); tng->time_per_frame = -1; return tng; }
static void *open_tng_read(const char *filename, const char*, int *natoms) { tngdata *tng; tng_function_status stat; int64_t n, exp; tng = new tngdata; stat = tng_util_trajectory_open(filename, 'r', &tng->tng_traj); if(stat != TNG_SUCCESS) { fprintf(stderr, "tngplugin) Cannot open file '%s'\n", filename); return NULL; } tng_num_particles_get(tng->tng_traj, &n); *natoms = (int)n; tng->natoms = (int)n; tng->step = 0; tng_num_frames_get(tng->tng_traj, &n); tng->n_frames = n; tng->has_velocities = 0; tng_distance_unit_exponential_get(tng->tng_traj, &exp); tng->coord_exponential = (int) exp; return tng; }
void gmx_tng_open(const char *filename, char mode, tng_trajectory_t *tng) { #ifdef GMX_USE_TNG /* First check whether we have to make a backup, * only for writing, not for read or append. */ if (mode == 'w') { #ifndef GMX_FAHCORE /* only make backups for normal gromacs */ make_backup(filename); #endif } /* tng must not be pointing at already allocated memory. * Memory will be allocated by tng_util_trajectory_open() and must * later on be freed by tng_util_trajectory_close(). */ if (TNG_SUCCESS != tng_util_trajectory_open(filename, mode, tng)) { /* TNG does return more than one degree of error, but there is no use case for GROMACS handling the non-fatal errors gracefully. */ gmx_fatal(FARGS, "%s while opening %s for %s", gmx_strerror("file"), filename, modeToVerb(mode)); } if (mode == 'w' || mode == 'a') { /* FIXME in TNG: When adding data to the header, subsequent blocks might get * overwritten. This could be solved by moving the first trajectory * frame set(s) to the end of the file. Could that cause other problems, * e.g. when continuing a simulation? */ char hostname[256]; gmx_gethostname(hostname, 256); if (mode == 'w') { tng_first_computer_name_set(*tng, hostname); } /* TODO: This should be implemented when the above fixme is done (adding data to * the header). */ // else // { // tng_last_computer_name_set(*tng, hostname); // } char programInfo[256]; const char *precisionString = ""; #ifdef GMX_DOUBLE precisionString = " (double precision)"; #endif sprintf(programInfo, "%.100s, %.128s%.24s", gmx::getProgramContext().displayName(), GromacsVersion(), precisionString); if (mode == 'w') { tng_first_program_name_set(*tng, programInfo); } /* TODO: This should be implemented when the above fixme is done (adding data to * the header). */ // else // { // tng_last_program_name_set(*tng, programInfo); // } #ifdef HAVE_UNISTD_H char username[256]; getlogin_r(username, 256); if (mode == 'w') { tng_first_user_name_set(*tng, username); } /* TODO: This should be implemented when the above fixme is done (adding data to * the header). */ // else // { // tng_last_user_name_set(*tng, username); // } #endif } #else gmx_file("GROMACS was compiled without TNG support, cannot handle this file type"); GMX_UNUSED_VALUE(filename); GMX_UNUSED_VALUE(mode); GMX_UNUSED_VALUE(tng); #endif }
int main () /******************************************************************************/ /* Purpose: MAIN is the main program for MD_OPENMP. Discussion: MD implements a simple molecular dynamics simulation. The program uses Open MP directives to allow parallel computation. The velocity Verlet time integration scheme is used. The particles interact with a central pair potential. Output of the program is saved in the TNG format, which is why this code is included in the TNG API release. The high-level API of the TNG API is used where appropriate. Licensing: This code is distributed under the GNU LGPL license. Modified: 8 Jan 2013 Author: Original FORTRAN77 version by Bill Magro. C version by John Burkardt. TNG trajectory output by Magnus Lundborg. Parameters: None */ { float *acc; float *box; float *box_shape; float dt = 0.0002; float e0; float *force; int i; float kinetic; float mass = 1.0; int nd = 3; int np = 50; float *pos; float potential; int proc_num; int seed = 123456789; int step; int step_num = 50000; int step_print; int step_print_index; int step_print_num; int step_save; float *vel; float wtime; tng_trajectory_t traj; tng_molecule_t molecule; tng_chain_t chain; tng_residue_t residue; tng_atom_t atom; timestamp ( ); proc_num = omp_get_num_procs ( ); acc = ( float * ) malloc ( nd * np * sizeof ( float ) ); box = ( float * ) malloc ( nd * sizeof ( float ) ); box_shape = (float *) malloc (9 * sizeof (float)); force = ( float * ) malloc ( nd * np * sizeof ( float ) ); pos = ( float * ) malloc ( nd * np * sizeof ( float ) ); vel = ( float * ) malloc ( nd * np * sizeof ( float ) ); printf ( "\n" ); printf ( "MD_OPENMP\n" ); printf ( " C/OpenMP version\n" ); printf ( "\n" ); printf ( " A molecular dynamics program.\n" ); printf ( "\n" ); printf ( " NP, the number of particles in the simulation is %d\n", np ); printf ( " STEP_NUM, the number of time steps, is %d\n", step_num ); printf ( " DT, the size of each time step, is %f\n", dt ); printf ( "\n" ); printf ( " Number of processors available = %d\n", proc_num ); printf ( " Number of threads = %d\n", omp_get_max_threads ( ) ); printf("\n"); printf(" Initializing trajectory storage.\n"); /* Initialize the TNG trajectory */ tng_util_trajectory_open(TNG_EXAMPLE_FILES_DIR "tng_md_out.tng", 'w', &traj); /* Set molecules data */ /* N.B. This is still not done using utility functions. The low-level API * is used. */ printf(" Creating molecules in trajectory.\n"); tng_molecule_add(traj, "water", &molecule); tng_molecule_chain_add(traj, molecule, "W", &chain); tng_chain_residue_add(traj, chain, "WAT", &residue); if(tng_residue_atom_add(traj, residue, "O", "O", &atom) == TNG_CRITICAL) { tng_util_trajectory_close(&traj); printf(" Cannot create molecules.\n"); exit(1); } tng_molecule_cnt_set(traj, molecule, np); /* Set the dimensions of the box. */ for(i = 0; i < 9; i++) { box_shape[i] = 0.0; } for ( i = 0; i < nd; i++ ) { box[i] = 10.0; /* box_shape stores 9 values according to the TNG specs */ box_shape[i*nd + i] = box[i]; } printf ( "\n" ); printf ( " Initializing positions, velocities, and accelerations.\n" ); /* Set initial positions, velocities, and accelerations. */ initialize ( np, nd, box, &seed, pos, vel, acc ); /* Compute the forces and energies. */ printf ( "\n" ); printf ( " Computing initial forces and energies.\n" ); compute ( np, nd, pos, vel, mass, force, &potential, &kinetic ); e0 = potential + kinetic; /* Saving frequency */ step_save = 400; step_print = 0; step_print_index = 0; step_print_num = 10; /* This is the main time stepping loop: Compute forces and energies, Update positions, velocities, accelerations. */ printf(" Every %d steps box shape, particle positions, velocities and forces are\n", step_save); printf(" saved to a TNG trajectory file.\n"); printf ( "\n" ); printf ( " At certain step intervals, we report the potential and kinetic energies.\n" ); printf ( " The sum of these energies should be a constant.\n" ); printf ( " As an accuracy check, we also print the relative error\n" ); printf ( " in the total energy.\n" ); printf ( "\n" ); printf ( " Step Potential Kinetic (P+K-E0)/E0\n" ); printf ( " Energy P Energy K Relative Energy Error\n" ); printf ( "\n" ); step = 0; printf ( " %8d %14f %14f %14e\n", step, potential, kinetic, ( potential + kinetic - e0 ) / e0 ); step_print_index++; step_print = ( step_print_index * step_num ) / step_print_num; /* Set the output frequency of box shape, positions, velocities and forces */ if(tng_util_box_shape_write_frequency_set(traj, step_save) != TNG_SUCCESS) { printf("Error setting writing frequency data. %s: %d\n", __FILE__, __LINE__); exit(1); } if(tng_util_pos_write_frequency_set(traj, step_save) != TNG_SUCCESS) { printf("Error setting writing frequency data. %s: %d\n", __FILE__, __LINE__); exit(1); } if(tng_util_vel_write_frequency_set(traj, step_save) != TNG_SUCCESS) { printf("Error setting writing frequency data. %s: %d\n", __FILE__, __LINE__); exit(1); } if(tng_util_force_write_frequency_set(traj, step_save) != TNG_SUCCESS) { printf("Error setting writing frequency data. %s: %d\n", __FILE__, __LINE__); exit(1); } /* Write the first frame of box shape, positions, velocities and forces */ if(tng_util_box_shape_write(traj, 0, box_shape) != TNG_SUCCESS) { printf("Error writing box shape. %s: %d\n", __FILE__, __LINE__); exit(1); } if(tng_util_pos_write(traj, 0, pos) != TNG_SUCCESS) { printf("Error adding data. %s: %d\n", __FILE__, __LINE__); exit(1); } if(tng_util_vel_write(traj, 0, vel) != TNG_SUCCESS) { printf("Error adding data. %s: %d\n", __FILE__, __LINE__); exit(1); } if(tng_util_force_write(traj, 0, force) != TNG_SUCCESS) { printf("Error adding data. %s: %d\n", __FILE__, __LINE__); exit(1); } wtime = omp_get_wtime ( ); for ( step = 1; step < step_num; step++ ) { compute ( np, nd, pos, vel, mass, force, &potential, &kinetic ); if ( step == step_print ) { printf ( " %8d %14f %14f %14e\n", step, potential, kinetic, ( potential + kinetic - e0 ) / e0 ); step_print_index++; step_print = ( step_print_index * step_num ) / step_print_num; } if(step % step_save == 0) { /* Write box shape, positions, velocities and forces */ if(tng_util_box_shape_write(traj, step, box_shape) != TNG_SUCCESS) { printf("Error writing box shape. %s: %d\n", __FILE__, __LINE__); exit(1); } if(tng_util_pos_write(traj, step, pos) != TNG_SUCCESS) { printf("Error adding data. %s: %d\n", __FILE__, __LINE__); break; } if(tng_util_vel_write(traj, step, vel) != TNG_SUCCESS) { printf("Error adding data. %s: %d\n", __FILE__, __LINE__); break; } if(tng_util_force_write(traj, step, force) != TNG_SUCCESS) { printf("Error adding data. %s: %d\n", __FILE__, __LINE__); break; } } update ( np, nd, pos, vel, force, acc, mass, dt ); } wtime = omp_get_wtime ( ) - wtime; printf ( "\n" ); printf ( " Elapsed time for main computation:\n" ); printf ( " %f seconds.\n", wtime ); free ( acc ); free ( box ); free ( box_shape ); free ( force ); free ( pos ); free ( vel ); /* Close the TNG output. */ tng_util_trajectory_close(&traj); printf ( "\n" ); printf ( "MD_OPENMP\n" ); printf ( " Normal end of execution.\n" ); printf ( "\n" ); timestamp ( ); return 0; }