2020-08-11 16:34:22 +02:00
/*
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
2020-08-19 10:47:40 +02:00
* Author : Jan Eitzinger ( je ) , jan . eitzinger @ fau . de
* Copyright ( c ) 2020 RRZE , University Erlangen - Nuremberg
2020-08-11 16:34:22 +02:00
*
2020-08-19 10:47:40 +02:00
* This file is part of MD - Bench .
2020-08-11 16:34:22 +02:00
*
2020-08-19 10:47:40 +02:00
* MD - Bench is free software : you can redistribute it and / or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
2020-08-11 16:34:22 +02:00
*
2020-08-19 10:47:40 +02:00
* MD - Bench 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 Lesser General Public License for more
* details .
2020-08-11 16:34:22 +02:00
*
2020-08-19 10:47:40 +02:00
* You should have received a copy of the GNU Lesser General Public License along
* with MD - Bench . If not , see < https : //www.gnu.org/licenses/>.
2020-08-11 16:34:22 +02:00
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
2021-12-25 13:52:33 +01:00
# include <stdbool.h>
2020-08-11 16:34:22 +02:00
# include <unistd.h>
# include <limits.h>
# include <math.h>
# include <float.h>
2020-11-05 12:41:44 +01:00
# include <likwid-marker.h>
2020-08-19 09:00:35 +02:00
# include <timing.h>
2020-08-18 14:27:28 +02:00
# include <allocate.h>
# include <neighbor.h>
# include <parameter.h>
# include <atom.h>
2021-10-12 15:04:08 +02:00
# include <stats.h>
2020-08-18 14:27:28 +02:00
# include <thermo.h>
# include <pbc.h>
2021-10-12 22:39:54 +02:00
# include <timers.h>
2021-10-26 00:40:39 +02:00
# include <eam.h>
2021-10-29 16:52:19 +02:00
# include <vtk.h>
2020-08-18 14:27:28 +02:00
2020-08-11 16:34:22 +02:00
# define HLINE "----------------------------------------------------------------------------\n"
2022-06-26 16:25:59 +02:00
extern void cuda_final_integrate ( bool doReneighbour , Parameter * param ,
Atom * atom , Atom * c_atom ,
const int num_threads_per_block ) ;
extern void cuda_initial_integrate ( bool doReneighbour , Parameter * param ,
Atom * atom , Atom * c_atom ,
const int num_threads_per_block ) ;
extern double computeForce ( bool , Parameter * , Atom * , Neighbor * , Atom * , Neighbor * , const int ) ;
2021-10-26 09:11:17 +02:00
extern double computeForceTracing ( Parameter * , Atom * , Neighbor * , Stats * , int , int ) ;
2021-11-03 00:57:24 +01:00
extern double computeForceEam ( Eam * eam , Parameter * , Atom * atom , Neighbor * neighbor , Stats * stats , int first_exec , int timestep ) ;
2020-08-14 08:32:36 +02:00
2020-08-19 09:00:35 +02:00
void init ( Parameter * param )
{
2021-10-26 00:40:39 +02:00
param - > input_file = NULL ;
2021-10-29 16:52:19 +02:00
param - > vtk_file = NULL ;
2021-10-26 00:40:39 +02:00
param - > force_field = FF_LJ ;
2020-08-11 16:34:22 +02:00
param - > epsilon = 1.0 ;
param - > sigma6 = 1.0 ;
param - > rho = 0.8442 ;
2021-05-19 23:51:02 +02:00
param - > ntypes = 4 ;
2020-08-11 16:34:22 +02:00
param - > ntimes = 200 ;
param - > dt = 0.005 ;
param - > nx = 32 ;
param - > ny = 32 ;
param - > nz = 32 ;
param - > cutforce = 2.5 ;
2020-08-18 14:27:28 +02:00
param - > cutneigh = param - > cutforce + 0.30 ;
2020-08-11 16:34:22 +02:00
param - > temp = 1.44 ;
param - > nstat = 100 ;
param - > mass = 1.0 ;
param - > dtforce = 0.5 * param - > dt ;
2020-08-18 14:27:28 +02:00
param - > every = 20 ;
2021-10-12 15:04:08 +02:00
param - > proc_freq = 2.4 ;
2020-08-14 08:32:36 +02:00
}
2022-06-23 18:54:56 +02:00
void initCudaAtom ( Atom * atom , Neighbor * neighbor , Atom * c_atom , Neighbor * c_neighbor ) {
2022-07-03 19:53:33 +02:00
c_atom - > Natoms = atom - > Natoms ;
c_atom - > Nlocal = atom - > Nlocal ;
c_atom - > Nghost = atom - > Nghost ;
c_atom - > Nmax = atom - > Nmax ;
c_atom - > ntypes = atom - > ntypes ;
c_atom - > border_map = NULL ;
2022-06-23 18:54:56 +02:00
const int Nlocal = atom - > Nlocal ;
2022-06-23 19:39:36 +02:00
checkCUDAError ( " c_atom->x malloc " , cudaMalloc ( ( void * * ) & ( c_atom - > x ) , sizeof ( MD_FLOAT ) * atom - > Nmax * 3 ) ) ;
checkCUDAError ( " c_atom->x memcpy " , cudaMemcpy ( c_atom - > x , atom - > x , sizeof ( MD_FLOAT ) * atom - > Nmax * 3 , cudaMemcpyHostToDevice ) ) ;
2022-06-23 18:54:56 +02:00
2022-06-23 19:39:36 +02:00
checkCUDAError ( " c_atom->fx malloc " , cudaMalloc ( ( void * * ) & ( c_atom - > fx ) , sizeof ( MD_FLOAT ) * Nlocal * 3 ) ) ;
2022-06-23 18:54:56 +02:00
2022-06-23 19:39:36 +02:00
checkCUDAError ( " c_atom->vx malloc " , cudaMalloc ( ( void * * ) & ( c_atom - > vx ) , sizeof ( MD_FLOAT ) * Nlocal * 3 ) ) ;
checkCUDAError ( " c_atom->vx memcpy " , cudaMemcpy ( c_atom - > vx , atom - > vx , sizeof ( MD_FLOAT ) * Nlocal * 3 , cudaMemcpyHostToDevice ) ) ;
2022-06-23 18:54:56 +02:00
2022-06-23 19:39:36 +02:00
checkCUDAError ( " c_atom->type malloc " , cudaMalloc ( ( void * * ) & ( c_atom - > type ) , sizeof ( int ) * atom - > Nmax ) ) ;
checkCUDAError ( " c_atom->epsilon malloc " , cudaMalloc ( ( void * * ) & ( c_atom - > epsilon ) , sizeof ( MD_FLOAT ) * atom - > ntypes * atom - > ntypes ) ) ;
checkCUDAError ( " c_atom->sigma6 malloc " , cudaMalloc ( ( void * * ) & ( c_atom - > sigma6 ) , sizeof ( MD_FLOAT ) * atom - > ntypes * atom - > ntypes ) ) ;
checkCUDAError ( " c_atom->cutforcesq malloc " , cudaMalloc ( ( void * * ) & ( c_atom - > cutforcesq ) , sizeof ( MD_FLOAT ) * atom - > ntypes * atom - > ntypes ) ) ;
2022-06-23 18:54:56 +02:00
checkCUDAError ( " c_neighbor->neighbors malloc " , cudaMalloc ( ( void * * ) & c_neighbor - > neighbors , sizeof ( int ) * Nlocal * neighbor - > maxneighs ) ) ;
checkCUDAError ( " c_neighbor->numneigh malloc " , cudaMalloc ( ( void * * ) & c_neighbor - > numneigh , sizeof ( int ) * Nlocal ) ) ;
2022-06-23 19:39:36 +02:00
checkCUDAError ( " c_atom->type memcpy " , cudaMemcpy ( c_atom - > type , atom - > type , sizeof ( int ) * atom - > Nmax , cudaMemcpyHostToDevice ) ) ;
checkCUDAError ( " c_atom->sigma6 memcpy " , cudaMemcpy ( c_atom - > sigma6 , atom - > sigma6 , sizeof ( MD_FLOAT ) * atom - > ntypes * atom - > ntypes , cudaMemcpyHostToDevice ) ) ;
checkCUDAError ( " c_atom->epsilon memcpy " , cudaMemcpy ( c_atom - > epsilon , atom - > epsilon , sizeof ( MD_FLOAT ) * atom - > ntypes * atom - > ntypes , cudaMemcpyHostToDevice ) ) ;
2022-06-23 18:54:56 +02:00
2022-06-23 19:39:36 +02:00
checkCUDAError ( " c_atom->cutforcesq memcpy " , cudaMemcpy ( c_atom - > cutforcesq , atom - > cutforcesq , sizeof ( MD_FLOAT ) * atom - > ntypes * atom - > ntypes , cudaMemcpyHostToDevice ) ) ;
2022-06-23 18:54:56 +02:00
}
2020-08-19 09:22:43 +02:00
double setup (
Parameter * param ,
2021-10-26 00:40:39 +02:00
Eam * eam ,
2020-08-19 09:22:43 +02:00
Atom * atom ,
2021-10-12 15:04:08 +02:00
Neighbor * neighbor ,
2022-06-23 18:54:56 +02:00
Atom * c_atom ,
Neighbor * c_neighbor ,
2022-06-26 16:25:59 +02:00
Stats * stats ,
2022-07-19 20:38:11 +02:00
const int num_threads_per_block ,
double * timers )
2020-08-19 09:22:43 +02:00
{
2021-10-29 16:52:19 +02:00
if ( param - > force_field = = FF_EAM ) { initEam ( eam , param ) ; }
2020-08-19 09:22:43 +02:00
double S , E ;
2021-03-30 01:54:56 +02:00
param - > lattice = pow ( ( 4.0 / param - > rho ) , ( 1.0 / 3.0 ) ) ;
param - > xprd = param - > nx * param - > lattice ;
param - > yprd = param - > ny * param - > lattice ;
param - > zprd = param - > nz * param - > lattice ;
2020-08-19 09:22:43 +02:00
S = getTimeStamp ( ) ;
2020-08-19 09:00:35 +02:00
initAtom ( atom ) ;
initNeighbor ( neighbor , param ) ;
2021-11-03 00:57:24 +01:00
initPbc ( atom ) ;
2021-10-12 15:04:08 +02:00
initStats ( stats ) ;
2020-08-19 09:00:35 +02:00
setupNeighbor ( ) ;
createAtom ( atom , param ) ;
setupThermo ( param , atom - > Natoms ) ;
adjustThermo ( param , atom ) ;
setupPbc ( atom , param ) ;
2022-06-26 18:37:09 +02:00
initCudaAtom ( atom , neighbor , c_atom , c_neighbor ) ;
2022-07-03 19:53:33 +02:00
updatePbc_cuda ( atom , param , c_atom , true , num_threads_per_block ) ;
2022-07-19 20:38:11 +02:00
buildNeighbor_cuda ( atom , neighbor , c_atom , c_neighbor , num_threads_per_block , timers ) ;
2020-08-19 09:22:43 +02:00
E = getTimeStamp ( ) ;
2022-01-01 18:18:12 +01:00
2020-08-19 09:22:43 +02:00
return E - S ;
}
double reneighbour (
Parameter * param ,
Atom * atom ,
2022-06-26 16:25:59 +02:00
Neighbor * neighbor ,
Atom * c_atom ,
Neighbor * c_neighbor ,
2022-07-17 18:34:17 +02:00
const int num_threads_per_block ,
double * timers )
2020-08-19 09:22:43 +02:00
{
2022-07-17 18:34:17 +02:00
double S , E , beforeEvent , afterEvent ;
2020-08-19 09:22:43 +02:00
S = getTimeStamp ( ) ;
2022-07-17 18:34:17 +02:00
beforeEvent = S ;
2020-11-05 12:41:44 +01:00
LIKWID_MARKER_START ( " reneighbour " ) ;
2022-07-13 14:07:19 +02:00
updateAtomsPbc_cuda ( atom , param , c_atom , num_threads_per_block ) ;
2022-07-17 18:34:17 +02:00
afterEvent = getTimeStamp ( ) ;
timers [ NEIGH_UPDATE_ATOMS_PBC ] + = afterEvent - beforeEvent ;
beforeEvent = afterEvent ;
2020-08-19 09:22:43 +02:00
setupPbc ( atom , param ) ;
2022-07-17 18:34:17 +02:00
afterEvent = getTimeStamp ( ) ;
timers [ NEIGH_SETUP_PBC ] + = afterEvent - beforeEvent ;
beforeEvent = afterEvent ;
2022-07-03 19:53:33 +02:00
updatePbc_cuda ( atom , param , c_atom , true , num_threads_per_block ) ;
2022-07-17 18:34:17 +02:00
afterEvent = getTimeStamp ( ) ;
timers [ NEIGH_UPDATE_PBC ] + = afterEvent - beforeEvent ;
beforeEvent = afterEvent ;
2021-11-03 00:57:24 +01:00
//sortAtom(atom);
2022-07-19 20:38:11 +02:00
buildNeighbor_cuda ( atom , neighbor , c_atom , c_neighbor , num_threads_per_block , timers ) ;
2020-11-05 12:41:44 +01:00
LIKWID_MARKER_STOP ( " reneighbour " ) ;
2020-08-19 09:22:43 +02:00
E = getTimeStamp ( ) ;
2022-07-17 18:34:17 +02:00
afterEvent = E ;
2022-07-19 20:38:11 +02:00
timers [ NEIGH_BUILD_LISTS ] + = afterEvent - beforeEvent ;
2020-08-19 09:22:43 +02:00
return E - S ;
2020-08-19 09:00:35 +02:00
}
2020-08-18 14:27:28 +02:00
void initialIntegrate ( Parameter * param , Atom * atom )
2020-08-14 08:32:36 +02:00
{
2020-08-18 14:27:28 +02:00
for ( int i = 0 ; i < atom - > Nlocal ; i + + ) {
2022-01-01 18:18:12 +01:00
atom_vx ( i ) + = param - > dtforce * atom_fx ( i ) ;
atom_vy ( i ) + = param - > dtforce * atom_fy ( i ) ;
atom_vz ( i ) + = param - > dtforce * atom_fz ( i ) ;
atom_x ( i ) = atom_x ( i ) + param - > dt * atom_vx ( i ) ;
atom_y ( i ) = atom_y ( i ) + param - > dt * atom_vy ( i ) ;
atom_z ( i ) = atom_z ( i ) + param - > dt * atom_vz ( i ) ;
2020-08-11 16:34:22 +02:00
}
}
2020-08-18 14:27:28 +02:00
void finalIntegrate ( Parameter * param , Atom * atom )
2020-08-11 16:34:22 +02:00
{
2020-08-18 14:27:28 +02:00
for ( int i = 0 ; i < atom - > Nlocal ; i + + ) {
2022-01-01 18:18:12 +01:00
atom_vx ( i ) + = param - > dtforce * atom_fx ( i ) ;
atom_vy ( i ) + = param - > dtforce * atom_fy ( i ) ;
atom_vz ( i ) + = param - > dtforce * atom_fz ( i ) ;
2020-08-11 16:34:22 +02:00
}
}
2020-08-18 14:27:28 +02:00
void printAtomState ( Atom * atom )
{
printf ( " Atom counts: Natoms=%d Nlocal=%d Nghost=%d Nmax=%d \n " ,
atom - > Natoms , atom - > Nlocal , atom - > Nghost , atom - > Nmax ) ;
2021-10-26 09:16:31 +02:00
/* int nall = atom->Nlocal + atom->Nghost; */
2020-08-18 14:27:28 +02:00
2021-10-26 09:16:31 +02:00
/* for (int i=0; i<nall; i++) { */
/* printf("%d %f %f %f\n", i, atom->x[i], atom->y[i], atom->z[i]); */
/* } */
2020-08-18 14:27:28 +02:00
}
2021-10-26 00:40:39 +02:00
int str2ff ( const char * string )
{
if ( strncmp ( string , " lj " , 2 ) = = 0 ) return FF_LJ ;
if ( strncmp ( string , " eam " , 3 ) = = 0 ) return FF_EAM ;
return - 1 ;
}
const char * ff2str ( int ff )
{
if ( ff = = FF_LJ ) { return " lj " ; }
if ( ff = = FF_EAM ) { return " eam " ; }
return " invalid " ;
}
2022-06-26 16:25:59 +02:00
int get_num_threads ( ) {
const char * num_threads_env = getenv ( " NUM_THREADS " ) ;
int num_threads = 0 ;
2022-06-26 18:37:09 +02:00
if ( num_threads_env = = 0 )
2022-06-26 16:25:59 +02:00
num_threads = 32 ;
else {
num_threads = atoi ( num_threads_env ) ;
}
return num_threads ;
}
2021-10-26 00:40:39 +02:00
int main ( int argc , char * * argv )
2020-08-11 16:34:22 +02:00
{
2020-08-19 09:00:35 +02:00
double timer [ NUMTIMER ] ;
2021-10-26 00:40:39 +02:00
Eam eam ;
2020-08-18 14:27:28 +02:00
Atom atom ;
2020-08-11 16:34:22 +02:00
Neighbor neighbor ;
2021-10-12 15:04:08 +02:00
Stats stats ;
2020-08-11 16:34:22 +02:00
Parameter param ;
2022-06-23 18:54:56 +02:00
Atom c_atom ;
Neighbor c_neighbor ;
2020-08-11 16:34:22 +02:00
2020-11-05 12:41:44 +01:00
LIKWID_MARKER_INIT ;
# pragma omp parallel
{
LIKWID_MARKER_REGISTER ( " force " ) ;
2021-07-16 00:24:43 +02:00
//LIKWID_MARKER_REGISTER("reneighbour");
//LIKWID_MARKER_REGISTER("pbc");
2020-11-05 12:41:44 +01:00
}
2020-08-19 09:00:35 +02:00
init ( & param ) ;
for ( int i = 0 ; i < argc ; i + + )
{
2021-10-26 00:40:39 +02:00
if ( ( strcmp ( argv [ i ] , " -f " ) = = 0 ) )
{
if ( ( param . force_field = str2ff ( argv [ + + i ] ) ) < 0 ) {
fprintf ( stderr , " Invalid force field! \n " ) ;
exit ( - 1 ) ;
}
continue ;
}
if ( ( strcmp ( argv [ i ] , " -i " ) = = 0 ) )
{
param . input_file = strdup ( argv [ + + i ] ) ;
continue ;
}
2020-08-19 09:00:35 +02:00
if ( ( strcmp ( argv [ i ] , " -n " ) = = 0 ) | | ( strcmp ( argv [ i ] , " --nsteps " ) = = 0 ) )
{
param . ntimes = atoi ( argv [ + + i ] ) ;
continue ;
}
if ( ( strcmp ( argv [ i ] , " -nx " ) = = 0 ) )
{
param . nx = atoi ( argv [ + + i ] ) ;
continue ;
}
if ( ( strcmp ( argv [ i ] , " -ny " ) = = 0 ) )
{
param . ny = atoi ( argv [ + + i ] ) ;
continue ;
}
if ( ( strcmp ( argv [ i ] , " -nz " ) = = 0 ) )
{
param . nz = atoi ( argv [ + + i ] ) ;
continue ;
}
2021-10-26 00:40:39 +02:00
if ( ( strcmp ( argv [ i ] , " --freq " ) = = 0 ) )
2021-10-12 15:04:08 +02:00
{
param . proc_freq = atof ( argv [ + + i ] ) ;
continue ;
}
2021-10-29 16:52:19 +02:00
if ( ( strcmp ( argv [ i ] , " --vtk " ) = = 0 ) )
{
param . vtk_file = strdup ( argv [ + + i ] ) ;
continue ;
}
2020-08-19 09:00:35 +02:00
if ( ( strcmp ( argv [ i ] , " -h " ) = = 0 ) | | ( strcmp ( argv [ i ] , " --help " ) = = 0 ) )
{
printf ( " MD Bench: A minimalistic re-implementation of miniMD \n " ) ;
printf ( HLINE ) ;
2021-10-26 00:40:39 +02:00
printf ( " -f <string>: force field (lj or eam), default lj \n " ) ;
printf ( " -i <string>: input file for EAM \n " ) ;
2020-08-19 09:22:43 +02:00
printf ( " -n / --nsteps <int>: set number of timesteps for simulation \n " ) ;
printf ( " -nx/-ny/-nz <int>: set linear dimension of systembox in x/y/z direction \n " ) ;
2021-10-26 00:40:39 +02:00
printf ( " --freq <real>: processor frequency (GHz) \n " ) ;
2021-10-29 16:52:19 +02:00
printf ( " --vtk <string>: VTK file for visualization \n " ) ;
2020-08-19 09:00:35 +02:00
printf ( HLINE ) ;
exit ( EXIT_SUCCESS ) ;
}
}
2022-06-26 16:25:59 +02:00
// this should be multiple of 32 as operations are performed at the level of warps
const int num_threads_per_block = get_num_threads ( ) ;
2022-07-19 20:38:11 +02:00
setup ( & param , & eam , & atom , & neighbor , & c_atom , & c_neighbor , & stats , num_threads_per_block , ( double * ) & timer ) ;
2020-08-18 14:27:28 +02:00
computeThermo ( 0 , & param , & atom ) ;
2021-10-26 00:40:39 +02:00
if ( param . force_field = = FF_EAM ) {
2021-11-03 00:57:24 +01:00
computeForceEam ( & eam , & param , & atom , & neighbor , & stats , 1 , 0 ) ;
2021-10-26 00:40:39 +02:00
} else {
2021-10-26 09:16:31 +02:00
# if defined(MEM_TRACER) || defined(INDEX_TRACER) || defined(COMPUTE_STATS)
computeForceTracing ( & param , & atom , & neighbor , & stats , 1 , 0 ) ;
2021-10-26 09:11:17 +02:00
# else
2022-06-26 16:25:59 +02:00
computeForce ( true , & param , & atom , & neighbor , & c_atom , & c_neighbor , num_threads_per_block ) ;
2021-10-26 09:11:17 +02:00
# endif
2021-10-26 00:40:39 +02:00
}
2020-08-11 16:34:22 +02:00
2020-08-19 09:22:43 +02:00
timer [ FORCE ] = 0.0 ;
timer [ NEIGH ] = 0.0 ;
timer [ TOTAL ] = getTimeStamp ( ) ;
2022-07-17 18:34:17 +02:00
timer [ NEIGH_UPDATE_ATOMS_PBC ] = 0.0 ;
timer [ NEIGH_SETUP_PBC ] = 0.0 ;
timer [ NEIGH_UPDATE_PBC ] = 0.0 ;
2022-07-19 20:38:11 +02:00
timer [ NEIGH_BINATOMS ] = 0.0 ;
timer [ NEIGH_BUILD_LISTS ] = 0.0 ;
2020-08-19 09:22:43 +02:00
2021-10-29 16:52:19 +02:00
if ( param . vtk_file ! = NULL ) {
write_atoms_to_vtk_file ( param . vtk_file , & atom , 0 ) ;
}
2020-08-11 16:34:22 +02:00
for ( int n = 0 ; n < param . ntimes ; n + + ) {
2021-12-25 13:52:33 +01:00
const bool doReneighbour = ( n + 1 ) % param . every = = 0 ;
2021-12-25 15:36:08 +01:00
2022-06-26 16:25:59 +02:00
cuda_initial_integrate ( doReneighbour , & param , & atom , & c_atom , num_threads_per_block ) ;
2022-01-01 18:18:12 +01:00
2021-12-25 13:52:33 +01:00
if ( doReneighbour ) {
2022-07-19 20:38:11 +02:00
timer [ NEIGH ] + = reneighbour ( & param , & atom , & neighbor , & c_atom , & c_neighbor , num_threads_per_block , ( double * ) & timer ) ;
2021-12-25 13:52:33 +01:00
} else {
2022-07-17 18:34:17 +02:00
double before = getTimeStamp ( ) ;
2022-07-03 21:14:33 +02:00
updatePbc_cuda ( & atom , & param , & c_atom , false , num_threads_per_block ) ;
2022-07-17 18:34:17 +02:00
double after = getTimeStamp ( ) ;
timer [ NEIGH_UPDATE_PBC ] + = after - before ;
2020-08-11 16:34:22 +02:00
}
2021-10-26 00:40:39 +02:00
if ( param . force_field = = FF_EAM ) {
2021-11-03 00:57:24 +01:00
timer [ FORCE ] + = computeForceEam ( & eam , & param , & atom , & neighbor , & stats , 0 , n + 1 ) ;
2021-10-26 00:40:39 +02:00
} else {
2021-10-26 09:16:31 +02:00
# if defined(MEM_TRACER) || defined(INDEX_TRACER) || defined(COMPUTE_STATS)
timer [ FORCE ] + = computeForceTracing ( & param , & atom , & neighbor , & stats , 0 , n + 1 ) ;
2021-10-26 09:11:17 +02:00
# else
2022-06-26 16:25:59 +02:00
timer [ FORCE ] + = computeForce ( doReneighbour , & param , & atom , & neighbor , & c_atom , & c_neighbor , num_threads_per_block ) ;
2021-10-26 09:11:17 +02:00
# endif
2021-10-26 00:40:39 +02:00
}
2022-01-24 18:04:50 +01:00
2022-06-26 16:25:59 +02:00
cuda_final_integrate ( doReneighbour , & param , & atom , & c_atom , num_threads_per_block ) ;
2020-08-11 16:34:22 +02:00
2020-08-17 14:01:46 +02:00
if ( ! ( ( n + 1 ) % param . nstat ) & & ( n + 1 ) < param . ntimes ) {
2022-07-05 00:54:11 +02:00
checkCUDAError ( " computeThermo atom->x memcpy back " , cudaMemcpy ( atom . x , c_atom . x , atom . Nmax * sizeof ( MD_FLOAT ) * 3 , cudaMemcpyDeviceToHost ) ) ;
2020-08-18 14:27:28 +02:00
computeThermo ( n + 1 , & param , & atom ) ;
2020-08-11 16:34:22 +02:00
}
2021-10-29 16:52:19 +02:00
if ( param . vtk_file ! = NULL ) {
write_atoms_to_vtk_file ( param . vtk_file , & atom , n + 1 ) ;
}
2020-08-11 16:34:22 +02:00
}
2022-07-19 20:38:11 +02:00
timer [ NEIGH_BUILD_LISTS ] - = timer [ NEIGH_BINATOMS ] ;
2020-08-19 09:22:43 +02:00
timer [ TOTAL ] = getTimeStamp ( ) - timer [ TOTAL ] ;
2020-08-18 14:27:28 +02:00
computeThermo ( - 1 , & param , & atom ) ;
2020-08-12 15:38:08 +02:00
2020-08-19 09:22:43 +02:00
printf ( HLINE ) ;
2021-10-26 00:40:39 +02:00
printf ( " Force field: %s \n " , ff2str ( param . force_field ) ) ;
2021-03-22 21:51:47 +01:00
printf ( " Data layout for positions: %s \n " , POS_DATA_LAYOUT ) ;
2020-11-05 12:41:44 +01:00
# if PRECISION == 1
printf ( " Using single precision floating point. \n " ) ;
# else
printf ( " Using double precision floating point. \n " ) ;
# endif
printf ( HLINE ) ;
2020-08-19 10:00:19 +02:00
printf ( " System: %d atoms %d ghost atoms, Steps: %d \n " , atom . Natoms , atom . Nghost , param . ntimes ) ;
2022-07-19 20:38:11 +02:00
printf ( " TOTAL %.2fs FORCE %.2fs NEIGH %.2fs REST %.2fs NEIGH_TIMERS: UPD_AT: %.2fs SETUP_PBC %.2fs UPDATE_PBC %.2fs BINATOMS %.2fs BUILD_NEIGHBOR %.2fs \n " ,
timer [ TOTAL ] , timer [ FORCE ] , timer [ NEIGH ] , timer [ TOTAL ] - timer [ FORCE ] - timer [ NEIGH ] , timer [ NEIGH_UPDATE_ATOMS_PBC ] , timer [ NEIGH_SETUP_PBC ] , timer [ NEIGH_UPDATE_PBC ] , timer [ NEIGH_BINATOMS ] , timer [ NEIGH_BUILD_LISTS ] ) ;
2020-08-19 09:22:43 +02:00
printf ( HLINE ) ;
2020-08-19 10:00:19 +02:00
printf ( " Performance: %.2f million atom updates per second \n " ,
1e-6 * ( double ) atom . Natoms * param . ntimes / timer [ TOTAL ] ) ;
2022-07-19 20:38:11 +02:00
double atomUpdatesTotal = ( double ) atom . Natoms * param . ntimes ;
2022-07-20 23:04:22 +02:00
printf ( " Force_perf in millions per sec: %.2f \n " , 1e-6 * atomUpdatesTotal / timer [ FORCE ] ) ;
2022-07-19 20:38:11 +02:00
double atomNeighUpdatesTotal = ( double ) atom . Natoms * param . ntimes / param . every ;
printf ( " Neighbor_perf in millions per sec: updateAtomsPbc: %.2f setupPbc: %.2f updatePbc: %.2f binAtoms: %.2f buildNeighbor_wo_binning: %.2f \n " , 1e-6 * atomNeighUpdatesTotal / timer [ NEIGH_UPDATE_ATOMS_PBC ] , 1e-6 * atomNeighUpdatesTotal / timer [ NEIGH_SETUP_PBC ] , 1e-6 * atomUpdatesTotal / timer [ NEIGH_UPDATE_PBC ] , 1e-6 * atomNeighUpdatesTotal / timer [ NEIGH_BINATOMS ] , 1e-6 * atomNeighUpdatesTotal / timer [ NEIGH_BUILD_LISTS ] ) ;
2021-10-26 09:16:31 +02:00
# ifdef COMPUTE_STATS
2021-10-12 22:39:54 +02:00
displayStatistics ( & atom , & param , & stats , timer ) ;
2021-10-26 09:11:17 +02:00
# endif
2020-11-05 12:41:44 +01:00
LIKWID_MARKER_CLOSE ;
2020-08-11 16:34:22 +02:00
return EXIT_SUCCESS ;
}