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