Newer
Older
/*----------------------------------------------------------------------
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
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
See the GNU General Public License for more details:
<http://www.gnu.org/licenses/>.
----------------------------------------------------------------------*/
#include "reax_types.h"
#include "basic_comm.h"
#include "vector.h"
#include "reax_basic_comm.h"
#include "reax_vector.h"
Kurt A. O'Hearn
committed
static void * Get_Buffer_Offset( const void * const buffer,
const int offset, const int type )
{
void * ptr;
switch ( type )
{
case REAL_PTR_TYPE:
ptr = (real *) buffer + offset;
break;
case RVEC_PTR_TYPE:
ptr = (rvec *) buffer + offset;
break;
case RVEC2_PTR_TYPE:
ptr = (rvec2 *) buffer + offset;
break;
default:
fprintf( stderr, "[ERROR] unknown pointer type. Terminating...\n" );
exit( UNKNOWN_OPTION );
break;
}
return ptr;
}
void real_packer( void *dummy, mpi_out_data *out_buf )
{
int i;
real *buf = (real*) dummy;
real *out = (real*) out_buf->out_atoms;
}
void rvec_packer( void *dummy, mpi_out_data *out_buf )
{
rvec *buf, *out;
buf = (rvec*) dummy;
out = (rvec*) out_buf->out_atoms;
memcpy( out + i, buf + out_buf->index[i], sizeof(rvec) );
}
void rvec2_packer( void *dummy, mpi_out_data *out_buf )
{
rvec2 *buf, *out;
buf = (rvec2*) dummy;
out = (rvec2*) out_buf->out_atoms;
memcpy( out + i, buf + out_buf->index[i], sizeof(rvec2) );
void Dist( reax_system* system, mpi_datatypes *mpi_data, void *buf,
Kurt A. O'Hearn
committed
int buf_type, MPI_Datatype type, dist_packer pack )
int d;
mpi_out_data *out_bufs;
MPI_Comm comm;
MPI_Request req1, req2;
MPI_Status stat1, stat2;
neighbor_proc *nbr1, *nbr2;
fprintf( stderr, "p%d dist: entered\n", system->my_rank );
comm = mpi_data->comm_mesh3D;
out_bufs = mpi_data->out_buffers;
for ( d = 0; d < 3; ++d )
{
/* initiate recvs */
Kurt A. O'Hearn
committed
nbr1 = &system->my_nbrs[2 * d];
Kurt A. O'Hearn
committed
MPI_Irecv( Get_Buffer_Offset( buf, nbr1->atoms_str, buf_type ),
nbr1->atoms_cnt, type, nbr1->rank, 2 * d + 1, comm, &req1 );
Kurt A. O'Hearn
committed
nbr2 = &system->my_nbrs[2 * d + 1];
Kurt A. O'Hearn
committed
MPI_Irecv( Get_Buffer_Offset( buf, nbr2->atoms_str, buf_type ),
nbr2->atoms_cnt, type, nbr2->rank, 2 * d, comm, &req2 );
/* send both messages in dimension d */
if ( out_bufs[2 * d].cnt )
{
pack( buf, out_bufs + (2 * d) );
MPI_Send( out_bufs[2 * d].out_atoms, out_bufs[2 * d].cnt, type,
}
if ( out_bufs[2 * d + 1].cnt )
{
pack( buf, out_bufs + (2 * d + 1) );
MPI_Send( out_bufs[2 * d + 1].out_atoms, out_bufs[2 * d + 1].cnt,
type, nbr2->rank, 2 * d + 1, comm );
if( nbr1->atoms_cnt )
{
MPI_Wait( &req1, &stat1 );
}
if( nbr2->atoms_cnt )
{
MPI_Wait( &req2, &stat2 );
}
fprintf( stderr, "p%d dist: done\n", system->my_rank );
#endif
}
void real_unpacker( void *dummy_in, void *dummy_buf, mpi_out_data *out_buf )
{
real *in, *buf;
in = (real*) dummy_in;
buf = (real*) dummy_buf;
}
void rvec_unpacker( void *dummy_in, void *dummy_buf, mpi_out_data *out_buf )
{
rvec *in, *buf;
in = (rvec*) dummy_in;
buf = (rvec*) dummy_buf;
for ( i = 0; i < out_buf->cnt; ++i )
{
rvec_Add( buf[ out_buf->index[i] ], in[i] );
fprintf( stderr, "rvec_unpacker: cnt=%d i =%d index[i]=%d\n",
}
void rvec2_unpacker( void *dummy_in, void *dummy_buf, mpi_out_data *out_buf )
{
rvec2 *in, *buf;
in = (rvec2*) dummy_in;
buf = (rvec2*) dummy_buf;
for ( i = 0; i < out_buf->cnt; ++i )
{
buf[ out_buf->index[i] ][0] += in[i][0];
buf[ out_buf->index[i] ][1] += in[i][1];
}
void Coll( reax_system* system, mpi_datatypes *mpi_data, void *buf,
Kurt A. O'Hearn
committed
int buf_type, MPI_Datatype type, coll_unpacker unpack )
int d;
mpi_out_data *out_bufs;
MPI_Comm comm;
MPI_Request req1, req2;
MPI_Status stat1, stat2;
neighbor_proc *nbr1, *nbr2;
fprintf( stderr, "p%d coll: entered\n", system->my_rank );
comm = mpi_data->comm_mesh3D;
out_bufs = mpi_data->out_buffers;
for ( d = 2; d >= 0; --d )
{
/* initiate recvs */
Kurt A. O'Hearn
committed
nbr1 = &system->my_nbrs[2 * d];
Kurt A. O'Hearn
committed
MPI_Irecv( mpi_data->in1_buffer, out_bufs[2 * d].cnt,
type, nbr1->rank, 2 * d + 1, comm, &req1 );
Kurt A. O'Hearn
committed
nbr2 = &system->my_nbrs[2 * d + 1];
Kurt A. O'Hearn
committed
MPI_Irecv( mpi_data->in2_buffer, out_bufs[2 * d + 1].cnt,
type, nbr2->rank, 2 * d, comm, &req2 );
/* send both messages in dimension d */
if ( nbr1->atoms_cnt )
Kurt A. O'Hearn
committed
MPI_Send( Get_Buffer_Offset( buf, nbr1->atoms_str, buf_type ),
nbr1->atoms_cnt, type, nbr1->rank, 2 * d, comm );
Kurt A. O'Hearn
committed
MPI_Send( Get_Buffer_Offset( buf, nbr2->atoms_str, buf_type ),
nbr2->atoms_cnt, type, nbr2->rank, 2 * d + 1, comm );
fprintf( stderr, "p%d coll[%d] nbr1: str=%d cnt=%d recv=%d\n",
system->my_rank, d, nbr1->atoms_str, nbr1->atoms_cnt,
out_bufs[2 * d].cnt );
fprintf( stderr, "p%d coll[%d] nbr2: str=%d cnt=%d recv=%d\n",
system->my_rank, d, nbr2->atoms_str, nbr2->atoms_cnt,
out_bufs[2 * d + 1].cnt );
if ( out_bufs[2 * d].cnt )
{
MPI_Wait( &req1, &stat1 );
unpack( mpi_data->in1_buffer, buf, &out_bufs[2 * d] );
}
if ( out_bufs[2 * d + 1].cnt )
{
MPI_Wait( &req2, &stat2 );
unpack( mpi_data->in2_buffer, buf, &out_bufs[2 * d + 1] );
fprintf( stderr, "p%d coll: done\n", system->my_rank );
#endif
}
real Parallel_Norm( real *v, int n, MPI_Comm comm )
{
Kurt A. O'Hearn
committed
/* compute local part of vector 2-norm */
MPI_Allreduce( &my_sum, &norm_sqr, 1, MPI_DOUBLE, MPI_SUM, comm );
}
real Parallel_Dot( real *v1, real *v2, int n, MPI_Comm comm )
{
Kurt A. O'Hearn
committed
/* compute local part of inner product */
MPI_Allreduce( &my_dot, &res, 1, MPI_DOUBLE, MPI_SUM, comm );
}
real Parallel_Vector_Acc( real *v, int n, MPI_Comm comm )
{
Kurt A. O'Hearn
committed
/* compute local part of vector element-wise sum */
MPI_Allreduce( &my_acc, &res, 1, MPI_DOUBLE, MPI_SUM, comm );
}
/*****************************************************************************/
#if defined(TEST_FORCES)
void Coll_ids_at_Master( reax_system *system, storage *workspace, mpi_datatypes
*mpi_data )
MPI_Gather( &system->n, 1, MPI_INT, workspace->rcounts, 1, MPI_INT,
if ( system->my_rank == MASTER_NODE )
{
workspace->displs[0] = 0;
for ( i = 1; i < system->nprocs; ++i )
workspace->displs[i] = workspace->displs[i - 1] + workspace->rcounts[i - 1];
Kurt A. O'Hearn
committed
id_list = (int*) smalloc( system->n * sizeof(int), "Coll_ids_at_Master::id_list" );
MPI_Gatherv( id_list, system->n, MPI_INT, workspace->id_all,
workspace->rcounts, workspace->displs, MPI_INT, MASTER_NODE,
MPI_COMM_WORLD );
Kurt A. O'Hearn
committed
sfree( id_list, "Coll_ids_at_Master::id_list" );
if ( system->my_rank == MASTER_NODE )
{
for ( i = 0 ; i < system->bigN; ++i )
fprintf( stderr, "id_all[%d]: %d\n", i, workspace->id_all[i] );
void Coll_rvecs_at_Master( reax_system *system, storage *workspace,
MPI_Gatherv( v, system->n, mpi_data->mpi_rvec, workspace->f_all,
workspace->rcounts, workspace->displs, mpi_data->mpi_rvec,
MASTER_NODE, MPI_COMM_WORLD );