-
Kurt A. O'Hearn authoredKurt A. O'Hearn authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
allocate.c 31.83 KiB
/*----------------------------------------------------------------------
PuReMD - Purdue ReaxFF Molecular Dynamics Program
Copyright (2010) Purdue University
Hasan Metin Aktulga, haktulga@cs.purdue.edu
Joseph Fogarty, jcfogart@mail.usf.edu
Sagar Pandit, pandit@usf.edu
Ananth Y Grama, ayg@cs.purdue.edu
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reax_types.h"
#include "index_utils.h"
#if defined(PURE_REAX)
#include "allocate.h"
#include "list.h"
#include "reset_tools.h"
#include "tool_box.h"
#include "vector.h"
#elif defined(LAMMPS_REAX)
#include "reax_allocate.h"
#include "reax_list.h"
#include "reax_reset_tools.h"
#include "reax_tool_box.h"
#include "reax_vector.h"
#endif
/* allocate space for my_atoms
important: we cannot know the exact number of atoms that will fall into a
process's box throughout the whole simulation. therefore
we need to make upper bound estimates for various data structures */
int PreAllocate_Space( reax_system *system, control_params *control,
storage *workspace )
{
/* determine capacity based on box vol & est atom volume */
system->local_cap = MAX( (int)(system->n * SAFE_ZONE), MIN_CAP );
system->total_cap = MAX( (int)(system->N * SAFE_ZONE), MIN_CAP );
#if defined(DEBUG)||defined(__CUDA_DEBUG_LOG__)
fprintf( stderr, "p%d: local_cap=%d total_cap=%d\n",
system->my_rank, system->local_cap, system->total_cap );
#endif
system->my_atoms = (reax_atom*)
scalloc( system->total_cap, sizeof(reax_atom), "my_atoms" );
/* space for keeping restriction info, if any */
if ( control->restrict_bonds )
{
workspace->restricted =
(int*) scalloc( system->local_cap, sizeof(int), "restricted_atoms" );
workspace->restricted_list = (int *)
scalloc( system->local_cap * MAX_RESTRICT, sizeof(int), "restricted_list" );
}
return SUCCESS;
}
/************* system *************/
void Allocate_System( reax_system *system, int local_cap, int total_cap,
char *msg )
{
system->my_atoms = (reax_atom*)
srealloc( system->my_atoms, total_cap * sizeof(reax_atom), "system:my_atoms" );
}
/************* workspace *************/
void DeAllocate_Workspace( control_params *control, storage *workspace )
{
int i;
if ( workspace->allocated == FALSE )
{
return;
}
workspace->allocated = 0;
/* communication storage */
for ( i = 0; i < MAX_NBRS; ++i )
{
sfree( workspace->tmp_dbl[i], "tmp_dbl[i]" );
sfree( workspace->tmp_rvec[i], "tmp_rvec[i]" );
sfree( workspace->tmp_rvec2[i], "tmp_rvec2[i]" );
}
/* bond order storage */
sfree( workspace->within_bond_box, "skin" );
sfree( workspace->total_bond_order, "total_bo" );
sfree( workspace->Deltap, "Deltap" );
sfree( workspace->Deltap_boc, "Deltap_boc" );
sfree( workspace->dDeltap_self, "dDeltap_self" );
sfree( workspace->Delta, "Delta" );
sfree( workspace->Delta_lp, "Delta_lp" );
sfree( workspace->Delta_lp_temp, "Delta_lp_temp" );
sfree( workspace->dDelta_lp, "dDelta_lp" );
sfree( workspace->dDelta_lp_temp, "dDelta_lp_temp" );
sfree( workspace->Delta_e, "Delta_e" );
sfree( workspace->Delta_boc, "Delta_boc" );
sfree( workspace->nlp, "nlp" );
sfree( workspace->nlp_temp, "nlp_temp" );
sfree( workspace->Clp, "Clp" );
sfree( workspace->vlpex, "vlpex" );
sfree( workspace->bond_mark, "bond_mark" );
sfree( workspace->done_after, "done_after" );
/* QEq storage */
sfree( workspace->Hdia_inv, "Hdia_inv" );
sfree( workspace->b_s, "b_s" );
sfree( workspace->b_t, "b_t" );
sfree( workspace->b_prc, "b_prc" );
sfree( workspace->b_prm, "b_prm" );
sfree( workspace->s, "s" );
sfree( workspace->t, "t" );
sfree( workspace->droptol, "droptol" );
sfree( workspace->b, "b" );
sfree( workspace->x, "x" );
/* GMRES storage */
//SUDHIR
/*
for( i = 0; i < RESTART+1; ++i ) {
sfree( workspace->h[i], "h[i]" );
sfree( workspace->v[i], "v[i]" );
}
*/
sfree( workspace->h, "h" );
sfree( workspace->v, "v" );
sfree( workspace->y, "y" );
sfree( workspace->z, "z" );
sfree( workspace->g, "g" );
sfree( workspace->hs, "hs" );
sfree( workspace->hc, "hc" );
/* CG storage */
sfree( workspace->r, "r" );
sfree( workspace->d, "d" );
sfree( workspace->q, "q" );
sfree( workspace->p, "p" );
sfree( workspace->r2, "r2" );
sfree( workspace->d2, "d2" );
sfree( workspace->q2, "q2" );
sfree( workspace->p2, "p2" );
/* integrator */
// sfree( workspace->f_old );
sfree( workspace->v_const, "v_const" );
/*workspace->realloc.far_nbrs = -1;
workspace->realloc.Htop = -1;
workspace->realloc.hbonds = -1;
workspace->realloc.bonds = -1;
workspace->realloc.num_3body = -1;
workspace->realloc.gcell_atoms = -1;*/
/* storage for analysis */
if ( control->molecular_analysis || control->diffusion_coef )
{
sfree( workspace->mark, "mark" );
sfree( workspace->old_mark, "old_mark" );
}
if ( control->diffusion_coef )
{
sfree( workspace->x_old, "x_old" );
}
/* force related storage */
sfree( workspace->f, "f" );
sfree( workspace->CdDelta, "CdDelta" );
#ifdef TEST_FORCES
sfree(workspace->dDelta, "dDelta" );
sfree( workspace->f_ele, "f_ele" );
sfree( workspace->f_vdw, "f_vdw" );
sfree( workspace->f_bo, "f_bo" );
sfree( workspace->f_be, "f_be" );
sfree( workspace->f_lp, "f_lp" );
sfree( workspace->f_ov, "f_ov" );
sfree( workspace->f_un, "f_un" );
sfree( workspace->f_ang, "f_ang" );
sfree( workspace->f_coa, "f_coa" );
sfree( workspace->f_pen, "f_pen" );
sfree( workspace->f_hb, "f_hb" );
sfree( workspace->f_tor, "f_tor" );
sfree( workspace->f_con, "f_con" );
sfree( workspace->f_tot, "f_tot" );
sfree( workspace->rcounts, "rcounts" );
sfree( workspace->displs, "displs" );
sfree( workspace->id_all, "id_all" );
sfree( workspace->f_all, "f_all" );
#endif
}
void Allocate_Workspace( reax_system *system, control_params *control,
storage *workspace, int local_cap, int total_cap, char *msg )
{
int i, total_real, total_rvec, local_rvec;
workspace->allocated = 1;
total_real = total_cap * sizeof(real);
total_rvec = total_cap * sizeof(rvec);
local_rvec = local_cap * sizeof(rvec);
/* communication storage */
for ( i = 0; i < MAX_NBRS; ++i )
{
workspace->tmp_dbl[i] = (real*)scalloc(total_cap, sizeof(real), "tmp_dbl");
workspace->tmp_rvec[i] = (rvec*)scalloc(total_cap, sizeof(rvec), "tmp_rvec");
workspace->tmp_rvec2[i] =
(rvec2*)scalloc(total_cap, sizeof(rvec2), "tmp_rvec2");
}
/* bond order related storage */
workspace->within_bond_box = (int*) scalloc(total_cap, sizeof(int), "skin");
workspace->total_bond_order = (real*) smalloc( total_real, "total_bo" );
workspace->Deltap = (real*) smalloc( total_real, "Deltap" );
workspace->Deltap_boc = (real*) smalloc( total_real, "Deltap_boc" );
workspace->dDeltap_self = (rvec*) smalloc( total_rvec, "dDeltap_self" );
workspace->Delta = (real*) smalloc( total_real, "Delta" );
workspace->Delta_lp = (real*) smalloc( total_real, "Delta_lp" );
workspace->Delta_lp_temp = (real*) smalloc( total_real, "Delta_lp_temp" );
workspace->dDelta_lp = (real*) smalloc( total_real, "dDelta_lp" );
workspace->dDelta_lp_temp = (real*) smalloc( total_real, "dDelta_lp_temp" );
workspace->Delta_e = (real*) smalloc( total_real, "Delta_e" );
workspace->Delta_boc = (real*) smalloc( total_real, "Delta_boc" );
workspace->nlp = (real*) smalloc( total_real, "nlp" );
workspace->nlp_temp = (real*) smalloc( total_real, "nlp_temp" );
workspace->Clp = (real*) smalloc( total_real, "Clp" );
workspace->vlpex = (real*) smalloc( total_real, "vlpex" );
workspace->bond_mark = (int*) scalloc(total_cap, sizeof(int), "bond_mark");
workspace->done_after = (int*) scalloc(total_cap, sizeof(int), "done_after");
/* QEq storage */
workspace->Hdia_inv = (real*) scalloc( total_cap, sizeof(real), "Hdia_inv" );
workspace->b_s = (real*) scalloc( total_cap, sizeof(real), "b_s" );
workspace->b_t = (real*) scalloc( total_cap, sizeof(real), "b_t" );
workspace->b_prc = (real*) scalloc( total_cap, sizeof(real), "b_prc" );
workspace->b_prm = (real*) scalloc( total_cap, sizeof(real), "b_prm" );
workspace->s = (real*) scalloc( total_cap, sizeof(real), "s" );
workspace->t = (real*) scalloc( total_cap, sizeof(real), "t" );
workspace->droptol = (real*) scalloc( total_cap, sizeof(real), "droptol" );
workspace->b = (rvec2*) scalloc( total_cap, sizeof(rvec2), "b" );
workspace->x = (rvec2*) scalloc( total_cap, sizeof(rvec2), "x" );
/* GMRES storage */
workspace->y = (real*) scalloc( RESTART + 1, sizeof(real), "y" );
workspace->z = (real*) scalloc( RESTART + 1, sizeof(real), "z" );
workspace->g = (real*) scalloc( RESTART + 1, sizeof(real), "g" );
//SUHDIR
//workspace->h = (real**) scalloc( RESTART+1, sizeof(real*), "h" );
workspace->h = (real *) scalloc ( (RESTART + 1) * (RESTART + 1), sizeof (real), "h");
workspace->hs = (real*) scalloc( RESTART + 1, sizeof(real), "hs" );
workspace->hc = (real*) scalloc( RESTART + 1, sizeof(real), "hc" );
//SUDHIR
//workspace->v = (real**) scalloc( RESTART+1, sizeof(real*), "v" );
workspace->v = (real *) scalloc ( (RESTART + 1) * (RESTART + 1), sizeof (real), "v");
/*
for( i = 0; i < RESTART+1; ++i ) {
workspace->h[i] = (real*) scalloc( RESTART+1, sizeof(real), "h[i]" );
workspace->v[i] = (real*) scalloc( total_cap, sizeof(real), "v[i]" );
}
*/
/* CG storage */
workspace->r = (real*) scalloc( total_cap, sizeof(real), "r" );
workspace->d = (real*) scalloc( total_cap, sizeof(real), "d" );
workspace->q = (real*) scalloc( total_cap, sizeof(real), "q" );
workspace->p = (real*) scalloc( total_cap, sizeof(real), "p" );
workspace->r2 = (rvec2*) scalloc( total_cap, sizeof(rvec2), "r2" );
workspace->d2 = (rvec2*) scalloc( total_cap, sizeof(rvec2), "d2" );
workspace->q2 = (rvec2*) scalloc( total_cap, sizeof(rvec2), "q2" );
workspace->p2 = (rvec2*) scalloc( total_cap, sizeof(rvec2), "p2" );
/* integrator storage */
workspace->v_const = (rvec*) smalloc( local_rvec, "v_const" );
/* storage for analysis */
if ( control->molecular_analysis || control->diffusion_coef )
{
workspace->mark = (int*) scalloc( local_cap, sizeof(int), "mark" );
workspace->old_mark = (int*) scalloc( local_cap, sizeof(int), "old_mark" );
}
else
{
workspace->mark = workspace->old_mark = NULL;
}
if ( control->diffusion_coef )
{
workspace->x_old = (rvec*) scalloc( local_cap, sizeof(rvec), "x_old" );
}
else
{
workspace->x_old = NULL;
}
/* force related storage */
workspace->f = (rvec*) scalloc( total_cap, sizeof(rvec), "f" );
workspace->CdDelta = (real*) scalloc( total_cap, sizeof(real), "CdDelta" );
#ifdef TEST_FORCES
workspace->dDelta = (rvec*) smalloc( total_rvec, "dDelta" );
workspace->f_ele = (rvec*) smalloc( total_rvec, "f_ele" );
workspace->f_vdw = (rvec*) smalloc( total_rvec, "f_vdw" );
workspace->f_bo = (rvec*) smalloc( total_rvec, "f_bo" );
workspace->f_be = (rvec*) smalloc( total_rvec, "f_be" );
workspace->f_lp = (rvec*) smalloc( total_rvec, "f_lp" );
workspace->f_ov = (rvec*) smalloc( total_rvec, "f_ov" );
workspace->f_un = (rvec*) smalloc( total_rvec, "f_un" );
workspace->f_ang = (rvec*) smalloc( total_rvec, "f_ang" );
workspace->f_coa = (rvec*) smalloc( total_rvec, "f_coa" );
workspace->f_pen = (rvec*) smalloc( total_rvec, "f_pen" );
workspace->f_hb = (rvec*) smalloc( total_rvec, "f_hb" );
workspace->f_tor = (rvec*) smalloc( total_rvec, "f_tor" );
workspace->f_con = (rvec*) smalloc( total_rvec, "f_con" );
workspace->f_tot = (rvec*) smalloc( total_rvec, "f_tot" );
if ( system->my_rank == MASTER_NODE )
{
workspace->rcounts = (int*) smalloc(system->nprocs * sizeof(int), "rcount");
workspace->displs = (int*) smalloc(system->nprocs * sizeof(int), "displs");
workspace->id_all = (int*) smalloc(system->bigN * sizeof(int), "id_all");
workspace->f_all = (rvec*) smalloc(system->bigN * sizeof(rvec), "f_all");
}
else
{
workspace->rcounts = NULL;
workspace->displs = NULL;
workspace->id_all = NULL;
workspace->f_all = NULL;
}
#endif
}
void Reallocate_Neighbor_List( reax_list *far_nbrs, int n, int num_intrs )
{
Delete_List( far_nbrs );
Make_List( n, num_intrs, TYP_FAR_NEIGHBOR, far_nbrs );
}
void Allocate_Matrix( sparse_matrix *H, int n, int m )
{
H->n = n;
H->m = m;
H->start = (int*) smalloc( sizeof(int) * n, "Allocate_Matrix::start" );
H->end = (int*) smalloc( sizeof(int) * n, "Allocate_Matrix::end" );
H->entries = (sparse_matrix_entry*)
smalloc( sizeof(sparse_matrix_entry) * m, "Allocate_Matrix::entries" );
}
void Deallocate_Matrix( sparse_matrix *H )
{
sfree( H->start, "Deallocate_Matrix::start" );
sfree( H->end, "Deallocate_Matrix::end" );
sfree( H->entries, "Deallocate_Matrix::entries" );
sfree( H, "Deallocate_Matrix::matrix" );
}
static void Reallocate_Matrix( sparse_matrix *H, int n, int m, char *name )
{
Deallocate_Matrix( H );
Allocate_Matrix( H, n, m );
#if defined(DEBUG_FOCUS)
fprintf( stderr, "reallocating %s matrix, n = %d, m = %d\n", name, n, m );
fprintf( stderr, "memory allocated: %s = %dMB\n",
name, (int)(m * sizeof(sparse_matrix_entry) / (1024 * 1024)) );
#endif
}
void Reallocate_HBonds_List( reax_system *system, reax_list *hbonds )
{
int i, id, total_hbonds;
total_hbonds = 0;
for ( i = 0; i < system->n; ++i )
{
if ( (id = system->my_atoms[i].Hindex) >= 0 )
{
system->my_atoms[i].num_hbonds = MAX( Num_Entries(id, hbonds) * SAFER_ZONE,
MIN_HBONDS );
total_hbonds += system->my_atoms[i].num_hbonds;
}
}
total_hbonds = MAX( total_hbonds * SAFER_ZONE, MIN_CAP * MIN_HBONDS );
Delete_List( hbonds );
Make_List( system->Hcap, total_hbonds, TYP_HBOND, hbonds);
}
void Reallocate_Bonds_List( reax_system *system, reax_list *bonds,
int *total_bonds, int *est_3body )
{
int i;
*total_bonds = 0;
*est_3body = 0;
for ( i = 0; i < system->N; ++i )
{
*est_3body += SQR( Num_Entries( i, bonds ) );
system->my_atoms[i].num_bonds = MAX( Num_Entries(i, bonds) * 2, MIN_BONDS );
*total_bonds += system->my_atoms[i].num_bonds;
}
*total_bonds = MAX( *total_bonds * SAFE_ZONE, MIN_CAP * MIN_BONDS );
Delete_List( bonds );
Make_List( system->total_cap, *total_bonds, TYP_BOND, bonds );
}
/************* grid *************/
int Estimate_GCell_Population( reax_system* system, MPI_Comm comm )
{
int d, i, j, k, l, max_atoms, my_max, all_max;
ivec c;
grid *g;
grid_cell *gc;
simulation_box *my_ext_box;
reax_atom *atoms;
my_ext_box = &(system->my_ext_box);
g = &(system->my_grid);
atoms = system->my_atoms;
Reset_Grid( g );
for ( l = 0; l < system->n; l++ )
{
for ( d = 0; d < 3; ++d )
{
c[d] = (int)((atoms[l].x[d] - my_ext_box->min[d]) * g->inv_len[d]);
if ( c[d] >= g->native_end[d] )
{
c[d] = g->native_end[d] - 1;
}
else if ( c[d] < g->native_str[d] )
{
c[d] = g->native_str[d];
}
}
#if defined(DEBUG)
fprintf( stderr, "p%d bin_my_atoms: l:%d - atom%d @ %.5f %.5f %.5f" \
"--> cell: %d %d %d\n",
system->my_rank, l, atoms[l].orig_id,
atoms[l].x[0], atoms[l].x[1], atoms[l].x[2],
c[0], c[1], c[2] );
#endif
gc = &( g->cells[ index_grid_3d(c[0], c[1], c[2], g) ] );
gc->top++;
}
max_atoms = 0;
for ( i = 0; i < g->ncells[0]; i++ )
{
for ( j = 0; j < g->ncells[1]; j++ )
{
for ( k = 0; k < g->ncells[2]; k++ )
{
gc = &(g->cells[ index_grid_3d(i, j, k, g) ]);
if ( max_atoms < gc->top )
{
max_atoms = gc->top;
}
#if defined(DEBUG)
fprintf( stderr, "p%d gc[%d,%d,%d]->top=%d\n",
system->my_rank, i, j, k, gc->top );
#endif
}
}
}
my_max = MAX( max_atoms * SAFE_ZONE, MIN_GCELL_POPL );
MPI_Allreduce( &my_max, &all_max, 1, MPI_INT, MPI_MAX, comm );
#if defined(DEBUG)
fprintf( stderr, "p%d max_atoms=%d, my_max=%d, all_max=%d\n",
system->my_rank, max_atoms, my_max, all_max );
#endif
return all_max;
}
void Allocate_Grid( reax_system *system, MPI_Comm comm )
{
int i, j, k;
grid *g;
grid_cell *gc;
int total;
g = &( system->my_grid );
total = g->ncells[0] * g->ncells[1] * g->ncells[2];
/* allocate gcell reordering space */
g->order = (ivec*) scalloc( g->total + 1, sizeof(ivec), "g:order" );
/* allocate the gcells for the new grid */
g->max_nbrs = (2 * g->vlist_span[0] + 1) * (2 * g->vlist_span[1] + 1) *
(2 * g->vlist_span[2] + 1) + 3;
g->cells = (grid_cell *) scalloc( total, sizeof(grid_cell), "g:gcell" );
for (i = 0; i < total; i++)
{
gc = &( g->cells[ i ] );
gc->top = 0;
gc->mark = 0;
}
g->str = (int *) scalloc( total, sizeof(int), "grid:str" );
g->end = (int *) scalloc( total, sizeof(int), "grid:end" );
g->cutoff = (real *) scalloc( total, sizeof(real), "grid:cutoff" );
g->nbrs_x = (ivec *) scalloc( total * g->max_nbrs, sizeof(ivec), "grid:nbrs_x" );
g->nbrs_cp = (rvec *) scalloc( total * g->max_nbrs, sizeof(rvec), "grid:nbrs_cp" );
for ( i = 0; i < total * g->max_nbrs; i++ )
{
g->nbrs_x[i][0] = -1;
g->nbrs_x[i][1] = -1;
g->nbrs_x[i][2] = -1;
}
g->rel_box = (ivec *) scalloc( total, sizeof (ivec), "grid:rel_box" );
/* allocate atom id storage in gcells */
g->max_atoms = Estimate_GCell_Population( system, comm );
/* space for storing atom id's is required only for native cells */
for ( i = g->native_str[0]; i < g->native_end[0]; ++i )
{
for ( j = g->native_str[1]; j < g->native_end[1]; ++j )
{
for ( k = g->native_str[2]; k < g->native_end[2]; ++k )
{
g->cells[ index_grid_3d(i, j, k, g) ].atoms =
(int*) scalloc( g->max_atoms, sizeof(int), "g:atoms" );
}
}
}
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d-allocated %dx%dx%d grid: nbrs=%d atoms=%d space=%dMB\n",
system->my_rank, g->ncells[0], g->ncells[1], g->ncells[2],
g->max_nbrs, g->max_atoms,
(int)
((g->total * sizeof(grid_cell) + g->total * g->max_nbrs * sizeof(int*) +
g->total * g->max_nbrs * sizeof(rvec) +
(g->native_end[0] - g->native_str[0]) *
(g->native_end[1] - g->native_str[1]) *
(g->native_end[2] - g->native_str[2])*g->max_atoms * sizeof(int)) /
(1024 * 1024)) );
#endif
}
void Deallocate_Grid( grid *g )
{
int i, j, k;
grid_cell *gc;
sfree( g->order, "g:order" );
sfree( g->str, "g:str" );
sfree( g->end, "g:end" );
sfree( g->nbrs_x, "g:nbrs_x" );
sfree( g->nbrs_cp, "g:nbrs_cp" );
sfree( g->cutoff, "g:cutoff" );
/* deallocate the grid cells */
for ( i = 0; i < g->ncells[0]; i++ )
{
for ( j = 0; j < g->ncells[1]; j++ )
{
for ( k = 0; k < g->ncells[2]; k++ )
{
gc = &(g->cells[ index_grid_3d(i, j, k, g)] );
if ( gc->atoms != NULL )
{
sfree( gc->atoms, "g:atoms" );
}
}
}
}
sfree( g->cells, "g:cells" );
}
/************ mpi buffers ********************/
/* make the allocations based on the largest need by the three comms:
1- transfer an atom who has moved into other proc's domain (mpi_atom)
2- exchange boundary atoms (boundary_atom)
3- update position info for boundary atoms (mpi_rvec)
the largest space by far is required for the 2nd comm operation above.
buffers are void*, type cast to the correct pointer type to access
the allocated buffers */
void Allocate_MPI_Buffers( mpi_datatypes *mpi_data, int est_recv,
neighbor_proc *my_nbrs, char *msg )
{
int i;
mpi_out_data *mpi_buf;
/* in buffers */
mpi_data->in1_buffer = (void*)
scalloc( est_recv, sizeof(boundary_atom), "in1_buffer" );
mpi_data->in2_buffer = (void*)
scalloc( est_recv, sizeof(boundary_atom), "in2_buffer" );
/* out buffers */
for ( i = 0; i < MAX_NBRS; ++i )
{
mpi_buf = &( mpi_data->out_buffers[i] );
/* allocate storage for the neighbor processor i */
mpi_buf->index = (int*)
scalloc( my_nbrs[i].est_send, sizeof(int), "mpibuf:index" );
mpi_buf->out_atoms = (void*)
scalloc( my_nbrs[i].est_send, sizeof(boundary_atom), "mpibuf:out_atoms" );
}
}
void Deallocate_MPI_Buffers( mpi_datatypes *mpi_data )
{
int i;
mpi_out_data *mpi_buf;
sfree( mpi_data->in1_buffer, "in1_buffer" );
sfree( mpi_data->in2_buffer, "in2_buffer" );
for ( i = 0; i < MAX_NBRS; ++i )
{
mpi_buf = &( mpi_data->out_buffers[i] );
sfree( mpi_buf->index, "mpibuf:index" );
sfree( mpi_buf->out_atoms, "mpibuf:out_atoms" );
}
}
void ReAllocate( reax_system *system, control_params *control,
simulation_data *data, storage *workspace, reax_list **lists,
mpi_datatypes *mpi_data )
{
int i, j, k, p;
int num_bonds, est_3body, nflag, Nflag, Hflag, mpi_flag, total_send;
int renbr;
reallocate_data *realloc;
reax_list *far_nbrs;
sparse_matrix *H;
grid *g;
neighbor_proc *nbr_pr;
mpi_out_data *nbr_data;
char msg[200];
realloc = &(workspace->realloc);
g = &(system->my_grid);
H = &workspace->H;
#if defined(DEBUG)
fprintf( stderr, "p%d@reallocate: n: %d, N: %d, numH: %d\n",
system->my_rank, system->n, system->N, system->numH );
fprintf( stderr, "p%d@reallocate: local_cap: %d, total_cap: %d, Hcap: %d\n",
system->my_rank, system->local_cap, system->total_cap,
system->Hcap);
fprintf( stderr, "p%d: realloc.far_nbrs: %d\n",
system->my_rank, realloc->far_nbrs );
fprintf( stderr, "p%d: realloc.H: %d, realloc.Htop: %d\n",
system->my_rank, realloc->H, realloc->Htop );
fprintf( stderr, "p%d: realloc.Hbonds: %d, realloc.num_hbonds: %d\n",
system->my_rank, realloc->hbonds, realloc->num_hbonds );
fprintf( stderr, "p%d: realloc.bonds: %d, num_bonds: %d\n",
system->my_rank, realloc->bonds, realloc->num_bonds );
fprintf( stderr, "p%d: realloc.num_3body: %d\n",
system->my_rank, realloc->num_3body );
#endif
// IMPORTANT: LOOSE ZONES CHECKS ARE DISABLED FOR NOW BY &&'ing with 0!!!
nflag = 0;
if ( system->n >= DANGER_ZONE * system->local_cap ||
(0 && system->n <= LOOSE_ZONE * system->local_cap) )
{
nflag = 1;
system->local_cap = (int)(system->n * SAFE_ZONE);
}
Nflag = 0;
if ( system->N >= DANGER_ZONE * system->total_cap ||
(0 && system->N <= LOOSE_ZONE * system->total_cap) )
{
Nflag = 1;
system->total_cap = (int)(system->N * SAFE_ZONE);
}
if ( Nflag )
{
/* system */
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: reallocating system and workspace -"\
"n=%d N=%d local_cap=%d total_cap=%d\n",
system->my_rank, system->n, system->N,
system->local_cap, system->total_cap );
#endif
Allocate_System( system, system->local_cap, system->total_cap, msg );
/* workspace */
DeAllocate_Workspace( control, workspace );
Allocate_Workspace( system, control, workspace, system->local_cap,
system->total_cap, msg );
}
renbr = (data->step - data->prev_steps) % control->reneighbor == 0;
/* far neighbors */
if ( renbr )
{
far_nbrs = *lists + FAR_NBRS;
if ( Nflag || realloc->far_nbrs >= far_nbrs->num_intrs * DANGER_ZONE )
{
// if ( realloc->far_nbrs > far_nbrs->num_intrs )
// {
// fprintf( stderr, "[ERROR] step%d-ran out of space on far_nbrs: top=%d, max=%d",
// data->step, realloc->far_nbrs, far_nbrs->num_intrs );
// MPI_Abort( MPI_COMM_WORLD, INSUFFICIENT_MEMORY );
// }
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: reallocating far_nbrs: far_nbrs=%d, space=%dMB\n",
system->my_rank, (int)(realloc->far_nbrs * SAFE_ZONE),
(int)(realloc->far_nbrs * SAFE_ZONE * sizeof(far_neighbor_data) /
(1024 * 1024)) );
#endif
Reallocate_Neighbor_List( far_nbrs, system->total_cap, realloc->far_nbrs * SAFE_ZONE );
realloc->far_nbrs = FALSE;
}
}
/* charge coef matrix */
if ( nflag || realloc->Htop >= H->m * DANGER_ZONE )
{
// if ( realloc->Htop > H->m )
// {
// fprintf( stderr,
// "step%d - ran out of space on H matrix: Htop=%d, max = %d",
// data->step, realloc->Htop, H->m );
// MPI_Abort( MPI_COMM_WORLD, INSUFFICIENT_MEMORY );
// }
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: reallocating H matrix: Htop=%d, space=%dMB\n",
system->my_rank, (int)(realloc->Htop * SAFE_ZONE),
(int)(realloc->Htop * SAFE_ZONE * sizeof(sparse_matrix_entry) /
(1024 * 1024)) );
#endif
Reallocate_Matrix( H, system->local_cap,
realloc->Htop * SAFE_ZONE, "H" );
//Deallocate_Matrix( workspace->L );
//Deallocate_Matrix( workspace->U );
//MATRIX-CHANGES
//workspace->L = NULL;
//workspace->U = NULL;
realloc->Htop = 0;
}
/* hydrogen bonds list */
if ( control->hbond_cut > 0.0 )
{
Hflag = 0;
if ( system->numH >= DANGER_ZONE * system->Hcap ||
(0 && system->numH <= LOOSE_ZONE * system->Hcap) )
{
Hflag = 1;
//system->Hcap = (int)(system->numH * SAFE_ZONE);
// Tried fix
system->Hcap = (int)(system->n * SAFE_ZONE);
}
if ( Hflag || realloc->hbonds )
{
Reallocate_HBonds_List( system, (*lists) + HBONDS );
realloc->hbonds = 0;
#if defined(DEBUG_FOCUS)
fprintf(stderr, "p%d: reallocating hbonds: total_hbonds=%d space=%dMB\n",
system->my_rank, ret, (int)(ret * sizeof(hbond_data) / (1024 * 1024)));
#endif
}
}
/* bonds list */
num_bonds = est_3body = -1;
if ( Nflag || realloc->bonds )
{
Reallocate_Bonds_List( system, (*lists) + BONDS, &num_bonds, &est_3body );
realloc->bonds = 0;
realloc->num_3body = MAX( realloc->num_3body, est_3body );
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: reallocating bonds: total_bonds=%d, space=%dMB\n",
system->my_rank, num_bonds,
(int)(num_bonds * sizeof(bond_data) / (1024 * 1024)) );
#endif
}
/* 3-body list */
if ( realloc->num_3body > 0 )
{
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: reallocating 3body list: num_3body=%d, space=%dMB\n",
system->my_rank, realloc->num_3body,
(int)(realloc->num_3body * sizeof(three_body_interaction_data) /
(1024 * 1024)) );
#endif
Delete_List( (*lists) + THREE_BODIES );
if ( num_bonds == -1 )
{
num_bonds = ((*lists) + BONDS)->num_intrs;
}
realloc->num_3body = MAX( realloc->num_3body * SAFE_ZONE, MIN_3BODIES );
Make_List( num_bonds, realloc->num_3body,
TYP_THREE_BODY, (*lists) + THREE_BODIES);
}
/* grid */
if ( renbr && realloc->gcell_atoms > -1 )
{
#if defined(DEBUG_FOCUS)
fprintf( stderr, "reallocating gcell: g->max_atoms: %d\n", g->max_atoms );
#endif
for ( i = g->native_str[0]; i < g->native_end[0]; i++ )
{
for ( j = g->native_str[1]; j < g->native_end[1]; j++ )
{
for ( k = g->native_str[2]; k < g->native_end[2]; k++ )
{
/* reallocate g->atoms */
sfree( g->cells[ index_grid_3d(i, j, k, g) ].atoms, "g:atoms" );
g->cells[ index_grid_3d(i, j, k, g) ].atoms = (int*)
scalloc( realloc->gcell_atoms, sizeof(int), "g:atoms" );
}
}
}
realloc->gcell_atoms = -1;
}
/* mpi buffers */
// we have to be at a renbring step -
// to ensure correct values at mpi_buffers for update_boundary_positions
if ( !renbr )
{
mpi_flag = FALSE;
}
// check whether in_buffer capacity is enough
else if ( system->max_recved >= system->est_recv * 0.90 )
{
mpi_flag = TRUE;
}
else
{
// otherwise check individual outgoing buffers
mpi_flag = FALSE;
for ( p = 0; p < MAX_NBRS; ++p )
{
nbr_pr = &( system->my_nbrs[p] );
nbr_data = &( mpi_data->out_buffers[p] );
if ( nbr_data->cnt >= nbr_pr->est_send * 0.90 )
{
mpi_flag = TRUE;
break;
}
}
}
if ( mpi_flag == TRUE )
{
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: reallocating mpi_buf: old_recv=%d\n",
system->my_rank, system->est_recv );
for ( p = 0; p < MAX_NBRS; ++p )
{
fprintf( stderr, "p%d: nbr%d old_send=%d\n",
system->my_rank, p, system->my_nbrs[p].est_send );
}
#endif
/* update mpi buffer estimates based on last comm */
system->est_recv = MAX( system->max_recved * SAFER_ZONE, MIN_SEND );
system->est_trans =
(system->est_recv * sizeof(boundary_atom)) / sizeof(mpi_atom);
total_send = 0;
for ( p = 0; p < MAX_NBRS; ++p )
{
nbr_pr = &( system->my_nbrs[p] );
nbr_data = &( mpi_data->out_buffers[p] );
nbr_pr->est_send = MAX( nbr_data->cnt * SAFER_ZONE, MIN_SEND );
total_send += nbr_pr->est_send;
}
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d: reallocating mpi_buf: recv=%d send=%d total=%dMB\n",
system->my_rank, system->est_recv, total_send,
(int)((system->est_recv + total_send)*sizeof(boundary_atom) /
(1024 * 1024)));
for ( p = 0; p < MAX_NBRS; ++p )
{
fprintf( stderr, "p%d: nbr%d new_send=%d\n",
system->my_rank, p, system->my_nbrs[p].est_send );
}
#endif
/* reallocate mpi buffers */
Deallocate_MPI_Buffers( mpi_data );
Allocate_MPI_Buffers( mpi_data, system->est_recv, system->my_nbrs, msg );
}
#if defined(DEBUG_FOCUS)
fprintf( stderr, "p%d @ step%d: reallocate done\n",
system->my_rank, data->step );
MPI_Barrier( MPI_COMM_WORLD );
#endif
}