accelerInt  v0.1
solver_main.c
Go to the documentation of this file.
1 
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <math.h>
16 #include <string.h>
17 #include <stdbool.h>
18 #include <complex.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #ifdef DEBUG
22 #include <fenv.h>
23 #endif
24 
25 //our code
26 #include "header.h"
27 #include "solver.h"
28 #include "timer.h"
30 
31 #ifdef GENERATE_DOCS
32 namespace generic {
33 #endif
34 
47 void write_log(int NUM, double t, const double* y_host, FILE* pFile)
48 {
49  fwrite(&t, sizeof(double), 1, pFile);
50  double buffer[NN];
51  for (int j = 0; j < NUM; j++)
52  {
53  double Y_N = 1.0;
54  buffer[0] = y_host[j];
55  for (int i = 1; i < NSP; ++i)
56  {
57  buffer[i] = y_host[NUM * i + j];
58  Y_N -= buffer[i];
59  }
60  #if NN == NSP + 1 //pyjac
61  buffer[NSP] = Y_N;
62  #endif
63  apply_reverse_mask(&buffer[1]);
64  fwrite(buffer, sizeof(double), NN, pFile);
65  }
66 }
67 
68 
70 
87 int main (int argc, char *argv[])
88 {
89 
90 //enable signaling NAN and other bad numerics tracking for easier debugging
91 #ifdef DEBUG
92  feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
93 #endif
94 
95  int NUM = 1;
96  int num_threads = 1;
97 
99  // OpenMP
101  // set & initialize OpenMP threads via command line argument (if any)
102  #ifdef _OPENMP
103  int max_threads = omp_get_max_threads ();
104  if (argc == 1) {
105  // set to max threads (environment variable)
106  omp_set_num_threads (max_threads);
107  } else {
108  if (argc > 1) {
109  num_threads = max_threads;
110  // first check if is number
111  if (sscanf(argv[1], "%i", &num_threads) !=1 || (num_threads <= 0) || (num_threads > max_threads)) {
112  printf("Error: Number of threads not in correct range\n");
113  printf("Provide number between 1 and %i\n", max_threads);
114  exit(1);
115  }
116  omp_set_num_threads (num_threads);
117  }
118 
119  if (argc > 2) { //check for problem size
120  int problemsize = NUM;
121  if (sscanf(argv[2], "%i", &problemsize) !=1 || (problemsize <= 0))
122  {
123  printf("Error: Problem size not in correct range\n");
124  printf("Provide number greater than 0\n");
125  exit(1);
126  }
127  NUM = problemsize;
128  }
129  }
130 
131  //get max number of threads from OMP
132  num_threads = 0;
133  #pragma omp parallel reduction(+:num_threads)
134  num_threads += 1;
135 
136  #endif
137 
138  // print number of independent ODEs
139  printf ("# ODEs: %d\n", NUM);
140  printf ("# threads: %d\n", num_threads);
141 
142  initialize_solver(num_threads);
143 
145  // arrays
147 
148 #ifdef SHUFFLE
149  const char* filename = "shuffled_data.bin";
150 #elif !defined(SAME_IC)
151  const char* filename = "ign_data.bin";
152 #endif
153 
154  double* y_host;
155  double* var_host;
156 
157 #ifdef SAME_IC
158  set_same_initial_conditions(NUM, &y_host, &var_host);
159 #else
160  read_initial_conditions(filename, NUM, &y_host, &var_host);
161 #endif
162 
163 // flag for ignition
164 #ifdef IGN
165  bool ign_flag = false;
166  // ignition delay time, units [s]
167  double t_ign = 0.0;
168  double T0 = y_host[0];
169 #endif
170 
171 #ifdef LOG_OUTPUT
172  // file for data
173  FILE *pFile;
174  const char* f_name = solver_name();
175  int len = strlen(f_name);
176  char out_name[len + 13];
177  struct stat info;
178  if (stat("./log/", &info) != 0)
179  {
180  printf("Expecting 'log' subdirectory in current working directory. Please run"
181  " mkdir log (or the equivalent) and run again.\n");
182  exit(-1);
183  }
184  sprintf(out_name, "log/%s-log.bin", f_name);
185  pFile = fopen(out_name, "wb");
186 
187  write_log(NUM, 0, y_host, pFile);
188  init_solver_log();
189 #endif
190 
192  // start timer
193  StartTimer();
195 
196  // set initial time
197  double t = 0;
198  double t_next = fmin(end_time, t_step);
199  int numSteps = 0;
200 
201  // time integration loop
202  while (t + EPS < end_time)
203  {
204  numSteps++;
205 
206  intDriver(NUM, t, t_next, var_host, y_host);
207  t = t_next;
208  t_next = fmin(end_time, (numSteps + 1) * t_step);
209 
210 #if defined(PRINT)
211  printf("%.15le\t%.15le\n", t, y_host[0]);
212 #endif
213 #ifdef DEBUG
214  // check if within bounds
215  if ((y_host[0] < 0.0) || (y_host[0] > 10000.0))
216  {
217  printf("Error, out of bounds.\n");
218  printf("Time: %e, ind %d val %e\n", t, 0, y_host[0]);
219  return 1;
220  }
221 #endif
222 #ifdef LOG_OUTPUT
223  #if !defined(LOG_END_ONLY)
224  write_log(NUM, t, y_host, pFile);
225  solver_log();
226  #endif
227 #endif
228 #ifdef IGN
229  // determine if ignition has occurred
230  if ((y_host[0] >= (T0 + 400.0)) && !(ign_flag)) {
231  ign_flag = true;
232  t_ign = t;
233  }
234 #endif
235  }
236 
237 #ifdef LOG_END_ONLY
238  write_log(NUM, t, y_host, pFile);
239  solver_log();
240 #endif
241 
243  // end timer
244  double runtime = GetTimer();
246 
247 
248  runtime /= 1000.0;
249  printf ("Time: %.15e sec\n", runtime);
250  runtime = runtime / ((double)(numSteps));
251  printf ("Time per step: %e (s)\t%.15e (s/thread)\n", runtime, runtime / NUM);
252 #ifdef IGN
253  printf ("Ig. Delay (s): %e\n", t_ign);
254 #endif
255  printf("TFinal: %e\n", y_host[0]);
256 
257 #ifdef LOG_OUTPUT
258  fclose (pFile);
259 #endif
260 
261  free (y_host);
262  free(var_host);
263  cleanup_solver(num_threads);
264 
265  return 0;
266 }
267 
268 #ifdef GENERATE_DOCS
269 }
270 #endif
An example header file that defines system size and other required methods for integration of the van...
#define omp_get_max_threads()
Definition: header.h:16
void intDriver(const int NUM, const double t, const double t_end, const double *pr_global, double *y_global)
Integration driver for the CPU integrators.
#define NSP
The IVP system size.
Definition: header.cuh:20
Timer interface for Linux.
#define t_step
void write_log(int NUM, double t, const double *y_host, FILE *pFile)
Writes state vectors to file.
Definition: solver_main.c:47
int main(int argc, char *argv[])
Definition: solver_main.c:87
void apply_reverse_mask(double *y_host)
Not needed for van der Pol.
Definition: ics.cu:53
void cleanup_solver(int num_threads)
Cleans up the created solvers.
Definition: cvodes_init.c:165
void StartTimer()
Definition: timer.h:43
definition of the generic initial condition reader
void initialize_solver(int num_threads)
Initializes the solver.
Definition: cvodes_init.c:49
void set_same_initial_conditions(int NUM, double **y_host, double **var_host)
Set same ICs for all problems.
Definition: ics.cu:25
Contains skeleton of all methods that need to be defined on a per solver basis.
void solver_log()
Executes solver specific logging tasks.
Definition: cvodes_init.c:192
void init_solver_log()
Initializes solver specific items for logging.
Definition: cvodes_init.c:190
const char * solver_name()
Returns a descriptive solver name.
Definition: cvodes_init.c:181
double GetTimer()
Definition: timer.h:60
Definition: solver.h:19
void read_initial_conditions(const char *filename, int NUM, double **y_host, double **variable_host)
Reads initial conditions for IVPs from binary file.
#define EPS
#define NN
Input vector size (in read_initial_conditions)
Definition: header.cuh:22
#define end_time