Salome HOME
Add error detection for the cases where the launcher resources are not correctly...
authorboulant <boulant>
Mon, 19 Nov 2012 17:11:52 +0000 (17:11 +0000)
committerboulant <boulant>
Mon, 19 Nov 2012 17:11:52 +0000 (17:11 +0000)
src/Tools/padder/doc/images/padder_error_noresource.png [new file with mode: 0644]
src/Tools/padder/doc/images/padder_sphererendering.png [new file with mode: 0644]
src/Tools/padder/doc/input/padder_userguide.doc
src/Tools/padder/meshjob/idl/MESHJOB.idl
src/Tools/padder/meshjob/impl/MeshJobManager_i.cxx
src/Tools/padder/meshjob/impl/MeshJobManager_i.hxx
src/Tools/padder/resources/testdata/Makefile.am
src/Tools/padder/resources/testdata/teststudy.hdf [new file with mode: 0644]
src/Tools/padder/spadderpy/gui/plugindialog.py

diff --git a/src/Tools/padder/doc/images/padder_error_noresource.png b/src/Tools/padder/doc/images/padder_error_noresource.png
new file mode 100644 (file)
index 0000000..41261e0
Binary files /dev/null and b/src/Tools/padder/doc/images/padder_error_noresource.png differ
diff --git a/src/Tools/padder/doc/images/padder_sphererendering.png b/src/Tools/padder/doc/images/padder_sphererendering.png
new file mode 100644 (file)
index 0000000..a1b97ec
Binary files /dev/null and b/src/Tools/padder/doc/images/padder_sphererendering.png differ
index 0ec4c87498879d7f8888e679818eee4594bb0af0..a44b10eb05a134a3f582b2c12a4ffde9afa24131 100644 (file)
@@ -8,25 +8,56 @@
 
 \section S1_PADDER The SpherePadder Algorithm
 
 
 \section S1_PADDER The SpherePadder Algorithm
 
-SpherePadder is a geometric algorithm that creates a set of rigid spherical particles of different sizes called a "discrete element mesh". The centroid positions of particles are randomly generated by a "disordering" technique described in [1] that provides a polydisperse assembly with a particular size distribution. The spheres are positioned or “padded” into a tetrahedral mesh, which must be generated first. As illustrated below, SpherePadder creates a Discrete Element (DE) assembly in seven steps (see [1] for details):
+SpherePadder is a geometric algorithm that creates a set of rigid
+spherical particles of different sizes called a "discrete element
+mesh". The centroid positions of particles are randomly generated by a
+"disordering" technique described in [1] that provides a polydisperse
+assembly with a particular size distribution. The spheres are
+positioned or “padded” into a tetrahedral mesh, which must be
+generated first. As illustrated below, SpherePadder creates a Discrete
+Element (DE) assembly in seven steps (see [1] for details):
 
 \image html padder_image01.png
 
 
 \image html padder_image01.png
 
-In order to increase the density of the whole packing and to fill spheres in the gaps close to the mesh boundaries (created by removing boundary spheres), SpherePadder detect `void spaces' where new spheres could be added by applying a particular geometric procedure, using tetrahedra resulting from a tridimensional Delaunay triangulation built with the sphere centers. That triangulation is generated by using the CGAL library [2].
-
-DE meshes generated by SpherePadder algorithm are used in EUROPLEXUS fast dynamics software simulations [3] to model the discontinuous behaviour (fractures, fragmentation) of reinforced concrete structures under severe dynamic loads such as impacts or explosions. The characteristic size of elements does not have to be representative of concrete constituents, such as granulars or cement matrix, since the aim is to reproduce the dynamic behaviour of the simulated material at the macroscopic scale.
-
-To generate DE mesh for a reinforced concrete structure, one should supply a single tetrahedral mesh for concrete and as many segment-type 1D meshes as groups of steel reinforcement bars of different diameters. The size (length) of segment-type steel reinforcement elements should correspond to the modelled bar’s diameter. SpherePadder algorithm will create steel discrete elements by using the segment’s length as the DE diameter. 
-
-Warning: The User should control that all steel bars of a given diameter in a mesh belong to the same mesh group, and that different steel bar groups do not use the same diameter.
+In order to increase the density of the whole packing and to fill
+spheres in the gaps close to the mesh boundaries (created by removing
+boundary spheres), SpherePadder detect `void spaces' where new spheres
+could be added by applying a particular geometric procedure, using
+tetrahedra resulting from a tridimensional Delaunay triangulation
+built with the sphere centers. That triangulation is generated by
+using the CGAL library [2]. 
+
+DE meshes generated by SpherePadder algorithm are used in EUROPLEXUS
+fast dynamics software simulations [3] to model the discontinuous
+behaviour (fractures, fragmentation) of reinforced concrete structures
+under severe dynamic loads such as impacts or explosions. The
+characteristic size of elements does not have to be representative of
+concrete constituents, such as granulars or cement matrix, since the
+aim is to reproduce the dynamic behaviour of the simulated material at
+the macroscopic scale. 
+
+To generate DE mesh for a reinforced concrete structure, one should
+supply a single tetrahedral mesh for concrete and as many segment-type
+1D meshes as groups of steel reinforcement bars of different
+diameters. The size (length) of segment-type steel reinforcement
+elements should correspond to the modelled bar’s
+diameter. SpherePadder algorithm will create steel discrete elements
+by using the segment’s length as the DE diameter.
+
+Warning: The User should control that all steel bars of a given
+diameter in a mesh belong to the same mesh group, and that different
+steel bar groups do not use the same diameter.
 
 \image html padder_image02.png
 
 If steel mesh is not provided, a pure concrete DE mesh is generated.
 
 
 \image html padder_image02.png
 
 If steel mesh is not provided, a pure concrete DE mesh is generated.
 
-In MED representation, DE meshes are described by using MED_BALL type structural elements. Each MED_BALL element is defined by its centroid location and a diameter.
+In MED representation, DE meshes are described by using MED_BALL type
+structural elements. Each MED_BALL element is defined by its centroid
+location and a diameter. 
 
 
-Written in C++, SpherePadder is free software licensed under the terms of the GNU General Public License.
+Written in C++, SpherePadder is free software licensed under the terms
+of the GNU General Public License. 
 
 Bibliography:
 - [1] J.-F.Jerier, V.Richefeu, D.Imbault, F.-V. Donzé, “Packing spherical discrete elements for large scale simulations”, Computer Methods in Applied Mechanics and Engineering 199 (2010) 1668–1676.
 
 Bibliography:
 - [1] J.-F.Jerier, V.Richefeu, D.Imbault, F.-V. Donzé, “Packing spherical discrete elements for large scale simulations”, Computer Methods in Applied Mechanics and Engineering 199 (2010) 1668–1676.
@@ -35,60 +66,104 @@ Bibliography:
 
 \section S2_PADDER The SpherePadder SALOME plugin
 
 
 \section S2_PADDER The SpherePadder SALOME plugin
 
-The SpherePadder algorithm is implemented in the SMESH module as a SALOME plugin. This section illustrates how to use this plugin to create a discrete element mesh.
+The SpherePadder algorithm is implemented as an external software
+program. This external program is integrated in the SMESH module as a
+SALOME plugin that manage the execution of the SpherePadder program
+from within the SALOME framework. This section illustrates how to use
+this plugin to create a discrete element mesh.
 
 
-In this example, we consider a concrete piece with a single reinforcement bars group. Thus, two standard (Finite Element type) meshes have been created and published in the study, the first one named “concrete”, and second one named "ferrail", for the steel bars part:
+In this example, we consider a concrete piece with a single
+reinforcement bars group. Thus, two standard (Finite Element type)
+meshes have been created and published in the study, the first one
+named “concrete”, and second one named "ferrail", for the steel bars
+part: 
 
 \image html padder_image03.png
 
 
 \image html padder_image03.png
 
-The SpherePadder plugin can be activated in the SMESH plugins menu, as illustrated on the figure below:
+The SpherePadder plugin can be activated in the SMESH plugins menu, as
+illustrated on the figure below: 
 
 \image html padder_image04.png
 
 
 \image html padder_image04.png
 
-When clicking on the "PADDER mesher" item, the graphical interface of the SpherePadder plugin appears:
+When clicking on the "PADDER mesher" item, the graphical interface of
+the SpherePadder plugin appears:
 
 \image html padder_image05.png
 
 
 \image html padder_image05.png
 
-This interface invites you to specify input data by pressing the button "Input". This command opens the Input dialog box allowing to specify the list and the type of selected meshes (to be chosen between "concrete" and "steelbar" using the combobox on the right side of the input line):
+This interface invites you to specify input data by pressing the
+button "Input". This command opens the Input dialog box allowing to
+specify the list and the type of selected meshes (to be chosen between
+"concrete" and "steelbar" using the combobox on the right side of the
+input line): 
 
 \image html padder_image06.png
 
 
 \image html padder_image06.png
 
-In the figure below, the mesh with name "concrete" has been selected in the study and added to the list of the input file as a "concrete mesh". First, you have to choose the mesh in the dialog box using the rounded arrow icon, then specify for this mesh a group name which will be published in the final DE mesh, and finally click on the "Add" icon:
+In the figure below, the mesh with name "concrete" has been selected
+in the study and added to the list of the input file as a "concrete
+mesh". First, you have to choose the mesh in the dialog box using the
+rounded arrow icon, then specify for this mesh a group name which will
+be published in the final DE mesh, and finally click on the "Add"
+icon: 
 
 \image html padder_image07.png
 
 
 \image html padder_image07.png
 
-Then, the mesh with name "ferrail" is selected and added to the list as a "steelbar mesh":
+Then, the mesh with name "ferrail" is selected and added to the list
+as a "steelbar mesh": 
 
 \image html padder_image08.png
 
 
 \image html padder_image08.png
 
-The input dialog box has to be validated to return to the main plugin interface. The "Compute" button is now enabled, indicating that the problem is ready to be computed:
+The input dialog box has to be validated to return to the main plugin
+interface. The "Compute" button is now enabled, indicating that the
+problem is ready to be computed: 
 
 \image html padder_image09.png
 
 
 \image html padder_image09.png
 
-The command "Compute" starts the job run. The progression can be requested using the command "Refresh". In the figure below, the job is still running:
+The command "Compute" starts the job run. The progression can be
+requested using the command "Refresh". In the figure below, the job is
+still running: 
 
 \image html padder_image10.png
 
 
 \image html padder_image10.png
 
-Finally, the job is finished and the result is ready to be published in the SALOME study:
+Finally, the job is finished and the result is ready to be published
+in the SALOME study: 
 
 \image html padder_image11.png
 
 
 \image html padder_image11.png
 
-Click on the button "Publish" to import the resulting MED file into SMESH and publish the resulting mesh in the SALOME study:
+Click on the button "Publish" to import the resulting MED file into
+SMESH and publish the resulting mesh in the SALOME study: 
 
 \image html padder_image12.png
 
 
 \image html padder_image12.png
 
-Note that the final ED mesh contains as many groups as the used input meshes. Their names have been specified in the input dialog. For the moment, the DE mesh is shown as a set of points of equal size. In the next version, the PointSprite (sphere-like) mode will be used to show the MED_BALL elements with their real diameters.
+Note that the final ED mesh contains as many groups as the input
+meshes. Their names have been specified in the input dialog. For the
+moment, the DE mesh is shown as a set of points of equal size:
 
 \image html padder_image13.png
 
 
 \image html padder_image13.png
 
-\section S3_PADDER Configuring the plugin
+In the next version, the PointSprite (sphere-like) mode will be used
+to show the MED_BALL elements with their real diameters. Then the
+above example should look like on the following capture (realized in
+module GEOM for illustration):
 
 
+\image html padder_sphererendering.png
+
+\section S3_PADDER Configuring the SpherePadder SALOME plugin
 
 The configuration of the plugin consists in specifying the location of
 
 The configuration of the plugin consists in specifying the location of
-the padder executable program for each of the SALOME resource (at
-least for the localhost resource). This specification is done in the
-file padder.cfg, located in the plugin installation folder
-(i.e. <SMESH_ROOT_DIR>/plugins):
+the padder executable program (padder.exe) and its runtime environment
+file (padder.env). This configuration is automatically done at
+installation process of the SALOME plateform, on the basis of the
+environment variable PADDERHOME that localizes the installation root
+of the SpherePadder external program. This installation process
+creates a configuration file padder.cfg located in the folder
+<SMESH_ROOT_DIR>/share/salome/plugins/smesh, where <SMESH_ROOT_DIR> is
+the installation root directory of the SMESH module.
+
+In the case where you have to specify a different configuration than
+the generated configuration, you must edit the file padder.cfg. This
+file defines a list of computing resources, and at least a local
+resource (a padder program working on your local host), and a remote
+resource (a padder program working on a remote host):
 
 \code
 # This section specify the configurations to be used respectively for
 
 \code
 # This section specify the configurations to be used respectively for
@@ -123,4 +198,39 @@ binpath = /usr/local/bin/padder.exe
 envpath = /usr/local/share/envPadder.sh
 \endcode
 
 envpath = /usr/local/share/envPadder.sh
 \endcode
 
+The resource labels (localhost and nepal in the above example) must
+correspond to existing computing resources of SALOME. These resources
+are specified in the SALOME configuration CatalogResources.xml,
+located at the root directory of your SALOME application. The
+resources catalog is supposed to contain at least the localhost
+resource of type 'ssh' defined as follow:
+
+\code
+<!DOCTYPE ResourcesCatalog>
+<resources>
+
+   <!-- Generic configuration that should works on every workstation -->
+   <machine name="localhost" hostname="localhost"
+            protocol="ssh" batch="ssh_batch"
+            memInMB="500" CPUFreqMHz="0" nbOfNodes="1" nbOfProcPerNode="1"/>
+
+</resources>
+\endcode
+
+Note that these SALOME computing resources can be graphically edited
+using the JOBMANAGER module (see JOBMANAGER documentation).
+
+The typical error message when trying to use the padder plugin while
+the localhost resource is not correctly defined is :
+
+\code
+ERR: the job with jobid = 0 can't be started
+ERR: No batchmanager for that cluster - Bad batch description of the resource"
+\endcode
+
+This error message is display in the graphical interface of the plugin
+when you request a computing of your mesh:
+
+\image html padder_error_noresource.png
+
 */
 */
index a5559cd77e8ee537e3a3d08daad65c90072e646e..895fbd7cd0b5c162c6dc866328a2a22705dd83d8 100644 (file)
@@ -119,6 +119,8 @@ module MESHJOB
     MeshJobPaths getPaths(in long jobId)
       raises (SALOME::SALOME_Exception);
 
     MeshJobPaths getPaths(in long jobId)
       raises (SALOME::SALOME_Exception);
 
+    /*! Returns the last error message (for user display) */
+    string getLastErrorMessage();
   };
 
 };
   };
 
 };
index 72520fbabf811486d528ea35cb196834f4779948..95e092dfb1a398815e103254c8f484349a8e2076 100644 (file)
@@ -94,6 +94,8 @@ MeshJobManager_i::MeshJobManager_i(CORBA::ORB_ptr orb,
     LOG("The SALOME resource manager can't be reached ==> STOP");
     throw KERNEL::createSalomeException("The SALOME resource manager can't be reached");
   }
     LOG("The SALOME resource manager can't be reached ==> STOP");
     throw KERNEL::createSalomeException("The SALOME resource manager can't be reached");
   }
+
+  _lastErrorMessage = "";
 }
 
 MeshJobManager_i::~MeshJobManager_i() {
 }
 
 MeshJobManager_i::~MeshJobManager_i() {
@@ -383,7 +385,17 @@ CORBA::Long MeshJobManager_i::initialize(const MESHJOB::MeshJobParameterList & m
   //const char * resourceName = "boulant@claui2p1";
   //const char * resourceName = "nepal@nepal";
   const char * resourceName = _configMap[configId].resname;
   //const char * resourceName = "boulant@claui2p1";
   //const char * resourceName = "nepal@nepal";
   const char * resourceName = _configMap[configId].resname;
-  Engines::ResourceDefinition * resourceDefinition = _resourcesManager->GetResourceDefinition(resourceName);
+  
+  Engines::ResourceDefinition * resourceDefinition;
+  try {
+    resourceDefinition = _resourcesManager->GetResourceDefinition(resourceName);
+  }
+  catch (const CORBA::SystemException& ex) {
+    _lastErrorMessage = std::string("We can not access to the ressource ") + std::string(resourceName);
+    _lastErrorMessage+= std::string("(check the file CatalogResource.xml)");
+    LOG(_lastErrorMessage);
+    return JOBID_UNDEFINED;
+  }
   // CAUTION: This resource should have been defined in the
   // CatalogResource.xml associated to the SALOME application.
   //
   // CAUTION: This resource should have been defined in the
   // CatalogResource.xml associated to the SALOME application.
   //
@@ -413,29 +425,22 @@ CORBA::Long MeshJobManager_i::initialize(const MESHJOB::MeshJobParameterList & m
   //
   // So, even in the case of a simple test shell script, you should
   // set this value at least to a standard threshold as 500MB
   //
   // So, even in the case of a simple test shell script, you should
   // set this value at least to a standard threshold as 500MB
-
   int jobId = JOBID_UNDEFINED;
   try {
   int jobId = JOBID_UNDEFINED;
   try {
-    std::cerr << "#####################################" << std::endl;
-    std::cerr << "#####################################" << std::endl;
-    std::cerr << "jobUndef = " << JOBID_UNDEFINED << std::endl;
     jobId = _salomeLauncher->createJob(jobParameters);
     jobId = _salomeLauncher->createJob(jobParameters);
-    std::cerr << "#####################################" << std::endl;
-    std::cerr << "#####################################" << std::endl;
-    std::cerr << "#####################################" << std::endl;
-    std::cerr << "jobId = " << jobId << std::endl;
     // We register the datetime tag of this job
     _jobDateTimeMap[jobId]=jobDatetimeTag;
     _jobPathsMap[jobId] = jobPaths;
   }
   catch (const SALOME::SALOME_Exception & ex) {
     // We register the datetime tag of this job
     _jobDateTimeMap[jobId]=jobDatetimeTag;
     _jobPathsMap[jobId] = jobPaths;
   }
   catch (const SALOME::SALOME_Exception & ex) {
-    LOG("SALOME Exception in createJob !" <<ex.details.text.in());
-    //LOG(ex.details.text.in());
+    LOG("SALOME Exception at initialization step !" <<ex.details.text.in());
+    _lastErrorMessage = ex.details.text.in();
     return JOBID_UNDEFINED;
   }
   catch (const CORBA::SystemException& ex) {
     LOG("Receive SALOME System Exception: "<<ex);
     LOG("Check SALOME servers...");
     return JOBID_UNDEFINED;
   }
   catch (const CORBA::SystemException& ex) {
     LOG("Receive SALOME System Exception: "<<ex);
     LOG("Check SALOME servers...");
+    _lastErrorMessage = "Check the SALOME servers (or try to restart SALOME)";
     return JOBID_UNDEFINED;
   }
   
     return JOBID_UNDEFINED;
   }
   
@@ -452,12 +457,13 @@ bool MeshJobManager_i::start(CORBA::Long jobId) {
   }
   catch (const SALOME::SALOME_Exception & ex) {
     LOG("SALOME Exception in launchjob !" <<ex.details.text.in());
   }
   catch (const SALOME::SALOME_Exception & ex) {
     LOG("SALOME Exception in launchjob !" <<ex.details.text.in());
-    //LOG(ex.details.text.in());
+    _lastErrorMessage = ex.details.text.in();
     return false;
   }
   catch (const CORBA::SystemException& ex) {
     LOG("Receive SALOME System Exception: "<<ex);
     LOG("Check SALOME servers...");
     return false;
   }
   catch (const CORBA::SystemException& ex) {
     LOG("Receive SALOME System Exception: "<<ex);
     LOG("Check SALOME servers...");
+    _lastErrorMessage = "Check the SALOME servers (or try to restart SALOME)";
     return false;
   }
 
     return false;
   }
 
@@ -477,6 +483,7 @@ char* MeshJobManager_i::getState(CORBA::Long jobId) {
   catch (const SALOME::SALOME_Exception & ex)
   {
     LOG("SALOME Exception in getJobState !");
   catch (const SALOME::SALOME_Exception & ex)
   {
     LOG("SALOME Exception in getJobState !");
+    _lastErrorMessage = ex.details.text.in();
     state = ex.details.text;
   }
   catch (const CORBA::SystemException& ex)
     state = ex.details.text;
   }
   catch (const CORBA::SystemException& ex)
@@ -525,6 +532,7 @@ MESHJOB::MeshJobResults * MeshJobManager_i::finalize(CORBA::Long jobId) {
   {
     LOG("SALOME Exception in getResults !");
     result->status = "SALOME Exception in getResults !";
   {
     LOG("SALOME Exception in getResults !");
     result->status = "SALOME Exception in getResults !";
+    _lastErrorMessage = ex.details.text.in();
   }
   catch (const CORBA::SystemException& ex)
   {
   }
   catch (const CORBA::SystemException& ex)
   {
@@ -610,6 +618,11 @@ std::vector<std::string> * MeshJobManager_i::_getResourceNames() {
   return resourceNames;
 }
 
   return resourceNames;
 }
 
+char* MeshJobManager_i::getLastErrorMessage() {
+  beginService("MeshJobManager_i::getState");
+  endService("MeshJobManager_i::getState");
+  return CORBA::string_dup(_lastErrorMessage.c_str());
+}
 
 //
 // ==========================================================================
 
 //
 // ==========================================================================
index 283a92d7adac9ea52b8b532345b3fc36bfe06419..f53d7aa34888ce4f4b12fa44e2a81a0b1719cfd2 100644 (file)
@@ -51,6 +51,8 @@ public:
   MESHJOB::MeshJobPaths *   getPaths(CORBA::Long jobId);
   bool           clean      (CORBA::Long jobId);
 
   MESHJOB::MeshJobPaths *   getPaths(CORBA::Long jobId);
   bool           clean      (CORBA::Long jobId);
 
+  char*          getLastErrorMessage();
+
   static long JOBID_UNDEFINED;
 
 private:
   static long JOBID_UNDEFINED;
 
 private:
@@ -75,6 +77,8 @@ private:
 
   std::vector<std::string> * _getResourceNames();
 
 
   std::vector<std::string> * _getResourceNames();
 
+  std::string _lastErrorMessage;
+
 };
 
 #endif
 };
 
 #endif
index ac4164895380f0ed47f89732ca09069534e82515..77c74fac088618b421a28c0d9f1e6210a6121ddb 100644 (file)
@@ -23,7 +23,8 @@ mysalomeresdir=$(salomeresdir)/padderdata
 
 dist_mysalomeres_DATA =  \
        concrete.med     \
 
 dist_mysalomeres_DATA =  \
        concrete.med     \
-       ferraill.med
+       ferraill.med     \
+       teststudy.hdf
 
 NOT_USED_FILES = buildparticules.py particules.png
 EXTRA_DIST += $(NOT_USED_FILES)
 
 NOT_USED_FILES = buildparticules.py particules.png
 EXTRA_DIST += $(NOT_USED_FILES)
diff --git a/src/Tools/padder/resources/testdata/teststudy.hdf b/src/Tools/padder/resources/testdata/teststudy.hdf
new file mode 100644 (file)
index 0000000..24e6b83
Binary files /dev/null and b/src/Tools/padder/resources/testdata/teststudy.hdf differ
index 2cf4c15d89811ddbfb796e309d5cac59ed5f9126..e62d7fdad5d5375c4fcb18c6af6ecfe3060a535c 100644 (file)
@@ -287,12 +287,14 @@ class PluginDialog(QDialog):
         self.__jobid = jobManager.initialize(meshJobParameterList, self.__configId)
         if self.__jobid < 0:
             self.__log("ERR: the job can't be initialized")
         self.__jobid = jobManager.initialize(meshJobParameterList, self.__configId)
         if self.__jobid < 0:
             self.__log("ERR: the job can't be initialized")
+            self.__log("ERR: %s"%jobManager.getLastErrorMessage())
             return
         self.__log("INF: the job has been initialized with jobid = "+str(self.__jobid))
         
         startOk = jobManager.start(self.__jobid)
         if not startOk:
             self.__log("ERR: the job with jobid = "+str(self.__jobid)+" can't be started")
             return
         self.__log("INF: the job has been initialized with jobid = "+str(self.__jobid))
         
         startOk = jobManager.start(self.__jobid)
         if not startOk:
             self.__log("ERR: the job with jobid = "+str(self.__jobid)+" can't be started")
+            self.__log("ERR: %s"%jobManager.getLastErrorMessage())
             return
         self.__log("INF: the job "+str(self.__jobid)+" has been started")
         self.__ui.lblStatusBar.setText("Submission OK")
             return
         self.__log("INF: the job "+str(self.__jobid)+" has been started")
         self.__ui.lblStatusBar.setText("Submission OK")
@@ -334,11 +336,13 @@ class PluginDialog(QDialog):
 
         if state not in end_states:
             self.__log("ERR: jobid = "+str(self.__jobid)+" ended abnormally with state="+str(state))
 
         if state not in end_states:
             self.__log("ERR: jobid = "+str(self.__jobid)+" ended abnormally with state="+str(state))
+            self.__log("ERR: %s"%jobManager.getLastErrorMessage())
             return
 
         meshJobResults = jobManager.finalize(self.__jobid)
         if state == "ERROR":
             self.__log("ERR: jobid = "+str(self.__jobid)+" ended with error: "+meshJobResults.status)
             return
 
         meshJobResults = jobManager.finalize(self.__jobid)
         if state == "ERROR":
             self.__log("ERR: jobid = "+str(self.__jobid)+" ended with error: "+meshJobResults.status)
+            self.__log("ERR: %s"%jobManager.getLastErrorMessage())
             return
 
         logsdirname = os.path.join(meshJobResults.results_dirname, "logs")
             return
 
         logsdirname = os.path.join(meshJobResults.results_dirname, "logs")