int main(int argc, char **argv) { /* default values for the control parameters of the driver */ /* are in parameters.h */ if ((argc == 2) && ((strncmp(argv[1],"-h",strlen("-h")) == 0) || (strncmp(argv[1],"-H",strlen("-H")) == 0))) { printf("Usage: WATER-SPATIAL < infile, where the contents of infile can be\nobtained from the comments at the top of water.C and the first scanf \nin main() in water.C\n\n"); exit(0); } #else int main(void) { #endif /* POSSIBLE ENHANCEMENT: One might bind the first process to a processor here, even before the other (child) processes are bound later in mdmain(). */ six = stdout; TEMP =298.0; RHO =0.9980; /* read input */ #ifndef SIM_SOCLIB if (scanf("%lf%ld%ld%ld%ld%ld%ld%ld%ld%lf",&TSTEP, &NMOL, &NSTEP, &NORDER, &NSAVE, &NRST, &NPRINT, &NFMC,&NumProcs, &CUTOFF) != 10) fprintf(stderr,"ERROR: Usage: water < infile, which must have 10 fields, see SPLASH documentation or comment at top of water.C\n"); #else TSTEP = 1.5e-16; NMOL = NMOLS; NSTEP = 3; NORDER = 6; NSAVE = -1 ; NRST = 3000 ; NPRINT = 3 ; NFMC = 0; NumProcs = NB_P; CUTOFF = 6.212752; #endif printf("Using %ld procs on %ld steps of %ld mols\n", NumProcs, NSTEP, NMOL); printf("Other parameters:\n\tTSTEP = %8.2e\n\tNORDER = %ld\n\tNSAVE = %ld\n",TSTEP,NORDER,NSAVE); printf("\tNRST = %ld\n\tNPRINT = %ld\n\tNFMC = %ld\n\tCUTOFF = %lf\n\n",NRST,NPRINT,NFMC,CUTOFF); /* set up scaling factors and constants */ NORD1=NORDER+1; CNSTNT(NORD1,TLC); /* sub. call to set up constants */ SYSCNS(); /* sub. call to initialize system constants */ printf("%ld boxes with %ld processors\n\n", BOX_PER_SIDE * BOX_PER_SIDE * BOX_PER_SIDE, NumProcs); if (NumProcs > (BOX_PER_SIDE * BOX_PER_SIDE * BOX_PER_SIDE)) { fprintf(stderr,"ERROR: less boxes (%ld) than processors (%ld)\n", BOX_PER_SIDE * BOX_PER_SIDE * BOX_PER_SIDE, NumProcs); fflush(stderr); exit(-1); } fprintf(six,"\nTEMPERATURE = %8.2f K\n",TEMP); fprintf(six,"DENSITY = %8.5f G/C.C.\n",RHO); fprintf(six,"NUMBER OF MOLECULES = %8ld\n",NMOL); fprintf(six,"NUMBER OF PROCESSORS = %8ld\n",NumProcs); fprintf(six,"TIME STEP = %8.2e SEC\n",TSTEP); fprintf(six,"ORDER USED TO SOLVE F=MA = %8ld \n",NORDER); fprintf(six,"NO. OF TIME STEPS = %8ld \n",NSTEP); fprintf(six,"FREQUENCY OF DATA SAVING = %8ld \n",NSAVE); fprintf(six,"FREQUENCY TO WRITE RST FILE= %8ld \n",NRST); fflush(six); { /* do memory initializations */ long procnum, i, j, k, l; struct list_of_boxes *temp_box; long xprocs, yprocs, zprocs; long x_inc, y_inc, z_inc; long x_ct, y_ct, z_ct; long x_left, y_left, z_left; long x_first, y_first, z_first; long x_last, y_last, z_last; double proccbrt; long gmem_size = sizeof(struct GlobalMemory); MAIN_INITENV((NumProcs),40000000,); /* macro call to initialize shared memory etc. */ /* Allocate space for main (BOX) data structure as well as * synchronization variables */ start_end = (first_last_array **) G_MALLOC(sizeof(first_last_array *) * NumProcs); for (i=0; i < NumProcs; i++) { start_end[i] = (first_last_array *) G_MALLOC(sizeof(first_last_array)); } /* Calculate start and finish box numbers for processors */ xprocs = 0; yprocs = 0; proccbrt = (double) pow((double) NumProcs, 1.0/3.0) + 0.00000000000001; j = (long) proccbrt; if (j<1) j = 1; while ((xprocs == 0) && (j>0)) { k = (long) sqrt((double) (NumProcs / j)); if (k<1) k=1; while ((yprocs == 0) && (k>0)) { l = NumProcs/(j*k); if ((j*k*l) == NumProcs) { xprocs = j; yprocs = k; zprocs = l; } /* if */ k--; } /* while yprocs && k */ j--; } /* while xprocs && j */ printf("xprocs = %ld\typrocs = %ld\tzprocs = %ld\n", xprocs, yprocs, zprocs); fflush(stdout); /* Fill in start_end array values */ procnum = 0; x_inc = BOX_PER_SIDE/xprocs; y_inc = BOX_PER_SIDE/yprocs; z_inc = BOX_PER_SIDE/zprocs; x_left = BOX_PER_SIDE - (xprocs*x_inc); y_left = BOX_PER_SIDE - (yprocs*y_inc); z_left = BOX_PER_SIDE - (zprocs*z_inc); printf("x_inc = %ld\t y_inc = %ld\t z_inc = %ld\n",x_inc,y_inc,z_inc); printf("x_left = %ld\t y_left = %ld\t z_left = %ld\n",x_left,y_left,z_left); fflush(stdout); x_first = 0; x_ct = x_left; x_last = -1; x_inc++; for (i=0; i<xprocs; i++) { y_ct = y_left; if (x_ct == 0) x_inc--; x_last += x_inc; y_first = 0; y_last = -1; y_inc++; for (j=0; j<yprocs; j++) { z_ct = z_left; if (y_ct == 0) y_inc--; y_last += y_inc; z_first = 0; z_last = -1; z_inc++; for (k=0; k<zprocs; k++) { if (z_ct == 0) z_inc--; z_last += z_inc; start_end[procnum]->box[XDIR][FIRST] = x_first; start_end[procnum]->box[XDIR][LAST] = min(x_last, BOX_PER_SIDE - 1); start_end[procnum]->box[YDIR][FIRST] = y_first; start_end[procnum]->box[YDIR][LAST] = min(y_last, BOX_PER_SIDE - 1); start_end[procnum]->box[ZDIR][FIRST] = z_first; start_end[procnum]->box[ZDIR][LAST] = min(z_last, BOX_PER_SIDE - 1); z_first = z_last + 1; z_ct--; procnum++; } y_first = y_last + 1; y_ct--; } x_first = x_last + 1; x_ct--; } /* Allocate space for my_boxes array */ my_boxes = (box_list **) G_MALLOC(NumProcs * sizeof(box_list *)); /* Set all box ptrs to null */ for (i=0; i<NumProcs; i++) my_boxes[i] = NULL; /* Set up links for all boxes for initial interf and intraf */ temp_box = my_boxes[0]; while (temp_box) { temp_box = temp_box->next_box; } /* Allocate space for BOX array */ BOX = (box_type ***) G_MALLOC(BOX_PER_SIDE * sizeof(box_type **)); for (i=0; i < BOX_PER_SIDE; i++) { BOX[i] = (box_type **) G_MALLOC( BOX_PER_SIDE * sizeof(box_type *)); for (j=0; j < BOX_PER_SIDE; j++) { BOX[i][j] = (box_type *) G_MALLOC(BOX_PER_SIDE * sizeof(box_type)); for (k=0; k < BOX_PER_SIDE; k++) { BOX[i][j][k].list = NULL; LOCKINIT(BOX[i][j][k].boxlock); } } } /* for i */ gl = (struct GlobalMemory *) G_MALLOC(gmem_size); /* macro calls to initialize synch variables */ BARINIT(gl->start, NumProcs); BARINIT(gl->InterfBar, NumProcs); BARINIT(gl->PotengBar, NumProcs); LOCKINIT(gl->IOLock); LOCKINIT(gl->IndexLock); LOCKINIT(gl->IntrafVirLock); LOCKINIT(gl->InterfVirLock); LOCKINIT(gl->KinetiSumLock); LOCKINIT(gl->PotengSumLock); } fprintf(six,"SPHERICAL CUTOFF RADIUS = %8.4f ANGSTROM\n",CUTOFF); fflush(six); IRST=0; /* call initialization routine */ INITIA(); gl->tracktime = 0; gl->intratime = 0; gl->intertime = 0; /* initialize Index to 1 so that the first created child gets id 1, not 0 */ gl->Index = 1; if (NSAVE > 0) { /* not true for input decks provided */ fprintf(six,"COLLECTING X AND V DATA AT EVERY %4ld TIME STEPS \n",NSAVE); } /* spawn helper processes */ CLOCK(gl->computestart); CREATE(WorkStart, NumProcs); /* macro to make main process wait for all others to finish */ WAIT_FOR_END(NumProcs); CLOCK(gl->computeend); printf("COMPUTESTART (after initialization) = %lu\n",gl->computestart); printf("COMPUTEEND = %lu\n",gl->computeend); printf("COMPUTETIME (after initialization) = %lu\n",gl->computeend-gl->computestart); printf("Measured Time (2nd timestep onward) = %lu\n",gl->tracktime); printf("Intramolecular time only (2nd timestep onward) = %lu\n",gl->intratime); printf("Intermolecular time only (2nd timestep onward) = %lu\n",gl->intertime); printf("Other time (2nd timestep onward) = %lu\n",gl->tracktime - gl->intratime - gl->intertime); printf("\nExited Happily with XTT = %g (note: XTT value is garbage if NPRINT > NSTEP)\n", XTT); MAIN_END; } /* main.c */
int main(int argc, char **argv) { /* default values for the control parameters of the driver */ /* are in parameters.h */ if ((argc == 2) &&((strncmp(argv[1],"-h",strlen("-h")) == 0) || (strncmp(argv[1],"-H",strlen("-H")) == 0))) { printf("Usage: WATER-NSQUARED < infile, where the contents of infile can be\nobtained from the comments at the top of water.C and the first scanf \nin main() in water.C\n\n"); exit(0); } /* POSSIBLE ENHANCEMENT: Here's where one might bind the main process (process 0) to a processor if one wanted to. Others can be bound in the WorkStart routine. */ six = stdout; /* output file */ TEMP =298.0; RHO =0.9980; CUTOFF=0.0; /* read input */ if (scanf("%lf%ld%ld%ld%ld%ld%ld%ld%ld%lf",&TSTEP, &NMOL, &NSTEP, &NORDER, &NSAVE, &NRST, &NPRINT, &NFMC,&NumProcs, &CUTOFF) != 10) fprintf(stderr,"ERROR: Usage: water < infile, which must have 10 fields, see SPLASH documentation or comment at top of water.C\n"); if (NMOL > MAXLCKS) { fprintf(stderr, "Just so you know ... Lock array in global.H has size %ld < %ld (NMOL)\n code will still run correctly but there may be lock contention\n\n", MAXLCKS, NMOL); } printf("Using %ld procs on %ld steps of %ld mols\n", NumProcs, NSTEP, NMOL); printf("Other parameters:\n\tTSTEP = %8.2e\n\tNORDER = %ld\n\tNSAVE = %ld\n",TSTEP,NORDER,NSAVE); printf("\tNRST = %ld\n\tNPRINT = %ld\n\tNFMC = %ld\n\tCUTOFF = %lf\n\n",NRST,NPRINT,NFMC,CUTOFF); /* SET UP SCALING FACTORS AND CONSTANTS */ NORD1=NORDER+1; CNSTNT(NORD1,TLC); /* sub. call to set up constants */ { /* Do memory initializations */ long pid; long mol_size = sizeof(molecule_type) * NMOL; long gmem_size = sizeof(struct GlobalMemory); /* POSSIBLE ENHANCEMENT: One might bind the first process to a processor here, even before the other (child) processes are bound later in mdmain(). */ MAIN_INITENV(,70000000,); /* macro call to initialize shared memory etc. */ THREAD_INIT_FREE(); /* allocate space for main (VAR) data structure as well as synchronization variables */ /* POSSIBLE ENHANCEMENT: One might want to allocate a process's portion of the VAR array and what it points to in its local memory */ VAR = (molecule_type *) G_MALLOC(mol_size); gl = (struct GlobalMemory *) G_MALLOC(gmem_size); /* POSSIBLE ENHANCEMENT: One might want to allocate process i's PFORCES[i] array in its local memory */ PFORCES = (double ****) G_MALLOC(NumProcs * sizeof (double ***)); { long i,j,k; for (i = 0; i < NumProcs; i++) { PFORCES[i] = (double ***) G_MALLOC(NMOL * sizeof (double **)); for (j = 0; j < NMOL; j++) { PFORCES[i][j] = (double **) G_MALLOC(NDIR * sizeof (double *)); for (k = 0; k < NDIR; k++) { PFORCES[i][j][k] = (double *) G_MALLOC(NATOM * sizeof (double)); } } } } /* macro calls to initialize synch varibles */ BARINIT(gl->start, NumProcs); BARINIT(gl->InterfBar, NumProcs); BARINIT(gl->PotengBar, NumProcs); LOCKINIT(gl->IOLock); LOCKINIT(gl->IndexLock); LOCKINIT(gl->IntrafVirLock); LOCKINIT(gl->InterfVirLock); LOCKINIT(gl->FXLock); LOCKINIT(gl->FYLock); LOCKINIT(gl->FZLock); if (NMOL < MAXLCKS) { ALOCKINIT(gl->MolLock, NMOL); } else { ALOCKINIT(gl->MolLock, MAXLCKS); } LOCKINIT(gl->KinetiSumLock); LOCKINIT(gl->PotengSumLock); /* set up control for static scheduling */ MolsPerProc = NMOL/NumProcs; StartMol[0] = 0; for (pid = 1; pid < NumProcs; pid += 1) { StartMol[pid] = StartMol[pid-1] + MolsPerProc; } StartMol[NumProcs] = NMOL; } SYSCNS(); /* sub. call to initialize system constants */ fprintf(six,"\nTEMPERATURE = %8.2f K\n",TEMP); fprintf(six,"DENSITY = %8.5f G/C.C.\n",RHO); fprintf(six,"NUMBER OF MOLECULES = %8ld\n",NMOL); fprintf(six,"NUMBER OF PROCESSORS = %8ld\n",NumProcs); fprintf(six,"TIME STEP = %8.2e SEC\n",TSTEP); fprintf(six,"ORDER USED TO SOLVE F=MA = %8ld \n",NORDER); fprintf(six,"NO. OF TIME STEPS = %8ld \n",NSTEP); fprintf(six,"FREQUENCY OF DATA SAVING = %8ld \n",NSAVE); fprintf(six,"FREQUENCY TO WRITE RST FILE= %8ld \n",NRST); fprintf(six,"SPHERICAL CUTOFF RADIUS = %8.4f ANGSTROM\n",CUTOFF); fflush(six); /* initialization routine; also reads displacements and sets up random velocities*/ INITIA(); /*.....start molecular dynamic loop */ gl->tracktime = 0; gl->intratime = 0; gl->intertime = 0; /* initialize Index to 1 so that the first created child gets id 1, not 0 */ gl->Index = 1; if (NSAVE > 0) /* not true for input decks provided */ fprintf(six,"COLLECTING X AND V DATA AT EVERY %4ld TIME STEPS \n",NSAVE); /* spawn helper processes, each getting its unique process id */ CLOCK(gl->computestart); CREATE(WorkStart, NumProcs); /* macro to make main process wait for all others to finish */ WAIT_FOR_END(NumProcs); CLOCK(gl->computeend); printf("COMPUTESTART (after initialization) = %lu\n",gl->computestart); printf("COMPUTEEND = %lu\n",gl->computeend); printf("COMPUTETIME (after initialization) = %lu\n",gl->computeend-gl->computestart); printf("Measured Time (2nd timestep onward) = %lu\n",gl->tracktime); printf("Intramolecular time only (2nd timestep onward) = %lu\n",gl->intratime); printf("Intermolecular time only (2nd timestep onward) = %lu\n",gl->intertime); printf("Other time (2nd timestep onward) = %lu\n",gl->tracktime - gl->intratime - gl->intertime); printf("\nExited Happily with XTT = %g (note: XTT value is garbage if NPRINT > NSTEP)\n", XTT); MAIN_END; } /* main.c */