1 /*****************************************************************************
2  * Copyright (c) 2019 FrontISTR Commons
3  * This software is released under the MIT License, see LICENSE.txt
4  *****************************************************************************/
5 /**
6  * \brief Startup routine for FrontISTR
7  */
8 
9 #include <stdio.h>
10 #include <time.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <FrontISTRConfig.h>
14 #include "hecmw_log.h"
15 #ifndef HECMW_SERIAL
16 #include "mpi.h"
17 #else
18 #include <unistd.h>
19 #endif
20 #ifdef _OPENMP
21 #include <omp.h>
22 #endif /* _OPENMP */
23 
24 extern void fstr_main();
25 
26 /**
27  * \brief struct of command-line option
28  */
29 struct option_rec {
30   char *option_name;
31   void (*func)(char *);
32 };
33 
get_procs_num()34 int get_procs_num(){
35 #ifndef HECMW_SERIAL
36   int proc;
37   MPI_Comm_size(MPI_COMM_WORLD, &proc);
38   return proc;
39 #else
40   return 1;
41 #endif
42 }
print_hostname()43 void print_hostname(){
44   int rank,proc;
45   int name_length = 256;
46   char name[name_length];
47   int ret,i;
48 #ifndef HECMW_SERIAL
49   MPI_Status status;
50   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
51   MPI_Comm_size(MPI_COMM_WORLD, &proc);
52   MPI_Get_processor_name(name, &name_length);
53     if (rank == 0){
54       printf("    %d: %s\n",0,name);
55       for (i=1;i<proc;i++){
56         ret = MPI_Recv(&name, name_length, MPI_CHAR, i, 0, MPI_COMM_WORLD, &status);
57         printf("    %d: %s\n",i,name);
58       }
59     }else{
60       ret = MPI_Send(&name, name_length, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
61     }
62 #else
63   gethostname(name, name_length);
64   printf("    %d: %s\n",0,name);
65 #endif
66 }
get_threads_num()67 int get_threads_num(){
68 #ifdef _OPENMP
69   return omp_get_max_threads();
70 #else
71   return 1;
72 #endif /* _OPENMP */
73 }
74 
75 #ifdef _OPENMP
76 /**
77  * \brief Set number of OpenMP threads
78  */
set_num_threads(char * arg)79 void set_num_threads(char *arg) {
80   int exec_threads;
81 
82   if (arg == NULL) {
83     fprintf(stderr, "Error : specify number of OpenMP threads.\n");
84     fprintf(stderr, "Format: -t <n>\n");
85     exit(1);
86   }
87 
88   exec_threads = atoi(arg);
89 
90   if (exec_threads == 0) {
91     fprintf(stderr, "Error : specify 1 or more OpenMP threads.\n");
92     exit(1);
93   }
94   omp_set_num_threads(exec_threads);
95 }
96 #endif /* _OPENMP */
97 
98 /**
99  * \brief show available command line option
100  */
help(char * arg)101 void help(char *arg) {
102   printf("usage: [ mpirun -np <mpiprocs> ] fistr1 [options] \n");
103   printf(" -h: Show this help message.\n");
104   printf(" -v: Show version.\n");
105 #ifdef _OPENMP
106   printf(" -t <n>: Set number of OpenMP threads\n");
107 #endif
108   printf(" -c <Path of control file>: Use this control file. Default "
109       "./hecmw_ctrl.dat\n");
110   printf("--debug: Show debug messages.\n");
111   exit(0);
112 }
113 
114 /**
115  * \brief show version and revision of FrontISTR
116  */
version(char * arg)117 void version(char *arg) {
118 #ifdef WITH_MPI
119   printf("MPI: Enabled\n");
120 #else
121   printf("MPI: Disabled\n");
122 #endif
123 #ifndef OPENMP_UNKNOWN
124 #ifdef WITH_OPENMP
125   printf("OpenMP: Enabled\n");
126 #else
127   printf("OpenMP: Disabled\n");
128 #endif
129 #else
130   printf("OpenMP: Unknown\n");
131 #endif
132 #ifdef HECMW_METIS_VER
133   printf("HECMW_METIS_VER: %d\n", HECMW_METIS_VER);
134 #endif
135   printf("CompileOption: ");
136 #ifdef WITH_MPI
137   printf("-p ");
138 #endif
139 #ifdef WITH_TOOLS
140   printf("--with-tools ");
141 #endif
142 #ifdef WITH_REFINER
143   printf("--with-refiner ");
144 #endif
145 #ifdef WITH_METIS
146   printf("--with-metis ");
147 #endif
148 #ifdef WITH_MUMPS
149   printf("--with-mumps ");
150 #endif
151 #ifdef WITH_LAPACK
152   printf("--with-lapack ");
153 #endif
154 #ifdef WITH_ML
155   printf("--with-ml ");
156 #endif
157 #ifdef WITH_PARMETIS
158   printf("--with-parmetis ");
159 #endif
160 #ifdef WITH_MKL
161   printf("--with-mkl ");
162 #endif
163   printf("\n");
164   exit(0);
165 }
166 
167 /**
168  * \brief load hecmw_ctrl.dat from specified place
169  */
load_hecmw_ctrl(char * arg)170 void load_hecmw_ctrl(char *arg) {
171   fprintf(stderr, "Sorry this option cannot work yet. (-c)\n");
172   fprintf(stderr, "%s\n", arg);
173   exit(0);
174 }
175 
176 /**
177  * \brief set log level to HECMW_LOG_DEBUG
178  */
set_loglevel_debug(char * arg)179 void set_loglevel_debug(char *arg) {
180   HECMW_setloglv(HECMW_LOG_DEBUG);
181 }
182 
183 /**
184  * \brief specify command line option name and executing function name.
185  * \attension list must be terminated with NULL value.
186  */
187 struct option_rec options[] = {
188   {"-h", help},
189   {"-H", help},
190   {"-v", version},
191   {"-V", version},
192 #ifdef _OPENMP
193   {"-t", set_num_threads},
194   {"-T", set_num_threads},
195 #endif /* _OPENMP */
196   {"-c", load_hecmw_ctrl},
197   {"-C", load_hecmw_ctrl},
198   {"--debug", set_loglevel_debug},
199   {NULL, NULL}
200 };
201 
202 /**
203  * \brief main function
204  */
main(int argc,char * argv[])205 int main(int argc, char *argv[])
206 {
207   char date[64];
208   struct option_rec *p;
209   unsigned int i;
210   int rank=0;
211   time_t t = time(NULL);
212 
213 #ifndef HECMW_SERIAL
214   MPI_Init(&argc, &argv);
215   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
216 #endif
217   if ( rank==0 ){
218     printf("##################################################################\n");
219     printf("#                         FrontISTR                              #\n");
220     printf("##################################################################\n");
221     printf("---\n");
222     if (VERSION_PATCH == 0){
223       printf("version:    %d.%d\n", VERSION_MAJOR,VERSION_MINOR);
224     }else{
225       printf("version:    %d.%d.%d\n", VERSION_MAJOR,VERSION_MINOR, VERSION_PATCH);
226     }
227     printf("git_hash:   %s\n", GIT_HASH );
228     printf("build:\n");
229     printf("  date:     %s\n", BUILD_DATE );
230     printf("  MPI:      ");
231 #ifdef WITH_MPI
232     printf("enabled\n");
233 #else
234     printf("disabled\n");
235 #endif
236     printf("  OpenMP:   ");
237 #ifndef OPENMP_UNKNOWN
238 #ifdef WITH_OPENMP
239     printf("enabled\n");
240 #else
241     printf("disabled\n");
242 #endif
243 #else
244     printf("unknown\n");
245 #endif
246     printf("  option:   ");
247     printf("\"");
248 #ifdef WITH_MPI
249     printf("-p ");
250 #endif
251 #ifdef WITH_TOOLS
252     printf("--with-tools ");
253 #endif
254 #ifdef WITH_REFINER
255     printf("--with-refiner ");
256 #endif
257 #ifdef WITH_METIS
258     printf("--with-metis ");
259 #endif
260 #ifdef WITH_MUMPS
261     printf("--with-mumps ");
262 #endif
263 #ifdef WITH_LAPACK
264     printf("--with-lapack ");
265 #endif
266 #ifdef WITH_ML
267     printf("--with-ml ");
268 #endif
269 #ifdef WITH_PARMETIS
270     printf("--with-parmetis ");
271 #endif
272 #ifdef WITH_MKL
273     printf("--with-mkl ");
274 #endif
275     printf("\"");
276     printf("\n");
277 #ifdef HECMW_METIS_VER
278     printf("  HECMW_METIS_VER: %d\n", HECMW_METIS_VER);
279 #endif
280   }
281 
282   for (i = 0; i < argc; i++) {
283     for (p = options; p->option_name != NULL; p++) {
284       if (strncmp(p->option_name, argv[i], strlen(p->option_name)) == 0) {
285         p->func(argv[i + 1]);
286       }
287     }
288   }
289   if ( rank==0 ){
290     printf("execute:  \n");
291     strftime(date, sizeof(date), "%Y-%m-%dT%H:%M:%S%z", localtime(&t));
292     printf("  date:       %s\n", date);
293     printf("  processes:  %d\n", get_procs_num());
294     printf("  threads:    %d\n", get_threads_num());
295     printf("  cores:      %d\n", get_threads_num()*get_procs_num());
296     printf("  host:\n");
297   }
298   print_hostname();
299   if ( rank==0 ){
300     printf("---\n");
301     printf("...\n");
302   }
303 #ifndef HECMW_SERIAL
304   MPI_Barrier( MPI_COMM_WORLD );
305 #endif
306   fstr_main();
307   return 0;
308 }
309