/*
 * thermal_runaway_propagation.java
 */

import com.comsol.model.*;
import com.comsol.model.util.*;

/** Model exported on May 17 2026, 08:24 by COMSOL 6.4.0.422. */
public class thermal_runaway_propagation {

  public static Model run() {
    Model model = ModelUtil.create("Model");

//    From the File menu, choose New.
//    In the New window, click Model Wizard.
//    In the Model Wizard window, click 3D.
//    In the Select Physics tree, select Electrochemistry > Batteries > Battery Pack (bp).
//    Click Add.
//    In the Select Physics tree, select Heat Transfer > Heat Transfer in Solids (ht).
//    Click Add.
//    Click Study.
//    In the Select Study tree, select General Studies > Time Dependent.
//    Click Done.

    model.component().create("comp1", true);

    model.component("comp1").geom().create("geom1", 3);
    model.component("comp1").geom("geom1").geomRep("comsol");

    model.component("comp1").mesh().create("mesh1");
    model.component("comp1").mesh("mesh1").contribute("geom/detail", true);

    model.component("comp1").physics().create("bp", "BatteryPack", "geom1");
    model.component("comp1").physics().create("ht", "HeatTransfer", "geom1");

    model.study().create("std1");
    model.study("std1").create("time", "Transient");

//    Import the geometry sequence from a file.
//    In the Geometry toolbar, click Insert Sequence and choose Insert Sequence.
//    Browse to the model's Application Library folder and double-click the file thermal_runaway_propagation_geom_sequence.mph.
//    In the Insert Sequence dialog, select Geometry 1 in the Select geometry sequence to insert list.
//    Click OK.

    model.component("comp1").geom("geom1").insertFile("thermal_runaway_propagation_geom_sequence.mph", "geom1");

//    In the Geometry toolbar, click Build All.

    model.component("comp1").geom("geom1").run("adjsel1");

//    Inspect the imported geometry. You can enable and disable wireframe rendering and transparency to view internal geometry features.
//    Click the Transparency button in the Graphics toolbar.

    model.component("comp1").view("view1").set("transparency", true);
    model.component("comp1").view("view1").set("showgrid", false);
    model.component("comp1").view("view1").set("showaxisorientation", false);

//    In the Model Builder window, under Component 1 (comp1), click Geometry 1.

    model.component("comp1").view("view1").set("showgrid", true);
    model.component("comp1").view("view1").set("showaxisorientation", true);

//    Disable the analysis of the geometry as the remaining small geometric details can be kept.
//    In the Model Builder window, click Geometry 1.
//    In the Settings window for Geometry, locate the Cleanup section.
//    Clear the Automatic detection of small details checkbox.
//    In the Model Builder window, collapse the Component 1 (comp1) > Geometry 1 node.
//    Some geometry parameters were imported together with the geometry sequence.
//    In the Model Builder window, under Global Definitions, click Parameters 1.
//    In the Settings window for Parameters, type Geometry Parameters in the Label text field.

    model.param().label("Geometry Parameters");

//    Import some additional parameters needed for setting up the physics.
//    In the Home toolbar, click Parameters and choose Add > Parameters.

    model.param().create("par2");

//    In the Settings window for Parameters, type Physics Parameters in the Label text field.

    model.param("par2").label("Physics Parameters");

//    Locate the Parameters section.
//    Click Load from File.
//    Browse to the model's Application Library folder and double-click the file thermal_runaway_propagation_physics_parameters.txt.
//    To import content from file, use:
//    model.param("par2").loadFile("FILENAME");
    model.param("par2").set("Q_cell", "2.5[A*h]", "Cell capacity");
    model.param("par2").set("n_batt", "nx_batt*ny_batt", "Number of battery cells in pack");
    model.param("par2").set("I_1C_pack", "Q_cell*ny_batt/1[h]", "Total 1C pack current (when applied at terminals)");
    model.param("par2").set("SOC_0", "0.25", "Initial state of charge");
    model.param("par2").set("C_rate", "2", "C rate");
    model.param("par2").set("T_ext", "30[degC]", "External temperature");
    model.param("par2").set("h_conv", "10[W/m^2/K]", "Convective cooling heat transfer coefficient");
    model.param("par2").set("kT_batt_il", "30[W/m/K]", "Battery in-layer thermal conductivity");
    model.param("par2").set("kT_batt_tl", "1[W/m/K]", "Battery through-layer thermal conductivity");
    model.param("par2").set("rho_batt", "2000[kg/m^3]", "Battery average density");
    model.param("par2").set("Cp_batt", "1400[J/(kg*K)]", "Battery average heat capacity");
    model.param("par2").set("J0", "0.85", "Dimensionless charge exchange current density");
    model.param("par2").set("tau", "1000[s]", "Diffusion time constant");
    model.param("par2").set("eta_1C", "4.5[mV]", "Ohmic overpotential at 1C");
    model.param("par2").set("T_trigger", "80[degC]", "Trigger temperature for thermal event");
    model.param("par2").set("t_start", "1[min]", "Start time for first cell thermal runaway");
    model.param("par2").set("t_peak", "1[s]", "Peak time during cell thermal runaway");
    model.param("par2").set("t_tr", "6[s]", "Cell thermal runaway time");
    model.param("par2").set("W_tr", "32[kJ]", "Total heat release during cell thermal runaway");
    model.param("par2").set("Qh_peak", "2*W_tr/t_tr", "Peak heat source during cell thermal runaway");
    model.param("par2").set("E_max_cell", "4.2[V]", "Maximum cell voltage during charge");
    model.param("par2").set("E_max_pack", "nx_batt*E_max_cell", "Maximum pack voltage during charge");

//    In the Home toolbar, click Add Material to open the Add Material window.
//    Add some materials from the built-in material library.
//    In the tree, select Built-in > Air.
//    Right-click and choose Add to Component 1 (comp1).

    model.component("comp1").material().create("mat1", "Common");
    model.component("comp1").material("mat1").propertyGroup("def").func().create("eta", "Piecewise");
    model.component("comp1").material("mat1").propertyGroup("def").func().create("Cp", "Piecewise");
    model.component("comp1").material("mat1").propertyGroup("def").func().create("rho", "Analytic");
    model.component("comp1").material("mat1").propertyGroup("def").func().create("k", "Piecewise");
    model.component("comp1").material("mat1").propertyGroup("def").func().create("cs", "Analytic");
    model.component("comp1").material("mat1").propertyGroup("def").func().create("an1", "Analytic");
    model.component("comp1").material("mat1").propertyGroup("def").func().create("an2", "Analytic");
    model.component("comp1").material("mat1").propertyGroup()
         .create("RefractiveIndex", "RefractiveIndex", "Refractive index");
    model.component("comp1").material("mat1").propertyGroup()
         .create("NonlinearModel", "NonlinearModel", "Nonlinear model");
    model.component("comp1").material("mat1").propertyGroup().create("idealGas", "idealGas", "Ideal gas");
    model.component("comp1").material("mat1").propertyGroup("idealGas").func().create("Cp", "Piecewise");
    model.component("comp1").material("mat1").label("Air");
    model.component("comp1").material("mat1").set("family", "air");
    model.component("comp1").material("mat1").propertyGroup("def").func("eta").set("arg", "T");
    model.component("comp1").material("mat1").propertyGroup("def").func("eta")
         .set("pieces", new String[][]{{"200.0", "1600.0", "-8.38278E-7+8.35717342E-8*T^1-7.69429583E-11*T^2+4.6437266E-14*T^3-1.06585607E-17*T^4"}});
    model.component("comp1").material("mat1").propertyGroup("def").func("eta").set("argunit", "K");
    model.component("comp1").material("mat1").propertyGroup("def").func("eta").set("fununit", "Pa*s");
    model.component("comp1").material("mat1").propertyGroup("def").func("Cp").set("arg", "T");
    model.component("comp1").material("mat1").propertyGroup("def").func("Cp")
         .set("pieces", new String[][]{{"200.0", "1600.0", "1047.63657-0.372589265*T^1+9.45304214E-4*T^2-6.02409443E-7*T^3+1.2858961E-10*T^4"}});
    model.component("comp1").material("mat1").propertyGroup("def").func("Cp").set("argunit", "K");
    model.component("comp1").material("mat1").propertyGroup("def").func("Cp").set("fununit", "J/(kg*K)");
    model.component("comp1").material("mat1").propertyGroup("def").func("rho")
         .set("expr", "pA*0.02897/R_const[K*mol/J]/T");
    model.component("comp1").material("mat1").propertyGroup("def").func("rho").set("args", new String[]{"pA", "T"});
    model.component("comp1").material("mat1").propertyGroup("def").func("rho").set("fununit", "kg/m^3");
    model.component("comp1").material("mat1").propertyGroup("def").func("rho")
         .set("argunit", new String[]{"Pa", "K"});
    model.component("comp1").material("mat1").propertyGroup("def").func("rho")
         .set("plotaxis", new String[]{"off", "on"});
    model.component("comp1").material("mat1").propertyGroup("def").func("rho")
         .set("plotfixedvalue", new String[]{"101325", "273.15"});
    model.component("comp1").material("mat1").propertyGroup("def").func("rho")
         .set("plotargs", new String[][]{{"pA", "101325", "101325"}, {"T", "273.15", "293.15"}});
    model.component("comp1").material("mat1").propertyGroup("def").func("k").set("arg", "T");
    model.component("comp1").material("mat1").propertyGroup("def").func("k")
         .set("pieces", new String[][]{{"200.0", "1600.0", "-0.00227583562+1.15480022E-4*T^1-7.90252856E-8*T^2+4.11702505E-11*T^3-7.43864331E-15*T^4"}});
    model.component("comp1").material("mat1").propertyGroup("def").func("k").set("argunit", "K");
    model.component("comp1").material("mat1").propertyGroup("def").func("k").set("fununit", "W/(m*K)");
    model.component("comp1").material("mat1").propertyGroup("def").func("cs")
         .set("expr", "sqrt(1.4*R_const[K*mol/J]/0.02897*T)");
    model.component("comp1").material("mat1").propertyGroup("def").func("cs").set("args", new String[]{"T"});
    model.component("comp1").material("mat1").propertyGroup("def").func("cs").set("fununit", "m/s");
    model.component("comp1").material("mat1").propertyGroup("def").func("cs").set("argunit", new String[]{"K"});
    model.component("comp1").material("mat1").propertyGroup("def").func("cs")
         .set("plotfixedvalue", new String[]{"273.15"});
    model.component("comp1").material("mat1").propertyGroup("def").func("cs")
         .set("plotargs", new String[][]{{"T", "273.15", "373.15"}});
    model.component("comp1").material("mat1").propertyGroup("def").func("an1").set("funcname", "alpha_p");
    model.component("comp1").material("mat1").propertyGroup("def").func("an1")
         .set("expr", "-1/rho(pA,T)*d(rho(pA,T),T)");
    model.component("comp1").material("mat1").propertyGroup("def").func("an1").set("args", new String[]{"pA", "T"});
    model.component("comp1").material("mat1").propertyGroup("def").func("an1").set("fununit", "1/K");
    model.component("comp1").material("mat1").propertyGroup("def").func("an1")
         .set("argunit", new String[]{"Pa", "K"});
    model.component("comp1").material("mat1").propertyGroup("def").func("an1")
         .set("plotaxis", new String[]{"off", "on"});
    model.component("comp1").material("mat1").propertyGroup("def").func("an1")
         .set("plotfixedvalue", new String[]{"101325", "273.15"});
    model.component("comp1").material("mat1").propertyGroup("def").func("an1")
         .set("plotargs", new String[][]{{"pA", "101325", "101325"}, {"T", "273.15", "373.15"}});
    model.component("comp1").material("mat1").propertyGroup("def").func("an2").set("funcname", "muB");
    model.component("comp1").material("mat1").propertyGroup("def").func("an2").set("expr", "0.6*eta(T)");
    model.component("comp1").material("mat1").propertyGroup("def").func("an2").set("args", new String[]{"T"});
    model.component("comp1").material("mat1").propertyGroup("def").func("an2").set("fununit", "Pa*s");
    model.component("comp1").material("mat1").propertyGroup("def").func("an2").set("argunit", new String[]{"K"});
    model.component("comp1").material("mat1").propertyGroup("def").func("an2")
         .set("plotfixedvalue", new String[]{"200"});
    model.component("comp1").material("mat1").propertyGroup("def").func("an2")
         .set("plotargs", new String[][]{{"T", "200", "1600"}});
    model.component("comp1").material("mat1").propertyGroup("def").set("thermalexpansioncoefficient", "");
    model.component("comp1").material("mat1").propertyGroup("def").set("molarmass", "");
    model.component("comp1").material("mat1").propertyGroup("def").set("bulkviscosity", "");
    model.component("comp1").material("mat1").propertyGroup("def")
         .set("thermalexpansioncoefficient", new String[]{"alpha_p(pA,T)", "0", "0", "0", "alpha_p(pA,T)", "0", "0", "0", "alpha_p(pA,T)"});
    model.component("comp1").material("mat1").propertyGroup("def").set("molarmass", "0.02897[kg/mol]");
    model.component("comp1").material("mat1").propertyGroup("def").set("bulkviscosity", "muB(T)");
    model.component("comp1").material("mat1").propertyGroup("def")
         .set("relpermeability", new String[]{"1", "0", "0", "0", "1", "0", "0", "0", "1"});
    model.component("comp1").material("mat1").propertyGroup("def")
         .set("relpermittivity", new String[]{"1", "0", "0", "0", "1", "0", "0", "0", "1"});
    model.component("comp1").material("mat1").propertyGroup("def").set("dynamicviscosity", "eta(T)");
    model.component("comp1").material("mat1").propertyGroup("def").set("ratioofspecificheat", "1.4");
    model.component("comp1").material("mat1").propertyGroup("def")
         .set("electricconductivity", new String[]{"0[S/m]", "0", "0", "0", "0[S/m]", "0", "0", "0", "0[S/m]"});
    model.component("comp1").material("mat1").propertyGroup("def").set("heatcapacity", "Cp(T)");
    model.component("comp1").material("mat1").propertyGroup("def").set("density", "rho(pA,T)");
    model.component("comp1").material("mat1").propertyGroup("def")
         .set("thermalconductivity", new String[]{"k(T)", "0", "0", "0", "k(T)", "0", "0", "0", "k(T)"});
    model.component("comp1").material("mat1").propertyGroup("def").set("soundspeed", "cs(T)");
    model.component("comp1").material("mat1").propertyGroup("def").addInput("temperature");
    model.component("comp1").material("mat1").propertyGroup("def").addInput("pressure");
    model.component("comp1").material("mat1").propertyGroup("RefractiveIndex")
         .set("n", new String[]{"1", "0", "0", "0", "1", "0", "0", "0", "1"});
    model.component("comp1").material("mat1").propertyGroup("NonlinearModel").set("BA", "def.gamma-1");
    model.component("comp1").material("mat1").propertyGroup("idealGas").func("Cp").label("Piecewise 2");
    model.component("comp1").material("mat1").propertyGroup("idealGas").func("Cp").set("arg", "T");
    model.component("comp1").material("mat1").propertyGroup("idealGas").func("Cp")
         .set("pieces", new String[][]{{"200.0", "1600.0", "1047.63657-0.372589265*T^1+9.45304214E-4*T^2-6.02409443E-7*T^3+1.2858961E-10*T^4"}});
    model.component("comp1").material("mat1").propertyGroup("idealGas").func("Cp").set("argunit", "K");
    model.component("comp1").material("mat1").propertyGroup("idealGas").func("Cp").set("fununit", "J/(kg*K)");
    model.component("comp1").material("mat1").propertyGroup("idealGas").set("Rs", "R_const/Mn");
    model.component("comp1").material("mat1").propertyGroup("idealGas").set("heatcapacity", "Cp(T)");
    model.component("comp1").material("mat1").propertyGroup("idealGas").set("ratioofspecificheat", "1.4");
    model.component("comp1").material("mat1").propertyGroup("idealGas").set("molarmass", "0.02897[kg/mol]");
    model.component("comp1").material("mat1").propertyGroup("idealGas").addInput("temperature");
    model.component("comp1").material("mat1").propertyGroup("idealGas").addInput("pressure");
    model.component("comp1").material("mat1").materialType("nonSolid");

//    In the tree, select Built-in > Acrylic plastic.
//    Right-click and choose Add to Component 1 (comp1).

    model.component("comp1").material().create("mat2", "Common");
    model.component("comp1").material("mat2").propertyGroup()
         .create("Enu", "Enu", "Young's modulus and Poisson's ratio");
    model.component("comp1").material("mat2").label("Acrylic plastic");
    model.component("comp1").material("mat2").set("family", "custom");
    model.component("comp1").material("mat2")
         .set("customspecular", new double[]{0.9803921568627451, 0.9803921568627451, 0.9803921568627451});
    model.component("comp1").material("mat2").set("diffuse", "custom");
    model.component("comp1").material("mat2")
         .set("customdiffuse", new double[]{0.39215686274509803, 0.7843137254901961, 0.39215686274509803});
    model.component("comp1").material("mat2").set("ambient", "custom");
    model.component("comp1").material("mat2")
         .set("customambient", new double[]{0.39215686274509803, 0.7843137254901961, 0.39215686274509803});
    model.component("comp1").material("mat2").set("noise", true);
    model.component("comp1").material("mat2").set("lighting", "phong");
    model.component("comp1").material("mat2").set("shininess", 1000);
    model.component("comp1").material("mat2").propertyGroup("def")
         .set("thermalexpansioncoefficient", new String[]{"7.0e-5[1/K]", "0", "0", "0", "7.0e-5[1/K]", "0", "0", "0", "7.0e-5[1/K]"});
    model.component("comp1").material("mat2").propertyGroup("def").set("heatcapacity", "1470[J/(kg*K)]");
    model.component("comp1").material("mat2").propertyGroup("def").set("density", "1190[kg/m^3]");
    model.component("comp1").material("mat2").propertyGroup("def")
         .set("thermalconductivity", new String[]{"0.18[W/(m*K)]", "0", "0", "0", "0.18[W/(m*K)]", "0", "0", "0", "0.18[W/(m*K)]"});
    model.component("comp1").material("mat2").propertyGroup("Enu").set("E", "3.2[GPa]");
    model.component("comp1").material("mat2").propertyGroup("Enu").set("nu", "0.35");

//    In the tree, select Built-in > Steel AISI 4340.
//    Right-click and choose Add to Component 1 (comp1).

    model.component("comp1").material().create("mat3", "Common");
    model.component("comp1").material("mat3").propertyGroup()
         .create("Enu", "Enu", "Young's modulus and Poisson's ratio");
    model.component("comp1").material("mat3").label("Steel AISI 4340");
    model.component("comp1").material("mat3").set("family", "steel");
    model.component("comp1").material("mat3").propertyGroup("def")
         .set("relpermeability", new String[]{"1", "0", "0", "0", "1", "0", "0", "0", "1"});
    model.component("comp1").material("mat3").propertyGroup("def")
         .set("electricconductivity", new String[]{"4.032e6[S/m]", "0", "0", "0", "4.032e6[S/m]", "0", "0", "0", "4.032e6[S/m]"});
    model.component("comp1").material("mat3").propertyGroup("def")
         .set("thermalexpansioncoefficient", new String[]{"12.3e-6[1/K]", "0", "0", "0", "12.3e-6[1/K]", "0", "0", "0", "12.3e-6[1/K]"});
    model.component("comp1").material("mat3").propertyGroup("def").set("heatcapacity", "475[J/(kg*K)]");
    model.component("comp1").material("mat3").propertyGroup("def")
         .set("relpermittivity", new String[]{"1", "0", "0", "0", "1", "0", "0", "0", "1"});
    model.component("comp1").material("mat3").propertyGroup("def").set("density", "7850[kg/m^3]");
    model.component("comp1").material("mat3").propertyGroup("def")
         .set("thermalconductivity", new String[]{"44.5[W/(m*K)]", "0", "0", "0", "44.5[W/(m*K)]", "0", "0", "0", "44.5[W/(m*K)]"});
    model.component("comp1").material("mat3").propertyGroup("Enu").set("E", "205[GPa]");
    model.component("comp1").material("mat3").propertyGroup("Enu").set("nu", "0.28");

//    In the Home toolbar, click Add Material to close the Add Material window.
//    In the Settings window for Material, locate the Geometric Entity Selection section.
//    From the Selection list, select Air Compartment.

    model.component("comp1").material("mat1").selection().named("geom1_comsel1");

//    In the Model Builder window, click Acrylic plastic (mat2).
//    In the Settings window for Material, locate the Geometric Entity Selection section.
//    From the Selection list, select Holders (Part 3 - Holders 1).

    model.component("comp1").material("mat2").selection().named("geom1_pi3_csel1_dom");

//    In the Model Builder window, click Steel AISI 4340 (mat3).
//    In the Settings window for Material, locate the Geometric Entity Selection section.
//    From the Selection list, select All Conductors (Part 2 - Conductors 1).

    model.component("comp1").material("mat3").selection().named("geom1_pi2_boxsel1");

//    The battery pack interface is active on the battery and conductor domains only.
//    In the Model Builder window, under Component 1 (comp1), click Battery Pack (bp).
//    In the Settings window for Battery Pack, locate the Domain Selection section.
//    From the Selection list, select Batteries and Conductors.

    model.component("comp1").physics("bp").selection().named("geom1_unisel1");

//    In the Model Builder window, under Component 1 (comp1) > Battery Pack (bp), click Batteries.
//    In the Settings window for Batteries, locate the Domain Selection section.
//    From the Selection list, select Batteries.

    model.component("comp1").physics("bp").feature("batt").selection().named("geom1_csel1_dom");

//    Locate the Initial Capacity section.
//    In the \[Q_\textrm{cell,0}\] text field, type Q_cell.

    model.component("comp1").physics("bp").feature("batt").set("Q_cell0", "Q_cell");

//    Locate the Initial Cell Charge Distribution section.
//    In the \[\textrm{SOC}_\textrm{cell,0}\] text field, type SOC_0.

    model.component("comp1").physics("bp").feature("batt").set("SOC_pack0", "SOC_0");

//    In the Model Builder window, click Cell Equilibrium Potential 1.
//    In the Settings window for Cell Equilibrium Potential, locate the Open Circuit Voltage section.
//    Click Clear Table.

    model.component("comp1").physics("bp").feature("batt").feature("cep1").set("SOC_Eocv", new int[]{});
    model.component("comp1").physics("bp").feature("batt").feature("cep1").set("Eocv", new int[]{});

//    Click Load from File.
//    Browse to the model's Application Library folder and double-click the file thermal_runaway_propagation_E_OCP_data.txt.

    model.component("comp1").physics("bp").feature("batt").feature("cep1")
         .set("SOC_Eocv", new String[]{"0.000", "0.010", "0.020", "0.030", "0.040", "0.050", "0.060", "0.070", "0.080", "0.090", 
         "0.100", "0.110", "0.120", "0.130", "0.140", "0.150", "0.160", "0.170", "0.180", "0.190", 
         "0.200", "0.210", "0.220", "0.230", "0.240", "0.250", "0.260", "0.270", "0.280", "0.290", 
         "0.300", "0.310", "0.320", "0.330", "0.340", "0.350", "0.360", "0.370", "0.380", "0.390", 
         "0.400", "0.410", "0.420", "0.430", "0.440", "0.450", "0.460", "0.470", "0.480", "0.490", 
         "0.500", "0.510", "0.520", "0.530", "0.540", "0.550", "0.560", "0.570", "0.580", "0.590", 
         "0.600", "0.610", "0.620", "0.630", "0.640", "0.650", "0.660", "0.670", "0.680", "0.690", 
         "0.700", "0.710", "0.720", "0.730", "0.740", "0.750", "0.760", "0.770", "0.780", "0.790", 
         "0.800", "0.810", "0.820", "0.830", "0.840", "0.850", "0.860", "0.870", "0.880", "0.890", 
         "0.900", "0.910", "0.920", "0.930", "0.940", "0.950", "0.960", "0.970", "0.980", "0.990", 
         "1.000"});
    model.component("comp1").physics("bp").feature("batt").feature("cep1")
         .set("Eocv", new String[]{"1.310", "2.261", "2.833", "3.184", "3.393", "3.511", "3.587", "3.626", "3.656", "3.685", 
         "3.699", "3.711", "3.723", "3.735", "3.747", "3.759", "3.767", "3.775", "3.783", "3.791", 
         "3.800", "3.808", "3.816", "3.824", "3.832", "3.840", "3.845", "3.850", "3.854", "3.859", 
         "3.864", "3.868", "3.873", "3.878", "3.882", "3.887", "3.891", "3.896", "3.900", "3.905", 
         "3.910", "3.916", "3.921", "3.928", "3.934", "3.941", "3.947", "3.953", "3.959", "3.965", 
         "3.970", "3.975", "3.979", "3.983", "3.986", "3.989", "3.992", "3.995", "3.997", "4.000", 
         "4.002", "4.004", "4.007", "4.009", "4.011", "4.014", "4.017", "4.020", "4.023", "4.026", 
         "4.029", "4.032", "4.035", "4.035", "4.036", "4.037", "4.037", "4.038", "4.039", "4.039", 
         "4.040", "4.041", "4.041", "4.042", "4.042", "4.043", "4.043", "4.045", "4.049", "4.052", 
         "4.055", "4.058", "4.061", "4.064", "4.069", "4.079", "4.092", "4.111", "4.134", "4.167", 
         "4.204"});

//    In this tutorial we will keep the default value of 0 for the temperature derivative of the open circuit voltage for all SOC values. The reason is that during the thermal runaway, very high temperatures are expected, which in turn would result in inaccurate cell open circuit voltage values for nonzero values of the derivative.
//    In the Model Builder window, click Voltage Losses 1.
//    In the Settings window for Voltage Losses, locate the Ohmic Overpotential section.
//    In the \[\eta_\textrm{IR,1C}\] text field, type eta_1C.

    model.component("comp1").physics("bp").feature("batt").feature("vl1").set("eta_ir1C", "eta_1C");

//    Locate the Activation Overpotential section.
//    In the \[J_0\] text field, type J0.

    model.component("comp1").physics("bp").feature("batt").feature("vl1").set("J0", "J0");

//    Locate the Concentration Overpotential section.
//    Select the Include concentration overpotential checkbox.

    model.component("comp1").physics("bp").feature("batt").feature("vl1")
         .set("IncludeConcentrationOverpotential", true);

//    In the \[\tau\] text field, type tau.

    model.component("comp1").physics("bp").feature("batt").feature("vl1").set("tau", "tau");

//    This model will make use of two thermal events. The first event triggers a heat source in a malfunctioning cell at an explicit time.
//    In the Model Builder window, click Batteries.
//    In the Physics toolbar, click Attributes and choose Thermal Event.

    model.component("comp1").physics("bp").feature("batt").create("te1", "ThermalEvent", 3);

//    In the Settings window for Thermal Event, locate the Domain Selection section.
//    Click Clear Selection.

    model.component("comp1").physics("bp").feature("batt").feature("te1").selection().set();

//    Select Domains 24, 25, 26.

    model.component("comp1").physics("bp").feature("batt").feature("te1").selection().set(24, 25, 26);

//    Locate the Thermal Event section.
//    From the Event condition list, select Explicit time.

    model.component("comp1").physics("bp").feature("batt").feature("te1").set("EventConditionType", "ExplicitTime");

//    In the \[t_\textrm{exp}\] text field, type t_start.

    model.component("comp1").physics("bp").feature("batt").feature("te1").set("t_exp", "t_start");

//    In the table, enter the following settings:

    model.component("comp1").physics("bp").feature("batt").feature("te1").setIndex("t_te_tab", "t_peak", 1, 0);
    model.component("comp1").physics("bp").feature("batt").feature("te1").setIndex("Qh_te_tab", "Qh_peak", 1, 0);

//    Click Add.

    model.component("comp1").physics("bp").feature("batt").feature("te1").setIndex("t_te_tab", 0, 2, 0);
    model.component("comp1").physics("bp").feature("batt").feature("te1").setIndex("Qh_te_tab", 0, 2, 0);
    model.component("comp1").physics("bp").feature("batt").feature("te1").setIndex("Qh_te_tab", 0, 2, 0);
    model.component("comp1").physics("bp").feature("batt").feature("te1").setIndex("t_te_tab", 0, 2, 0);
    model.component("comp1").physics("bp").feature("batt").feature("te1").setIndex("Qh_te_tab", 0, 2, 0);

//    In the table, enter the following settings:

    model.component("comp1").physics("bp").feature("batt").feature("te1").setIndex("t_te_tab", "t_tr", 2, 0);

//    Select the Add ohmic overpotential after event checkbox.

    model.component("comp1").physics("bp").feature("batt").feature("te1")
         .set("AddOhmicOverPotentialAfterEvent", true);

//    Locate the Domain Selection section.
//    Click Create Selection.
//    Create a named selection of the malfunctioning cell. This will make it easy to select the complementary (nonmalfunctioning) battery cells.
//    In the Create Selection dialog, type Malfunctioning Cell in the Selection name text field.
//    Click OK.

    model.component("comp1").selection().create("sel1", "Explicit");
    model.component("comp1").selection("sel1").geom(3);
    model.component("comp1").selection("sel1").label("Malfunctioning Cell");
    model.component("comp1").selection("sel1").set(24, 25, 26);

    model.component("comp1").physics("bp").feature("batt").feature("te1").selection().named("sel1");

//    In the Model Builder window, expand the Component 1 (comp1) > Definitions node.
//    In the Model Builder window, expand the Component 1 (comp1) > Definitions > Selections node.
//    Right-click Component 1 (comp1) > Definitions and choose Selections > Difference.

    model.component("comp1").selection().create("dif1", "Difference");

//    In the Settings window for Difference, type Nonmalfunctioning Cells in the Label text field.

    model.component("comp1").selection("dif1").label("Nonmalfunctioning Cells");

//    Locate the Input Entities section.
//    Under Selections to add, click Add.
//    In the Add dialog, select Batteries in the Selections to add list.
//    Click OK.

    model.component("comp1").selection("dif1").set("add", new String[]{"geom1_csel1_dom"});

//    In the Settings window for Difference, locate the Input Entities section.
//    Under Selections to subtract, click Add.
//    In the Add dialog, select Malfunctioning Cell in the Selections to subtract list.
//    Click OK.

    model.component("comp1").selection("dif1").set("subtract", new String[]{"sel1"});

//    Now duplicate the first thermal event to create a second one for the complementary cells that is to be triggered if the maximum temperature exceeds a certain trigger level.
//    In the Model Builder window, right-click Component 1 (comp1) > Battery Pack (bp) > Batteries > Thermal Event 1 and choose Duplicate.

    model.component("comp1").physics("bp").feature("batt").feature().duplicate("te2", "te1");

//    In the Settings window for Thermal Event, locate the Domain Selection section.
//    From the Selection list, select Nonmalfunctioning Cells.

    model.component("comp1").physics("bp").feature("batt").feature("te2").selection().named("dif1");

//    Locate the Thermal Event section.
//    From the Event condition list, select Maximum temperature.

    model.component("comp1").physics("bp").feature("batt").feature("te2").set("EventConditionType", "maxT");

//    In the \[T_\textrm{max,te}\] text field, type T_trigger.

    model.component("comp1").physics("bp").feature("batt").feature("te2").set("maxT_te", "T_trigger");

//    Ground the negative terminals of the pack as follows:
//    In the Model Builder window, under Component 1 (comp1) > Battery Pack (bp), click Current Conductors.
//    In the Settings window for Current Conductors, locate the Domain Selection section.
//    From the Selection list, select All Conductors (Part 2 - Conductors 1).

    model.component("comp1").physics("bp").feature("ccnd").selection().named("geom1_pi2_boxsel1");

//    In the Physics toolbar, click Attributes and choose Ground.

    model.component("comp1").physics("bp").feature("ccnd").create("egnd1", "ElectricGround", 2);

//    In the Settings window for Ground, locate the Boundary Selection section.
//    From the Selection list, select Conductor Boundaries, Negative Terminals (Part 2 - Conductors 1).

    model.component("comp1").physics("bp").feature("ccnd").feature("egnd1").selection().named("geom1_pi2_boxsel4");

//    Use a charge-discharge cycling condition on the positive terminals of the pack. This will turn off the charging current when a specified voltage maximum level is reached.
//    In the Model Builder window, click Current Conductors.
//    In the Physics toolbar, click Attributes and choose Charge-Discharge Cycling.

    return model;
  }

  public static Model run2(Model model) {

    model.component("comp1").physics("bp").feature("ccnd").create("cdc1", "ChargeDischargeCycling", 2);

//    In the Settings window for Charge-Discharge Cycling, locate the Boundary Selection section.
//    From the Selection list, select Conductor Boundaries, Positive Terminals (Part 2 - Conductors 1).

    model.component("comp1").physics("bp").feature("ccnd").feature("cdc1").selection().named("geom1_pi2_boxsel5");

//    Locate the Charge Settings section.
//    In the \[I_{\textrm{ch}}\] text field, type C_rate*I_1C_pack.

    model.component("comp1").physics("bp").feature("ccnd").feature("cdc1").set("Ich", "C_rate*I_1C_pack");

//    In the \[V_{\textrm{max}}\] text field, type E_max_pack.

    model.component("comp1").physics("bp").feature("ccnd").feature("cdc1").set("Vmax", "E_max_pack");

//    Select the Include rest period checkbox.

    model.component("comp1").physics("bp").feature("ccnd").feature("cdc1").set("item.OCCH", true);

//    In the \[t_{\textrm{rest,ch}}\] text field, type 1[h].

    model.component("comp1").physics("bp").feature("ccnd").feature("cdc1").set("trech", "1[h]");

//    Locate the Start Mode section.
//    From the Start with list, select Charge first.

    model.component("comp1").physics("bp").feature("ccnd").feature("cdc1").set("StartWith", "Charge_first");

//    Finalize the pack part of the model by specifying how the batteries are connected to the conductor domains.
//    In the Model Builder window, under Component 1 (comp1) > Battery Pack (bp), click Negative Connectors.
//    In the Settings window for Negative Connectors, locate the Boundary Selection section.
//    From the Selection list, select Negative Connectors.

    model.component("comp1").physics("bp").feature("nc").selection().named("geom1_unisel2");

//    In the Model Builder window, click Positive Connectors.
//    In the Settings window for Positive Connectors, locate the Boundary Selection section.
//    From the Selection list, select Positive Connectors.

    model.component("comp1").physics("bp").feature("pc").selection().named("geom1_unisel3");

//    Now setup the heat transfer part of the model. Start with specifying the properties of the layers (jelly roll) of the active battery materials.
//    In the Model Builder window, under Component 1 (comp1), click Heat Transfer in Solids (ht).
//    In the Physics toolbar, click Domains and choose Battery Layers.

    model.component("comp1").physics("ht").create("bl1", "BatteryLayers", 3);

//    In the Settings window for Battery Layers, locate the Domain Selection section.
//    From the Selection list, select Batteries.

    model.component("comp1").physics("ht").feature("bl1").selection().named("geom1_csel1_dom");

//    Locate the Battery Layers section.
//    From the Layer configuration list, select Spirally wound (cylindrical).

    model.component("comp1").physics("ht").feature("bl1").set("LayerConfiguration", "SpirallyWound");

//    In the \[k_\textrm{tl}\] text field, type kT_batt_tl.

    model.component("comp1").physics("ht").feature("bl1").set("ThroughLayerConductivity", "kT_batt_tl");

//    In the \[k_\textrm{il}\] text field, type kT_batt_il.

    model.component("comp1").physics("ht").feature("bl1").set("InLayerConductivity", "kT_batt_il");

//    In the \[\rho_\textrm{eff}\] text field, type rho_batt.

    model.component("comp1").physics("ht").feature("bl1").set("Density", "rho_batt");

//    In the \[C_{p,\textrm{eff}}\] text field, type Cp_batt.

    model.component("comp1").physics("ht").feature("bl1").set("HeatCapacity", "Cp_batt");

//    In the Model Builder window, click Initial Values 1.
//    In the Settings window for Initial Values, locate the Initial Values section.
//    In the \[T\] text field, type T_ext.

    model.component("comp1").physics("ht").feature("init1").set("Tinit", "T_ext");

//    In the Physics toolbar, click Boundaries and choose Heat Flux.

    model.component("comp1").physics("ht").create("hf1", "HeatFluxBoundary", 2);

//    In the Settings window for Heat Flux, locate the Boundary Selection section.
//    From the Selection list, select All boundaries.

    model.component("comp1").physics("ht").feature("hf1").selection().all();

//    Locate the Heat Flux section.
//    From the Flux type list, select Convective heat flux.

    model.component("comp1").physics("ht").feature("hf1").set("HeatFluxType", "ConvectiveHeatFlux");

//    In the \[h\] text field, type h_conv.

    model.component("comp1").physics("ht").feature("hf1").set("h", "h_conv");

//    In the \[T_{\textrm{ext}}\] text field, type T_ext.

    model.component("comp1").physics("ht").feature("hf1").set("Text", "T_ext");

//    In the Physics toolbar, click Multiphysics Couplings and choose Domain > Electrochemical Heating.

    model.component("comp1").multiphysics().create("ech1", "ElectrochemicalHeating", 3);

//    For this model we will create a swept mesh in the longitudinal axis direction of the battery cylinders.
//    In the Mesh toolbar, click More Attributes and choose Identical Mesh.

    model.component("comp1").mesh("mesh1").create("id1", "IdenticalMesh");

//    In the Settings window for Identical Mesh, locate the First Entity Group section.
//    From the Selection list, select Identical Mesh Boundaries, Group 1.

    model.component("comp1").mesh("mesh1").feature("id1").selection("group1").named("geom1_boxsel2");

//    Locate the Second Entity Group section.
//    From the Selection list, select Identical Mesh Boundaries, Group 2.

    model.component("comp1").mesh("mesh1").feature("id1").selection("group2").named("geom1_boxsel3");

//    In the Mesh toolbar, click More Generators and choose Free Triangular.

    model.component("comp1").mesh("mesh1").create("ftri1", "FreeTri");

//    In the Settings window for Free Triangular, locate the Boundary Selection section.
//    From the Selection list, select Identical Mesh Boundaries, Group 1.

    model.component("comp1").mesh("mesh1").feature("ftri1").selection().named("geom1_boxsel2");

//    Right-click Free Triangular 1 and choose Size.

    model.component("comp1").mesh("mesh1").feature("ftri1").create("size1", "Size");

//    In the Settings window for Size, locate the Element Size section.
//    Click the Custom button.

    model.component("comp1").mesh("mesh1").feature("ftri1").feature("size1").set("custom", true);

//    Locate the Element Size Parameters section.
//    Select the Minimum element size checkbox.

    model.component("comp1").mesh("mesh1").feature("ftri1").feature("size1").set("hminactive", true);

//    In the associated text field, type gap/2.

    model.component("comp1").mesh("mesh1").feature("ftri1").feature("size1").set("hmin", "gap/2");

//    Select the Resolution of narrow regions checkbox.

    model.component("comp1").mesh("mesh1").feature("ftri1").feature("size1").set("hnarrowactive", true);

//    In the associated text field, type 1.5.

    model.component("comp1").mesh("mesh1").feature("ftri1").feature("size1").set("hnarrow", 1.5);

//    In the Model Builder window, under Component 1 (comp1) > Mesh 1, click Size.
//    In the Settings window for Size, locate the Element Size section.
//    From the Predefined list, select Coarse.

    model.component("comp1").mesh("mesh1").feature("size").set("hauto", 6);

//    Click Build All.

    model.component("comp1").mesh("mesh1").run();

//    In the Mesh toolbar, click Swept.

    model.component("comp1").mesh("mesh1").create("swe1", "Sweep");

//    In the Settings window for Swept, locate the Domain Selection section.
//    From the Geometric entity level list, select Domain.

    model.component("comp1").mesh("mesh1").feature("swe1").selection().geom("geom1", 3);

//    From the Selection list, select Mesh Sweep Domains.

    model.component("comp1").mesh("mesh1").feature("swe1").selection().named("geom1_boxsel1");

//    Click Build Selected.

    model.component("comp1").mesh("mesh1").run("swe1");

//    In the Mesh toolbar, click Free Tetrahedral.

    model.component("comp1").mesh("mesh1").create("ftet1", "FreeTet");

//    In the Settings window for Free Tetrahedral, click Build All.

    model.component("comp1").mesh("mesh1").run();

//    Add probes for the pack voltage and the maximum and average battery temperatures before solving. The probes will output their corresponding values to a table for each step taken by the time-dependent solver.
//    In the Definitions toolbar, click Probes and choose Global Variable Probe.

    model.component("comp1").probe().create("var1", "GlobalVariable");

//    In the Settings window for Global Variable Probe, click Replace Expression in the upper-right corner of the Expression section.
//    From the menu, choose Component 1 (comp1) > Battery Pack > Charge-Discharge Cycling 1 > bp.ccnd.cdc1.phis0 - Cell potential - V.

    model.component("comp1").probe("var1").set("expr", "bp.ccnd.cdc1.phis0");
    model.component("comp1").probe("var1").set("descr", "Cell potential");

//    Locate the Expression section.
//    Select the Description checkbox.

    model.component("comp1").probe("var1").set("descractive", true);

//    In the associated text field, type Pack voltage.

    model.component("comp1").probe("var1").set("descr", "Pack voltage");

//    Click to expand the Table and Window Settings section.
//    Click Add Table.

    model.result().table().create("tbl1", "Table");

    model.component("comp1").probe("var1").set("table", "tbl1");

//    Click Add Plot Window.

    model.component("comp1").probe("var1").set("window", "window1");
    model.component("comp1").probe("var1").set("windowtitle", "Probe Plot 1");

//    In the Definitions toolbar, click Probes and choose Domain Probe.

    model.component("comp1").probe().create("dom1", "Domain");
    model.component("comp1").probe("dom1").set("intsurface", true);
    model.component("comp1").probe("dom1").set("intvolume", true);

//    In the Settings window for Domain Probe, locate the Probe Type section.
//    From the Type list, select Maximum.

    model.component("comp1").probe("dom1").set("type", "maximum");

//    Locate the Source Selection section.
//    From the Selection list, select Batteries.

    model.component("comp1").probe("dom1").selection().named("geom1_csel1_dom");

//    Click Replace Expression in the upper-right corner of the Expression section.
//    From the menu, choose Component 1 (comp1) > Heat Transfer in Solids > Temperature > T - Temperature - K.

    model.component("comp1").probe("dom1").set("expr", "T");
    model.component("comp1").probe("dom1").set("descr", "Temperature");

//    Locate the Expression section.
//    In the Table and plot unit field, type degC.

    model.component("comp1").probe("dom1").set("unit", "degC");

//    Select the Description checkbox.

    model.component("comp1").probe("dom1").set("descractive", true);

//    In the associated text field, type Maximum temperature in batteries.

    model.component("comp1").probe("dom1").set("descr", "Maximum temperature in batteries");

//    Click to expand the Table and Window Settings section.
//    Click Add Table.

    model.result().table().create("tbl2", "Table");

    model.component("comp1").probe("dom1").set("table", "tbl2");

//    From the Plot window list, select Probe Plot 1.

    model.component("comp1").probe("dom1").set("window", "window1");

//    In the Model Builder window, right-click Domain Probe 1 (dom1) and choose Duplicate.

    model.component("comp1").probe().duplicate("dom2", "dom1");

//    In the Settings window for Domain Probe, locate the Probe Type section.
//    From the Type list, select Average.

    model.component("comp1").probe("dom2").set("type", "average");

//    Locate the Expression section.
//    In the Description text field, type Average temperature in batteries.

    model.component("comp1").probe("dom2").set("descr", "Average temperature in batteries");

//    In the Model Builder window, under Study 1, click Step 1: Time Dependent.
//    In the Settings window for Time Dependent, locate the Study Settings section.
//    From the Time unit list, select min.

    model.study("std1").feature("time").set("tunit", "min");

//    In the Output times text field, type range(0,5,20).

    model.study("std1").feature("time").set("tlist", "range(0,5,20)");

//    In order to improve the accuracy of the solution, set the initial step of the time-dependent solver to 0.1 s. This will ensure that the heat released by each thermal event is properly resolved in the time domain.
//    In the Study toolbar, click Show Default Solver.

    model.study("std1").showAutoSequences("all");

//    In the Model Builder window, expand the Solution 1 (sol1) node, then click Time-Dependent Solver 1.
//    In the Settings window for Time-Dependent Solver, click to expand the Time Stepping section.
//    In the Initial step text field, type 0.1[s].

    model.sol("sol1").feature("t1").set("initialstepbdf", "0.1[s]");

//    Click to expand the Output section.
//    Also disable storing of the time-derivatives. This will avoid numerical artifacts when interpolating between solutions at different times when creating an animation of the runaway propagation. It will also reduce the required disk space for storing the model.
//    Clear the Store the first time derivative checkbox.

    model.sol("sol1").feature("t1").set("storeudot", false);

//    In the Study toolbar, click Compute.

    model.study("std1").createAutoSequences("all");

    model.component("comp1").probe("var1").genResult("none");
    model.component("comp1").probe("dom1").genResult("none");
    model.component("comp1").probe("dom2").genResult("none");

    model.sol("sol1").runAll();

    model.result().create("pg2", "PlotGroup1D");
    model.result("pg2").set("data", "dset1");
    model.result("pg2").create("glob1", "Global");
    model.result("pg2").feature("glob1").set("unit", new String[]{"", "", ""});
    model.result("pg2").feature("glob1")
         .set("expr", new String[]{"bp.E_cell_max", "bp.E_cell_avg", "bp.E_cell_min"});
    model.result("pg2").feature("glob1").set("descr", new String[]{"Cell voltage", "Cell voltage", "Cell voltage"});
    model.result("pg2").label("Cell Voltage (bp)");
    model.result("pg2").feature("glob1").set("legendmethod", "manual");
    model.result("pg2").feature("glob1").setIndex("legends", "E<sub>max</sub>", 0);
    model.result("pg2").feature("glob1").setIndex("legends", "E<sub>avg</sub>", 1);
    model.result("pg2").feature("glob1").setIndex("legends", "E<sub>min</sub>", 2);
    model.result("pg2").create("glob2", "Global");
    model.result("pg2").feature("glob2").set("unit", new String[]{"", "", ""});
    model.result("pg2").feature("glob2").set("expr", new String[]{"bp.I_app_max", "bp.I_app_avg", "bp.I_app_min"});
    model.result("pg2").feature("glob2")
         .set("descr", new String[]{"Applied cell current", "Applied cell current", "Applied cell current"});
    model.result("pg2").feature("glob2").set("linestyle", "dashed");
    model.result("pg2").feature("glob2").set("linecolor", "cyclereset");
    model.result("pg2").feature("glob2").set("legendmethod", "manual");
    model.result("pg2").feature("glob2").setIndex("legends", "I<sub>max</sub>", 0);
    model.result("pg2").feature("glob2").setIndex("legends", "I<sub>avg</sub>", 1);
    model.result("pg2").feature("glob2").setIndex("legends", "I<sub>min</sub>", 2);
    model.result("pg2").set("twoyaxes", true);
    model.result("pg2").setIndex("plotonsecyaxis", true, 1, 1);
    model.result("pg2").set("titletype", "none");
    model.result().create("pg3", "PlotGroup1D");
    model.result("pg3").set("data", "dset1");
    model.result("pg3").create("glob1", "Global");
    model.result("pg3").feature("glob1").set("unit", new String[]{"", "", ""});
    model.result("pg3").feature("glob1").set("expr", new String[]{"bp.SOC_max", "bp.SOC_avg", "bp.SOC_min"});
    model.result("pg3").feature("glob1")
         .set("descr", new String[]{"State of charge", "State of charge", "State of charge"});
    model.result("pg3").label("State of Charge (bp)");
    model.result("pg3").feature("glob1").set("legendmethod", "manual");
    model.result("pg3").feature("glob1").setIndex("legends", "SOC<sub>max</sub>", 0);
    model.result("pg3").feature("glob1").setIndex("legends", "SOC<sub>avg</sub>", 1);
    model.result("pg3").feature("glob1").setIndex("legends", "SOC<sub>min</sub>", 2);
    model.result("pg3").create("glob2", "Global");
    model.result("pg3").feature("glob2").set("unit", new String[]{"", "", ""});
    model.result("pg3").feature("glob2").set("expr", new String[]{"bp.I_app_max", "bp.I_app_avg", "bp.I_app_min"});
    model.result("pg3").feature("glob2")
         .set("descr", new String[]{"Applied cell current", "Applied cell current", "Applied cell current"});
    model.result("pg3").feature("glob2").set("linestyle", "dashed");
    model.result("pg3").feature("glob2").set("linecolor", "cyclereset");
    model.result("pg3").feature("glob2").set("legendmethod", "manual");
    model.result("pg3").feature("glob2").setIndex("legends", "I<sub>max</sub>", 0);
    model.result("pg3").feature("glob2").setIndex("legends", "I<sub>avg</sub>", 1);
    model.result("pg3").feature("glob2").setIndex("legends", "I<sub>min</sub>", 2);
    model.result("pg3").set("twoyaxes", true);
    model.result("pg3").setIndex("plotonsecyaxis", true, 1, 1);
    model.result("pg3").set("titletype", "none");
    model.result().create("pg4", "PlotGroup3D");
    model.result("pg4").set("data", "dset1");
    model.result("pg4").label("Electric Potential (bp)");
    model.result("pg4").create("surf1", "Surface");
    model.result("pg4").feature("surf1").set("expr", new String[]{"phis"});
    model.result().create("pg5", "PlotGroup3D");
    model.result("pg5").label("Temperature (ht)");
    model.result("pg5").set("smooth", "internal");
    model.result("pg5").feature().create("vol1", "Volume");
    model.result("pg5").feature("vol1").set("solutionparams", "parent");
    model.result("pg5").feature("vol1").set("expr", "T");
    model.result("pg5").feature("vol1").set("colortable", "HeatCameraLight");
    model.result("pg5").feature("vol1").set("smooth", "internal");
    model.result("pg5").feature("vol1").set("data", "parent");
    model.result("pg2").run();
    model.result("pg5").run();

//    Modify the default temperature plot as follows:
//    In the Model Builder window, under Results, click Temperature (ht).
//    In the Settings window for 3D Plot Group, locate the Plot Settings section.
//    Clear the Plot dataset edges checkbox.

    model.result("pg5").set("edges", false);
    model.result("pg5").run();

//    In the Model Builder window, expand the Temperature (ht) node.
//    Right-click Volume 1 and choose Delete.

    model.result("pg5").feature().remove("vol1");
    model.result("pg5").run();

//    In the Settings window for 3D Plot Group, click to expand the Selection section.
//    From the Geometric entity level list, select Boundary.

    model.result("pg5").selection().geom("geom1", 2);

//    From the Selection list, select Non-Air External Boundaries.

    model.result("pg5").selection().named("geom1_adjsel1");

//    Right-click Temperature (ht) and choose Surface.

    model.result("pg5").create("surf1", "Surface");
    model.result("pg5").feature("surf1").set("evaluationsettings", "parent");

//    In the Settings window for Surface, locate the Expression section.
//    In the Expression text field, type T.

    model.result("pg5").feature("surf1").set("expr", "T");

//    In the Unit field, type degC.

    model.result("pg5").feature("surf1").set("unit", "degC");

//    Locate the Coloring and Style section.
//    From the Color table list, select HeatCameraLight.

    model.result("pg5").feature("surf1").set("colortable", "HeatCameraLight");

//    In the Temperature (ht) toolbar, click Plot.

    model.result("pg5").run();
    model.result("pg5").run();

//    In the Model Builder window, click Temperature (ht).
//    In the Settings window for 3D Plot Group, click to expand the Title section.
//    From the Title type list, select Manual.

    model.result("pg5").set("titletype", "manual");

//    In the Parameter indicator text field, type Time=eval(round(t)) s.

    model.result("pg5").set("paramindicator", "Time=eval(round(t)) s");

//    Click the Transparency button in the Graphics toolbar.

    model.component("comp1").view("view1").set("transparency", false);

//    In the Temperature (ht) toolbar, click Plot.

    model.result("pg5").run();

//    You may now change the time in the <l>Data</l> section to plot the temperature at various times. By default the solver is set to output the solution before and after triggering of an event hence the dual entries for some of the times in the list.
//    Locate the Data section.
//    From the Time (min) list, select 7.6399.

    model.result("pg5").set("looplevel", new int[]{6});

//    In the Temperature (ht) toolbar, click Plot.

    model.result("pg5").run();
    model.result("pg5").set("looplevel", new int[]{8});
    model.result("pg5").run();
    model.result("pg5").set("looplevel", new int[]{12});
    model.result("pg5").run();
    model.result("pg5").set("looplevel", new int[]{16});
    model.result("pg5").run();
    model.result("pg5").set("looplevel", new int[]{20});
    model.result("pg5").run();
    model.result("pg5").set("looplevel", new int[]{24});
    model.result("pg5").run();
    model.result("pg1").set("window", "window1");
    model.result("pg1").run();

//    Polish the default-generated probe plot as follows:
//    In the Model Builder window, under Results, click Probe Plot Group 1.
//    In the Settings window for 1D Plot Group, type Pack Voltage and Max Temperature Probes in the Label text field.

    model.result("pg1").label("Pack Voltage and Max Temperature Probes");

//    Locate the Plot Settings section.
//    Select the Two y-axes checkbox.

    model.result("pg1").set("twoyaxes", true);

//    In the table, enter the following settings:

    model.result("pg1").setIndex("plotonsecyaxis", true, 1, 1);

//    Select the Secondary y-axis label checkbox.

    model.result("pg1").set("yseclabelactive", true);

//    In the associated text field, type Temperature in batteries (degC).

    model.result("pg1").set("yseclabel", "Temperature in batteries (degC)");

//    Locate the Legend section.
//    From the Position list, select Middle right.

    model.result("pg1").set("legendpos", "middleright");
    model.result("pg1").set("window", "window1");
    model.result("pg1").run();

//    In the Model Builder window, expand the Pack Voltage and Max Temperature Probes node, then click Probe Table Graph 1.
//    In the Settings window for Table Graph, click to expand the Legends section.
//    From the Legends list, select Manual.

    model.result("pg1").feature("tblp1").set("legendmethod", "manual");

//    In the table, enter the following settings:

    model.result("pg1").feature("tblp1").setIndex("legends", "E<sub>pack</sub>", 0);
    model.result("pg1").set("window", "window1");
    model.result("pg1").run();

//    In the Model Builder window, click Probe Table Graph 2.
//    In the Settings window for Table Graph, locate the Legends section.
//    From the Legends list, select Manual.

    model.result("pg1").feature("tblp2").set("legendmethod", "manual");

//    In the table, enter the following settings:

    model.result("pg1").feature("tblp2").setIndex("legends", "T<sub>max</sub>", 0);
    model.result("pg1").feature("tblp2").setIndex("legends", "T<sub>avg</sub>", 1);

//    In the Pack Voltage and Max Temperature Probes toolbar, click Plot.

    model.result("pg1").set("window", "window1");
    model.result("pg1").run();

//    You may also create an animation of the temperature surface plot as follows:
//    In the Results toolbar, click Animation and choose Player.

    model.result().export().create("anim1", "Animation");
    model.result().export("anim1").set("target", "player");
    model.result().export("anim1").set("fontsize", "9");
    model.result().export("anim1").set("colortheme", "globaltheme");
    model.result().export("anim1").set("customcolor", new double[]{1, 1, 1});
    model.result().export("anim1").set("background", "color");
    model.result().export("anim1").set("gltfincludelines", "on");
    model.result().export("anim1").set("title1d", "on");
    model.result().export("anim1").set("legend1d", "on");
    model.result().export("anim1").set("logo1d", "on");
    model.result().export("anim1").set("options1d", "on");
    model.result().export("anim1").set("title2d", "on");
    model.result().export("anim1").set("legend2d", "on");
    model.result().export("anim1").set("logo2d", "on");
    model.result().export("anim1").set("options2d", "off");
    model.result().export("anim1").set("title3d", "on");
    model.result().export("anim1").set("legend3d", "on");
    model.result().export("anim1").set("logo3d", "on");
    model.result().export("anim1").set("options3d", "off");
    model.result().export("anim1").set("axisorientation", "on");
    model.result().export("anim1").set("grid", "on");
    model.result().export("anim1").set("axes1d", "on");
    model.result().export("anim1").set("axes2d", "on");
    model.result().export("anim1").set("showgrid", "on");

//    In the Settings window for Animation, locate the Scene section.
//    From the Subject list, select Temperature (ht).

    model.result().export("anim1").set("plotgroup", "pg5");

//    Locate the Animation Editing section.
//    From the Time selection list, select Interpolated.

    model.result().export("anim1").set("looplevelinput", "interp");

//    In the Times (min) text field, type range(0,0.25,20).

    model.result().export("anim1").set("interp", "range(0,0.25,20)");

//    Locate the Frames section.
//    From the Frame selection list, select All.

    model.result().export("anim1").set("framesel", "all");

//    Click the Play button in the Graphics toolbar.

    model.result().export("anim1").run();

    model.func().create("int1", "Interpolation");
    model.func("int1").set("funcname", "Q_tr");
    model.func("int1").setIndex("table", 0, 0, 0);
    model.func("int1").setIndex("table", 0, 0, 1);
    model.func("int1").setIndex("table", "t_peak", 1, 0);
    model.func("int1").setIndex("table", "Qh_peak/1000", 1, 1);
    model.func("int1").setIndex("table", "t_tr", 2, 0);
    model.func("int1").setIndex("table", 0, 2, 1);
    model.func("int1").setIndex("fununit", "kW", 0);
    model.func("int1").setIndex("argunit", "s", 0);
    model.func().remove("int1");

    model.title("Thermal Runaway Propagation in a Battery Pack");

    model
         .description("Due to abuse, such as internal or external short circuits or excessive heating, an individual battery cell may go into thermal runaway, during which the battery cell generates a significant amount of heat. If enough heat is transferred between adjacent cells during a thermal runaway event, neighboring cells will also go into thermal runaway.\n\nA thermal runaway propagating through the whole pack constitutes a severe safety hazard. When designing a battery pack, measures need to be taken in order to mitigate runaway propagation.\n\nThis tutorial simulates the heat transfer and resulting thermal runaway propagation in a pack consisting of 20\u00a0cylindrical cells using event-based heat sources.");

    return model;
  }

  public static void main(String[] args) {
    Model model = run();
    run2(model);
  }

}
