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"
typedef void (*dist_packer)( void*, mpi_out_data* );
typedef void (*coll_unpacker)( void*, void*, mpi_out_data* );
static void int_packer( void *dummy, mpi_out_data *out_buf )
{
int i;
int *buf = (int*) dummy;
int *out = (int*) out_buf->out_atoms;
for ( i = 0; i < out_buf->cnt; ++i )
{
out[i] = buf[ out_buf->index[i] ];
}
}
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
static void real_packer( void *dummy, mpi_out_data *out_buf )
{
int i;
real *buf = (real*) dummy;
real *out = (real*) out_buf->out_atoms;
for ( i = 0; i < out_buf->cnt; ++i )
{
out[i] = buf[ out_buf->index[i] ];
}
}
static void rvec_packer( void *dummy, mpi_out_data *out_buf )
{
int i;
rvec *buf, *out;
buf = (rvec*) dummy;
out = (rvec*) out_buf->out_atoms;
for ( i = 0; i < out_buf->cnt; ++i )
{
memcpy( out + i, buf + out_buf->index[i], sizeof(rvec) );
}
}
static void rvec2_packer( void *dummy, mpi_out_data *out_buf )
{
int i;
rvec2 *buf, *out;
buf = (rvec2*) dummy;
out = (rvec2*) out_buf->out_atoms;
for ( i = 0; i < out_buf->cnt; ++i )
{
memcpy( out + i, buf + out_buf->index[i], sizeof(rvec2) );
}
}
static void int_unpacker( void *dummy_in, void *dummy_buf, mpi_out_data *out_buf )
{
int i;
int *in, *buf;
in = (int*) dummy_in;
buf = (int*) dummy_buf;
for ( i = 0; i < out_buf->cnt; ++i )
{
buf[ out_buf->index[i] ] += in[i];
}
}
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
static void real_unpacker( void *dummy_in, void *dummy_buf, mpi_out_data *out_buf )
{
int i;
real *in, *buf;
in = (real*) dummy_in;
buf = (real*) dummy_buf;
for ( i = 0; i < out_buf->cnt; ++i )
{
buf[ out_buf->index[i] ] += in[i];
}
}
static void rvec_unpacker( void *dummy_in, void *dummy_buf, mpi_out_data *out_buf )
{
int i;
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] );
#if defined(DEBUG)
fprintf( stderr, "rvec_unpacker: cnt=%d i =%d index[i]=%d\n",
out_buf->cnt, i, out_buf->index[i] );
#endif
}
}
static void rvec2_unpacker( void *dummy_in, void *dummy_buf, mpi_out_data *out_buf )
{
int i;
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];
}
}
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 INT_PTR_TYPE:
ptr = (int *) buffer + offset;
break;
Kurt A. O'Hearn
committed
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;
}
static dist_packer Get_Packer( const int type )
dist_packer ptr;
switch ( type )
case REAL_PTR_TYPE:
ptr = real_packer;
break;
case RVEC_PTR_TYPE:
ptr = rvec_packer;
break;
case RVEC2_PTR_TYPE:
ptr = rvec2_packer;
break;
default:
fprintf( stderr, "[ERROR] unknown pointer type. Terminating...\n" );
exit( UNKNOWN_OPTION );
break;
return ptr;
static coll_unpacker Get_Unpacker( const int type )
coll_unpacker ptr;
switch ( type )
case REAL_PTR_TYPE:
ptr = real_unpacker;
break;
case RVEC_PTR_TYPE:
ptr = rvec_unpacker;
break;
case RVEC2_PTR_TYPE:
ptr = rvec2_unpacker;
break;
default:
fprintf( stderr, "[ERROR] unknown pointer type. Terminating...\n" );
exit( UNKNOWN_OPTION );
break;
return ptr;
void Dist( const reax_system * const system, const mpi_datatypes * const mpi_data,
void *buf, int buf_type, MPI_Datatype type )
int d;
mpi_out_data *out_bufs;
MPI_Comm comm;
MPI_Request req1, req2;
MPI_Status stat1, stat2;
neighbor_proc *nbr1, *nbr2;
dist_packer pack;
fprintf( stderr, "p%d dist: entered\n", system->my_rank );
comm = mpi_data->comm_mesh3D;
out_bufs = mpi_data->out_buffers;
pack = Get_Packer( buf_type );
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 );
void Coll( const reax_system const* system, const mpi_datatypes * const mpi_data,
void *buf, int buf_type, MPI_Datatype type )
int d;
mpi_out_data *out_bufs;
MPI_Comm comm;
MPI_Request req1, req2;
MPI_Status stat1, stat2;
neighbor_proc *nbr1, *nbr2;
coll_unpacker unpack;
fprintf( stderr, "p%d coll: entered\n", system->my_rank );
comm = mpi_data->comm_mesh3D;
out_bufs = mpi_data->out_buffers;
unpack = Get_Unpacker( buf_type );
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 );
real Parallel_Norm( const real * const v, const 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( const real * const v1, const real * const v2,
const 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( const real * const v, const 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 );