changed reading hint
[gromacs/adressmacs.git] / src / gmxlib / main.c
blobabe483679755c8a814dffdc953ef7097f153cd88
1 /*
2 * $Id$
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 2.0
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
16 * Please refer to:
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
23 * or e-mail to:
24 * gromacs@chem.rug.nl
26 * And Hey:
27 * Green Red Orange Magenta Azure Cyan Skyblue
29 static char *SRCID_main_c = "$Id$";
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <limits.h>
35 #include "smalloc.h"
36 #include "fatal.h"
37 #include "network.h"
38 #include "main.h"
39 #include "macros.h"
40 #include "futil.h"
41 #include "filenm.h"
43 #define BUFSIZE 1024
45 FILE *stdlog=NULL;
46 int gmx_parallel=0;
48 static void mem_init(void)
50 #ifdef _860_
51 void *p;
52 unsigned long avail;
54 avail=maxavail();
55 if ((p=malloc(avail))==NULL)
56 fatal_error(errno,"mem init");
57 else
59 memset(p,0,avail);
60 free(p);
62 #endif
65 static int get_pid(FILE *log,int left,int right,int *pid,int *nprocs)
67 * The ring of processors is only defined by the interconnection
68 * via the supplied communication channels (left and right). Thus
69 * it is not defined what the (hardware) processor id's are in the
70 * ring. To be independent of the processor id assignment (to allow
71 * procesor switching without modifying a processor id) this routine
72 * determines the processor id and the number of processors. On entry
73 * pid needs to be set to an unique value in the system and nprocs
74 * needs to be set to the maximum number of processors in the system.
75 * The lowest pid in the ring will then get the value 0 assigned. The
76 * rest is then assigned by incrementing processor id's to the right
77 * until the ring is closed. The function returns 1 in case it succeeded
78 * in determining the values for pid and nprocs, else it returns 0. If
79 * the hardware does not implement a ring structure this will hang the
80 * system!
83 int i,pids[MAXPROC],min_index,min_pid,send_pid,receive_pid;
85 *nprocs=0;
86 send_pid=*pid;
87 min_pid=send_pid;
88 min_index=*nprocs;
89 do {
90 #ifdef DEBUGPAR
91 fprintf(log,"Sending: %d\n",send_pid);
92 #endif
93 gmx_tx(left,record(send_pid));
94 gmx_rx(right,record(receive_pid));
95 gmx_tx_wait(left);
96 gmx_rx_wait(right);
97 #ifdef DEBUGPAR
98 fprintf(log,"Received: %d\n",receive_pid);
99 #endif
100 if (send_pid<min_pid) {
101 min_pid=send_pid;
102 min_index=*nprocs;
104 pids[(*nprocs)++]=send_pid;
105 send_pid=receive_pid;
106 } while (receive_pid!=*pid);
108 #ifdef DEBUGPAR
109 fprintf(log,"min_index=%d\n",min_index);
110 fprintf(log,"nprocs =%d\n",*nprocs);
111 fprintf(log,"pid =%d\n",*pid);
112 #endif
114 for (i=min_index; (*pid)!=pids[i%(*nprocs)]; i++)
116 (*pid)=(i-min_index+(*nprocs))%(*nprocs);
117 #ifdef DEBUGPAR
118 fprintf(log,"min_index=%d\n",min_index);
119 fprintf(log,"nprocs =%d\n",*nprocs);
120 fprintf(log,"pid =%d\n",*pid);
121 for (i=0; i<(*nprocs); i++) {
122 fprintf(log,"%d translated %d --> %d",
123 i,pids[i],(i-min_index+(*nprocs))%(*nprocs));
124 if (pids[i]==(*pid))
125 fprintf(log," *");
126 fprintf(log,"\n");
128 #endif
129 return 1;
132 char *par_fn(char *base,int ftp,t_commrec *cr)
134 static char buf[256];
136 /* Copy to buf, and strip extension */
137 strcpy(buf,base);
138 buf[strlen(base)-4] = '\0';
140 /* Add processor info */
141 if (PAR(cr))
142 sprintf(buf+strlen(buf),"%d",cr->pid);
143 strcat(buf,".");
145 /* Add extension again */
146 strcat(buf,(ftp == efTPX) ? "tpr" : (ftp == efENX) ? "edr" : ftp2ext(ftp));
148 return buf;
151 void open_log(char *lognm,t_commrec *cr)
153 int len,testlen,pid;
154 char *buf,*host;
156 debug_gmx();
158 /* Communicate the filename for logfile */
159 if (cr->nprocs > 1) {
160 if (MASTER(cr)) {
161 len = strlen(lognm)+1;
162 gmx_txs(cr->right,record(len));
163 gmx_rxs(cr->left,record(testlen));
165 debug_gmx();
167 gmx_txs(cr->right,lognm,len);
168 gmx_rxs(cr->left,lognm,len);
169 if (len != testlen)
170 fatal_error(0,"Communication error on PROC 0!");
173 else {
174 gmx_rxs(cr->left,record(len));
175 debug_gmx();
177 gmx_txs(cr->right,record(len));
178 snew(lognm,len);
179 gmx_rxs(cr->left,lognm,len);
180 gmx_txs(cr->right,lognm,len);
184 debug_gmx();
186 /* Since log always ends with '.log' let's use this info */
187 buf = par_fn(lognm,efLOG,cr);
188 stdlog = ffopen(buf,"w");
190 /* Get some machine parameters */
191 host = getenv("HOST");
192 #ifndef NO_GETPID
193 pid = getpid();
194 #else
195 pid = 0;
196 #endif
197 fprintf(stdlog,"Log file opened: pid %d, nprocs = %d, host = %s, process = %d\n",
198 cr->pid,cr->nprocs,host ? host : "unknown",pid);
199 fflush(stdlog);
200 debug_gmx();
203 static void comm_args(t_commrec *cr,int *argc,char ***argv)
205 int i,len;
206 char **argv_tmp=NULL,*buf;
208 if (!MASTER(cr))
209 *argc=0;
210 gmx_sumi(1,argc,cr);
212 if (!MASTER(cr))
213 snew(argv_tmp,*argc+1);
214 fprintf(stderr,"PID=%d argc=%d\n",cr->pid,*argc);
215 for(i=0; (i<*argc); i++) {
216 if (MASTER(cr)) {
217 len = strlen((*argv)[i])+1;
218 gmx_txs(cr->right,&len,sizeof(len));
219 gmx_rxs(cr->left,&len,sizeof(len));
220 gmx_txs(cr->right,(*argv)[i],len);
221 snew(buf,len);
222 gmx_rxs(cr->left,buf,len);
223 if (strcmp(buf,(*argv)[i]) != 0)
224 fatal_error(0,"Communicating argv[%d]=%s\n",i,(*argv)[i]);
225 sfree(buf);
227 else {
228 gmx_rxs(cr->left,&len,sizeof(len));
229 gmx_txs(cr->right,&len,sizeof(len));
230 snew(argv_tmp[i],len);
231 gmx_rxs(cr->left,argv_tmp[i],len);
232 gmx_txs(cr->right,argv_tmp[i],len);
235 if (!MASTER(cr)) {
236 argv_tmp[*argc] = NULL;
237 *argv = argv_tmp;
239 debug_gmx();
242 t_commrec *init_par(int *argc,char ***argv_ptr)
244 t_commrec *cr;
245 char **argv;
246 int i;
248 argv = *argv_ptr;
249 snew(cr,1);
251 cr->nprocs=1;
252 /* Get the number of processors.
253 * This is useless for newer MPI versions.
255 for(i=0; (argv[i] != NULL); i++) {
256 if (strcmp(argv[i],"-np")==0)
257 if (argv[i+1]!=NULL)
258 cr->nprocs=atoi(argv[i+1]);
261 #ifdef USE_MPI
262 gmx_parallel = 1;
263 #ifdef _SGI_
264 if (getenv("MPI_ENVIRONMENT") == NULL)
265 gmx_parallel = 0;
266 #endif
267 if (gmx_parallel)
268 cr->pid=mpiio_setup(argc,argv,&cr->nprocs);
269 else
270 cr->pid=0;
271 #else
272 cr->pid=0;
273 if (cr->nprocs > 1) {
274 gmx_parallel = 1;
275 #ifdef USE_PVM3
276 cr->pid=pvmio_setup(argv,cr->nprocs);
277 #else
278 cr->pid=gmx_cpu_id();
279 #endif
281 #endif
283 #ifdef _amb_
284 pageMode(1);
285 #endif
286 mem_init();
288 if (!PAR(cr) && (cr->pid != 0))
289 fatal_error(0,"(!PAR(cr) && (cr->pid != 0))");
291 if (PAR(cr)) {
292 gmx_left_right(cr->nprocs,cr->pid,&cr->left,&cr->right);
293 #ifdef DEBUGPAR
294 fprintf(stderr,"Going to initialise network\n");
295 #endif
297 #ifndef USE_PVM3
298 #ifdef DEBUGPAR
299 fprintf(stderr,"Initialised network\n");
300 fprintf(stderr,"Getting new processor id's\n");
301 #endif
302 if (get_pid(stderr,cr->left,cr->right,&cr->pid,&cr->nprocs)==0)
303 fatal_error(0,"could not get pid & nprocs from ring topology");
304 #ifdef DEBUGPAR
305 fprintf(stderr,"Got new processor id's\n");
306 fprintf(stderr,"nprocs=%d, pid=%d\n",cr->nprocs,cr->pid);
307 #endif
309 #endif
312 /* Communicate arguments if parallel */
313 if (PAR(cr))
314 comm_args(cr,argc,argv_ptr);
316 return cr;