diff --git a/sirepo/job_driver/sbatch.py b/sirepo/job_driver/sbatch.py
index 4e8f6f6bd..dd9f5fe1f 100644
--- a/sirepo/job_driver/sbatch.py
+++ b/sirepo/job_driver/sbatch.py
@@ -178,14 +178,21 @@ disown
                         e,
                         pkdexc(),
                     )
-        except Exception as e:
-            if isinstance(e, OSError) and e.errno == errno.EHOSTUNREACH:
+        except asyncssh.misc.PermissionDenied:
+            pkdlog('{}', pkdexc())
+            self._srdb_root = None
+            self._raise_sbatch_login_srexception('invalid-creds', op.msg)
+        except asyncssh.misc.ProtocolError:
+            pkdlog('{}', pkdexc())
+            raise sirepo.util.UserAlert(
+                f'Unable to connect to {self.cfg.host}. Please try again later.',
+            )
+        except OSError as e:
+            pkdlog('{}', pkdexc())
+            if e.errno == errno.EHOSTUNREACH:
                 raise sirepo.util.UserAlert(
-                    'Host {} unreachable. Please try again later.'.format(self.cfg.host),
+                    f'Host {self.cfg.host} unreachable. Please try again later.',
                 )
-            if isinstance(e, asyncssh.misc.PermissionDenied):
-                self._srdb_root = None
-                self._raise_sbatch_login_srexception('invalid-creds', op.msg)
             raise
         finally:
             self.pkdel('_creds')
diff --git a/sirepo/package_data/static/html/zgoubi-twiss.html b/sirepo/package_data/static/html/zgoubi-twiss.html
index a2fc4efc8..aa64a2bdf 100644
--- a/sirepo/package_data/static/html/zgoubi-twiss.html
+++ b/sirepo/package_data/static/html/zgoubi-twiss.html
@@ -1,6 +1,6 @@
 <div class="container-fluid">
   <div class="row">
-    <div class="col-md-6">
+    <div class="col-md-6 col-xl-4">
       <div class="row">
       <div class="col-sm-12">
         <div data-basic-editor-panel="" data-view-name="twissSettings"></div>
@@ -8,7 +8,7 @@
       </div>
     </div>
     </div>
-    <div class="col-md-6">
+    <div class="col-md-6 col-xl-4">
       <div class="row">
       <div class="col-sm-12">
         <div data-report-panel="parameterWithLattice" data-model-name="twissReport2"></div>
diff --git a/sirepo/package_data/static/js/sirepo-components.js b/sirepo/package_data/static/js/sirepo-components.js
index 0e9d1978b..94bdf0024 100644
--- a/sirepo/package_data/static/js/sirepo-components.js
+++ b/sirepo/package_data/static/js/sirepo-components.js
@@ -3095,7 +3095,7 @@ SIREPO.app.directive('sbatchLoginModal', function() {
                 if (data.state === 'error') {
                     errorResponse = data.error;
                 }
-                sbatchLoginStatusService.loggedIn = data.loginSuccess;
+                sbatchLoginStatusService.loggedIn = data.loginSuccess ? true: false;
                 el.modal('hide');
             }
 
@@ -3126,7 +3126,8 @@ SIREPO.app.directive('sbatchLoginModal', function() {
                             simulationId: data.simulationId,
                             simulationType: data.simulationType,
                             username: $scope.username,
-                        }
+                        },
+                        handleResponse
                     );
                 };
                 el.modal('show');
diff --git a/sirepo/package_data/static/js/zgoubi.js b/sirepo/package_data/static/js/zgoubi.js
index 5a066d32b..811408fd9 100644
--- a/sirepo/package_data/static/js/zgoubi.js
+++ b/sirepo/package_data/static/js/zgoubi.js
@@ -31,7 +31,7 @@ SIREPO.app.config(function() {
         },
         elementPic: {
             aperture: ['COLLIMA'],
-            bend: ['AUTOREF', 'BEND', 'DIPOLE', 'CHANGREF', 'CHANGREF_VALUE', 'FFA', 'FFA_SPI', 'MULTIPOL'],
+            bend: ['AUTOREF', 'BEND', 'CHANGREF', 'CHANGREF_VALUE', 'FFA', 'FFA_SPI', 'MULTIPOL'],
             drift: ['DRIFT'],
             magnet: ['QUADRUPO', 'SEXTUPOL', 'TOSCA'],
             rf: ['CAVITE'],
@@ -95,15 +95,15 @@ SIREPO.app.controller('LatticeController', function(appState, errorService, pane
     var self = this;
     self.latticeService = latticeService;
     self.advancedNames = ['AUTOREF',  'TOSCA', 'YMY'];
-    self.basicNames = ['BEND', 'CAVITE', 'CHANGREF', 'CHANGREF2', 'COLLIMA', 'DRIFT', 'DIPOLE', 'FFA', 'FFA_SPI', 'MARKER', 'MULTIPOL', 'QUADRUPO', 'SCALING', 'SEXTUPOL', 'SOLENOID', 'SPINR'];
+    self.basicNames = ['BEND', 'CAVITE', 'CHANGREF', 'CHANGREF2', 'COLLIMA', 'DRIFT', 'FFA', 'FFA_SPI', 'MARKER', 'MULTIPOL', 'QUADRUPO', 'SCALING', 'SEXTUPOL', 'SOLENOID', 'SPINR'];
     var scaling = null;
 
     function updateScaling() {
-        var max = SIREPO.APP_SCHEMA.constants.maxScalingFamily;
+        var MAX_SCALING_FAMILY = 7;
         scaling = {};
         appState.models.elements.some(function(m) {
             if (m.type == 'SCALING' && m.IOPT == '1') {
-                for (var i = 1; i <= max; i++) {
+                for (var i = 1; i <= MAX_SCALING_FAMILY; i++) {
                     var key = m['NAMEF' + i];
                     if (m['LBL' + i]) {
                         key += '.' + m['LBL' + i];
@@ -167,13 +167,6 @@ SIREPO.app.controller('LatticeController', function(appState, errorService, pane
                 item.subElements.pop();
             }
         }
-        else if (item.type == 'DIPOLE') {
-            item.l = item.RM * (
-                item.OMEGA_E - item.OMEGA_S +
-                    Math.tan(item.ACN - item.OMEGA_E) +
-                    Math.tan(item.AT - item.ACN + item.OMEGA_S));
-            item.angle = item.AT;
-        }
         else if (item.type == 'MULTIPOL') {
             item.color = '';
             if (item.B_2) {
@@ -248,11 +241,6 @@ SIREPO.app.controller('SourceController', function(appState, latticeService, pan
         panelState.showTab('bunch', 2, bunch.method == 'MCOBJET3');
         panelState.showTab('bunch', 3, bunch.method == 'MCOBJET3');
         panelState.showTab('bunch', 4, bunch.method == 'OBJET2.1');
-        panelState.showTab('bunch', 5, bunch.method.indexOf('OBJET3') == 0);
-        panelState.showTab('bunch', 6, bunch.method.indexOf('OBJET3') == 0);
-        panelState.showField('bunch', 'FNAME', bunch.method == 'OBJET3');
-        panelState.showField('bunch', 'FNAME2', bunch.method == 'OBJET3.1');
-        panelState.showField('bunch', 'FNAME3', bunch.method == 'OBJET3.2');
     }
 
     function processBunchTwiss() {
diff --git a/sirepo/package_data/static/json/zgoubi-schema.json b/sirepo/package_data/static/json/zgoubi-schema.json
index 5e4cb5b6f..5609bb34e 100644
--- a/sirepo/package_data/static/json/zgoubi-schema.json
+++ b/sirepo/package_data/static/json/zgoubi-schema.json
@@ -1,7 +1,6 @@
 {
     "constants": {
-        "helpUserManualURL": "https://zgoubi.sourceforge.io/ZGOUBI_DOCS/Zgoubi.pdf",
-        "maxScalingFamily": 16
+        "helpUserManualURL": "https://zgoubi.sourceforge.io/ZGOUBI_DOCS/Zgoubi.pdf"
     },
     "appModes": {
         "default": {
@@ -32,14 +31,7 @@
         ],
         "BunchMethod": [
             ["MCOBJET3", "Random Distribution"],
-            ["OBJET2.1", "Specific Coordinates"],
-            ["OBJET3", "From File (zgoubi.fai format)"],
-            ["OBJET3.1", "From File (Y, T, Z, P, S, D)"],
-            ["OBJET3.2", "From File (X, Y, Z, PX, PY, PZ)"]
-        ],
-        "BunchRayTrace": [
-            ["0", "Initial Coordinates FO(J, I)"],
-            ["1", "Current Coordinates F(J, I)"]
+            ["OBJET2.1", "Specific Coordinates"]
         ],
         "CaviteFormat": [
             ["0", "Element inactive"],
@@ -248,8 +240,7 @@
             ["MUON+", "Positive Muon"],
             ["MUON-", "Negative Muon"],
             ["PROTON", "Proton"],
-            ["Other", "Other"],
-            ["None", "Not Selected"]
+            ["Other", "Other"]
         ],
         "PhaseSpaceCoordinate": [
             ["Y", "Y"],
@@ -451,32 +442,7 @@
             "beta_X": ["Longitudinal Beta [m]", "Float", 1.0, "", 1e-99],
             "emit_X": ["Longitudinal Emittance", "Float", 1e-6],
             "n_cutoff_X": ["Longitudinal Cutoff 1", "Float", 3.0],
-            "n_cutoff2_X": ["Longitudinal Cutoff 2", "Float", 0.0],
-            "FNAME": ["Particle File", "InputFile", ""],
-            "FNAME2": ["Particle File", "InputFile", ""],
-            "FNAME3": ["Particle File", "InputFile", ""],
-            "IT1": ["Particle Start", "Integer", 1],
-            "IT2": ["Particle End", "Integer", 999],
-            "ITStep": ["Particle Step", "Integer", 1],
-            "IP1": ["Pass Start", "Integer", 1],
-            "IP2": ["Pass End", "Integer", 999],
-            "IPStep": ["Pass Step", "Integer", 1],
-            "YF": ["Scale Y", "Float", 1],
-            "TF": ["Scale Y'", "Float", 1],
-            "ZF": ["Scale Z", "Float", 1],
-            "PF": ["Scale Z'", "Float", 1],
-            "SF": ["Scale S", "Float", 1],
-            "DPF": ["Scale DP", "Float", 1],
-            "TiF": ["Scale Ti", "Float", 1],
-            "YR": ["Offset Y [m]", "Float", 0],
-            "TR": ["Offset Y' [rad]", "Float", 0],
-            "ZR": ["Offset Z [m]", "Float", 0],
-            "PR": ["Offset Z' [rad]", "Float", 0],
-            "SR": ["Offset S [m]", "Float", 0],
-            "DPR": ["Offset DP", "Float", 0],
-            "TiR": ["Offset Ti", "Float", 0],
-            "TAG": ["Tagging Letter", "String", "*", "TAG allows retaining only particles with identical tagging letter LET"],
-            "InitC": ["Ray Tracing Start", "BunchRayTrace", "0"]
+            "n_cutoff2_X": ["Longitudinal Cutoff 2", "Float", 0.0]
         },
         "bunchAnimation": {
             "x": ["Phase Space Coordinate", "PhaseSpaceCoordinate", "Y"],
@@ -777,74 +743,6 @@
             "C3": ["Horizontal Center [m]", "Float", 0],
             "C4": ["Vertical Center [m]", "Float", 0]
         },
-        "DIPOLE": {
-            "name": ["Name", "ValidatedString"],
-            "AT": ["Total Angular Extent of the Dipole [rad]", "Float", 0.0, "AT"],
-            "IL": ["Save Step-by-Step Coordinates and Fields", "Integer", "0", "IL"],
-            "RM": ["Reference Radius [m]", "Float", 0.0, "RM"],
-            "ACN": ["Azimuth for positioning of EFB [rad]", "Float", 0.0, "ACN"],
-            "B_0": ["Field at Pole Tip [kG]", "Float", 0.0, "B_0"],
-            "N": ["1st order field index", "Float", 0.0, "N"],
-            "B": ["2nd order field index", "Float", 0.0, "N'"],
-            "G": ["3rd order field index", "Float", 0.0, "N''"],
-            "LAM_E": ["Entrance Fringe Field Extent [m]", "Float", 0.0],
-            "XI_E": ["Entrance Spiral Angle [rad]", "Float", 0.0, "$\\xi$"],
-            "NCE": ["Number of Components", "Integer", 6],
-            "CE_0": ["Entrance Fringe Field Coefficients $C_0$", "Float", 0.0],
-            "CE_1": ["Entrance Fringe Field Coefficients $C_1$", "Float", 0.0],
-            "CE_2": ["Entrance Fringe Field Coefficients $C_2$", "Float", 0.0],
-            "CE_3": ["Entrance Fringe Field Coefficients $C_3$", "Float", 0.0],
-            "CE_4": ["Entrance Fringe Field Coefficients $C_4$", "Float", 0.0],
-            "CE_5": ["Entrance Fringe Field Coefficients $C_5$", "Float", 0.0],
-            "SHIFT_E": ["Entrance Fringe Shift [m]", "Float", 0.0, "shift"],
-            "OMEGA_E": ["Entrance Azimuth with Respect to ACN [rad]", "Float", 0.0, "$\\omega^+$ or $\\omega^-$"],
-            "THETA_E": ["Entrance Wedge Angle [rad]", "Float", 0.0, "$\\theta$"],
-            "R1_E": ["Entrance Radii $R_1$ [m]", "Float", 1e4],
-            "U1_E": ["Entrance Extent $U_1$ [m]", "Float", -1e4],
-            "U2_E": ["Entrance Extent $U_2$ [m]", "Float", 1e4],
-            "R2_E": ["Entrance Radii $R_2$ [m]", "Float", 1e4],
-            "LAM_S": ["Exit Fringe Field Extent [m]", "Float", 0.0],
-            "XI_S": ["Exit Spiral Angle [rad]", "Float", 0.0, "$\\xi$"],
-            "NCS": ["Number of Components", "Integer", 6],
-            "CS_0": ["Exit Fringe Field Coefficients $C_0$", "Float", 0.0],
-            "CS_1": ["Exit Fringe Field Coefficients $C_1$", "Float", 0.0],
-            "CS_2": ["Exit Fringe Field Coefficients $C_2$", "Float", 0.0],
-            "CS_3": ["Exit Fringe Field Coefficients $C_3$", "Float", 0.0],
-            "CS_4": ["Exit Fringe Field Coefficients $C_4$", "Float", 0.0],
-            "CS_5": ["Exit Fringe Field Coefficients $C_5$", "Float", 0.0],
-            "SHIFT_S": ["Exit Fringe Shift [m]", "Float", 0.0, "shift"],
-            "OMEGA_S": ["Exit Azimuth with Respect to ACN [rad]", "Float", 0.0, "$\\omega+$"],
-            "THETA_S": ["Exit Wedge Angle [rad]", "Float", 0.0, "$\\theta$"],
-            "R1_S": ["Exit Radii $R_1$ [m]", "Float", 1e4],
-            "U1_S": ["Exit Extent $U_1$ [m]", "Float", -1e4],
-            "U2_S": ["Exit Extent $U_2$ [m]", "Float", 1e4],
-            "R2_S": ["Exit Radii $R_2$ [m]", "Float", 1e4],
-            "LAM_L": ["Exit Fringe Field Extent [m]", "Float", 0.0],
-            "XI_L": ["Exit Spiral Angle [rad]", "Float", 0.0, "$\\xi$"],
-            "NCL": ["Number of Components", "Integer", 6],
-            "CL_0": ["Lateral Fringe Field Coefficients $C_0$", "Float", 0.0],
-            "CL_1": ["Lateral Fringe Field Coefficients $C_1$", "Float", 0.0],
-            "CL_2": ["Lateral Fringe Field Coefficients $C_2$", "Float", 0.0],
-            "CL_3": ["Lateral Fringe Field Coefficients $C_3$", "Float", 0.0],
-            "CL_4": ["Lateral Fringe Field Coefficients $C_4$", "Float", 0.0],
-            "CL_5": ["Lateral Fringe Field Coefficients $C_5$", "Float", 0.0],
-            "SHIFT_L": ["Lateral Fringe Shift [m]", "Float", 0.0, "shift"],
-            "OMEGA_L": ["Lateral Azimuth with Respect to ACN [rad]", "Float", 0.0, "$\\omega+$"],
-            "THETA_L": ["Lateral Wedge Angle [rad]", "Float", 0.0, "$\\theta$"],
-            "R1_L": ["Lateral Radii $R_1$ [m]", "Float", 1e4],
-            "U1_L": ["Lateral Extent $U_1$ [m]", "Float", -1e4],
-            "U2_L": ["Lateral Extent $U_2$ [m]", "Float", 1e4],
-            "R2_L": ["Lateral Radii $R_2$ [m]", "Float", 1e4],
-            "R3": ["Lateral Radii $R_3$ [m]", "Float", 1e4],
-            "IORDRE": ["Polynomial Interpolation", "MeshPolynomialInterpolation", "2", "IORDRE"],
-            "Resol": ["Resolution", "Float", 1.0, "Resol"],
-            "XPAS": ["Integration Step [m]", "Float", "0.02", "XPAS"],
-            "KPOS": ["Alignment", "ElementAlignment", "1", "KPOS"],
-            "RE": ["Entrance Frame Radius [m]", "Float", 0, "RE"],
-            "TE": ["Entrance Frame Angle [rad]", "Float", 0, "TE"],
-            "RS": ["Exit Frame Radius [m]", "Float", 0, "RS"],
-            "TS": ["Exit Frame Angle [rad]", "Float", 0, "TS"]
-        },
         "DRIFT": {
             "name": ["Name", "ValidatedString"],
             "l": ["Length [m]", "Float", 0.0, "XL"]
@@ -1165,10 +1063,7 @@
                     "particle.G",
                     "particle.Tau",
                     "rigidity",
-                    "method",
-                    "FNAME",
-                    "FNAME2",
-                    "FNAME3"
+                    "method"
                 ]],
                 ["Distribution", [
                     "particleCount",
@@ -1238,44 +1133,6 @@
                     "particleCoordinate.X",
                     "particleCoordinate.D"
                 ]],
-                ["Selection", [
-                    [
-                        ["Particle", [
-                            "IT1",
-                            "IT2",
-                            "ITStep"
-                        ]],
-                        ["Pass", [
-                            "IP1",
-                            "IP2",
-                            "IPStep"
-                        ]]
-                    ],
-                    "TAG",
-                    "InitC"
-                ]],
-                ["Scale and Offset", [
-                    [
-                        ["Scale", [
-                            "YF",
-                            "TF",
-                            "ZF",
-                            "PF",
-                            "SF",
-                            "DPF",
-                            "TiF"
-                        ]],
-                        ["Offset", [
-                            "YR",
-                            "TR",
-                            "ZR",
-                            "PR",
-                            "SR",
-                            "DPR",
-                            "TiR"
-                        ]]
-                    ]
-                ]],
                 ["Spin and SR Loss", [
                     "SPNTRK.KSO",
                     [
@@ -1626,85 +1483,6 @@
                 "C4"
             ]
         },
-        "DIPOLE": {
-            "title": "Dipole",
-            "description": "Dipole Magnet",
-            "advanced": [
-                ["Main", [
-                    "name",
-                    "AT",
-                    "RM",
-                    "ACN",
-                    "B_0",
-                    "N",
-                    "B",
-                    "G",
-                    "Resol",
-                    "XPAS",
-                    "KPOS",
-                    "IORDRE",
-                    [
-                        ["Entrance", [
-                            "RE",
-                            "TE"
-                        ]],
-                        ["Exit", [
-                            "RS",
-                            "TS"
-                        ]]
-                    ],
-                    "IL"
-                ]],
-                ["Dipole Fringe Fields", [
-                    [
-                        ["Entrance", [
-                            "NCE",
-                            "CE_0",
-                            "CE_1",
-                            "CE_2",
-                            "CE_3",
-                            "CE_4",
-                            "CE_5",
-                            "LAM_E",
-                            "XI_E",
-                            "SHIFT_E"
-                        ]],
-                        ["Exit", [
-                            "NCS",
-                            "CS_0",
-                            "CS_1",
-                            "CS_2",
-                            "CS_3",
-                            "CS_4",
-                            "CS_5",
-                            "LAM_S",
-                            "XI_S",
-                            "SHIFT_S"
-                        ]]
-                    ]
-                ]],
-                ["Dipole Angles", [
-                    [
-                        ["Entrance", [
-                            "OMEGA_E",
-                            "THETA_E",
-                            "R1_E",
-                            "U1_E",
-                            "U2_E",
-                            "R2_E"
-                        ]],
-                        ["Exit", [
-                            "OMEGA_S",
-                            "THETA_S",
-                            "R1_S",
-                            "U1_S",
-                            "U2_S",
-                            "R2_S"
-                        ]]
-                    ]
-                ]]
-            ]
-        },
         "DRIFT": {
             "title": "DRIFT",
             "description": "Field free drift space",
diff --git a/sirepo/package_data/template/zgoubi/bunch.py.jinja b/sirepo/package_data/template/zgoubi/bunch.py.jinja
index 7e8614207..e0846453b 100644
--- a/sirepo/package_data/template/zgoubi/bunch.py.jinja
+++ b/sirepo/package_data/template/zgoubi/bunch.py.jinja
@@ -17,7 +17,7 @@ line.add(core.FAKE_ELEM("""
 {{ bunch_alpha_X }} {{ bunch_beta_X }} {{ bunch_emit_X }} {{ bunch_n_cutoff_X }} {{ bunch_n_cutoff2_X }}
 123456 234567 345678
 """))
-{% elif bunch_method == 'OBJET2.1' %}
+{% else %}
 line.add(core.FAKE_ELEM("""
 'OBJET'
 {{ bunch_rigidity }}
@@ -28,28 +28,8 @@ line.add(core.FAKE_ELEM("""
 {% endfor %}
 {{ '1 ' * bunch_particleCount2 }}
 """))
-{% else %}
-line.add(core.FAKE_ELEM("""
-'OBJET'
-{{ bunch_rigidity }}
-{% if bunch_method == 'OBJET3' %}
-3
-{% elif bunch_method == 'OBJET3.1' %}
-3.1
-{% else %}
-3.2
-{% endif %}
-{{ bunch_IT1 }} {{ bunch_IT2 }} {{ bunch_ITStep }}
-{{ bunch_IP1 }} {{ bunch_IP2 }} {{ bunch_IPStep }}
-{{ bunch_YF }} {{ bunch_TF }} {{ bunch_ZF }} {{ bunch_PF }} {{ bunch_SF }} {{ bunch_DPF }} {{ bunch_TiF }} {{ bunch_TAG }}
-{{ bunch_YR }} {{ bunch_TR }} {{ bunch_ZR }} {{ bunch_PR }} {{ bunch_SR }} {{ bunch_DPR }} {{ bunch_TiR }}
-{{ bunch_InitC }}
-{% if bunch_method == 'OBJET3' %}{{ bunch_FNAME }}{% elif bunch_method == 'OBJET3.1' %}{{ bunch_FNAME2 }}{% else %}{{ bunch_FNAME3 }}{% endif %}
-"""))
 {% endif %}
-{% if particle_particleType != 'None' %}
 line.add(core.FAKE_ELEM("""
 'PARTICUL'
 {{ particleDef }}
 """))
-{% endif %}
diff --git a/sirepo/package_data/template/zgoubi/twiss.py.jinja b/sirepo/package_data/template/zgoubi/twiss.py.jinja
index 02ae8f163..5bb9041b5 100644
--- a/sirepo/package_data/template/zgoubi/twiss.py.jinja
+++ b/sirepo/package_data/template/zgoubi/twiss.py.jinja
@@ -12,12 +12,11 @@ line.add(core.OBJET5(
     DR={{ bunchCoordinates[0]['D'] }},
 {% endif %}
 ))
-{% if particle_particleType != 'None' %}
 line.add(core.FAKE_ELEM("""
 'PARTICUL'
 {{ particleDef }}
 """))
-{% endif %}
+
 line.add(core.FAKE_ELEM("""
 'OPTIONS'
 1 1
diff --git a/sirepo/pkcli/zgoubi.py b/sirepo/pkcli/zgoubi.py
index 795189f91..baedea298 100644
--- a/sirepo/pkcli/zgoubi.py
+++ b/sirepo/pkcli/zgoubi.py
@@ -78,9 +78,7 @@ def _beamline_steps(beamline_map, element_map, beamline_id):
 
 def _bunch_match_twiss(cfg_dir, data):
     bunch = data.models.bunch
-    if bunch.match_twiss_parameters == '1' \
-       and bunch.method == 'MCOBJET3' \
-       and ('bunchReport' in data.report or data.report == 'animation'):
+    if bunch.match_twiss_parameters == '1' and ('bunchReport' in data.report or data.report == 'animation'):
         report = data['report']
         data['report'] = 'twissReport2'
         template.write_parameters(data, py.path.local(cfg_dir), False, 'twiss.py')
@@ -130,9 +128,6 @@ def _validate_estimate_output_file_size(data, res):
     count = bunch.particleCount
     if bunch.method == 'OBJET2.1':
         count = bunch.particleCount2
-    elif re.search(r'^OBJET3', bunch.method):
-        #TODO(pjm): just an estimate, need to read/filter data file
-        count = 10
     settings = data.models.simulationSettings
     line_size = 800
     fai_size = line_size * settings.npass / (settings.ip or 1) * float(count)
diff --git a/sirepo/sim_data/zgoubi.py b/sirepo/sim_data/zgoubi.py
index 36c4ab256..174e9dfc7 100644
--- a/sirepo/sim_data/zgoubi.py
+++ b/sirepo/sim_data/zgoubi.py
@@ -104,14 +104,6 @@ class SimData(sirepo.sim_data.SimDataBase):
     @classmethod
     def _lib_file_basenames(cls, data):
         res = []
-        bunch = data.models.bunch
-        for info in (
-            ['OBJET3', 'FNAME'],
-            ['OBJET3.1', 'FNAME2'],
-            ['OBJET3.2', 'FNAME3'],
-        ):
-            if bunch.method == info[0] and bunch[info[1]]:
-                res.append(cls.lib_file_name_with_model_field('bunch', info[1], bunch[info[1]]))
         for el in data.models.elements:
             if el.type == 'TOSCA' and el.magnetFile:
                 res.append(cls.lib_file_name_with_model_field('TOSCA', 'magnetFile', el.magnetFile))
diff --git a/sirepo/template/template_common.py b/sirepo/template/template_common.py
index 4de46821b..e7b982ec9 100644
--- a/sirepo/template/template_common.py
+++ b/sirepo/template/template_common.py
@@ -188,7 +188,6 @@ class ParticleEnergy(object):
         assert energy.gamma >= 1, \
             'energy gamma out of range: {}'.format(energy.gamma)
         energy.energy = energy.gamma * particle.mass
-        energy.kinetic_energy = energy.energy - particle.mass
         energy.beta = math.sqrt(1.0 - 1.0 / (energy.gamma ** 2))
         energy.pc = energy.gamma * energy.beta * particle.mass
         energy.brho = energy.pc / (abs(particle.charge) * cls.SPEED_OF_LIGHT * 1e-9)
diff --git a/sirepo/template/zgoubi.py b/sirepo/template/zgoubi.py
index 34b35adf4..2677f754a 100644
--- a/sirepo/template/zgoubi.py
+++ b/sirepo/template/zgoubi.py
@@ -32,6 +32,8 @@ WANT_BROWSER_FRAME_CACHE = True
 
 TUNES_INPUT_FILE = 'tunesFromFai.In'
 
+ZGOUBI_LOG_FILE = 'sr_zgoubi.log'
+
 _ELEMENT_NAME_MAP = PKDict({
     'FFAG': 'FFA',
     'FFAG-SPI': 'FFA-SPI',
@@ -429,14 +431,6 @@ def import_file(req, unit_test_mode=False, **kwargs):
     )
 
 
-def post_execution_processing(success_exit=True, is_parallel=False, run_dir=None, **kwargs):
-    if success_exit:
-        return None
-    if not is_parallel:
-        return _parse_zgoubi_log(run_dir)
-    return None
-
-
 def prepare_sequential_output_file(run_dir, data):
     report = data.report
     if 'bunchReport' in report or 'twissReport' in report or 'opticsReport' in report:
@@ -744,10 +738,11 @@ def _generate_beamline(data, beamline_map, element_map, beamline_id):
         elif el.type == 'SCALING':
             #TODO(pjm): convert to fake element jinja template
             form = 'line.add(core.FAKE_ELEM(""" \'SCALING\'\n{} {}\n{}"""))\n'
-            max_family = _SCHEMA.constants.maxScalingFamily
+            #TODO(pjm): keep in sync with zgoubi.js
+            _MAX_SCALING_FAMILY = 7
             count = 0
             scale_values = ''
-            for idx in range(1, max_family + 1):
+            for idx in range(1, _MAX_SCALING_FAMILY + 1):
                 # NAMEF1, SCL1, LBL1
                 if el.get('NAMEF{}'.format(idx), 'none') != 'none':
                     count += 1
@@ -791,11 +786,6 @@ def _generate_pyzgoubi_element(el, schema_type=None):
 
 
 def _generate_parameters_file(data):
-    bunch = data.models.bunch
-    zgoubi_importer.MODEL_UNITS.scale_to_native('bunch', bunch)
-    for f in ('FNAME', 'FNAME2', 'FNAME3'):
-        if bunch[f]:
-            bunch[f] = _SIM_DATA.lib_file_name_with_model_field('bunch', f, bunch[f])
     res, v = template_common.generate_parameters_file(data)
     report = data.report if 'report' in data else ''
     if report == 'tunesReport':
@@ -803,7 +793,7 @@ def _generate_parameters_file(data):
     v.zgoubiCommandFile = _ZGOUBI_COMMAND_FILE
     v.particleDef = _generate_particle(data.models.particle)
     v.beamlineElements = _generate_beamline_elements(report, data)
-    v.bunchCoordinates = bunch.coordinates
+    v.bunchCoordinates = data.models.bunch.coordinates
     res += template_common.render_jinja(SIM_TYPE, v, 'base.py')
     if 'twissReport' in report or 'opticsReport' in report or report == 'twissSummaryReport':
         v.fitYRange = [-10, 10]
@@ -856,8 +846,6 @@ def _parse_zgoubi_log(run_dir):
         if re.search('all particles lost', line):
             res += '{}\n'.format(line)
             continue
-        if re.search('charge found null', line):
-            res += '{}\n'.format(line)
         match = re.search(r'Enjob occured at element # (\d+)', line)
         if match:
             res += '{}\n'.format(line)
diff --git a/sirepo/template/zgoubi_importer.py b/sirepo/template/zgoubi_importer.py
index 7fb09d23c..94e0787de 100644
--- a/sirepo/template/zgoubi_importer.py
+++ b/sirepo/template/zgoubi_importer.py
@@ -141,13 +141,6 @@ def _init_model_units():
         return ModelUnits.scale_value(v, 'cm_to_m', is_native)
 
     return ModelUnits(PKDict(
-        bunch=PKDict(
-            YR='cm_to_m',
-            TR='mrad_to_rad',
-            ZR='cm_to_m',
-            PR='mrad_to_rad',
-            SR='cm_to_m',
-        ),
         AUTOREF=PKDict(
             XCE='cm_to_m',
             YCE='cm_to_m',
@@ -180,40 +173,6 @@ def _init_model_units():
             C3='cm_to_m',
             C4='cm_to_m',
         ),
-        DIPOLE=PKDict(
-            AT='deg_to_rad',
-            ACN='deg_to_rad',
-            RM='cm_to_m',
-            LAM_E='cm_to_m',
-            SHIFT_E='cm_to_m',
-            OMEGA_E='deg_to_rad',
-            THETA_E='deg_to_rad',
-            R1_E='cm_to_m',
-            U1_E='cm_to_m',
-            U2_E='cm_to_m',
-            R2_E='cm_to_m',
-            LAM_S='cm_to_m',
-            SHIFT_S='cm_to_m',
-            OMEGA_S='deg_to_rad',
-            THETA_S='deg_to_rad',
-            R1_S='cm_to_m',
-            U1_S='cm_to_m',
-            U2_S='cm_to_m',
-            R2_S='cm_to_m',
-            LAM_L='cm_to_m',
-            SHIFT_L='cm_to_m',
-            OMEGA_L='deg_to_rad',
-            THETA_L='deg_to_rad',
-            R1_L='cm_to_m',
-            U1_L='cm_to_m',
-            U2_L='cm_to_m',
-            R2_L='cm_to_m',
-            R3_L='cm_to_m',
-            RE='cm_to_m',
-            TE='deg_to_rad',
-            RS='cm_to_m',
-            TS='deg_to_rad',
-        ),
         DRIFT=PKDict(
             l='cm_to_m',
         ),
diff --git a/sirepo/template/zgoubi_parser.py b/sirepo/template/zgoubi_parser.py
index 13ff637ac..e742f935a 100644
--- a/sirepo/template/zgoubi_parser.py
+++ b/sirepo/template/zgoubi_parser.py
@@ -331,30 +331,6 @@ def _zgoubi_collima(command):
     assert False, 'unsupported COLLIMA IFORM: {}'.format(iform)
 
 
-def _zgoubi_dipole(command):
-    res = _parse_command(command, [
-        'IL',
-        'AT RM',
-        'ACN B_0 N B G',
-        'LAM_E XI_E',
-        'NCE CE_0 CE_1 CE_2 CE_3 CE_4 CE_5 SHIFT_E',
-        'OMEGA_E THETA_E R1_E U1_E U2_E R2_E',
-        'LAM_S XI_S',
-        'NCS CS_0 CS_1 CS_2 CS_3 CS_4 CS_5 SHIFT_S',
-        'OMEGA_S THETA_S R1_S U1_S U2_S R2_S',
-        'LAM_L XI_L',
-        'NCL CL_0 CL_1 CL_2 CL_3 CL_4 CL_5 SHIFT_L',
-        'OMEGA_L THETA_L R1_L U1_L U2_L R2_L R3',
-        'IORDRE Resol',
-        'XPAS',
-        'KPOS RE TE RS TS',
-    ])
-    if res.KPOS == '1':
-        res.DP = res.RE
-        _remove_fields(res, ['RE', 'TE', 'RS', 'TS'])
-    return res
-
-
 def _zgoubi_drift(command):
     return _parse_command(command, [
         'l',

Better error when sbatch is down
Cori is currently down for maintenance. I tried to use is as the driver on production and alpha. 

On alpha, an error page was returned but the modal didn't not disappear.  It was just hung. There was an error saying "request failed" that could be more informative.
![Screen Shot 2020-05-20 at 9 31 22 AM](https://user-images.githubusercontent.com/10264515/82465685-cc27bd00-9a7c-11ea-97e9-66ab7fe055a6.png)

diff --git a/tests/template/particle_energy_test.py b/tests/template/particle_energy_test.py
index a5072e965..c0168cbb2 100644
--- a/tests/template/particle_energy_test.py
+++ b/tests/template/particle_energy_test.py
@@ -20,12 +20,9 @@ def test_energy_conversion():
         brho=1.0000079454967472,
         energy=0.9850032377589688,
         gamma=1.0498055888568685,
-        kinetic_energy=0.04673119175896878,
         pc=0.2997948399999999,
     ))
     for f in energy:
-        if f == 'kinetic_energy':
-            continue
         pkeq(energy, ParticleEnergy.compute_energy('madx', 'proton', PKDict({
             f: energy[f],
         })))
@@ -44,7 +41,6 @@ def test_energy_conversion_by_sim_type():
             brho=3.33897659310099,
             energy=1.0010001304797258,
             gamma=1958.908474421938,
-            kinetic_energy=1.0004891315517257,
             pc=1.001,
         )
     )
@@ -55,7 +51,6 @@ def test_energy_conversion_by_sim_type():
             brho=3.002077837014637,
             energy=0.900000438932496,
             gamma=1761.257,
-            kinetic_energy=0.899489440004496,
             pc=0.9000002938659415,
         )
     )

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
aenum==3.1.15
alabaster==0.7.16
argh==0.31.3
asyncssh==2.20.0
Authlib==1.5.1
babel==2.17.0
black==24.10.0
blinker==1.9.0
certifi==2025.1.31
cffi==1.17.1
charset-normalizer==3.4.1
click==8.1.8
cryptography==44.0.2
dnspython==2.7.0
docutils==0.21.2
et_xmlfile==2.0.0
exceptiongroup==1.2.2
Flask==3.1.0
Flask-Mail==0.10.0
future==1.0.0
futures==3.0.5
github3.py==4.0.1
greenlet==3.1.1
idna==3.10
imagesize==1.4.1
importlib_metadata==8.6.1
iniconfig==2.1.0
itsdangerous==2.2.0
Jinja2==3.1.6
MarkupSafe==3.0.2
msgpack==1.1.0
mypy-extensions==1.0.0
numconv==2.1.1
numpy==2.0.2
openpyxl==3.1.5
packaging==24.2
pandas==2.2.3
path==17.1.0
path.py==12.5.0
pathspec==0.12.1
platformdirs==4.3.7
pluggy==1.5.0
psutil==7.0.0
py==1.11.0
py-cpuinfo==9.0.0
pycparser==2.22
Pygments==2.19.1
pyIsEmail==2.0.1
PyJWT==2.10.1
pykern==20250224.223823
pytest==8.3.5
pytest-asyncio==0.26.0
python-dateutil==2.9.0.post0
pytz==2025.2
requests==2.32.3
ruamel.yaml==0.18.10
ruamel.yaml.clib==0.2.12
-e git+https://github.com/radiasoft/sirepo.git@8de0bf4303402bb4d37e5a1a67fc36b60e26d890#egg=sirepo
six==1.17.0
snowballstemmer==2.2.0
Sphinx==7.4.7
sphinxcontrib-applehelp==2.0.0
sphinxcontrib-devhelp==2.0.0
sphinxcontrib-htmlhelp==2.1.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==2.0.0
sphinxcontrib-serializinghtml==2.0.0
SQLAlchemy==2.0.40
toml==0.10.2
tomli==2.2.1
tornado==6.4.2
typing_extensions==4.13.0
tzdata==2025.2
ua-parser==1.0.1
ua-parser-builtins==0.18.0.post1
uritemplate==4.1.1
urllib3==2.3.0
user-agents==2.2.0
uWSGI==2.0.28
Werkzeug==3.1.3
XlsxWriter==3.2.2
zipp==3.21.0

name: sirepo
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - aenum==3.1.15
      - alabaster==0.7.16
      - argh==0.31.3
      - asyncssh==2.20.0
      - authlib==1.5.1
      - babel==2.17.0
      - black==24.10.0
      - blinker==1.9.0
      - certifi==2025.1.31
      - cffi==1.17.1
      - charset-normalizer==3.4.1
      - click==8.1.8
      - cryptography==44.0.2
      - dnspython==2.7.0
      - docutils==0.21.2
      - et-xmlfile==2.0.0
      - exceptiongroup==1.2.2
      - flask==3.1.0
      - flask-mail==0.10.0
      - future==1.0.0
      - futures==3.0.5
      - github3-py==4.0.1
      - greenlet==3.1.1
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==8.6.1
      - iniconfig==2.1.0
      - itsdangerous==2.2.0
      - jinja2==3.1.6
      - markupsafe==3.0.2
      - msgpack==1.1.0
      - mypy-extensions==1.0.0
      - numconv==2.1.1
      - numpy==2.0.2
      - openpyxl==3.1.5
      - packaging==24.2
      - pandas==2.2.3
      - path==17.1.0
      - path-py==12.5.0
      - pathspec==0.12.1
      - platformdirs==4.3.7
      - pluggy==1.5.0
      - psutil==7.0.0
      - py==1.11.0
      - py-cpuinfo==9.0.0
      - pycparser==2.22
      - pygments==2.19.1
      - pyisemail==2.0.1
      - pyjwt==2.10.1
      - pykern==20250224.223823
      - pytest==8.3.5
      - pytest-asyncio==0.26.0
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - requests==2.32.3
      - ruamel-yaml==0.18.10
      - ruamel-yaml-clib==0.2.12
      - six==1.17.0
      - snowballstemmer==2.2.0
      - sphinx==7.4.7
      - sphinxcontrib-applehelp==2.0.0
      - sphinxcontrib-devhelp==2.0.0
      - sphinxcontrib-htmlhelp==2.1.0
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==2.0.0
      - sphinxcontrib-serializinghtml==2.0.0
      - sqlalchemy==2.0.40
      - toml==0.10.2
      - tomli==2.2.1
      - tornado==6.4.2
      - typing-extensions==4.13.0
      - tzdata==2025.2
      - ua-parser==1.0.1
      - ua-parser-builtins==0.18.0.post1
      - uritemplate==4.1.1
      - urllib3==2.3.0
      - user-agents==2.2.0
      - uwsgi==2.0.28
      - werkzeug==3.1.3
      - xlsxwriter==3.2.2
      - zipp==3.21.0
prefix: /opt/conda/envs/sirepo

tests/template/particle_energy_test.py::test_energy_conversion tests/template/particle_energy_test.py::test_energy_conversion_by_sim_type
sirepo/package_data/static/js/zgoubi.js sirepo/pkcli/zgoubi.py sirepo/package_data/template/zgoubi/twiss.py.jinja sirepo/template/zgoubi_importer.py sirepo/package_data/static/html/zgoubi-twiss.html sirepo/job_driver/sbatch.py sirepo/sim_data/zgoubi.py sirepo/template/zgoubi.py sirepo/template/zgoubi_parser.py sirepo/template/template_common.py sirepo/package_data/static/js/sirepo-components.js sirepo/package_data/static/json/zgoubi-schema.json sirepo/package_data/template/zgoubi/bunch.py.jinja
sirepo/package_data/static/js/zgoubi.js sirepo/pkcli/zgoubi.py sirepo/package_data/template/zgoubi/twiss.py.jinja sirepo/template/zgoubi_importer.py sirepo/package_data/static/html/zgoubi-twiss.html sirepo/job_driver/sbatch.py sirepo/sim_data/zgoubi.py sirepo/template/zgoubi.py sirepo/template/zgoubi_parser.py sirepo/template/template_common.py sirepo/package_data/static/js/sirepo-components.js sirepo/package_data/static/json/zgoubi-schema.json sirepo/package_data/template/zgoubi/bunch.py.jinja