cuik.c
Go to the documentation of this file.
1 
2 #include "cuiksystem.h"
3 #include "parameters.h"
4 
5 #include "defines.h"
6 #include "error.h"
7 #include "box_list.h"
8 #include "filename.h"
9 #include "random.h"
10 
11 #include <string.h>
12 #include <stdlib.h>
13 #include <time.h>
14 
15 #if (_USE_MPI)
16  #include <mpi.h>
17  #include <unistd.h>
18 #endif
19 
20 
173 int main(int argc, char **arg)
174 {
175  signed int np=1,p=0; /* The default mode is to run in one processor */
176 
177  FILE *f_out; /* File where the solutions are printed as they
178  are found */
179 
180  FILE *f_state; /* File from where we try to recover the execution
181  state of cuik (this is used to continue execution
182  after a crash) */
183 
184  #if (!_QUIET)
185  FILE *f_in; /* Used to read-and-print the equation input
186  file in the output file */
187  #endif
188 
189  Tfilename fcuik;
190  Tfilename fparam;
191  Tfilename fsols;
192  Tfilename fstate;
193 
194  TCuikSystem cuiksystem; /* The set of variables and equations */
195  Tparameters parameters; /* Parameters used in the Cuik process */
196 
197  boolean restart; /* Restart from a state file */
198  unsigned int ri;
199 
200  #if (_USE_MPI)
201  unsigned int i;
202  unsigned int fileflag_in;
203  MPI_Status status;
204  char name[MPI_MAX_PROCESSOR_NAME+1];
205  signed int len;
206 
207  MPI_Init(&argc,&arg);
208 
209  /* Set up a new Error handler */
210  //MPI_Errhandler_set(MPI_COMM_WORLD,MPI_ERRORS_RETURN);
211  MPI_Comm_set_errhandler(MPI_COMM_WORLD,MPI_ERRORS_RETURN);
212 
213  MPI_Comm_rank(MPI_COMM_WORLD,&p); /*number of this process*/
214  MPI_Comm_size(MPI_COMM_WORLD,&np); /*total number of processes*/
215  #endif
216 
217  if (argc>1)
218  {
219  ri=(unsigned int)time(NULL);
220  //ri=1465223267;
221  randomSet(ri);
222 
223  /*Init parameters*/
224  CreateFileName(NULL,arg[1],NULL,PARAM_EXT,&fparam);
225  InitParametersFromFile(GetFileFullName(&fparam),&parameters);
226 
227  /*Read the problem from file*/
228  CreateFileName(NULL,arg[1],NULL,CUIK_EXT,&fcuik);
229  InitCuikSystemFromFile(&parameters,GetFileFullName(&fcuik),&cuiksystem);
230 
231  #if (_USE_MPI)
232  /* Update the cuiksystem for all the processors (in complex files this can
233  take a while and its better to do it before starting to process boxes */
234  VerifyCuikSystem(&parameters,&cuiksystem);
235  #endif
236 
237  /*Check if a state file is available*/
238  if (p==0)
239  {
240  CreateFileName(NULL,arg[1],NULL,STATE_EXT,&fstate);
241  f_state=fopen(GetFileFullName(&fstate),"rb");
242  if (f_state)
243  {
244  restart=TRUE;
245  fclose(f_state);
246  }
247  else
248  restart=FALSE;
249  }
250  else
251  restart=FALSE;
252 
253 
254  /*Check if we can create the output file*/
255  f_out=stdout; /* the default is stdout for all processes.
256  Only process 0 has special output file */
257  if (p==0)
258  {
259  CreateFileName(NULL,arg[1],NULL,SOL_EXT,&fsols);
260  if (restart)
261  f_out=fopen(GetFileFullName(&fsols),"a"); /*append data to an already existing file*/
262  else
263  f_out=fopen(GetFileFullName(&fsols),"w"); /*start a brand new output file*/
264 
265  if (!f_out)
266  Error("Could not open main output file");
267  }
268 
269  #if (!_QUIET)
270  /*While the rest of processors read the parameter file, the
271  first processors stores data about the problem to be solved
272  next in the output file*/
273  if (p==0)
274  {
275  if (restart)
276  {
277  fprintf(f_out,"\n==========================================================================\n");
278  fprintf(f_out,"RESTARTING CUIK FROM A PREVIOUS EXECUTION STATE\n");
279  fprintf(f_out,"WE ASSUME THAT THE .cuik FILE AND THE .param FILE HAVE NOT CHANGED");
280  fprintf(f_out,"\n==========================================================================\n\n");
281  fflush(f_out);
282  }
283  else
284  {
285  fprintf(f_out,"\n==========================================================================\n");
286  fprintf(f_out,"Random seed: %u",ri);
287  fprintf(f_out,"\n==========================================================================\n");
288  PrintParameters(f_out,&parameters);
289 
290  /*Print the description of the problem to be solved*/
291  fprintf(f_out,"\n==========================================================================\n");
292  fprintf(f_out,"Equations from file: %s\n",GetFileFullName(&fcuik));
293  f_in=fopen(GetFileFullName(&fcuik),"r");
294  if (!f_in)
295  Error("Error opening input file");
296  else
297  {
298  int c;
299 
300  do { c=fgetc(f_in); if (c!=EOF) fprintf(f_out,"%c",c); } while(c!=EOF);
301  fclose(f_in);
302  fprintf(f_out,"\n");
303  }
304 
305  fprintf(f_out,"\n==========================================================================\n");
306  PrintCuikSystemWithSimplification(&parameters,f_out,&cuiksystem);
307  fprintf(f_out,"\n==========================================================================\n");
308  }
309  fflush(f_out);
310  }
311  #endif
312 
313  /* The main processors takes care of writing the solutions as they are
314  found by the slaves */
315  if ((p==0)&&(!restart))
316  {
317  fprintf(f_out,"Cuik executed in %u processors\n",np);
318  fprintf(f_out,"SOLUTIONS (to input file %s):\n\n",GetFileFullName(&fcuik));
319  fflush(f_out);
320  }
321 
322  if (np<3) /*single cpu execution -> Do not use parallel cuik*/
323  {
324  if (p==0)
325  SolveCuikSystem(&parameters,restart,GetFileFullName(&fstate),
326  NULL,f_out,NULL,&cuiksystem);
327  }
328  #if (_USE_MPI)
329  else
330  {
331  MPI_Get_processor_name(name,&len);
332 
333  /*Execution on several cpu: one is the master and the rest are slaves*/
334  /*First we wait all the slaves to be ready. We do not want to send out boxes
335  if the slaves are not ready to receive them.*/
336  if (p==0)
337  {
338  fprintf(stdout,"Main scheduler running on %s\n",name);
339  fprintf(stdout,"Waiting all processes to read the param/cuik files\n");
340  fflush(stdout);
341 
342  for(i=1;i<(unsigned int)np;i++)
343  {
344  while ((MPI_Recv(&fileflag_in,1,MPI_UNSIGNED,i,50+i,MPI_COMM_WORLD,&status)!=MPI_SUCCESS)&&
345  (fileflag_in!=i));
346  fprintf(stdout,"Ping from process %u received\n",i);
347  fflush(stdout);
348  }
349 
350  fprintf(stdout,"Starting scheduler\n");
351  fflush(stdout);
352 
353  MPI_SolveCuikSystem(&parameters,restart,GetFileFullName(&fstate),NULL,f_out,&cuiksystem); /* one master */
354  }
355  else
356  {
357  fprintf(stdout,"Starting sub-proces on processor %d running on %s\n",p,name);
358  fflush(stdout);
359  /* Send a signal to the scheduler process (process number 0) indicating
360  that sub-process 'p' is ready to process boxes */
361  MPI_Ssend(&p,1,MPI_UNSIGNED,0,50+p,MPI_COMM_WORLD);
362 
363  MPI_TreatBox(&parameters,&cuiksystem); /* and np-1 slaves */
364 
365  printf("Killing sub-process %u\n",p);
366  fflush(stdout);
367  }
368  }
369  #endif
370 
371  if (p==0)
372  {
373  fprintf(f_out,"END OF THE SOLUTION FILE\n\n");
374  fclose(f_out);
375  }
376 
377  /*Delete the parameters and the equations*/
378  DeleteParameters(&parameters);
379  DeleteCuikSystem(&cuiksystem);
380 
381  DeleteFileName(&fcuik);
382  DeleteFileName(&fparam);
383 
384  if (p==0)
385  {
386  DeleteFileName(&fsols);
387 
388  /*Remove the last state file generated*/
389  remove(GetFileFullName(&fstate));
390  DeleteFileName(&fstate);
391  }
392  }
393  else
394  {
395  if (p==0) /* Only one error message */
396  {
397  fprintf(stderr," Wrong number of parameters.\n");
398  fprintf(stderr," Use:\n");
399  fprintf(stderr," cuik <problem file name>.cuik \n");
400  fprintf(stderr," where <problem file name> contains the kinematic equations\n");
401  fprintf(stderr," (the '.cuik' extension is not required)\n");
402  }
403  }
404 
405  #if (_USE_MPI)
406  MPI_Finalize();
407  #endif
408 
409  return(EXIT_SUCCESS);
410 }
411