From c58585eb15de48ccf7d6ae3fd32cb530d47cc56c Mon Sep 17 00:00:00 2001
From: Simone Pagan Griso <simone.pagan.griso@cern.ch>
Date: Thu, 6 Aug 2020 19:22:18 -0700
Subject: [PATCH] catch exception if energy balance fails to converge and
 handle it properly

---
 .../Pythia8_i/src/UserHooks/DecayToSUEP.cxx     | 17 ++++++++++++++++-
 .../Pythia8_i/src/UserHooks/suep_shower.cxx     | 14 +++++++++++++-
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/Generators/Pythia8_i/src/UserHooks/DecayToSUEP.cxx b/Generators/Pythia8_i/src/UserHooks/DecayToSUEP.cxx
index cf7ece3e852..d52df4bba1d 100644
--- a/Generators/Pythia8_i/src/UserHooks/DecayToSUEP.cxx
+++ b/Generators/Pythia8_i/src/UserHooks/DecayToSUEP.cxx
@@ -128,7 +128,22 @@ namespace Pythia8{
 
 	// Generate the shower, output are 4 vectors in the rest frame of the shower
 	higgs4mom=process[ii].p();
-	suep_shower4momenta=suep_shower.generate_shower();
+	int nShowerAttempts=0;
+	do {
+	  try {
+	    nShowerAttempts++;
+	    suep_shower4momenta=suep_shower.generate_shower();
+	    nShowerAttempts = -1; //exit condition
+	  } catch (std::exception &e) {
+	    //Failed to generate the shower!
+	    //Can happen in some rare circumstances, try again
+	  }
+	} while ((nShowerAttempts > 0) && (nShowerAttempts < 3));
+	if (nShowerAttempts >= 3) {
+	  //Something is seriously wrong then, print warning and skip to next event
+	  std::cout << "[SUEP] ERROR: Something went terribly wrong in generating the shower. Skipping the event." << std::endl;
+	  return true; //veto the event!
+	}
 
 	// Loop over hidden sector mesons and append to the event	
 	for (unsigned j = 0; j < suep_shower4momenta.size(); ++j){
diff --git a/Generators/Pythia8_i/src/UserHooks/suep_shower.cxx b/Generators/Pythia8_i/src/UserHooks/suep_shower.cxx
index 6e0dfe6a03d..08c9ea67ad5 100644
--- a/Generators/Pythia8_i/src/UserHooks/suep_shower.cxx
+++ b/Generators/Pythia8_i/src/UserHooks/suep_shower.cxx
@@ -150,7 +150,19 @@ vector< Vec4 > Suep_shower::generate_shower(){
   // finally, ballance the total energy, without destroying momentum conservation
   tolerance tol = 0.00001;
   double p_scale;
-  p_scale = (bisect(boost::bind(&Suep_shower::reballance_func, this, _1, event),0.0,2.0, tol)).first;
+  try {
+    p_scale = (bisect(boost::bind(&Suep_shower::reballance_func, this, _1, event),0.0,2.0, tol)).first;
+  } catch (std::exception &e) {
+    //in some rare circumstances, this balancing might fail
+    std::cout << "[SUEP_SHOWER] WARNING: Failed to rebalance the following event; Printing for debug and throw exception" << std::endl;
+    std::cout << e.what() << std::endl;
+    std::cout << "N. Particle, px, py, pz, E" << std::endl;
+    for (size_t jj=0; jj < event.size(); jj++) {
+      //print out event
+      std::cout << jj << ": " << event[jj].px() << ", " << event[jj].py() << ", " << event[jj].pz() << ", " << event[jj].e() << std::endl;
+    }
+    throw e;
+  }
   
   for(int n=0;n<len;n++){
     event[n].px(p_scale*event[n].px());
-- 
GitLab