Usage

Getting Started

The most simple way of using the library is to interact with the Cell Simulation Interface, CSI object:

>>> from cideMOD import CSI, DEFAULTS
>>> csi = CSI('params.json', DEFAULTS.SIMULATION_OPTIONS.value,
              test_plan = DEFAULTS.TEST_PLAN.value)
>>> csi.run_test_plan()

Specify Model Options

The model options can be specified through the get_model_options method. For example:

>>> from cideMOD import CSI, DEFAULTS, get_model_options
>>> options = get_model_options(model='P2D', solve_thermal=False, SEI_model='solvent_diffusion')
>>> csi = CSI('params.json', options, test_plan=DEFAULTS.TEST_PLAN.value)
>>> csi.run_test_plan()

Cell Parameters

Cell properties and material parameters are specified in a single json file or optionally a Python dictionary can be used as well. Several examples of different cell datasets are given under the data folder. The json file must contain different mandatory objects:

  • Structure:

    The "structure" entry determines the configuration of the cell. It is a list containing the tags of the different subdomains in order. The easiest configuration would be ["a","s","c"] corresponding to a cell composed of an anode, separator and cathode. A cell composed of two units could have this other structure ["ncc","a","s","c","pcc","c","s","a","ncc"]. All the subdomains specified in the “structure” entry must have its own entry defined in the following points.

  • Current collectors:

    There is a distinction between the "positive_current_collector" and "negative_current_ollector", as they often have different properties. These keywords must contain geometry properties and conductivity. If the thermal model is used, thermal properties should be specified as well.

  • Electrodes:

    There is a distinction between the "positive_electrode" and "negative_electrode", as they have different properties. These keywords must contain information about geometry, porosity, and conductivity. If the thermal model is used, thermal properties should be specified as well. Additionally, electrodes should contain a list of the active materials that it contains.

    • Active materials:

      Each electrode can have one or more active materials. These are specified as dictionaries with the electrochemical properties that they have.

  • Separator:

    The "separator" keyword must contain geometry and porosity properties. If the thermal model is used, thermal properties should be specified as well.

  • Electrolyte:

    The "electrolyte" keyword must contain the electrochemical properties such as diffusivity, conductivity, transference number and activity parameter. If the thermal model is used, thermal properties should be specified as well.

In the data folder, there are several examples of such parameter files. This is an example of them:

{
        "specific_heat": {"unit": "J/kg K", "notes": "assumed uniform heat capacity across cell", "value": 1080.0, "effective": true, "correction":"bruggeman"}
    },
    "positive_electrode": {
        "name": "LiCoO2",
        "thickness": {"unit": "m", "value": 68.0e-06},
        "height": {"unit": "m", "value": 51e-3},
        "width": {"unit": "m", "value": 47e-3},
        "area": {"unit": "m^2", "value": 0.002397},
        "porosity": {"unit": "-", "value": 0.32},
        "bruggeman": {"unit": "-", "value": 1.83},
        "electronic_conductivity": {"unit": "S/m", "value": 10, "effective": false, "correction":"bruggeman"},
        "thermal_conductivity": {"unit": "W/mK", "value": 1.58, "effective": true, "correction":"bruggeman"},
        "specific_heat": {"unit": "J/kg K", "notes": "assumed", "value": 1080.0, "effective": true, "correction":"bruggeman"},
        "density": {"unit": "kg/m3", "notes": "assumed","value": 2000},
        "active_materials": 
        [
	      {
		    "volume_fraction": {"unit": "-", "value": 0.62},
            "particle_radius": {"unit": "m", "value": 3.0e-06},
            "stoichiometry1": {"unit": "-", "value": 0.435},
            "stoichiometry0": {"unit": "-", "value": 0.9651},
            "kinetic_constant": {"unit": "m^2.5/mol^0.5 s", "value": 1e-11},
            "alpha": {"unit": "-", "value": 0.5},
            "maximum_concentration": {"unit": "mol/m3", "value": 49943.0},
            "diffusion_constant": {"unit": "m^2/s", "value": 5.387e-15, "arrhenius": {"activationEnergy": 5000, "referenceTemperature":298.15}},
            "OCP": {
                "unit": ["-", "V"], 
                "type": "spline", 
                "spline_type": "Akima1D", 
                "source": "file", 
                "value": "OCPs/OCV_LCO_Rieger.txt"
            },
            "partial_molar_volume": {"unit": "m^3/mol", "value": -0.728e-6},
            "young_modulus": {"unit": "Pa", "value": 375e+9},
            "poisson_ratio": {"unit": "-", "value": 0.2}
          }
        ]
    },
    "positive_current_collector": {
        "name": "Al",
        "thickness": {"unit": "m", "value": 15e-06},
        "area": {"unit": "m^2", "value": 0.002397},
        "density": {"unit": "kg/m3", "notes": "taken from literature","value": 2700},
        "specific_heat": {"unit": "J/kg K", "notes": "taken from literature", "value": 900.0},
        "thermal_conductivity": {"unit": "W/mK", "value": 205},
        "electronic_conductivity": {"unit": "S/m", "value": 3.77e7}
    },
    "electrolyte": {
        "name": "LiPF6",
        "diffusion_constant": {
            "unit": "m^2/s", 
            "value": "pow(10,-0.22*0.001*c_e-8.43-54/(temp-229-5*0.001*c_e))",
            "_value": 6e-12, "effective": false, "correction":"bruggeman"
        },
        "ionic_conductivity": {
            "unit": "S/m", 
            "value": "c_e*0.0001*pow(-10.5+0.074*temp-6.96*pow(10,-5)*pow(temp,2)+0.688*0.001*c_e-0.0178*0.001*c_e*temp+2.8*pow(10,-8)*c_e*pow(temp,2)+0.494*pow(0.001*c_e,2)-8.86*pow(10,-4)*pow(0.001*c_e,2)*temp,2)",
            "_value": 0.7, "effective": false, "correction":"bruggeman"
        },
        "transference_number": {"unit": "-", "value": 0.38},
        "activity_dependence": {
            "unit":"-", 
            "note": "This is the (dln(f)/dln(c_e)+1) term in the potential equation",
            "value":"(0.601-0.24*pow(1e-3*c_e,0.5)+0.982*(1-0.0052*(temp-T_0))*pow(1e-3*c_e,3/2))/(1-t_p)",
            "_value": 1
        },
        "initial_concentration": {"unit": "mol/m3", "value": 1000}
    },
    "structure": ["ncc","a","s","c","pcc"],
    "references": {
        "1": "Ai (2020)",
        "2": "Rieger (2016)"
    },
    "results": {
        "0.5C": {
            "voltage":{
                "source":"file",
                "value":"reference_data/V_0.5C_Rieger.txt",
                "unit": "V"
            },
            "temperatureRise":
            {
                "source":"file",
                "value":"reference_data/T_0.5C_Rieger.txt",
                "unit": "ºC"
            },
            "thicknessChange":
            {
                "source":"file",
                "value":"reference_data/thick_0.5C_Rieger.txt",
                "unit": "micrometers"
            }
        },
        "1C": {
            "voltage":{
                "source":"file",
                "value":"reference_data/V_1C_Rieger.txt",
                "unit": "V"
            },
            "temperatureRise":
            {
                "source":"file",
                "value":"reference_data/T_1C_Rieger.txt",
                "unit": "ºC"
            },
            "thicknessChange":
            {
                "source":"file",
                "value":"reference_data/thick_1C_Rieger.txt",
                "unit": "micrometers"
            }
        },
        "2C": {
            "voltage":{
                "source":"file",
                "value":"reference_data/V_2C_Rieger.txt",
                "unit": "V"
            },
            "temperatureRise":
            {
                "source":"file",
                "value":"reference_data/T_2C_Rieger.txt",
                "unit": "ºC"
            },
            "thicknessChange":
            {
                "source":"file",
                "value":"reference_data/thick_2C_Rieger.txt",
                "unit": "micrometers"
            }
        }
    }
}

Note

Consider that several parameters as OCP, diffusivities and conductivities can be specified as a function or an array of points.

Test Plan

When using the CSI interface to simulate cell behavior, it is necesary to specify a test plan. This can be specified as a json or created programatically as python dictionaries or using cideMOD’s Input and Trigger classes. An example of a test plan built in the code with the different building blocks can be found in the Use Cases section.

Finer control

If you want to have more control over the inner details of the model, you can directly interact with the Problem object, as is the main responsible of assembling the models and running the simulation. An example of a simple discharge with this approach is given in the main.py file under the examples folder:

from cideMOD import (
    CellParser,
    ErrorCheck,
    Problem,
    SolverCrashed,
    Trigger,
    get_model_options,
)

case = "Ai_2020"
data_path = f"data/data_{case}"
params = "params.json"

model_options = get_model_options(model='P2D', save_path=f"{case}_discharge", overwrite=False)
cell = CellParser(params, data_path, model_options)
problem = Problem(cell, model_options)
problem.set_cell_state(SoC=1, T_ini=273 + 25, T_ext=273 + 25)
problem.setup()
C_rate = -1
I_app = C_rate * cell.ref_capacity
t_f = 3600 / abs(C_rate) * 1.25

v_min = Trigger(3, "v")
status = problem.solve(
    min_step=10, i_app=I_app, t_f=t_f, store_delay=10, adaptive=False, triggers=[v_min]
)
err = ErrorCheck(problem, status)

if isinstance(status, SolverCrashed):
    raise status.args[0]

In the folder examples/notebooks you can find several examples configuring cideMOD simulations from a beggining to an advance level.

Outputs

There are two kind of outputs available. For each simulation, the library saves results to a folder on the fly in case of internal variables, and at the end of the time-loop in the case of global variables.

  • Internal variables:

    These are the problem variables, or any derived value that has different values for each point in the cell geometry. These are automatically defined in the code, and written in the XDMF Format. The parameter store_delay can be modified to a negative value to suppress this output, or to a positive value to specify the frequency (in timesteps) at which the results are saved to the disk.

  • Global variables:

    These are overall cell figures (for example; cell voltage, current, maximum temperature, etc…), that are calculated and saved as a list of values over time internally in the memory. When the time iterations are finished, they are saved to disk as text files.