cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cpu.cpp
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2013 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
5 #include "cdstd.h"
6 
7 #if defined(__HP_aCC)
8 /* this is for the HP compiler on the sdx */
9 extern "C" unsigned long fegettrapenable();
10 extern "C" void fesettrapenable(unsigned long);
11 #endif
12 
13 #if defined(__ia64) && defined(__INTEL_COMPILER)
14 extern "C" unsigned long fpgetmask();
15 extern "C" void fpsetmask(unsigned long);
16 #endif
17 
18 #if defined(__sun) || defined(__sgi)
19 #include <ieeefp.h>
20 #if defined(HAVE_SUNMATH) || defined(FLUSH_DENORM_TO_ZERO)
21 #include <sunmath.h>
22 #endif
23 #endif
24 
25 #if defined(__alpha) && defined(__linux) && defined(__GNUC__)
26 #define __USE_GNU
27 #include <fenv.h>
28 #endif
29 
30 #if defined(__unix) || defined(__APPLE__)
31 #include <unistd.h>
32 #endif
33 
34 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
35 #include <sys/types.h>
36 #include <sys/sysctl.h>
37 #endif
38 
39 /* the redefinition of float in cddefines.h can cause problems in system headers
40  * hence these includes MUST come after the system header includes above */
41 #include "cddefines.h"
42 #include "cpu.h"
43 #include "path.h"
44 #include "trace.h"
45 
46 STATIC NORETURN void AbortErrorMessage( const char* fname, vector<string>& PathList, access_scheme scheme );
47 
48 // Use Schwartz/nifty counter to ensure that global policy class
49 // is set up before other globals/statics, and deleted last.
51 static int cpu_count = 0;
53 {
54  if (0 == cpu_count++)
55  {
56  m_i = new t_cpu_i;
57  }
58 }
60 {
61  if (0 == --cpu_count)
62  {
63  delete m_i;
64  }
65 }
66 
67 /* NB NB - this constructor needs to be called before any of the user code is executed !! */
69 {
70  DEBUG_ENTRY( "t_cpu_i()" );
71 
72  // set up signal handlers so that we can control what happens...
74 
75  p_exit_status.resize( ES_TOP, "--undefined--" );
76  p_exit_status[ES_SUCCESS] = "ok";
77  p_exit_status[ES_FAILURE] = "early termination";
78  p_exit_status[ES_WARNINGS] = "warnings";
79  p_exit_status[ES_BOTCHES] = "botched monitors";
80  p_exit_status[ES_CLOUDY_ABORT] = "cloudy abort";
81  p_exit_status[ES_BAD_ASSERT] = "failed assert";
82  p_exit_status[ES_BAD_ALLOC] = "failed memory alloc";
83  p_exit_status[ES_OUT_OF_RANGE] = "array bound exceeded";
84  p_exit_status[ES_USER_INTERRUPT] = "user interrupt";
85  p_exit_status[ES_TERMINATION_REQUEST] = "process killed";
86  p_exit_status[ES_ILLEGAL_INSTRUCTION] = "illegal instruction";
87  p_exit_status[ES_FP_EXCEPTION] = "fp exception";
88  p_exit_status[ES_SEGFAULT] = "segmentation fault";
89  p_exit_status[ES_BUS_ERROR] = "bus error";
90  p_exit_status[ES_UNKNOWN_SIGNAL] = "unknown signal";
91  p_exit_status[ES_UNKNOWN_EXCEPTION] = "unknown exception";
92 
93  /* >>chng 05 dec 14, add test of endianness of the CPU, PvH */
94  endian.c[0] = 0x12;
95  endian.c[1] = 0x34;
96  endian.c[2] = 0x56;
97  endian.c[3] = 0x78;
98 
99  /* >>chng 05 dec 15, add signaling NaN for float and double to cpu struct, PvH */
100  /* in C++ this should be replaced by numeric_limits<TYPE>::signaling_NaN() */
101  if( sizeof(sys_float) == 4 )
102  {
103 # ifdef __mips
104  /* definition of signaling and quiet NaN is reversed on MIPS */
105  Float_SNaN_Value = 0xffffffff;
106 # else
107  if( big_endian() || little_endian() )
108  {
109  /* this should work on most modern CPU's */
110  Float_SNaN_Value = 0xffbfffff;
111  }
112  else
113  {
114  /* this is an unusual CPU -> bit pattern for SNaN is unknown */
115  Float_SNaN_Value = -1;
116  }
117 # endif
118  }
119  else
120  {
121  /* this is an unusual CPU -> bit pattern for SNaN is unknown */
122  Float_SNaN_Value = -1;
123  }
124 
125 # ifdef HAVE_INT64
126 
127  if( sizeof(double) == 8 )
128  {
129 # ifdef __mips
130  /* definition of signaling and quiet NaN is reversed on MIPS */
131  Double_SNaN_Value = 0xffffffffffffffff;
132 # else
133  /* this should work on most modern CPU's */
134  Double_SNaN_Value = 0xfff7ffffffbfffff;
135 # endif
136  }
137  else
138  {
139  /* this is an unusual CPU -> bit pattern for SNaN is unknown */
140  Double_SNaN_Value = -1;
141  }
142 
143 # else
144 
145  if( sizeof(double) == 8 )
146  {
147 # ifdef __mips
148  /* definition of signaling and quiet NaN is reversed on MIPS */
149  Double_SNaN_Value[0] = 0xffffffff;
150  Double_SNaN_Value[1] = 0xffffffff;
151 # else
152  if( big_endian() )
153  {
154  /* this should work on most modern CPU's */
155  Double_SNaN_Value[0] = 0xfff7ffff;
156  Double_SNaN_Value[1] = 0xffbfffff;
157  }
158  else if( little_endian() )
159  {
160  /* this should work on most modern CPU's */
161  Double_SNaN_Value[0] = 0xffbfffff;
162  Double_SNaN_Value[1] = 0xfff7ffff;
163  }
164  else
165  {
166  /* this is an unusual CPU -> bit pattern for SNaN is unknown */
167  Double_SNaN_Value[0] = -1;
168  Double_SNaN_Value[1] = -1;
169  }
170 # endif
171  }
172  else
173  {
174  /* this is an unusual CPU -> bit pattern for SNaN is unknown */
175  Double_SNaN_Value[0] = -1;
176  Double_SNaN_Value[1] = -1;
177  }
178 
179 # endif
180 
181  /* set FP environment to trap FP exceptions */
182  enable_traps();
183 
184  ioStdin = stdin;
185  ioQQQ = stdout;
186  ioPrnErr = stderr;
187  lgPrnErr = false;
188 
189  test_float = FLT_MIN;
190  test_double = DBL_MIN;
191 
192  /* default is for failed asserts not to abort */
193  p_lgAssertAbort = false;
194 
195  const char *str;
196 
197  /* determine the no. of CPUs on this machine; used by PHYMIR, grid command, .... */
198 # if defined(_SC_NPROCESSORS_ONLN) /* Linux, Sun Sparc, DEC Alpha, MacOS (OS releases >= 10.4) */
199  n_avail_CPU = sysconf(_SC_NPROCESSORS_ONLN);
200 # elif defined(_SC_NPROC_ONLN) /* SGI Iris */
201  n_avail_CPU = sysconf(_SC_NPROC_ONLN);
202 # elif defined(_SC_CRAY_NCPU) /* Cray */
203  n_avail_CPU = sysconf(_SC_CRAY_NCPU);
204 # elif defined(_WIN32) /* Microsoft Windows */
205  str = getenv( "NUMBER_OF_PROCESSORS" );
206  if( str != NULL )
207  {
208  int found = sscanf( str, "%ld", &n_avail_CPU );
209  if( found != 1 )
210  n_avail_CPU = 1;
211  }
212  else
213  {
214  n_avail_CPU = 1;
215  }
216 # elif defined(HW_AVAILCPU) /* MacOS, BSD variants */
217  int mib[2];
218  size_t len = sizeof(n_avail_CPU);
219  mib[0] = CTL_HW;
220  mib[1] = HW_AVAILCPU; // alternatively, try HW_NCPU;
221  sysctl(mib, 2, &n_avail_CPU, &len, NULL, 0);
222  if( n_avail_CPU < 1 )
223  {
224  mib[1] = HW_NCPU;
225  sysctl(mib, 2, &n_avail_CPU, &len, NULL, 0);
226  if( n_avail_CPU < 1 )
227  n_avail_CPU = 1;
228  }
229 # else
230  /* Other systems, supply no. of CPUs on OPTIMIZE PHYMIR command line */
231  n_avail_CPU = 1;
232 # endif
233  /* the constructor is run before MPI starts, so the rank is not available yet */
234 # ifdef MPI_ENABLED
235  p_lgMPI = true;
236 # else
237  p_lgMPI = false;
238 # endif
239  /* the default is for all ranks to cooperate on the same sim */
240  p_lgMPISingleRankMode = false;
241  n_rank = 0;
242 
243 # ifdef _WIN32
244  str = getenv( "COMPUTERNAME" );
245 # else
246  str = getenv( "HOSTNAME" );
247 # endif
248 
249  if( str != NULL )
250  strncpy( HostName, str, STDLEN );
251  else
252  strncpy( HostName, "unknown", STDLEN );
253  HostName[STDLEN-1] = '\0';
254 
255  /* pick up the path from the environment, if set by user */
256  const char *path = getenv( "CLOUDY_DATA_PATH" );
257 
258  /* if the environment variable was not set, the default set in path.h takes effect */
259  string chSearchPathRaw = ( path != NULL ) ? string( path ) : string( CLOUDY_DATA_PATH );
260 
261 # ifdef _WIN32
262  string separator( ";" );
263  p_chDirSeparator = '\\';
264 # else
265  string separator( ":" );
266  p_chDirSeparator = '/';
267 # endif
268 
269  chSearchPath.push_back( "" ); // the current working directory should be first and last
270  Split( chSearchPathRaw, separator, chSearchPath, SPM_RELAX );
271  chSearchPath.push_back( "" );
272 
273  for( vector<string>::size_type i=0; i < chSearchPath.size(); ++i )
274  {
275  if( chSearchPath[i].length() > 0 )
276  {
277  /* get last valid char */
278  char chEnd = *chSearchPath[i].rbegin();
279 
280  /* make sure path ends with directory separator */
281  if( chEnd != p_chDirSeparator )
283  }
284  }
285 
286  nFileDone = 0;
287 }
288 
290 {
291  /* >>chng 01 aug 07, added code to circumvent math library bug with g++ on
292  * alpha-linux machines, see bug report 51072 on http://bugzilla.redhat.com, PvH */
293  /* >>chng 01 apr 17, added code for Solaris and SGI operating systems, PvH */
294  /* this routine contains no code for alphas or crays, they do not need
295  * special code to enable FP exceptions since they are enabled by default */
296 
297  /* there is no command line option on MS Visual Studio to force crash */
298 # if defined(_MSC_VER)
299  volatile unsigned int NewMask;
300 
301  /* | is a bitwise inclusive or, turns on bits
302  * 0|0 = 0
303  * 0|1 = 1|0 = 1|1 = 1 */
304  NewMask = _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_INVALID;
305  /* ~ is the unary bitwise complement - all bits flip */
306  NewMask = ~NewMask;
307  _controlfp( NewMask , _MCW_EM );
308 
309  /* this is the code for Linux PC (but not Linux alpha) to force crash */
310  /* >>chng 04 apr 26, added support for AMD64, enable FPE traps for SSE/SSE2, PvH */
311  /* >>chng 06 aug 12, added support for Apple MacOSX, and hopefully also Solaris x86, PvH */
312 # elif defined(__GNUC__) && ( defined(__i386) || defined(__amd64) )
313  volatile unsigned int Old_Mask, New_Mask;
314 # if defined(__SSE__) || defined(__SSE2__)
315  volatile unsigned int SSE_Mask;
316 # endif
317 
318 # define _FPU_MASK_IM 0x01 /* Invalid */
319 # define _FPU_MASK_DM 0x02 /* Denormalized */
320 # define _FPU_MASK_ZM 0x04 /* Division-by-zero */
321 # define _FPU_MASK_OM 0x08 /* Overflow */
322 # define _FPU_MASK_UM 0x10 /* Underflow */
323 # define _FPU_MASK_PM 0x20 /* Inexact */
324 
325  /* | is a bitwise inclusive or, turns on bits */
326  /* 0|0 = 0 */
327  /* 0|1 = 1|0 = 1|1 = 1 */
328 
329  /* ~ is the unary bitwise complement - all bits flip */
330 
331  /* this enables FPE traps for regular i387 FP instructions */
332 
333  volatile unsigned int UnMask = ~((unsigned int)( _FPU_MASK_ZM | _FPU_MASK_IM | _FPU_MASK_OM ));
334 
335  __asm__ volatile("fnstcw %0" : "=m" (*&Old_Mask));
336 
337  New_Mask = Old_Mask & UnMask;
338 
339  __asm__ volatile("fldcw %0" : : "m" (*&New_Mask));
340 
341 # if defined(__SSE__) || defined(__SSE2__)
342 
343 # if defined(FLUSH_DENORM_TO_ZERO)
344  /* using this causes denormalized numbers to be flushed to zero,
345  * which will speed up the code on Pentium 4 processors */
346  SSE_Mask = 0x9900;
347 # else
348  /* this version allows denormalized numbers to be retained */
349  SSE_Mask = 0x1900;
350 # endif
351 
352  /* this enables FPE traps for SSE/SSE2 instructions */
353 
354  __asm__ volatile( "ldmxcsr %0" : : "m" (*&SSE_Mask) );
355 
356 # endif
357 
358  /* this is for IA64 systems running g++ or icc (e.g. SGI, HP, ...) */
359 # elif defined(__ia64)
360 
361 # define FPSR_TRAP_VD (1 << 0) /* invalid op trap disabled */
362 # define FPSR_TRAP_DD (1 << 1) /* denormal trap disabled */
363 # define FPSR_TRAP_ZD (1 << 2) /* zero-divide trap disabled */
364 # define FPSR_TRAP_OD (1 << 3) /* overflow trap disabled */
365 # define FPSR_TRAP_UD (1 << 4) /* underflow trap disabled */
366 # define FPSR_TRAP_ID (1 << 5) /* inexact trap disabled */
367 
368 # define FPSR_SF0_FTZ (1 << 6) /* flush denormalized numbers to zero */
369 
370 # if defined(__GNUC_EXCL__)
371  /* __asm__ instructions are not supported by icc as of v9.0 */
372 # define _IA64_REG_AR_FPSR 40
373 
374 # define ia64_getreg( regnum ) __asm__ volatile( "mov %0=ar%1" : "=r" (fpsr) : "i"(regnum) )
375 # define ia64_setreg( regnum, val ) __asm__ volatile( "mov ar%0=%1" :: "i" (regnum), "r"(val): "memory" )
376 # define ia64_serialize __asm__ volatile( "srlz.i" );
377 
378  volatile unsigned long fpsr, flags = FPSR_TRAP_VD | FPSR_TRAP_ZD | FPSR_TRAP_OD;
379 
380  ia64_getreg( _IA64_REG_AR_FPSR );
381  fpsr &= ~flags;
382 # if defined(FLUSH_DENORM_TO_ZERO)
383  fpsr |= FPSR_SF0_FTZ;
384 # endif
385  ia64_setreg( _IA64_REG_AR_FPSR, fpsr );
386  /* this prevents RAW and WAW dependency violations in case this ever gets inlined... */
387  ia64_serialize;
388 
389 # elif defined(__INTEL_COMPILER)
390  /* this is for icc on IA64 SGI machines */
391  unsigned long fpsr = fpgetmask();
392  fpsr |= FPSR_TRAP_VD | FPSR_TRAP_ZD | FPSR_TRAP_OD;
393  fpsetmask( fpsr );
394 # elif defined(__HP_aCC)
395  /* this is for the HP compiler on the sdx */
396  unsigned long fpsr = fegettrapenable();
397  fpsr |= FPSR_TRAP_VD | FPSR_TRAP_ZD | FPSR_TRAP_OD;
398  fesettrapenable( fpsr );
399 # endif /* defined(__GNUC_EXCL__) */
400 
401  /* this is for Solaris and SGI to force crash */
402 # elif defined(__sun) || defined(__sgi)
403 
404  fp_except mask;
405 
406  /* >>chng 05 dec 30, accept FLUSH_DENORM_TO_ZERO as a synonym for HAVE_SUNMATH, PvH */
407 # if defined(HAVE_SUNMATH) || defined(FLUSH_DENORM_TO_ZERO)
408 
409  /* >>chng 01 oct 09, disable gradual underflow on ultrasparc whith g++
410  * (only needed for versions < 3.1 or >= 4.3.0, see Note 1).
411  *
412  * compile this module with:
413  * g++ [ other options... ] -I<include-dir> -DHAVE_SUNMATH -c cpu.cpp
414  * link the program with:
415  * g++ -L<library-dir> -o cloudy.exe *.o -lsunmath
416  *
417  * you probably need to use -I<include-dir> and -L<library-dir> to point the
418  * compiler/linker to the location of the sunmath.h header file and libsunmath.so
419  * library (e.g., -I/opt/SUNWspro/prod/include/cc -L/opt/SUNWspro/lib; note that
420  * the actual location may vary from one installation to another).
421  * See also bug report 4487 on http://gcc.gnu.org/bugzilla/
422  *
423  * Note 1: Starting with g++ 3.1, bug 4487 has been solved: -funsafe-math-optimizations
424  * will automatically disable gradual underflow. Hence using nonstandard_arithmetic()
425  * is no longer necessary. The option -funsafe-math-optimizations should be included
426  * both when compiling and linking:
427  *
428  * g++ [ other options... ] -funsafe-math-optimizations -c *.c
429  * g++ [ other options... ] -funsafe-math-optimizations -o cloudy.exe *.o
430  *
431  * Starting with g++ 4.3.0 the -funsafe-math-optimizations option can no longer be
432  * used as it implicitly enables -fno-trapping-math, which is unsafe for Cloudy
433  * because we do trap floating point exceptions.
434  *
435  * Note 2: Don't use nonstandard_arithmetic() with CC (the SunWorks/Forte compiler);
436  * use the -fast commandline option instead to disable gradual underflow (or use
437  * -fnonstd if you don't want all the other options enabled by -fast). The option
438  * -fast (or -fnonstd) should be included both when compiling and linking:
439  *
440  * CC [ other options... ] -fast -c *.c
441  * CC -fast -o cloudy.exe *.o
442  *
443  * PvH */
444  nonstandard_arithmetic();
445 # endif
446 
447  /* enable floating point exceptions on sun and sgi */
448  mask = fpgetmask();
449  mask = mask | FP_X_INV | FP_X_OFL | FP_X_DZ;
450  fpsetmask(mask);
451 
452 # elif defined(__alpha) && defined(__linux) && defined(__GNUC__)
453 
454  /* the following is not supported on all hardware platforms, but certainly for EV56
455  * and later. earlier versions may work as well, but that has not been tested.
456  * for details see https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=51072 */
457 # ifdef FE_NONIEEE_ENV
458  /* this prevents the infamous math library bug when compiling with gcc on alpha-linux
459  * machines. if this doesn't work on your system, the only alternative is to link
460  * against the Compaq math library: gcc *.o -lcpml -lm, or use ccc itself, PvH */
461  fesetenv(FE_NONIEEE_ENV);
462 # endif
463 
464 # endif
465  return;
466 }
467 
469 {
470  DEBUG_ENTRY( "set_signal_handlers()" );
471 
472 #ifdef CATCH_SIGNAL
473 # ifdef __unix
474  p_action.sa_handler = &signal_handler;
475  sigemptyset( &p_action.sa_mask );
476  p_action.sa_flags = SA_NODEFER;
477 
478  p_default.sa_handler = SIG_DFL;
479  sigemptyset( &p_default.sa_mask );
480  p_default.sa_flags = SA_NODEFER;
481 
482  for( int sig=1; sig <= 31; sig++ )
483  {
484  // is the signal valid?
485  if( sigaction( sig, NULL, NULL ) == 0 )
486  // these two are for suspending and resuming a job
487  if( sig != SIGSTOP && sig != SIGCONT )
488  sigaction( sig, action(), NULL );
489  }
490 # endif
491 
492 # ifdef _MSC_VER
493  signal( SIGABRT, &signal_handler );
494  signal( SIGFPE, &signal_handler );
495  signal( SIGILL, &signal_handler );
496  signal( SIGINT, &signal_handler );
497  signal( SIGSEGV, &signal_handler );
498  signal( SIGTERM, &signal_handler );
499 # endif
500 #endif
501 }
502 
504 {
505  // when an FPE is caught, the mask is reset...
506  cpu.i().enable_traps();
507 # ifdef _MSC_VER
508  // at this point the signal handler has reverted to the default handler
509  signal( sig, &signal_handler );
510 # endif
511  throw bad_signal( sig );
512 }
513 
514 
516 {
517  fprintf(ioQQQ, "The path is:\n");
518  for( vector<string>::size_type i=1; i < chSearchPath.size()-1; ++i )
519  fprintf( ioQQQ, " ==%s==\n", chSearchPath[i].c_str() );
520 }
521 
522 // this routine generates a list of all full paths to the locations where we should look for the file
523 void t_cpu_i::getPathList( const char* fname, vector<string>& PathList, access_scheme scheme ) const
524 {
525  DEBUG_ENTRY( "getPathList()" );
526 
527  vector<string>::size_type begin, end;
528 
529  switch( scheme )
530  {
531  case AS_DATA_ONLY:
532  case AS_DATA_ONLY_TRY:
533  case AS_DATA_OPTIONAL:
534  begin = 1;
535  end = cpu.i().chSearchPath.size()-1;
536  break;
537  case AS_DATA_LOCAL:
538  case AS_DATA_LOCAL_TRY:
539  begin = 1;
540  end = cpu.i().chSearchPath.size();
541  break;
542  case AS_LOCAL_DATA:
543  case AS_LOCAL_DATA_TRY:
544  begin = 0;
545  end = cpu.i().chSearchPath.size()-1;
546  break;
547  case AS_LOCAL_ONLY:
548  case AS_LOCAL_ONLY_TRY:
549  case AS_SILENT_TRY:
550  begin = 0;
551  end = 1;
552  break;
553  default:
554  TotalInsanity();
555  }
556 
557  PathList.clear();
558  string FileName( fname );
559  for( vector<string>::size_type i=begin; i < end; ++i )
560  PathList.push_back( cpu.i().chSearchPath[i] + FileName );
561 }
562 
563 STATIC NORETURN void AbortErrorMessage( const char* fname, vector<string>& PathList, access_scheme scheme )
564 {
565  DEBUG_ENTRY( "AbortErrorMessage()" );
566 
567  if( scheme == AS_DATA_OPTIONAL )
568  // presence is optional -> make warning less scary...
569  fprintf( ioQQQ, "\nI could not open the data file %s\n\n", fname );
570  else
571  fprintf( ioQQQ, "\nPROBLEM DISASTER I could not open the data file %s\n\n", fname );
572  if( cpu.i().firstOpen() || scheme == AS_DATA_ONLY )
573  {
574  // failed on very first open -> most likely path is not correct
575  // failed on AS_DATA_ONLY -> CLOUDY_DATA_PATH may point to obsolete data dir
576  fprintf( ioQQQ, "Although there may be other reasons you have received this error,\n");
577  fprintf( ioQQQ, "the most likely are that the path has not been properly set\n");
578  fprintf( ioQQQ, "or that the path points to an old version of the data.\n\n");
579  fprintf( ioQQQ, "Please have a look at the file path.h in the source directory\n");
580  fprintf( ioQQQ, "to check how the variable CLOUDY_DATA_PATH is set - \n");
581  fprintf( ioQQQ, "it should give the location of the data files I need.\n");
582  fprintf( ioQQQ, "These are the files in the data download from the web site.\n\n");
583  fprintf( ioQQQ, "Recompile the code with the correct data path set in path.h\n");
584  fprintf( ioQQQ, "or use the shell command \nexport CLOUDY_DATA_PATH=\"/path/to/data\"\n to set the\n");
585  fprintf( ioQQQ, "path from a bash command prompt.\n\n");
586  cpu.i().printDataPath();
587  }
588  else
589  {
590  // failed on search including local directory -> most likely the file name
591  // was mistyped on a compile command, or Cloudy is run in the wrong directory
592  // if scheme == AS_DATA_OPTIONAL, this most likely is a stellar grid that is not installed.
593  fprintf( ioQQQ, "These are all the paths I tried:\n" );
594  for( vector<string>::const_iterator ptr=PathList.begin(); ptr != PathList.end(); ++ptr )
595  fprintf( ioQQQ, " ==%s==\n", ptr->c_str() );
596  // AS_DATA_OPTIONAL files should provide their own message (currently only stellar grids)
597  if( scheme != AS_DATA_OPTIONAL )
598  {
599  fprintf( ioQQQ, "\nAlthough there may be other reasons you have received this error,\n");
600  fprintf( ioQQQ, "the most likely are that you mistyped the file name, or that you\n");
601  fprintf( ioQQQ, "are running Cloudy in the wrong directory. If you are running a\n");
602  fprintf( ioQQQ, "COMPILE command, this needs to be done in the data directory.\n\n");
603  fprintf( ioQQQ, "Otherwise, please have a look at the file path.h in the source\n");
604  fprintf( ioQQQ, "directory to check how the variable CLOUDY_DATA_PATH is set - \n");
605  fprintf( ioQQQ, "it should give the location of the data files I need.\n");
606  fprintf( ioQQQ, "These are the files in the data download from the web site.\n\n");
607  fprintf( ioQQQ, "Recompile the code with the correct data path set in path.h\n");
608  fprintf( ioQQQ, "or use the shell command \nexport CLOUDY_DATA_PATH=\"/path/to/data\"\n to set the\n");
609  fprintf( ioQQQ, "path from a bash command prompt.\n\n");
610  }
611  }
612  fprintf(ioQQQ, "Sorry.\n\n\n");
614 }
615 
616 FILE* open_data( const char* fname, const char* mode, access_scheme scheme )
617 {
618  DEBUG_ENTRY( "open_data()" );
619 
620  bool lgAbort = ( scheme == AS_DATA_ONLY || scheme == AS_DATA_OPTIONAL || scheme == AS_DATA_LOCAL ||
621  scheme == AS_LOCAL_DATA || scheme == AS_LOCAL_ONLY );
622 
623  vector<string> PathList;
624  cpu.i().getPathList( fname, PathList, scheme );
625 
626  FILE* handle = NULL;
627  vector<string>::const_iterator ptr;
628  for( ptr=PathList.begin(); ptr != PathList.end() && handle == NULL; ++ptr )
629  {
630  handle = fopen( ptr->c_str(), mode );
631  if( trace.lgTrace && scheme != AS_SILENT_TRY )
632  fprintf( ioQQQ, " open_data trying %s mode %s handle %p\n", ptr->c_str(), mode, handle );
633  }
634 
635  if( handle == NULL && lgAbort )
636  AbortErrorMessage( fname, PathList, scheme );
637 
638  ++cpu.i().nFileDone;
639 
640  return handle;
641 }
642 
643 void open_data( fstream& stream, const char* fname, ios_base::openmode mode, access_scheme scheme )
644 {
645  DEBUG_ENTRY( "open_data()" );
646 
647  bool lgAbort = ( scheme == AS_DATA_ONLY || scheme == AS_DATA_OPTIONAL || scheme == AS_DATA_LOCAL ||
648  scheme == AS_LOCAL_DATA || scheme == AS_LOCAL_ONLY );
649 
650  vector<string> PathList;
651  cpu.i().getPathList( fname, PathList, scheme );
652 
653  ASSERT( !stream.is_open() );
654  vector<string>::const_iterator ptr;
655  for( ptr=PathList.begin(); ptr != PathList.end() && !stream.is_open(); ++ptr )
656  {
657  stream.open( ptr->c_str(), mode );
658  if( trace.lgTrace && scheme != AS_SILENT_TRY )
659  fprintf( ioQQQ, " open_data trying %s succes? %c\n", ptr->c_str(), TorF(stream.is_open()) );
660  }
661 
662  if( !stream.is_open() && lgAbort )
663  AbortErrorMessage( fname, PathList, scheme );
664 
665  ++cpu.i().nFileDone;
666 }
667 
674 {
675  if( sizeof(sys_float) == 4 )
676  *reinterpret_cast<int32*>(&x) = cpu.i().Float_SNaN_Value;
677  else
678  x = -FLT_MAX;
679 }
680 
681 void set_NaN(sys_float x[], /* x[n] */
682  long n)
683 {
684  long i;
685 
686  if( sizeof(sys_float) == 4 )
687  {
688  int32 *y = reinterpret_cast<int32*>(x);
689  for( i=0; i < n; i++ )
690  *y++ = cpu.i().Float_SNaN_Value;
691  }
692  else
693  {
694  for( i=0; i < n; i++ )
695  x[i] = -FLT_MAX;
696  }
697 }
698 
699 void set_NaN(double &x)
700 {
701  if( sizeof(double) == 8 )
702  {
703 # ifdef HAVE_INT64
704  *reinterpret_cast<int64*>(&x) = cpu.i().Double_SNaN_Value;
705 # else
706  int32 *y = reinterpret_cast<int32*>(&x);
707  *y++ = cpu.i().Double_SNaN_Value[0];
708  *y = cpu.i().Double_SNaN_Value[1];
709 # endif
710  }
711  else
712  x = -DBL_MAX;
713 }
714 
715 /* set_NaN - set NaN */
716 void set_NaN(double x[], /* x[n] */
717  long n)
718 {
719  long i;
720 
721  if( sizeof(double) == 8 )
722  {
723 # ifdef HAVE_INT64
724  int64 *y = reinterpret_cast<int64*>(x);
725  for( i=0; i < n; i++ )
726  *y++ = cpu.i().Double_SNaN_Value;
727 # else
728  int32 *y = reinterpret_cast<int32*>(x);
729  for( i=0; i < n; i++ )
730  {
731  *y++ = cpu.i().Double_SNaN_Value[0];
732  *y++ = cpu.i().Double_SNaN_Value[1];
733  }
734 # endif
735  }
736  else
737  {
738  for( i=0; i < n; i++ )
739  x[i] = -DBL_MAX;
740  }
741 }
742 
744 bool MyIsnan(const sys_float &x)
745 {
746  if( sizeof(sys_float) == 4 && FLT_MAX_EXP-FLT_MIN_EXP+3 == 256 )
747  {
748  const int32 *p = reinterpret_cast<const int32*>(&x);
749  int32 r = *p & 0x7f800000; r ^= 0x7f800000;
750  int32 s = *p & 0x007fffff;
751  return ( r == 0 && s != 0 );
752  }
753  else
754  /* we don't understand this CPU */
755  return false;
756 }
757 
759 bool MyIsnan(const double &x)
760 {
761  if( sizeof(double) == 8 && DBL_MAX_EXP-DBL_MIN_EXP+3 == 2048 )
762  {
763 # ifdef HAVE_INT64
764  const int64 *p = reinterpret_cast<const int64*>(&x);
765  int64 r = *p & 0x7ff0000000000000; r ^= 0x7ff0000000000000;
766  int64 s = *p & 0x000fffffffffffff;
767  return ( r == 0 && s != 0 );
768 # else
769  const int32 *p = reinterpret_cast<const int32*>(&x);
770  if( cpu.i().little_endian() )
771  {
772  int32 r = p[1] & 0x7ff00000; r ^= 0x7ff00000;
773  int32 s = p[1] & 0x000fffff; s |= p[0];
774  return ( r == 0 && s != 0 );
775  }
776  else if( cpu.i().big_endian() )
777  {
778  int32 r = p[0] & 0x7ff00000; r ^= 0x7ff00000;
779  int32 s = p[0] & 0x000fffff; s |= p[1];
780  return ( r == 0 && s != 0 );
781  }
782  else
783  /* we don't understand this CPU */
784  return false;
785 # endif
786  }
787  else
788  /* we don't understand this CPU */
789  return false;
790 }
long n_rank
Definition: cpu.h:256
FILE * open_data(const char *fname, const char *mode, access_scheme scheme)
Definition: cpu.cpp:616
static void signal_handler(int sig)
Definition: cpu.cpp:503
void getPathList(const char *fname, vector< string > &PathList, access_scheme scheme) const
Definition: cpu.cpp:523
#define NORETURN
Definition: cpu.h:370
bool p_lgMPISingleRankMode
Definition: cpu.h:254
NORETURN void TotalInsanity(void)
Definition: service.cpp:886
double test_double
Definition: cpu.h:229
union t_cpu_i::@3 endian
void set_NaN(sys_float &x)
Definition: cpu.cpp:673
t_cpu_i & i()
Definition: cpu.h:334
int32 Double_SNaN_Value[2]
Definition: cpu.h:235
char TorF(bool l)
Definition: cddefines.h:714
access_scheme
Definition: cpu.h:194
Definition: cpu.h:218
const int STDLEN
Definition: cpu.h:184
static t_cpu_i * m_i
Definition: cpu.h:332
bool big_endian() const
Definition: cpu.h:274
bool MyIsnan(const sys_float &x)
Definition: cpu.cpp:744
FILE * ioQQQ
Definition: cddefines.cpp:7
STATIC NORETURN void AbortErrorMessage(const char *fname, vector< string > &PathList, access_scheme scheme)
Definition: cpu.cpp:563
char HostName[STDLEN]
Definition: cpu.h:258
bool little_endian() const
Definition: cpu.h:275
~t_cpu()
Definition: cpu.cpp:59
t_trace trace
Definition: trace.cpp:5
long n_avail_CPU
Definition: cpu.h:247
void Split(const string &str, const string &sep, vector< string > &lst, split_mode mode)
Definition: service.cpp:106
#define STATIC
Definition: cddefines.h:101
bool lgTrace
Definition: trace.h:12
int nFileDone
Definition: cpu.h:263
#define EXIT_FAILURE
Definition: cddefines.h:144
float sys_float
Definition: cddefines.h:110
t_cpu_i()
Definition: cpu.cpp:68
void printDataPath() const
Definition: cpu.cpp:515
int32 Float_SNaN_Value
Definition: cpu.h:231
bool firstOpen() const
Definition: cpu.h:319
#define cdEXIT(FAIL)
Definition: cddefines.h:438
char p_chDirSeparator
Definition: cpu.h:262
vector< string > p_exit_status
Definition: cpu.h:268
static int cpu_count
Definition: cpu.cpp:51
#define ASSERT(exp)
Definition: cddefines.h:582
FILE * ioPrnErr
Definition: cddefines.cpp:9
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:688
void set_signal_handlers()
Definition: cpu.cpp:468
bool p_lgAssertAbort
Definition: cpu.h:244
bool lgPrnErr
Definition: cddefines.cpp:13
int32 i
Definition: cpu.h:225
void enable_traps() const
Definition: cpu.cpp:289
sys_float test_float
Definition: cpu.h:228
static t_cpu cpu
Definition: cpu.h:342
bool p_lgMPI
Definition: cpu.h:249
vector< string > chSearchPath
Definition: cpu.h:260
t_cpu()
Definition: cpu.cpp:52
bool lgAbort
Definition: cddefines.cpp:10
FILE * ioStdin
Definition: cddefines.cpp:8