-
Kurt A. O'Hearn authoredKurt A. O'Hearn authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
tool_box.c 11.06 KiB
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reax_types.h"
#if defined(PURE_REAX)
#include "tool_box.h"
#elif defined(LAMMPS_REAX)
#include "reax_tool_box.h"
#endif
/************** taken from comm_tools.c **************/
int SumScan( int n, int me, int root, MPI_Comm comm )
{
int i, my_order, wsize;
int *nbuf = NULL;
if ( me == root )
{
MPI_Comm_size( comm, &wsize );
nbuf = (int *) scalloc( wsize, sizeof(int), "SumScan:nbuf" );
MPI_Gather( &n, 1, MPI_INT, nbuf, 1, MPI_INT, root, comm );
for ( i = 0; i < wsize - 1; ++i )
{
nbuf[i + 1] += nbuf[i];
}
MPI_Scatter( nbuf, 1, MPI_INT, &my_order, 1, MPI_INT, root, comm );
sfree( nbuf, "SumScan:nbuf" );
}
else
{
MPI_Gather( &n, 1, MPI_INT, nbuf, 1, MPI_INT, root, comm );
MPI_Scatter( nbuf, 1, MPI_INT, &my_order, 1, MPI_INT, root, comm );
}
return my_order;
}
void SumScanB( int n, int me, int wsize, int root, MPI_Comm comm, int *nbuf )
{
int i;
MPI_Gather( &n, 1, MPI_INT, nbuf, 1, MPI_INT, root, comm );
if ( me == root )
{
for ( i = 0; i < wsize - 1; ++i )
{
nbuf[i + 1] += nbuf[i];
}
}
MPI_Bcast( nbuf, wsize, MPI_INT, root, comm );
}
/* determine whether point p is inside the box */
void Fit_to_Periodic_Box( simulation_box *box, rvec *p )
{
int i;
for ( i = 0; i < 3; ++i )
{
if ( (*p)[i] < box->min[i] )
{
/* handle lower coords */
while ( (*p)[i] < box->min[i] )
{
(*p)[i] += box->box_norms[i];
}
}
else if ( (*p)[i] >= box->max[i] )
{
/* handle higher coords */
while ( (*p)[i] >= box->max[i] )
{
(*p)[i] -= box->box_norms[i];
}
}
}
}
/************** from geo_tools.c *****************/
void Make_Point( real x, real y, real z, rvec* p )
{
(*p)[0] = x;
(*p)[1] = y;
(*p)[2] = z;
}
int is_Valid_Serial( storage *workspace, int serial )
{
// if( workspace->map_serials[ serial ] < 0 )
// {
// fprintf( stderr, "CONECT line includes invalid pdb serial number %d.\n",
// serial );
// fprintf( stderr, "Please correct the input file.Terminating...\n" );
// MPI_Abort( MPI_COMM_WORLD, INVALID_INPUT );
// }
return SUCCESS;
}
int Check_Input_Range( int val, int lo, int hi, char *message )
{
if ( val < lo || val > hi )
{
fprintf( stderr, "%s\nInput %d - Out of range %d-%d. Terminating...\n",
message, val, lo, hi );
MPI_Abort( MPI_COMM_WORLD, INVALID_INPUT );
}
return 1;
}
void Trim_Spaces( char *element )
{
int i, j;
// skip initial space chars
for ( i = 0; element[i] == ' '; ++i );
for ( j = i; j < (int)(strlen(element)) && element[j] != ' '; ++j )
{
// make uppercase, offset to 0
element[j - i] = toupper( element[j] );
}
// finalize the string
element[j - i] = 0;
}
/************ from system_props.c *************/
real Get_Time( )
{
struct timeval tim;
gettimeofday( &tim, NULL );
return ( tim.tv_sec + (tim.tv_usec / 1000000.0) );
}
real Get_Timing_Info( real t_start )
{
struct timeval tim;
real t_end;
gettimeofday(&tim, NULL );
t_end = tim.tv_sec + (tim.tv_usec / 1000000.0);
return (t_end - t_start);
}
void Update_Timing_Info( real *t_start, real *timing )
{
struct timeval tim;
real t_end;
gettimeofday( &tim, NULL );
t_end = tim.tv_sec + (tim.tv_usec / 1000000.0);
*timing += (t_end - *t_start);
*t_start = t_end;
}
/*********** from io_tools.c **************/
int Get_Atom_Type( reax_interaction *reax_param, char *s )
{
int i, ret, flag;
flag = FAILURE;
for ( i = 0; i < reax_param->num_atom_types; ++i )
{
if ( strncmp( reax_param->sbp[i].name, s, 15 ) == 0 )
{
ret = i;
flag = SUCCESS;
break;
}
}
if ( flag == FAILURE )
{
fprintf( stderr, "Unknown atom type (%s). Terminating...\n", s );
MPI_Abort( MPI_COMM_WORLD, UNKNOWN_ATOM_TYPE );
}
return ret;
}
char *Get_Element( reax_system *system, int i )
{
return &system->reax_param.sbp[system->my_atoms[i].type].name[0];
}
char *Get_Atom_Name( reax_system *system, int i )
{
return &system->my_atoms[i].name[0];
}
void Allocate_Tokenizer_Space( char **line, char **backup, char ***tokens )
{
int i;
*line = (char*) smalloc( sizeof(char) * MAX_LINE, "Tokenizer:line" );
*backup = (char*) smalloc( sizeof(char) * MAX_LINE, "Tokenizer:backup" );
*tokens = (char**) smalloc( sizeof(char*) * MAX_TOKENS, "Tokenizer:tokens" );
for ( i = 0; i < MAX_TOKENS; i++ )
{
(*tokens)[i] = (char*) smalloc(sizeof(char) * MAX_TOKEN_LEN, "Tokenizer:tokens[i]" );
}
}
int Tokenize( const char* s, char*** tok )
{
char test[MAX_LINE];
char *sep = "\t \n!=";
char *word, *saveptr;
int count = 0;
strncpy( test, s, MAX_LINE );
for ( word = strtok_r(test, sep, &saveptr); word; word = strtok_r(NULL, sep, &saveptr) )
{
strncpy( (*tok)[count], word, MAX_LINE );
count++;
}
return count;
}
/* Safe wrapper around libc malloc
*
* n: num. of bytes to allocated
* name: message with details about pointer, used for warnings/errors
*
* returns: ptr to allocated memory
* */
void * smalloc( size_t n, const char *name )
{
void *ptr;
if ( n == 0 )
{
fprintf( stderr, "[ERROR] failed to allocate %zu bytes for array %s.\n",
n, name );
exit( INSUFFICIENT_MEMORY );
}
#if defined(DEBUG)
fprintf( stderr, "[INFO] requesting %zu bytes for %s\n", n, name );
fflush( stderr );
#endif
ptr = malloc( n );
if ( ptr == NULL )
{
fprintf( stderr, "[ERROR] failed to allocate %zu bytes for array %s.\n",
n, name );
exit( INSUFFICIENT_MEMORY );
}
#if defined(DEBUG)
fprintf( stderr, "[INFO] granted memory at address: %p\n", ptr );
fflush( stderr );
#endif
return ptr;
}
/* Safe wrapper around libc realloc
*
* n: num. of bytes to reallocated
* name: message with details about pointer, used for warnings/errors
*
* returns: ptr to reallocated memory
* */
void * srealloc( void *ptr, size_t n, const char *name )
{
void *new_ptr;
if ( n == 0 )
{
fprintf( stderr, "[ERROR] failed to reallocate %zu bytes for array %s.\n",
n, name );
exit( INSUFFICIENT_MEMORY );
}
#if defined(DEBUG)
if ( ptr == NULL )
{
fprintf( stderr, "[INFO] trying to allocate %zu NEW bytes for array %s.\n",
n, name );
}
fprintf( stderr, "[INFO] requesting %zu bytes for %s\n", n, name );
fflush( stderr );
#endif
new_ptr = realloc( ptr, n );
/* technically, ptr may still be allocated and valid,
* but we needed more memory, so abort */
if ( new_ptr == NULL )
{
fprintf( stderr, "[ERROR] failed to reallocate %zu bytes for array %s.\n",
n, name );
exit( INSUFFICIENT_MEMORY );
}
#if defined(DEBUG)
fprintf( stderr, "[INFO] granted memory at address: %p\n", new_ptr );
fflush( stderr );
#endif
return new_ptr;
}
/* Safe wrapper around libc calloc
*
* n: num. of elements to allocated (each of size bytes)
* size: num. of bytes per element
* name: message with details about pointer, used for warnings/errors
*
* returns: ptr to allocated memory, all bits initialized to zeros
* */
void * scalloc( size_t n, size_t size, const char *name )
{
void *ptr;
if ( n == 0 )
{
fprintf( stderr, "[ERROR] failed to allocate %zu bytes for array %s.\n",
n * size, name );
exit( INSUFFICIENT_MEMORY );
}
#if defined(DEBUG)
fprintf( stderr, "[INFO] requesting %zu bytes for %s\n", n * size, name );
fflush( stderr );
#endif
ptr = calloc( n, size );
if ( ptr == NULL )
{
fprintf( stderr, "[ERROR] failed to allocate %zu bytes for array %s.\n",
n * size, name );
exit( INSUFFICIENT_MEMORY );
}
#if defined(DEBUG)
fprintf( stderr, "[INFO] granted memory at address: %p\n", ptr );
fflush( stderr );
#endif
return ptr;
}
/* Safe wrapper around libc free
*
* ptr: pointer to dynamically allocated memory which will be deallocated
* name: message with details about pointer, used for warnings/errors
* */
void sfree( void *ptr, const char *name )
{
if ( ptr == NULL )
{
fprintf( stderr, "[WARNING] trying to free the already NULL pointer %s!\n",
name );
return;
}
#if defined(DEBUG)
fprintf( stderr, "[INFO] trying to free pointer (%s), address: %p\n",
name, (void *) ptr );
fflush( stderr );
#endif
free( ptr );
}
/* Safe wrapper around libc fopen
*
* fname: name of file to be opened
* mode: mode in which to open file
* msg: message to be printed in case of error
* */
FILE * sfopen( const char * fname, const char * mode, const char * msg )
{
FILE * ptr;
if ( fname == NULL )
{
fprintf( stderr, "[ERROR] trying to open file: NULL file name (%s). Terminating...\n",
msg );
exit( INVALID_INPUT );
}
if ( mode == NULL )
{
fprintf( stderr, "[ERROR] trying to open file: NULL mode (%s). Terminating...\n",
msg );
exit( INVALID_INPUT );
}
ptr = fopen( fname, mode );
if ( ptr == NULL )
{
fprintf( stderr, "[ERROR] failed to open file %s with mode %s (%s)\n",
fname, mode, msg );
exit( INVALID_INPUT );
}
return ptr;
}
/* Safe wrapper around libc fclose
*
* fname: name of file to be opened
* mode: mode in which to open file
* msg: message to be printed in case of error
* */
void sfclose( FILE * fp, const char * msg )
{
int ret;
if ( fp == NULL )
{
fprintf( stderr, "[WARNING] trying to close NULL file pointer (%s). Returning...\n", msg );
return;
}
ret = fclose( fp );
if ( ret != 0 )
{
fprintf( stderr, "[ERROR] error detected when closing file (%s). Terminating...\n", msg );
exit( INVALID_INPUT );
}
}