[cig-commits] r5688 - in short/3D/PyLith/branches/pylith-0.8/pylith3d: . module pylith3d

leif at geodynamics.org leif at geodynamics.org
Fri Jan 5 18:11:28 PST 2007


Author: leif
Date: 2007-01-05 18:11:26 -0800 (Fri, 05 Jan 2007)
New Revision: 5688

Added:
   short/3D/PyLith/branches/pylith-0.8/pylith3d/pylith3d/PetscUtil.py
Modified:
   short/3D/PyLith/branches/pylith-0.8/pylith3d/Makefile.am
   short/3D/PyLith/branches/pylith-0.8/pylith3d/module/setup.cc
   short/3D/PyLith/branches/pylith-0.8/pylith3d/pylith3d/Application.py
   short/3D/PyLith/branches/pylith-0.8/pylith3d/pylith3d/Pylith3d_setup.py
Log:
Implemented strict command-line processing.

Previously, Pyre-based PyLith command-line options and PETSc options
were mixed together.  This caused Pyre to issue warnings about the
unrecognized PETSc options, and PETSc to warn about the unrecognized
Pyre options.  (Pyre errors were degraded to warnings by giving
"--typos=relaxed" as a matter for course.)

Now, PETSc and Pyre options are cleanly separated.  (The use of
"--typos=relaxed" is discouraged.)  This is implemented as follows:

PETSc options are designated explicitly using a 'petsc' dummy
facility+component, which allows passing arbitrary options to PETSc:
"--petsc.xxx".  In addition, commonly-used/highly-relevant PETSc
options are listed in PyLith's inventory; so, for example, on can give
"-log_summary" instead of "-petsc.log_summary" (either one will work).
Finally, PyLith overrides the standard Pyre CommandlineParser with
PetscCommandlineParser, which mimics PETSc's command-line processing
logic.  This lets one write "-ksp_rtol 1e-09" (as is customary)
instead of "-ksp_rtol=1e-09".

~~~

Also: PetscInitialize() was being called twice; I removed the second
occurance.  The binding for PetscInitialize() was free()ing the 'argv'
passed to PETSc; this is potentially dangerous since PETSc maintains a
reference to this block, so now the 'argv' is not freed.


Modified: short/3D/PyLith/branches/pylith-0.8/pylith3d/Makefile.am
===================================================================
--- short/3D/PyLith/branches/pylith-0.8/pylith3d/Makefile.am	2007-01-05 22:33:03 UTC (rev 5687)
+++ short/3D/PyLith/branches/pylith-0.8/pylith3d/Makefile.am	2007-01-06 02:11:26 UTC (rev 5688)
@@ -27,7 +27,8 @@
 	pylith3d/MaterialModel/IsotropicLinearMaxwellViscoelasticESF.py \
 	pylith3d/MaterialModel/IsotropicPowerLawMaxwellViscoelastic.py \
 	pylith3d/MaterialModel/MaterialModel.py \
-	pylith3d/Materials.py
+	pylith3d/Materials.py \
+	pylith3d/PetscUtil.py
 
 # pypylith3d (libpylith3d + pylith3dmodule + embedded Python interpreter)
 INCLUDES = -I$(top_srcdir)/pylith3d/module -I$(PYTHON_INCDIR)

Modified: short/3D/PyLith/branches/pylith-0.8/pylith3d/module/setup.cc
===================================================================
--- short/3D/PyLith/branches/pylith-0.8/pylith3d/module/setup.cc	2007-01-05 22:33:03 UTC (rev 5687)
+++ short/3D/PyLith/branches/pylith-0.8/pylith3d/module/setup.cc	2007-01-06 02:11:26 UTC (rev 5688)
@@ -46,12 +46,15 @@
 char pypylith3d_petsc_initialize__doc__[] = "";
 char pypylith3d_petsc_initialize__name__[] = "PetscInitialize";
 
-PyObject * pypylith3d_petsc_initialize(PyObject *, PyObject *)
+PyObject * pypylith3d_petsc_initialize(PyObject *, PyObject *args)
 {
-  PyObject *sysMod = PyImport_ImportModule("sys");
-  PyObject *argList = PyObject_GetAttrString(sysMod, "argv");
+  PyObject *argList;
+  if (!PyArg_ParseTuple(args, "O:PetscInitialize", &argList)) {
+    return 0;
+  }
+
   int argc = PySequence_Length(argList);
-  char **argv = (char **) malloc(argc * sizeof(char *));
+  char **argv = (char **) malloc((argc + 1) * sizeof(char *));
   int a;
 
   for(a = 0; a < argc; a++) {
@@ -60,6 +63,7 @@
     argv[a] = (char *) malloc((strlen(arg)+1)* sizeof(char));
     strcpy(argv[a], arg);
   }
+  argv[argc] = NULL;
   if (PetscInitialize(&argc, &argv, NULL, "Pylith 3D")) {
     PyErr_SetString(PyExc_RuntimeError, "PETSc failed to initialize");
     return 0;
@@ -71,13 +75,8 @@
     << "Initializing PETSc"
     << journal::endl;
 
-  // cleanup
-  for(a = 0; a < argc; a++) {
-    free(argv[a]);
-  }
-  free(argv);
-  Py_DECREF(argList);
-  Py_DECREF(sysMod);
+  // Do not free 'argv' -- PETSc saves a reference to it ('PetscGlobalArgs').
+
   // return
   Py_INCREF(Py_None);
   return Py_None;

Modified: short/3D/PyLith/branches/pylith-0.8/pylith3d/pylith3d/Application.py
===================================================================
--- short/3D/PyLith/branches/pylith-0.8/pylith3d/pylith3d/Application.py	2007-01-05 22:33:03 UTC (rev 5687)
+++ short/3D/PyLith/branches/pylith-0.8/pylith3d/pylith3d/Application.py	2007-01-06 02:11:26 UTC (rev 5688)
@@ -40,7 +40,7 @@
 #        start = now()
         pl3dsetup = self.inventory.setup
         import pylith3d
-        pylith3d.PetscInitialize()
+        pylith3d.PetscInitialize(self.petscArgs)
         self.inventory.scanner.inventory.fileRoot, mesh = pylith3d.processMesh(self.inventory.scanner.inventory.fileRoot, self.inventory.scanner.inventory.interpolateMesh, self.inventory.scanner.inventory.partitioner)
         try:
             pl3dsetup.initialize(self.inventory.scanner)
@@ -74,25 +74,67 @@
         return
 
 
+    def _configure(self):
+        self.petscArgs = []
+        
+        ksp_monitor = self.inventory.ksp_monitor
+        if ksp_monitor:
+            self.petscArgs.append("-ksp_monitor")
+            if ksp_monitor != "true":
+                self.petscArgs.append(ksp_monitor)
+        
+        if self.inventory.ksp_view:
+            self.petscArgs.append("-ksp_view")
+        
+        ksp_rtol = self.inventory.ksp_rtol
+        if ksp_rtol:
+            self.petscArgs.extend(["-ksp_rtol", ksp_rtol])
+        
+        if self.inventory.log_summary:
+            self.petscArgs.append("-log_summary")
+
+        pc_type = self.inventory.pc_type
+        sub_pc_type = self.inventory.sub_pc_type
+        self.petscArgs.extend(["-pc_type", pc_type, "-sub_pc_type", sub_pc_type])
+
+        if self.inventory.start_in_debugger:
+            self.petscArgs.append("-start_in_debugger")
+
+        self.petscArgs.extend(self.inventory.petsc.getArgs())
+
+        return
+
+
+    def createCommandlineParser(self):
+        from PetscUtil import PetscCommandlineParser
+        return PetscCommandlineParser()
+
+
     class Inventory(BaseScript.Inventory):
 
         import pyre.inventory
         from Pylith3d_scan import Pylith3d_scan
         from Pylith3d_setup import Pylith3d_setup
         from Pylith3d_run import Pylith3d_run
+        from PetscUtil import PetscFacility
 
         scanner = pyre.inventory.facility("scanner", factory=Pylith3d_scan)
         setup = pyre.inventory.facility("setup", factory=Pylith3d_setup)
         solver = pyre.inventory.facility("solver", factory=Pylith3d_run)
-        # ksp_monitor = pyre.inventory.str("ksp_monitor",default="1")
-        # ksp_view = pyre.inventory.str("ksp_view",default="1")
-        # log_summary = pyre.inventory.str("log_summary",default="1")
-        # log_info = pyre.inventory.str("log_info",default="0")
-        # pc_type = pyre.inventory.str("pc_type",default="1")
-        # start_in_debugger = pyre.inventory.str("start_in_debugger",default="0")
-        # petsc_solver = pyre.inventory.str("petsc_solver",default="1")
 
+        # declare PETSc options that are of interest to PyLith
+        ksp_monitor = pyre.inventory.str("ksp_monitor")
+        ksp_view = pyre.inventory.bool("ksp_view")
+        ksp_rtol = pyre.inventory.str("ksp_rtol")
+        log_summary = pyre.inventory.bool("log_summary")
+        pc_type = pyre.inventory.str("pc_type")
+        sub_pc_type = pyre.inventory.str("sub_pc_type")
+        start_in_debugger = pyre.inventory.str("start_in_debugger")
 
+        # a dummy facility for passing arbitrary options to PETSc
+        petsc = PetscFacility("petsc")
+
+
 # version
 # $Id: Application.py,v 1.5 2005/04/15 00:18:21 willic3 Exp $
 

Added: short/3D/PyLith/branches/pylith-0.8/pylith3d/pylith3d/PetscUtil.py
===================================================================
--- short/3D/PyLith/branches/pylith-0.8/pylith3d/pylith3d/PetscUtil.py	2007-01-05 22:33:03 UTC (rev 5687)
+++ short/3D/PyLith/branches/pylith-0.8/pylith3d/pylith3d/PetscUtil.py	2007-01-06 02:11:26 UTC (rev 5688)
@@ -0,0 +1,162 @@
+#!/usr/bin/env python
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+#  PyLith by Charles A. Williams, Brad Aagaard, and Matt Knepley
+#
+#  Copyright (c) 2004-2006 Rensselaer Polytechnic Institute
+#
+#  Permission is hereby granted, free of charge, to any person obtaining
+#  a copy of this software and associated documentation files (the
+#  "Software"), to deal in the Software without restriction, including
+#  without limitation the rights to use, copy, modify, merge, publish,
+#  distribute, sublicense, and/or sell copies of the Software, and to
+#  permit persons to whom the Software is furnished to do so, subject to
+#  the following conditions:
+#
+#  The above copyright notice and this permission notice shall be
+#  included in all copies or substantial portions of the Software.
+#
+#  THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+#  EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+#  MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+#  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+#  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+#  OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+#  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+
+
+from pyre.applications.CommandlineParser import CommandlineParser
+
+
+class PetscCommandlineParser(CommandlineParser):
+    """A parser which mimics PETSc's command line processing."""
+
+    # The logic used here is derived from the 'while' loop at the end
+    # of PetscOptionsInsert().  However, this doesn't check for "bad"
+    # MPICH options, as these should have been removed by MPI_Init().
+
+
+    def _parse(self, argv, root):
+        
+        self.action = None
+        self.argv = argv
+        self.processed = []
+        self.unprocessed = []
+        
+        while self.argv:
+            
+            arg = self.argv.pop(0)
+            
+            iname = self._filterNonOptionArgument(arg)
+            if iname is None:
+                continue
+            
+            if iname.lower() == "options_file":
+                # NYI
+                if self.argv:
+                    filename = self.argv.pop(0)
+                else:
+                    pass # error
+                continue
+
+            if (not self.argv) or self._isOptionArgument(self.argv[0]):
+                iname, value = self._parseArgument(iname)
+            else:
+                value = self.argv.pop(0)
+
+            self._processArgument(iname, value, root)
+
+        return
+
+
+    def _optionPrefix(self, arg):
+        for prefix in self.prefixes:
+            if arg.startswith(prefix):
+                return prefix
+        return None
+
+
+    def _isOptionArgument(self, arg):
+        import string
+        prefix = self._optionPrefix(arg)
+        if prefix is not None:
+            candidate = arg[len(prefix):]
+            if (prefix == "-" and
+                len(candidate) > 0 and
+                candidate[0] in string.digits):
+                return False
+            return True
+        return False
+
+
+    def _filterNonOptionArgument(self, arg):
+        
+        prefix = self._optionPrefix(arg)
+        
+        if prefix is not None:
+            self._debug.line("    prefix: '%s starts with '%s'" % (arg, prefix))
+            candidate = arg[len(prefix):]
+            return candidate
+        
+        # prefix matching failed; leave this argument alone
+        self._debug.line("    prefix: '%s' is not an option" % arg)
+        self.processed.append(arg)
+        return None
+
+
+
+from pyre.components import Component
+
+
+class Petsc(Component):
+
+
+    def updateConfiguration(self, registry):
+        self.options = [
+            (name, descriptor.value) for name, descriptor in registry.properties.iteritems()
+            ]
+        return []
+
+
+    def getArgs(self):
+        args = []
+        for iname, value in self.options:
+            args.append('-' + iname)
+            if value != 'true':
+                args.append(value)
+        return args
+
+
+    def __init__(self, name):
+        Component.__init__(self, name, name)
+        self.options = []
+        return
+
+
+
+from pyre.inventory.Facility import Facility
+
+
+class PetscFacility(Facility):
+
+
+    def __init__(self, name):
+        Facility.__init__(self, name=name, factory=Petsc, args=[name])
+        return
+
+
+    def _retrieveComponent(self, instance, componentName):
+        petsc = Petsc(componentName)
+
+        import pyre.parsing.locators
+        locator = pyre.parsing.locators.simple('built-in')
+
+        return petsc, locator
+
+
+
+# End of file 

Modified: short/3D/PyLith/branches/pylith-0.8/pylith3d/pylith3d/Pylith3d_setup.py
===================================================================
--- short/3D/PyLith/branches/pylith-0.8/pylith3d/pylith3d/Pylith3d_setup.py	2007-01-05 22:33:03 UTC (rev 5687)
+++ short/3D/PyLith/branches/pylith-0.8/pylith3d/pylith3d/Pylith3d_setup.py	2007-01-06 02:11:26 UTC (rev 5688)
@@ -1002,12 +1002,6 @@
         print "Hello from pl3dsetup.sparsesetup (begin)!"
         print "Setting up sparse matrix storage:"
         
-        # Initialize PETSc and set up logging
-        import os
-        wd = os.getcwd()
-        pylith3d.PetscInitialize()
-        os.chdir(wd) # Work-around MPI_Init() changing our directory!
-        
         self.autoprestrStage, \
         self.elasticStage, \
         self.viscousStage, \



More information about the cig-commits mailing list