From b1e52a8b836ed2a15d743ab536e6283ac6fdd4d3 Mon Sep 17 00:00:00 2001 From: "Kurt A. O'Hearn" <ohearnku@msu.edu> Date: Thu, 7 Oct 2021 00:03:50 -0400 Subject: [PATCH] sPuReMD: rework memory management logic to better match PG-PuReMD code. Adapt new memory management logic for multiple simulation logic (as motivated by memory issues observed with QM/MM code for AMBER integration work). Other code clean-up. --- sPuReMD/src/allocate.c | 196 ++--- sPuReMD/src/allocate.h | 9 +- sPuReMD/src/box.c | 153 ++-- sPuReMD/src/box.h | 22 +- sPuReMD/src/forces.c | 1372 +++++++++++++++------------------- sPuReMD/src/forces.h | 11 +- sPuReMD/src/init_md.c | 266 +++---- sPuReMD/src/integrate.c | 757 ++++++++++++------- sPuReMD/src/integrate.h | 14 +- sPuReMD/src/list.c | 25 +- sPuReMD/src/list.h | 27 +- sPuReMD/src/neighbors.c | 57 +- sPuReMD/src/neighbors.h | 8 +- sPuReMD/src/reax_types.h | 98 ++- sPuReMD/src/reset_tools.c | 3 +- sPuReMD/src/spuremd.c | 89 ++- sPuReMD/src/system_props.c | 9 +- sPuReMD/src/system_props.h | 6 +- sPuReMD/src/valence_angles.c | 14 +- 19 files changed, 1617 insertions(+), 1519 deletions(-) diff --git a/sPuReMD/src/allocate.c b/sPuReMD/src/allocate.c index 4f980bc8..c235913a 100644 --- a/sPuReMD/src/allocate.c +++ b/sPuReMD/src/allocate.c @@ -21,6 +21,7 @@ #include "allocate.h" +#include "grid.h" #include "list.h" #include "tool_box.h" @@ -97,7 +98,8 @@ void PreAllocate_Space( reax_system * const system, } -static void Reallocate_Neighbor_List( reax_list *far_nbr_list, int n, int n_max, int num_intrs ) +static void Reallocate_Neighbor_List( reax_list * const far_nbr_list, int n, + int n_max, int num_intrs ) { if ( far_nbr_list->allocated == TRUE ) { @@ -146,7 +148,6 @@ void Deallocate_Matrix( sparse_matrix * const H ) static void Reallocate_Matrix( sparse_matrix *H, int n, int n_max, int m ) { Deallocate_Matrix( H ); - Allocate_Matrix( H, n, n_max, m ); } @@ -178,177 +179,104 @@ void Initialize_HBond_List( int n, int const * const h_index, } -static void Reallocate_Initialize_HBond_List( int n, int num_h, int num_h_max, - int *h_index, reax_list *hbond_list ) +static void Reallocate_List( reax_list * const list, int n, int n_max, + int max_intrs, int type ) { - int i, num_hbonds, *hb_top; - - hb_top = scalloc( n, sizeof(int), __FILE__, __LINE__ ); - num_hbonds = 0; - - for ( i = 0; i < n; ++i ) - { - if ( h_index[i] >= 0 ) - { - hb_top[i] = MAX( Num_Entries( h_index[i], hbond_list ) * SAFE_HBONDS, - MIN_HBONDS ); - num_hbonds += hb_top[i]; - } - } - - if ( hbond_list->allocated == TRUE ) + if ( list->allocated == TRUE ) { - Delete_List( TYP_HBOND, hbond_list ); + Delete_List( type, list ); } - Make_List( num_h, num_h_max, num_hbonds, TYP_HBOND, hbond_list ); - - Initialize_HBond_List( n, h_index, hb_top, hbond_list ); - - sfree( hb_top, __FILE__, __LINE__ ); + Make_List( n, n_max, max_intrs, type, list ); } -void Initialize_Bond_List( int * const bond_top, - reax_list * const bond_list ) +void Reallocate_Part1( reax_system * const system, control_params const * const control, + static_storage * const workspace, reax_list ** const lists ) { - int i; + int i, j, k; + reallocate_data *realloc; + grid *g; - /* find starting indexes for each atom and the total number of bonds */ - for ( i = 1; i < bond_list->n; ++i ) - { - bond_top[i] += bond_top[i - 1]; - } + realloc = &workspace->realloc; + g = &system->g; - Set_Start_Index( 0, 0, bond_list ); - Set_End_Index( 0, 0, bond_list ); - for ( i = 1; i < bond_list->n; ++i ) + if ( realloc->gcell_atoms > -1 ) { - Set_Start_Index( i, bond_top[i - 1], bond_list ); - Set_End_Index( i, bond_top[i - 1], bond_list ); - } -} - - -static void Reallocate_Initialize_Bond_List( int n, int n_max, - reax_list *bond_list, int *num_bonds, int *est_3body ) -{ - int i; - int *bond_top; - - bond_top = scalloc( n, sizeof(int), __FILE__, __LINE__ ); - *num_bonds = 0; - *est_3body = 0; +#if defined(DEBUG_FOCUS) + fprintf( stderr, "[INFO] reallocating gcell: g->max_atoms: %d\n", g->max_atoms ); +#endif - for ( i = 0; i < n; ++i ) - { - *est_3body += SQR( Num_Entries( i, bond_list ) ); - bond_top[i] = MAX( Num_Entries( i, bond_list ) * 2, MIN_BONDS ); - *num_bonds += bond_top[i]; - } + for ( i = 0; i < g->ncell_max[0]; i++ ) + { + for ( j = 0; j < g->ncell_max[1]; j++ ) + { + for ( k = 0; k < g->ncell_max[2]; k++ ) + { + sfree( g->atoms[i][j][k], __FILE__, __LINE__ ); + g->atoms[i][j][k] = scalloc( workspace->realloc.gcell_atoms, + sizeof(int), __FILE__, __LINE__ ); + } + } + } - if ( bond_list->allocated == TRUE ) - { - Delete_List( TYP_BOND, bond_list ); + realloc->gcell_atoms = -1; } - Make_List( n, n_max, (int) CEIL( *num_bonds * SAFE_ZONE ), - TYP_BOND, bond_list ); - - Initialize_Bond_List( bond_top, bond_list ); - - sfree( bond_top, __FILE__, __LINE__ ); } -void Reallocate( reax_system * const system, control_params const * const control, - static_storage * const workspace, reax_list ** const lists, - int nbr_flag ) +void Reallocate_Part2( reax_system const * const system, + control_params const * const control, simulation_data const * const data, + static_storage * const workspace, reax_list ** const lists ) { - int i, j, k; - int num_bonds, est_3body; + int renbr; reallocate_data *realloc; - grid *g; realloc = &workspace->realloc; - g = &system->g; + renbr = ((data->step - data->prev_steps) % control->reneighbor) == 0 ? TRUE : FALSE; - if ( realloc->num_far > 0 && nbr_flag == TRUE ) + if ( renbr == TRUE && realloc->far_nbrs == TRUE ) { Reallocate_Neighbor_List( lists[FAR_NBRS], - system->N, system->N_max, realloc->num_far * SAFE_ZONE ); - realloc->num_far = -1; + system->N, system->N_max, realloc->total_far_nbrs ); + Init_List_Indices( lists[FAR_NBRS] ); + + realloc->far_nbrs = FALSE; } - if ( realloc->Htop > 0 ) + if ( realloc->cm == TRUE ) { Reallocate_Matrix( &workspace->H, system->N_cm, system->N_cm_max, - realloc->Htop * SAFE_ZONE ); - realloc->Htop = -1; + realloc->total_cm_entries ); - Deallocate_Matrix( &workspace->L ); - Deallocate_Matrix( &workspace->U ); + realloc->cm = FALSE; } - if ( control->hbond_cut > 0.0 && realloc->hbonds > 0 ) + if ( realloc->bonds == TRUE ) { - Reallocate_Initialize_HBond_List( system->N, workspace->num_H, - workspace->num_H_max, workspace->hbond_index, lists[HBONDS] ); - realloc->hbonds = -1; - } + Reallocate_List( lists[BONDS], system->N, system->N_max, + realloc->total_bonds, TYP_BOND ); + Init_List_Indices( lists[BONDS] ); - num_bonds = est_3body = -1; - if ( realloc->bonds > 0 ) - { - Reallocate_Initialize_Bond_List( system->N, system->N_max, lists[BONDS], &num_bonds, &est_3body ); - realloc->bonds = -1; - realloc->num_3body = MAX( realloc->num_3body, est_3body ); + realloc->bonds = FALSE; + realloc->thbody = TRUE; } - if ( realloc->num_3body > 0 ) + if ( control->hbond_cut > 0.0 && workspace->num_H > 0 && realloc->hbonds == TRUE ) { - if ( lists[THREE_BODIES]->allocated == TRUE ) - { - Delete_List( TYP_THREE_BODY, lists[THREE_BODIES] ); - } - - if ( num_bonds == -1 ) - { - num_bonds = lists[BONDS]->total_intrs; - } - realloc->num_3body *= SAFE_ZONE; + Reallocate_List( lists[HBONDS], workspace->num_H, workspace->num_H_max, + realloc->total_hbonds, TYP_HBOND ); + Init_List_Indices( lists[HBONDS] ); - Make_List( num_bonds, num_bonds, realloc->num_3body, - TYP_THREE_BODY, lists[THREE_BODIES] ); - realloc->num_3body = -1; - -#if defined(DEBUG_FOCUS) - fprintf( stderr, "[INFO] reallocating 3 bodies\n" ); - fprintf( stderr, "[INFO] reallocated - num_bonds: %d\n", num_bonds ); - fprintf( stderr, "[INFO] reallocated - num_3body: %d\n", realloc->num_3body ); - fprintf( stderr, "[INFO] reallocated 3body memory: %ldMB\n", - realloc->num_3body * sizeof(three_body_interaction_data) / - (1024 * 1024) ); -#endif + realloc->hbonds = FALSE; } - if ( realloc->gcell_atoms > -1 ) + if ( realloc->thbody == TRUE ) { -#if defined(DEBUG_FOCUS) - fprintf( stderr, "[INFO] reallocating gcell: g->max_atoms: %d\n", g->max_atoms ); -#endif + Reallocate_List( lists[THREE_BODIES], realloc->total_bonds, + (int) CEIL( realloc->total_bonds * SAFE_ZONE ), + realloc->total_thbodies, TYP_THREE_BODY ); + Init_List_Indices( lists[THREE_BODIES] ); - for ( i = 0; i < g->ncell_max[0]; i++ ) - { - for ( j = 0; j < g->ncell_max[1]; j++ ) - { - for ( k = 0; k < g->ncell_max[2]; k++ ) - { - sfree( g->atoms[i][j][k], __FILE__, __LINE__ ); - g->atoms[i][j][k] = scalloc( workspace->realloc.gcell_atoms, sizeof(int), - __FILE__, __LINE__ ); - } - } - } - - realloc->gcell_atoms = -1; + realloc->thbody = FALSE; } } diff --git a/sPuReMD/src/allocate.h b/sPuReMD/src/allocate.h index 05ee7fdc..f94ded87 100644 --- a/sPuReMD/src/allocate.h +++ b/sPuReMD/src/allocate.h @@ -28,9 +28,6 @@ void PreAllocate_Space( reax_system * const, control_params const * const, static_storage * const, int ); -void Reallocate( reax_system * const, control_params const * const, - static_storage * const, reax_list ** const, int ); - void Allocate_Matrix( sparse_matrix * const , int, int, int ); void Deallocate_Matrix( sparse_matrix * const ); @@ -40,5 +37,11 @@ void Initialize_HBond_List( int, int const * const, int * const, void Initialize_Bond_List( int * const, reax_list * const ); +void Reallocate_Part1( reax_system * const, control_params const * const, + static_storage * const, reax_list ** const ); + +void Reallocate_Part2( reax_system const * const, control_params const * const, + simulation_data const * const, static_storage * const, reax_list ** const ); + #endif diff --git a/sPuReMD/src/box.c b/sPuReMD/src/box.c index 7a20fa9f..bdc558dd 100644 --- a/sPuReMD/src/box.c +++ b/sPuReMD/src/box.c @@ -243,7 +243,7 @@ void Update_Box_Semi_Isotropic( simulation_box *box, rvec mu ) * the simulation box that this atom was re-mapped into * during the position update where (0,0,0) represents no mapping * */ -void Update_Atom_Position_Periodic( rvec x, rvec dx, ivec rel_map, simulation_box *box ) +void Update_Atom_Position_Periodic( rvec x, rvec dx, ivec rel_map, simulation_box const * const box ) { int i, remapped; real tmp; @@ -302,7 +302,7 @@ void Update_Atom_Position_Periodic( rvec x, rvec dx, ivec rel_map, simulation_bo * x: updated atom position * rel_map: unused * */ -void Update_Atom_Position_Non_Periodic( rvec x, rvec dx, ivec rel_map, simulation_box *box ) +void Update_Atom_Position_Non_Periodic( rvec x, rvec dx, ivec rel_map, simulation_box const * const box ) { int i; real tmp; @@ -344,8 +344,9 @@ void Update_Atom_Position_Non_Periodic( rvec x, rvec dx, ivec rel_map, simulatio * r: displacement vector betweeon the atoms * return value: distance */ -real Compute_Atom_Distance_Periodic( simulation_box* box, rvec x1, rvec x2, - ivec x1_rel_map, ivec x2_rel_map, ivec x2_rel_box, rvec r ) +real Compute_Atom_Distance_Periodic( simulation_box const * const box, + rvec x1, rvec x2, ivec x1_rel_map, ivec x2_rel_map, ivec x2_rel_box, + rvec r ) { int i; real norm; @@ -385,7 +386,7 @@ real Compute_Atom_Distance_Periodic( simulation_box* box, rvec x1, rvec x2, * r: displacement vector betweeon the atoms * return value: distance */ -real Compute_Atom_Distance_Non_Periodic( simulation_box* box, rvec x1, rvec x2, +real Compute_Atom_Distance_Non_Periodic( simulation_box const * const box, rvec x1, rvec x2, ivec x1_rel_map, ivec x2_rel_map, ivec x2_rel_box, rvec r ) { int i; @@ -425,7 +426,7 @@ void Compute_Atom_Distance_Triclinic( control_params *control, } -void Update_Atom_Position_Triclinic( control_params *control, simulation_box *box, +void Update_Atom_Position_Triclinic( control_params *control, simulation_box * const box, rvec x, rvec dx, ivec rel_map ) { rvec xa, dxa; @@ -468,7 +469,8 @@ real Metric_Product( rvec x1, rvec x2, simulation_box* box ) * vlist_cut. If so, this neighborhood is added to the list of far neighbors. * Note: Periodic boundary conditions do not apply. */ int Find_Non_Periodic_Far_Neighbors( rvec x1, rvec x2, int atom, int nbr_atom, - simulation_box *box, real vlist_cut, far_neighbor_data *data ) + simulation_box const * const box, real vlist_cut, + far_neighbor_data * const data, int max ) { int count; real norm_sqr; @@ -479,11 +481,14 @@ int Find_Non_Periodic_Far_Neighbors( rvec x1, rvec x2, int atom, int nbr_atom, if ( norm_sqr <= SQR( vlist_cut ) && norm_sqr >= MIN_NBR_DIST ) { - data->nbr = nbr_atom; - ivec_MakeZero( data->rel_box ); -// rvec_MakeZero( data->ext_factor ); - data->d = SQRT( norm_sqr ); - rvec_Copy( data->dvec, dvec ); + if ( max > 0 ) + { + data->nbr = nbr_atom; + ivec_MakeZero( data->rel_box ); +// rvec_MakeZero( data->ext_factor ); + data->d = SQRT( norm_sqr ); + rvec_Copy( data->dvec, dvec ); + } count = 1; } else @@ -498,7 +503,7 @@ int Find_Non_Periodic_Far_Neighbors( rvec x1, rvec x2, int atom, int nbr_atom, /* Similar to Find_Non_Periodic_Far_Neighbors but does not * update the far neighbors list */ int Count_Non_Periodic_Far_Neighbors( rvec x1, rvec x2, int atom, int nbr_atom, - simulation_box *box, real vlist_cut ) + simulation_box const * const box, real vlist_cut ) { int count; real norm_sqr; @@ -525,7 +530,8 @@ int Count_Non_Periodic_Far_Neighbors( rvec x1, rvec x2, int atom, int nbr_atom, * If the periodic distance between x1 and x2 is less than vlist_cut, this * neighborhood is added to the list of far neighbors. */ int Find_Periodic_Far_Neighbors_Big_Box( rvec x1, rvec x2, int atom, int nbr_atom, - simulation_box *box, real vlist_cut, far_neighbor_data *data ) + simulation_box const * const box, real vlist_cut, + far_neighbor_data * const data, int max ) { int i, count; real norm_sqr, tmp, sqr_vlist_cut; @@ -568,11 +574,14 @@ int Find_Periodic_Far_Neighbors_Big_Box( rvec x1, rvec x2, int atom, int nbr_ato if ( norm_sqr <= sqr_vlist_cut && norm_sqr >= MIN_NBR_DIST ) { - data->nbr = nbr_atom; - ivec_Copy( data->rel_box, rel_box ); -// rvec_Copy( data->ext_factor, ext_factor ); - data->d = SQRT( norm_sqr ); - rvec_Copy( data->dvec, dvec ); + if ( max > 0 ) + { + data->nbr = nbr_atom; + ivec_Copy( data->rel_box, rel_box ); +// rvec_Copy( data->ext_factor, ext_factor ); + data->d = SQRT( norm_sqr ); + rvec_Copy( data->dvec, dvec ); + } count = 1; } else @@ -587,7 +596,7 @@ int Find_Periodic_Far_Neighbors_Big_Box( rvec x1, rvec x2, int atom, int nbr_ato /* Similar to Find_Periodic_Far_Neighbors_Big_Box but does not * update the far neighbors list */ int Count_Periodic_Far_Neighbors_Big_Box( rvec x1, rvec x2, int atom, int nbr_atom, - simulation_box *box, real vlist_cut ) + simulation_box const * const box, real vlist_cut ) { int i, count; real norm_sqr, d, tmp; @@ -640,7 +649,8 @@ int Count_Periodic_Far_Neighbors_Big_Box( rvec x1, rvec x2, int atom, int nbr_at * might get too small (such as <5 A!). In this case we have to consider the * periodic images of x2 that are two boxs away!!! */ int Find_Periodic_Far_Neighbors_Small_Box( rvec x1, rvec x2, int atom, int nbr_atom, - simulation_box *box, real vlist_cut, far_neighbor_data *data ) + simulation_box const * const box, real vlist_cut, + far_neighbor_data * const data, int max ) { int i, j, k, count; int imax, jmax, kmax; @@ -676,54 +686,57 @@ int Find_Periodic_Far_Neighbors_Small_Box( rvec x1, rvec x2, int atom, int nbr_a if ( sqr_norm <= sqr_vlist_cut && sqr_norm >= MIN_NBR_DIST ) { - data[count].nbr = nbr_atom; - - data[count].rel_box[0] = i; - data[count].rel_box[1] = j; - data[count].rel_box[2] = k; - -// if ( i ) -// { -// data[count].ext_factor[0] = (real)i / -ABS(i); -// } -// else -// { -// data[count].ext_factor[0] = 0; -// } -// -// if ( j ) -// { -// data[count].ext_factor[1] = (real)j / -ABS(j); -// } -// else -// { -// data[count].ext_factor[1] = 0; -// } -// -// if ( k ) -// { -// data[count].ext_factor[2] = (real)k / -ABS(k); -// } -// else -// { -// data[count].ext_factor[2] = 0; -// } -// -// if ( i == 0 && j == 0 && k == 0 ) -// { -// data[count].imaginary = 0; -// } -// else -// { -// data[count].imaginary = 1; -// } - - data[count].d = SQRT( sqr_norm ); - assert( data[count].d > 0.0 ); - - data[count].dvec[0] = d_i; - data[count].dvec[1] = d_j; - data[count].dvec[2] = d_k; + if ( count < max ) + { + data[count].nbr = nbr_atom; + + data[count].rel_box[0] = i; + data[count].rel_box[1] = j; + data[count].rel_box[2] = k; + +// if ( i ) +// { +// data[count].ext_factor[0] = (real)i / -ABS(i); +// } +// else +// { +// data[count].ext_factor[0] = 0; +// } +// +// if ( j ) +// { +// data[count].ext_factor[1] = (real)j / -ABS(j); +// } +// else +// { +// data[count].ext_factor[1] = 0; +// } +// +// if ( k ) +// { +// data[count].ext_factor[2] = (real)k / -ABS(k); +// } +// else +// { +// data[count].ext_factor[2] = 0; +// } +// +// if ( i == 0 && j == 0 && k == 0 ) +// { +// data[count].imaginary = 0; +// } +// else +// { +// data[count].imaginary = 1; +// } + + data[count].d = SQRT( sqr_norm ); + assert( data[count].d > 0.0 ); + + data[count].dvec[0] = d_i; + data[count].dvec[1] = d_j; + data[count].dvec[2] = d_k; + } ++count; } @@ -738,7 +751,7 @@ int Find_Periodic_Far_Neighbors_Small_Box( rvec x1, rvec x2, int atom, int nbr_a /* Similar to Find_Periodic_Far_Neighbors_Small_Box but does not * update the far neighbors list */ int Count_Periodic_Far_Neighbors_Small_Box( rvec x1, rvec x2, int atom, int nbr_atom, - simulation_box *box, real vlist_cut ) + simulation_box const * const box, real vlist_cut ) { int i, j, k, count; int imax, jmax, kmax; diff --git a/sPuReMD/src/box.h b/sPuReMD/src/box.h index e9b63d84..d7d81a2a 100644 --- a/sPuReMD/src/box.h +++ b/sPuReMD/src/box.h @@ -37,38 +37,38 @@ void Update_Box_Isotropic( simulation_box*, real ); void Update_Box_Semi_Isotropic( simulation_box*, rvec ); int Find_Non_Periodic_Far_Neighbors( rvec, rvec, int, int, - simulation_box*, real, far_neighbor_data* ); + simulation_box const * const, real, far_neighbor_data * const, int ); int Count_Non_Periodic_Far_Neighbors( rvec, rvec, int, int, - simulation_box*, real ); + simulation_box const * const , real ); int Find_Periodic_Far_Neighbors_Big_Box( rvec, rvec, int, int, - simulation_box*, real, far_neighbor_data* ); + simulation_box const * const, real, far_neighbor_data * const, int ); int Count_Periodic_Far_Neighbors_Big_Box( rvec, rvec, int, int, - simulation_box*, real ); + simulation_box const * const, real ); int Find_Periodic_Far_Neighbors_Small_Box( rvec, rvec, int, int, - simulation_box*, real, far_neighbor_data* ); + simulation_box const * const, real, far_neighbor_data * const, int ); int Count_Periodic_Far_Neighbors_Small_Box( rvec, rvec, int, int, - simulation_box*, real ); + simulation_box const * const, real ); void Compute_Atom_Distance_Triclinic( control_params *, simulation_box *, rvec, rvec, ivec, ivec, ivec, rvec ); void Update_Atom_Position_Triclinic( control_params *, - simulation_box *, rvec, rvec, ivec ); + simulation_box * const, rvec, rvec, ivec ); /* These functions assume that the coordinates are in triclinic system */ /* this function returns cartesian norm but triclinic distance vector */ -real Compute_Atom_Distance_Periodic( simulation_box*, rvec, rvec, ivec, ivec, ivec, rvec ); +real Compute_Atom_Distance_Periodic( simulation_box const * const, rvec, rvec, ivec, ivec, ivec, rvec ); -real Compute_Atom_Distance_Non_Periodic( simulation_box*, rvec, rvec, ivec, ivec, ivec, rvec ); +real Compute_Atom_Distance_Non_Periodic( simulation_box const * const, rvec, rvec, ivec, ivec, ivec, rvec ); -void Update_Atom_Position_Periodic( rvec, rvec, ivec, simulation_box* ); +void Update_Atom_Position_Periodic( rvec, rvec, ivec, simulation_box const * const ); -void Update_Atom_Position_Non_Periodic( rvec, rvec, ivec, simulation_box* ); +void Update_Atom_Position_Non_Periodic( rvec, rvec, ivec, simulation_box const * const ); real Metric_Product( rvec, rvec, simulation_box* ); diff --git a/sPuReMD/src/forces.c b/sPuReMD/src/forces.c index dd59f912..dfe47bb0 100644 --- a/sPuReMD/src/forces.c +++ b/sPuReMD/src/forces.c @@ -54,7 +54,7 @@ static int compare_bonds( const void *p1, const void *p2 ) #endif -void Init_Bonded_Force_Functions( control_params *control ) +void Init_Bonded_Force_Functions( control_params * const control ) { control->intr_funcs[0] = &BO; control->intr_funcs[1] = &Bonds; @@ -268,106 +268,8 @@ static void Compute_Total_Force( reax_system *system, control_params *control, } -static void Validate_Lists( static_storage *workspace, reax_list **lists, int step, int n, - int Hmax, int Htop, int num_bonds, int num_hbonds ) -{ - int i, flag; - reax_list *bonds, *hbonds; - - bonds = lists[BONDS]; - hbonds = lists[HBONDS]; - - /* far neighbors */ - if ( Htop > Hmax * DANGER_ZONE ) - { - workspace->realloc.Htop = Htop; - if ( Htop > Hmax ) - { - fprintf( stderr, - "[ERROR] step%d - ran out of space on H matrix: Htop=%d, max = %d", - step, Htop, Hmax ); - exit( INSUFFICIENT_MEMORY ); - } - } - - /* bond list */ - flag = -1; - workspace->realloc.num_bonds = num_bonds; - for ( i = 0; i < n - 1; ++i ) - { - if ( End_Index(i, bonds) >= Start_Index(i + 1, bonds) - 2 ) - { - workspace->realloc.bonds = 1; - if ( End_Index(i, bonds) > Start_Index(i + 1, bonds) ) - { - flag = i; - } - } - } - - if ( flag > -1 ) - { - fprintf( stderr, "[ERROR] step%d-bondchk failed: i=%d end(i)=%d str(i+1)=%d\n", - step, flag, End_Index(flag, bonds), Start_Index(flag + 1, bonds) ); - exit( INSUFFICIENT_MEMORY ); - } - - if ( End_Index(i, bonds) >= bonds->total_intrs - 2 ) - { - workspace->realloc.bonds = 1; - - if ( End_Index(i, bonds) > bonds->total_intrs ) - { - fprintf( stderr, "[ERROR] step%d-bondchk failed: i=%d end(i)=%d bond_end=%d\n", - step, flag, End_Index(i, bonds), bonds->total_intrs ); - exit( INSUFFICIENT_MEMORY ); - } - } - - - /* hbonds list */ - if ( workspace->num_H > 0 ) - { - flag = -1; - workspace->realloc.num_hbonds = num_hbonds; - for ( i = 0; i < workspace->num_H - 1; ++i ) - { - if ( Num_Entries(i, hbonds) >= - (Start_Index(i + 1, hbonds) - Start_Index(i, hbonds)) * DANGER_ZONE ) - { - workspace->realloc.hbonds = 1; - if ( End_Index(i, hbonds) > Start_Index(i + 1, hbonds) ) - { - flag = i; - } - } - } - - if ( flag > -1 ) - { - fprintf( stderr, "[ERROR] step%d-hbondchk failed: i=%d end(i)=%d str(i+1)=%d\n", - step, flag, End_Index(flag, hbonds), Start_Index(flag + 1, hbonds) ); - exit( INSUFFICIENT_MEMORY ); - } - - if ( Num_Entries(i, hbonds) >= - (hbonds->total_intrs - Start_Index(i, hbonds)) * DANGER_ZONE ) - { - workspace->realloc.hbonds = 1; - - if ( End_Index(i, hbonds) > hbonds->total_intrs ) - { - fprintf( stderr, "[ERROR] step%d-hbondchk failed: i=%d end(i)=%d hbondend=%d\n", - step, flag, End_Index(i, hbonds), hbonds->total_intrs ); - exit( INSUFFICIENT_MEMORY ); - } - } - } -} - - -static inline real Init_Charge_Matrix_Entry_Tab( reax_system *system, - control_params *control, LR_lookup_table **LR, int i, int j, +static inline real Init_Charge_Matrix_Entry_Tab( reax_system const * const system, + control_params const * const control, LR_lookup_table ** const LR, int i, int j, real r_ij, MATRIX_ENTRY_POSITION pos ) { int r; @@ -501,23 +403,34 @@ static void Init_Charge_Matrix_Remaining_Entries( reax_system const * const syst for ( i = 0; i < system->N; ++i ) { /* total charge constraint on atoms */ - H->j[*Htop] = i; - H->val[*Htop] = 1.0; - - H_sp->j[*H_sp_top] = i; - H_sp->val[*H_sp_top] = 1.0; + if ( *Htop < H->m ) + { + H->j[*Htop] = i; + H->val[*Htop] = 1.0; + } + ++(*Htop); - *Htop = *Htop + 1; - *H_sp_top = *H_sp_top + 1; + if ( *H_sp_top < H_sp->m ) + { + H_sp->j[*H_sp_top] = i; + H_sp->val[*H_sp_top] = 1.0; + } + ++(*H_sp_top); } - H->j[*Htop] = system->N; - H->val[*Htop] = 0.0; - *Htop = *Htop + 1; + if ( *Htop < H->m ) + { + H->j[*Htop] = system->N; + H->val[*Htop] = 0.0; + } + ++(*Htop); - H_sp->j[*H_sp_top] = system->N; - H_sp->val[*H_sp_top] = 0.0; - *H_sp_top = *H_sp_top + 1; + if ( *H_sp_top < H_sp->m ) + { + H_sp->j[*H_sp_top] = system->N; + H_sp->val[*H_sp_top] = 0.0; + } + ++(*H_sp_top); } else { @@ -530,24 +443,35 @@ static void Init_Charge_Matrix_Remaining_Entries( reax_system const * const syst j <= system->molec_charge_constraint_ranges[2 * i + 1]; ++j ) { /* molecule charge constraint on atoms */ - H->j[*Htop] = j - 1; - H->val[*Htop] = 1.0; - - H_sp->j[*H_sp_top] = j - 1; - H_sp->val[*H_sp_top] = 1.0; + if ( *Htop < H->m ) + { + H->j[*Htop] = j - 1; + H->val[*Htop] = 1.0; + } + ++(*Htop); - *Htop = *Htop + 1; - *H_sp_top = *H_sp_top + 1; + if ( *H_sp_top < H_sp->m ) + { + H_sp->j[*H_sp_top] = j - 1; + H_sp->val[*H_sp_top] = 1.0; + } + ++(*H_sp_top); } /* explicit zeros on diagonals */ - H->j[*Htop] = system->N + i; - H->val[*Htop] = 0.0; - *Htop = *Htop + 1; + if ( *Htop < H->m ) + { + H->j[*Htop] = system->N + i; + H->val[*Htop] = 0.0; + } + ++(*Htop); - H_sp->j[*H_sp_top] = system->N + i; - H_sp->val[*H_sp_top] = 0.0; - *H_sp_top = *H_sp_top + 1; + if ( *H_sp_top < H_sp->m ) + { + H_sp->j[*H_sp_top] = system->N + i; + H_sp->val[*H_sp_top] = 0.0; + } + ++(*H_sp_top); } } break; @@ -566,13 +490,19 @@ static void Init_Charge_Matrix_Remaining_Entries( reax_system const * const syst H_sp->start[system->N + i] = *H_sp_top; /* constraint on ref. value for kinetic energy potential */ - H->j[*Htop] = i; - H->val[*Htop] = 1.0; - *Htop = *Htop + 1; + if ( *Htop < H->m ) + { + H->j[*Htop] = i; + H->val[*Htop] = 1.0; + } + ++(*Htop); - H_sp->j[*H_sp_top] = i; - H_sp->val[*H_sp_top] = 1.0; - *H_sp_top = *H_sp_top + 1; + if ( *H_sp_top < H_sp->m ) + { + H_sp->j[*H_sp_top] = i; + H_sp->val[*H_sp_top] = 1.0; + } + ++(*H_sp_top); /* kinetic energy terms */ for ( pj = Start_Index(i, far_nbr_list); pj < End_Index(i, far_nbr_list); ++pj ) @@ -609,8 +539,11 @@ static void Init_Charge_Matrix_Remaining_Entries( reax_system const * const syst if ( val_flag == FALSE ) { - H->j[*Htop] = system->N + j; - H->val[*Htop] = bond_softness; + if ( *Htop < H->m ) + { + H->j[*Htop] = system->N + j; + H->val[*Htop] = bond_softness; + } ++(*Htop); } @@ -628,8 +561,11 @@ static void Init_Charge_Matrix_Remaining_Entries( reax_system const * const syst if ( val_flag == FALSE ) { - H_sp->j[*H_sp_top] = system->N + j; - H_sp->val[*H_sp_top] = bond_softness; + if ( *H_sp_top < H_sp->m ) + { + H_sp->j[*H_sp_top] = system->N + j; + H_sp->val[*H_sp_top] = bond_softness; + } ++(*H_sp_top); } @@ -641,13 +577,19 @@ static void Init_Charge_Matrix_Remaining_Entries( reax_system const * const syst } /* placeholders for diagonal entries, to be replaced below */ - H->j[*Htop] = system->N + i; - H->val[*Htop] = 0.0; - *Htop = *Htop + 1; + if ( *Htop < H->m ) + { + H->j[*Htop] = system->N + i; + H->val[*Htop] = 0.0; + } + ++(*Htop); - H_sp->j[*H_sp_top] = system->N + i; - H_sp->val[*H_sp_top] = 0.0; - *H_sp_top = *H_sp_top + 1; + if ( *H_sp_top < H_sp->m ) + { + H_sp->j[*H_sp_top] = system->N + i; + H_sp->val[*H_sp_top] = 0.0; + } + ++(*H_sp_top); } /* second to last row */ @@ -679,23 +621,35 @@ static void Init_Charge_Matrix_Remaining_Entries( reax_system const * const syst /* coupling with the kinetic energy potential */ for ( i = 0; i < system->N; ++i ) { - H->j[*Htop] = system->N + i; - H->val[*Htop] = 1.0; - *Htop = *Htop + 1; + if ( *Htop < H->m ) + { + H->j[*Htop] = system->N + i; + H->val[*Htop] = 1.0; + } + ++(*Htop); - H_sp->j[*H_sp_top] = system->N + i; - H_sp->val[*H_sp_top] = 1.0; - *H_sp_top = *H_sp_top + 1; + if ( *H_sp_top < H_sp->m ) + { + H_sp->j[*H_sp_top] = system->N + i; + H_sp->val[*H_sp_top] = 1.0; + } + ++(*H_sp_top); } /* explicitly store zero on diagonal */ - H->j[*Htop] = system->N_cm - 2; - H->val[*Htop] = 0.0; - *Htop = *Htop + 1; + if ( *Htop < H->m ) + { + H->j[*Htop] = system->N_cm - 2; + H->val[*Htop] = 0.0; + } + ++(*Htop); - H_sp->j[*H_sp_top] = system->N_cm - 2; - H_sp->val[*H_sp_top] = 0.0; - *H_sp_top = *H_sp_top + 1; + if ( *H_sp_top < H_sp->m ) + { + H_sp->j[*H_sp_top] = system->N_cm - 2; + H_sp->val[*H_sp_top] = 0.0; + } + ++(*H_sp_top); /* last row */ H->start[system->N_cm - 1] = *Htop; @@ -703,23 +657,35 @@ static void Init_Charge_Matrix_Remaining_Entries( reax_system const * const syst for ( i = 0; i < system->N; ++i ) { - H->j[*Htop] = i; - H->val[*Htop] = 1.0; - *Htop = *Htop + 1; + if ( *Htop < H->m ) + { + H->j[*Htop] = i; + H->val[*Htop] = 1.0; + } + ++(*Htop); - H_sp->j[*H_sp_top] = i; - H_sp->val[*H_sp_top] = 1.0; - *H_sp_top = *H_sp_top + 1; + if ( *H_sp_top < H_sp->m ) + { + H_sp->j[*H_sp_top] = i; + H_sp->val[*H_sp_top] = 1.0; + } + ++(*H_sp_top); } /* explicitly store zero on diagonal */ - H->j[*Htop] = system->N_cm - 1; - H->val[*Htop] = 0.0; - *Htop = *Htop + 1; + if ( *Htop < H->m ) + { + H->j[*Htop] = system->N_cm - 1; + H->val[*Htop] = 0.0; + } + ++(*Htop); - H_sp->j[*H_sp_top] = system->N_cm - 1; - H_sp->val[*H_sp_top] = 0.0; - *H_sp_top = *H_sp_top + 1; + if ( *H_sp_top < H_sp->m ) + { + H_sp->j[*H_sp_top] = system->N_cm - 1; + H_sp->val[*H_sp_top] = 0.0; + } + ++(*H_sp_top); sfree( X_diag, __FILE__, __LINE__ ); break; @@ -737,26 +703,26 @@ static void Init_Distance( reax_system const * const system, { int i, j, pj; int start_i, end_i; - reax_list *far_nbr_list; + reax_list *far_nbrs; - far_nbr_list = lists[FAR_NBRS]; + far_nbrs = lists[FAR_NBRS]; - for ( i = 0; i < system->N; ++i ) + for ( i = 0; i < far_nbrs->n; ++i ) { - start_i = Start_Index( i, far_nbr_list ); - end_i = End_Index( i, far_nbr_list ); + start_i = Start_Index( i, far_nbrs ); + end_i = End_Index( i, far_nbrs ); /* update distance and displacement vector between atoms i and j (i-j) * for the j atom entry in the far nbr list */ for ( pj = start_i; pj < end_i; ++pj ) { - j = far_nbr_list->far_nbr_list[pj].nbr; + j = far_nbrs->far_nbr_list[pj].nbr; - far_nbr_list->far_nbr_list[pj].d = control->compute_atom_distance( + far_nbrs->far_nbr_list[pj].d = control->compute_atom_distance( &system->box, system->atoms[i].x, system->atoms[j].x, system->atoms[i].rel_map, system->atoms[j].rel_map, - far_nbr_list->far_nbr_list[pj].rel_box, - far_nbr_list->far_nbr_list[pj].dvec ); + far_nbrs->far_nbr_list[pj].rel_box, + far_nbrs->far_nbr_list[pj].dvec ); } } } @@ -775,37 +741,32 @@ static void Init_CM_Half( reax_system const * const system, int flag, flag_sp, val_flag; real val; sparse_matrix *H, *H_sp; - reax_list *far_nbr_list; + reax_list *far_nbrs; - far_nbr_list = lists[FAR_NBRS]; + far_nbrs = lists[FAR_NBRS]; H = &workspace->H; H_sp = &workspace->H_sp; Htop = 0; H_sp_top = 0; - for ( i = 0; i < system->N; ++i ) + for ( i = 0; i < far_nbrs->n; ++i ) { - start_i = Start_Index( i, far_nbr_list ); - end_i = End_Index( i, far_nbr_list ); + start_i = Start_Index( i, far_nbrs ); + end_i = End_Index( i, far_nbrs ); H->start[i] = Htop; H_sp->start[i] = H_sp_top; for ( pj = start_i; pj < end_i; ++pj ) { - j = far_nbr_list->far_nbr_list[pj].nbr; + j = far_nbrs->far_nbr_list[pj].nbr; flag = FALSE; flag_sp = FALSE; -#if defined(QMMM) -// if ( system->atoms[i].qmmm_mask == TRUE -// || system->atoms[j].qmmm_mask == TRUE ) -// { -#endif - if ( far_nbr_list->far_nbr_list[pj].d <= control->nonb_cut ) + if ( far_nbrs->far_nbr_list[pj].d <= control->nonb_cut ) { flag = TRUE; - if ( far_nbr_list->far_nbr_list[pj].d <= control->nonb_sp_cut ) + if ( far_nbrs->far_nbr_list[pj].d <= control->nonb_sp_cut ) { flag_sp = TRUE; } @@ -814,7 +775,7 @@ static void Init_CM_Half( reax_system const * const system, if ( flag == TRUE ) { val = Init_Charge_Matrix_Entry( system, control, - workspace, i, j, far_nbr_list->far_nbr_list[pj].d, + workspace, i, j, far_nbrs->far_nbr_list[pj].d, OFF_DIAGONAL ); val_flag = FALSE; @@ -830,8 +791,11 @@ static void Init_CM_Half( reax_system const * const system, if ( val_flag == FALSE ) { - H->j[Htop] = j; - H->val[Htop] = val; + if ( Htop < H->m ) + { + H->j[Htop] = j; + H->val[Htop] = val; + } ++Htop; } @@ -858,15 +822,15 @@ static void Init_CM_Half( reax_system const * const system, } } } -#if defined(QMMM) -// } -#endif } /* diagonal entry */ - H->j[Htop] = i; - H->val[Htop] = Init_Charge_Matrix_Entry( system, control, - workspace, i, i, far_nbr_list->far_nbr_list[pj].d, DIAGONAL ); + if ( Htop < H->m ) + { + H->j[Htop] = i; + H->val[Htop] = Init_Charge_Matrix_Entry( system, control, + workspace, i, i, 0.0, DIAGONAL ); + } ++Htop; H_sp->j[H_sp_top] = i; @@ -874,403 +838,187 @@ static void Init_CM_Half( reax_system const * const system, ++H_sp_top; } - Init_Charge_Matrix_Remaining_Entries( system, control, far_nbr_list, + Init_Charge_Matrix_Remaining_Entries( system, control, far_nbrs, H, H_sp, &Htop, &H_sp_top ); H->start[system->N_cm] = Htop; H_sp->start[system->N_cm] = H_sp_top; + + + if ( Htop > H->m ) + { + workspace->realloc.cm = TRUE; + } } -/* Compute entries of the bonds/hbonds lists and store the lists in full format - * using the far neighbors list (stored in full format) */ -static void Init_Bond_Full( reax_system const * const system, +/* Compute the tabulated charge matrix entries and store the matrix in half format + * using the far neighbors list (stored in half format) + */ +static void Init_CM_Tab_Half( reax_system const * const system, control_params const * const control, - static_storage * const workspace, reax_list ** const lists, - int * const num_bonds, int * const num_hbonds ) + static_storage * const workspace, reax_list ** const lists ) { - int i, j, pj; + int i, j, pj, target; int start_i, end_i; - int type_i, type_j; - int btop_i, btop_j; - int ihb, jhb, ihb_top, jhb_top; - real r_ij, r2; - real C12, C34, C56; - real Cln_BOp_s, Cln_BOp_pi, Cln_BOp_pi2; - real BO, BO_s, BO_pi, BO_pi2; - reax_list *far_nbrs, *bonds, *hbonds; - single_body_parameters *sbp_i, *sbp_j; - two_body_parameters *twbp; - far_neighbor_data *nbr_pj; - bond_data *ibond, *jbond; - bond_order_data *bo_ij, *bo_ji; + int Htop, H_sp_top; + int flag, flag_sp, val_flag; + real val; + sparse_matrix *H, *H_sp; + reax_list *far_nbrs; far_nbrs = lists[FAR_NBRS]; - bonds = lists[BONDS]; - hbonds = lists[HBONDS]; - *num_bonds = 0; - *num_hbonds = 0; - btop_i = 0; - btop_j = 0; + H = &workspace->H; + H_sp = &workspace->H_sp; + Htop = 0; + H_sp_top = 0; - for ( i = 0; i < system->N; ++i ) + for ( i = 0; i < far_nbrs->n; ++i ) { - type_i = system->atoms[i].type; start_i = Start_Index( i, far_nbrs ); end_i = End_Index( i, far_nbrs ); - btop_i = End_Index( i, bonds ); - sbp_i = &system->reax_param.sbp[type_i]; + H->start[i] = Htop; + H_sp->start[i] = H_sp_top; - if ( control->hbond_cut > 0.0 ) + for ( pj = start_i; pj < end_i; ++pj ) { - ihb = sbp_i->p_hbond; + j = far_nbrs->far_nbr_list[pj].nbr; + flag = FALSE; + flag_sp = FALSE; - if ( ihb == H_ATOM ) - { - ihb_top = End_Index( workspace->hbond_index[i], hbonds ); - } - else + if ( far_nbrs->far_nbr_list[pj].d <= control->nonb_cut ) { - ihb_top = -1; - } - } - else - { - ihb = NON_H_BONDING_ATOM; - ihb_top = -1; - } + flag = TRUE; - for ( pj = start_i; pj < end_i; ++pj ) - { - nbr_pj = &far_nbrs->far_nbr_list[pj]; - j = nbr_pj->nbr; + if ( far_nbrs->far_nbr_list[pj].d <= control->nonb_sp_cut ) + { + flag_sp = TRUE; + } + } -#if defined(QMMM) - if ( system->atoms[i].qmmm_mask == TRUE - || system->atoms[j].qmmm_mask == TRUE ) - { -#endif - if ( nbr_pj->d <= control->nonb_cut ) + if ( flag == TRUE ) { - type_j = system->atoms[j].type; - sbp_j = &system->reax_param.sbp[type_j]; - twbp = &system->reax_param.tbp[type_i][type_j]; - r_ij = nbr_pj->d; + val = Init_Charge_Matrix_Entry_Tab( system, control, + workspace->LR, i, j, far_nbrs->far_nbr_list[pj].d, + OFF_DIAGONAL ); + val_flag = FALSE; -#if defined(QMMM) - if ( system->atoms[i].qmmm_mask == TRUE - && system->atoms[j].qmmm_mask == TRUE ) - { -#endif - /* Only non-dummy atoms can form bonds */ - if ( system->atoms[i].is_dummy == FALSE - && system->atoms[j].is_dummy == FALSE ) + for ( target = H->start[i]; target < Htop; ++target ) { - - /* hydrogen bond lists */ - if ( control->hbond_cut > 0.0 - && (ihb == H_ATOM || ihb == H_BONDING_ATOM) - && nbr_pj->d <= control->hbond_cut ) + if ( H->j[target] == j ) { - jhb = sbp_j->p_hbond; - - if ( ihb == H_ATOM && jhb == H_BONDING_ATOM ) - { - hbonds->hbond_list[ihb_top].nbr = j; - hbonds->hbond_list[ihb_top].scl = 1; - hbonds->hbond_list[ihb_top].ptr = nbr_pj; - ++ihb_top; - ++(*num_hbonds); - } - else if ( ihb == H_BONDING_ATOM && jhb == H_ATOM ) - { - jhb_top = End_Index( workspace->hbond_index[j], hbonds ); - hbonds->hbond_list[jhb_top].nbr = i; - hbonds->hbond_list[jhb_top].scl = -1; - hbonds->hbond_list[jhb_top].ptr = nbr_pj; - Set_End_Index( workspace->hbond_index[j], jhb_top + 1, hbonds ); - ++(*num_hbonds); - } + H->val[target] += val; + val_flag = TRUE; + break; } + } - /* uncorrected bond orders */ - if ( nbr_pj->d <= control->bond_cut ) + if ( val_flag == FALSE ) + { + if ( Htop < H->m ) { - r2 = SQR( r_ij ); - - if ( sbp_i->r_s > 0.0 && sbp_j->r_s > 0.0 ) - { - C12 = twbp->p_bo1 * POW( r_ij / twbp->r_s, twbp->p_bo2 ); - BO_s = (1.0 + control->bo_cut) * EXP( C12 ); - } - else - { - C12 = 0.0; - BO_s = 0.0; - } + H->j[Htop] = j; + H->val[Htop] = val; + } + ++Htop; + } - if ( sbp_i->r_pi > 0.0 && sbp_j->r_pi > 0.0 ) - { - C34 = twbp->p_bo3 * POW( r_ij / twbp->r_p, twbp->p_bo4 ); - BO_pi = EXP( C34 ); - } - else - { - C34 = 0.0; - BO_pi = 0.0; - } + /* H_sp matrix entry */ + if ( flag_sp == TRUE ) + { + val_flag = FALSE; - if ( sbp_i->r_pi_pi > 0.0 && sbp_j->r_pi_pi > 0.0 ) - { - C56 = twbp->p_bo5 * POW( r_ij / twbp->r_pp, twbp->p_bo6 ); - BO_pi2 = EXP( C56 ); - } - else + for ( target = H_sp->start[i]; target < H_sp_top; ++target ) + { + if ( H_sp->j[target] == j ) { - C56 = 0.0; - BO_pi2 = 0.0; + H_sp->val[target] += val; + val_flag = TRUE; + break; } + } - /* Initially BO values are the uncorrected ones, page 1 */ - BO = BO_s + BO_pi + BO_pi2; - - if ( BO >= control->bo_cut ) - { - *num_bonds += 2; - /****** bonds i-j and j-i ******/ - ibond = &bonds->bond_list[btop_i]; - btop_j = End_Index( j, bonds ); - jbond = &bonds->bond_list[btop_j]; - - ibond->nbr = j; - jbond->nbr = i; - ibond->d = r_ij; - jbond->d = r_ij; - rvec_Copy( ibond->dvec, nbr_pj->dvec ); - rvec_Scale( jbond->dvec, -1, nbr_pj->dvec ); - ivec_Copy( ibond->rel_box, nbr_pj->rel_box ); - ivec_Scale( jbond->rel_box, -1, nbr_pj->rel_box ); - ibond->dbond_index = btop_i; - jbond->dbond_index = btop_i; - ibond->sym_index = btop_j; - jbond->sym_index = btop_i; - ++btop_i; - Set_End_Index( j, btop_j + 1, bonds ); - - bo_ij = &ibond->bo_data; - bo_ij->BO = BO; - bo_ij->BO_s = BO_s; - bo_ij->BO_pi = BO_pi; - bo_ij->BO_pi2 = BO_pi2; - bo_ji = &jbond->bo_data; - bo_ji->BO = BO; - bo_ji->BO_s = BO_s; - bo_ji->BO_pi = BO_pi; - bo_ji->BO_pi2 = BO_pi2; - - /* Bond Order page2-3, derivative of total bond order prime */ - Cln_BOp_s = twbp->p_bo2 * C12 / r2; - Cln_BOp_pi = twbp->p_bo4 * C34 / r2; - Cln_BOp_pi2 = twbp->p_bo6 * C56 / r2; - - /* Only dln_BOp_xx wrt. dr_i is stored here, note that - dln_BOp_xx/dr_i = -dln_BOp_xx/dr_j and all others are 0 */ - rvec_Scale( bo_ij->dln_BOp_s, -bo_ij->BO_s * Cln_BOp_s, ibond->dvec ); - rvec_Scale( bo_ij->dln_BOp_pi, -bo_ij->BO_pi * Cln_BOp_pi, ibond->dvec ); - rvec_Scale( bo_ij->dln_BOp_pi2, - -bo_ij->BO_pi2 * Cln_BOp_pi2, ibond->dvec ); - rvec_Scale( bo_ji->dln_BOp_s, -1., bo_ij->dln_BOp_s ); - rvec_Scale( bo_ji->dln_BOp_pi, -1., bo_ij->dln_BOp_pi ); - rvec_Scale( bo_ji->dln_BOp_pi2, -1., bo_ij->dln_BOp_pi2 ); - - /* Only dBOp wrt. dr_i is stored here, note that - dBOp/dr_i = -dBOp/dr_j and all others are 0 */ - rvec_Scale( bo_ij->dBOp, -(bo_ij->BO_s * Cln_BOp_s - + bo_ij->BO_pi * Cln_BOp_pi - + bo_ij->BO_pi2 * Cln_BOp_pi2), ibond->dvec ); - rvec_Scale( bo_ji->dBOp, -1., bo_ij->dBOp ); - - rvec_Add( workspace->dDeltap_self[i], bo_ij->dBOp ); - rvec_Add( workspace->dDeltap_self[j], bo_ji->dBOp ); - - bo_ij->BO_s -= control->bo_cut; - bo_ij->BO -= control->bo_cut; - bo_ji->BO_s -= control->bo_cut; - bo_ji->BO -= control->bo_cut; - workspace->total_bond_order[i] += bo_ij->BO; - workspace->total_bond_order[j] += bo_ji->BO; - bo_ij->Cdbo = 0.0; - bo_ij->Cdbopi = 0.0; - bo_ij->Cdbopi2 = 0.0; - bo_ji->Cdbo = 0.0; - bo_ji->Cdbopi = 0.0; - bo_ji->Cdbopi2 = 0.0; - - Set_End_Index( j, btop_j + 1, bonds ); - } + if ( val_flag == FALSE ) + { + H_sp->j[H_sp_top] = j; + H_sp->val[H_sp_top] = val; + ++H_sp_top; } } -#if defined(QMMM) - } -#endif - } -#if defined(QMMM) } -#endif } - Set_End_Index( i, btop_i, bonds ); - if ( ihb == H_ATOM ) + /* diagonal entry */ + if ( Htop < H->m ) { - Set_End_Index( workspace->hbond_index[i], ihb_top, hbonds ); + H->j[Htop] = i; + H->val[Htop] = Init_Charge_Matrix_Entry_Tab( system, control, + workspace->LR, i, i, 0.0, DIAGONAL ); } - } -} - - -/* Generate bond list (full format), hydrogen bond list (full format), - * and charge matrix (half symmetric format) - * from the far neighbors list (with distance updates, if necessary) - * */ -static void Init_Forces( reax_system *system, control_params *control, - simulation_data *data, static_storage *workspace, - reax_list **lists, output_controls *out_control ) -{ - int renbr; - int num_bonds, num_hbonds; - static int dist_done = FALSE, cm_done = FALSE, bonds_done = FALSE; - - renbr = ((data->step - data->prev_steps) % control->reneighbor) == 0 ? TRUE : FALSE; - num_bonds = 0; - num_hbonds = 0; - - if ( renbr == FALSE && dist_done == FALSE ) - { - Init_Distance( system, control, lists ); + ++Htop; - dist_done = TRUE; + H_sp->j[H_sp_top] = i; + H_sp->val[H_sp_top] = H->val[Htop - 1]; + ++H_sp_top; } - if ( cm_done == FALSE ) - { -// if ( workspace->H.format == SYM_HALF_MATRIX ) -// { - Init_CM_Half( system, control, workspace, lists ); -// } -// else -// { -// Init_CM_Full( system, control, data, workspace, lists, out_control ); -// } - } + Init_Charge_Matrix_Remaining_Entries( system, control, far_nbrs, + H, H_sp, &Htop, &H_sp_top ); - if ( bonds_done == FALSE ) + H->start[system->N_cm] = Htop; + H_sp->start[system->N_cm] = H_sp_top; + + + if ( Htop > H->m ) { -// if ( lists[FAR_NBRS]->format == HALF_LIST ) -// { -// Init_Bond_Half( system, control, workspace, lists, &num_bonds, &num_hbonds ); -// } -// else -// { - Init_Bond_Full( system, control, workspace, lists, &num_bonds, &num_hbonds ); -// } + workspace->realloc.cm = TRUE; } - -// ret = (workspace->realloc.cm == FALSE -// && workspace->realloc.bonds == FALSE -// && workspace->realloc.hbonds == FALSE -// ? SUCCESS : FAILURE); -// -// if ( workspace->realloc.cm == FALSE ) -// { -// cm_done = TRUE; -// } -// if ( workspace->realloc.bonds == FALSE && workspace->realloc.hbonds == FALSE ) -// { -// bonds_done = TRUE; -// } -// -// if ( ret == SUCCESS ) -// { - dist_done = FALSE; - cm_done = FALSE; - bonds_done = FALSE; -// } - - /* validate lists - decide if reallocation is required! */ - Validate_Lists( workspace, lists, - data->step, system->N, workspace->H.m, workspace->H.start[system->N_cm], - num_bonds, num_hbonds ); - -#if defined(TEST_FORCES) - /* Calculate_dBO requires a sorted bonds list */ -// for ( i = 0; i < bonds->n; ++i ) -// { -// if ( Num_Entries(i, bonds) > 0 ) -// { -// qsort( &bonds->bond_list[Start_Index(i, bonds)], -// Num_Entries(i, bonds), sizeof(bond_data), compare_bonds ); -// } -// } -#endif - -#if defined(DEBUG_FOCUS) - fprintf( stderr, "step%d: Htop = %d, num_bonds = %d, num_hbonds = %d\n", - data->step, Htop, num_bonds, num_hbonds ); - -#endif } -static void Init_Forces_Tab( reax_system *system, control_params *control, - simulation_data *data, static_storage *workspace, - reax_list **lists, output_controls *out_control ) +/* Compute entries of the bonds/hbonds lists and store the lists in full format + * using the far neighbors list (stored in full format) */ +static void Init_Bond_Full( reax_system const * const system, + control_params const * const control, + static_storage * const workspace, reax_list ** const lists ) { - int i, j, pj, target; + int i, j, pj; int start_i, end_i; int type_i, type_j; - int Htop, H_sp_top, btop_i, btop_j, num_bonds, num_hbonds; + int btop_i, btop_j; int ihb, jhb, ihb_top, jhb_top; - int flag, flag_sp, val_flag, renbr; - real r_ij, r2, val; + int num_bonds, num_hbonds; + real r_ij, r2; real C12, C34, C56; real Cln_BOp_s, Cln_BOp_pi, Cln_BOp_pi2; real BO, BO_s, BO_pi, BO_pi2; - sparse_matrix *H, *H_sp; reax_list *far_nbrs, *bonds, *hbonds; single_body_parameters *sbp_i, *sbp_j; two_body_parameters *twbp; far_neighbor_data *nbr_pj; - reax_atom *atom_i, *atom_j; bond_data *ibond, *jbond; bond_order_data *bo_ij, *bo_ji; far_nbrs = lists[FAR_NBRS]; bonds = lists[BONDS]; hbonds = lists[HBONDS]; - H = &workspace->H; - H_sp = &workspace->H_sp; - Htop = 0; - H_sp_top = 0; num_bonds = 0; num_hbonds = 0; btop_i = 0; btop_j = 0; - renbr = ((data->step - data->prev_steps) % control->reneighbor) == 0 ? TRUE : FALSE; - for ( i = 0; i < system->N; ++i ) + for ( i = 0; i < far_nbrs->n; ++i ) { - atom_i = &system->atoms[i]; - type_i = atom_i->type; + type_i = system->atoms[i].type; start_i = Start_Index( i, far_nbrs ); end_i = End_Index( i, far_nbrs ); - H->start[i] = Htop; - H_sp->start[i] = H_sp_top; btop_i = End_Index( i, bonds ); sbp_i = &system->reax_param.sbp[type_i]; - if ( control->hbond_cut > 0.0 ) + if ( control->hbond_cut > 0.0 && workspace->num_H > 0 ) { ihb = sbp_i->p_hbond; + if ( ihb == H_ATOM ) { ihb_top = End_Index( workspace->hbond_index[i], hbonds ); @@ -1286,116 +1034,34 @@ static void Init_Forces_Tab( reax_system *system, control_params *control, ihb_top = -1; } - /* update i-j distance - check if j is within cutoff */ for ( pj = start_i; pj < end_i; ++pj ) { nbr_pj = &far_nbrs->far_nbr_list[pj]; j = nbr_pj->nbr; - flag = FALSE; - flag_sp = FALSE; #if defined(QMMM) if ( system->atoms[i].qmmm_mask == TRUE || system->atoms[j].qmmm_mask == TRUE ) { #endif - /* check if reneighboring step -- - * atomic distances just computed via - * Verlet list, so use current distances */ - if ( renbr == TRUE ) - { - if ( nbr_pj->d <= control->nonb_cut ) - { - flag = TRUE; - - if ( nbr_pj->d <= control->nonb_sp_cut ) - { - flag_sp = TRUE; - } - } - } - /* update atomic distances */ - else - { - atom_j = &system->atoms[j]; - nbr_pj->d = control->compute_atom_distance( &system->box, - atom_i->x, atom_j->x, atom_i->rel_map, - atom_j->rel_map, nbr_pj->rel_box, - nbr_pj->dvec ); - - if ( nbr_pj->d <= control->nonb_cut ) - { - flag = TRUE; - - if ( nbr_pj->d <= control->nonb_sp_cut ) - { - flag_sp = TRUE; - } - } - } - - if ( flag == TRUE ) + if ( nbr_pj->d <= control->nonb_cut ) { type_j = system->atoms[j].type; sbp_j = &system->reax_param.sbp[type_j]; twbp = &system->reax_param.tbp[type_i][type_j]; r_ij = nbr_pj->d; - val = Init_Charge_Matrix_Entry( system, control, - workspace, i, j, r_ij, OFF_DIAGONAL ); - val_flag = FALSE; - - for ( target = H->start[i]; target < Htop; ++target ) - { - if ( H->j[target] == j ) - { - H->val[target] += val; - val_flag = TRUE; - break; - } - } - - if ( val_flag == FALSE ) - { - H->j[Htop] = j; - H->val[Htop] = val; - ++Htop; - } - - /* H_sp matrix entry */ - if ( flag_sp == TRUE ) - { - val_flag = FALSE; - - for ( target = H_sp->start[i]; target < H_sp_top; ++target ) - { - if ( H_sp->j[target] == j ) - { - H_sp->val[target] += val; - val_flag = TRUE; - break; - } - } - - if ( val_flag == FALSE ) - { - H_sp->j[H_sp_top] = j; - H_sp->val[H_sp_top] = val; - ++H_sp_top; - } - } - #if defined(QMMM) if ( system->atoms[i].qmmm_mask == TRUE && system->atoms[j].qmmm_mask == TRUE ) { #endif - /* Only non-dummy atoms can form bonds */ if ( system->atoms[i].is_dummy == FALSE && system->atoms[j].is_dummy == FALSE ) { + /* hydrogen bond lists */ - if ( control->hbond_cut > 0.0 + if ( control->hbond_cut > 0.0 && workspace->num_H > 0 && (ihb == H_ATOM || ihb == H_BONDING_ATOM) && nbr_pj->d <= control->hbond_cut ) { @@ -1403,19 +1069,25 @@ static void Init_Forces_Tab( reax_system *system, control_params *control, if ( ihb == H_ATOM && jhb == H_BONDING_ATOM ) { - hbonds->hbond_list[ihb_top].nbr = j; - hbonds->hbond_list[ihb_top].scl = 1; - hbonds->hbond_list[ihb_top].ptr = nbr_pj; - ++ihb_top; + if ( num_hbonds < hbonds->total_intrs ) + { + hbonds->hbond_list[ihb_top].nbr = j; + hbonds->hbond_list[ihb_top].scl = 1; + hbonds->hbond_list[ihb_top].ptr = nbr_pj; + ++ihb_top; + } ++num_hbonds; } else if ( ihb == H_BONDING_ATOM && jhb == H_ATOM ) { - jhb_top = End_Index( workspace->hbond_index[j], hbonds ); - hbonds->hbond_list[jhb_top].nbr = i; - hbonds->hbond_list[jhb_top].scl = -1; - hbonds->hbond_list[jhb_top].ptr = nbr_pj; - Set_End_Index( workspace->hbond_index[j], jhb_top + 1, hbonds ); + if ( num_hbonds < hbonds->total_intrs ) + { + jhb_top = End_Index( workspace->hbond_index[j], hbonds ); + hbonds->hbond_list[jhb_top].nbr = i; + hbonds->hbond_list[jhb_top].scl = -1; + hbonds->hbond_list[jhb_top].ptr = nbr_pj; + Set_End_Index( workspace->hbond_index[j], jhb_top + 1, hbonds ); + } ++num_hbonds; } } @@ -1463,77 +1135,80 @@ static void Init_Forces_Tab( reax_system *system, control_params *control, if ( BO >= control->bo_cut ) { + if ( num_bonds < bonds->total_intrs ) + { + /****** bonds i-j and j-i ******/ + ibond = &bonds->bond_list[btop_i]; + btop_j = End_Index( j, bonds ); + jbond = &bonds->bond_list[btop_j]; + + ibond->nbr = j; + jbond->nbr = i; + ibond->d = r_ij; + jbond->d = r_ij; + rvec_Copy( ibond->dvec, nbr_pj->dvec ); + rvec_Scale( jbond->dvec, -1, nbr_pj->dvec ); + ivec_Copy( ibond->rel_box, nbr_pj->rel_box ); + ivec_Scale( jbond->rel_box, -1, nbr_pj->rel_box ); + ibond->dbond_index = btop_i; + jbond->dbond_index = btop_i; + ibond->sym_index = btop_j; + jbond->sym_index = btop_i; + ++btop_i; + Set_End_Index( j, btop_j + 1, bonds ); + + bo_ij = &ibond->bo_data; + bo_ij->BO = BO; + bo_ij->BO_s = BO_s; + bo_ij->BO_pi = BO_pi; + bo_ij->BO_pi2 = BO_pi2; + bo_ji = &jbond->bo_data; + bo_ji->BO = BO; + bo_ji->BO_s = BO_s; + bo_ji->BO_pi = BO_pi; + bo_ji->BO_pi2 = BO_pi2; + + /* Bond Order page2-3, derivative of total bond order prime */ + Cln_BOp_s = twbp->p_bo2 * C12 / r2; + Cln_BOp_pi = twbp->p_bo4 * C34 / r2; + Cln_BOp_pi2 = twbp->p_bo6 * C56 / r2; + + /* Only dln_BOp_xx wrt. dr_i is stored here, note that + dln_BOp_xx/dr_i = -dln_BOp_xx/dr_j and all others are 0 */ + rvec_Scale( bo_ij->dln_BOp_s, -bo_ij->BO_s * Cln_BOp_s, ibond->dvec ); + rvec_Scale( bo_ij->dln_BOp_pi, -bo_ij->BO_pi * Cln_BOp_pi, ibond->dvec ); + rvec_Scale( bo_ij->dln_BOp_pi2, + -bo_ij->BO_pi2 * Cln_BOp_pi2, ibond->dvec ); + rvec_Scale( bo_ji->dln_BOp_s, -1., bo_ij->dln_BOp_s ); + rvec_Scale( bo_ji->dln_BOp_pi, -1., bo_ij->dln_BOp_pi ); + rvec_Scale( bo_ji->dln_BOp_pi2, -1., bo_ij->dln_BOp_pi2 ); + + /* Only dBOp wrt. dr_i is stored here, note that + dBOp/dr_i = -dBOp/dr_j and all others are 0 */ + rvec_Scale( bo_ij->dBOp, -(bo_ij->BO_s * Cln_BOp_s + + bo_ij->BO_pi * Cln_BOp_pi + + bo_ij->BO_pi2 * Cln_BOp_pi2), ibond->dvec ); + rvec_Scale( bo_ji->dBOp, -1., bo_ij->dBOp ); + + rvec_Add( workspace->dDeltap_self[i], bo_ij->dBOp ); + rvec_Add( workspace->dDeltap_self[j], bo_ji->dBOp ); + + bo_ij->BO_s -= control->bo_cut; + bo_ij->BO -= control->bo_cut; + bo_ji->BO_s -= control->bo_cut; + bo_ji->BO -= control->bo_cut; + workspace->total_bond_order[i] += bo_ij->BO; + workspace->total_bond_order[j] += bo_ji->BO; + bo_ij->Cdbo = 0.0; + bo_ij->Cdbopi = 0.0; + bo_ij->Cdbopi2 = 0.0; + bo_ji->Cdbo = 0.0; + bo_ji->Cdbopi = 0.0; + bo_ji->Cdbopi2 = 0.0; + + Set_End_Index( j, btop_j + 1, bonds ); + } num_bonds += 2; - /****** bonds i-j and j-i ******/ - ibond = &bonds->bond_list[btop_i]; - btop_j = End_Index( j, bonds ); - jbond = &bonds->bond_list[btop_j]; - - ibond->nbr = j; - jbond->nbr = i; - ibond->d = r_ij; - jbond->d = r_ij; - rvec_Copy( ibond->dvec, nbr_pj->dvec ); - rvec_Scale( jbond->dvec, -1, nbr_pj->dvec ); - ivec_Copy( ibond->rel_box, nbr_pj->rel_box ); - ivec_Scale( jbond->rel_box, -1, nbr_pj->rel_box ); - ibond->dbond_index = btop_i; - jbond->dbond_index = btop_i; - ibond->sym_index = btop_j; - jbond->sym_index = btop_i; - ++btop_i; - Set_End_Index( j, btop_j + 1, bonds ); - - bo_ij = &ibond->bo_data; - bo_ij->BO = BO; - bo_ij->BO_s = BO_s; - bo_ij->BO_pi = BO_pi; - bo_ij->BO_pi2 = BO_pi2; - bo_ji = &jbond->bo_data; - bo_ji->BO = BO; - bo_ji->BO_s = BO_s; - bo_ji->BO_pi = BO_pi; - bo_ji->BO_pi2 = BO_pi2; - - /* Bond Order page2-3, derivative of total bond order prime */ - Cln_BOp_s = twbp->p_bo2 * C12 / r2; - Cln_BOp_pi = twbp->p_bo4 * C34 / r2; - Cln_BOp_pi2 = twbp->p_bo6 * C56 / r2; - - /* Only dln_BOp_xx wrt. dr_i is stored here, note that - dln_BOp_xx/dr_i = -dln_BOp_xx/dr_j and all others are 0 */ - rvec_Scale( bo_ij->dln_BOp_s, -bo_ij->BO_s * Cln_BOp_s, ibond->dvec ); - rvec_Scale( bo_ij->dln_BOp_pi, -bo_ij->BO_pi * Cln_BOp_pi, ibond->dvec ); - rvec_Scale( bo_ij->dln_BOp_pi2, - -bo_ij->BO_pi2 * Cln_BOp_pi2, ibond->dvec ); - rvec_Scale( bo_ji->dln_BOp_s, -1., bo_ij->dln_BOp_s ); - rvec_Scale( bo_ji->dln_BOp_pi, -1., bo_ij->dln_BOp_pi ); - rvec_Scale( bo_ji->dln_BOp_pi2, -1., bo_ij->dln_BOp_pi2 ); - - /* Only dBOp wrt. dr_i is stored here, note that - dBOp/dr_i = -dBOp/dr_j and all others are 0 */ - rvec_Scale( bo_ij->dBOp, -(bo_ij->BO_s * Cln_BOp_s - + bo_ij->BO_pi * Cln_BOp_pi - + bo_ij->BO_pi2 * Cln_BOp_pi2), ibond->dvec ); - rvec_Scale( bo_ji->dBOp, -1., bo_ij->dBOp ); - - rvec_Add( workspace->dDeltap_self[i], bo_ij->dBOp ); - rvec_Add( workspace->dDeltap_self[j], bo_ji->dBOp ); - - bo_ij->BO_s -= control->bo_cut; - bo_ij->BO -= control->bo_cut; - bo_ji->BO_s -= control->bo_cut; - bo_ji->BO -= control->bo_cut; - workspace->total_bond_order[i] += bo_ij->BO; - workspace->total_bond_order[j] += bo_ji->BO; - bo_ij->Cdbo = 0.0; - bo_ij->Cdbopi = 0.0; - bo_ij->Cdbopi2 = 0.0; - bo_ji->Cdbo = 0.0; - bo_ji->Cdbopi = 0.0; - bo_ji->Cdbopi2 = 0.0; - - Set_End_Index( j, btop_j + 1, bonds ); } } } @@ -1546,16 +1221,6 @@ static void Init_Forces_Tab( reax_system *system, control_params *control, #endif } - /* diagonal entry */ - H->j[Htop] = i; - H->val[Htop] = Init_Charge_Matrix_Entry( system, control, - workspace, i, i, r_ij, DIAGONAL ); - ++Htop; - - H_sp->j[H_sp_top] = i; - H_sp->val[H_sp_top] = H->val[Htop - 1]; - ++H_sp_top; - Set_End_Index( i, btop_i, bonds ); if ( ihb == H_ATOM ) { @@ -1563,28 +1228,190 @@ static void Init_Forces_Tab( reax_system *system, control_params *control, } } - Init_Charge_Matrix_Remaining_Entries( system, control, far_nbrs, - H, H_sp, &Htop, &H_sp_top ); + if ( num_bonds > bonds->total_intrs ) + { + workspace->realloc.bonds = TRUE; + } - H->start[system->N_cm] = Htop; - H_sp->start[system->N_cm] = H_sp_top; + if ( control->hbond_cut > 0.0 && workspace->num_H > 0 + && num_hbonds > hbonds->total_intrs ) + { + workspace->realloc.hbonds = TRUE; + } +} + + +/* Generate bond list (full format), hydrogen bond list (full format), + * and charge matrix (half symmetric format) + * from the far neighbors list (with distance updates, if necessary) + * */ +static int Init_Forces( reax_system * const system, + control_params const * const control, + simulation_data * const data, static_storage * const workspace, + reax_list ** const lists, output_controls * const out_control ) +{ + int i, renbr, ret; + static int dist_done = FALSE, cm_done = FALSE, bonds_done = FALSE; + + renbr = ((data->step - data->prev_steps) % control->reneighbor) == 0 ? TRUE : FALSE; + + if ( renbr == FALSE && dist_done == FALSE ) + { + Init_Distance( system, control, lists ); + + dist_done = TRUE; + } + + if ( cm_done == FALSE ) + { + if ( control->tabulate <= 0 ) + { +// if ( workspace->H.format == SYM_HALF_MATRIX ) +// { + Init_CM_Half( system, control, workspace, lists ); +// } +// else +// { +// Init_CM_Full( system, control, data, workspace, lists, out_control ); +// } + } + else + { +// if ( workspace->H.format == SYM_HALF_MATRIX ) +// { + Init_CM_Tab_Half( system, control, workspace, lists ); +// } +// else +// { +// Init_CM_Tab_Full( system, control, data, workspace, lists, out_control ); +// } + } + } + + if ( bonds_done == FALSE ) + { + for ( i = 0; i < system->N; ++i ) + { + workspace->total_bond_order[i] = 0.0; + } + for ( i = 0; i < system->N; ++i ) + { + rvec_MakeZero( workspace->dDeltap_self[i] ); + } + +// if ( lists[FAR_NBRS]->format == HALF_LIST ) +// { +// Init_Bond_Half( system, control, workspace, lists ); +// } +// else +// { + Init_Bond_Full( system, control, workspace, lists ); +// } + } + + ret = (workspace->realloc.cm == FALSE + && workspace->realloc.bonds == FALSE + && workspace->realloc.hbonds == FALSE ? SUCCESS : FAILURE); + + if ( workspace->realloc.cm == FALSE ) + { + cm_done = TRUE; + } + if ( workspace->realloc.bonds == FALSE && workspace->realloc.hbonds == FALSE ) + { + bonds_done = TRUE; + } - /* validate lists - decide if reallocation is required! */ - Validate_Lists( workspace, lists, - data->step, system->N, H->m, Htop, num_bonds, num_hbonds ); + if ( ret == SUCCESS ) + { + dist_done = FALSE; + cm_done = FALSE; + bonds_done = FALSE; + } -#if defined(DEBUG_FOCUS) - fprintf( stderr, "step%d: Htop = %d, num_bonds = %d, num_hbonds = %d\n", - data->step, Htop, num_bonds, num_hbonds ); - //Print_Bonds( system, bonds, "sbonds.out" ); - //Print_Bond_List2( system, bonds, "sbonds.out" ); - //Print_Sparse_Matrix2( H, "H.out", NULL ); +#if defined(TEST_FORCES) + /* Calculate_dBO requires a sorted bonds list */ +// for ( i = 0; i < bonds->n; ++i ) +// { +// if ( Num_Entries(i, bonds) > 0 ) +// { +// qsort( &bonds->bond_list[Start_Index(i, bonds)], +// Num_Entries(i, bonds), sizeof(bond_data), compare_bonds ); +// } +// } #endif + + return ret; } -void Estimate_Storage_Sizes( reax_system *system, control_params *control, - reax_list **lists, int *Htop, int *hb_top, int *bond_top, int *num_3body ) +static void Estimate_Storages_CM( reax_system const * const system, + control_params const * const control, static_storage * const workspace, + reax_list ** const lists ) +{ + int i, pj; + int start_i, end_i; + int Htop; + reax_list *far_nbrs; + + Htop = 0; + far_nbrs = lists[FAR_NBRS]; + + for ( i = 0; i < far_nbrs->n; ++i ) + { + start_i = Start_Index( i, far_nbrs ); + end_i = End_Index( i, far_nbrs ); + + /* update i-j distance - check if j is within cutoff */ + for ( pj = start_i; pj < end_i; ++pj ) + { + if ( far_nbrs->far_nbr_list[pj].d <= control->nonb_cut ) + { + ++Htop; + } + } + + /* diagonal entry */ + ++Htop; + } + + switch ( control->charge_method ) + { + case QEQ_CM: + break; + + case EE_CM: + if ( system->num_molec_charge_constraints == 0 ) + { + Htop += system->N_cm; + } + else + { + for ( i = 0; i < system->num_molec_charge_constraints; ++i ) + { + Htop += system->molec_charge_constraint_ranges[2 * i + 1] + - system->molec_charge_constraint_ranges[2 * i] + 1; + } + } + break; + + case ACKS2_CM: + Htop = 2 * Htop + 3 * system->N + 2; + break; + + default: + fprintf( stderr, "[ERROR] Unknown charge method type. Terminating...\n" ); + exit( INVALID_INPUT ); + break; + } + + workspace->realloc.total_cm_entries = (int) CEIL( Htop * SAFE_ZONE ); +} + + +static void Estimate_Storages_Bonds( reax_system const * const system, + control_params const * const control, static_storage * const workspace, + reax_list ** const lists ) { int i, j, pj; int start_i, end_i; @@ -1601,6 +1428,15 @@ void Estimate_Storage_Sizes( reax_system *system, control_params *control, far_nbrs = lists[FAR_NBRS]; + for ( i = 0; i < system->N_max; ++i ) + { + system->bonds[i] = 0; + } + for ( i = 0; i < system->N_max; ++i ) + { + system->hbonds[i] = 0; + } + for ( i = 0; i < far_nbrs->n; ++i ) { atom_i = &system->atoms[i]; @@ -1622,7 +1458,6 @@ void Estimate_Storage_Sizes( reax_system *system, control_params *control, type_j = atom_j->type; sbp_j = &system->reax_param.sbp[type_j]; twbp = &system->reax_param.tbp[type_i][type_j]; - ++(*Htop); /* hydrogen bond lists */ if ( control->hbond_cut > 0.0 @@ -1633,11 +1468,11 @@ void Estimate_Storage_Sizes( reax_system *system, control_params *control, if ( ihb == H_ATOM && jhb == H_BONDING_ATOM ) { - ++hb_top[i]; + ++system->hbonds[i]; } else if ( ihb == H_BONDING_ATOM && jhb == H_ATOM ) { - ++hb_top[j]; + ++system->hbonds[j]; } } @@ -1684,93 +1519,100 @@ void Estimate_Storage_Sizes( reax_system *system, control_params *control, if ( BO >= control->bo_cut ) { - ++bond_top[i]; - ++bond_top[j]; + ++system->bonds[i]; + ++system->bonds[j]; } } } } } - switch ( control->charge_method ) + workspace->realloc.total_thbodies = 0; + for ( i = 0; i < system->N; ++i ) { - case QEQ_CM: - break; + //TODO: the factor of 2 depends on the bond list format (and also effects thbody list), revisit later + system->bonds[i] = MAX( (int) CEIL( system->bonds[i] * 2.0 * SAFE_ZONE ), MIN_BONDS ); + } - case EE_CM: - if ( system->num_molec_charge_constraints == 0 ) - { - *Htop += system->N_cm; - } - else - { - for ( i = 0; i < system->num_molec_charge_constraints; ++i ) - { - *Htop += system->molec_charge_constraint_ranges[2 * i + 1] - - system->molec_charge_constraint_ranges[2 * i] + 1; - } - } - break; + for ( i = 0; i < system->N; ++i ) + { + system->hbonds[i] = MAX( (int) CEIL( system->hbonds[i] * SAFE_HBONDS ), MIN_HBONDS ); + } - case ACKS2_CM: - *Htop = 2 * *Htop + 3 * system->N + 2; - break; + /* reductions to get totals */ + workspace->realloc.total_bonds = 0; + workspace->realloc.total_hbonds = 0; + workspace->realloc.total_thbodies = 0; - default: - fprintf( stderr, "[ERROR] Unknown charge method type. Terminating...\n" ); - exit( INVALID_INPUT ); - break; + for ( i = 0; i < system->N_max; ++i ) + { + workspace->realloc.total_bonds += system->bonds[i]; + } + for ( i = 0; i < system->N_max; ++i ) + { + workspace->realloc.total_hbonds += system->hbonds[i]; } + for ( i = 0; i < system->N_max; ++i ) + { + workspace->realloc.total_thbodies += SQR( system->bonds[i] ); + } +} - *Htop *= SAFE_ZONE; - for ( i = 0; i < system->N; ++i ) +void Estimate_Storages( reax_system const * const system, + control_params const * const control, static_storage * const workspace, + reax_list ** const lists, int realloc_cm, int realloc_bonds ) +{ + if ( realloc_cm == TRUE ) + { + Estimate_Storages_CM( system, control, workspace, lists ); + } + + if ( realloc_bonds == TRUE ) { - hb_top[i] = MAX( hb_top[i] * SAFE_HBONDS, MIN_HBONDS ); - *num_3body += SQR( bond_top[i] ); - bond_top[i] = MAX( bond_top[i] * 2, MIN_BONDS ); + Estimate_Storages_Bonds( system, control, workspace, lists ); } - *num_3body *= SAFE_ZONE; } -void Compute_Forces( reax_system *system, control_params *control, - simulation_data *data, static_storage *workspace, - reax_list** lists, output_controls *out_control, int realloc ) +int Compute_Forces( reax_system * const system, control_params * const control, + simulation_data * const data, static_storage * const workspace, + reax_list ** const lists, output_controls * const out_control, int realloc ) { + int ret; real t_start, t_elapsed; t_start = Get_Time( ); - if ( control->tabulate <= 0 ) - { - Init_Forces( system, control, data, workspace, lists, out_control ); - } - else - { - Init_Forces_Tab( system, control, data, workspace, lists, out_control ); - } + ret = Init_Forces( system, control, data, workspace, lists, out_control ); t_elapsed = Get_Timing_Info( t_start ); data->timing.init_forces += t_elapsed; - t_start = Get_Time( ); - Compute_Bonded_Forces( system, control, data, workspace, lists, out_control ); - t_elapsed = Get_Timing_Info( t_start ); - data->timing.bonded += t_elapsed; + if ( ret != SUCCESS ) + { + Estimate_Storages( system, control, workspace, lists, workspace->realloc.cm, + workspace->realloc.bonds || workspace->realloc.hbonds ); + } - t_start = Get_Time( ); - Compute_NonBonded_Forces( system, control, data, workspace, - lists, out_control, realloc ); - t_elapsed = Get_Timing_Info( t_start ); - data->timing.nonb += t_elapsed; + if ( ret == SUCCESS ) + { + t_start = Get_Time( ); + Compute_Bonded_Forces( system, control, data, workspace, lists, out_control ); + t_elapsed = Get_Timing_Info( t_start ); + data->timing.bonded += t_elapsed; - Compute_Total_Force( system, control, data, workspace, lists ); + t_start = Get_Time( ); + Compute_NonBonded_Forces( system, control, data, workspace, + lists, out_control, realloc ); + t_elapsed = Get_Timing_Info( t_start ); + data->timing.nonb += t_elapsed; -#if defined(DEBUG_FOCUS) - //Print_Total_Force( system, control, data, workspace, lists, out_control ); -#endif + Compute_Total_Force( system, control, data, workspace, lists ); #if defined(TEST_FORCES) - Print_Total_Force( system, control, data, workspace, lists, out_control ); - Compare_Total_Forces( system, control, data, workspace, lists, out_control ); + Print_Total_Force( system, control, data, workspace, lists, out_control ); + Compare_Total_Forces( system, control, data, workspace, lists, out_control ); #endif + } + + return ret; } diff --git a/sPuReMD/src/forces.h b/sPuReMD/src/forces.h index 982ba286..e34b304c 100644 --- a/sPuReMD/src/forces.h +++ b/sPuReMD/src/forces.h @@ -25,13 +25,14 @@ #include "reax_types.h" -void Init_Bonded_Force_Functions( control_params* ); +void Init_Bonded_Force_Functions( control_params * const ); -void Compute_Forces( reax_system *, control_params *, simulation_data *, - static_storage *, reax_list **, output_controls *, int ); +void Estimate_Storages( reax_system const * const, control_params const * const, + static_storage * const, reax_list ** const, int, int ); -void Estimate_Storage_Sizes( reax_system *, control_params *, reax_list **, - int *, int *, int *, int * ); +int Compute_Forces( reax_system * const, control_params * const, + simulation_data * const, static_storage * const, reax_list ** const, + output_controls * const, int ); #endif diff --git a/sPuReMD/src/init_md.c b/sPuReMD/src/init_md.c index 7b43cb96..cd9d6075 100644 --- a/sPuReMD/src/init_md.c +++ b/sPuReMD/src/init_md.c @@ -38,8 +38,8 @@ #include "vector.h" -static void Generate_Initial_Velocities( reax_system *system, - control_params *control, real T ) +static void Generate_Initial_Velocities( reax_system * const system, + control_params const * const control, real T ) { int i; real scale, norm; @@ -98,8 +98,8 @@ static void Generate_Initial_Velocities( reax_system *system, } -static void Init_System( reax_system *system, control_params *control, - simulation_data *data ) +static void Init_System( reax_system * const system, control_params * const control, + simulation_data * const data, static_storage * const workspace, int realloc ) { int i; rvec dx; @@ -155,12 +155,26 @@ static void Init_System( reax_system *system, control_params *control, } Setup_Grid( system ); + + Bin_Atoms( system, workspace ); + +#if defined(REORDER_ATOMS) + Reorder_Atoms( system, workspace, control ); +#endif + + if ( realloc == TRUE ) + { + /* list management */ + system->bonds = smalloc( sizeof(int) * system->N_max, __FILE__, __LINE__ ); + + system->hbonds = smalloc( sizeof(int) * system->N_max, __FILE__, __LINE__ ); + } } -static void Init_Simulation_Data( reax_system *system, control_params *control, - simulation_data *data, output_controls *out_control, - evolve_function *Evolve, int realloc ) +static void Init_Simulation_Data( reax_system * const system, + control_params * const control, simulation_data * const data, + evolve_function * const Evolve, int realloc ) { #if defined(_OPENMP) if ( realloc == TRUE && (control->ensemble == sNPT || control->ensemble == iNPT @@ -278,8 +292,9 @@ static void Init_Simulation_Data( reax_system *system, control_params *control, } -/* Initialize Taper params */ -static void Init_Taper( control_params *control, static_storage *workspace ) +/* Initialize taper function applied to van der Waals and Coulomb interactions */ +static void Init_Taper( control_params const * const control, + static_storage * const workspace ) { real d1, d7; real swa, swa2, swa3; @@ -322,8 +337,9 @@ static void Init_Taper( control_params *control, static_storage *workspace ) } -static void Init_Workspace( reax_system *system, control_params *control, - static_storage *workspace, int realloc ) +static void Init_Workspace( reax_system * const system, + control_params const * const control, static_storage * const workspace, + int realloc ) { int i; @@ -770,71 +786,82 @@ static void Init_Workspace( reax_system *system, control_params *control, __FILE__, __LINE__ ); #endif - workspace->realloc.num_far = -1; - workspace->realloc.Htop = -1; - workspace->realloc.hbonds = -1; - workspace->realloc.bonds = -1; - workspace->realloc.num_3body = -1; + workspace->realloc.far_nbrs = FALSE; + workspace->realloc.cm = FALSE; + workspace->realloc.hbonds = FALSE; + workspace->realloc.bonds = FALSE; + workspace->realloc.thbody = FALSE; workspace->realloc.gcell_atoms = -1; Reset_Workspace( system, workspace ); - /* Initialize Taper function */ Init_Taper( control, workspace ); } -static void Init_Lists( reax_system *system, control_params *control, - simulation_data *data, static_storage *workspace, - reax_list **lists, output_controls *out_control, int realloc ) +static void Init_Lists( reax_system * const system, + control_params * const control, simulation_data * const data, + static_storage * const workspace, reax_list ** const lists, int realloc ) { - int i, num_nbrs, num_bonds, num_hbonds, num_3body, Htop; - int *hb_top, *bond_top; - - num_nbrs = Estimate_Num_Neighbors( system, control, workspace, lists ); + int i, ret; - if ( lists[FAR_NBRS]->allocated == FALSE ) - { - Make_List( system->N, system->N_max, num_nbrs, TYP_FAR_NEIGHBOR, lists[FAR_NBRS] ); - } - else if ( realloc == TRUE || lists[FAR_NBRS]->total_intrs < num_nbrs ) + if ( realloc == TRUE ) { - if ( lists[FAR_NBRS]->allocated == TRUE ) + Estimate_Num_Neighbors( system, control, workspace, lists ); + + if ( lists[FAR_NBRS]->allocated == FALSE ) { - Delete_List( TYP_FAR_NEIGHBOR, lists[FAR_NBRS] ); + Make_List( system->N, system->N_max, workspace->realloc.total_far_nbrs, + TYP_FAR_NEIGHBOR, lists[FAR_NBRS] ); + } + else if ( realloc == TRUE + || lists[FAR_NBRS]->total_intrs < workspace->realloc.total_far_nbrs ) + { + if ( lists[FAR_NBRS]->allocated == TRUE ) + { + Delete_List( TYP_FAR_NEIGHBOR, lists[FAR_NBRS] ); + } + Make_List( system->N, system->N_max, + MAX( workspace->realloc.total_far_nbrs, lists[FAR_NBRS]->total_intrs ), + TYP_FAR_NEIGHBOR, lists[FAR_NBRS] ); } - Make_List( system->N, system->N_max, - MAX( num_nbrs, lists[FAR_NBRS]->total_intrs ), - TYP_FAR_NEIGHBOR, lists[FAR_NBRS] ); } - else + + lists[FAR_NBRS]->n = system->N; + + ret = Generate_Neighbor_Lists( system, control, data, workspace, lists ); + + if ( ret != SUCCESS ) { - lists[FAR_NBRS]->n = system->N; - } + Estimate_Num_Neighbors( system, control, workspace, lists ); - Generate_Neighbor_Lists( system, control, data, workspace, lists ); + Delete_List( TYP_FAR_NEIGHBOR, lists[FAR_NBRS] ); + Make_List( system->N, system->N_max, + MAX( workspace->realloc.total_far_nbrs, lists[FAR_NBRS]->total_intrs ), + TYP_FAR_NEIGHBOR, lists[FAR_NBRS] ); - Htop = 0; - hb_top = scalloc( system->N, sizeof(int), __FILE__, __LINE__ ); - bond_top = scalloc( system->N, sizeof(int), __FILE__, __LINE__ ); - num_3body = 0; + Generate_Neighbor_Lists( system, control, data, workspace, lists ); + } - Estimate_Storage_Sizes( system, control, lists, &Htop, - hb_top, bond_top, &num_3body ); - num_3body = MAX( num_3body, MIN_BONDS ); + if ( realloc == TRUE ) + { + Estimate_Storages( system, control, workspace, lists, TRUE, TRUE ); + } if ( workspace->H.allocated == FALSE ) { - Allocate_Matrix( &workspace->H, system->N_cm, system->N_cm_max, Htop ); + Allocate_Matrix( &workspace->H, system->N_cm, system->N_cm_max, + workspace->realloc.total_cm_entries ); } - else if ( realloc == TRUE || workspace->H.m < Htop + else if ( realloc == TRUE || workspace->H.m < workspace->realloc.total_cm_entries || workspace->H.n_max < system->N_cm_max ) { if ( workspace->H.allocated == TRUE ) { Deallocate_Matrix( &workspace->H ); } - Allocate_Matrix( &workspace->H, system->N_cm, system->N_cm_max, Htop ); + Allocate_Matrix( &workspace->H, system->N_cm, system->N_cm_max, + workspace->realloc.total_cm_entries ); } else { @@ -844,12 +871,13 @@ static void Init_Lists( reax_system *system, control_params *control, if ( workspace->H_sp.allocated == FALSE ) { /* TODO: better estimate for H_sp? - * If so, need to refactor Estimate_Storage_Sizes + * If so, need to refactor Estimate_Storages * to use various cut-off distances as parameters * (non-bonded, hydrogen, 3body, etc.) */ - Allocate_Matrix( &workspace->H_sp, system->N_cm, system->N_cm_max, Htop ); + Allocate_Matrix( &workspace->H_sp, system->N_cm, system->N_cm_max, + workspace->realloc.total_cm_entries ); } - else if ( realloc == TRUE || workspace->H_sp.m < Htop + else if ( realloc == TRUE || workspace->H_sp.m < workspace->realloc.total_cm_entries || workspace->H.n_max < system->N_cm_max ) { if ( workspace->H_sp.allocated == TRUE ) @@ -857,10 +885,11 @@ static void Init_Lists( reax_system *system, control_params *control, Deallocate_Matrix( &workspace->H_sp ); } /* TODO: better estimate for H_sp? - * If so, need to refactor Estimate_Storage_Sizes + * If so, need to refactor Estimate_Storages * to use various cut-off distances as parameters * (non-bonded, hydrogen, 3body, etc.) */ - Allocate_Matrix( &workspace->H_sp, system->N_cm, system->N_cm_max, Htop ); + Allocate_Matrix( &workspace->H_sp, system->N_cm, system->N_cm_max, + workspace->realloc.total_cm_entries ); } else { @@ -870,7 +899,6 @@ static void Init_Lists( reax_system *system, control_params *control, workspace->num_H = 0; if ( control->hbond_cut > 0.0 ) { - /* init hydrogen atom indexes */ for ( i = 0; i < system->N; ++i ) { if ( system->reax_param.sbp[ system->atoms[i].type ].p_hbond == H_ATOM ) @@ -882,78 +910,60 @@ static void Init_Lists( reax_system *system, control_params *control, workspace->hbond_index[i] = -1; } } - - if ( workspace->num_H == 0 ) + for ( i = system->N; i < system->N_max; ++i ) { - control->hbond_cut = 0.0; + workspace->hbond_index[i] = -1; } - else + } + + if ( control->hbond_cut > 0.0 && workspace->num_H > 0 ) + { + if ( lists[HBONDS]->allocated == FALSE ) { - num_hbonds = 0; - for ( i = 0; i < system->N; ++i ) - { - num_hbonds += hb_top[i]; - } + workspace->num_H_max = (int) CEIL( SAFE_ZONE * workspace->num_H ); - if ( lists[HBONDS]->allocated == FALSE ) + Make_List( workspace->num_H, workspace->num_H_max, + (int) CEIL( SAFE_ZONE * workspace->realloc.total_hbonds ), + TYP_HBOND, lists[HBONDS] ); + } + else if ( workspace->num_H_max < workspace->num_H + || lists[HBONDS]->total_intrs < workspace->realloc.total_hbonds ) + { + if ( workspace->num_H_max < workspace->num_H ) { workspace->num_H_max = (int) CEIL( SAFE_ZONE * workspace->num_H ); - - Make_List( workspace->num_H, workspace->num_H_max, - (int) CEIL( SAFE_ZONE * num_hbonds ), - TYP_HBOND, lists[HBONDS] ); } - else if ( workspace->num_H_max < workspace->num_H - || lists[HBONDS]->total_intrs < num_hbonds ) - { - if ( workspace->num_H_max < workspace->num_H ) - { - workspace->num_H_max = (int) CEIL( SAFE_ZONE * workspace->num_H ); - } - if ( lists[HBONDS]->allocated == TRUE ) - { - Delete_List( TYP_HBOND, lists[HBONDS] ); - } - Make_List( workspace->num_H, workspace->num_H_max, - MAX( num_hbonds, lists[HBONDS]->total_intrs ), - TYP_HBOND, lists[HBONDS] ); - } - else + if ( lists[HBONDS]->allocated == TRUE ) { - lists[HBONDS]->n = workspace->num_H; + Delete_List( TYP_HBOND, lists[HBONDS] ); } - - Initialize_HBond_List( system->N, workspace->hbond_index, hb_top, lists[HBONDS] ); + Make_List( workspace->num_H, workspace->num_H_max, + MAX( workspace->realloc.total_hbonds, lists[HBONDS]->total_intrs ), + TYP_HBOND, lists[HBONDS] ); + } + else + { + lists[HBONDS]->n = workspace->num_H; } - } - -#if defined(DEBUG_FOCUS) - fprintf( stderr, "estimated storage - num_hbonds: %d\n", num_hbonds ); - fprintf( stderr, "memory allocated: hbonds = %ldMB\n", - num_hbonds * sizeof(hbond_data) / (1024 * 1024) ); -#endif - num_bonds = 0; - for ( i = 0; i < system->N; ++i ) - { - num_bonds += bond_top[i]; + Init_List_Indices( lists[HBONDS] ); } /* bonds list */ if ( lists[BONDS]->allocated == FALSE ) { - Make_List( system->N, system->N_max, (int) CEIL( num_bonds * SAFE_ZONE ), + Make_List( system->N, system->N_max, (int) CEIL( workspace->realloc.total_bonds * SAFE_ZONE ), TYP_BOND, lists[BONDS] ); } - else if ( realloc == TRUE || lists[BONDS]->total_intrs < num_bonds ) + else if ( realloc == TRUE || lists[BONDS]->total_intrs < workspace->realloc.total_bonds ) { if ( lists[BONDS]->allocated == TRUE ) { Delete_List( TYP_BOND, lists[BONDS] ); } Make_List( system->N, system->N_max, - MAX( num_bonds, lists[BONDS]->total_intrs ), + MAX( workspace->realloc.total_bonds, lists[BONDS]->total_intrs ), TYP_BOND, lists[BONDS] ); } else @@ -961,45 +971,34 @@ static void Init_Lists( reax_system *system, control_params *control, lists[BONDS]->n = system->N; } - Initialize_Bond_List( bond_top, lists[BONDS] ); - -#if defined(DEBUG_FOCUS) - fprintf( stderr, "estimated storage - num_bonds: %d\n", num_bonds ); - fprintf( stderr, "memory allocated: bonds = %ldMB\n", - num_bonds * sizeof(bond_data) / (1024 * 1024) ); -#endif + Init_List_Indices( lists[BONDS] ); /* 3bodies list */ if ( lists[THREE_BODIES]->allocated == FALSE ) { - Make_List( num_bonds, num_bonds, num_3body, TYP_THREE_BODY, lists[THREE_BODIES] ); + Make_List( workspace->realloc.total_bonds, (int) CEIL( workspace->realloc.total_bonds * SAFE_ZONE ), + workspace->realloc.total_thbodies, TYP_THREE_BODY, lists[THREE_BODIES] ); } - else if ( lists[THREE_BODIES]->n_max < num_bonds - || lists[THREE_BODIES]->total_intrs < num_3body ) + else if ( lists[THREE_BODIES]->n_max < workspace->realloc.total_bonds + || lists[THREE_BODIES]->total_intrs < workspace->realloc.total_thbodies ) { if ( lists[THREE_BODIES]->allocated == TRUE ) { Delete_List( TYP_THREE_BODY, lists[THREE_BODIES] ); } - Make_List( MAX( num_bonds, lists[THREE_BODIES]->n_max), - MAX( num_bonds, lists[THREE_BODIES]->n_max), - MAX( num_3body, lists[THREE_BODIES]->total_intrs ), + Make_List( workspace->realloc.total_bonds, + MAX( workspace->realloc.total_bonds, lists[THREE_BODIES]->n_max), + MAX( workspace->realloc.total_thbodies, lists[THREE_BODIES]->total_intrs ), TYP_THREE_BODY, lists[THREE_BODIES] ); } else { - lists[THREE_BODIES]->n = num_bonds; + lists[THREE_BODIES]->n = workspace->realloc.total_bonds; } -#if defined(DEBUG_FOCUS) - fprintf( stderr, "estimated storage - num_3body: %d\n", num_3body ); - fprintf( stderr, "memory allocated: 3-body = %ldMB\n", - num_3body * sizeof(three_body_interaction_data) / (1024 * 1024) ); -#endif - #if defined(TEST_FORCES) //TODO: increased num. of DDELTA list elements, find a better count later - Make_List( system->N, num_bonds * 20, TYP_DDELTA, lists[DDELTA] ); + Make_List( system->N, workspace->realloc.total_bonds * 20, TYP_DDELTA, lists[DDELTA] ); for ( i = 0; i < lists[DDELTA]->n; ++i ) { @@ -1007,7 +1006,8 @@ static void Init_Lists( reax_system *system, control_params *control, Set_End_Index( i, 0, lists[DDELTA] ); } - Make_List( num_bonds, num_bonds * MAX_BONDS * 3, TYP_DBO, lists[DBO] ); + Make_List( workspace->realloc.total_bonds, workspace->realloc.total_bonds * MAX_BONDS * 3, + TYP_DBO, lists[DBO] ); for ( i = 0; i < lists[DBO]->n; ++i ) { @@ -1015,9 +1015,6 @@ static void Init_Lists( reax_system *system, control_params *control, Set_End_Index( i, 0, lists[DBO] ); } #endif - - sfree( hb_top, __FILE__, __LINE__ ); - sfree( bond_top, __FILE__, __LINE__ ); } @@ -1282,10 +1279,10 @@ static void Init_Out_Controls( reax_system *system, control_params *control, } -void Initialize( reax_system *system, control_params *control, - simulation_data *data, static_storage *workspace, reax_list **lists, - output_controls *out_control, evolve_function *Evolve, - int output_enabled, int realloc ) +void Initialize( reax_system * const system, control_params * const control, + simulation_data * const data, static_storage * const workspace, + reax_list ** const lists, output_controls * const out_control, + evolve_function * const Evolve, int output_enabled, int realloc ) { #if defined(_OPENMP) #pragma omp parallel default(none) shared(control) @@ -1308,13 +1305,13 @@ void Initialize( reax_system *system, control_params *control, Randomize( ); - Init_System( system, control, data ); + Init_System( system, control, data, workspace, realloc ); - Init_Simulation_Data( system, control, data, out_control, Evolve, realloc ); + Init_Simulation_Data( system, control, data, Evolve, realloc ); Init_Workspace( system, control, workspace, realloc ); - Init_Lists( system, control, data, workspace, lists, out_control, realloc ); + Init_Lists( system, control, data, workspace, lists, realloc ); Init_Out_Controls( system, control, workspace, out_control, output_enabled ); @@ -1386,6 +1383,9 @@ static void Finalize_System( reax_system *system, control_params *control, sfree( system->atoms, __FILE__, __LINE__ ); } + + sfree( system->bonds, __FILE__, __LINE__ ); + sfree( system->hbonds, __FILE__, __LINE__ ); } diff --git a/sPuReMD/src/integrate.c b/sPuReMD/src/integrate.c index fc1a95f1..05893a8e 100644 --- a/sPuReMD/src/integrate.c +++ b/sPuReMD/src/integrate.c @@ -32,152 +32,234 @@ #include "vector.h" -/* Perform simulation using the microcanonical ensemble with - * the Velocity Verlet integrator. */ -void Velocity_Verlet_NVE( reax_system *system, control_params *control, - simulation_data *data, static_storage *workspace, - reax_list **lists, output_controls *out_control ) +/* Velocity Verlet integrator for microcanonical ensemble. */ +int Velocity_Verlet_NVE( reax_system * const system, control_params * const control, + simulation_data * const data, static_storage * const workspace, + reax_list ** const lists, output_controls * const out_control ) { - int i, renbr; + int i, renbr, ret; + static int verlet_part1_done = FALSE, gen_nbr_list = FALSE; real inv_m, scalar1, scalar2; rvec dx; + ret = SUCCESS; renbr = ((data->step - data->prev_steps) % control->reneighbor) == 0 ? TRUE : FALSE; scalar1 = -0.5 * control->dt * F_CONV; scalar2 = -0.5 * SQR( control->dt ) * F_CONV; - for ( i = 0; i < system->N; i++ ) + if ( verlet_part1_done == FALSE ) { - inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; + for ( i = 0; i < system->N; i++ ) + { + inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; - /* Compute x(t + dt) */ - rvec_ScaledSum( dx, control->dt, system->atoms[i].v, - scalar2 * inv_m, system->atoms[i].f ); + /* Compute x(t + dt) */ + rvec_ScaledSum( dx, control->dt, system->atoms[i].v, + scalar2 * inv_m, system->atoms[i].f ); - control->update_atom_position( system->atoms[i].x, dx, - system->atoms[i].rel_map, &system->box ); + control->update_atom_position( system->atoms[i].x, dx, + system->atoms[i].rel_map, &system->box ); - /* Compute v(t + dt/2) */ - rvec_ScaledAdd( system->atoms[i].v, - scalar1 * inv_m, system->atoms[i].f ); + /* Compute v(t + dt/2) */ + rvec_ScaledAdd( system->atoms[i].v, + scalar1 * inv_m, system->atoms[i].f ); + } + + if ( renbr == TRUE ) + { + Reallocate_Part1( system, control, workspace, lists ); + + Bin_Atoms( system, workspace ); + +#if defined(REORDER_ATOMS) + Reorder_Atoms( system, workspace, control ); +#endif + } + + verlet_part1_done = TRUE; } - Reallocate( system, control, workspace, lists, renbr ); + Reallocate_Part2( system, control, data, workspace, lists ); Reset( system, control, data, workspace, lists ); - if ( renbr == TRUE ) + if ( renbr == TRUE && gen_nbr_list == FALSE ) { - Generate_Neighbor_Lists( system, control, data, workspace, lists ); + ret = Generate_Neighbor_Lists( system, control, data, workspace, lists ); + + if ( ret == SUCCESS ) + { + gen_nbr_list = TRUE; + } + else + { + Estimate_Num_Neighbors( system, control, workspace, lists ); + } } - Compute_Forces( system, control, data, workspace, lists, out_control, FALSE ); + if ( ret == SUCCESS ) + { + ret = Compute_Forces( system, control, data, workspace, lists, + out_control, FALSE ); + } - for ( i = 0; i < system->N; i++ ) + if ( ret == SUCCESS ) { - inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; + for ( i = 0; i < system->N; i++ ) + { + inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; - /* Compute v(t + dt) */ - rvec_ScaledAdd( system->atoms[i].v, - scalar1 * inv_m, system->atoms[i].f ); + /* Compute v(t + dt) */ + rvec_ScaledAdd( system->atoms[i].v, + scalar1 * inv_m, system->atoms[i].f ); + } + + verlet_part1_done = FALSE; + gen_nbr_list = FALSE; } + + return ret; } -/* Perform simulation using constant volume and temperature (NVT ensemble) - * with a Berendsen thermostat and the Velocity Verlet integrator. */ -void Velocity_Verlet_Berendsen_NVT( reax_system* system, - control_params* control, simulation_data *data, - static_storage *workspace, reax_list **lists, - output_controls *out_control ) +/* Velocity Verlet integrator for constant volume and temperature + * with Berendsen thermostat. + * + * NOTE: All box dimensions are scaled by the same amount, and + * there is no change in the angles between axes. */ +int Velocity_Verlet_Berendsen_NVT( reax_system * const system, + control_params * const control, simulation_data * const data, + static_storage * const workspace, reax_list ** const lists, + output_controls * const out_control ) { - int i, renbr; + int i, renbr, ret; + static int verlet_part1_done = FALSE, gen_nbr_list = FALSE; real inv_m, scalar1, scalar2, lambda; rvec dx; + ret = SUCCESS; renbr = ((data->step - data->prev_steps) % control->reneighbor) == 0 ? TRUE : FALSE; scalar1 = -0.5 * control->dt * F_CONV; scalar2 = -0.5 * SQR( control->dt ) * F_CONV; - /* velocity verlet, 1st part */ - for ( i = 0; i < system->N; i++ ) + if ( verlet_part1_done == FALSE ) { - inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; + /* velocity verlet, 1st part */ + for ( i = 0; i < system->N; i++ ) + { + inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; - /* Compute x(t + dt) */ - rvec_ScaledSum( dx, control->dt, system->atoms[i].v, scalar2 * inv_m, system->atoms[i].f ); + /* Compute x(t + dt) */ + rvec_ScaledSum( dx, control->dt, system->atoms[i].v, scalar2 * inv_m, system->atoms[i].f ); - control->update_atom_position( system->atoms[i].x, dx, system->atoms[i].rel_map, &system->box ); + control->update_atom_position( system->atoms[i].x, dx, system->atoms[i].rel_map, &system->box ); - /* Compute v(t + dt/2) */ - rvec_ScaledAdd( system->atoms[i].v, scalar1 * inv_m, system->atoms[i].f ); + /* Compute v(t + dt/2) */ + rvec_ScaledAdd( system->atoms[i].v, scalar1 * inv_m, system->atoms[i].f ); + } + + Reallocate_Part1( system, control, workspace, lists ); + + if ( renbr == TRUE ) + { + Bin_Atoms( system, workspace ); + +#if defined(REORDER_ATOMS) + Reorder_Atoms( system, workspace, control ); +#endif + } + + verlet_part1_done = TRUE; } - Reallocate( system, control, workspace, lists, renbr ); + Reallocate_Part2( system, control, data, workspace, lists ); Reset( system, control, data, workspace, lists ); - if ( renbr == TRUE ) + if ( renbr == TRUE && gen_nbr_list == FALSE ) { - Generate_Neighbor_Lists( system, control, data, workspace, lists ); + ret = Generate_Neighbor_Lists( system, control, data, workspace, lists ); + + if ( ret == SUCCESS ) + { + gen_nbr_list = TRUE; + } + else + { + Estimate_Num_Neighbors( system, control, workspace, lists ); + } } - Compute_Forces( system, control, data, workspace, - lists, out_control, FALSE ); + if ( ret == SUCCESS ) + { + ret = Compute_Forces( system, control, data, workspace, lists, + out_control, FALSE ); + } - /* velocity verlet, 2nd part */ - for ( i = 0; i < system->N; i++ ) + if ( ret == SUCCESS ) { - inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; + /* velocity verlet, 2nd part */ + for ( i = 0; i < system->N; i++ ) + { + inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; - /* Compute v(t + dt) */ - rvec_ScaledAdd( system->atoms[i].v, scalar1 * inv_m, system->atoms[i].f ); - } + /* Compute v(t + dt) */ + rvec_ScaledAdd( system->atoms[i].v, scalar1 * inv_m, system->atoms[i].f ); + } - Compute_Kinetic_Energy( system, data ); + Compute_Kinetic_Energy( system, data ); - /* temperature scaler */ - lambda = 1.0 + ((control->dt * 1.0e-12) / control->Tau_T) - * (control->T / data->therm.T - 1.0); + /* temperature scaler */ + lambda = 1.0 + ((control->dt * 1.0e-12) / control->Tau_T) + * (control->T / data->therm.T - 1.0); - if ( lambda < MIN_dT ) - { - lambda = MIN_dT; - } + if ( lambda < MIN_dT ) + { + lambda = MIN_dT; + } - lambda = SQRT( lambda ); + lambda = SQRT( lambda ); - if ( lambda > MAX_dT ) - { - lambda = MAX_dT; - } + if ( lambda > MAX_dT ) + { + lambda = MAX_dT; + } - /* Scale velocities and positions at t+dt */ - for ( i = 0; i < system->N; ++i ) - { - rvec_Scale( system->atoms[i].v, lambda, system->atoms[i].v ); + /* Scale velocities and positions at t+dt */ + for ( i = 0; i < system->N; ++i ) + { + rvec_Scale( system->atoms[i].v, lambda, system->atoms[i].v ); + } + + /* update kinetic energy and temperature based on new velocities */ + Compute_Kinetic_Energy( system, data ); + + verlet_part1_done = FALSE; + gen_nbr_list = FALSE; } - /* update kinetic energy and temperature based on new velocities */ - Compute_Kinetic_Energy( system, data ); + return ret; } -/* Perform simulation using constant volume and temperature (NVT ensemble) - * with a Nose-Hoover thermostat and the Velocity Verlet integrator. +/* Velocity Verlet integrator for constant volume and constant temperature + * with Nose-Hoover thermostat. * * Reference: Understanding Molecular Simulation, Frenkel and Smit * Academic Press Inc. San Diego, 1996 p. 388-391 */ -void Velocity_Verlet_Nose_Hoover_NVT_Klein( reax_system* system, control_params* control, - simulation_data *data, static_storage *workspace, reax_list **lists, - output_controls *out_control ) +int Velocity_Verlet_Nose_Hoover_NVT_Klein( reax_system * const system, + control_params * const control, simulation_data * const data, + static_storage * const workspace, reax_list ** const lists, + output_controls * const out_control ) { - int i, itr, renbr; + int i, itr, renbr, ret; + static int verlet_part1_done = FALSE, gen_nbr_list = FALSE; real inv_m, scalar1, scalar2, scalar3, scalar4, coef_v; real E_kin_new, G_xi_new, v_xi_new, v_xi_old; rvec dx; thermostat *therm; + ret = SUCCESS; renbr = ((data->step - data->prev_steps) % control->reneighbor) == 0 ? TRUE : FALSE; scalar1 = -0.5 * control->dt * F_CONV; scalar2 = -0.5 * SQR( control->dt ) * F_CONV; @@ -185,296 +267,413 @@ void Velocity_Verlet_Nose_Hoover_NVT_Klein( reax_system* system, control_params* scalar4 = -0.5 * SQR( control->dt ); therm = &data->therm; - /* Compute x(t + dt) and copy old forces */ - for ( i = 0; i < system->N; i++ ) + if ( verlet_part1_done == FALSE ) { - inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; + /* Compute x(t + dt) and copy old forces */ + for ( i = 0; i < system->N; i++ ) + { + inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; - rvec_ScaledSum( dx, control->dt + scalar4 * therm->v_xi, system->atoms[i].v, - scalar2 * inv_m, system->atoms[i].f ); + rvec_ScaledSum( dx, control->dt + scalar4 * therm->v_xi, system->atoms[i].v, + scalar2 * inv_m, system->atoms[i].f ); - control->update_atom_position( system->atoms[i].x, dx, - system->atoms[i].rel_map, &system->box ); + control->update_atom_position( system->atoms[i].x, dx, + system->atoms[i].rel_map, &system->box ); - rvec_Copy( workspace->f_old[i], system->atoms[i].f ); - } + rvec_Copy( workspace->f_old[i], system->atoms[i].f ); + } - /* Compute xi(t + dt) */ - therm->xi += therm->v_xi * control->dt + 0.5 * SQR( control->dt ) * therm->G_xi; + /* Compute xi(t + dt) */ + therm->xi += therm->v_xi * control->dt + 0.5 * SQR( control->dt ) * therm->G_xi; - Reallocate( system, control, workspace, lists, renbr ); + if ( renbr == TRUE ) + { + Reallocate_Part1( system, control, workspace, lists ); - Reset( system, control, data, workspace, lists ); + Bin_Atoms( system, workspace ); - if ( renbr == TRUE ) - { - Generate_Neighbor_Lists( system, control, data, workspace, lists ); +#if defined(REORDER_ATOMS) + Reorder_Atoms( system, workspace, control ); +#endif + } + + verlet_part1_done = TRUE; } - /* Calculate Forces at time (t + dt) */ - Compute_Forces( system, control, data, workspace, lists, out_control, FALSE ); + Reallocate_Part2( system, control, data, workspace, lists ); - /* Compute iteration constants for each atom's velocity */ - for ( i = 0; i < system->N; ++i ) + Reset( system, control, data, workspace, lists ); + + if ( renbr == TRUE && gen_nbr_list == FALSE ) { - inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; + ret = Generate_Neighbor_Lists( system, control, data, workspace, lists ); - rvec_Scale( workspace->v_const[i], - 1.0 + scalar3 * therm->v_xi, system->atoms[i].v ); - rvec_ScaledAdd( workspace->v_const[i], - scalar1 * inv_m, workspace->f_old[i] ); - rvec_ScaledAdd( workspace->v_const[i], - scalar1 * inv_m, system->atoms[i].f ); + if ( ret == SUCCESS ) + { + gen_nbr_list = TRUE; + } + else + { + Estimate_Num_Neighbors( system, control, workspace, lists ); + } } - v_xi_new = therm->v_xi_old + 2.0 * control->dt * therm->G_xi; - E_kin_new = 0.0; - G_xi_new = 0.0; - v_xi_old = 0.0; - itr = 0; - do + if ( ret == SUCCESS ) { - itr++; - v_xi_old = v_xi_new; - coef_v = 1.0 / (1.0 + 0.5 * control->dt * v_xi_old); - E_kin_new = 0.0; + /* Calculate Forces at time (t + dt) */ + ret = Compute_Forces( system, control, data, workspace, lists, + out_control, FALSE ); + } + if ( ret == SUCCESS ) + { + /* Compute iteration constants for each atom's velocity */ for ( i = 0; i < system->N; ++i ) { - rvec_Scale( system->atoms[i].v, coef_v, workspace->v_const[i] ); + inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; + + rvec_Scale( workspace->v_const[i], + 1.0 + scalar3 * therm->v_xi, system->atoms[i].v ); + rvec_ScaledAdd( workspace->v_const[i], + scalar1 * inv_m, workspace->f_old[i] ); + rvec_ScaledAdd( workspace->v_const[i], + scalar1 * inv_m, system->atoms[i].f ); + } - E_kin_new += 0.5 * system->reax_param.sbp[system->atoms[i].type].mass - * rvec_Dot( system->atoms[i].v, system->atoms[i].v ); + v_xi_new = therm->v_xi_old + 2.0 * control->dt * therm->G_xi; + E_kin_new = 0.0; + G_xi_new = 0.0; + v_xi_old = 0.0; + itr = 0; + do + { + itr++; + v_xi_old = v_xi_new; + coef_v = 1.0 / (1.0 + 0.5 * control->dt * v_xi_old); + E_kin_new = 0.0; + + for ( i = 0; i < system->N; ++i ) + { + rvec_Scale( system->atoms[i].v, coef_v, workspace->v_const[i] ); + + E_kin_new += 0.5 * system->reax_param.sbp[system->atoms[i].type].mass + * rvec_Dot( system->atoms[i].v, system->atoms[i].v ); + } + + G_xi_new = control->Tau_T * (2.0 * E_kin_new + - data->N_f * K_B * control->T); + v_xi_new = therm->v_xi + 0.5 * control->dt * (therm->G_xi + G_xi_new); } + while ( FABS( v_xi_new - v_xi_old ) > 1.0e-5 ); - G_xi_new = control->Tau_T * (2.0 * E_kin_new - - data->N_f * K_B * control->T); - v_xi_new = therm->v_xi + 0.5 * control->dt * (therm->G_xi + G_xi_new); + therm->v_xi_old = therm->v_xi; + therm->v_xi = v_xi_new; + therm->G_xi = G_xi_new; + + verlet_part1_done = FALSE; + gen_nbr_list = FALSE; } - while ( FABS( v_xi_new - v_xi_old ) > 1.0e-5 ); - therm->v_xi_old = therm->v_xi; - therm->v_xi = v_xi_new; - therm->G_xi = G_xi_new; + return ret; } -/* Perform simulation using constant pressure and temperature (NPT ensemble) - * with a Berendsen thermostat and the Velocity Verlet integrator. +/* Velocity Verlet integrator for constant pressure and constant temperature + * with a Berendsen thermostat. * * NOTE: All box dimensions are scaled by the same amount, and * there is no change in the angles between axes. */ -void Velocity_Verlet_Berendsen_Isotropic_NPT( reax_system* system, - control_params* control, simulation_data *data, static_storage *workspace, - reax_list **lists, output_controls *out_control ) +int Velocity_Verlet_Berendsen_Isotropic_NPT( reax_system * const system, + control_params * const control, simulation_data * const data, + static_storage * const workspace, reax_list ** const lists, + output_controls * const out_control ) { - int i, renbr; + int i, renbr, ret; + static int verlet_part1_done = FALSE, gen_nbr_list = FALSE; real inv_m, dt, lambda, mu; rvec dx, mu_3; + ret = SUCCESS; dt = control->dt; renbr = ((data->step - data->prev_steps) % control->reneighbor) == 0 ? TRUE : FALSE; - /* velocity verlet, 1st part */ - for ( i = 0; i < system->N; i++ ) + if ( verlet_part1_done == FALSE ) { - inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; + /* velocity verlet, 1st part */ + for ( i = 0; i < system->N; i++ ) + { + inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; - /* Compute x(t + dt) */ - rvec_ScaledSum( dx, dt, system->atoms[i].v, - F_CONV * inv_m * -0.5 * SQR(dt), system->atoms[i].f ); + /* Compute x(t + dt) */ + rvec_ScaledSum( dx, dt, system->atoms[i].v, + F_CONV * inv_m * -0.5 * SQR(dt), system->atoms[i].f ); - control->update_atom_position( system->atoms[i].x, dx, system->atoms[i].rel_map, &system->box ); + control->update_atom_position( system->atoms[i].x, dx, system->atoms[i].rel_map, &system->box ); - /* Compute v(t + dt/2) */ - rvec_ScaledAdd( system->atoms[i].v, - F_CONV * inv_m * -0.5 * dt, system->atoms[i].f ); + /* Compute v(t + dt/2) */ + rvec_ScaledAdd( system->atoms[i].v, + F_CONV * inv_m * -0.5 * dt, system->atoms[i].f ); + } + + if ( renbr == TRUE ) + { + Update_Grid( system ); + + Reallocate_Part1( system, control, workspace, lists ); + + Bin_Atoms( system, workspace ); + +#if defined(REORDER_ATOMS) + Reorder_Atoms( system, workspace, control ); +#endif + } + + verlet_part1_done = TRUE; } - Reallocate( system, control, workspace, lists, renbr ); + Reallocate_Part2( system, control, data, workspace, lists ); Reset( system, control, data, workspace, lists ); - if ( renbr == TRUE ) + if ( renbr == TRUE && gen_nbr_list == FALSE ) { - Update_Grid( system ); + ret = Generate_Neighbor_Lists( system, control, data, workspace, lists ); - Generate_Neighbor_Lists( system, control, data, workspace, lists ); + if ( ret == SUCCESS ) + { + gen_nbr_list = TRUE; + } + else + { + Estimate_Num_Neighbors( system, control, workspace, lists ); + } } - Compute_Forces( system, control, data, workspace, lists, out_control, FALSE ); - - /* velocity verlet, 2nd part */ - for ( i = 0; i < system->N; i++ ) + if ( ret == SUCCESS ) { - inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; - - /* Compute v(t + dt) */ - rvec_ScaledAdd( system->atoms[i].v, - -0.5 * dt * F_CONV * inv_m, system->atoms[i].f ); + ret = Compute_Forces( system, control, data, workspace, lists, + out_control, FALSE ); } - Compute_Kinetic_Energy( system, data ); + if ( ret == SUCCESS ) + { + /* velocity verlet, 2nd part */ + for ( i = 0; i < system->N; i++ ) + { + inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; + + /* Compute v(t + dt) */ + rvec_ScaledAdd( system->atoms[i].v, + -0.5 * dt * F_CONV * inv_m, system->atoms[i].f ); + } - Compute_Pressure_Isotropic( system, control, data, out_control ); + Compute_Kinetic_Energy( system, data ); - /* pressure scaler */ - for ( i = 0; i < 3; ++i ) - { - mu_3[i] = POW( 1.0 + (dt / control->Tau_P[i]) - * (data->tot_press[i] - control->P[i]), 1.0 / 3.0 ); + Compute_Pressure_Isotropic( system, control, data, out_control ); - if ( mu_3[i] < MIN_dV ) + /* pressure scaler */ + for ( i = 0; i < 3; ++i ) { - mu_3[i] = MIN_dV; + mu_3[i] = POW( 1.0 + (dt / control->Tau_P[i]) + * (data->tot_press[i] - control->P[i]), 1.0 / 3.0 ); + + if ( mu_3[i] < MIN_dV ) + { + mu_3[i] = MIN_dV; + } + else if ( mu_3[i] > MAX_dV ) + { + mu_3[i] = MAX_dV; + } } - else if ( mu_3[i] > MAX_dV ) + mu = (mu_3[0] + mu_3[1] + mu_3[2]) / 3.0; + + /* temperature scaler */ + lambda = 1.0 + ((dt * 1.0e-12) / control->Tau_T) + * (control->T / data->therm.T - 1.0); + + if ( lambda < MIN_dT ) { - mu_3[i] = MAX_dV; + lambda = MIN_dT; } - } - mu = (mu_3[0] + mu_3[1] + mu_3[2]) / 3.0; - /* temperature scaler */ - lambda = 1.0 + ((dt * 1.0e-12) / control->Tau_T) - * (control->T / data->therm.T - 1.0); + lambda = SQRT( lambda ); - if ( lambda < MIN_dT ) - { - lambda = MIN_dT; - } + if ( lambda > MAX_dT ) + { + lambda = MAX_dT; + } - lambda = SQRT( lambda ); + /* Scale velocities and positions at t+dt */ + for ( i = 0; i < system->N; ++i ) + { + rvec_Scale( system->atoms[i].v, lambda, system->atoms[i].v ); + + /* IMPORTANT: What Adri does with scaling positions first to + * unit coordinates and then back to cartesian coordinates essentially + * is scaling the coordinates with mu^2. However, this causes unphysical + * modifications on the system because box dimensions + * are being scaled with mu! We need to discuss this with Adri! */ + rvec_Scale( system->atoms[i].x, mu, system->atoms[i].x ); + } - if ( lambda > MAX_dT ) - { - lambda = MAX_dT; - } + /* update kinetic energy and temperature based on new velocities */ + Compute_Kinetic_Energy( system, data ); - /* Scale velocities and positions at t+dt */ - for ( i = 0; i < system->N; ++i ) - { - rvec_Scale( system->atoms[i].v, lambda, system->atoms[i].v ); - - /* IMPORTANT: What Adri does with scaling positions first to - * unit coordinates and then back to cartesian coordinates essentially - * is scaling the coordinates with mu^2. However, this causes unphysical - * modifications on the system because box dimensions - * are being scaled with mu! We need to discuss this with Adri! */ - rvec_Scale( system->atoms[i].x, mu, system->atoms[i].x ); - } + Update_Box_Isotropic( &system->box, mu ); - /* update kinetic energy and temperature based on new velocities */ - Compute_Kinetic_Energy( system, data ); + verlet_part1_done = FALSE; + gen_nbr_list = FALSE; + } - Update_Box_Isotropic( &system->box, mu ); + return ret; } /* Perform simulation using constant pressure and temperature (NPT ensemble) * with a Berendsen thermostat and the Velocity Verlet integrator. */ -void Velocity_Verlet_Berendsen_Semi_Isotropic_NPT( reax_system* system, - control_params* control, simulation_data *data, static_storage *workspace, - reax_list **lists, output_controls *out_control ) +int Velocity_Verlet_Berendsen_Semi_Isotropic_NPT( reax_system * const system, + control_params * const control, simulation_data * const data, + static_storage * const workspace, reax_list ** const lists, + output_controls * const out_control ) { - int i, renbr; + int i, renbr, ret; + static int verlet_part1_done = FALSE, gen_nbr_list = FALSE; real dt, inv_m, lambda; rvec dx, mu; + ret = SUCCESS; dt = control->dt; renbr = ((data->step - data->prev_steps) % control->reneighbor) == 0 ? TRUE : FALSE; - /* velocity verlet, 1st part */ - for ( i = 0; i < system->N; i++ ) + if ( verlet_part1_done == FALSE ) { - inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; + /* velocity verlet, 1st part */ + for ( i = 0; i < system->N; i++ ) + { + inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; - /* Compute x(t + dt) */ - rvec_ScaledSum( dx, dt, system->atoms[i].v, - -0.5 * F_CONV * inv_m * SQR(dt), system->atoms[i].f ); + /* Compute x(t + dt) */ + rvec_ScaledSum( dx, dt, system->atoms[i].v, + -0.5 * F_CONV * inv_m * SQR(dt), system->atoms[i].f ); - control->update_atom_position( system->atoms[i].x, dx, system->atoms[i].rel_map, &system->box ); + control->update_atom_position( system->atoms[i].x, dx, system->atoms[i].rel_map, &system->box ); - /* Compute v(t + dt/2) */ - rvec_ScaledAdd( system->atoms[i].v, - -0.5 * F_CONV * inv_m * dt, system->atoms[i].f ); + /* Compute v(t + dt/2) */ + rvec_ScaledAdd( system->atoms[i].v, + -0.5 * F_CONV * inv_m * dt, system->atoms[i].f ); + } + + if ( renbr == TRUE ) + { + Update_Grid( system ); + + Reallocate_Part1( system, control, workspace, lists ); + + Bin_Atoms( system, workspace ); + +#if defined(REORDER_ATOMS) + Reorder_Atoms( system, workspace, control ); +#endif + } + + verlet_part1_done = TRUE; } - Reallocate( system, control, workspace, lists, renbr ); + Reallocate_Part2( system, control, data, workspace, lists ); Reset( system, control, data, workspace, lists ); - if ( renbr == TRUE ) + if ( renbr == TRUE && gen_nbr_list == FALSE ) { - Update_Grid( system ); + ret = Generate_Neighbor_Lists( system, control, data, workspace, lists ); - Generate_Neighbor_Lists( system, control, data, workspace, lists ); + if ( ret == SUCCESS ) + { + gen_nbr_list = TRUE; + } + else + { + Estimate_Num_Neighbors( system, control, workspace, lists ); + } } - Compute_Forces( system, control, data, workspace, lists, out_control, FALSE ); - - /* velocity verlet, 2nd part */ - for ( i = 0; i < system->N; i++ ) + if ( ret == SUCCESS ) { - inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; - /* Compute v(t + dt) */ - rvec_ScaledAdd( system->atoms[i].v, - -0.5 * dt * F_CONV * inv_m, system->atoms[i].f ); + ret = Compute_Forces( system, control, data, workspace, lists, + out_control, FALSE ); } - Compute_Kinetic_Energy( system, data ); + if ( ret == SUCCESS ) + { + /* velocity verlet, 2nd part */ + for ( i = 0; i < system->N; i++ ) + { + inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; + /* Compute v(t + dt) */ + rvec_ScaledAdd( system->atoms[i].v, + -0.5 * dt * F_CONV * inv_m, system->atoms[i].f ); + } - Compute_Pressure_Isotropic( system, control, data, out_control ); + Compute_Kinetic_Energy( system, data ); - /* pressure scaler */ - for ( i = 0; i < 3; ++i ) - { - mu[i] = POW( 1.0 + (dt / control->Tau_P[i]) - * (data->tot_press[i] - control->P[i]), 1.0 / 3.0 ); + Compute_Pressure_Isotropic( system, control, data, out_control ); - if ( mu[i] < MIN_dV ) + /* pressure scaler */ + for ( i = 0; i < 3; ++i ) { - mu[i] = MIN_dV; + mu[i] = POW( 1.0 + (dt / control->Tau_P[i]) + * (data->tot_press[i] - control->P[i]), 1.0 / 3.0 ); + + if ( mu[i] < MIN_dV ) + { + mu[i] = MIN_dV; + } + else if ( mu[i] > MAX_dV ) + { + mu[i] = MAX_dV; + } } - else if ( mu[i] > MAX_dV ) + + /* temperature scaler */ + lambda = 1.0 + ((dt * 1.0e-12) / control->Tau_T) + * (control->T / data->therm.T - 1.0); + + if ( lambda < MIN_dT ) { - mu[i] = MAX_dV; + lambda = MIN_dT; } - } - /* temperature scaler */ - lambda = 1.0 + ((dt * 1.0e-12) / control->Tau_T) - * (control->T / data->therm.T - 1.0); + lambda = SQRT( lambda ); - if ( lambda < MIN_dT ) - { - lambda = MIN_dT; - } + if ( lambda > MAX_dT ) + { + lambda = MAX_dT; + } - lambda = SQRT( lambda ); + /* Scale velocities and positions at t+dt */ + for ( i = 0; i < system->N; ++i ) + { + rvec_Scale( system->atoms[i].v, lambda, system->atoms[i].v ); + + /* IMPORTANT: What Adri does with scaling positions first to + * unit coordinates and then back to cartesian coordinates essentially + * is scaling the coordinates with mu^2. However, this causes unphysical + * modifications on the system because box dimensions + * are being scaled with mu! We need to discuss this with Adri! */ + rvec_Multiply( system->atoms[i].x, mu, system->atoms[i].x ); + } - if ( lambda > MAX_dT ) - { - lambda = MAX_dT; - } + /* update kinetic energy and temperature based on new velocities */ + Compute_Kinetic_Energy( system, data ); - /* Scale velocities and positions at t+dt */ - for ( i = 0; i < system->N; ++i ) - { - rvec_Scale( system->atoms[i].v, lambda, system->atoms[i].v ); - - /* IMPORTANT: What Adri does with scaling positions first to - * unit coordinates and then back to cartesian coordinates essentially - * is scaling the coordinates with mu^2. However, this causes unphysical - * modifications on the system because box dimensions - * are being scaled with mu! We need to discuss this with Adri! */ - rvec_Multiply( system->atoms[i].x, mu, system->atoms[i].x ); - } + Update_Box_Semi_Isotropic( &system->box, mu ); - /* update kinetic energy and temperature based on new velocities */ - Compute_Kinetic_Energy( system, data ); + verlet_part1_done = FALSE; + gen_nbr_list = FALSE; + } - Update_Box_Semi_Isotropic( &system->box, mu ); + return ret; } @@ -482,16 +681,19 @@ void Velocity_Verlet_Berendsen_Semi_Isotropic_NPT( reax_system* system, /* BELOW FUNCTIONS ARE NOT BEING USED ANYMORE! */ /************************************************/ #if defined(ANISOTROPIC) -void Velocity_Verlet_Nose_Hoover_NVT( reax_system* system, control_params* control, - simulation_data *data, static_storage *workspace, reax_list **lists, - output_controls *out_control ) +int Velocity_Verlet_Nose_Hoover_NVT( reax_system * const system, + control_params * const control, simulation_data * const data, + static_storage * const workspace, reax_list ** const lists, + output_controls * const out_control ) { - int i; + int i, ret; real inv_m; real dt = control->dt; real dt_sqr = SQR(dt); rvec dx; + ret = SUCCESS; + for ( i = 0; i < system->N; i++ ) { inv_m = 1.0 / system->reax_param.sbp[system->atoms[i].type].mass; @@ -515,6 +717,15 @@ void Velocity_Verlet_Nose_Hoover_NVT( reax_system* system, control_params* contr data->therm.xi += 0.5 * dt * control->Tau_T * (2.0 * data->E_Kin - data->N_f * K_B / F_CONV * control->T); + if ( renbr == TRUE ) + { + Bin_Atoms( system, workspace ); + +#if defined(REORDER_ATOMS) + Reorder_Atoms( system, workspace, control ); +#endif + } + Reset( system, control, data, workspace ); fprintf(out_control->log, "reset-"); fflush( out_control->log ); @@ -552,14 +763,17 @@ void Velocity_Verlet_Nose_Hoover_NVT( reax_system* system, control_params* contr fprintf( out_control->log, "Xi: %8.3f %8.3f %8.3f\n", data->therm.xi, data->E_Kin, data->N_f * K_B / F_CONV * control->T ); fflush( out_control->log ); + + return ret; } -void Velocity_Verlet_Isotropic_NPT( reax_system* system, control_params* control, - simulation_data *data, static_storage *workspace, reax_list **lists, - output_controls *out_control ) +int Velocity_Verlet_Isotropic_NPT( reax_system * const system, + control_params * const control, simulation_data * const data, + static_storage * const workspace, reax_list ** const lists, + output_controls * const out_control ) { - int i, itr; + int i, itr, ret; real deps, v_eps_new = 0, v_eps_old = 0, G_xi_new; real dxi, v_xi_new = 0, v_xi_old = 0, a_eps_new; real inv_m, exp_deps, inv_3V; @@ -572,6 +786,8 @@ void Velocity_Verlet_Isotropic_NPT( reax_system* system, control_params* control simulation_box *box = &system->box; rvec dx, dv; + ret = SUCCESS; + // Here we just calculate how much to increment eps, xi, v_eps, v_xi. // Commits are done after positions and velocities of atoms are updated // because position, velocity updates uses v_eps, v_xi terms; @@ -618,6 +834,15 @@ void Velocity_Verlet_Isotropic_NPT( reax_system* system, control_params* control iso_bar->eps += deps; Update_Box_Isotropic( &system->box, EXP( 3.0 * iso_bar->eps ) ); + if ( renbr == TRUE ) + { + Bin_Atoms( system, workspace ); + +#if defined(REORDER_ATOMS) + Reorder_Atoms( system, workspace, control ); +#endif + } + /* Calculate new forces, f(t + dt) */ Reset( system, control, data, workspace ); fprintf(out_control->log, "reset-"); @@ -718,5 +943,7 @@ void Velocity_Verlet_Isotropic_NPT( reax_system* system, control_params* control iso_bar->a_eps, iso_bar->v_eps, iso_bar->eps); fprintf(out_control->log, "xi: \tG- %8.3f v- %8.3f xi - %8.3f\n", therm->G_xi, therm->v_xi, therm->xi); + + return ret; } #endif diff --git a/sPuReMD/src/integrate.h b/sPuReMD/src/integrate.h index 7207fa8f..b7f6dd3b 100644 --- a/sPuReMD/src/integrate.h +++ b/sPuReMD/src/integrate.h @@ -26,26 +26,26 @@ #include "reax_types.h" -void Velocity_Verlet_NVE( reax_system *, control_params *, simulation_data *, +int Velocity_Verlet_NVE( reax_system *, control_params *, simulation_data *, static_storage *, reax_list **, output_controls * ); -void Velocity_Verlet_Berendsen_NVT( reax_system *, control_params *, +int Velocity_Verlet_Berendsen_NVT( reax_system *, control_params *, simulation_data *, static_storage *, reax_list **, output_controls * ); -void Velocity_Verlet_Nose_Hoover_NVT_Klein( reax_system *, control_params *, +int Velocity_Verlet_Nose_Hoover_NVT_Klein( reax_system *, control_params *, simulation_data *, static_storage *, reax_list **, output_controls * ); -void Velocity_Verlet_Berendsen_Isotropic_NPT( reax_system *, control_params *, +int Velocity_Verlet_Berendsen_Isotropic_NPT( reax_system *, control_params *, simulation_data *, static_storage *, reax_list **, output_controls * ); -void Velocity_Verlet_Berendsen_Semi_Isotropic_NPT( reax_system *, control_params *, +int Velocity_Verlet_Berendsen_Semi_Isotropic_NPT( reax_system *, control_params *, simulation_data *, static_storage *, reax_list **, output_controls * ); #if defined(ANISOTROPIC) -void Velocity_Verlet_Nose_Hoover_NVT( reax_system *, control_params *, +int Velocity_Verlet_Nose_Hoover_NVT( reax_system *, control_params *, simulation_data *, static_storage *, reax_list **, output_controls * ); -void Velocity_Verlet_Isotropic_NPT( reax_system *, control_params *, +int Velocity_Verlet_Isotropic_NPT( reax_system *, control_params *, simulation_data *, static_storage *, reax_list **, output_controls * ); #endif diff --git a/sPuReMD/src/list.c b/sPuReMD/src/list.c index fd9087e4..cd20c089 100644 --- a/sPuReMD/src/list.c +++ b/sPuReMD/src/list.c @@ -24,7 +24,8 @@ #include "tool_box.h" -void Make_List( int n, int n_max, int total_intrs, int type, reax_list* l ) +/* Allocates a new instance of reax_list with internal lists of specified type */ +void Make_List( int n, int n_max, int total_intrs, int type, reax_list * const l ) { assert( n > 0 ); assert( n_max > 0 ); @@ -141,7 +142,8 @@ void Make_List( int n, int n_max, int total_intrs, int type, reax_list* l ) } -void Delete_List( int type, reax_list* l ) +/* Deallocates any space allocated for a reax_list instance */ +void Delete_List( int type, reax_list * const l ) { assert( l != NULL ); @@ -217,3 +219,22 @@ void Delete_List( int type, reax_list* l ) break; } } + + +/* Initialize list indices + * + * l: pointer to list + * */ +void Init_List_Indices( reax_list * const l ) +{ + int i; + + assert( l != NULL ); + assert( l->n > 0 ); + + for ( i = 0; i < l->n; ++i ) + { + Set_Start_Index( i, 0, l ); + Set_End_Index( i, 0, l ); + } +} diff --git a/sPuReMD/src/list.h b/sPuReMD/src/list.h index 6c46c1e9..43b5dca6 100644 --- a/sPuReMD/src/list.h +++ b/sPuReMD/src/list.h @@ -25,11 +25,28 @@ #include "reax_types.h" -void Make_List( int, int, int, int, reax_list* ); - -void Delete_List( int, reax_list* ); - - +/* Allocates a new instance of reax_list with internal lists of specified type */ +void Make_List( int, int, int, int, reax_list * const ); + +/* Deallocates any space allocated for a reax_list instance */ +void Delete_List( int, reax_list * const ); + +void Init_List_Indices( reax_list * const ); + + +/* Return the size for the i-th internal list + * + * Inputs: + * l: list of lists (reax_list) + * i: list to return size for + * + * Returns: + * size of i-th internal list + * + * Unchecked runtime exceptions: + * l is not a NULL pointer + * i is a valid internal list index + * */ static inline int Num_Entries( int i, reax_list const * const l ) { assert( l != NULL ); diff --git a/sPuReMD/src/neighbors.c b/sPuReMD/src/neighbors.c index a673c46d..c75db365 100644 --- a/sPuReMD/src/neighbors.c +++ b/sPuReMD/src/neighbors.c @@ -42,10 +42,10 @@ * Define the preprocessor definition SMALL_BOX_SUPPORT to enable (in * reax_types.h). */ typedef int (*count_far_neighbors_function)( rvec, rvec, int, int, - simulation_box*, real ); + simulation_box const * const, real ); typedef int (*find_far_neighbors_function)( rvec, rvec, int, int, - simulation_box*, real, far_neighbor_data* ); + simulation_box const * const, real, far_neighbor_data * const, int ); static void Choose_Neighbor_Counter( reax_system const * const system, @@ -132,7 +132,7 @@ static inline real DistSqr_to_CP( rvec cp, rvec x ) /* Estimate the storage requirements for the far neighbor list */ -int Estimate_Num_Neighbors( reax_system * const system, +void Estimate_Num_Neighbors( reax_system const * const system, control_params const * const control, static_storage * const workspace, reax_list ** const lists ) { @@ -143,16 +143,13 @@ int Estimate_Num_Neighbors( reax_system * const system, int *nbr_atoms; ivec *nbrs; rvec *nbrs_cp; - grid *g; + grid const * const g = &system->g; count_far_neighbors_function Count_Far_Neighbors; - g = &system->g; num_far = 0; Choose_Neighbor_Counter( system, control, &Count_Far_Neighbors ); - Bin_Atoms( system, workspace ); - /* for each cell in the grid along the 3 * Cartesian directions: (i, j, k) => (x, y, z) */ for ( i = 0; i < g->ncell[0]; i++ ) @@ -211,46 +208,34 @@ int Estimate_Num_Neighbors( reax_system * const system, } } -#if defined(DEBUG_FOCUS) - fprintf( stderr, "[INFO] Estimate_Num_Neighbors: num_far = %d\n", - (int) CEIL( num_far * SAFE_ZONE ) ); -#endif - - return (int) CEIL( num_far * SAFE_ZONE ); + workspace->realloc.total_far_nbrs = (int) CEIL( num_far * SAFE_ZONE ); } /* Generate the far neighbor list */ -void Generate_Neighbor_Lists( reax_system * const system, +int Generate_Neighbor_Lists( reax_system * const system, control_params const * const control, simulation_data * const data, static_storage * const workspace, reax_list ** const lists ) { int i, j, k, l, m, itr; int x, y, z; int atom1, atom2, max; - int num_far, count; + int num_far, count, ret; int *nbr_atoms; ivec *nbrs; rvec *nbrs_cp; - grid *g; + grid const * const g = &system->g; reax_list *far_nbrs; - far_neighbor_data *nbr_data; find_far_neighbors_function Find_Far_Neighbors; real t_start, t_elapsed; t_start = Get_Time( ); - g = &system->g; num_far = 0; far_nbrs = lists[FAR_NBRS]; + ret = SUCCESS; Choose_Neighbor_Finder( system, control, &Find_Far_Neighbors ); - Bin_Atoms( system, workspace ); - -#if defined(REORDER_ATOMS) - Reorder_Atoms( system, workspace, control ); -#endif - for ( i = 0; i < far_nbrs->n; ++i ) { Set_Start_Index( i, 0, far_nbrs ); @@ -300,11 +285,11 @@ void Generate_Neighbor_Lists( reax_system * const system, if ( atom1 >= atom2 ) { - nbr_data = &far_nbrs->far_nbr_list[num_far]; - count = Find_Far_Neighbors( system->atoms[atom1].x, system->atoms[atom2].x, atom1, atom2, - &system->box, control->vlist_cut, nbr_data ); + &system->box, control->vlist_cut, + &far_nbrs->far_nbr_list[num_far], + far_nbrs->total_intrs - num_far ); num_far += count; } @@ -315,11 +300,6 @@ void Generate_Neighbor_Lists( reax_system * const system, } Set_End_Index( atom1, num_far, far_nbrs ); - -#if defined(DEBUG_FOCUS) - fprintf( stderr, "[INFO] Generate_Neighbor_Lists: i = %d, start = %d, end = %d, itr = %d\n", - atom1, Start_Index(atom1,far_nbrs), End_Index(atom1,far_nbrs), itr ); -#endif } } } @@ -331,16 +311,9 @@ void Generate_Neighbor_Lists( reax_system * const system, ivec_MakeZero( system->atoms[i].rel_map ); } - if ( num_far > far_nbrs->total_intrs * DANGER_ZONE ) + if ( num_far > far_nbrs->total_intrs ) { - workspace->realloc.num_far = num_far; - - if ( num_far > far_nbrs->total_intrs ) - { - fprintf( stderr, "[ERROR] Generate_Neighbor_Lists: step%d-ran out of space on far_nbrs: top=%d, max=%d", - data->step, num_far, far_nbrs->total_intrs ); - exit( INSUFFICIENT_MEMORY ); - } + ret = FAILURE; } #if defined(DEBUG_FOCUS) @@ -358,4 +331,6 @@ void Generate_Neighbor_Lists( reax_system * const system, t_elapsed = Get_Timing_Info( t_start ); data->timing.nbrs += t_elapsed; + + return ret; } diff --git a/sPuReMD/src/neighbors.h b/sPuReMD/src/neighbors.h index 45292a9d..24047cac 100644 --- a/sPuReMD/src/neighbors.h +++ b/sPuReMD/src/neighbors.h @@ -25,11 +25,11 @@ #include "reax_types.h" -void Generate_Neighbor_Lists( reax_system * const, control_params const * const, - simulation_data * const, static_storage * const, reax_list ** const ); - -int Estimate_Num_Neighbors( reax_system * const, control_params const * const, +void Estimate_Num_Neighbors( reax_system const * const, control_params const * const, static_storage * const, reax_list ** const ); +int Generate_Neighbor_Lists( reax_system * const, control_params const * const, + simulation_data * const, static_storage * const, reax_list ** const ); + #endif diff --git a/sPuReMD/src/reax_types.h b/sPuReMD/src/reax_types.h index 286a0d29..7cf2fabf 100644 --- a/sPuReMD/src/reax_types.h +++ b/sPuReMD/src/reax_types.h @@ -70,12 +70,12 @@ #if defined(USE_REF_FORTRAN_REAXFF_CONSTANTS) /* transcendental constant pi */ #define PI (3.14159265) - /* unit conversion from ??? to kcal / mol */ + /* unit conversion, ??? to kcal / mol */ #define C_ELE (332.0638) - /* Boltzmann constant, AMU * A^2 / (ps^2 * K) */ + /* Boltzmann constant, in J / mol / K */ // #define K_B (0.831687) #define K_B (0.8314510) - /* unit conversion for atomic force to AMU * A / ps^2 */ + /* unit conversion for atomic force, kcal to J */ #define F_CONV (4.184e2) /* energy conversion constant from electron volts to kilo-calories per mole */ #define KCALpMOL_to_EV (23.02) @@ -110,13 +110,13 @@ #if !defined(K_B) /* in ??? */ // #define K_B (503.398008) - /* Boltzmann constant, AMU * A^2 / (ps^2 * K) */ + /* in J / mol / K */ // #define K_B (0.831687) #define K_B (0.8314510) #endif /* unit conversion for atomic force */ #if !defined(F_CONV) - /* to AMU * A / ps^2 */ + /* ??? to AMU * A / ps^2 */ #define F_CONV (1.0e6 / 48.88821291 / 48.88821291) #endif /* unit conversion for atomic energy */ @@ -196,6 +196,10 @@ /* min. temperature scaler for atomic positions and velocities in NPT ensembles */ #define MIN_dT (0.0) +/* max. num. of main simulation loop retries; + * retries occur when memory allocation checks determine more memory is needed */ +#define MAX_RETRIES (5) + #define ALMOST_ZERO (1.0e-10) #define NEG_INF (-1.0e10) #define NO_BOND (1.0e-3) @@ -433,31 +437,32 @@ typedef struct spuremd_handle spuremd_handle; /* function pointer for calculating a bonded interaction */ -typedef void (*interaction_function)( reax_system*, control_params*, - simulation_data*, static_storage*, reax_list**, output_controls* ); +typedef void (*interaction_function)( reax_system *, control_params *, + simulation_data *, static_storage *, reax_list **, output_controls * ); /* function pointer for calculating pairwise atom distance */ -typedef real (*atom_distance_function)( simulation_box*, +typedef real (*atom_distance_function)( simulation_box const * const, rvec, rvec, ivec, ivec, ivec, rvec ); /* function pointer for updating atom positions */ -typedef void (*update_atom_position_function)( rvec, rvec, ivec, simulation_box* ); +typedef void (*update_atom_position_function)( rvec, rvec, ivec, simulation_box const * const ); #if defined(TEST_FORCES) /* function pointers for printed bonded interactions */ -typedef void (*print_interaction)(reax_system*, control_params*, simulation_data*, - static_storage*, reax_list**, output_controls* ); +typedef void (*print_interaction)( reax_system *, control_params *, simulation_data *, + static_storage *, reax_list **, output_controls * ); #endif /* function pointer for evolving the atomic system (i.e., updating the positions) * given the pre-computed forces from the prescribed interactions */ -typedef void (*evolve_function)( reax_system*, control_params*, - simulation_data*, static_storage*, reax_list**, output_controls* ); +typedef int (*evolve_function)( reax_system * const, control_params * const, + simulation_data * const, static_storage * const, reax_list ** const, + output_controls * const ); /* function pointer for a callback function to be triggered after * completion of a simulation step -- useful for, e.g., the Python wrapper */ -typedef void (*callback_function)( int, reax_atom*, simulation_data* ); +typedef void (*callback_function)( int, reax_atom *, simulation_data * ); /* function pointer for writing trajectory file header */ -typedef int (*write_header_function)( reax_system*, control_params*, - static_storage*, output_controls* ); +typedef int (*write_header_function)( reax_system *, control_params *, + static_storage *, output_controls * ); /* function pointer for apending a frame to the trajectory file */ -typedef int (*append_traj_frame_function)( reax_system*, control_params*, - simulation_data*, static_storage*, reax_list **, output_controls* ); +typedef int (*append_traj_frame_function)( reax_system *, control_params *, + simulation_data *, static_storage *, reax_list **, output_controls * ); /* function pointer for writing to the trajectory file */ typedef int (*write_function)( FILE *, const char *, ... ); @@ -891,14 +896,21 @@ struct reax_system unsigned int num_molec_charge_constraints; /* max. num. of charge constraints on groups of atoms (i.e., molecules) */ unsigned int max_num_molec_charge_constraints; - /* atom info */ - reax_atom *atoms; /* atomic interaction parameters */ reax_interaction reax_param; - /* simulation space (a.k.a. box) parameters */ + /* grid specifying domain (i.e., spatial) decompisition + * of atoms within simulation box */ simulation_box box; /* grid structure used for binning atoms and tracking neighboring bins */ grid g; + /* collection of atomic info. */ + reax_atom *atoms; + /* num. bonds per atom */ + int *bonds; + /* num. hydrogen bonds per atom */ + int *hbonds; + /* num. matrix entries per row */ + int *cm_entries; }; @@ -1439,15 +1451,35 @@ struct sparse_matrix }; +/* used to determine if and how much space should be reallocated */ struct reallocate_data { - int num_far; - int Htop; + /* TRUE if far neighbor list needs + * to be reallocated, FALSE otherwise */ + int far_nbrs; + /* total num. of (max) far neighbors across all atoms */ + int total_far_nbrs; + /* TRUE if charge matrix needs + * to be reallocated, FALSE otherwise */ + int cm; + /* total num. matrix entries (sum over max) */ + int total_cm_entries; + /* TRUE if hbond list needs + * to be reallocated, FALSE otherwise */ int hbonds; - int num_hbonds; + /* total num. hydrogen bonds (sum over max) */ + int total_hbonds; + /* TRUE if bond list needs + * to be reallocated, FALSE otherwise */ int bonds; - int num_bonds; - int num_3body; + /* total num. bonds (sum over max) */ + int total_bonds; + /* TRUE if three body list needs + * to be reallocated, FALSE otherwise */ + int thbody; + /* total num. three body interactions */ + int total_thbodies; + /**/ int gcell_atoms; }; @@ -1664,23 +1696,21 @@ struct static_storage }; -/* interaction lists */ +/* 1-D flattened list of lists used for various interaction types */ struct reax_list { - /* 0 if struct members are NOT allocated, 1 otherwise */ + /* FALSE if struct members are NOT allocated, TRUE otherwise */ int allocated; - /* num. active entries in list for this simulation */ + /* num. active entries (i.e., nested lists) in the list for this simulation */ int n; - /* max. num. entries in list across all simulations */ + /* max. num. entries (i.e., nested lists) in the list across all simulations */ int n_max; /* total interactions across all entries which can be stored in the list */ int total_intrs; - /* starting position of atom's interactions */ + /* starting position of interactions for an inner list */ int *index; - /* ending position of atom's interactions */ + /* ending position of interactions for an inner list */ int *end_index; - /* max. num. of interactions per list entry */ - int *max_intrs; /* interaction list (polymorphic via union dereference) */ // union // { diff --git a/sPuReMD/src/reset_tools.c b/sPuReMD/src/reset_tools.c index 57ececef..6756bb87 100644 --- a/sPuReMD/src/reset_tools.c +++ b/sPuReMD/src/reset_tools.c @@ -200,7 +200,7 @@ void Reset_Neighbor_Lists( reax_system *system, control_params *control, Set_End_Index( i, tmp, bonds ); } - if ( control->hbond_cut > 0.0 ) + if ( control->hbond_cut > 0.0 && workspace->num_H > 0 ) { for ( i = 0; i < system->N; ++i ) { @@ -268,7 +268,6 @@ void Reset_Grid( grid *g ) } - void Reset_Marks( grid *g, ivec *grid_stack, int grid_top ) { int i; diff --git a/sPuReMD/src/spuremd.c b/sPuReMD/src/spuremd.c index 913d3050..28214f53 100644 --- a/sPuReMD/src/spuremd.c +++ b/sPuReMD/src/spuremd.c @@ -353,7 +353,7 @@ int setup_callback( const void * const handle, const callback_function callback */ int simulate( const void * const handle ) { - int steps, ret; + int steps, ret, ret_forces, retries; evolve_function Evolve; spuremd_handle *spmd_handle; @@ -374,10 +374,23 @@ int simulate( const void * const handle ) Reset( spmd_handle->system, spmd_handle->control, spmd_handle->data, spmd_handle->workspace, spmd_handle->lists ); - Compute_Forces( spmd_handle->system, spmd_handle->control, spmd_handle->data, + ret_forces = Compute_Forces( spmd_handle->system, spmd_handle->control, spmd_handle->data, spmd_handle->workspace, spmd_handle->lists, spmd_handle->out_control, spmd_handle->realloc ); + if ( ret_forces != SUCCESS ) + { + ret_forces = Compute_Forces( spmd_handle->system, spmd_handle->control, spmd_handle->data, + spmd_handle->workspace, spmd_handle->lists, spmd_handle->out_control, + spmd_handle->realloc ); + + if ( ret_forces != SUCCESS ) + { + fprintf( stderr, "[ERROR] Unrecoverable memory allocation issue (Compute_Forces). Terminating...\n" ); + exit( INVALID_GEO ); + } + } + Compute_Kinetic_Energy( spmd_handle->system, spmd_handle->data ); if ( spmd_handle->control->compute_pressure == TRUE && spmd_handle->control->ensemble != sNPT @@ -414,54 +427,76 @@ int simulate( const void * const handle ) } //} - for ( ++spmd_handle->data->step; spmd_handle->data->step <= spmd_handle->control->nsteps; spmd_handle->data->step++ ) + ++spmd_handle->data->step; + retries = 0; + while ( spmd_handle->data->step <= spmd_handle->control->nsteps + && retries < MAX_RETRIES ) { + ret = SUCCESS; + if ( spmd_handle->control->T_mode != 0 ) { Temperature_Control( spmd_handle->control, spmd_handle->data, spmd_handle->out_control ); } - Evolve( spmd_handle->system, spmd_handle->control, spmd_handle->data, - spmd_handle->workspace, spmd_handle->lists, spmd_handle->out_control ); - - Post_Evolve( spmd_handle->system, spmd_handle->control, spmd_handle->data, + ret = Evolve( spmd_handle->system, spmd_handle->control, spmd_handle->data, spmd_handle->workspace, spmd_handle->lists, spmd_handle->out_control ); - if ( spmd_handle->output_enabled == TRUE ) + if ( ret == SUCCESS ) { - Output_Results( spmd_handle->system, spmd_handle->control, spmd_handle->data, + Post_Evolve( spmd_handle->system, spmd_handle->control, spmd_handle->data, spmd_handle->workspace, spmd_handle->lists, spmd_handle->out_control ); } - Check_Energy( spmd_handle->data ); - - if ( spmd_handle->output_enabled == TRUE ) + if ( ret == SUCCESS ) { - steps = spmd_handle->data->step - spmd_handle->data->prev_steps; + if ( spmd_handle->output_enabled == TRUE ) + { + Output_Results( spmd_handle->system, spmd_handle->control, spmd_handle->data, + spmd_handle->workspace, spmd_handle->lists, spmd_handle->out_control ); + } - Analysis( spmd_handle->system, spmd_handle->control, spmd_handle->data, - spmd_handle->workspace, spmd_handle->lists, spmd_handle->out_control ); + Check_Energy( spmd_handle->data ); - if ( spmd_handle->out_control->restart_freq > 0 - && steps % spmd_handle->out_control->restart_freq == 0 ) + if ( spmd_handle->output_enabled == TRUE ) { - Write_Restart( spmd_handle->system, spmd_handle->control, spmd_handle->data, - spmd_handle->workspace, spmd_handle->out_control ); + steps = spmd_handle->data->step - spmd_handle->data->prev_steps; + + Analysis( spmd_handle->system, spmd_handle->control, spmd_handle->data, + spmd_handle->workspace, spmd_handle->lists, spmd_handle->out_control ); + + if ( spmd_handle->out_control->restart_freq > 0 + && steps % spmd_handle->out_control->restart_freq == 0 ) + { + Write_Restart( spmd_handle->system, spmd_handle->control, spmd_handle->data, + spmd_handle->workspace, spmd_handle->out_control ); + } + + if ( spmd_handle->out_control->write_steps > 0 + && steps % spmd_handle->out_control->write_steps == 0 ) + { + Write_PDB( spmd_handle->system, spmd_handle->lists[BONDS], spmd_handle->data, + spmd_handle->control, spmd_handle->workspace, spmd_handle->out_control ); + } } - if ( spmd_handle->out_control->write_steps > 0 - && steps % spmd_handle->out_control->write_steps == 0 ) + if ( spmd_handle->callback != NULL ) { - Write_PDB( spmd_handle->system, spmd_handle->lists[BONDS], spmd_handle->data, - spmd_handle->control, spmd_handle->workspace, spmd_handle->out_control ); + spmd_handle->callback( spmd_handle->system->N, spmd_handle->system->atoms, + spmd_handle->data ); } - } - if ( spmd_handle->callback != NULL ) + ++spmd_handle->data->step; + retries = 0; + } + else { - spmd_handle->callback( spmd_handle->system->N, spmd_handle->system->atoms, - spmd_handle->data ); + ++retries; + +#if defined(DEBUG_FOCUS) + fprintf( stderr, "[INFO] p%d: retrying step %d...\n", system->my_rank, data->step ); +#endif } } diff --git a/sPuReMD/src/system_props.c b/sPuReMD/src/system_props.c index 57a060a8..0829259b 100644 --- a/sPuReMD/src/system_props.c +++ b/sPuReMD/src/system_props.c @@ -59,7 +59,8 @@ void Temperature_Control( control_params *control, simulation_data *data, } -void Compute_Total_Mass( reax_system *system, simulation_data *data ) +void Compute_Total_Mass( reax_system const * const system, + simulation_data * const data ) { int i; @@ -74,7 +75,8 @@ void Compute_Total_Mass( reax_system *system, simulation_data *data ) } -void Compute_Center_of_Mass( reax_system *system, simulation_data *data ) +void Compute_Center_of_Mass( reax_system const * const system, + simulation_data * const data ) { int i; real m, xx, xy, xz, yy, yz, zz, det; @@ -181,7 +183,8 @@ void Compute_Center_of_Mass( reax_system *system, simulation_data *data ) } -void Compute_Kinetic_Energy( reax_system* system, simulation_data* data ) +void Compute_Kinetic_Energy( reax_system const * const system, + simulation_data * const data ) { int i; real m; diff --git a/sPuReMD/src/system_props.h b/sPuReMD/src/system_props.h index 26e1594b..6fccbc4a 100644 --- a/sPuReMD/src/system_props.h +++ b/sPuReMD/src/system_props.h @@ -27,11 +27,11 @@ void Temperature_Control( control_params*, simulation_data*, output_controls* ); -void Compute_Total_Mass( reax_system*, simulation_data* ); +void Compute_Total_Mass( reax_system const * const, simulation_data * const ); -void Compute_Center_of_Mass( reax_system*, simulation_data* ); +void Compute_Center_of_Mass( reax_system const * const, simulation_data * const ); -void Compute_Kinetic_Energy( reax_system*, simulation_data* ); +void Compute_Kinetic_Energy( reax_system const * const , simulation_data * const ); void Compute_Total_Energy( simulation_data* ); diff --git a/sPuReMD/src/valence_angles.c b/sPuReMD/src/valence_angles.c index 5f094610..1a85372f 100644 --- a/sPuReMD/src/valence_angles.c +++ b/sPuReMD/src/valence_angles.c @@ -718,22 +718,26 @@ void Valence_Angles( reax_system *system, control_params *control, if ( num_thb_intrs >= thb_intrs->total_intrs * DANGER_ZONE ) { - workspace->realloc.num_3body = num_thb_intrs; + workspace->realloc.total_thbodies = (int) CEIL( num_thb_intrs * SAFE_ZONE ); + workspace->realloc.thbody = TRUE; + + /* retry functionality is not implemented as valence angle list + * computation is not an atomic transaction, so use older reallocation strategy for now */ if ( num_thb_intrs > thb_intrs->total_intrs ) { - fprintf( stderr, "step%d-ran out of space on angle_list: top=%d, max=%d", + fprintf( stderr, "[ERROR] step%d-ran out of space on angle_list: top=%d, max=%d", data->step, num_thb_intrs, thb_intrs->total_intrs ); exit( INSUFFICIENT_MEMORY ); } } #if defined(TEST_ENERGY) - fprintf( stderr, "Number of angle interactions: %d\n", num_thb_intrs ); + fprintf( stderr, "[INFO] Number of angle interactions: %d\n", num_thb_intrs ); - fprintf( stderr, "Angle Energy: %g\t Penalty Energy: %g\t Coalition Energy: %g\n", + fprintf( stderr, "[INFO] Angle Energy: %g\t Penalty Energy: %g\t Coalition Energy: %g\n", data->E_Ang, data->E_Pen, data->E_Coa ); - fprintf( stderr, "3body: press (%23.15e %23.15e %23.15e)\n", + fprintf( stderr, "[INFO] 3body: press (%23.15e %23.15e %23.15e)\n", data->press[0][0], data->press[1][1], data->press[2][2] ); #endif } -- GitLab