gem5/splash2/codes/apps/water-nsquared/initia.C

209 lines
7.7 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 "math.h"
#include "stdio.h"
#include "mdvar.h"
#include "water.h"
#include "cnst.h"
#include "fileio.h"
#include "parameters.h"
#include "mddata.h"
#include "split.h"
#include "global.h"
void INITIA()
{
/* this routine initializes the positions of the molecules along
a regular cubical lattice, and randomizes the initial velocities of
the atoms. The random numbers used in the initialization of velocities
are read from the file random.in, which must be in the current working
directory in which the program is run */
FILE *random_numbers; /* points to input file containing
pseudo-random numbers for initializing
velocities */
double XMAS[4], XT[4], YT[4], Z;
double SUX, SUY, SUZ, SUMX, SUMY, SUMZ, FAC;
long mol=0;
long atom=0;
long deriv;
random_numbers = fopen("random.in","r");
if (random_numbers == NULL) {
fprintf(stderr,"Error in opening file random.in\n");
fflush(stderr);
exit(-1);
}
XMAS[1]=sqrt(OMAS*HMAS);
XMAS[0]=HMAS;
XMAS[2]=HMAS;
/* .....assign positions */
{
double NS = pow((double) NMOL, 1.0/3.0) - 0.00001;
double XS = BOXL/NS;
double ZERO = XS * 0.50;
double WCOS = ROH * cos(ANGLE * 0.5);
double WSIN = ROH * sin(ANGLE * 0.5);
long i,j,k;
printf("\nNS = %.16f\n",NS);
printf("BOXL = %10f\n",BOXL);
printf("CUTOFF = %10f\n",CUTOFF);
printf("XS = %10f\n",XS);
printf("ZERO = %g\n",ZERO);
printf("WCOS = %f\n",WCOS);
printf("WSIN = %f\n",WSIN);
fflush(stdout);
#ifdef RANDOM
/* if we want to initialize to a random distribution of displacements
for the molecules, rather than a distribution along a regular lattice
spaced according to intermolecular distances in water */
srand(1023);
for (i = 0; i < NMOL; i++) {
VAR[mol].F[DISP][XDIR][O] = xrand(0, BOXL);
VAR[mol].F[DISP][XDIR][H1] = VAR[mol].F[DISP][XDIR][O] + WCOS;
VAR[mol].F[DISP][XDIR][H2] = VAR[mol].F[DISP][XDIR][H1];
VAR[mol].F[DISP][YDIR][O] = xrand(0, BOXL);
VAR[mol].F[DISP][YDIR][H1] = VAR[mol].F[DISP][YDIR][O] + WSIN;
VAR[mol].F[DISP][YDIR][H2] = VAR[mol].F[DISP][YDIR][O] - WSIN;
VAR[mol].F[DISP][ZDIR][O] = xrand(0, BOXL);
VAR[mol].F[DISP][ZDIR][H1] = VAR[mol].F[DISP][ZDIR][O];
VAR[mol].F[DISP][ZDIR][H2] = VAR[mol].F[DISP][ZDIR][O];
}
#else
/* not random initial placement, but rather along a regular
lattice. This is the default and the prefered initialization
since random does not necessarily make sense from the viewpoint
of preserving bond distances */
fprintf(six, "***** NEW RUN STARTING FROM REGULAR LATTICE *****\n");
fflush(six);
XT[2] = ZERO;
mol = 0;
for (i=0; i < NS; i+=1) {
XT[1]=XT[2]+WCOS;
XT[3]=XT[1];
YT[2]=ZERO;
for (j=0; j < NS; j+=1) {
YT[1]=YT[2]+WSIN;
YT[3]=YT[2]-WSIN;
Z=ZERO;
for (k = 0; k < NS; k++) {
for (atom = 0; atom < NATOMS; atom +=1) {
VAR[mol].F[DISP][XDIR][atom] = XT[atom+1];
VAR[mol].F[DISP][YDIR][atom] = YT[atom+1];
VAR[mol].F[DISP][ZDIR][atom] = Z;
}
mol += 1;
Z=Z+XS;
}
YT[2]=YT[2]+XS;
}
XT[2]=XT[2]+XS;
}
if (NMOL != mol) {
printf("Lattice init error: total mol %ld != NMOL %ld\n", mol, NMOL);
exit(-1);
}
#endif
}
/* ASSIGN RANDOM MOMENTA */
fscanf(random_numbers,"%lf",&SUX);
SUMX=0.0;
SUMY=0.0;
SUMZ=0.0;
/* read pseudo-random numbers from input file random.in */
for (mol = 0; mol < NMOL; mol++) {
for (atom = 0; atom < NATOMS; atom++) {
fscanf(random_numbers,"%lf",&VAR[mol].F[VEL][XDIR][atom]);
fscanf(random_numbers,"%lf",&VAR[mol].F[VEL][YDIR][atom]);
fscanf(random_numbers,"%lf",&VAR[mol].F[VEL][ZDIR][atom]);
SUMX = SUMX + VAR[mol].F[VEL][XDIR][atom];
SUMY = SUMY + VAR[mol].F[VEL][YDIR][atom];
SUMZ = SUMZ + VAR[mol].F[VEL][ZDIR][atom];
for (deriv = ACC; deriv < MAXODR; deriv++) {
VAR[mol].F[deriv][XDIR][atom] = 0.0;
VAR[mol].F[deriv][YDIR][atom] = 0.0;
VAR[mol].F[deriv][ZDIR][atom] = 0.0;
}
} /* atoms */
} /* molecules */
/* find average momenta per atom */
SUMX=SUMX/(NATOMS*NMOL);
SUMY=SUMY/(NATOMS*NMOL);
SUMZ=SUMZ/(NATOMS*NMOL);
/* find normalization factor so that <k.e.>=KT/2 */
SUX=0.0;
SUY=0.0;
SUZ=0.0;
for (mol = 0; mol < NMOL; mol++) {
SUX = SUX + (pow( (VAR[mol].F[VEL][XDIR][H1] - SUMX),2.0)
+pow( (VAR[mol].F[VEL][XDIR][H2] - SUMX),2.0))/HMAS
+pow( (VAR[mol].F[VEL][XDIR][O] - SUMX),2.0)/OMAS;
SUY = SUY + (pow( (VAR[mol].F[VEL][YDIR][H1] - SUMY),2.0)
+pow( (VAR[mol].F[VEL][YDIR][H2] - SUMY),2.0))/HMAS
+pow( (VAR[mol].F[VEL][YDIR][O] - SUMY),2.0)/OMAS;
SUZ = SUZ + (pow( (VAR[mol].F[VEL][ZDIR][H1] - SUMZ),2.0)
+pow( (VAR[mol].F[VEL][ZDIR][H2] - SUMZ),2.0))/HMAS
+pow( (VAR[mol].F[VEL][ZDIR][O] - SUMZ),2.0)/OMAS;
}
FAC=BOLTZ*TEMP*NATMO/UNITM * pow((UNITT*TSTEP/UNITL),2.0);
SUX=sqrt(FAC/SUX);
SUY=sqrt(FAC/SUY);
SUZ=sqrt(FAC/SUZ);
/* normalize individual velocities so that there are no bulk
momenta */
XMAS[1]=OMAS;
for (mol = 0; mol < NMOL; mol++) {
for (atom = 0; atom < NATOMS; atom++) {
VAR[mol].F[VEL][XDIR][atom] = ( VAR[mol].F[VEL][XDIR][atom] -
SUMX) * SUX/XMAS[atom];
VAR[mol].F[VEL][YDIR][atom] = ( VAR[mol].F[VEL][YDIR][atom] -
SUMY) * SUY/XMAS[atom];
VAR[mol].F[VEL][ZDIR][atom] = ( VAR[mol].F[VEL][ZDIR][atom] -
SUMZ) * SUZ/XMAS[atom];
} /* for atom */
} /* for mol */
fclose(random_numbers);
} /* end of subroutine INITIA */
/*
* XRAND: generate floating-point random number.
*/
double xrand(double xl, double xh)
{
double x;
x=(xl + (xh - xl) * ((double) rand()) / 2147483647.0);
return (x);
}