Sanchayan Maity
0f4b39775c
During the last commit of splash2 benchmark it seems before committing when we ran "make clean", it effectively undid what the patch at below link did http://www.capsl.udel.edu/splash/Download.html Fix this since without this it is not possible to build the arcane splash2 benchmark.
304 lines
12 KiB
C
304 lines
12 KiB
C
/*************************************************************************/
|
|
/* */
|
|
/* Copyright (c) 1994 Stanford University */
|
|
/* */
|
|
/* All rights reserved. */
|
|
/* */
|
|
/* Permission is given to use, copy, and modify this software for any */
|
|
/* non-commercial purpose as long as this copyright notice is not */
|
|
/* removed. All other uses, including redistribution in whole or in */
|
|
/* part, are forbidden without prior written permission. */
|
|
/* */
|
|
/* This software is provided with absolutely no warranty and no */
|
|
/* support. */
|
|
/* */
|
|
/*************************************************************************/
|
|
|
|
EXTERN_ENV
|
|
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
#include "mdvar.h"
|
|
#include "water.h"
|
|
#include "wwpot.h"
|
|
#include "cnst.h"
|
|
#include "parameters.h"
|
|
#include "mddata.h"
|
|
#include "split.h"
|
|
#include "global.h"
|
|
|
|
void INTERF(long DEST, double *VIR, long ProcID)
|
|
{
|
|
|
|
/* This is the routine that computes intermolecular interactions and
|
|
* hence takes up most of the execution time. It is
|
|
* called both from main() and from mdmain().
|
|
* When called from main(), it is used to estimate the initial
|
|
* accelerations by computing intermolecular forces. When called
|
|
* from mdmain(), it is used to compute intermolecular forces.
|
|
* The parameter DEST specifies whether results go into the
|
|
* accelerations or the forces. It uses the routine UPDATE_FORCES
|
|
* which is defined in this file, and routine CSHIFT in file cshift.U
|
|
*
|
|
* This routine calculates inter-molecular interaction forces.
|
|
* the distances are arranged in the order M-M, M-H1, M-H2, H1-M,
|
|
* H2-M, H1-H2, H1-H1, H2-H1, H2-H2, O-O, O-H1, O-H2, H1-O, H2-O,
|
|
* where the M are "centers" of the molecules.
|
|
*/
|
|
|
|
long dir;
|
|
long KC, K;
|
|
long i, j, k;
|
|
|
|
long XBOX, YBOX, ZBOX, X_NUM, Y_NUM, Z_NUM;
|
|
/* per interaction arrays that hold some computed distances */
|
|
double YL[15], XL[15], ZL[15], RS[15], FF[15], RL[15];
|
|
double FTEMP;
|
|
double LVIR = 0.0;
|
|
struct link *curr_ptr, *neighbor_ptr;
|
|
struct list_of_boxes *curr_box;
|
|
double *temp_p;
|
|
|
|
curr_box = my_boxes[ProcID];
|
|
while (curr_box) {
|
|
|
|
i = curr_box->coord[XDIR]; /* X coordinate of box */
|
|
j = curr_box->coord[YDIR]; /* Y coordinate of box */
|
|
k = curr_box->coord[ZDIR]; /* Z coordinate of box */
|
|
|
|
/* loop over nearest neighbor boxes */
|
|
|
|
for (XBOX=i-1; XBOX<=i+1; XBOX++) {
|
|
for (YBOX=j-1; YBOX<=j+1; YBOX++) {
|
|
for (ZBOX=k-1; ZBOX<=k+1; ZBOX++) {
|
|
|
|
/* Special case for two boxes per side */
|
|
|
|
if ((BOX_PER_SIDE == 2) && ((XBOX < 0) || (XBOX == 2) ||
|
|
(YBOX < 0) || (YBOX == 2) || (ZBOX < 0) || (ZBOX == 2)))
|
|
continue;
|
|
|
|
X_NUM = XBOX;
|
|
Y_NUM = YBOX;
|
|
Z_NUM = ZBOX;
|
|
|
|
/* Make box number valid if out of box */
|
|
|
|
if (X_NUM == -1)
|
|
X_NUM += BOX_PER_SIDE;
|
|
else if (X_NUM >= BOX_PER_SIDE)
|
|
X_NUM -= BOX_PER_SIDE;
|
|
if (Y_NUM == -1)
|
|
Y_NUM += BOX_PER_SIDE;
|
|
else if (Y_NUM >= BOX_PER_SIDE)
|
|
Y_NUM -= BOX_PER_SIDE;
|
|
if (Z_NUM == -1)
|
|
Z_NUM += BOX_PER_SIDE;
|
|
else if (Z_NUM >= BOX_PER_SIDE)
|
|
Z_NUM -= BOX_PER_SIDE;
|
|
|
|
/* Don't do current box more than once */
|
|
|
|
if ((X_NUM == i) && (Y_NUM == j) && (Z_NUM == k) &&
|
|
((XBOX != i) || (YBOX != j) || (ZBOX !=k))) {
|
|
continue;
|
|
}
|
|
|
|
neighbor_ptr = BOX[X_NUM][Y_NUM][Z_NUM].list;
|
|
|
|
while (neighbor_ptr) {
|
|
|
|
/* go through current box list */
|
|
|
|
curr_ptr = BOX[i][j][k].list;
|
|
while (curr_ptr) {
|
|
|
|
/* Don't do interaction with same molecule */
|
|
|
|
if (curr_ptr == neighbor_ptr) {
|
|
curr_ptr = curr_ptr->next_mol;
|
|
continue;
|
|
}
|
|
|
|
/* compute some intermolecular distances;
|
|
first call CSHIFT to implement periodic boundary conditions */
|
|
|
|
CSHIFT(curr_ptr->mol.F[DISP][XDIR],neighbor_ptr->mol.F[DISP][XDIR],
|
|
curr_ptr->mol.VM[XDIR],neighbor_ptr->mol.VM[XDIR],XL,BOXH,BOXL);
|
|
CSHIFT(curr_ptr->mol.F[DISP][YDIR],neighbor_ptr->mol.F[DISP][YDIR],
|
|
curr_ptr->mol.VM[YDIR],neighbor_ptr->mol.VM[YDIR],YL,BOXH,BOXL);
|
|
CSHIFT(curr_ptr->mol.F[DISP][ZDIR],neighbor_ptr->mol.F[DISP][ZDIR],
|
|
curr_ptr->mol.VM[ZDIR],neighbor_ptr->mol.VM[ZDIR],ZL,BOXH,BOXL);
|
|
|
|
KC=0;
|
|
for (K = 0; K < 9; K++) {
|
|
RS[K]=XL[K]*XL[K]+YL[K]*YL[K]+ZL[K]*ZL[K];
|
|
if (RS[K] > CUT2)
|
|
KC++;
|
|
} /* for K */
|
|
|
|
if (KC != 9) {
|
|
for (K = 0; K < 14; K++)
|
|
FF[K]=0.0;
|
|
if (RS[0] < CUT2) {
|
|
FF[0]=QQ4/(RS[0]*sqrt(RS[0]))+REF4;
|
|
LVIR = LVIR + FF[0]*RS[0];
|
|
} /* if */
|
|
|
|
|
|
for (K = 1; K < 5; K++) {
|
|
if (RS[K] < CUT2) {
|
|
FF[K]= -QQ2/(RS[K]*sqrt(RS[K]))-REF2;
|
|
LVIR = LVIR + FF[K]*RS[K];
|
|
} /* if */
|
|
if (RS[K+4] <= CUT2) {
|
|
RL[K+4]=sqrt(RS[K+4]);
|
|
FF[K+4]=QQ/(RS[K+4]*RL[K+4])+REF1;
|
|
LVIR = LVIR + FF[K+4]*RS[K+4];
|
|
} /* if */
|
|
} /* for K */
|
|
|
|
if (KC == 0) {
|
|
RS[9]=XL[9]*XL[9]+YL[9]*YL[9]+ZL[9]*ZL[9];
|
|
RL[9]=sqrt(RS[9]);
|
|
FF[9]=AB1*exp(-B1*RL[9])/RL[9];
|
|
LVIR = LVIR + FF[9]*RS[9];
|
|
for (K = 10; K < 14; K++) {
|
|
FTEMP=AB2*exp(-B2*RL[K-5])/RL[K-5];
|
|
FF[K-5]=FF[K-5]+FTEMP;
|
|
LVIR= LVIR+FTEMP*RS[K-5];
|
|
RS[K]=XL[K]*XL[K]+YL[K]*YL[K]+ZL[K]*ZL[K];
|
|
RL[K]=sqrt(RS[K]);
|
|
FF[K]=(AB3*exp(-B3*RL[K])-AB4*exp(-B4*RL[K]))/RL[K];
|
|
LVIR = LVIR + FF[K]*RS[K];
|
|
} /* for K */
|
|
} /* if KC == 0 */
|
|
|
|
UPDATE_FORCES(curr_ptr, DEST, XL, YL, ZL, FF);
|
|
} /* if KC != 9 */
|
|
|
|
curr_ptr = curr_ptr->next_mol;
|
|
} /* while curr_ptr */
|
|
|
|
neighbor_ptr = neighbor_ptr->next_mol;
|
|
} /* while neighbor_ptr */
|
|
|
|
}
|
|
}
|
|
} /* neighbor boxes' for loops */
|
|
|
|
curr_box = curr_box->next_box;
|
|
} /* while mybox */
|
|
|
|
/* accumulate running sum from private partial sums */
|
|
|
|
LOCK(gl->InterfVirLock);
|
|
*VIR = *VIR + LVIR/2.0;
|
|
UNLOCK(gl->InterfVirLock);
|
|
|
|
/* wait till all forces are updated */
|
|
|
|
BARRIER(gl->InterfBar, NumProcs);
|
|
|
|
/* divide final forces by masses */
|
|
|
|
curr_box = my_boxes[ProcID];
|
|
while (curr_box) {
|
|
|
|
i = curr_box->coord[XDIR]; /* X coordinate of box */
|
|
j = curr_box->coord[YDIR]; /* Y coordinate of box */
|
|
k = curr_box->coord[ZDIR]; /* Z coordinate of box */
|
|
|
|
curr_ptr = BOX[i][j][k].list;
|
|
while (curr_ptr) {
|
|
for ( dir = XDIR; dir <= ZDIR; dir++) {
|
|
temp_p = curr_ptr->mol.F[DEST][dir];
|
|
temp_p[H1] = temp_p[H1] * FHM;
|
|
temp_p[O] = temp_p[O] * FOM;
|
|
temp_p[H2] = temp_p[H2] * FHM;
|
|
} /* for dir */
|
|
|
|
curr_ptr = curr_ptr->next_mol;
|
|
} /* while curr_ptr */
|
|
curr_box = curr_box->next_box;
|
|
} /* while curr_box */
|
|
|
|
}/* end of subroutine INTERF */
|
|
|
|
|
|
/************* UPDATE FORCES SUBROUTINE *************/
|
|
|
|
void UPDATE_FORCES(struct link *link_ptr, long DEST, double *XL, double *YL, double *ZL, double *FF)
|
|
{
|
|
/* From the computed distances etc., compute the
|
|
* intermolecular forces and update the force (or
|
|
* acceleration) locations.
|
|
*/
|
|
|
|
long K;
|
|
double G110[3], G23[3], G45[3], TT1[3], TT[3], TT2[3];
|
|
double GG[15][3];
|
|
|
|
/* tx_p, ty_p, tz_p are temporary pointers used to avoid too much
|
|
pointer (and array) dereferencing. Since the pointers dereferenced
|
|
otherwise are global pointers probably stored in processor 0's memory,
|
|
this can also have the effect of reducing hot-spotting and remote
|
|
references when cache misses are incurred on these pointers. */
|
|
|
|
double *tx_p, *ty_p, *tz_p;
|
|
|
|
|
|
/* CALCULATE X-COMPONENT FORCES */
|
|
|
|
for (K = 0; K < 14; K++) {
|
|
GG[K+1][XDIR] = FF[K]*XL[K];
|
|
GG[K+1][YDIR] = FF[K]*YL[K];
|
|
GG[K+1][ZDIR] = FF[K]*ZL[K];
|
|
}
|
|
|
|
G110[XDIR] = GG[10][XDIR]+GG[1][XDIR]*C1;
|
|
G110[YDIR] = GG[10][YDIR]+GG[1][YDIR]*C1;
|
|
G110[ZDIR] = GG[10][ZDIR]+GG[1][ZDIR]*C1;
|
|
G23[XDIR] = GG[2][XDIR]+GG[3][XDIR];
|
|
G23[YDIR] = GG[2][YDIR]+GG[3][YDIR];
|
|
G23[ZDIR] = GG[2][ZDIR]+GG[3][ZDIR];
|
|
G45[XDIR]=GG[4][XDIR]+GG[5][XDIR];
|
|
G45[YDIR]=GG[4][YDIR]+GG[5][YDIR];
|
|
G45[ZDIR]=GG[4][ZDIR]+GG[5][ZDIR];
|
|
TT1[XDIR] =GG[1][XDIR]*C2;
|
|
TT1[YDIR] =GG[1][YDIR]*C2;
|
|
TT1[ZDIR] =GG[1][ZDIR]*C2;
|
|
TT[XDIR] =G23[XDIR]*C2+TT1[XDIR];
|
|
TT[YDIR] =G23[YDIR]*C2+TT1[YDIR];
|
|
TT[ZDIR] =G23[ZDIR]*C2+TT1[ZDIR];
|
|
TT2[XDIR]=G45[XDIR]*C2+TT1[XDIR];
|
|
TT2[YDIR]=G45[YDIR]*C2+TT1[YDIR];
|
|
TT2[ZDIR]=G45[ZDIR]*C2+TT1[ZDIR];
|
|
|
|
/* Update force or acceleration for link */
|
|
|
|
tx_p = link_ptr->mol.F[DEST][XDIR];
|
|
ty_p = link_ptr->mol.F[DEST][YDIR];
|
|
tz_p = link_ptr->mol.F[DEST][ZDIR];
|
|
|
|
tx_p[H1] +=
|
|
GG[6][XDIR]+GG[7][XDIR]+GG[13][XDIR]+TT[XDIR]+GG[4][XDIR];
|
|
tx_p[O] +=
|
|
G110[XDIR] + GG[11][XDIR] +GG[12][XDIR]+C1*G23[XDIR];
|
|
tx_p[H2] +=
|
|
GG[8][XDIR]+GG[9][XDIR]+GG[14][XDIR]+TT[XDIR]+GG[5][XDIR];
|
|
ty_p[H1] +=
|
|
GG[6][YDIR]+GG[7][YDIR]+GG[13][YDIR]+TT[YDIR]+GG[4][YDIR];
|
|
ty_p[O] +=
|
|
G110[YDIR]+GG[11][YDIR]+GG[12][YDIR]+C1*G23[YDIR];
|
|
ty_p[H2] +=
|
|
GG[8][YDIR]+GG[9][YDIR]+GG[14][YDIR]+TT[YDIR]+GG[5][YDIR];
|
|
tz_p[H1] +=
|
|
GG[6][ZDIR]+GG[7][ZDIR]+GG[13][ZDIR]+TT[ZDIR]+GG[4][ZDIR];
|
|
tz_p[O] +=
|
|
G110[ZDIR]+GG[11][ZDIR]+GG[12][ZDIR]+C1*G23[ZDIR];
|
|
tz_p[H2] +=
|
|
GG[8][ZDIR]+GG[9][ZDIR]+GG[14][ZDIR]+TT[ZDIR]+GG[5][ZDIR];
|
|
|
|
} /* end of subroutine UPDATE_FORCES */
|