gem5/splash2/codes/apps/water-spatial/intraf.C

175 lines
6.4 KiB
C
Raw Normal View History

/*************************************************************************/
/* */
/* 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 <cmath>
#include <cstdio>
#include "frcnst.h"
#include "global.h"
#include "mddata.h"
#include "mdvar.h"
#include "parameters.h"
#include "split.h"
#include "water.h"
#include "wwpot.h"
void INTRAF(double *VIR, long ProcID)
{
/* This routine calculates the intra-molecular force
* acting on each atom.
* FC11, FC12, FC13, AND FC33 are the quardratic force constants
* FC111, FC112, ....... ETC. are the cubic force constants
* FC1111, FC1112 ...... ETC. are the quartic force constants
*/
double SUM, R1, R2, VR1[4], VR2[4], COS, SIN;
double DT, DTS, DR1, DR1S, DR2, DR2S, R1S, R2S, DR11[4], DR23[4];
double DT1[4], DT3[4], F1, F2, F3, T1, T2;
double LVIR; /* private copy of global sum to reduce synchronized updates */
long dir, atom;
long i, j, k;
struct link *curr_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 */
curr_ptr = BOX[i][j][k].list;
while (curr_ptr) {
SUM=0.0;
R1=0.0;
R2=0.0;
/* loop through the three directions */
for (dir=XDIR; dir<=ZDIR; dir++) {
temp_p = curr_ptr->mol.F[DISP][dir];
curr_ptr->mol.VM[dir] = C1 * temp_p[O]
+ C2 * (temp_p[H1] +
temp_p[H2] );
VR1[dir] = temp_p[O] - temp_p[H1];
R1 += VR1[dir] * VR1[dir];
VR2[dir] = temp_p[O] - temp_p[H2];
R2 += VR2[dir] * VR2[dir];
SUM += VR1[dir] * VR2[dir];
} /* for dir */
R1=sqrt(R1);
R2=sqrt(R2);
/*calc cos(THETA), sin(THETA), delta(R1), delta(R2), delta(THETA)*/
COS=SUM/(R1*R2);
SIN=sqrt(ONE-COS*COS);
DT=(acos(COS)-ANGLE)*ROH;
DTS=DT*DT;
DR1=R1-ROH;
DR1S=DR1*DR1;
DR2=R2-ROH;
DR2S=DR2*DR2;
/* calculate derivatives of R1/X1, R2/X3, THETA/X1, and THETA/X3 */
R1S=ROH/(R1*SIN);
R2S=ROH/(R2*SIN);
for (dir = XDIR; dir <= ZDIR; dir++) {
DR11[dir]=VR1[dir]/R1;
DR23[dir]=VR2[dir]/R2;
DT1[dir]=(-DR23[dir]+DR11[dir]*COS)*R1S;
DT3[dir]=(-DR11[dir]+DR23[dir]*COS)*R2S;
} /* for dir */
/* calculate forces */
F1=FC11*DR1+FC12*DR2+FC13*DT;
F2=FC33*DT +FC13*(DR1+DR2);
F3=FC11*DR2+FC12*DR1+FC13*DT;
F1=F1+(3.0*FC111*DR1S+FC112*(2.0*DR1+DR2)*DR2
+2.0*FC113*DR1*DT+FC123*DR2*DT+FC133*DTS)*ROHI;
F2=F2+(3.0*FC333*DTS+FC113*(DR1S+DR2S)
+FC123*DR1*DR2+2.0*FC133*(DR1+DR2)*DT)*ROHI;
F3=F3+(3.0*FC111*DR2S+FC112*(2.0*DR2+DR1)*DR1
+2.0*FC113*DR2*DT+FC123*DR1*DT+FC133*DTS)*ROHI;
F1=F1+(4.0*FC1111*DR1S*DR1+FC1112*(3.0*DR1S+DR2S)
*DR2+2.0*FC1122*DR1*DR2S+3.0*FC1113*DR1S*DT
+FC1123*(2.0*DR1+DR2)*DR2*DT+(2.0*FC1133*DR1
+FC1233*DR2+FC1333*DT)*DTS)*ROHI2;
F2=F2+(4.0*FC3333*DTS*DT+FC1113*(DR1S*DR1+DR2S*DR2)
+FC1123*(DR1+DR2)*DR1*DR2+2.0*FC1133*(DR1S+DR2S)
*DT+2.0*FC1233*DR1*DR2*DT+3.0*FC1333*(DR1+DR2)*DTS)
*ROHI2;
F3=F3+(4.0*FC1111*DR2S*DR2+FC1112*(3.0*DR2S+DR1S)
*DR1+2.0*FC1122*DR1S*DR2+3.0*FC1113*DR2S*DT
+FC1123*(2.0*DR2+DR1)*DR1*DT+(2.0*FC1133*DR2
+FC1233*DR1+FC1333*DT)*DTS)*ROHI2;
/* Update forces */
for (dir = XDIR; dir <= ZDIR; dir++) {
temp_p = curr_ptr->mol.F[FORCES][dir];
T1=F1*DR11[dir]+F2*DT1[dir];
temp_p[H1] = T1;
T2=F3*DR23[dir]+F2*DT3[dir];
temp_p[H2] = T2;
temp_p[O] = -(T1+T2);
} /* for dir */
curr_ptr = curr_ptr->next_mol;
} /* while curr_ptr */
curr_box = curr_box->next_box;
} /* while curr_box */
/* calculate summation of the product of the displacement and computed
force for every molecule, direction, and atom */
LVIR=0.0;
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++)
for (atom = 0; atom < NATOM; atom++)
LVIR += curr_ptr->mol.F[DISP][dir][atom] *
curr_ptr->mol.F[FORCES][dir][atom];
curr_ptr = curr_ptr->next_mol;
} /* while curr_ptr */
curr_box = curr_box->next_box;
} /* while curr_box */
/* Update potential energy */
LOCK(gl->IntrafVirLock);
*VIR = *VIR + LVIR;
UNLOCK(gl->IntrafVirLock);
} /* end of subroutine INTRAF */