File: scalarTypes.py

package info (click to toggle)
petsc 3.14.5%2Bdfsg1-4
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 266,472 kB
  • sloc: ansic: 680,898; python: 33,303; cpp: 16,324; makefile: 14,022; f90: 13,731; javascript: 10,713; fortran: 9,581; sh: 1,373; xml: 619; objc: 445; csh: 192; pascal: 148; java: 13
file content (131 lines) | stat: -rwxr-xr-x 6,897 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env python
from __future__ import generators
import config.base

class Configure(config.base.Configure):
  def __init__(self, framework):
    config.base.Configure.__init__(self, framework)
    self.headerPrefix   = ''
    self.substPrefix    = ''
    self.have__float128 = 0
    return

  def __str1__(self):
    output  = '  Scalar type: ' + self.scalartype + '\n'
    output += '  Precision: ' + self.precision + '\n'
    if self.have__float128 and not self.precision == '__float128': output += '  Support for __float128\n'
    return output

  def setupHelp(self, help):
    import nargs
    #  Dec 2016, the __fp16 type is only available with GNU compilers on ARM systems
    help.addArgument('PETSc', '-with-precision=<__fp16,single,double,__float128>', nargs.Arg(None, 'double', 'Specify numerical precision'))
    help.addArgument('PETSc', '-with-scalar-type=<real or complex>', nargs.Arg(None, 'real', 'Specify real or complex numbers'))
    return

  def setupDependencies(self, framework):
    config.base.Configure.setupDependencies(self, framework)
    self.types         = framework.require('config.types', self)
    self.languages     = framework.require('PETSc.options.languages', self)
    self.compilers     = framework.require('config.compilers', self)
    self.libraries     = framework.require('config.libraries',self)
    self.setCompilers  = framework.require('config.setCompilers', self)
    self.compilerFlags = framework.require('config.compilerFlags', self)
    self.types         = framework.require('config.types', self)
    self.headers       = framework.require('config.headers', self)
    self.libraries     = framework.require('config.libraries', self)
    return


  def configureScalarType(self):
    '''Choose between real and complex numbers'''
    self.scalartype = self.framework.argDB['with-scalar-type'].lower()
    if self.scalartype == 'complex':
      self.addDefine('USE_COMPLEX', '1')
      if self.languages.clanguage == 'C' and not self.types.c99_complex:
        raise RuntimeError('C Compiler provided doest not support C99 complex')
      if self.languages.clanguage == 'Cxx' and not self.types.cxx_complex:
        raise RuntimeError('Cxx compiler provided does not support std::complex')
      if self.languages.clanguage == 'Cxx':
        self.addDefine('USE_CXXCOMPLEX',1)
    elif not self.scalartype == 'real':
      raise RuntimeError('--with-scalar-type must be real or complex')
    self.logPrint('Scalar type is '+str(self.scalartype))
    # On apple isinf() and isnan() do not work when <complex> is included
    self.pushLanguage(self.languages.clanguage)
    if self.scalartype == 'complex' and self.languages.clanguage == 'Cxx':
      if self.checkLink('#include <math.h>\n#include <complex>\n','double b = 2.0;int a = isnormal(b);\n'):
        self.addDefine('HAVE_ISNORMAL',1)
      if self.checkLink('#include <math.h>\n#include <complex>\n','double b = 2.0;int a = isnan(b);\n'):
        self.addDefine('HAVE_ISNAN',1)
      elif self.checkLink('#include <float.h>\n#include <complex>\n','double b = 2.0;int a = _isnan(b);\n'):
        self.addDefine('HAVE__ISNAN',1)
      if self.checkLink('#include <math.h>\n#include <complex>\n','double b = 2.0;int a = isinf(b);\n'):
        self.addDefine('HAVE_ISINF',1)
      elif self.checkLink('#include <float.h>\n#include <complex>\n','double b = 2.0;int a = _finite(b);\n'):
        self.addDefine('HAVE__FINITE',1)
    else:
      if self.checkLink('#include <math.h>\n','double b = 2.0; int a = isnormal(b);\n'):
        self.addDefine('HAVE_ISNORMAL',1)
      if self.checkLink('#include <math.h>\n','double b = 2.0; int a = isnan(b);\n'):
        self.addDefine('HAVE_ISNAN',1)
      elif self.checkLink('#include <float.h>\n','double b = 2.0;int a = _isnan(b);\n'):
        self.addDefine('HAVE__ISNAN',1)
      if self.checkLink('#include <math.h>\n','double b = 2.0; int a = isinf(b);\n'):
        self.addDefine('HAVE_ISINF',1)
      elif self.checkLink('#include <float.h>\n','double b = 2.0;int a = _finite(b);\n'):
        self.addDefine('HAVE__FINITE',1)
    self.popLanguage()
    return

  def configurePrecision(self):
    '''Set the default real number precision for PETSc objects'''
    self.log.write('Checking C compiler works with __float128\n')
    self.have__float128 = 0
    if self.libraries.check('quadmath','logq',prototype='#include <quadmath.h>',call='__float128 f; logq(f);'):
      self.log.write('C compiler with quadmath library\n')
      self.have__float128 = 1
      if hasattr(self.compilers, 'FC'):
        self.libraries.pushLanguage('FC')
        self.log.write('Checking Fortran works with quadmath library\n')
        if self.libraries.check('quadmath','     ',call = '      real*16 s,w; w = 2.0 ;s = cos(w)'):
          self.log.write('Fortran works with quadmath library\n')
        else:
          self.have__float128 = 0
          self.log.write('Fortran fails with quadmath library\n')
        self.libraries.popLanguage()
      if self.have__float128:
          self.libraries.add('quadmath','logq',prototype='#include <quadmath.h>',call='__float128 f; logq(f);')
          self.addDefine('HAVE_REAL___FLOAT128', '1')

    self.precision = self.framework.argDB['with-precision'].lower()
    if self.precision == '__fp16':  # supported by gcc trunk
      if self.scalartype == 'complex':
        raise RuntimeError('__fp16 can only be used with real numbers, not complex')
      if hasattr(self.compilers, 'FC'):
        raise RuntimeError('__fp16 can only be used with C compiler, not Fortran')
      self.addDefine('USE_REAL___FP16', '1')
      self.addMakeMacro('PETSC_SCALAR_SIZE', '16')
    elif self.precision == 'single':
      self.addDefine('USE_REAL_SINGLE', '1')
      self.addMakeMacro('PETSC_SCALAR_SIZE', '32')
    elif self.precision == 'double':
      self.addDefine('USE_REAL_DOUBLE', '1')
      self.addMakeMacro('PETSC_SCALAR_SIZE', '64')
    elif self.precision == '__float128':  # supported by gcc 4.6/gfortran and later
      if self.have__float128:
        self.addDefine('USE_REAL___FLOAT128', '1')
        self.addMakeMacro('PETSC_SCALAR_SIZE', '128')
      else:
        raise RuntimeError('__float128 support not found. --with-precision=__float128 works with gcc-4.6 and newer compilers.')
    else:
      raise RuntimeError('--with-precision must be __fp16, single, double, or __float128')
    self.logPrint('Precision is '+str(self.precision))
    if self.precision == '__float128' and self.scalartype == 'complex' and self.languages.clanguage == 'Cxx':
      raise RuntimeError('Cannot use --with-precision=__float128 --with-scalar-type=complex and --with-clanguage=cxx because C++ std:complex class has no support for __float128, use --with-clanguage=c')
    return

  def configure(self):
    self.executeTest(self.configureScalarType)
    self.executeTest(self.configurePrecision)
    return