xref: /petsc/config/BuildSystem/config/packages/MUMPS.py (revision 9a2cd68e563fb69dfcb2578ce58f7db064c2e0fb)
1import config.package
2
3class Configure(config.package.Package):
4  def __init__(self, framework):
5    config.package.Package.__init__(self, framework)
6    self.version          = '5.5.1-p1'
7    self.minversion       = '5.2.1'
8    self.versionname      = 'MUMPS_VERSION'
9    self.requiresversion  = 1
10    self.gitcommit        = 'v'+self.version
11    self.download         = ['http://ftp.mcs.anl.gov/pub/petsc/externalpackages/MUMPS_'+self.version+'.tar.gz']
12    self.downloaddirnames = ['petsc-pkg-mumps','MUMPS']
13    self.buildLanguages   = ['C','FC']
14    self.precisions       = ['single','double']
15    self.downloadonWindows= 1
16    self.hastests         = 1
17    self.hastestsdatafiles= 1
18    return
19
20  def setupHelp(self, help):
21    import nargs
22    config.package.Package.setupHelp(self, help)
23    help.addArgument('MUMPS', '-with-mumps-serial', nargs.ArgBool(None, 0, 'Use serial build of MUMPS'))
24    return
25
26  def setupDependencies(self, framework):
27    config.package.Package.setupDependencies(self, framework)
28    self.flibs            = framework.require('config.packages.flibs',self)
29    self.blasLapack       = framework.require('config.packages.BlasLapack',self)
30    self.mpi              = framework.require('config.packages.MPI',self)
31    self.metis            = framework.require('config.packages.metis',self)
32    self.parmetis         = framework.require('config.packages.parmetis',self)
33    self.ptscotch         = framework.require('config.packages.PTScotch',self)
34    self.scalapack        = framework.require('config.packages.scalapack',self)
35    self.hwloc            = framework.require('config.packages.hwloc',self)
36    self.openmp           = framework.require('config.packages.openmp',self)
37    self.scalartypes      = framework.require('PETSc.options.scalarTypes',self)
38    if self.argDB['with-mumps-serial']:
39      self.deps           = [self.blasLapack,self.flibs]
40      self.odeps          = [self.metis,self.openmp]
41    else:
42      self.deps           = [self.scalapack,self.mpi,self.blasLapack,self.flibs]
43      self.odeps          = [self.metis,self.parmetis,self.ptscotch,self.hwloc,self.openmp]
44    return
45
46  def configureLibrary(self):
47    for arg in ['with-64-bit-blas-indices','known-64-bit-blas-indices']:
48      if self.argDB.get(arg):
49        raise RuntimeError('MUMPS cannot be used with %s' % arg)
50    if self.scalartypes.precision == 'single':
51      if self.scalartypes.scalartype == 'real': l = 's'
52      else: l = 'c'
53    else:
54      if self.scalartypes.scalartype == 'real': l = 'd'
55      else: l = 'z'
56    self.functions = [l+'mumps_c']
57    self.includes  = [l+'mumps_c.h']
58    liblist_common = [['libmumps_common.a','libpord.a','libpthread.a'],
59                     ['libmumps_common.a','libpord.a'],
60                     ['libmumps_common.a','libpord.a','libmpiseq.a'],
61                     ['libmumps_common.a','libpord.a','libpthread.a','libmpiseq.a']]
62    self.liblist   = []
63    for libc in liblist_common:
64       self.liblist.append(['lib'+l+'mumps.a'] + libc)
65    config.package.Package.configureLibrary(self)
66
67  def consistencyChecks(self):
68    config.package.Package.consistencyChecks(self)
69    if self.argDB['with-'+self.package] or self.argDB['download-'+self.package]:
70      if self.mpi.usingMPIUni and not self.argDB['with-mumps-serial']:
71        raise RuntimeError('Since you are building without MPI you must use --with-mumps-serial to install the correct MUMPS.')
72    if self.argDB['with-mumps-serial']:
73      if not self.mpi.usingMPIUni:
74        raise RuntimeError('Serial MUMPS version is only compatible with MPIUni\nReconfigure using --with-mpi=0')
75    return
76
77  def Install(self):
78    import os
79
80    if self.openmp.found:
81      #  MUMPS has no make flags for turning on/off OpenMP it just uses it if it can
82      self.usesopenmp = 'yes'
83      # use OMP_NUM_THREADS to control the number of threads used
84
85    if not self.fortran.FortranDefineCompilerOption:
86      raise RuntimeError('Fortran compiler cannot handle preprocessing directives from command line.')
87    g = open(os.path.join(self.packageDir,'Makefile.inc'),'w')
88    g.write('LPORDDIR   = $(topdir)/PORD/lib/\n')
89    g.write('IPORD      = -I$(topdir)/PORD/include/\n')
90    g.write('LPORD      = -L$(LPORDDIR) -lpord\n')
91    g.write('PLAT       = \n')
92    orderingsc = '-Dpord'
93    orderingsf = self.fortran.FortranDefineCompilerOption+'pord'
94    # Disable threads on BGL
95    if self.libraries.isBGL():
96      orderingsc += ' -DWITHOUT_PTHREAD'
97    if self.metis.found:
98      g.write('IMETIS = '+self.headers.toString(self.metis.include)+'\n')
99      g.write('LMETIS = '+self.libraries.toString(self.metis.lib)+'\n')
100      orderingsc += ' -Dmetis'
101      orderingsf += ' '+self.fortran.FortranDefineCompilerOption+'metis'
102    if self.parmetis.found:
103      g.write('IPARMETIS = '+self.headers.toString(self.parmetis.include)+'\n')
104      g.write('LPARMETIS = '+self.libraries.toString(self.parmetis.lib)+'\n')
105      orderingsc += ' -Dparmetis'
106      orderingsf += ' '+self.fortran.FortranDefineCompilerOption+'parmetis'
107    if self.ptscotch.found:
108      g.write('ISCOTCH = '+self.headers.toString(self.ptscotch.include)+'\n')
109      g.write('LSCOTCH = '+self.libraries.toString(self.ptscotch.lib)+'\n')
110      orderingsc += ' -Dscotch  -Dptscotch'
111      orderingsf += ' '+self.fortran.FortranDefineCompilerOption+'scotch '+self.fortran.FortranDefineCompilerOption+'ptscotch'
112
113    g.write('ORDERINGSC = '+orderingsc+'\n')
114    g.write('ORDERINGSF = '+orderingsf+'\n')
115    g.write('LORDERINGS  = $(LPARMETIS) $(LMETIS) $(LPORD) $(LSCOTCH)\n')
116    g.write('IORDERINGSC = $(IPARMETIS) $(IMETIS) $(IPORD) $(ISCOTCH)\n')
117    g.write('IORDERINGSF = $(ISCOTCH)\n')
118
119    g.write('RM = /bin/rm -f\n')
120    self.pushLanguage('C')
121    g.write('CC = '+self.getCompiler()+'\n')
122    g.write('OPTC    = '+self.updatePackageCFlags(self.getCompilerFlags())+'\n')
123    g.write('OUTC = -o \n')
124    self.popLanguage()
125    if not self.fortran.fortranIsF90:
126      raise RuntimeError('Installing MUMPS requires a F90 compiler')
127    self.pushLanguage('FC')
128    g.write('FC = '+self.getCompiler()+'\n')
129    g.write('FL = '+self.getCompiler()+'\n')
130    g.write('OPTF    = '+self.updatePackageFFlags(self.getCompilerFlags())+'\n')
131    if self.openmp.found:
132      g.write('OPTF   += -DBLR_MT\n')
133    if self.blasLapack.checkForRoutine('dgemmt'):
134      g.write('OPTF   += -DGEMMT_AVAILABLE\n')
135    g.write('OUTF = -o \n')
136    self.popLanguage()
137
138    # set fortran name mangling
139    # this mangling information is for both BLAS and the Fortran compiler so cannot use the BlasLapack mangling flag
140    if self.compilers.fortranManglingDoubleUnderscore:
141      g.write('CDEFS   = -DAdd__\n')
142    elif self.compilers.fortranMangling == 'underscore':
143      g.write('CDEFS   = -DAdd_\n')
144    elif self.compilers.fortranMangling == 'caps':
145      g.write('CDEFS   = -DUPPPER\n')
146
147    g.write('AR      = '+self.setCompilers.AR+' '+self.setCompilers.AR_FLAGS+' \n')
148    g.write('LIBEXT  = .'+self.setCompilers.AR_LIB_SUFFIX+'\n')
149    g.write('RANLIB  = '+self.setCompilers.RANLIB+'\n')
150    g.write('SCALAP  = '+self.libraries.toString(self.scalapack.lib)+'\n')
151    if not self.argDB['with-mumps-serial']:
152      g.write('INCPAR  = '+self.headers.toString(self.mpi.include)+'\n')
153      g.write('LIBPAR  = $(SCALAP) '+self.libraries.toString(self.mpi.lib)+'\n')
154    else:
155      g.write('INCPAR  = -I../libseq\n')
156    g.write('INCSEQ  = -I$(topdir)/libseq\n')
157    g.write('LIBSEQ  =  $(LAPACK) -L$(topdir)/libseq -lmpiseq\n')
158    g.write('LIBBLAS = '+self.libraries.toString(self.blasLapack.dlib)+'\n')
159    g.write('OPTL    = '+self.getLinkerFlags()+'\n')
160    g.write('INCS = $(INCPAR)\n')
161    g.write('LIBS = $(LIBPAR)\n')
162    if self.argDB['with-mumps-serial']:
163      g.write('LIBSEQNEEDED = libseqneeded\n')
164      g.write('LIBS = $(LIBSEQ)\n')
165    else:
166      g.write('LIBSEQNEEDED =\n')
167      if self.openmp.found and self.hwloc.found:
168        g.write('LIBS += '+self.libraries.toString(self.hwloc.lib)+'\n')
169        g.write('OPTF += -DUSE_LIBHWLOC\n')
170        g.write('OPTC += -DUSE_LIBHWLOC\n')
171    g.close()
172    if self.installNeeded('Makefile.inc'):
173      try:
174        output1,err1,ret1  = config.package.Package.executeShellCommand('make clean', cwd=self.packageDir, timeout=60, log = self.log)
175      except RuntimeError as e:
176        pass
177      try:
178        self.logPrintBox('Compiling MUMPS; this may take several minutes')
179        output2,err2,ret2 = config.package.Package.executeShellCommand(self.make.make_jnp+' prerequisites', cwd=self.packageDir, timeout=2500, log = self.log)
180        output3,err3,ret3 = config.package.Package.executeShellCommand(self.make.make_jnp+' all', cwd=os.path.join(self.packageDir,'src'), timeout=2500, log = self.log)
181        libDir     = os.path.join(self.installDir, self.libdir)
182        includeDir = os.path.join(self.installDir, self.includedir)
183        self.logPrintBox('Installing MUMPS; this may take several minutes')
184        output,err,ret = config.package.Package.executeShellCommandSeq(
185          ['mkdir -p '+libDir+' '+includeDir,
186           'cp -f lib/*.* '+libDir+'/.',
187           'cp -f include/*.* '+includeDir+'/.'
188          ], cwd=self.packageDir, timeout=60, log = self.log)
189        if self.argDB['with-mumps-serial']:
190          output,err,ret = config.package.Package.executeShellCommand(['cp', '-f', 'libseq/libmpiseq.a', libDir+'/.'], cwd=self.packageDir, timeout=60, log = self.log)
191      except RuntimeError as e:
192        self.logPrint('Error running make on MUMPS: '+str(e))
193        raise RuntimeError('Error running make on MUMPS')
194      self.postInstall(output1+err1+output2+err2+output3+err3,'Makefile.inc')
195    return self.installDir
196
197