Commits

Mark Adams  committed ad27580 Merge

Merge remote-tracking branch 'origin/jed/object-id' into madams/sor-residual

  • Participants
  • Parent commits efece86, 704cc5c
  • Branches madams/sor-residual

Comments (0)

Files changed (42)

File bin/win32fe/win32fe.exe

Binary file modified.

File bin/win32fe/win32feutils.dll

Binary file modified.

File conf/gmakegen.py

+#!/usr/bin/env python
+
+import os
+from distutils.sysconfig import parse_makefile
+import sys
+import logging
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'config'))
+from cmakegen import Mistakes, stripsplit, AUTODIRS, SKIPDIRS
+from cmakegen import defaultdict # collections.defaultdict, with fallback for python-2.4
+
+PKGS = 'sys vec mat dm ksp snes ts'.split()
+LANGS = dict(c='C', cxx='C', cu='CU', F='F')
+
+try:
+    all([True, True])
+except NameError:               # needs python-2.5
+    def all(iterable):
+        for i in iterable:
+            if not i:
+                return False
+        return True
+
+try:
+    os.path.relpath             # needs python-2.6
+except AttributeError:
+    def _relpath(path, start=os.path.curdir):
+        """Return a relative version of a path"""
+
+        from os.path import curdir, abspath, commonprefix, sep, pardir, join
+        if not path:
+            raise ValueError("no path specified")
+
+        start_list = [x for x in abspath(start).split(sep) if x]
+        path_list = [x for x in abspath(path).split(sep) if x]
+
+        # Work out how much of the filepath is shared by start and path.
+        i = len(commonprefix([start_list, path_list]))
+
+        rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
+        if not rel_list:
+            return curdir
+        return join(*rel_list)
+    os.path.relpath = _relpath
+
+class debuglogger(object):
+    def __init__(self, log):
+        self._log = log
+
+    def write(self, string):
+        self._log.debug(string)
+
+class Petsc(object):
+    def __init__(self, petsc_dir=None, petsc_arch=None, verbose=False):
+        if petsc_dir is None:
+            petsc_dir = os.environ.get('PETSC_DIR')
+            if petsc_dir is None:
+                try:
+                    petsc_dir = parse_makefile(os.path.join('conf', 'petscvariables')).get('PETSC_DIR')
+                finally:
+                    if petsc_dir is None:
+                        raise RuntimeError('Could not determine PETSC_DIR, please set in environment')
+        if petsc_arch is None:
+            petsc_arch = os.environ.get('PETSC_ARCH')
+            if petsc_arch is None:
+                try:
+                    petsc_arch = parse_makefile(os.path.join(petsc_dir, 'conf', 'petscvariables')).get('PETSC_ARCH')
+                finally:
+                    if petsc_arch is None:
+                        raise RuntimeError('Could not determine PETSC_ARCH, please set in environment')
+        self.petsc_dir = petsc_dir
+        self.petsc_arch = petsc_arch
+        self.read_conf()
+        logging.basicConfig(filename=self.arch_path('conf', 'gmake.log'), level=logging.DEBUG)
+        self.log = logging.getLogger('gmakegen')
+        self.mistakes = Mistakes(debuglogger(self.log), verbose=verbose)
+        self.gendeps = []
+
+    def arch_path(self, *args):
+        return os.path.join(self.petsc_dir, self.petsc_arch, *args)
+
+    def read_conf(self):
+        self.conf = dict()
+        for line in open(self.arch_path('include', 'petscconf.h')):
+            if line.startswith('#define '):
+                define = line[len('#define '):]
+                space = define.find(' ')
+                key = define[:space]
+                val = define[space+1:]
+                self.conf[key] = val
+        self.conf.update(parse_makefile(self.arch_path('conf', 'petscvariables')))
+        self.have_fortran = int(self.conf.get('PETSC_HAVE_FORTRAN', '0'))
+
+    def inconf(self, key, val):
+        if key in ['package', 'function', 'define']:
+            return self.conf.get(val)
+        elif key == 'precision':
+            return val == self.conf['PETSC_PRECISION']
+        elif key == 'scalar':
+            return val == self.conf['PETSC_SCALAR']
+        elif key == 'language':
+            return val == self.conf['PETSC_LANGUAGE']
+        raise RuntimeError('Unknown conf check: %s %s' % (key, val))
+
+    def relpath(self, root, src):
+        return os.path.relpath(os.path.join(root, src), self.petsc_dir)
+
+    def get_sources(self, makevars):
+        """Return dict {lang: list_of_source_files}"""
+        source = dict()
+        for lang, sourcelang in LANGS.items():
+            source[lang] = [f for f in makevars.get('SOURCE'+sourcelang,'').split() if f.endswith(lang)]
+        return source
+
+    def gen_pkg(self, pkg):
+        pkgsrcs = dict()
+        for lang in LANGS:
+            pkgsrcs[lang] = []
+        for root, dirs, files in os.walk(os.path.join(self.petsc_dir, 'src', pkg)):
+            makefile = os.path.join(root,'makefile')
+            if not os.path.exists(makefile):
+                dirs[:] = []
+                continue
+            mklines = open(makefile)
+            conditions = set(tuple(stripsplit(line)) for line in mklines if line.startswith('#requires'))
+            mklines.close()
+            if not all(self.inconf(key, val) for key, val in conditions):
+                dirs[:] = []
+                continue
+            makevars = parse_makefile(makefile)
+            mdirs = makevars.get('DIRS','').split() # Directories specified in the makefile
+            self.mistakes.compareDirLists(root, mdirs, dirs) # diagnostic output to find unused directories
+            candidates = set(mdirs).union(AUTODIRS).difference(SKIPDIRS)
+            dirs[:] = list(candidates.intersection(dirs))
+            allsource = []
+            def mkrel(src):
+                return self.relpath(root, src)
+            source = self.get_sources(makevars)
+            for lang, s in source.items():
+                pkgsrcs[lang] += map(mkrel, s)
+                allsource += s
+            self.mistakes.compareSourceLists(root, allsource, files) # Diagnostic output about unused source files
+            self.gendeps.append(self.relpath(root, 'makefile'))
+        return pkgsrcs
+
+    def gen_gnumake(self, fd):
+        def write(stem, srcs):
+            fd.write('%s :=\n' % stem)
+            for lang in LANGS:
+                fd.write('%(stem)s.%(lang)s := %(srcs)s\n' % dict(stem=stem, lang=lang, srcs=' '.join(srcs[lang])))
+                fd.write('%(stem)s += $(%(stem)s.%(lang)s)\n' % dict(stem=stem, lang=lang))
+        for pkg in PKGS:
+            srcs = self.gen_pkg(pkg)
+            write('srcs-' + pkg, srcs)
+        return self.gendeps
+
+    def gen_ninja(self, fd):
+        libobjs = []
+        for pkg in PKGS:
+            srcs = self.gen_pkg(pkg)
+            for lang in LANGS:
+                for src in srcs[lang]:
+                    obj = '$objdir/%s.o' % src
+                    fd.write('build %(obj)s : %(lang)s_COMPILE %(src)s\n' % dict(obj=obj, lang=lang.upper(), src=os.path.join(self.petsc_dir,src)))
+                    libobjs.append(obj)
+        fd.write('\n')
+        fd.write('build $libdir/libpetsc.so : %s_LINK_SHARED %s\n\n' % ('CF'[self.have_fortran], ' '.join(libobjs)))
+        fd.write('build petsc : phony || $libdir/libpetsc.so\n\n')
+
+    def summary(self):
+        self.mistakes.summary()
+
+def WriteGnuMake(petsc):
+    arch_files = petsc.arch_path('conf', 'files')
+    fd = open(arch_files, 'w')
+    gendeps = petsc.gen_gnumake(fd)
+    fd.write('\n')
+    fd.write('# Dependency to regenerate this file\n')
+    fd.write('%s : %s %s\n' % (os.path.relpath(arch_files, petsc.petsc_dir),
+                               os.path.relpath(__file__, petsc.petsc_dir),
+                               ' '.join(gendeps)))
+    fd.write('\n')
+    fd.write('# Dummy dependencies in case makefiles are removed\n')
+    fd.write(''.join([dep + ':\n' for dep in gendeps]))
+    fd.close()
+
+def WriteNinja(petsc):
+    conf = dict()
+    parse_makefile(os.path.join(petsc.petsc_dir, 'conf', 'variables'), conf)
+    parse_makefile(petsc.arch_path('conf', 'petscvariables'), conf)
+    build_ninja = petsc.arch_path('build.ninja')
+    fd = open(build_ninja, 'w')
+    fd.write('objdir = obj-ninja\n')
+    fd.write('libdir = lib\n')
+    fd.write('c_compile = %(PCC)s\n' % conf)
+    fd.write('c_flags = %(PETSC_CC_INCLUDES)s %(PCC_FLAGS)s %(CCPPFLAGS)s\n' % conf)
+    fd.write('c_link = %(PCC_LINKER)s\n' % conf)
+    fd.write('c_link_flags = %(PCC_LINKER_FLAGS)s\n' % conf)
+    if petsc.have_fortran:
+        fd.write('f_compile = %(FC)s\n' % conf)
+        fd.write('f_flags = %(PETSC_FC_INCLUDES)s %(FC_FLAGS)s %(FCPPFLAGS)s\n' % conf)
+        fd.write('f_link = %(FC_LINKER)s\n' % conf)
+        fd.write('f_link_flags = %(FC_LINKER_FLAGS)s\n' % conf)
+    fd.write('petsc_external_lib = %(PETSC_EXTERNAL_LIB_BASIC)s\n' % conf)
+    fd.write('python = %(PYTHON)s\n' % conf)
+    fd.write('\n')
+    fd.write('rule C_COMPILE\n'
+             '  command = $c_compile -MMD -MF $out.d $c_flags -c $in -o $out\n'
+             '  description = CC $out\n'
+             '  depfile = $out.d\n'
+             # '  deps = gcc\n') # 'gcc' is default, 'msvc' only recognized by newer versions of ninja
+             '\n')
+    fd.write('rule C_LINK_SHARED\n'
+             '  command = $c_link $c_link_flags -shared -o $out $in $petsc_external_lib\n'
+             '  description = CLINK_SHARED $out\n'
+             '\n')
+    if petsc.have_fortran:
+        fd.write('rule F_COMPILE\n'
+                 '  command = $f_compile -MMD -MF $out.d $f_flags -c $in -o $out\n'
+                 '  description = FC $out\n'
+                 '  depfile = $out.d\n'
+                 '\n')
+        fd.write('rule F_LINK_SHARED\n'
+                 '  command = $f_link $f_link_flags -shared -o $out $in $petsc_external_lib\n'
+                 '  description = FLINK_SHARED $out\n'
+                 '\n')
+    fd.write('rule GEN_NINJA\n'
+             '  command = $python $in --output=ninja\n'
+             '  generator = 1\n'
+             '\n')
+    petsc.gen_ninja(fd)
+    fd.write('\n')
+    fd.write('build %s : GEN_NINJA | %s %s %s %s\n' % (build_ninja,
+                                                       os.path.abspath(__file__),
+                                                       os.path.join(petsc.petsc_dir, 'conf', 'variables'),
+                                                       petsc.arch_path('conf', 'petscvariables'),
+                                                       ' '.join(os.path.join(petsc.petsc_dir, dep) for dep in petsc.gendeps)))
+
+def main(petsc_dir=None, petsc_arch=None, output=None, verbose=False):
+    if output is None:
+        output = 'gnumake'
+    writer = dict(gnumake=WriteGnuMake, ninja=WriteNinja)
+    petsc = Petsc(petsc_dir=petsc_dir, petsc_arch=petsc_arch, verbose=verbose)
+    writer[output](petsc)
+    petsc.summary()
+
+if __name__ == '__main__':
+    import optparse
+    parser = optparse.OptionParser()
+    parser.add_option('--verbose', help='Show mismatches between makefiles and the filesystem', action='store_true', default=False)
+    parser.add_option('--petsc-arch', help='Set PETSC_ARCH different from environment', default=os.environ.get('PETSC_ARCH'))
+    parser.add_option('--output', help='Location to write output file', default=None)
+    opts, extra_args = parser.parse_args()
+    if extra_args:
+        import sys
+        sys.stderr.write('Unknown arguments: %s\n' % ' '.join(extra_args))
+        exit(1)
+    main(petsc_arch=opts.petsc_arch, output=opts.output, verbose=opts.verbose)
         if [ "$${makeflags_j}" != "$${makeflags}" ]; then parallel=true; fi;\
         if [ "$${parallel}" = "true" ]; then \
           printf ${PETSC_TEXT_HILIGHT}"********************* ERROR **********************\n" ; \
-          if [ "${PETSC_BUILD_USING_CMAKE}" != "" ]; then \
+          if [ "${PETSC_BUILD_USING_CMAKE}" != "" -o "${PETSC_BUILD_USING_GNUMAKE}" != "" ]; then \
              echo "PETSc compiles are automatically parallel, do not ";\
              echo "provide the -j option to make                     ";\
           else \
              echo "Parallel build with 'make -j' is not supported    ";\
              echo "for PETSc legacy builds. Run without -j <np>      ";\
-             echo "or ./configure PETSc with --download-cmake        ";\
+             echo "or configure PETSc with gnumake using --download-make";\
              echo "to enable parallel builds with PETSc              ";\
           fi;\
           printf "**************************************************"${PETSC_TEXT_NORMAL}"\n" ;\
 cmake: chk_makej
 	@${OMAKE} ccmake VERBOSE=1
 
+gnumake: chk_makej
+	@echo "Building PETSc using GNU Make with ${MAKE_NP} build threads"
+	@echo "=========================================="
+	@cd ${PETSC_DIR} && ${OMAKE} -f gmakefile -j ${MAKE_NP} V=${V}
+	@if [ "${BUILDSHAREDLIB}" = "yes" -a "${DSYMUTIL}" != "true" ]; then \
+        echo "Running ${DSYMUTIL} on ${SHLIBS}";\
+        for LIBNAME in ${SHLIBS}; do ${DSYMUTIL} ${INSTALL_LIB_DIR}/$$LIBNAME.${SL_LINKER_SUFFIX}; done; fi
+	@echo "========================================="
+
 # Does nothing; needed for some rules that require actions.
 foo:
 
         if [ $${mypwd} != $${newpwd} ]; then \
 	  ${OMAKE}  PETSC_ARCH=${PETSC_ARCH}  chk_petscdir;\
         fi
-	${PETSC_COMPILE_SINGLE} $<
+	${PETSC_COMPILE_SINGLE} ${PWD}/$<
 	@if [ "${PETSCPORTABLE}" != "" ]; then \
           ${PYTHON} ${PETSC_DIR}/bin/portabilitycheck.py $*.o ; \
         fi
 #
 #   Compiles CUDA code
 .cu.o:
-	${PETSC_CUCOMPILE_SINGLE} $<
+	${PETSC_CUCOMPILE_SINGLE} ${PWD}/$<
 
 .cu.a:
-	${PETSC_CUCOMPILE_SINGLE} $<
+	${PETSC_CUCOMPILE_SINGLE} ${PWD}/$<
 	-${AR} ${AR_FLAGS} ${LIBNAME} $*.o
 	-if test -n "${LIBTOOL}"; then ${AR} ${AR_FLAGS} ${LT_LIBNAME} $*.lo; fi
 	-${RM} $*.o $*.lo
 
 .c.a .cpp.a .cc.a .C.a:
-	-${PETSC_COMPILE_SINGLE} $<
+	-${PETSC_COMPILE_SINGLE} ${PWD}/$<
 	-${AR} ${AR_FLAGS} ${LIBNAME} $*.o
 	-if test -n "${LIBTOOL}"; then ${AR} ${AR_FLAGS} ${LT_LIBNAME} $*.lo; fi
 	-${RM} $*.o $*.lo

File conf/variables

 #
 PETSC_LIB_DIR	     = ${PETSC_DIR}/${PETSC_ARCH}/lib
 
-PETSC_CCPPFLAGS	    = ${PETSC_CC_INCLUDES} ${PETSCFLAGS} ${CPP_FLAGS} ${CPPFLAGS} -D__INSDIR__=${LOCDIR}
+PETSC_CCPPFLAGS	    = ${PETSC_CC_INCLUDES} ${PETSCFLAGS} ${CPP_FLAGS} ${CPPFLAGS}
 PETSC_FCPPFLAGS	    = ${PETSC_FC_INCLUDES} ${PETSCFLAGS} ${FPP_FLAGS} ${FPPFLAGS}
 PETSC_C_SH_LIB_PATH = ${CC_LINKER_SLFLAG}${PETSC_LIB_DIR}
 PETSC_F_SH_LIB_PATH = ${FC_LINKER_SLFLAG}${PETSC_LIB_DIR}
 #
 # The following variables define PETSc compile procedures
 #
-PETSC_COMPILE         = ${PCC} -c ${PCC_FLAGS} ${CFLAGS} ${CCPPFLAGS}  ${SOURCEC}
+PSOURCEC  = $(SOURCEC:%=${PWD}/%)
+PSOURCECU = $(SOURCECU:%=${PWD}/%)
+PETSC_COMPILE         = ${PCC} -c ${PCC_FLAGS} ${CFLAGS} ${CCPPFLAGS}  ${PSOURCEC}
 PETSC_COMPILE_SINGLE  = ${PCC} -o $*.o -c ${PCC_FLAGS} ${CFLAGS} ${CCPPFLAGS}
 PETSC_FCOMPILE        = ${FC} -c ${FC_FLAGS} ${FFLAGS} ${FCPPFLAGS}  ${SOURCEF}
-PETSC_CUCOMPILE       = ${CUDAC} ${CUDAC_FLAGS} -c --compiler-options="${PCC_FLAGS} ${CFLAGS} ${CCPPFLAGS}" ${SOURCECU}
+PETSC_CUCOMPILE       = ${CUDAC} ${CUDAC_FLAGS} -c --compiler-options="${PCC_FLAGS} ${CFLAGS} ${CCPPFLAGS}" ${PSOURCECU}
 PETSC_CUCOMPILE_SINGLE= ${CUDAC} -o $*.o ${CUDAC_FLAGS} -c --compiler-options="${PCC_FLAGS} ${CFLAGS} ${CCPPFLAGS}"
 #
 # define OBJSC and OBJSF OBJSCU

File config/BuildSystem/config/compilers.py

     for language in languages:
       self.generateDependencies[language] = 0
       self.setCompilers.pushLanguage(language)
-      for testFlag in ['-MMD', '-M']:
+      for testFlag in ['-MMD -MP', # GCC, Intel, Clang, Pathscale
+                       '-MMD',     # PGI
+                       '-xMMD',    # Sun
+                       '-qmakedep=gcc', # xlc
+                       '-MD',
+                       # Cray only supports -M, which writes to stdout
+                     ]:
         try:
           self.framework.logPrint('Trying '+language+' compiler flag '+testFlag)
-          if not self.setCompilers.checkLinkerFlag(testFlag):
-            self.framework.logPrint('Rejected '+language+' compiler flag '+testFlag+' because linker cannot handle it')
-            continue
-          self.framework.logPrint('Testing '+language+' compiler flag '+testFlag)
           if self.setCompilers.checkCompilerFlag(testFlag, compilerOnly = 1):
             depFilename = os.path.splitext(self.setCompilers.compilerObj)[0]+'.d'
             if os.path.isfile(depFilename):
               os.remove(depFilename)
               #self.setCompilers.insertCompilerFlag(testFlag, compilerOnly = 1)
+              self.framework.addMakeMacro(language.upper()+'_DEPFLAGS',testFlag)
               self.dependenciesGenerationFlag[language] = testFlag
               self.generateDependencies[language]       = 1
               break

File config/BuildSystem/config/package.py

     self.libraries     = framework.require('config.libraries', self)
     self.programs      = framework.require('config.programs', self)
     self.sourceControl = framework.require('config.sourceControl',self)
+    self.make          = framework.require('config.packages.make',self)
     self.mpi           = framework.require('config.packages.MPI',self)
 
     return

File config/BuildSystem/config/packages/MPI.py

     installDir = os.path.join(self.defaultInstallDir,self.arch)
     confDir = os.path.join(self.defaultInstallDir,self.arch,'conf')
     args = ['--prefix='+installDir,'--with-rsh=ssh']
+    args.append('MAKE='+self.make.make)
     # Configure and Build OPENMPI
     self.pushLanguage('C')
     flags = self.getCompilerFlags()
         raise RuntimeError('Error running configure on OPENMPI/MPI: '+str(e))
       try:
         self.logPrintBox('Compiling OPENMPI/MPI; this may take several minutes')
-        output,err,ret  = config.base.Configure.executeShellCommand('cd '+openmpiDir+' && '+self.programs.make+' clean', timeout=200, log = self.framework.log)
-        output,err,ret  = config.base.Configure.executeShellCommand('cd '+openmpiDir+' && '+self.programs.make+' -j ' + str(self.programs.make_np)+' all', timeout=6000, log = self.framework.log)
-        output,err,ret  = config.base.Configure.executeShellCommand('cd '+openmpiDir+' && '+self.programs.make+' install', timeout=6000, log = self.framework.log)
-        output,err,ret  = config.base.Configure.executeShellCommand('cd '+openmpiDir+' && '+self.programs.make+' clean', timeout=200, log = self.framework.log)
+        output,err,ret  = config.base.Configure.executeShellCommand('cd '+openmpiDir+' && '+self.make.make+' clean', timeout=200, log = self.framework.log)
+        output,err,ret  = config.base.Configure.executeShellCommand('cd '+openmpiDir+' && '+self.make.make_jnp+' all', timeout=6000, log = self.framework.log)
+        output,err,ret  = config.base.Configure.executeShellCommand('cd '+openmpiDir+' && '+self.make.make+' install', timeout=6000, log = self.framework.log)
+        output,err,ret  = config.base.Configure.executeShellCommand('cd '+openmpiDir+' && '+self.make.make+' clean', timeout=200, log = self.framework.log)
       except RuntimeError, e:
         raise RuntimeError('Error running make on OPENMPI/MPI: '+str(e))
       if not os.path.isdir(os.path.join(installDir,'lib')):
     # Configure and Build MPICH
     self.pushLanguage('C')
     args = ['--prefix='+installDir]
+    args.append('MAKE='+self.make.make)
     compiler = self.getCompiler()
     args.append('CC="'+self.getCompiler()+'"')
     args.append('CFLAGS="'+self.getCompilerFlags().replace('-fvisibility=hidden','')+'"')
         raise RuntimeError('Error running configure on MPICH: '+str(e))
       try:
         self.logPrintBox('Running make on MPICH; this may take several minutes')
-        output,err,ret  = config.base.Configure.executeShellCommand('cd '+mpichDir+' && '+self.programs.make+' clean', timeout=200, log = self.framework.log)
-        makej_cmd = self.programs.make+' -j ' + str(self.programs.make_np)
-        output,err,ret  = config.base.Configure.executeShellCommand('cd '+mpichDir+' && '+makej_cmd+' all', timeout=6000, log = self.framework.log)
-        output,err,ret  = config.base.Configure.executeShellCommand('cd '+mpichDir+' && '+self.programs.make+' install', timeout=6000, log = self.framework.log)
-        output,err,ret  = config.base.Configure.executeShellCommand('cd '+mpichDir+' && '+self.programs.make+' clean', timeout=200, log = self.framework.log)
+        output,err,ret  = config.base.Configure.executeShellCommand('cd '+mpichDir+' && '+self.make.make+' clean', timeout=200, log = self.framework.log)
+        output,err,ret  = config.base.Configure.executeShellCommand('cd '+mpichDir+' && '+self.make.make_jnp+' all', timeout=6000, log = self.framework.log)
+        output,err,ret  = config.base.Configure.executeShellCommand('cd '+mpichDir+' && '+self.make.make+' install', timeout=6000, log = self.framework.log)
+        output,err,ret  = config.base.Configure.executeShellCommand('cd '+mpichDir+' && '+self.make.make+' clean', timeout=200, log = self.framework.log)
       except RuntimeError, e:
         import sys
         if sys.platform.startswith('cygwin'):

File config/BuildSystem/config/packages/__init__.py

-all = ['f2cblaslapack','BlasLapack', 'CHOLMOD', 'exodusii', 'scientificpython', 'fiat', 'MOAB', 'MPI', 'netcdf', 'PETSc', 'UMFPACK', 'boost', 'cusp', 'thrust', 'hdf5', 'netcdf-cxx']
+all = ['make','f2cblaslapack','BlasLapack', 'CHOLMOD', 'exodusii', 'scientificpython', 'fiat', 'MOAB', 'MPI', 'netcdf', 'PETSc', 'UMFPACK', 'boost', 'cusp', 'thrust', 'hdf5', 'netcdf-cxx']

File config/BuildSystem/config/packages/make.py

+from __future__ import generators
+import config.package
+
+class Configure(config.package.Package):
+  def __init__(self, framework):
+    config.package.Package.__init__(self, framework)
+    self.download          = ['http://ftp.gnu.org/gnu/make/make-3.82.tar.gz','http://ftp.mcs.anl.gov/pub/petsc/externalpackages/make-3.82.tar.gz']
+    self.complex           = 1
+    self.double            = 0
+    self.requires32bitint  = 0
+    self.worksonWindows    = 1
+    self.downloadonWindows = 1
+    self.useddirectly      = 0
+
+    self.flags             = ''
+    self.haveGNUMake       = 0
+    return
+
+  def setupHelp(self, help):
+    import nargs
+    help.addArgument('Make', '-with-make=<prog>',                            nargs.Arg(None, 'gmake', 'Specify GNU make'))
+    help.addArgument('Make', '-with-make-np=<np>',                           nargs.ArgInt(None, None, min=1, help='Default number of threads to use for parallel builds'))
+    help.addArgument('Make', '-download-make=<no,yes,filename>',             nargs.ArgDownload(None, 0, 'Download and install GNU make'))
+    help.addArgument('Make', '-download-make-cc=<prog>',                     nargs.Arg(None, None, 'C compiler for GNU make configure'))
+    help.addArgument('Make', '-download-make-configure-options=<options>',   nargs.Arg(None, None, 'additional options for GNU make configure'))
+    return
+
+  def Install(self):
+    import os
+    args = ['--prefix='+self.installDir]
+    args.append('--program-prefix=g')
+    if self.framework.argDB.has_key('download-make-cc'):
+      args.append('CC="'+self.framework.argDB['download-make-cc']+'"')
+    if self.framework.argDB.has_key('download-make-configure-options'):
+      args.append(self.framework.argDB['download-make-configure-options'])
+    args = ' '.join(args)
+    fd = file(os.path.join(self.packageDir,'make.args'), 'w')
+    fd.write(args)
+    fd.close()
+    if self.installNeeded('make.args'):
+      try:
+        self.logPrintBox('Configuring GNU Make; this may take several minutes')
+        output,err,ret  = config.package.Package.executeShellCommand('cd '+self.packageDir+' && ./configure '+args, timeout=900, log = self.framework.log)
+      except RuntimeError, e:
+        raise RuntimeError('Error running configure on GNU make (install manually): '+str(e))
+      try:
+        self.logPrintBox('Compiling GNU Make; this may take several minutes')
+        if self.getExecutable('make', getFullPath = 1,resultName='make',setMakeMacro = 0):
+          output,err,ret  = config.package.Package.executeShellCommand('cd '+self.packageDir+' && '+self.make+' &&  '+self.make+' install && '+self.make+' clean', timeout=2500, log = self.framework.log)
+        else:
+          output,err,ret  = config.package.Package.executeShellCommand('cd '+self.packageDir+' && ./build.sh && ./make install && ./make clean', timeout=2500, log = self.framework.log)
+      except RuntimeError, e:
+        raise RuntimeError('Error running make; make install on GNU Make (install manually): '+str(e))
+      self.postInstall(output+err,'make.args')
+    self.binDir = os.path.join(self.installDir, 'bin')
+    self.make = os.path.join(self.binDir, 'gmake')
+    self.addMakeMacro('MAKE',self.make)
+    return self.installDir
+
+  def configureMake(self):
+    '''Check for user specified make - or gmake, make'''
+    if self.framework.clArgDB.has_key('with-make'):
+      if not self.getExecutable(self.framework.argDB['with-make'],getFullPath = 1,resultName = 'make'):
+        raise RuntimeError('Error! User provided make not found :'+self.framework.argDB['with-make'])
+      self.found = 1
+      return
+    if not self.getExecutable('gmake', getFullPath = 1,resultName = 'make') and not self.getExecutable('make', getFullPath = 1,resultName = 'make'):
+      import os
+      if os.path.exists('/usr/bin/cygcheck.exe') and not os.path.exists('/usr/bin/make'):
+        raise RuntimeError('''\
+*** Incomplete cygwin install detected . /usr/bin/make is missing. **************
+*** Please rerun cygwin-setup and select module "make" for install.**************''')
+      else:
+        raise RuntimeError('Could not locate the make utility on your system, try --download-make')
+    self.found = 1
+    return
+
+  def configureCheckGNUMake(self):
+    '''Check for GNU make'''
+    self.getExecutable('strings', getFullPath = 1,setMakeMacro = 0)
+    if hasattr(self, 'strings'):
+      try:
+        (output, error, status) = config.base.Configure.executeShellCommand(self.strings+' '+self.make, log = self.framework.log)
+        if not status and output.find('GNU Make') >= 0:
+          self.haveGNUMake = 1
+      except RuntimeError, e:
+        self.framework.log.write('Make check failed: '+str(e)+'\n')
+      if not self.haveGNUMake:
+        try:
+          (output, error, status) = config.base.Configure.executeShellCommand(self.strings+' '+self.make+'.exe', log = self.framework.log)
+          if not status and output.find('GNU Make') >= 0:
+            self.haveGNUMake = 1
+        except RuntimeError, e:
+          self.framework.log.write('Make check failed: '+str(e)+'\n')
+    # mac has fat binaries where 'string' check fails
+    if not self.haveGNUMake:
+      try:
+        (output, error, status) = config.base.Configure.executeShellCommand(self.make+' -v dummy-foobar', log = self.framework.log)
+        if not status and output.find('GNU Make') >= 0:
+          self.haveGNUMake = 1
+      except RuntimeError, e:
+        self.framework.log.write('Make check failed: '+str(e)+'\n')
+
+    # Setup make flags
+    if self.haveGNUMake:
+      self.flags += ' --no-print-directory'
+      self.addMakeMacro('PETSC_BUILD_USING_GNUMAKE',1)
+
+    # Check to see if make allows rules which look inside archives
+    if self.haveGNUMake:
+      self.addMakeRule('libc','${LIBNAME}(${OBJSC})')
+      self.addMakeRule('libcu','${LIBNAME}(${OBJSCU})')
+    else:
+      self.addMakeRule('libc','${OBJSC}','-${AR} ${AR_FLAGS} ${LIBNAME} ${OBJSC}')
+      self.addMakeRule('libcu','${OBJSCU}','-${AR} ${AR_FLAGS} ${LIBNAME} ${OBJSCU}')
+    self.addMakeRule('libf','${OBJSF}','-${AR} ${AR_FLAGS} ${LIBNAME} ${OBJSF}')
+    return
+
+  def configureMakeNP(self):
+    '''check no of cores on the build machine [perhaps to do make '-j ncores']'''
+    make_np = self.framework.argDB.get('with-make-np')
+    if make_np is not None:
+      self.framework.logPrint('using user-provided make_np = %d' % make_np)
+    else:
+      def compute_make_np(i):
+        f16 = .80
+        f32 = .65
+        f64 = .50
+        f99 = .30
+        if (i<=2):    return 2
+        elif (i<=4):  return i
+        elif (i<=16): return int(4+(i-4)*f16)
+        elif (i<=32): return int(4+12*f16+(i-16)*f32)
+        elif (i<=64): return int(4+12*f16+16*f32+(i-32)*f64)
+        else:         return int(4+12*f16+16*f32+32*f64+(i-64)*f99)
+        return
+      try:
+        import multiprocessing # python-2.6 feature
+        cores = multiprocessing.cpu_count()
+        make_np = compute_make_np(cores)
+        self.framework.logPrint('module multiprocessing found %d cores: using make_np = %d' % (cores,make_np))
+      except (ImportError), e:
+        make_np = 2
+        self.framework.logPrint('module multiprocessing *not* found: using default make_np = %d' % make_np)
+    self.make_np = make_np
+    self.addMakeMacro('MAKE_NP',str(make_np))
+    self.make_jnp = self.make + ' -j ' + str(self.make_np)
+    return
+
+  def configure(self):
+    '''Determine whether (GNU) make exist or not'''
+
+    if self.framework.argDB['with-make'] == '0':
+      return
+    if (self.framework.argDB['download-make']):
+      config.package.Package.configure(self)
+    else:
+      self.executeTest(self.configureMake)
+    self.executeTest(self.configureCheckGNUMake)
+    self.executeTest(self.configureMakeNP)
+    self.addMakeMacro('OMAKE ', self.make+' '+self.flags)
+    return

File config/BuildSystem/config/programs.py

 
   def setupHelp(self, help):
     import nargs
-    import nargs
-    help.addArgument('PETSc', '-with-make=<prog>', nargs.Arg(None, 'make', 'Specify make'))
-    help.addArgument('PETSc', '-with-make-np=<np>', nargs.ArgInt(None, None, min=1, help='Default number of threads to use for parallel builds'))
     help.addArgument('PETSc', '-with-autoreconf=<prog>', nargs.Arg(None, 'autoreconf', 'Specify autoreconf'))
     return
 
-  def configureMake(self):
-    '''Check various things about make'''
-    self.getExecutable(self.framework.argDB['with-make'], getFullPath = 1,resultName = 'make')
-
-    if not hasattr(self,'make'):
-      import os
-      if os.path.exists('/usr/bin/cygcheck.exe') and not os.path.exists('/usr/bin/make'):
-        raise RuntimeError('''\
-*** Incomplete cygwin install detected . /usr/bin/make is missing. **************
-*** Please rerun cygwin-setup and select module "make" for install.**************''')
-      else:
-        raise RuntimeError('Could not locate the make utility on your system, make sure\n it is in your path or use --with-make=/fullpathnameofmake\n and run ./configure again')
-    # Check for GNU make
-    haveGNUMake = 0
-    self.getExecutable('strings', getFullPath = 1)
-    if hasattr(self, 'strings'):
-      try:
-        (output, error, status) = config.base.Configure.executeShellCommand(self.strings+' '+self.make, log = self.framework.log)
-        if not status and output.find('GNU Make') >= 0:
-          haveGNUMake = 1
-      except RuntimeError, e:
-        self.framework.log.write('Make check failed: '+str(e)+'\n')
-      if not haveGNUMake:
-        try:
-          (output, error, status) = config.base.Configure.executeShellCommand(self.strings+' '+self.make+'.exe', log = self.framework.log)
-          if not status and output.find('GNU Make') >= 0:
-            haveGNUMake = 1
-        except RuntimeError, e:
-          self.framework.log.write('Make check failed: '+str(e)+'\n')
-    # mac has fat binaries where 'string' check fails
-    if not haveGNUMake:
-      try:
-        (output, error, status) = config.base.Configure.executeShellCommand(self.make+' -v dummy-foobar', log = self.framework.log)
-        if not status and output.find('GNU Make') >= 0:
-          haveGNUMake = 1
-      except RuntimeError, e:
-        self.framework.log.write('Make check failed: '+str(e)+'\n')
-
-    # Setup make flags
-    self.flags = ''
-    if haveGNUMake:
-      self.flags += ' --no-print-directory'
-    self.addMakeMacro('OMAKE ', self.make+' '+self.flags)
-
-    # Check to see if make allows rules which look inside archives
-    if haveGNUMake:
-      self.addMakeRule('libc','${LIBNAME}(${OBJSC})')
-      self.addMakeRule('libcu','${LIBNAME}(${OBJSCU})')
-    else:
-      self.addMakeRule('libc','${OBJSC}','-${AR} ${AR_FLAGS} ${LIBNAME} ${OBJSC}')
-      self.addMakeRule('libcu','${OBJSCU}','-${AR} ${AR_FLAGS} ${LIBNAME} ${OBJSCU}')
-    self.addMakeRule('libf','${OBJSF}','-${AR} ${AR_FLAGS} ${LIBNAME} ${OBJSF}')
-
-    # check no of cores on the build machine [perhaps to do make '-j ncores']
-    make_np = self.framework.argDB.get('with-make-np')
-    if make_np is not None:
-      self.framework.logPrint('using user-provided make_np = %d' % make_np)
-    else:
-      try:
-        import multiprocessing
-        cores = multiprocessing.cpu_count()
-        make_np = max(min(cores+1,5),cores/3)
-        self.framework.logPrint('module multiprocessing found %d cores: using make_np = %d' % (cores,make_np))
-      except (ImportError), e:
-        make_np = 2
-        self.framework.logPrint('module multiprocessing *not* found: using default make_np = %d' % make_np)
-      try:
-        import os
-        import pwd
-        if 'barrysmith' == pwd.getpwuid(os.getuid()).pw_name:
-          # Barry wants to use exactly the number of physical cores (not logical cores) because it breaks otherwise.
-          # Since this works for everyone else who uses a Mac, something must be wrong with their systems. ;-)
-          try:
-            (output, error, status) = config.base.Configure.executeShellCommand('/usr/sbin/system_profiler -detailLevel full SPHardwareDataType', log = self.framework.log)
-            import re
-            match = re.search(r'.*Total Number Of Cores: (\d+)', output)
-            if match:
-              make_np = int(match.groups()[0])
-              self.framework.logPrint('Found number of cores using system_profiler: make_np = %d' % (make_np,))
-          except:
-            pass
-      except:
-        pass
-    self.make_np = make_np
-    self.addMakeMacro('MAKE_NP',str(make_np))
-    return
-
   def configureMkdir(self):
     '''Make sure we can have mkdir automatically make intermediate directories'''
     self.getExecutable('mkdir', getFullPath = 1, setMakeMacro = 0)
     return
 
   def configure(self):
-    if not self.framework.argDB['with-make'] == '0':
-      self.executeTest(self.configureMake)
-      self.executeTest(self.configureMkdir)
-      self.executeTest(self.configureAutoreconf)
-      self.executeTest(self.configurePrograms)
+    self.executeTest(self.configureMkdir)
+    self.executeTest(self.configureAutoreconf)
+    self.executeTest(self.configurePrograms)
     return

File config/PETSc/Configure.py

   def __str2__(self):
     desc = []
     desc.append('xxx=========================================================================xxx')
-    if self.getMakeMacro('PETSC_BUILD_USING_CMAKE'):
+    if self.make.getMakeMacro('PETSC_BUILD_USING_GNUMAKE'):
+      build_type = 'gnumake build'
+    elif self.getMakeMacro('PETSC_BUILD_USING_CMAKE'):
       build_type = 'cmake build'
     else:
       build_type = 'legacy build'
     self.functions     = framework.require('config.functions',          self)
     self.libraries     = framework.require('config.libraries',          self)
     self.atomics       = framework.require('config.atomics',            self)
+    self.make          = framework.require('config.packages.make',      self)
     self.blasLapack    = framework.require('config.packages.BlasLapack',self)
     if os.path.isdir(os.path.join('config', 'PETSc')):
       for d in ['utilities', 'packages']:
     return
 
 #-----------------------------------------------------------------------------------------------------
+  def configureCygwinBrokenPipe(self):
+    '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make
+    http://cygwin.com/ml/cygwin/2013-05/msg00340.html '''
+    if config.setCompilers.Configure.isCygwin():
+      import platform
+      import re
+      r=re.compile("([0-9]+).([0-9]+).([0-9]+)")
+      m=r.match(platform.release())
+      major=int(m.group(1))
+      minor=int(m.group(2))
+      subminor=int(m.group(3))
+      if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)):
+        self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1')
+    return
+
+#-----------------------------------------------------------------------------------------------------
   def configureDefaultArch(self):
     conffile = os.path.join('conf', 'petscvariables')
     if self.framework.argDB['with-default-arch']:
     self.executeTest(self.configureSolaris)
     self.executeTest(self.configureLinux)
     self.executeTest(self.configureWin32)
+    self.executeTest(self.configureCygwinBrokenPipe)
     self.executeTest(self.configureDefaultArch)
     self.executeTest(self.configureScript)
     self.executeTest(self.configureInstall)

File config/PETSc/packages/PaStiX.py

     PETSc.package.NewPackage.setupDependencies(self, framework)
     self.blasLapack = framework.require('config.packages.BlasLapack',self)
     self.scotch     = framework.require('PETSc.packages.PTScotch',self)
-    self.make       = framework.require('config.programs', self)
     self.deps       = [self.mpi,self.blasLapack, self.scotch]
     return
 

File config/PETSc/packages/Triangle.py

   def setupDependencies(self, framework):
     PETSc.package.NewPackage.setupDependencies(self, framework)
     self.sharedLibraries = framework.require('PETSc.utilities.sharedLibraries', self)
-    self.make            = framework.require('config.programs', self)
     self.x               = framework.require('PETSc.packages.X', self)
     self.deps = []
     return

File config/PETSc/packages/tetgen.py

   def setupDependencies(self, framework):
     PETSc.package.NewPackage.setupDependencies(self, framework)
     self.sharedLibraries = framework.require('PETSc.utilities.sharedLibraries', self)
-    self.make            = framework.require('config.programs', self)
     self.deps            = []
     return
 

File config/builder.py

     self.languages       = self.framework.require('PETSc.utilities.languages',   None)
     self.debugging       = self.framework.require('PETSc.utilities.debugging',   None)
     self.debuggers       = self.framework.require('PETSc.utilities.debuggers',   None)
-    self.make            = self.framework.require('config.programs',        None)
     self.CHUD            = self.framework.require('PETSc.utilities.CHUD',        None)
     self.compilers       = self.framework.require('config.compilers',            None)
     self.types           = self.framework.require('config.types',                None)

File config/cmakeboot.py

    self.petscdir      = self.framework.require('PETSc.utilities.petscdir',    None)
    self.languages     = self.framework.require('PETSc.utilities.languages',   None)
    self.debugging     = self.framework.require('PETSc.utilities.debugging',   None)
-   self.make          = self.framework.require('config.programs',        None)
    self.cmake         = self.framework.require('PETSc.packages.cmake',       None)
    self.CHUD          = self.framework.require('PETSc.utilities.CHUD',        None)
    self.compilers     = self.framework.require('config.compilers',            None)

File config/cmakegen.py

         def __repr__(self):
             return 'defaultdict(%s, %s)' % (self.default_factory,
                                             dict.__repr__(self))
-# Run with --verbose
-VERBOSE = False
-MISTAKES = []
 
 class StdoutLogger(object):
   def write(self,str):
     raise RuntimeError('Unexpected language: %r'%val)
   raise RuntimeError('Unhandled case: %r=%r'%(key,val))
 
-def pkgsources(pkg):
+AUTODIRS = set('ftn-auto ftn-custom f90-custom'.split()) # Automatically recurse into these, if they exist
+SKIPDIRS = set('benchmarks'.split())                     # Skip these during the build
+NOWARNDIRS = set('tests tutorials'.split())              # Do not warn about mismatch in these
+
+def pathsplit(path):
+    """Recursively split a path, returns a tuple"""
+    stem, basename = os.path.split(path)
+    if stem == '':
+        return (basename,)
+    if stem == path:            # fixed point, likely '/'
+        return (path,)
+    return pathsplit(stem) + (basename,)
+
+class Mistakes(object):
+    def __init__(self, log, verbose=False):
+        self.mistakes = []
+        self.verbose = verbose
+        self.log = log
+
+    def compareDirLists(self,root, mdirs, dirs):
+        if NOWARNDIRS.intersection(pathsplit(root)):
+            return
+        smdirs = set(mdirs)
+        sdirs  = set(dirs).difference(AUTODIRS)
+        if not smdirs.issubset(sdirs):
+            self.mistakes.append('Makefile contains directory not on filesystem: %s: %r' % (root, sorted(smdirs - sdirs)))
+        if not self.verbose: return
+        if smdirs != sdirs:
+            from sys import stderr
+            stderr.write('Directory mismatch at %s:\n\t%s: %r\n\t%s: %r\n\t%s: %r\n'
+                         % (root,
+                            'in makefile   ',sorted(smdirs),
+                            'on filesystem ',sorted(sdirs),
+                            'symmetric diff',sorted(smdirs.symmetric_difference(sdirs))))
+
+    def compareSourceLists(self, root, msources, files):
+        if NOWARNDIRS.intersection(pathsplit(root)):
+            return
+        smsources = set(msources)
+        ssources  = set(f for f in files if os.path.splitext(f)[1] in ['.c', '.cxx', '.cc', '.cu', '.cpp', '.F'])
+        if not smsources.issubset(ssources):
+            self.mistakes.append('Makefile contains file not on filesystem: %s: %r' % (root, sorted(smsources - ssources)))
+        if not self.verbose: return
+        if smsources != ssources:
+            from sys import stderr
+            stderr.write('Source mismatch at %s:\n\t%s: %r\n\t%s: %r\n\t%s: %r\n'
+                         % (root,
+                            'in makefile   ',sorted(smsources),
+                            'on filesystem ',sorted(ssources),
+                            'symmetric diff',sorted(smsources.symmetric_difference(ssources))))
+
+    def summary(self):
+        for m in self.mistakes:
+            self.log.write(m + '\n')
+        if self.mistakes:
+            raise RuntimeError('PETSc makefiles contain mistakes or files are missing on filesystem.\n%s\nPossible reasons:\n\t1. Files were deleted locally, try "hg revert filename" or "git checkout filename".\n\t2. Files were deleted from repository, but were not removed from makefile. Send mail to petsc-maint@mcs.anl.gov.\n\t3. Someone forgot to "add" new files to the repository. Send mail to petsc-maint@mcs.anl.gov.' % ('\n'.join(self.mistakes)))
+
+def stripsplit(line):
+  return line[len('#requires'):].replace("'","").split()
+
+def pkgsources(pkg, mistakes):
   '''
   Walks the source tree associated with 'pkg', analyzes the conditional written into the makefiles,
   and returns a list of sources associated with each unique conditional (as a dictionary).
   '''
   from distutils.sysconfig import parse_makefile
-  autodirs = set('ftn-auto ftn-custom f90-custom'.split()) # Automatically recurse into these, if they exist
-  skipdirs = set('examples benchmarks'.split())            # Skip these during the build
-  def compareDirLists(mdirs,dirs):
-    smdirs = set(mdirs)
-    sdirs  = set(dirs).difference(autodirs)
-    if not smdirs.issubset(sdirs):
-      MISTAKES.append('Makefile contains directory not on filesystem: %s: %r' % (root, sorted(smdirs - sdirs)))
-    if not VERBOSE: return
-    if smdirs != sdirs:
-      from sys import stderr
-      print >>stderr, ('Directory mismatch at %s:\n\t%s: %r\n\t%s: %r\n\t%s: %r'
-                       % (root,
-                          'in makefile   ',sorted(smdirs),
-                          'on filesystem ',sorted(sdirs),
-                          'symmetric diff',sorted(smdirs.symmetric_difference(sdirs))))
-  def compareSourceLists(msources, files):
-    smsources = set(msources)
-    ssources  = set(f for f in files if os.path.splitext(f)[1] in ['.c', '.cxx', '.cc', '.cu', '.cpp', '.F'])
-    if not smsources.issubset(ssources):
-      MISTAKES.append('Makefile contains file not on filesystem: %s: %r' % (root, sorted(smsources - ssources)))
-    if not VERBOSE: return
-    if smsources != ssources:
-      from sys import stderr
-      print >>stderr, ('Source mismatch at %s:\n\t%s: %r\n\t%s: %r\n\t%s: %r'
-                       % (root,
-                          'in makefile   ',sorted(smsources),
-                          'on filesystem ',sorted(ssources),
-                          'symmetric diff',sorted(smsources.symmetric_difference(ssources))))
   allconditions = defaultdict(set)
   sources = defaultdict(deque)
   for root,dirs,files in os.walk(os.path.join('src',pkg)):
       continue
     makevars = parse_makefile(makefile)
     mdirs = makevars.get('DIRS','').split() # Directories specified in the makefile
-    compareDirLists(mdirs,dirs) # diagnostic output to find unused directories
-    candidates = set(mdirs).union(autodirs).difference(skipdirs)
+    mistakes.compareDirLists(root,mdirs,dirs) # diagnostic output to find unused directories
+    candidates = set(mdirs).union(AUTODIRS).difference(SKIPDIRS)
     dirs[:] = list(candidates.intersection(dirs))
     lines = open(makefile)
-    def stripsplit(line):
-      return filter(lambda c: c!="'", line[len('#requires'):]).split()
     conditions.update(set(tuple(stripsplit(line)) for line in lines if line.startswith('#requires')))
     lines.close()
     def relpath(filename):
     sourcecu = makevars.get('SOURCECU','').split()
     sourcec = makevars.get('SOURCEC','').split()
     sourcef = makevars.get('SOURCEF','').split()
-    compareSourceLists(sourcec+sourcef+sourcecu, files) # Diagnostic output about unused source files
+    mistakes.compareSourceLists(root,sourcec+sourcef+sourcecu, files) # Diagnostic output about unused source files
     sources[repr(sorted(conditions))].extend(relpath(f) for f in sourcec + sourcef + sourcecu)
     allconditions[root] = conditions
   return sources
 
 ''')
 
-def writePackage(f,pkg,pkgdeps):
-  for conds, srcs in pkgsources(pkg).items():
+def writePackage(f,pkg,pkgdeps,mistakes):
+  for conds, srcs in pkgsources(pkg,mistakes).items():
     conds = eval(conds)
     def body(indentlevel):
       indent = ' '*(indentlevel+2)
 endif ()
 ''' % dict(pkg=pkg, PKG=pkg.upper(), pkgdeps=' '.join('petsc%s'%p for p in pkgdeps)))
 
-def main(petscdir, log=StdoutLogger()):
+def main(petscdir, log=StdoutLogger(), verbose=False):
   import tempfile, shutil
   written = False               # We delete the temporary file if it wasn't finished, otherwise rename (atomic)
+  mistakes = Mistakes(log=log, verbose=verbose)
   fd,tmplists = tempfile.mkstemp(prefix='CMakeLists.txt.',dir=petscdir,text=True)
   try:
     f = os.fdopen(fd,'w')
                ('snes'           , 'ksp dm mat vec sys'),
                ('ts'             , 'snes ksp dm mat vec sys')]
     for pkg,deps in pkglist:
-      writePackage(f,pkg,deps.split())
+      writePackage(f,pkg,deps.split(),mistakes)
     f.write ('''
 if (PETSC_USE_SINGLE_LIBRARY)
   if (PETSC_HAVE_CUDA)
       shutil.move(tmplists,os.path.join(petscdir,'CMakeLists.txt'))
     else:
       os.remove(tmplists)
-  if MISTAKES:
-    for m in MISTAKES:
-      log.write(m + '\n')
-    raise RuntimeError('PETSc makefiles contain mistakes or files are missing on filesystem.\n%s\nPossible reasons:\n\t1. Files were deleted locally, try "hg revert filename" or "git checkout filename".\n\t2. Files were deleted from repository, but were not removed from makefile. Send mail to petsc-maint@mcs.anl.gov.\n\t3. Someone forgot to "add" new files to the repository. Send mail to petsc-maint@mcs.anl.gov.' % ('\n'.join(MISTAKES)))
+  mistakes.summary()
 
 if __name__ == "__main__":
   import optparse
   parser = optparse.OptionParser()
   parser.add_option('--verbose', help='Show mismatches between makefiles and the filesystem', dest='verbose', action='store_true', default=False)
   (opts, extra_args) = parser.parse_args()
-  if opts.verbose:
-    VERBOSE = True
-  main(petscdir=os.environ['PETSC_DIR'])
+  main(petscdir=os.environ['PETSC_DIR'], verbose=opts.verbose)

File config/install.py

     self.setCompilers  = self.framework.require('config.setCompilers',         None)
     self.arch          = self.framework.require('PETSc.utilities.arch',        None)
     self.petscdir      = self.framework.require('PETSc.utilities.petscdir',    None)
-    self.makesys       = self.framework.require('config.programs',             None)
     self.compilers     = self.framework.require('config.compilers',            None)
     return
 
     self.rootShareDir      = os.path.join(self.rootDir, 'share')
     self.destShareDir      = os.path.join(self.destDir, 'share')
 
-    self.make        = self.makesys.make+' '+self.makesys.flags
     self.ranlib      = self.compilers.RANLIB
     self.arLibSuffix = self.compilers.AR_LIB_SUFFIX
     return
+# -*- mode: makefile-gmake -*-
+
+# If $(PETSC_ARCH) is empty, this defines it and PETSC_DIR
+include ./$(PETSC_ARCH)/conf/petscvariables
+include ./conf/variables
+
+OBJDIR := $(PETSC_ARCH)/obj
+LIBDIR := $(abspath $(PETSC_ARCH)/lib)
+
+pkgs := sys vec mat dm ksp snes ts
+
+libpetsc_shared := $(LIBDIR)/libpetsc.$(SL_LINKER_SUFFIX)
+libpetsc_static := $(LIBDIR)/libpetsc.$(AR_LIB_SUFFIX)
+libpetscpkgs_shared := $(foreach pkg, $(pkgs), $(LIBDIR)/libpetsc$(pkg).$(SL_LINKER_SUFFIX))
+libpetscpkgs_static := $(foreach pkg, $(pkgs), $(LIBDIR)/libpetsc$(pkg).$(AR_LIB_SUFFIX))
+
+ifeq ($(PETSC_WITH_EXTERNAL_LIB),)
+  libpetscall_shared := $(libpetscpkgs_shared)
+  libpetscall_static := $(libpetscpkgs_static)
+else
+  libpetscall_shared := $(libpetsc_shared)
+  libpetscall_static := $(libpetsc_static)
+endif
+libpetscall := $(if $(filter-out no,$(BUILDSHAREDLIB)),$(libpetscall_shared),$(libpetscall_static))
+
+generated := $(PETSC_ARCH)/conf/files
+
+all : $(generated) $(libpetscall)
+
+.SECONDEXPANSION:		# to expand $$(@D)/.DIR
+
+#workarround old cygwin versions
+ifeq ($(PETSC_CYGWIN_BROKEN_PIPE),1)
+ifeq ($(shell basename $(AR)),ar)
+  V ?=1
+endif
+endif
+ifeq ($(V),)
+  quiet_HELP := "Use \"$(MAKE) V=1\" to see the verbose compile lines.\n"
+  quiet = @printf $(quiet_HELP)$(eval quiet_HELP:=)"  %10s %s\n" "$1$2" "$@"; $($1)
+else ifeq ($(V),0)		# Same, but do not print any help
+  quiet = @printf "  %10s %s\n" "$1$2" "$@"; $($1)
+else				# Show the full command line
+  quiet = $($1)
+endif
+
+$(PETSC_ARCH)/conf/files :
+	$(PYTHON) conf/gmakegen.py --petsc-arch=$(PETSC_ARCH)
+
+-include $(generated)
+
+ifeq ($(PETSC_LANGUAGE),CXXONLY)
+  cc_name := CXX
+else
+  cc_name := CC
+endif
+
+PETSC_COMPILE.c = $(call quiet,$(cc_name)) -c $(PCC_FLAGS) $(CFLAGS) $(CCPPFLAGS) $(C_DEPFLAGS)
+PETSC_COMPILE.cxx = $(call quiet,CXX) -c $(PCC_FLAGS) $(CFLAGS) $(CCPPFLAGS) $(CXX_DEPFLAGS)
+PETSC_COMPILE.cu = $(call quiet,CUDAC) -c $(CUDAC_FLAGS) --compiler-options="$(PCC_FLAGS) $(CXXFLAGS) $(CCPPFLAGS)"
+PETSC_GENDEPS.cu = $(call quiet,CUDAC,.dep) --generate-dependencies $(CUDAC_FLAGS) --compiler-options="$(PCC_FLAGS) $(CXXFLAGS) $(CCPPFLAGS)"
+PETSC_COMPILE.F = $(call quiet,FC) -c $(FC_FLAGS) $(FFLAGS) $(FCPPFLAGS) $(FC_DEPFLAGS)
+
+langs := c cu cxx F
+concatlang = $(foreach lang, $(langs), $(srcs-$(1).$(lang):%.$(lang)=$(OBJDIR)/%.o))
+srcs.o := $(foreach pkg, $(pkgs), $(call concatlang,$(pkg)))
+
+# with-single-library=1 (default)
+$(libpetsc_shared) : $(srcs.o) | $$(@D)/.DIR
+	$(call quiet,CLINKER) -shared -o $@ $^ $(PETSC_EXTERNAL_LIB_BASIC)
+
+$(libpetsc_static) : obj := $(srcs.o)
+
+define ARCHIVE_RECIPE_WIN32FE_LIB
+  @$(RM) $@ $@.args
+  @cygpath -w $^ > $@.args
+  $(call quiet,AR) $(AR_FLAGS) $@ @$@.args
+  @$(RM) $@.args
+endef
+
+define ARCHIVE_RECIPE_DEFAULT
+  @$(RM) $@
+  $(call quiet,AR) $(AR_FLAGS) $@ $^
+  $(call quiet,RANLIB) $@
+endef
+
+%.$(AR_LIB_SUFFIX) : $$(obj) | $$(@D)/.DIR
+	$(if $(findstring win32fe lib,$(AR)),$(ARCHIVE_RECIPE_WIN32FE_LIB),$(ARCHIVE_RECIPE_DEFAULT))
+
+# with-single-library=0
+libpkg = $(foreach pkg, $1, $(LIBDIR)/libpetsc$(pkg).$(SL_LINKER_SUFFIX))
+$(LIBDIR)/libpetscsys.$(SL_LINKER_SUFFIX)  : obj    := $(call concatlang,sys)
+$(LIBDIR)/libpetscvec.$(SL_LINKER_SUFFIX)  : obj    := $(call concatlang,vec)
+$(LIBDIR)/libpetscvec.$(SL_LINKER_SUFFIX)  : libdep := $(call libpkg,sys)
+$(LIBDIR)/libpetscmat.$(SL_LINKER_SUFFIX)  : obj    := $(call concatlang,mat)
+$(LIBDIR)/libpetscmat.$(SL_LINKER_SUFFIX)  : libdep := $(call libpkg,vec sys)
+$(LIBDIR)/libpetscdm.$(SL_LINKER_SUFFIX)   : obj    := $(call concatlang,dm)
+$(LIBDIR)/libpetscdm.$(SL_LINKER_SUFFIX)   : libdep := $(call libpkg,mat vec sys)
+$(LIBDIR)/libpetscksp.$(SL_LINKER_SUFFIX)  : obj    := $(call concatlang,ksp)
+$(LIBDIR)/libpetscksp.$(SL_LINKER_SUFFIX)  : libdep := $(call libpkg,dm mat vec sys)
+$(LIBDIR)/libpetscsnes.$(SL_LINKER_SUFFIX) : obj    := $(call concatlang,snes)
+$(LIBDIR)/libpetscsnes.$(SL_LINKER_SUFFIX) : libdep := $(call libpkg,ksp dm mat vec sys)
+$(LIBDIR)/libpetscts.$(SL_LINKER_SUFFIX)   : obj    := $(call concatlang,ts)
+$(LIBDIR)/libpetscts.$(SL_LINKER_SUFFIX)   : libdep := $(call libpkg,snes ksp dm mat vec sys)
+$(LIBDIR)/libpetscsys.$(AR_LIB_SUFFIX)  : $(call concatlang,sys)
+$(LIBDIR)/libpetscvec.$(AR_LIB_SUFFIX)  : $(call concatlang,vec)
+$(LIBDIR)/libpetscmat.$(AR_LIB_SUFFIX)  : $(call concatlang,mat)
+$(LIBDIR)/libpetscdm.$(AR_LIB_SUFFIX)   : $(call concatlang,dm)
+$(LIBDIR)/libpetscksp.$(AR_LIB_SUFFIX)  : $(call concatlang,ksp)
+$(LIBDIR)/libpetscsnes.$(AR_LIB_SUFFIX) : $(call concatlang,snes)
+$(LIBDIR)/libpetscts.$(AR_LIB_SUFFIX)   : $(call concatlang,ts)
+
+# The package libraries technically depend on each other (not just in an order-only way), but only
+# ABI changes like new or removed symbols requires relinking the dependent libraries.  ABI should
+# only occur when a header is changed, which would trigger recompilation and relinking anyway.
+# RELINK=1 causes dependent libraries to be relinked anyway.
+ifeq ($(RELINK),1)
+  libdep_true = $$(libdep)
+  libdep_order =
+else
+  libdep_true =
+  libdep_order = $$(libdep)
+endif
+$(libpetscpkgs_shared) : $$(obj) $(libdep_true) | $(libdep_order) $$(@D)/.DIR
+	$(call quiet,CLINKER) -shared -o $@ $(obj) $(libdep) $(PETSC_EXTERNAL_LIB_BASIC)
+
+$(OBJDIR)/%.o : %.c | $$(@D)/.DIR
+	$(PETSC_COMPILE.c) $< -o $@
+
+$(OBJDIR)/%.o : %.cxx | $$(@D)/.DIR
+	$(PETSC_COMPILE.cxx) $< -o $@
+
+$(OBJDIR)/%.o : %.cu | $$(@D)/.DIR
+	$(PETSC_COMPILE.cu) $< -o $@ # Compile first so that if there is an error, it comes from a normal compile
+	@$(PETSC_GENDEPS.cu) $< -o $(@:%.o=%.d) # Generate the dependencies for later
+
+$(OBJDIR)/%.o : %.F | $$(@D)/.DIR
+ifeq ($(FC_MODULE_OUTPUT_FLAG),)
+	cd $(PETSC_ARCH)/include && $(FC) -c $(FC_FLAGS) $(FFLAGS) $(FCPPFLAGS) $(FC_DEPFLAGS) ../../$< -o ../../$@
+else
+	$(PETSC_COMPILE.F) $< -o $@ $(FC_MODULE_OUTPUT_FLAG)$(PETSC_ARCH)/include
+endif
+
+%/.DIR :
+	@mkdir -p $(@D)
+	@touch $@
+
+.PRECIOUS: %/.DIR
+
+.SUFFIXES: # Clear .SUFFIXES because we don't use implicit rules
+.DELETE_ON_ERROR:               # Delete likely-corrupt target file if rule fails
+
+.PHONY: clean all print
+
+clean:
+	rm -rf $(OBJDIR) $(LIBDIR)/libpetsc* $(PETSC_ARCH)/include/*.mod $(generated)
+
+# make print VAR=the-variable
+print:
+	@echo $($(VAR))
+
+allobj.d := $(srcs.o:%.o=%.d)
+# Tell make that allobj.d are all up to date.  Without this, the include
+# below has quadratic complexity, taking more than one second for a
+# do-nothing build of PETSc (much worse for larger projects)
+$(allobj.d) : ;
+
+-include $(allobj.d)

File include/petsc-private/petscimpl.h

   MPI_Comm             comm;
   PetscInt             type;
   PetscLogDouble       flops,time,mem,memchildren;
-  PetscInt             id;
+  PetscObjectId        id;
   PetscInt             refct;
   PetscMPIInt          tag;
   PetscFunctionList    qlist;
   char                 *mansec;
   char                 *type_name;     /*  this is the subclass, for example VECSEQ which equals "seq" */
   PetscObject          parent;
-  PetscInt             parentid;
+  PetscObjectId        parentid;
   char*                name;
   char                 *prefix;
   PetscInt             tablevel;
   void                 *cpp;
-  PetscInt             state;
+  PetscObjectState     state;
   PetscInt             int_idmax,        intstar_idmax;
-  PetscInt             *intcomposedstate,*intstarcomposedstate;
+  PetscObjectState     *intcomposedstate,*intstarcomposedstate;
   PetscInt             *intcomposeddata, **intstarcomposeddata;
   PetscInt             real_idmax,        realstar_idmax;
-  PetscInt             *realcomposedstate,*realstarcomposedstate;
+  PetscObjectState     *realcomposedstate,*realstarcomposedstate;
   PetscReal            *realcomposeddata, **realstarcomposeddata;
   PetscInt             scalar_idmax,        scalarstar_idmax;
-  PetscInt             *scalarcomposedstate,*scalarstarcomposedstate;
+  PetscObjectState     *scalarcomposedstate,*scalarstarcomposedstate;
   PetscScalar          *scalarcomposeddata, **scalarstarcomposeddata;
   void                 (**fortran_func_pointers)(void);                  /* used by Fortran interface functions to stash user provided Fortran functions */
   PetscInt             num_fortran_func_pointers;                        /* number of Fortran function pointers allocated */
    #include "petscsys.h"
    PetscErrorCode PetscObjectStateIncrease(PetscObject obj)
 
-   Not Collective
+   Logically Collective
 
    Input Parameter:
 .  obj - any PETSc object, for example a Vec, Mat or KSP. This must be
    as VecSet() or MatScale() already call this routine. It is also called, as a
    precaution, in VecRestoreArray(), MatRestoreRow(), MatDenseRestoreArray().
 
-   Level: developer
-
-   seealso: PetscObjectStateQuery(), PetscObjectStateDecrease()
-
-   Concepts: state
-
-M*/
-#define PetscObjectStateIncrease(obj) ((obj)->state++,0)
-
-/*MC
-   PetscObjectStateDecrease - Decreases the state of any PetscObject,
-   regardless of the type.
-
-   Synopsis:
-   #include "petscsys.h"
-   PetscErrorCode PetscObjectStateDecrease(PetscObject obj)
-
-   Not Collective
-
-   Input Parameter:
-.  obj - any PETSc object, for example a Vec, Mat or KSP. This must be
-         cast with a (PetscObject), for example,
-         PetscObjectStateIncrease((PetscObject)mat);
-
-   Notes: object state is an integer which gets increased every time
-   the object is changed. By saving and later querying the object state
-   one can determine whether information about the object is still current.
-   Currently, state is maintained for Vec and Mat objects.
+   This routine is logically collective because state equality comparison needs to be possible without communication.
 
    Level: developer
 
-   seealso: PetscObjectStateQuery(), PetscObjectStateIncrease()
+   seealso: PetscObjectStateGet()
 
    Concepts: state
 
 M*/
-#define PetscObjectStateDecrease(obj) ((obj)->state--,0)
+#define PetscObjectStateIncrease(obj) ((obj)->state++,0)
 
-PETSC_EXTERN PetscErrorCode PetscObjectStateQuery(PetscObject,PetscInt*);
-PETSC_EXTERN PetscErrorCode PetscObjectSetState(PetscObject,PetscInt);
+PETSC_EXTERN PetscErrorCode PetscObjectStateGet(PetscObject,PetscObjectState*);
+PETSC_EXTERN PetscErrorCode PetscObjectStateSet(PetscObject,PetscObjectState);
 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataRegister(PetscInt*);
 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseInt(PetscObject);
 PETSC_EXTERN PetscErrorCode PetscObjectComposedDataIncreaseIntstar(PetscObject);
         PetscObjectComposedDataGetRealstar(obj,id,data,flag)
 #endif
 
+PETSC_EXTERN PetscErrorCode PetscObjectGetId(PetscObject,PetscObjectId*);
+
 PETSC_EXTERN PetscMPIInt Petsc_Counter_keyval;
 PETSC_EXTERN PetscMPIInt Petsc_InnerComm_keyval;
 PETSC_EXTERN PetscMPIInt Petsc_OuterComm_keyval;

File include/petsc-private/tsimpl.h

   struct {
     PetscReal time;             /* The time at which the matrices were last evaluated */
     Vec X;                      /* Solution vector at which the Jacobian was last evaluated */
-    PetscInt Xstate;            /* State of the solution vector */
+    PetscObjectState Xstate;    /* State of the solution vector */
     MatStructure mstructure;    /* The structure returned */
     /* Flag to unshift Jacobian before calling the IJacobian or RHSJacobian functions.  This is useful
      * if the user would like to reuse (part of) the Jacobian from the last evaluation. */

File include/petscerror.h

 #define __PETSCERROR_H
 
 /*
-   Defines the directory where the compiled source is located; used
-   in printing error messages. Each makefile has an entry
-   LOCDIR  =  thedirectory
-   and bmake/common_variables includes in CCPPFLAGS -D__SDIR__=${LOCDIR}
-   which is a flag passed to the C/C++ compilers. This declaration below
-   is only needed if some code is compiled without the -D__SDIR__
-*/
-#if !defined(__INSDIR__)
-#define __INSDIR__ "unknowndirectory/"
-#endif
-
-/*
    Defines the function where the compiled source is located; used
    in printing error messages. This is defined here in case the user
    does not declare it.
 
 #define PetscStringizeArg(a) #a
 #define PetscStringize(a) PetscStringizeArg(a)
-#define __SDIR__ PetscStringize(__INSDIR__)
+#define __SDIR__ ""
 
 #if defined(PETSC_USE_ERRORCHECKING)
 
     PetscStrcmpNoError(PETSC_FUNCTION_NAME,__FUNCT__,&_sc1);\
     PetscStrcmpNoError(__FUNCT__,"User provided function",&_sc2);\
     if (!_sc1 && !_sc2) { \
-      printf("%s%s:%d: __FUNCT__=\"%s\" does not agree with %s=\"%s\"\n",__SDIR__,__FILE__,__LINE__,__FUNCT__,PetscStringize(PETSC_FUNCTION_NAME),PETSC_FUNCTION_NAME); \
+      printf("%s:%d: __FUNCT__=\"%s\" does not agree with %s=\"%s\"\n",__FILE__,__LINE__,__FUNCT__,PetscStringize(PETSC_FUNCTION_NAME),PETSC_FUNCTION_NAME); \
     }                                                                   \
   } while (0)
 

File include/petscsys.h

 S*/
 typedef struct _p_PetscObject* PetscObject;
 
+/*MC
+    PetscObjectId - unique integer Id for a PetscObject
+
+    Level: developer
+
+    Notes: Unlike pointer values, object ids are never reused.
+
+.seealso: PetscObjectState, PetscObjectGetId()
+M*/
+typedef Petsc64bitInt PetscObjectId;
+
+/*MC
+    PetscObjectState - integer state for a PetscObject
+
+    Level: developer
+
+    Notes:
+    Object state is always-increasing and (for objects that track state) can be used to determine if an object has
+    changed since the last time you interacted with it.  It is 64-bit so that it will not overflow for a very long time.
+
+.seealso: PetscObjectId, PetscObjectStateQuery(), PetscObjectStateIncrease(), PetscObjectStateSet()
+M*/
+typedef Petsc64bitInt PetscObjectState;
+
 /*S
      PetscFunctionList - Linked list of functions, possibly stored in dynamic libraries, accessed
       by string name
 all: chk_makej
 	@${OMAKE}  PETSC_ARCH=${PETSC_ARCH}  PETSC_DIR=${PETSC_DIR} chk_petscdir chk_upgrade | tee ${PETSC_ARCH}/conf/make.log
 	@ln -sf ${PETSC_ARCH}/conf/make.log make.log
-	@if [ "${PETSC_BUILD_USING_CMAKE}" != "" ]; then \
+	@if [ "${PETSC_BUILD_USING_GNUMAKE}" != "" ]; then \
+	   ${OMAKE} PETSC_ARCH=${PETSC_ARCH} PETSC_DIR=${PETSC_DIR} all-gnumake-local 2>&1 | tee -a ${PETSC_ARCH}/conf/make.log; \
+	elif [ "${PETSC_BUILD_USING_CMAKE}" != "" ]; then \
 	   ${OMAKE} PETSC_ARCH=${PETSC_ARCH} PETSC_DIR=${PETSC_DIR} all-cmake-local 2>&1 | tee -a ${PETSC_ARCH}/conf/make.log \
 		| egrep -v '( --check-build-system |cmake -E | -o CMakeFiles/petsc[[:lower:]]*.dir/| -o lib/libpetsc|CMakeFiles/petsc[[:lower:]]*\.dir/(build|depend|requires)|-f CMakeFiles/Makefile2|Dependee .* is newer than depender |provides\.build. is up to date)'; \
 	 else \
         fi #solaris make likes to print the whole command that gave error. So split this up into the smallest chunk below
 	@if test -s ${PETSC_ARCH}/conf/error.log; then exit 1; fi
 
+all-gnumake:
+	@if [ "${PETSC_BUILD_USING_GNUMAKE}" != "" ]; then \
+          ${OMAKE}  PETSC_ARCH=${PETSC_ARCH}  PETSC_DIR=${PETSC_DIR} PETSC_BUILD_USING_CMAKE="" all;\
+        else printf ${PETSC_TEXT_HILIGHT}"Build not configured for GNUMAKE. Quiting"${PETSC_TEXT_NORMAL}"\n"; exit 1; fi
+
 all-cmake:
 	@if [ "${PETSC_BUILD_USING_CMAKE}" != "" ]; then \
-          ${OMAKE}  PETSC_ARCH=${PETSC_ARCH}  PETSC_DIR=${PETSC_DIR} all;\
+          ${OMAKE}  PETSC_ARCH=${PETSC_ARCH}  PETSC_DIR=${PETSC_DIR} PETSC_BUILD_USING_GNUMAKE="" all;\
         else printf ${PETSC_TEXT_HILIGHT}"Build not configured for CMAKE. Quiting"${PETSC_TEXT_NORMAL}"\n"; exit 1; fi
 
 all-legacy:
-	@${OMAKE}  PETSC_ARCH=${PETSC_ARCH}  PETSC_DIR=${PETSC_DIR} PETSC_BUILD_USING_CMAKE="" all
+	@${OMAKE}  PETSC_ARCH=${PETSC_ARCH}  PETSC_DIR=${PETSC_DIR} PETSC_BUILD_USING_CMAKE="" PETSC_BUILD_USING_GNUMAKE="" all
+
+all-gnumake-local: chk_makej info gnumake
 
 all-cmake-local: chk_makej info cmakegen cmake
 

File src/dm/impls/plex/examples/makefile

 ALL:
 
 LOCDIR	 = src/dm/impls/plex/examples/
-DIRS	 = tests
+DIRS	 = tests tutorials
 
 include ${PETSC_DIR}/conf/variables
 include ${PETSC_DIR}/conf/rules

File src/dm/impls/plex/examples/tutorials/makefile

+CFLAGS	        =
+FFLAGS	        =
+CPPFLAGS        =
+FPPFLAGS        =
+LOCDIR          = src/dm/impls/plex/examples/tutorials
+EXAMPLESC       = ex1.c
+EXAMPLESF       = ex1f90.F
+MANSEC          = DM
+
+include ${PETSC_DIR}/conf/variables
+include ${PETSC_DIR}/conf/rules
+
+ex1: ex1.o  chkopts
+	-${CLINKER} -o ex1 ex1.o ${PETSC_DM_LIB}
+	${RM} -f ex1.o
+
+ex1f90: ex1f90.o  chkopts
+	-${FLINKER} -o ex1f90 ex1f90.o  ${PETSC_DM_LIB}
+	${RM} -f ex1f90.o
+
+#--------------------------------------------------------------------------
+
+include ${PETSC_DIR}/conf/test

File src/docs/website/developers/index.html

         <li><a href="#master-tarball">access tarballs directly from 'master' branch.</a></li>
         <li><a href="#nightly-tarball">access the nightly tarball snapshot</a> at <a href="http://ftp.mcs.anl.gov/pub/petsc/petsc-dev.tar.gz">http://ftp.mcs.anl.gov/pub/petsc/petsc-dev.tar.gz</a></li>
       </ol>
-      (If you prefer <a href="http://www.selenic.com/mercurial">Mercurial</a> over Git, there is also a <a href=" https://bitbucket.org/petsc/petsc-hg">Mercurial mirror of the PETSc master branch</a> available.)
 
       <a name="using-git"><h3>1. Using Git</h3></a><a href="http://git-scm.com/downloads">Install Git</a> if it is not already installed on your machine.
 

File src/docs/website/documentation/changes/dev.html

       </div>
 
       <h4>General:</h4>
+      <ul>
+        <li>PetscObjectStateQuery() is now corrected with PetscObjectStateGet()</li>
+        <li>A new PetscObjectState typedef is used by interface; 64-bit int to prevent overflow.</li>
+      </ul>
       <h4>IS:</h4>
       <h4>PF:</h4>
       <h4>Vec:</h4>

File src/ksp/ksp/examples/tutorials/ex54.c

 #endif
   ierr = VecSet(xx,.0);CHKERRQ(ierr);
 
+  ierr = KSPSetUp(ksp);CHKERRQ(ierr);
+
   ierr = KSPSolve(ksp,bb,xx);CHKERRQ(ierr);
 
 #if defined(PETSC_USE_LOG)

File src/ksp/ksp/examples/tutorials/makefile

 runex54_Classical:
 	-@${MPIEXEC} -n 4 ./ex54 -ne 109 -alpha 1.e-3 -ksp_monitor_short -ksp_type cg -pc_gamg_type classical -ksp_converged_reason -pc_gamg_coarse_eq_limit 80 -mg_levels_ksp_type chebyshev -mg_levels_ksp_chebyshev_estimate_eigenvalues 0,0.05,0,1.05 -mg_levels_pc_type jacobi > ex54_classical.tmp 2>&1; \
          ${DIFF} output/ex54_classical.out ex54_classical.tmp || echo ${PWD} "\nPossible problem with with ex54_Classical, diffs above \n======================================"; \
-        #${RM} -f ex54_classical.tmp
+        ${RM} -f ex54_classical.tmp
 
 runex54f:
 	-@${MPIEXEC} -n 4 ./ex54f -ne 59 -theta 30.0 -epsilon 1.e-1 -ksp_monitor_short -ksp_type cg -pc_type gamg -pc_gamg_type agg -pc_gamg_agg_nsmooths 1 -ksp_converged_reason  -pc_gamg_coarse_eq_limit 80 -blob_center 0.,0. -mat_coarsen_type hem -pc_gamg_square_graph false > ex54f.tmp 2>&1; \
 runex55_Classical:
 	-@${MPIEXEC} -n 4 ./ex55 -ne 29 -alpha 1.e-3 -ksp_monitor_short -ksp_type gmres -pc_gamg_type classical -ksp_converged_reason -pc_gamg_coarse_eq_limit 80 -mg_levels_ksp_type chebyshev -mg_levels_pc_type sor -mg_levels_ksp_max_it 5 > ex55_classical.tmp 2>&1; \
          ${DIFF} output/ex55_classical.out ex55_classical.tmp || echo ${PWD} "\nPossible problem with with ex55_Classical, diffs above \n========================================="; \
-        #${RM} -f ex55_classical.tmp
+        ${RM} -f ex55_classical.tmp
 
 runex55_NC:
 	-@${MPIEXEC} -n 4 ./ex55 -ne 29 -alpha 1.e-3 -ksp_monitor_short -ksp_type cg -pc_gamg_type agg -pc_gamg_agg_nsmooths 1  -ksp_converged_reason -pc_gamg_coarse_eq_limit 80 -mg_levels_ksp_type chebyshev -mg_levels_ksp_chebyshev_estimate_eigenvalues 0,0.05,0,1.05 -mg_levels_pc_type jacobi > ex55_nc.tmp 2>&1; \

File src/mat/impls/aij/seq/aij.c

         if (xb == b) {
           x[i] = sum*idiag[i];
         } else {
-          x[i] = (1-omega)*x[i] + sum*idiag[i];
+          x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
         }
       }
-      ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
+      ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
     }
     its--;
   }
   while (its--) {
     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
       for (i=0; i<m; i++) {
-        n   = a->i[i+1] - a->i[i];
+        /* lower */
+        n   = diag[i] - a->i[i];
         idx = a->j + a->i[i];
         v   = a->a + a->i[i];
         sum = b[i];
         PetscSparseDenseMinusDot(sum,x,v,idx,n);
-        x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
+        t[i] = sum;             /* save application of the lower-triangular part */
+        /* upper */
+        n   = a->i[i+1] - diag[i] - 1;
+        idx = a->j + diag[i] + 1;
+        v   = a->a + diag[i] + 1;
+        PetscSparseDenseMinusDot(sum,x,v,idx,n);
+        x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
       }
+      xb   = t;
       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
-    }
+    } else xb = b;
     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
       for (i=m-1; i>=0; i--) {
-        n   = a->i[i+1] - a->i[i];
-        idx = a->j + a->i[i];
-        v   = a->a + a->i[i];
-        sum = b[i];
-        PetscSparseDenseMinusDot(sum,x,v,idx,n);
-        x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
+        sum = xb[i];
+        if (xb == b) {
+          /* whole matrix (no checkpointing available) */
+          n   = a->i[i+1] - a->i[i];
+          idx = a->j + a->i[i];
+          v   = a->a + a->i[i];
+          PetscSparseDenseMinusDot(sum,x,v,idx,n);
+          x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
+        } else { /* lower-triangular part has been saved, so only apply upper-triangular */
+          n   = a->i[i+1] - diag[i] - 1;
+          idx = a->j + diag[i] + 1;
+          v   = a->a + diag[i] + 1;
+          PetscSparseDenseMinusDot(sum,x,v,idx,n);
+          x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
+        }
+      }
+      if (xb == b) {
+        ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
+      } else {
+        ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
       }
-      ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
     }
   }
   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);

File src/mat/impls/aij/seq/inode.c

   while (its--) {
 
     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
-      ibdiag = a->inode.ibdiag;
+      for (i=0, row=0, ibdiag = a->inode.ibdiag;
+           i<m;
+           row += sizes[i], ibdiag += sizes[i]*sizes[i], i++) {
 
-      for (i=0, row=0; i<m; i++) {
-        sz  = ii[row + 1] - ii[row];
+        sz  = diag[row] - ii[row];
         v1  = a->a + ii[row];
         idx = a->j + ii[row];
-
         /* see comments for MatMult_SeqAIJ_Inode() for how this is coded */
         switch (sizes[i]) {
         case 1:
-
           sum1 = b[row];
           for (n = 0; n<sz-1; n+=2) {
             i1    = idx[0];
             tmp1  = x[i2];
             sum1 -= v1[0] * tmp0 + v1[1] * tmp1; v1 += 2;
           }
-
           if (n == sz-1) {
-            tmp0  = x[*idx];
+            tmp0  = x[*idx++];
+            sum1 -= *v1 * tmp0;
+            v1++;
+          }
+          t[row]   = sum1;
+          sz      = ii[row+1] - diag[row] - 1;
+          idx     = a->j + diag[row] + 1;
+          v1 += 1;
+          for (n = 0; n<sz-1; n+=2) {
+            i1    = idx[0];
+            i2    = idx[1];
+            idx  += 2;
+            tmp0  = x[i1];
+            tmp1  = x[i2];
+            sum1 -= v1[0] * tmp0 + v1[1] * tmp1; v1 += 2;
+          }
+          if (n == sz-1) {
+            tmp0  = x[*idx++];
             sum1 -= *v1 * tmp0;
           }
-
           /* in MatSOR_SeqAIJ this line would be
            *
            * x[row] = (1-omega)*x[row]+(sum1+(*bdiag++)*x[row])*(*ibdiag++);
            *
            * but omega == 1, so this becomes
            *
-           * x[row] = (sum1+(*bdiag++)*x[row])*(*ibdiag++);
+           * x[row] = sum1*(*ibdiag++);
            *
-           * but bdiag and ibdiag cancel each other, so we can change this
-           * to adding sum1*(*ibdiag++).  We can skip bdiag for the larger
-           * block sizes as well
            */
-          x[row++] += sum1*(*ibdiag++);
+          x[row] = sum1*(*ibdiag);
           break;
         case 2:
           v2   = a->a + ii[row+1];
             sum1 -= v1[0] * tmp0 + v1[1] * tmp1; v1 += 2;
             sum2 -= v2[0] * tmp0 + v2[1] * tmp1; v2 += 2;
           }
-
+          if (n == sz-1) {
+            tmp0  = x[*idx++];
+            sum1 -= v1[0] * tmp0;
+            sum2 -= v2[0] * tmp0;
+            v1++; v2++;
+          }
+          t[row]   = sum1;
+          t[row+1] = sum2;
+          sz      = ii[row+1] - diag[row] - 2;
+          idx     = a->j + diag[row] + 2;
+          v1 += 2;
+          v2 += 2;
+          for (n = 0; n<sz-1; n+=2) {
+            i1    = idx[0];
+            i2    = idx[1];
+            idx  += 2;
+            tmp0  = x[i1];
+            tmp1  = x[i2];
+            sum1 -= v1[0] * tmp0 + v1[1] * tmp1; v1 += 2;
+            sum2 -= v2[0] * tmp0 + v2[1] * tmp1; v2 += 2;
+          }
           if (n == sz-1) {
             tmp0  = x[*idx];
             sum1 -= v1[0] * tmp0;
             sum2 -= v2[0] * tmp0;
           }
-          x[row++] += sum1*ibdiag[0] + sum2*ibdiag[2];
-          x[row++] += sum1*ibdiag[1] + sum2*ibdiag[3];
-          ibdiag   += 4;
+          x[row] = sum1*ibdiag[0] + sum2*ibdiag[2];
+          x[row+1] = sum1*ibdiag[1] + sum2*ibdiag[3];
           break;
         case 3:
           v2   = a->a + ii[row+1];
             sum2 -= v2[0] * tmp0 + v2[1] * tmp1; v2 += 2;
             sum3 -= v3[0] * tmp0 + v3[1] * tmp1; v3 += 2;
           }
-
           if (n == sz-1) {
-            tmp0  = x[*idx];
+            tmp0  = x[*idx++];
             sum1 -= v1[0] * tmp0;
             sum2 -= v2[0] * tmp0;
             sum3 -= v3[0] * tmp0;
+            v1++; v2++; v3++;
           }
-          x[row++] += sum1*ibdiag[0] + sum2*ibdiag[3] + sum3*ibdiag[6];
-          x[row++] += sum1*ibdiag[1] + sum2*ibdiag[4] + sum3*ibdiag[7];
-          x[row++] += sum1*ibdiag[2] + sum2*ibdiag[5] + sum3*ibdiag[8];
-          ibdiag   += 9;
-          break;
-        case 4:
-          v2   = a->a + ii[row+1];
-          v3   = a->a + ii[row+2];
-          v4   = a->a + ii[row+3];
-          sum1 = b[row];
-          sum2 = b[row+1];
-          sum3 = b[row+2];
-          sum4 = b[row+3];
+          t[row]   = sum1;
+          t[row+1] = sum2;
+          t[row+2] = sum3;
+          sz      = ii[row+1] - diag[row] - 3;
+          idx     = a->j + diag[row] + 3;
+          v1 += 3;
+          v2 += 3;
+          v3 += 3;
           for (n = 0; n<sz-1; n+=2) {
             i1    = idx[0];
             i2    = idx[1];
             sum1 -= v1[0] * tmp0 + v1[1] * tmp1; v1 += 2;
             sum2 -= v2[0] * tmp0 + v2[1] * tmp1; v2 += 2;
             sum3 -= v3[0] * tmp0 + v3[1] * tmp1; v3 += 2;
-            sum4 -= v4[0] * tmp0 + v4[1] * tmp1; v4 += 2;
           }
-
           if (n == sz-1) {
             tmp0  = x[*idx];
             sum1 -= v1[0] * tmp0;
             sum2 -= v2[0] * tmp0;
             sum3 -= v3[0] * tmp0;
-            sum4 -= v4[0] * tmp0;
           }
-          x[row++] += sum1*ibdiag[0] + sum2*ibdiag[4] + sum3*ibdiag[8] + sum4*ibdiag[12];
-          x[row++] += sum1*ibdiag[1] + sum2*ibdiag[5] + sum3*ibdiag[9] + sum4*ibdiag[13];
-          x[row++] += sum1*ibdiag[2] + sum2*ibdiag[6] + sum3*ibdiag[10] + sum4*ibdiag[14];
-          x[row++] += sum1*ibdiag[3] + sum2*ibdiag[7] + sum3*ibdiag[11] + sum4*ibdiag[15];
-          ibdiag   += 16;
+          x[row] = sum1*ibdiag[0] + sum2*ibdiag[3] + sum3*ibdiag[6];
+          x[row+1] = sum1*ibdiag[1] + sum2*ibdiag[4] + sum3*ibdiag[7];
+          x[row+2] = sum1*ibdiag[2] + sum2*ibdiag[5] + sum3*ibdiag[8];
           break;
-        case 5:
+        case 4:
           v2   = a->a + ii[row+1];
           v3   = a->a + ii[row+2];
           v4   = a->a + ii[row+3];
-          v5   = a->a + ii[row+4];
           sum1 = b[row];
           sum2 = b[row+1];
           sum3 = b[row+2];
           sum4 = b[row+3];
-          sum5 = b[row+4];
           for (n = 0; n<sz-1; n+=2) {
             i1    = idx[0];
             i2    = idx[1];
             sum2 -= v2[0] * tmp0 + v2[1] * tmp1; v2 += 2;
             sum3 -= v3[0] * tmp0 + v3[1] * tmp1; v3 += 2;
             sum4 -= v4[0] * tmp0 + v4[1] * tmp1; v4 += 2;
-            sum5 -= v5[0] * tmp0 + v5[1] * tmp1; v5 += 2;
           }
-
           if (n == sz-1) {
-            tmp0  = x[*idx];
+            tmp0  = x[*idx++];
             sum1 -= v1[0] * tmp0;
             sum2 -= v2[0] * tmp0;
             sum3 -= v3[0] * tmp0;
             sum4 -= v4[0] * tmp0;
-            sum5 -= v5[0] * tmp0;
+            v1++; v2++; v3++; v4++;
           }
-          x[row++] += sum1*ibdiag[0] + sum2*ibdiag[5] + sum3*ibdiag[10] + sum4*ibdiag[15] + sum5*ibdiag[20];
-          x[row++] += sum1*ibdiag[1] + sum2*ibdiag[6] + sum3*ibdiag[11] + sum4*ibdiag[16] + sum5*ibdiag[21];
-          x[row++] += sum1*ibdiag[2] + sum2*ibdiag[7] + sum3*ibdiag[12] + sum4*ibdiag[17] + sum5*ibdiag[22];
-          x[row++] += sum1*ibdiag[3] + sum2*ibdiag[8] + sum3*ibdiag[13] + sum4*ibdiag[18] + sum5*ibdiag[23];
-          x[row++] += sum1*ibdiag[4] + sum2*ibdiag[9] + sum3*ibdiag[14] + sum4*ibdiag[19] + sum5*ibdiag[24];
-          ibdiag   += 25;
-          break;
-        default:
-          SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Inode size %D not supported",sizes[i]);
-        }
-      }
-
-      ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
-    }
-    if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
-
-      ibdiag = a->inode.ibdiag+a->inode.bdiagsize;
-      for (i=m-1, row=A->rmap->n-1; i>=0; i--) {
-        ibdiag -= sizes[i]*sizes[i];
-        sz      = ii[row+1] - ii[row];
-        v1      = a->a + ii[row];
-        idx     = a->j + ii[row];
-
-        /* see comments for MatMult_SeqAIJ_Inode() for how this is coded */
-        switch (sizes[i]) {
-        case 1:
-
-          sum1 = b[row];
-          for (n = 0; n<sz-1; n+=2) {
-            i1    = idx[0];
-            i2    = idx[1];
-            idx  += 2;
-            tmp0  = x[i1];
-            tmp1  = x[i2];
-            sum1 -= v1[0] * tmp0 + v1[1] * tmp1; v1 += 2;
-          }
-
-          if (n == sz-1) {
-            tmp0  = x[*idx];
-            sum1 -= *v1*tmp0;
-          }
-          x[row--] += sum1*(*ibdiag);
-          break;
-
-        case 2:
-
-          sum1 = b[row];
-          sum2 = b[row-1];
-          /* note that sum1 is associated with the second of the two rows */
-          v2 = a->a + ii[row - 1];
+          t[row]   = sum1;
+          t[row+1] = sum2;
+          t[row+2] = sum3;
+          t[row+3] = sum4;
+          sz      = ii[row+1] - diag[row] - 4;
+          idx     = a->j + diag[row] + 4;
+          v1 += 4;
+          v2 += 4;
+          v3 += 4;
+          v4 += 4;
           for (n = 0; n<sz-1; n+=2) {
             i1    = idx[0];
             i2    = idx[1];
             tmp1  = x[i2];
             sum1 -= v1[0] * tmp0 + v1[1] * tmp1; v1 += 2;
             sum2 -= v2[0] * tmp0 + v2[1] * tmp1; v2 += 2;
+            sum3 -= v3[0] * tmp0 + v3[1] * tmp1; v3 += 2;
+            sum4 -= v4[0] * tmp0 + v4[1] * tmp1; v4 += 2;
           }
-
           if (n == sz-1) {
             tmp0  = x[*idx];
-            sum1 -= *v1*tmp0;
-            sum2 -= *v2*tmp0;
+            sum1 -= v1[0] * tmp0;
+            sum2 -= v2[0] * tmp0;
+            sum3 -= v3[0] * tmp0;
+            sum4 -= v4[0] * tmp0;
           }
-          x[row--] += sum2*ibdiag[1] + sum1*ibdiag[3];
-          x[row--] += sum2*ibdiag[0] + sum1*ibdiag[2];
+          x[row] =   sum1*ibdiag[0] + sum2*ibdiag[4] + sum3*ibdiag[8] + sum4*ibdiag[12];
+          x[row+1] = sum1*ibdiag[1] + sum2*ibdiag[5] + sum3*ibdiag[9] + sum4*ibdiag[13];
+          x[row+2] = sum1*ibdiag[2] + sum2*ibdiag[6] + sum3*ibdiag[10] + sum4*ibdiag[14];
+          x[row+3] = sum1*ibdiag[3] + sum2*ibdiag[7] + sum3*ibdiag[11] + sum4*ibdiag[15];
           break;
-        case 3:
-
+        case 5:
+          v2   = a->a + ii[row+1];
+          v3   = a->a + ii[row+2];
+          v4   = a->a + ii[row+3];
+          v5   = a->a + ii[row+4];
           sum1 = b[row];
-          sum2 = b[row-1];
-          sum3 = b[row-2];
-          v2   = a->a + ii[row-1];
-          v3   = a->a + ii[row-2];
+          sum2 = b[row+1];
+          sum3 = b[row+2];
+          sum4 = b[row+3];
+          sum5 = b[row+4];
           for (n = 0; n<sz-1; n+=2) {
             i1    = idx[0];
             i2    = idx[1];
             sum1 -= v1[0] * tmp0 + v1[1] * tmp1; v1 += 2;
             sum2 -= v2[0] * tmp0 + v2[1] * tmp1; v2 += 2;
             sum3 -= v3[0] * tmp0 + v3[1] * tmp1; v3 += 2;
+            sum4 -= v4[0] * tmp0 + v4[1] * tmp1; v4 += 2;
+            sum5 -= v5[0] * tmp0 + v5[1] * tmp1; v5 += 2;
           }
-
           if (n == sz-1) {
-            tmp0  = x[*idx];
-            sum1 -= *v1*tmp0;
-            sum2 -= *v2*tmp0;
-            sum3 -= *v3*tmp0;
+            tmp0  = x[*idx++];
+            sum1 -= v1[0] * tmp0;
+            sum2 -= v2[0] * tmp0;
+            sum3 -= v3[0] * tmp0;
+            sum4 -= v4[0] * tmp0;
+            sum5 -= v5[0] * tmp0;
+            v1++; v2++; v3++; v4++; v5++;
           }
-          x[row--] += sum3*ibdiag[2] + sum2*ibdiag[5] + sum1*ibdiag[8];
-          x[row--] += sum3*ibdiag[1] + sum2*ibdiag[4] + sum1*ibdiag[7];
-          x[row--] += sum3*ibdiag[0] + sum2*ibdiag[3] + sum1*ibdiag[6];
-          break;
-        case 4:
-
-          sum1 = b[row];
-          sum2 = b[row-1];
-          sum3 = b[row-2];
-          sum4 = b[row-3];
-          v2   = a->a + ii[row-1];
-          v3   = a->a + ii[row-2];
-          v4   = a->a + ii[row-3];
+          t[row]   = sum1;
+          t[row+1] = sum2;
+          t[row+2] = sum3;