From 764ff2e3e71bc06614c5fffad4b75c5065739e02 Mon Sep 17 00:00:00 2001 From: tinosulzer Date: Mon, 4 Nov 2019 23:07:32 -0500 Subject: [PATCH 01/15] #685 set up casadi interpolation --- CHANGELOG.md | 2 +- examples/notebooks/change-input-current.ipynb | 16 +++++++------- .../1C_discharge_from_full/parameters.csv | 2 +- .../parameters.csv | 2 +- pybamm/__init__.py | 4 ++-- pybamm/expression_tree/functions.py | 2 +- pybamm/expression_tree/interpolant.py | 2 ++ .../operations/convert_to_casadi.py | 7 ++++++- pybamm/parameters/parameter_values.py | 4 ++-- .../get_constant_current.py | 2 +- .../get_user_current.py | 2 +- pybamm/solvers/dae_solver.py | 6 +++--- pybamm/solvers/ode_solver.py | 4 ++-- .../2019_08_sulzer_thesis/self_discharge.py | 2 +- .../drive_cycles/car_current_simulation.py | 2 +- results/drive_cycles/discharge_rest.py | 2 +- .../user_sin_current_simulation.py | 4 ++-- .../test_lead_acid/test_loqs.py | 2 +- .../test_composite_side_reactions.py | 2 +- .../test_full_side_reactions.py | 2 +- .../test_loqs_side_reactions.py | 2 +- .../test_lithium_ion/test_spm.py | 2 +- tests/integration/test_quick_plot.py | 2 +- .../test_operations/test_convert_to_casadi.py | 21 +++++++++++++++++++ .../test_parameters/test_current_functions.py | 8 +++---- .../test_electrical_parameters.py | 2 +- .../test_standard_parameters_lead_acid.py | 2 +- .../test_parameters/test_update_parameters.py | 2 +- tests/unit/test_solvers/test_casadi_solver.py | 6 +++--- 29 files changed, 73 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8be17aca65..9ef48364a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## Features - Added Simulation class ([#693](https://github.com/pybamm-team/PyBaMM/pull/693)) -- Add interface to CasADi solver ([#687](https://github.com/pybamm-team/PyBaMM/pull/687)) +- Add interface to CasADi solver ([#687](https://github.com/pybamm-team/PyBaMM/pull/687), [#691](https://github.com/pybamm-team/PyBaMM/pull/691)) - Add option to use CasADi's Algorithmic Differentiation framework to calculate Jacobians ([#687](https://github.com/pybamm-team/PyBaMM/pull/687)) - Add method to evaluate parameters more easily ([#669](https://github.com/pybamm-team/PyBaMM/pull/669)) - Add `Jacobian` class to reuse known Jacobians of expressions ([#665](https://github.com/pybamm-team/PyBaMM/pull/670)) diff --git a/examples/notebooks/change-input-current.ipynb b/examples/notebooks/change-input-current.ipynb index 7a1f0f7e9b..8226dabc84 100644 --- a/examples/notebooks/change-input-current.ipynb +++ b/examples/notebooks/change-input-current.ipynb @@ -22,7 +22,7 @@ "\n", "In this notebook we will use the SPM as the example model, and change the input current from the default option. If you are not familiar with running a model in PyBaMM, please see [this](./models/SPM.ipynb) notebook for more details.\n", "\n", - "In PyBaMM, the current function is set using the parameter \"Current function\". By default this is set to be a constant current provided by the class [`pybamm.GetConstantCurrent`](https://pybamm.readthedocs.io/en/latest/source/parameters/standard_current_functions/get_constant_current.html). This class takes a single optional argument \"current\" which is the size of the current in Amperes. If no argument is passed, the value of the current is set by the parameter \"Typical current [A]\" (see [this](parameter-values.ipynb) notebook for more information about parameters).\n", + "In PyBaMM, the current function is set using the parameter \"Current function\". By default this is set to be a constant current provided by the class [`pybamm.ConstantCurrent`](https://pybamm.readthedocs.io/en/latest/source/parameters/standard_current_functions/get_constant_current.html). This class takes a single optional argument \"current\" which is the size of the current in Amperes. If no argument is passed, the value of the current is set by the parameter \"Typical current [A]\" (see [this](parameter-values.ipynb) notebook for more information about parameters).\n", "\n", "In general it is recommended to change the size of a constant current input by changing the parameter \"Typical current [A]\", since this value is used to non-dimensionlise the model. Below we load the SPM with the default parameters, and then change the the typical current 16A. We then explicilty set the current function to be a constant current." ] @@ -49,14 +49,14 @@ "\n", "# change the typical current and set a constant discharge using the typical current value\n", "param[\"Typical current [A]\"] = 16\n", - "param[\"Current function\"] = pybamm.GetConstantCurrent()\n" + "param[\"Current function\"] = pybamm.ConstantCurrent()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "However, you may wish to change the value of the constant current without altering the typical current value used for non-dimensionlidation. For instance, the current function could be change to draw a current of 8A by updating the current function and passing the optional argument \"current\" to the class `GetConstantCurrent`" + "However, you may wish to change the value of the constant current without altering the typical current value used for non-dimensionlidation. For instance, the current function could be change to draw a current of 8A by updating the current function and passing the optional argument \"current\" to the class `ConstantCurrent`" ] }, { @@ -66,7 +66,7 @@ "outputs": [], "source": [ "# update the value of the current profile *without* changing the typical current used for non-dimensionlisation\n", - "param[\"Current function\"] = pybamm.GetConstantCurrent(current=pybamm.Scalar(8))" + "param[\"Current function\"] = pybamm.ConstantCurrent(current=pybamm.Scalar(8))" ] }, { @@ -240,7 +240,7 @@ "source": [ "## Adding your own current function \n", "\n", - "A user defined current function can be passed to any model using the class [`pybamm.GetUserCurrent`](https://pybamm.readthedocs.io/en/latest/source/parameters/standard_current_functions/get_user_current). The class takes in a method, which returns the current as a function of time, followed by any keyword arguments required by the method. \n", + "A user defined current function can be passed to any model using the class [`pybamm.UserCurrent`](https://pybamm.readthedocs.io/en/latest/source/parameters/standard_current_functions/get_user_current). The class takes in a method, which returns the current as a function of time, followed by any keyword arguments required by the method. \n", "\n", "For example, you may want to simulate a sinusoidal current with amplitude A and freqency omega. In order to do so you must first define the method" ] @@ -262,7 +262,7 @@ "source": [ "Note that time *must* me the first arguemnt of the function. The parameters may either be provided as floats, or may be one of the standard parameters provided in PyBaMM (see [here](https://pybamm.readthedocs.io/en/latest/source/parameters)). \n", "\n", - "The the model may be loaded and the \"Current function\" parameter updated to be a `GetUserCurrent` class which calls `my_fun`" + "The the model may be loaded and the \"Current function\" parameter updated to be a `UserCurrent` class which calls `my_fun`" ] }, { @@ -282,7 +282,7 @@ "# set user defined current function\n", "A = pybamm.electrical_parameters.I_typ\n", "omega = 0.1\n", - "param[\"Current function\"] = pybamm.GetUserCurrent(my_fun, A=A, omega=omega)\n", + "param[\"Current function\"] = pybamm.UserCurrent(my_fun, A=A, omega=omega)\n", "\n", "# process model and geometry\n", "param.process_model(model)\n", @@ -293,7 +293,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Note that the parameters in `my_fun` were passed as keyword arguments to the `GetUserCurrent` class. The model may then be solved in the usual way" + "Note that the parameters in `my_fun` were passed as keyword arguments to the `UserCurrent` class. The model may then be solved in the usual way" ] }, { diff --git a/input/parameters/lead-acid/experiments/1C_discharge_from_full/parameters.csv b/input/parameters/lead-acid/experiments/1C_discharge_from_full/parameters.csv index a69a021238..15dc8b80fa 100644 --- a/input/parameters/lead-acid/experiments/1C_discharge_from_full/parameters.csv +++ b/input/parameters/lead-acid/experiments/1C_discharge_from_full/parameters.csv @@ -11,7 +11,7 @@ Number of cells connected in series to make a battery,6,Manufacturer, Lower voltage cut-off [V],1.73,,(just under) 10.5V across 6-cell battery Upper voltage cut-off [V],2.44,,(just over) 14.5V across 6-cell battery C-rate,1,, -Current function,[inbuilt class]GetConstantCurrent,, +Current function,[inbuilt class]ConstantCurrent,, ,,, # Initial conditions Initial State of Charge,1,-, diff --git a/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Marquis2019/parameters.csv b/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Marquis2019/parameters.csv index dab0b3b48a..7c390e804e 100644 --- a/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Marquis2019/parameters.csv +++ b/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Marquis2019/parameters.csv @@ -11,7 +11,7 @@ Number of cells connected in series to make a battery,1,, Lower voltage cut-off [V],3.105,, Upper voltage cut-off [V],4.7,, C-rate,1,, -Current function,[inbuilt class]GetConstantCurrent,, +Current function,[inbuilt class]ConstantCurrent,, ,,, # Initial conditions Initial concentration in negative electrode [mol.m-3],19986.609595075,Scott Moura FastDFN, diff --git a/pybamm/__init__.py b/pybamm/__init__.py index 69cda501f7..4c72045389 100644 --- a/pybamm/__init__.py +++ b/pybamm/__init__.py @@ -273,9 +273,9 @@ def version(formatted=False): # from .parameters.standard_current_functions.base_current import GetCurrent from .parameters.standard_current_functions.get_constant_current import ( - GetConstantCurrent, + ConstantCurrent, ) -from .parameters.standard_current_functions.get_user_current import GetUserCurrent +from .parameters.standard_current_functions.get_user_current import UserCurrent from .parameters.standard_current_functions.get_current_data import GetCurrentData # diff --git a/pybamm/expression_tree/functions.py b/pybamm/expression_tree/functions.py index 1f1d28e524..bd46013eeb 100644 --- a/pybamm/expression_tree/functions.py +++ b/pybamm/expression_tree/functions.py @@ -230,7 +230,7 @@ def _function_simplify(self, simplified_children): if self.takes_no_params is True: # If self.function() takes no parameters then we can always simplify it return pybamm.Scalar(self.function()) - elif isinstance(self.function, pybamm.GetConstantCurrent): + elif isinstance(self.function, pybamm.ConstantCurrent): # If self.function() is a constant current then simplify to scalar return pybamm.Scalar(self.function.parameters_eval["Current [A]"]) else: diff --git a/pybamm/expression_tree/interpolant.py b/pybamm/expression_tree/interpolant.py index 5cb8a9c6ca..ef3c9a54b8 100644 --- a/pybamm/expression_tree/interpolant.py +++ b/pybamm/expression_tree/interpolant.py @@ -60,5 +60,7 @@ def __init__( interpolating_function, child, name=name, derivative="derivative" ) # Store information as attributes + self.x = data[:, 0] + self.y = data[:, 1] self.interpolator = interpolator self.extrapolate = extrapolate diff --git a/pybamm/expression_tree/operations/convert_to_casadi.py b/pybamm/expression_tree/operations/convert_to_casadi.py index d613badead..497f10af67 100644 --- a/pybamm/expression_tree/operations/convert_to_casadi.py +++ b/pybamm/expression_tree/operations/convert_to_casadi.py @@ -4,6 +4,7 @@ import pybamm import casadi import numpy as np +from scipy.interpolate import PchipInterpolator, CubicSpline class CasadiConverter(object): @@ -74,13 +75,17 @@ def _convert(self, symbol, t, y): return casadi.mmax(*converted_children) elif symbol.function == np.abs: return casadi.fabs(*converted_children) + elif isinstance(symbol.function, (PchipInterpolator, CubicSpline)): + return casadi.interpolant("LUT", "bspline", [symbol.x], symbol.y)( + *converted_children + ) elif not isinstance( symbol.function, pybamm.GetCurrent ) and symbol.function.__name__.startswith("elementwise_grad_of_"): differentiating_child_idx = int(symbol.function.__name__[-1]) # Create dummy symbolic variables in order to differentiate using CasADi dummy_vars = [ - casadi.SX.sym("y_" + str(i)) for i in range(len(converted_children)) + casadi.MX.sym("y_" + str(i)) for i in range(len(converted_children)) ] func_diff = casadi.gradient( symbol.differentiated_function(*dummy_vars), diff --git a/pybamm/parameters/parameter_values.py b/pybamm/parameters/parameter_values.py index 9880746c00..85b8457ff3 100644 --- a/pybamm/parameters/parameter_values.py +++ b/pybamm/parameters/parameter_values.py @@ -174,14 +174,14 @@ def check_and_update_parameter_values(self, values): raise ValueError( """ "C-rate" cannot be zero. A possible alternative is to set - "Current function" to `pybamm.GetConstantCurrent(current=0)` instead. + "Current function" to `pybamm.ConstantCurrent(current=0)` instead. """ ) if "Typical current [A]" in values and values["Typical current [A]"] == 0: raise ValueError( """ "Typical current [A]" cannot be zero. A possible alternative is to set - "Current function" to `pybamm.GetConstantCurrent(current=0)` instead. + "Current function" to `pybamm.ConstantCurrent(current=0)` instead. """ ) # If the capacity of the cell has been provided, make sure "C-rate" and current diff --git a/pybamm/parameters/standard_current_functions/get_constant_current.py b/pybamm/parameters/standard_current_functions/get_constant_current.py index 099cec05bf..a57203f7ac 100644 --- a/pybamm/parameters/standard_current_functions/get_constant_current.py +++ b/pybamm/parameters/standard_current_functions/get_constant_current.py @@ -4,7 +4,7 @@ import pybamm -class GetConstantCurrent(pybamm.GetCurrent): +class ConstantCurrent(pybamm.GetCurrent): """ Sets a constant input current for a simulation. diff --git a/pybamm/parameters/standard_current_functions/get_user_current.py b/pybamm/parameters/standard_current_functions/get_user_current.py index 0b1cc0b40f..24ef792b0d 100644 --- a/pybamm/parameters/standard_current_functions/get_user_current.py +++ b/pybamm/parameters/standard_current_functions/get_user_current.py @@ -4,7 +4,7 @@ import pybamm -class GetUserCurrent(pybamm.GetCurrent): +class UserCurrent(pybamm.GetCurrent): """ Sets a user-defined function as the input current for a simulation. diff --git a/pybamm/solvers/dae_solver.py b/pybamm/solvers/dae_solver.py index 74001b7b9c..46f8bfb001 100644 --- a/pybamm/solvers/dae_solver.py +++ b/pybamm/solvers/dae_solver.py @@ -227,10 +227,10 @@ def set_up_casadi(self, model): initial_conditions """ # Convert model attributes to casadi - t_casadi = casadi.SX.sym("t") + t_casadi = casadi.MX.sym("t") y0 = model.concatenated_initial_conditions - y_diff = casadi.SX.sym("y_diff", len(model.concatenated_rhs.evaluate(0, y0))) - y_alg = casadi.SX.sym( + y_diff = casadi.MX.sym("y_diff", len(model.concatenated_rhs.evaluate(0, y0))) + y_alg = casadi.MX.sym( "y_alg", len(model.concatenated_algebraic.evaluate(0, y0)) ) y_casadi = casadi.vertcat(y_diff, y_alg) diff --git a/pybamm/solvers/ode_solver.py b/pybamm/solvers/ode_solver.py index a1655d745f..168bc0479a 100644 --- a/pybamm/solvers/ode_solver.py +++ b/pybamm/solvers/ode_solver.py @@ -176,8 +176,8 @@ def set_up_casadi(self, model): y0 = model.concatenated_initial_conditions[:, 0] - t_casadi = casadi.SX.sym("t") - y_casadi = casadi.SX.sym("y", len(y0)) + t_casadi = casadi.MX.sym("t") + y_casadi = casadi.MX.sym("y", len(y0)) pybamm.logger.info("Converting RHS to CasADi") concatenated_rhs = model.concatenated_rhs.to_casadi(t_casadi, y_casadi) pybamm.logger.info("Converting events to CasADi") diff --git a/results/2019_08_sulzer_thesis/self_discharge.py b/results/2019_08_sulzer_thesis/self_discharge.py index 3b284d7b00..a040101832 100644 --- a/results/2019_08_sulzer_thesis/self_discharge.py +++ b/results/2019_08_sulzer_thesis/self_discharge.py @@ -32,7 +32,7 @@ def self_discharge_states(compute): ), ] extra_parameter_values = { - "Current function": pybamm.GetConstantCurrent(current=0) + "Current function": pybamm.ConstantCurrent(current=0) } t_eval = np.linspace(0, 1000, 100) all_variables, t_eval = model_comparison( diff --git a/results/drive_cycles/car_current_simulation.py b/results/drive_cycles/car_current_simulation.py index 81570e1bef..bcedf38408 100644 --- a/results/drive_cycles/car_current_simulation.py +++ b/results/drive_cycles/car_current_simulation.py @@ -40,7 +40,7 @@ def car_current(t): # load parameter values and process model and geometry param = model.default_parameter_values -param["Current function"] = pybamm.GetUserCurrent(car_current) +param["Current function"] = pybamm.UserCurrent(car_current) param.process_model(model) param.process_geometry(geometry) diff --git a/results/drive_cycles/discharge_rest.py b/results/drive_cycles/discharge_rest.py index 07f9007957..a576252285 100644 --- a/results/drive_cycles/discharge_rest.py +++ b/results/drive_cycles/discharge_rest.py @@ -41,7 +41,7 @@ # solve again with zero current, using last step of solution1 as initial conditions # update the current to be zero -param["Current function"] = pybamm.GetConstantCurrent(current=pybamm.Scalar(0)) +param["Current function"] = pybamm.ConstantCurrent(current=pybamm.Scalar(0)) param.update_model(model, disc) # Note: need to update model.concatenated_initial_conditions *after* update_model, # as update_model updates model.concatenated_initial_conditions, by concatenting diff --git a/results/drive_cycles/user_sin_current_simulation.py b/results/drive_cycles/user_sin_current_simulation.py index a2401c481e..ce579dd265 100644 --- a/results/drive_cycles/user_sin_current_simulation.py +++ b/results/drive_cycles/user_sin_current_simulation.py @@ -23,9 +23,9 @@ def my_fun(t, A, omega): # load parameter values and process models param = models[0].default_parameter_values for i, frequency in enumerate(frequencies): - # pass my_fun to GetUserCurrent class, giving the additonal parameters as + # pass my_fun to UserCurrent class, giving the additonal parameters as # keyword arguments - current = pybamm.GetUserCurrent(my_fun, A=A, omega=frequency) + current = pybamm.UserCurrent(my_fun, A=A, omega=frequency) param.update({"Current function": current}) param.process_model(models[i]) diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_loqs.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_loqs.py index ce1f3e8e21..cc04f85dbb 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_loqs.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_loqs.py @@ -47,7 +47,7 @@ def test_zero_current(self): model = pybamm.lead_acid.LOQS() parameter_values = model.default_parameter_values parameter_values.update( - {"Current function": pybamm.GetConstantCurrent(current=0)} + {"Current function": pybamm.ConstantCurrent(current=0)} ) modeltest = tests.StandardModelTest(model, parameter_values=parameter_values) modeltest.test_all() diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_composite_side_reactions.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_composite_side_reactions.py index af855e849d..e172dcd3d1 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_composite_side_reactions.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_composite_side_reactions.py @@ -37,7 +37,7 @@ def test_basic_processing_zero_current(self): model = pybamm.lead_acid.Composite(options) parameter_values = model.default_parameter_values parameter_values.update( - {"Current function": pybamm.GetConstantCurrent(current=0)} + {"Current function": pybamm.ConstantCurrent(current=0)} ) modeltest = tests.StandardModelTest(model, parameter_values=parameter_values) modeltest.test_all(skip_output_tests=True) diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_full_side_reactions.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_full_side_reactions.py index eb4823a1d7..0478e4c07d 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_full_side_reactions.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_full_side_reactions.py @@ -44,7 +44,7 @@ def test_basic_processing_zero_current(self): model = pybamm.lead_acid.Full(options) parameter_values = model.default_parameter_values parameter_values.update( - {"Current function": pybamm.GetConstantCurrent(current=0)} + {"Current function": pybamm.ConstantCurrent(current=0)} ) modeltest = tests.StandardModelTest(model, parameter_values=parameter_values) modeltest.test_all(skip_output_tests=True) diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_loqs_side_reactions.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_loqs_side_reactions.py index 1139a7d129..4c6a15c511 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_loqs_side_reactions.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_loqs_side_reactions.py @@ -45,7 +45,7 @@ def test_zero_current(self): model = pybamm.lead_acid.LOQS(options) parameter_values = model.default_parameter_values parameter_values.update( - {"Current function": pybamm.GetConstantCurrent(current=0)} + {"Current function": pybamm.ConstantCurrent(current=0)} ) modeltest = tests.StandardModelTest(model, parameter_values=parameter_values) modeltest.test_all(skip_output_tests=True) diff --git a/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_spm.py b/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_spm.py index 0aed23ae2e..d9e8f696e5 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_spm.py +++ b/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_spm.py @@ -84,7 +84,7 @@ def test_zero_current(self): model = pybamm.lithium_ion.SPM(options) parameter_values = model.default_parameter_values parameter_values.update( - {"Current function": pybamm.GetConstantCurrent(current=0)} + {"Current function": pybamm.ConstantCurrent(current=0)} ) modeltest = tests.StandardModelTest(model, parameter_values=parameter_values) modeltest.test_all() diff --git a/tests/integration/test_quick_plot.py b/tests/integration/test_quick_plot.py index d197b94a6b..8863d5b89e 100644 --- a/tests/integration/test_quick_plot.py +++ b/tests/integration/test_quick_plot.py @@ -43,7 +43,7 @@ def test_plot_lithium_ion(self): quick_plot.update(0.01) # Update parameters, solve, plot again - param.update({"Current function": pybamm.GetConstantCurrent(current=0)}) + param.update({"Current function": pybamm.ConstantCurrent(current=0)}) param.update_model(spm, disc_spm) solution_spm = spm.default_solver.solve(spm, t_eval) quick_plot = pybamm.QuickPlot(spm, mesh, solution_spm) diff --git a/tests/unit/test_expression_tree/test_operations/test_convert_to_casadi.py b/tests/unit/test_expression_tree/test_operations/test_convert_to_casadi.py index a516cb7955..9ebc374672 100644 --- a/tests/unit/test_expression_tree/test_operations/test_convert_to_casadi.py +++ b/tests/unit/test_expression_tree/test_operations/test_convert_to_casadi.py @@ -81,6 +81,27 @@ def test_special_functions(self): self.assertEqual(pybamm.Function(np.abs, b).to_casadi(), casadi.SX(2)) self.assertEqual(pybamm.Function(np.abs, c).to_casadi(), casadi.SX(3)) + def test_interpolation(self): + x = np.linspace(0, 1)[:, np.newaxis] + y = pybamm.StateVector(slice(0, 2)) + casadi_y = casadi.MX.sym("y", 2) + # linear + linear = np.hstack([x, 2 * x]) + y_test = np.array([0.4, 0.6]) + for interpolator in ["pchip", "cubic spline"]: + interp = pybamm.Interpolant(linear, y, interpolator=interpolator) + interp_casadi = interp.to_casadi(y=casadi_y) + f = casadi.Function("f", [casadi_y], [interp_casadi]) + np.testing.assert_array_almost_equal(interp.evaluate(y=y_test), f(y_test)) + # square + square = np.hstack([x, x ** 2]) + y = pybamm.StateVector(slice(0, 1)) + for interpolator in ["pchip", "cubic spline"]: + interp = pybamm.Interpolant(square, y, interpolator=interpolator) + interp_casadi = interp.to_casadi(y=casadi_y) + f = casadi.Function("f", [casadi_y], [interp_casadi]) + np.testing.assert_array_almost_equal(interp.evaluate(y=y_test), f(y_test)) + def test_concatenations(self): y = np.linspace(0, 1, 10)[:, np.newaxis] a = pybamm.Vector(y) diff --git a/tests/unit/test_parameters/test_current_functions.py b/tests/unit/test_parameters/test_current_functions.py index 0d6a2a248d..11e48cd00e 100644 --- a/tests/unit/test_parameters/test_current_functions.py +++ b/tests/unit/test_parameters/test_current_functions.py @@ -13,7 +13,7 @@ def test_base_current(self): self.assertEqual(function(10), 1) def test_constant_current(self): - function = pybamm.GetConstantCurrent(current=4) + function = pybamm.ConstantCurrent(current=4) assert isinstance(function(0), numbers.Number) assert isinstance(function(np.zeros(3)), numbers.Number) assert isinstance(function(np.zeros([3, 3])), numbers.Number) @@ -24,7 +24,7 @@ def test_constant_current(self): { "Typical current [A]": 2, "Typical timescale [s]": 1, - "Current function": pybamm.GetConstantCurrent(), + "Current function": pybamm.ConstantCurrent(), } ) processed_current = parameter_values.process_symbol(current) @@ -69,9 +69,9 @@ def my_fun(t, A, omega): A = pybamm.electrical_parameters.I_typ omega = 3 - # pass my_fun to GetUserCurrent class, giving the additonal parameters as + # pass my_fun to UserCurrent class, giving the additonal parameters as # keyword arguments - current = pybamm.GetUserCurrent(my_fun, A=A, omega=omega) + current = pybamm.UserCurrent(my_fun, A=A, omega=omega) # set and process parameters parameter_values = pybamm.ParameterValues( diff --git a/tests/unit/test_parameters/test_electrical_parameters.py b/tests/unit/test_parameters/test_electrical_parameters.py index 8f8f7cad79..4075d3e733 100644 --- a/tests/unit/test_parameters/test_electrical_parameters.py +++ b/tests/unit/test_parameters/test_electrical_parameters.py @@ -24,7 +24,7 @@ def test_current_functions(self): "Number of electrodes connected in parallel to make a cell": 8, "Typical current [A]": 2, "Typical timescale [s]": 60, - "Current function": pybamm.GetConstantCurrent(), + "Current function": pybamm.ConstantCurrent(), } ) dimensional_current_eval = parameter_values.process_symbol(dimensional_current) diff --git a/tests/unit/test_parameters/test_standard_parameters_lead_acid.py b/tests/unit/test_parameters/test_standard_parameters_lead_acid.py index 47b1fd16b6..6a311ab7cc 100644 --- a/tests/unit/test_parameters/test_standard_parameters_lead_acid.py +++ b/tests/unit/test_parameters/test_standard_parameters_lead_acid.py @@ -89,7 +89,7 @@ def test_current_functions(self): "Typical electrolyte concentration [mol.m-3]": 1, "Number of electrodes connected in parallel to make a cell": 8, "Typical current [A]": 2, - "Current function": pybamm.GetConstantCurrent(), + "Current function": pybamm.ConstantCurrent(), } ) dimensional_current_density_eval = parameter_values.process_symbol( diff --git a/tests/unit/test_parameters/test_update_parameters.py b/tests/unit/test_parameters/test_update_parameters.py index bab24a8f42..8f6794fcc3 100644 --- a/tests/unit/test_parameters/test_update_parameters.py +++ b/tests/unit/test_parameters/test_update_parameters.py @@ -75,7 +75,7 @@ def test_update_model(self): chemistry=pybamm.parameter_sets.Marquis2019 ) parameter_values_update.update( - {"Current function": pybamm.GetConstantCurrent(current=pybamm.Scalar(0))} + {"Current function": pybamm.ConstantCurrent(current=pybamm.Scalar(0))} ) modeltest3.test_update_parameters(parameter_values_update) modeltest3.test_solving(t_eval=t_eval) diff --git a/tests/unit/test_solvers/test_casadi_solver.py b/tests/unit/test_solvers/test_casadi_solver.py index 89a3f3a175..ca2769bda2 100644 --- a/tests/unit/test_solvers/test_casadi_solver.py +++ b/tests/unit/test_solvers/test_casadi_solver.py @@ -14,8 +14,8 @@ def test_integrate(self): # Constant solver = pybamm.CasadiSolver(rtol=1e-8, atol=1e-8, method="idas") - y = casadi.SX.sym("y") - constant_growth = casadi.SX(0.5) + y = casadi.MX.sym("y") + constant_growth = casadi.MX(0.5) problem = {"x": y, "ode": constant_growth} y0 = np.array([0]) @@ -40,7 +40,7 @@ def test_integrate_failure(self): # Turn off warnings to ignore sqrt error warnings.simplefilter("ignore") - y = casadi.SX.sym("y") + y = casadi.MX.sym("y") sqrt_decay = -np.sqrt(y) y0 = np.array([1]) From e0a4661c394fe8e608ee05ac0d3dcf6a9492f543 Mon Sep 17 00:00:00 2001 From: tinosulzer Date: Tue, 5 Nov 2019 12:31:00 -0500 Subject: [PATCH 02/15] #685 reformat current data --- examples/notebooks/change-input-current.ipynb | 62 +- input/drive_cycles/US06.csv | 1204 ++++++++--------- input/drive_cycles/car_current.csv | 30 +- pybamm/__init__.py | 9 +- .../operations/convert_to_casadi.py | 2 +- pybamm/parameters/parameter_values.py | 42 +- .../base_current.py | 2 +- ...onstant_current.py => constant_current.py} | 4 +- .../get_current_data.py | 91 -- .../get_user_current.py | 4 +- .../user_current.py | 31 + results/drive_cycles/US06_simulation.py | 4 +- .../test_parameters/test_current_functions.py | 18 +- 13 files changed, 701 insertions(+), 802 deletions(-) rename pybamm/parameters/standard_current_functions/{get_constant_current.py => constant_current.py} (86%) delete mode 100644 pybamm/parameters/standard_current_functions/get_current_data.py create mode 100644 pybamm/parameters/standard_current_functions/user_current.py diff --git a/examples/notebooks/change-input-current.ipynb b/examples/notebooks/change-input-current.ipynb index 8226dabc84..b4c6305de5 100644 --- a/examples/notebooks/change-input-current.ipynb +++ b/examples/notebooks/change-input-current.ipynb @@ -84,7 +84,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "fc997d14787542f69f2cba123ce0b994", + "model_id": "b900a39a72704c88927058510b7913b2", "version_major": 2, "version_minor": 0 }, @@ -127,11 +127,7 @@ "source": [ "## Loading in current data \n", "\n", - "Data can be loaded in from a csv file using the class [`pybamm.GetCurrentData`](https://pybamm.readthedocs.io/en/latest/source/parameters/standard_current_functions/get_current_data). Data should be given as a function of time (in seconds) and may be dimensional (in Amperes) or non-diemsnional (e.g. C-rate). Optionally, voltage data (in Volts) may be loaded in for convinient plotting and comparison. \n", - "\n", - "The input csv files should be stored in PyBaMM/input/drive_cycles and have the headings: \"time [s]\"; either \"current [A]\" for dimensional data, or \"current []\" for dimensionless data; and, optionally, \"voltage [V]\". \n", - "\n", - "To load in dimensional data we simply provide the filename and set the units to \"[A]\", e.g." + "Data can be loaded in from a csv file by specifying the path to that file and using the prefix \"[current data]\"." ] }, { @@ -140,54 +136,30 @@ "metadata": {}, "outputs": [], "source": [ - "param[\"Current function\"] = pybamm.GetCurrentData(\"US06.csv\", units=\"[A]\")" + "param[\"Current function\"] = \"[current data]US06\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "For non dimensional data, you also need to provide a current scale. For instance, if the data were C-rate then you would set the current scale to the 1C discharge current. If the 1C discharge current were 24 A and we had some C-rate data in the file car_current.csv, this would be loaded in as" + "As an example, we show how to solve the SPM using the US06 drive cycle" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, - "outputs": [], - "source": [ - "param[\"Current function\"] = pybamm.GetCurrentData(\"car_current.csv\", units=\"[]\", current_scale=24)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As an example, we how to solve the SPM using the US06 drive cycle" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/user/Documents/PyBaMM/pybamm/parameters/standard_current_functions/get_current_data.py:88: ModelWarning: Requested time (2387.404004088835) is outside of the data range [0, 600]\n", - " pybamm.ModelWarning,\n" - ] - }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "3f4c99601ab8417ba2186987cb532600", + "model_id": "26e7b28104b34991b3ebac266dab4934", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "interactive(children=(FloatSlider(value=0.0, description='t', max=0.03900922998674932, step=0.001), Output()),…" + "interactive(children=(FloatSlider(value=0.0, description='t', max=0.026526276390989537, step=0.001), Output())…" ] }, "metadata": {}, @@ -202,7 +174,7 @@ "\n", "# load parameter values and process model and geometry\n", "param = model.default_parameter_values\n", - "param[\"Current function\"] = pybamm.GetCurrentData(\"US06.csv\", units=\"[A]\")\n", + "param[\"Current function\"] = \"[current data]US06\"\n", "param.process_model(model)\n", "param.process_geometry(geometry)\n", "\n", @@ -247,7 +219,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -267,7 +239,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -298,26 +270,18 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 8, "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/user/Documents/PyBaMM/venv/lib/python3.6/site-packages/ipykernel_launcher.py:12: DeprecationWarning: object of type cannot be safely interpreted as an integer.\n", - " if sys.path[0] == '':\n" - ] - }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "913efe4e3e9e4b37bad2ded9c71b975e", + "model_id": "629672e99152464dad01e57ff152347a", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "interactive(children=(FloatSlider(value=0.0, description='t', max=0.0019504614993374662, step=9.75230749668733…" + "interactive(children=(FloatSlider(value=0.0, description='t', max=0.0013263138195494769, step=6.63156909774738…" ] }, "metadata": {}, @@ -372,7 +336,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.8" + "version": "3.7.4" } }, "nbformat": 4, diff --git a/input/drive_cycles/US06.csv b/input/drive_cycles/US06.csv index 287fd07020..e534a5db0f 100644 --- a/input/drive_cycles/US06.csv +++ b/input/drive_cycles/US06.csv @@ -1,603 +1,603 @@ # Based on the US06 drive cycle, -current [A],time [s] -0.012859,0 -0.012859,1 -0.012859,2 -0.012859,3 -0.012859,4 -0.012859,5 -0.013668,6 -0.023524,7 -0.03126,8 -0.050602,9 -0.58049,10 -2.6467,11 -3.8424,12 -4.1121,13 --0.23677,14 -3.1954,15 -4.134,16 -2.8259,17 -2.5489,18 -2.6931,19 -2.3144,20 -3.5036,21 -2.7033,22 -1.057,23 --0.44999,24 --0.4451,25 --1.8319,26 --0.6912,27 --0.41631,28 -0.39479,29 -1.4094,30 --0.067283,31 -0.40082,32 --1.6765,33 --3.0094,34 --2.9658,35 --2.8139,36 --2.1029,37 --1.7886,38 --1.0515,39 --0.33154,40 --0.00027238,41 -0.012859,42 -0.012859,43 -0.012859,44 -0.012859,45 -0.012859,46 -0.012859,47 -0.012859,48 -0.026246,49 -1.4175,50 -2.3404,51 -1.9203,52 -2.8051,53 -4.2382,54 -4.2743,55 -2.8574,56 -4.2758,57 -4.9662,58 -4.8662,59 -3.8788,60 -2.521,61 -3.5651,62 -3.3848,63 -3.6869,64 -3.1176,65 -2.8487,66 -2.1836,67 -0.18726,68 -0.91501,69 -0.0053402,70 --0.37207,71 --0.37225,72 -0.33741,73 -1.0426,74 -0.33741,75 --0.37219,76 --0.96565,77 -0.13474,78 -0.46979,79 -0.46799,80 -0.80472,81 -0.80717,82 -1.4932,83 -2.2074,84 -3.3239,85 -4.1708,86 -4.5251,87 -4.3083,88 -4.2568,89 -4.8156,90 -5.2028,91 -4.5034,92 -4.6358,93 -3.3841,94 -1.5935,95 -1.3703,96 -0.22134,97 --2.5008,98 --1.8485,99 --1.6727,100 --1.0737,101 --1.065,102 --1.4701,103 --1.7157,104 --1.5508,105 --1.6473,106 --1.3644,107 --1.5766,108 --1.4219,109 --1.4997,110 --1.242,111 --1.4213,112 --1.9789,113 --2.4495,114 --1.771,115 --0.67,116 --0.65407,117 --0.79789,118 --3.6676,119 --3.2481,120 --2.1471,121 --1.5972,122 --1.3075,123 --0.80837,124 --0.29408,125 --0.039143,126 --0.012101,127 --0.00027238,128 -0.012859,129 -0.012859,130 -0.012859,131 -0.012859,132 -0.012859,133 -0.012859,134 -0.012859,135 -0.13367,136 -1.3164,137 -2.9506,138 -4.3345,139 -5.7205,140 -5.4552,141 -5.8237,142 -6.0151,143 -3.7866,144 -2.7655,145 -2.3944,146 -2.948,147 -1.8924,148 -2.5999,149 -1.8149,150 -1.3287,151 -1.3425,152 -2.057,153 -0.67879,154 -0.67879,155 -2.0956,156 -3.7768,157 -1.8459,158 -3.0051,159 -1.3509,160 -3.1006,161 -1.4034,162 -1.4141,163 -1.4248,164 --0.50076,165 --1.2951,166 -0.40453,167 -0.21185,168 --0.11201,169 -1.1354,170 --0.62707,171 -1.4858,172 -0.011324,173 -0.55864,174 -0.18866,175 -1.1018,176 -1.1079,177 -0.37419,178 -0.18726,179 -0.5484,180 -0.54637,181 --0.86914,182 --0.24991,183 -1.3988,184 --2.4102,185 -5.0098,186 -2.5027,187 -3.1156,188 -2.6317,189 -0.96709,190 -3.2753,191 -1.7871,192 -2.998,193 -1.6541,194 -1.8721,195 -2.0978,196 -0.89478,197 -1.3038,198 --0.078976,199 -1.4977,200 -2.1259,201 -0.089321,202 -1.1053,203 -1.3141,204 -3.1926,205 -0.52137,206 -1.3521,207 -1.3591,208 -1.3661,209 -1.7966,210 -1.8134,211 -2.4758,212 -0.995,213 -1.8602,214 --2.6906,215 --0.067612,216 -1.5503,217 -1.3521,218 -0.10446,219 -2.1829,220 -0.73539,221 -0.31463,222 -1.5617,223 --0.49752,224 -2.1685,225 -0.7278,226 -1.1428,227 -0.51918,228 -1.3486,229 --0.35495,230 -1.124,231 -1.9596,232 -1.1428,233 -1.5655,234 -1.9998,235 -1.5964,236 --0.93064,237 -1.3556,238 --0.92625,239 -2.1543,240 --0.21363,241 -2.1543,242 -0.51263,243 --0.07259,244 -1.1146,245 -0.70538,246 -1.5276,247 -1.124,248 -0.7128,249 --0.49887,250 -0.89478,251 -1.7142,252 -0.70048,253 --0.21884,254 -1.2937,255 -0.68831,256 -0.88929,257 -1.093,258 -0.28185,259 -1.698,260 -1.5089,261 --0.078194,262 -0.88929,263 -1.093,264 --0.081297,265 -2.7118,266 -0.90306,267 --0.078194,268 -1.9111,269 -0.084907,270 -0.28185,271 -0.47868,272 -0.67631,273 -1.4829,274 -0.88383,275 -0.88383,276 -0.6811,277 -1.694,278 -0.48492,279 -0.88656,280 -1.2937,281 -1.5051,282 -0.69559,283 -3.1671,284 -2.1829,285 -1.9998,286 -1.5964,287 -2.6805,288 -1.4233,289 -2.9549,290 -1.4636,291 -1.6914,292 -2.8152,293 -1.0654,294 -2.1852,295 -1.757,296 -1.7695,297 -6.4018,298 -2.1159,299 -7.9136,300 --2.9379,301 -0.26072,302 -1.1932,303 -0.72206,304 -2.3667,305 -1.9156,306 -0.97617,307 --0.62823,308 -0.24381,309 -0.46769,310 -1.156,311 -0.69207,312 -1.3812,313 -1.1527,314 -1.6173,315 -3.2663,316 -2.3718,317 -3.5953,318 -4.151,319 -3.4975,320 -5.3167,321 -4.1756,322 -3.7387,323 --0.94696,324 --2.8522,325 -0.33794,326 -3.3004,327 -4.3626,328 -2.4058,329 -4.2276,330 -2.4839,331 -2.505,332 -1.4794,333 -2.5263,334 -1.4955,335 --0.40618,336 -1.4633,337 -0.42687,338 -0.41621,339 --0.94842,340 --0.95058,341 --2.8125,342 --1.9414,343 --2.0775,344 --4.2071,345 --1.091,346 -1.6593,347 --0.19359,348 -0.5667,349 -1.6394,350 -0.78484,351 -3.174,352 -1.6874,353 -3.0325,354 -1.0654,355 -1.9606,356 --0.023889,357 -0.83956,358 -0.83676,359 --0.63943,360 --0.34073,361 -0.35759,362 -0.13671,363 -1.6315,364 -1.8602,365 -0.14178,366 -1.6434,367 -2.5283,368 -2.1238,369 -1.9253,370 -1.4972,371 -1.9517,372 -1.9695,373 -0.41043,374 -2.8783,375 -1.1003,376 -1.1003,377 -2.4667,378 -2.0372,379 -1.5935,380 -1.8329,381 --0.15832,382 -1.8201,383 -0.44887,384 --0.16389,385 -1.5661,386 -1.5739,387 --0.0085663,388 -0.42601,389 -2.4615,390 -0.66037,391 -0.65518,392 -2.0145,393 -1.8031,394 -1.1263,395 -1.1263,396 -2.9716,397 -0.68939,398 -1.3775,399 -0.68671,400 -1.6054,401 -1.8458,402 -1.3922,403 -0.0053429,404 -2.074,405 -2.3266,406 -1.6454,407 -2.8354,408 -0.49679,409 -1.1966,410 -0.72483,411 -0.95438,412 -0.9513,413 -2.8354,414 -1.682,415 -2.1679,416 --0.95265,417 --0.14664,418 --0.15257,419 -0.00062616,420 -1.363,421 -2.0601,422 --0.31705,423 -2.9716,424 --0.47505,425 -1.3558,426 --1.1047,427 -0.41485,428 --0.17703,429 -1.2852,430 -0.84237,431 --0.029129,432 -0.16447,433 -1.4748,434 -1.2612,435 -1.0436,436 -0.16268,437 -0.59278,438 --0.34126,439 -1.6553,440 -0.1452,441 -1.4342,442 --0.046997,443 -1.4233,444 --0.19793,445 --4.0792,446 -0.88656,447 --0.50003,448 -0.26455,449 -1.4573,450 -0.26455,451 -1.4573,452 -0.86493,453 -1.67,454 -0.87569,455 -0.87569,456 -0.87569,457 -1.686,458 -0.076253,459 -1.686,460 -1.7021,461 -0.081997,462 -1.7021,463 -0.081997,464 -1.7021,465 -0.89753,466 -1.7183,467 -0.087843,468 -0.081997,469 --0.9152,470 --1.5834,471 --0.36787,472 --2.0567,473 --0.87672,474 --1.4815,475 --2.6241,476 --2.178,477 --0.036534,478 --0.90616,479 --2.4373,480 --2.9694,481 --3.5147,482 --1.8457,483 --0.98341,484 --2.4483,485 --3.8294,486 --1.9441,487 --0.048456,488 --1.0641,489 --1.0035,490 --0.66563,491 --0.32669,492 --0.027036,493 -0.012859,494 -0.012859,495 -0.012859,496 -0.012859,497 -0.012859,498 -0.012859,499 -0.012859,500 -0.013668,501 -0.34446,502 -1.4125,503 -2.4117,504 -3.237,505 -3.4134,506 -2.4722,507 -0.71203,508 --0.68697,509 --0.9946,510 --1.1241,511 --2.2309,512 --1.7637,513 --0.84058,514 -0.20754,515 -1.1729,516 -1.9691,517 -2.7371,518 -3.2787,519 -2.6509,520 -1.5214,521 --0.0058875,522 --1.3985,523 --1.9241,524 --1.808,525 --1.6276,526 --0.95015,527 --0.20711,528 --0.2798,529 --0.026526,530 -0.059693,531 -0.71684,532 -1.6183,533 -2.4505,534 -3.2363,535 -3.4634,536 -1.8132,537 -0.52817,538 --0.37846,539 --1.398,540 --1.9658,541 --1.8804,542 --1.5482,543 --0.64195,544 --0.15352,545 --0.0033494,546 -1.1079,547 -1.9138,548 -2.325,549 -3.0374,550 -3.3647,551 -3.7312,552 -0.086116,553 --2.2017,554 --2.3495,555 --2.0339,556 --1.4035,557 --0.91224,558 --0.37758,559 --0.056562,560 -0.012859,561 -0.012859,562 -0.012859,563 -0.012859,564 -0.012859,565 -0.012859,566 -0.012859,567 -0.014561,568 -0.70309,569 -2.0434,570 -3.5113,571 -3.4062,572 -3.9559,573 -7.1727,574 -3.4216,575 -3.9417,576 -6.9749,577 -8.1,578 -3.415,579 --0.024227,580 --0.25555,581 --0.3689,582 --1.9022,583 --2.9537,584 --2.95,585 --2.7289,586 --3.271,587 --3.5216,588 --2.3332,589 --2.2084,590 --2.0047,591 --1.3769,592 --0.34366,593 --0.035978,594 -0.012859,595 -0.012859,596 -0.012859,597 -0.012859,598 -0.012859,599 -0.012859,600 +# time [s],current [A] +0,0.012859 +1,0.012859 +2,0.012859 +3,0.012859 +4,0.012859 +5,0.012859 +6,0.013668 +7,0.023524 +8,0.03126 +9,0.050602 +10,0.58049 +11,2.6467 +12,3.8424 +13,4.1121 +14,-0.23677 +15,3.1954 +16,4.134 +17,2.8259 +18,2.5489 +19,2.6931 +20,2.3144 +21,3.5036 +22,2.7033 +23,1.057 +24,-0.44999 +25,-0.4451 +26,-1.8319 +27,-0.6912 +28,-0.41631 +29,0.39479 +30,1.4094 +31,-0.067283 +32,0.40082 +33,-1.6765 +34,-3.0094 +35,-2.9658 +36,-2.8139 +37,-2.1029 +38,-1.7886 +39,-1.0515 +40,-0.33154 +41,-0.00027238 +42,0.012859 +43,0.012859 +44,0.012859 +45,0.012859 +46,0.012859 +47,0.012859 +48,0.012859 +49,0.026246 +50,1.4175 +51,2.3404 +52,1.9203 +53,2.8051 +54,4.2382 +55,4.2743 +56,2.8574 +57,4.2758 +58,4.9662 +59,4.8662 +60,3.8788 +61,2.521 +62,3.5651 +63,3.3848 +64,3.6869 +65,3.1176 +66,2.8487 +67,2.1836 +68,0.18726 +69,0.91501 +70,0.0053402 +71,-0.37207 +72,-0.37225 +73,0.33741 +74,1.0426 +75,0.33741 +76,-0.37219 +77,-0.96565 +78,0.13474 +79,0.46979 +80,0.46799 +81,0.80472 +82,0.80717 +83,1.4932 +84,2.2074 +85,3.3239 +86,4.1708 +87,4.5251 +88,4.3083 +89,4.2568 +90,4.8156 +91,5.2028 +92,4.5034 +93,4.6358 +94,3.3841 +95,1.5935 +96,1.3703 +97,0.22134 +98,-2.5008 +99,-1.8485 +100,-1.6727 +101,-1.0737 +102,-1.065 +103,-1.4701 +104,-1.7157 +105,-1.5508 +106,-1.6473 +107,-1.3644 +108,-1.5766 +109,-1.4219 +110,-1.4997 +111,-1.242 +112,-1.4213 +113,-1.9789 +114,-2.4495 +115,-1.771 +116,-0.67 +117,-0.65407 +118,-0.79789 +119,-3.6676 +120,-3.2481 +121,-2.1471 +122,-1.5972 +123,-1.3075 +124,-0.80837 +125,-0.29408 +126,-0.039143 +127,-0.012101 +128,-0.00027238 +129,0.012859 +130,0.012859 +131,0.012859 +132,0.012859 +133,0.012859 +134,0.012859 +135,0.012859 +136,0.13367 +137,1.3164 +138,2.9506 +139,4.3345 +140,5.7205 +141,5.4552 +142,5.8237 +143,6.0151 +144,3.7866 +145,2.7655 +146,2.3944 +147,2.948 +148,1.8924 +149,2.5999 +150,1.8149 +151,1.3287 +152,1.3425 +153,2.057 +154,0.67879 +155,0.67879 +156,2.0956 +157,3.7768 +158,1.8459 +159,3.0051 +160,1.3509 +161,3.1006 +162,1.4034 +163,1.4141 +164,1.4248 +165,-0.50076 +166,-1.2951 +167,0.40453 +168,0.21185 +169,-0.11201 +170,1.1354 +171,-0.62707 +172,1.4858 +173,0.011324 +174,0.55864 +175,0.18866 +176,1.1018 +177,1.1079 +178,0.37419 +179,0.18726 +180,0.5484 +181,0.54637 +182,-0.86914 +183,-0.24991 +184,1.3988 +185,-2.4102 +186,5.0098 +187,2.5027 +188,3.1156 +189,2.6317 +190,0.96709 +191,3.2753 +192,1.7871 +193,2.998 +194,1.6541 +195,1.8721 +196,2.0978 +197,0.89478 +198,1.3038 +199,-0.078976 +200,1.4977 +201,2.1259 +202,0.089321 +203,1.1053 +204,1.3141 +205,3.1926 +206,0.52137 +207,1.3521 +208,1.3591 +209,1.3661 +210,1.7966 +211,1.8134 +212,2.4758 +213,0.995 +214,1.8602 +215,-2.6906 +216,-0.067612 +217,1.5503 +218,1.3521 +219,0.10446 +220,2.1829 +221,0.73539 +222,0.31463 +223,1.5617 +224,-0.49752 +225,2.1685 +226,0.7278 +227,1.1428 +228,0.51918 +229,1.3486 +230,-0.35495 +231,1.124 +232,1.9596 +233,1.1428 +234,1.5655 +235,1.9998 +236,1.5964 +237,-0.93064 +238,1.3556 +239,-0.92625 +240,2.1543 +241,-0.21363 +242,2.1543 +243,0.51263 +244,-0.07259 +245,1.1146 +246,0.70538 +247,1.5276 +248,1.124 +249,0.7128 +250,-0.49887 +251,0.89478 +252,1.7142 +253,0.70048 +254,-0.21884 +255,1.2937 +256,0.68831 +257,0.88929 +258,1.093 +259,0.28185 +260,1.698 +261,1.5089 +262,-0.078194 +263,0.88929 +264,1.093 +265,-0.081297 +266,2.7118 +267,0.90306 +268,-0.078194 +269,1.9111 +270,0.084907 +271,0.28185 +272,0.47868 +273,0.67631 +274,1.4829 +275,0.88383 +276,0.88383 +277,0.6811 +278,1.694 +279,0.48492 +280,0.88656 +281,1.2937 +282,1.5051 +283,0.69559 +284,3.1671 +285,2.1829 +286,1.9998 +287,1.5964 +288,2.6805 +289,1.4233 +290,2.9549 +291,1.4636 +292,1.6914 +293,2.8152 +294,1.0654 +295,2.1852 +296,1.757 +297,1.7695 +298,6.4018 +299,2.1159 +300,7.9136 +301,-2.9379 +302,0.26072 +303,1.1932 +304,0.72206 +305,2.3667 +306,1.9156 +307,0.97617 +308,-0.62823 +309,0.24381 +310,0.46769 +311,1.156 +312,0.69207 +313,1.3812 +314,1.1527 +315,1.6173 +316,3.2663 +317,2.3718 +318,3.5953 +319,4.151 +320,3.4975 +321,5.3167 +322,4.1756 +323,3.7387 +324,-0.94696 +325,-2.8522 +326,0.33794 +327,3.3004 +328,4.3626 +329,2.4058 +330,4.2276 +331,2.4839 +332,2.505 +333,1.4794 +334,2.5263 +335,1.4955 +336,-0.40618 +337,1.4633 +338,0.42687 +339,0.41621 +340,-0.94842 +341,-0.95058 +342,-2.8125 +343,-1.9414 +344,-2.0775 +345,-4.2071 +346,-1.091 +347,1.6593 +348,-0.19359 +349,0.5667 +350,1.6394 +351,0.78484 +352,3.174 +353,1.6874 +354,3.0325 +355,1.0654 +356,1.9606 +357,-0.023889 +358,0.83956 +359,0.83676 +360,-0.63943 +361,-0.34073 +362,0.35759 +363,0.13671 +364,1.6315 +365,1.8602 +366,0.14178 +367,1.6434 +368,2.5283 +369,2.1238 +370,1.9253 +371,1.4972 +372,1.9517 +373,1.9695 +374,0.41043 +375,2.8783 +376,1.1003 +377,1.1003 +378,2.4667 +379,2.0372 +380,1.5935 +381,1.8329 +382,-0.15832 +383,1.8201 +384,0.44887 +385,-0.16389 +386,1.5661 +387,1.5739 +388,-0.0085663 +389,0.42601 +390,2.4615 +391,0.66037 +392,0.65518 +393,2.0145 +394,1.8031 +395,1.1263 +396,1.1263 +397,2.9716 +398,0.68939 +399,1.3775 +400,0.68671 +401,1.6054 +402,1.8458 +403,1.3922 +404,0.0053429 +405,2.074 +406,2.3266 +407,1.6454 +408,2.8354 +409,0.49679 +410,1.1966 +411,0.72483 +412,0.95438 +413,0.9513 +414,2.8354 +415,1.682 +416,2.1679 +417,-0.95265 +418,-0.14664 +419,-0.15257 +420,0.00062616 +421,1.363 +422,2.0601 +423,-0.31705 +424,2.9716 +425,-0.47505 +426,1.3558 +427,-1.1047 +428,0.41485 +429,-0.17703 +430,1.2852 +431,0.84237 +432,-0.029129 +433,0.16447 +434,1.4748 +435,1.2612 +436,1.0436 +437,0.16268 +438,0.59278 +439,-0.34126 +440,1.6553 +441,0.1452 +442,1.4342 +443,-0.046997 +444,1.4233 +445,-0.19793 +446,-4.0792 +447,0.88656 +448,-0.50003 +449,0.26455 +450,1.4573 +451,0.26455 +452,1.4573 +453,0.86493 +454,1.67 +455,0.87569 +456,0.87569 +457,0.87569 +458,1.686 +459,0.076253 +460,1.686 +461,1.7021 +462,0.081997 +463,1.7021 +464,0.081997 +465,1.7021 +466,0.89753 +467,1.7183 +468,0.087843 +469,0.081997 +470,-0.9152 +471,-1.5834 +472,-0.36787 +473,-2.0567 +474,-0.87672 +475,-1.4815 +476,-2.6241 +477,-2.178 +478,-0.036534 +479,-0.90616 +480,-2.4373 +481,-2.9694 +482,-3.5147 +483,-1.8457 +484,-0.98341 +485,-2.4483 +486,-3.8294 +487,-1.9441 +488,-0.048456 +489,-1.0641 +490,-1.0035 +491,-0.66563 +492,-0.32669 +493,-0.027036 +494,0.012859 +495,0.012859 +496,0.012859 +497,0.012859 +498,0.012859 +499,0.012859 +500,0.012859 +501,0.013668 +502,0.34446 +503,1.4125 +504,2.4117 +505,3.237 +506,3.4134 +507,2.4722 +508,0.71203 +509,-0.68697 +510,-0.9946 +511,-1.1241 +512,-2.2309 +513,-1.7637 +514,-0.84058 +515,0.20754 +516,1.1729 +517,1.9691 +518,2.7371 +519,3.2787 +520,2.6509 +521,1.5214 +522,-0.0058875 +523,-1.3985 +524,-1.9241 +525,-1.808 +526,-1.6276 +527,-0.95015 +528,-0.20711 +529,-0.2798 +530,-0.026526 +531,0.059693 +532,0.71684 +533,1.6183 +534,2.4505 +535,3.2363 +536,3.4634 +537,1.8132 +538,0.52817 +539,-0.37846 +540,-1.398 +541,-1.9658 +542,-1.8804 +543,-1.5482 +544,-0.64195 +545,-0.15352 +546,-0.0033494 +547,1.1079 +548,1.9138 +549,2.325 +550,3.0374 +551,3.3647 +552,3.7312 +553,0.086116 +554,-2.2017 +555,-2.3495 +556,-2.0339 +557,-1.4035 +558,-0.91224 +559,-0.37758 +560,-0.056562 +561,0.012859 +562,0.012859 +563,0.012859 +564,0.012859 +565,0.012859 +566,0.012859 +567,0.012859 +568,0.014561 +569,0.70309 +570,2.0434 +571,3.5113 +572,3.4062 +573,3.9559 +574,7.1727 +575,3.4216 +576,3.9417 +577,6.9749 +578,8.1 +579,3.415 +580,-0.024227 +581,-0.25555 +582,-0.3689 +583,-1.9022 +584,-2.9537 +585,-2.95 +586,-2.7289 +587,-3.271 +588,-3.5216 +589,-2.3332 +590,-2.2084 +591,-2.0047 +592,-1.3769 +593,-0.34366 +594,-0.035978 +595,0.012859 +596,0.012859 +597,0.012859 +598,0.012859 +599,0.012859 +600,0.012859 diff --git a/input/drive_cycles/car_current.csv b/input/drive_cycles/car_current.csv index aaae1b7e5a..3d23ca51bc 100644 --- a/input/drive_cycles/car_current.csv +++ b/input/drive_cycles/car_current.csv @@ -1,16 +1,16 @@ # This is adapted from the file getCarCurrent.m which is part of the LIONSIMBA toolbox., -current [],time [s] -1,0 -1,50 --0.5,50.001 --0.5,60 -0.5,60.001 -0.5,210 -1,210.001 -1,410 -2,410.001 -2,415 -1.25,415.001 -1.25,615 --0.5,615.001 --0.5,3600 +# time [s], current [A] +0, 1 +50, 1 +50.001, -0.5 +60, -0.5 +60.001, 0.5 +210, 0.5 +210.001, 1 +410, 1 +410.001, 2 +415, 2 +415.001, 1.25 +615, 1.25 +615.001, -0.5 +3600, -0.5 diff --git a/pybamm/__init__.py b/pybamm/__init__.py index 4c72045389..55ad930ce5 100644 --- a/pybamm/__init__.py +++ b/pybamm/__init__.py @@ -271,12 +271,9 @@ def version(formatted=False): # # Current profiles # -from .parameters.standard_current_functions.base_current import GetCurrent -from .parameters.standard_current_functions.get_constant_current import ( - ConstantCurrent, -) -from .parameters.standard_current_functions.get_user_current import UserCurrent -from .parameters.standard_current_functions.get_current_data import GetCurrentData +from .parameters.standard_current_functions.base_current import BaseCurrent +from .parameters.standard_current_functions.constant_current import ConstantCurrent +from .parameters.standard_current_functions.user_current import UserCurrent # # other diff --git a/pybamm/expression_tree/operations/convert_to_casadi.py b/pybamm/expression_tree/operations/convert_to_casadi.py index 497f10af67..50335241e5 100644 --- a/pybamm/expression_tree/operations/convert_to_casadi.py +++ b/pybamm/expression_tree/operations/convert_to_casadi.py @@ -80,7 +80,7 @@ def _convert(self, symbol, t, y): *converted_children ) elif not isinstance( - symbol.function, pybamm.GetCurrent + symbol.function, pybamm.BaseCurrent ) and symbol.function.__name__.startswith("elementwise_grad_of_"): differentiating_child_idx = int(symbol.function.__name__[-1]) # Create dummy symbolic variables in order to differentiate using CasADi diff --git a/pybamm/parameters/parameter_values.py b/pybamm/parameters/parameter_values.py index 85b8457ff3..e9826c2a23 100644 --- a/pybamm/parameters/parameter_values.py +++ b/pybamm/parameters/parameter_values.py @@ -4,7 +4,6 @@ import pybamm import pandas as pd import os -import numpy as np class ParameterValues(dict): @@ -126,6 +125,13 @@ def read_parameters_csv(self, filename): df.dropna(how="all", inplace=True) return {k: v for (k, v) in zip(df["Name [units]"], df["Value"])} + def __setitem__(self, key, value): + "Call the update functionality when doing a setitem" + self.update({key: value}) + + def setitemsuper(self, key, value): + super().__setitem__(key, value) + def update(self, values, check_conflict=False, path=""): # check parameter values values = self.check_and_update_parameter_values(values) @@ -155,16 +161,27 @@ def update(self, values, check_conflict=False, path=""): # Extra set of brackets at the end makes an instance of the # class self[name] = getattr(pybamm, value[15:])() - # Data is flagged with the string "[data]" - elif value.startswith("[data]"): - data = np.loadtxt(os.path.join(path, value[6:] + ".csv")) + # Data is flagged with the string "[data]" or "[current data]" + elif value.startswith("[current data]") or value.startswith( + "[data]" + ): + if value.startswith("[current data]"): + data_path = os.path.join( + pybamm.root_dir(), "input", "drive_cycles" + ) + filename = os.path.join(data_path, value[14:] + ".csv") + else: + filename = os.path.join(path, value[6:] + ".csv") + data = pd.read_csv( + filename, comment="#", skip_blank_lines=True + ).to_numpy() # Save name and data - self[name] = (value[6:], data) + self.setitemsuper(name, (value[6:], data)) # Anything else should be a converted to a float else: - self[name] = float(value) + self.setitemsuper(name, float(value)) else: - self[name] = value + self.setitemsuper(name, value) # reset processed symbols self._processed_symbols = {} @@ -409,16 +426,12 @@ def _process_symbol(self, symbol): # if current setter, process any parameters that are symbols and # store the evaluated symbol in the parameters_eval dict - if isinstance(function_name, pybamm.GetCurrent): + if isinstance(function_name, pybamm.BaseCurrent): for param, sym in function_name.parameters.items(): if isinstance(sym, pybamm.Symbol): new_sym = self.process_symbol(sym) function_name.parameters[param] = new_sym function_name.parameters_eval[param] = new_sym.evaluate() - # If loading data, need to update interpolant with - # evaluated parameters - if isinstance(function_name, pybamm.GetCurrentData): - function_name.interpolate() # Create Function or Interpolant objec if isinstance(function_name, tuple): @@ -500,7 +513,7 @@ def update_scalars(self, symbol): # KeyError -> name not in parameter dict, don't update continue elif isinstance(x, pybamm.Function): - if isinstance(x.function, pybamm.GetCurrent): + if isinstance(x.function, pybamm.BaseCurrent): # Need to update parameters dict to be that of the new current # function and make new parameters_eval dict to be processed x.function.parameters = self["Current function"].parameters @@ -518,9 +531,6 @@ def update_scalars(self, symbol): # KeyError -> name not in parameter dict, evaluate # unnamed Scalar x.function.parameters_eval[param] = new_sym.evaluate() - if isinstance(x.function, pybamm.GetCurrentData): - # update interpolant - x.function.interpolate() return symbol diff --git a/pybamm/parameters/standard_current_functions/base_current.py b/pybamm/parameters/standard_current_functions/base_current.py index 3eb6cfdf2c..2f239d00b7 100644 --- a/pybamm/parameters/standard_current_functions/base_current.py +++ b/pybamm/parameters/standard_current_functions/base_current.py @@ -3,7 +3,7 @@ # -class GetCurrent(object): +class BaseCurrent(object): """ The base class for setting the input current for a simulation. The parameters dictionary holds the symbols of any paramters required to evaluate the current. diff --git a/pybamm/parameters/standard_current_functions/get_constant_current.py b/pybamm/parameters/standard_current_functions/constant_current.py similarity index 86% rename from pybamm/parameters/standard_current_functions/get_constant_current.py rename to pybamm/parameters/standard_current_functions/constant_current.py index a57203f7ac..ccfdefbd73 100644 --- a/pybamm/parameters/standard_current_functions/get_constant_current.py +++ b/pybamm/parameters/standard_current_functions/constant_current.py @@ -4,7 +4,7 @@ import pybamm -class ConstantCurrent(pybamm.GetCurrent): +class ConstantCurrent(pybamm.BaseCurrent): """ Sets a constant input current for a simulation. @@ -13,7 +13,7 @@ class ConstantCurrent(pybamm.GetCurrent): current : :class:`pybamm.Symbol` or float The size of the current in Amperes. - **Extends:"": :class:`pybamm.GetCurrent` + **Extends:"": :class:`pybamm.BaseCurrent` """ def __init__(self, current=pybamm.electrical_parameters.I_typ): diff --git a/pybamm/parameters/standard_current_functions/get_current_data.py b/pybamm/parameters/standard_current_functions/get_current_data.py deleted file mode 100644 index d683120ea3..0000000000 --- a/pybamm/parameters/standard_current_functions/get_current_data.py +++ /dev/null @@ -1,91 +0,0 @@ -# -# Load current profile from a csv file -# -import pybamm -import os -import pandas as pd -import numpy as np -import warnings -import scipy.interpolate as interp - - -class GetCurrentData(pybamm.GetCurrent): - """ - A class which loads a current profile from a csv file and creates an - interpolating function which can be called during solve. - - Parameters - ---------- - filename : str - The name of the file to load. - units : str, optional - The units of the current data which is to be loaded. Can be "[]" for - dimenionless data (default), or "[A]" for current in Amperes. - current_scale : :class:`pybamm.Symbol` or float, optional - The scale the current in Amperes if loading non-dimensional data. Default - is to use the typical current I_typ - - **Extends:"": :class:`pybamm.GetCurrent` - """ - - def __init__( - self, filename, units="[]", current_scale=pybamm.electrical_parameters.I_typ - ): - self.parameters = {"Current [A]": current_scale} - self.parameters_eval = {"Current [A]": current_scale} - - # Load data from csv - if filename: - pybamm_path = pybamm.root_dir() - data = pd.read_csv( - os.path.join(pybamm_path, "input", "drive_cycles", filename), - comment="#", - skip_blank_lines=True, - ).to_dict("list") - - self.time = np.array(data["time [s]"]) - self.units = units - self.current = np.array(data["current " + units]) - # If voltage data is present, load it into the class - try: - self.voltage = np.array(data["voltage [V]"]) - except KeyError: - self.voltage = None - else: - raise pybamm.ModelError("No input file provided for current") - - def __str__(self): - return "Current from data" - - def interpolate(self): - " Creates the interpolant from the loaded data " - # If data is dimenionless, multiply by a typical current (e.g. data - # could be C-rate and current_scale the 1C discharge current). Otherwise, - # just import the current data. - if self.units == "[]": - current = self.parameters_eval["Current [A]"] * self.current - elif self.units == "[A]": - current = self.current - else: - raise pybamm.ModelError( - "Current data must have units [A] or be dimensionless" - ) - # Interpolate using Piecewise Cubic Hermite Interpolating Polynomial - # (does not overshoot non-smooth data) - self.current_interp = interp.PchipInterpolator(self.time, current) - - def __call__(self, t): - """ - Calls the interpolating function created using the data from user-supplied - data file at time t (seconds). - """ - - if np.min(t) < self.time[0] or np.max(t) > self.time[-1]: - warnings.warn( - "Requested time ({}) is outside of the data range [{}, {}]".format( - t, self.time[0], self.time[-1] - ), - pybamm.ModelWarning, - ) - - return self.current_interp(t) diff --git a/pybamm/parameters/standard_current_functions/get_user_current.py b/pybamm/parameters/standard_current_functions/get_user_current.py index 24ef792b0d..c4c01b13bc 100644 --- a/pybamm/parameters/standard_current_functions/get_user_current.py +++ b/pybamm/parameters/standard_current_functions/get_user_current.py @@ -4,7 +4,7 @@ import pybamm -class UserCurrent(pybamm.GetCurrent): +class UserCurrent(pybamm.BaseCurrent): """ Sets a user-defined function as the input current for a simulation. @@ -16,7 +16,7 @@ class UserCurrent(pybamm.GetCurrent): any keyword arguments, i.e. function(t, **kwargs). **kwargs : Any keyword arguments required by function. - **Extends:"": :class:`pybamm.GetCurrent` + **Extends:"": :class:`pybamm.BaseCurrent` """ def __init__(self, function, **kwargs): diff --git a/pybamm/parameters/standard_current_functions/user_current.py b/pybamm/parameters/standard_current_functions/user_current.py new file mode 100644 index 0000000000..c4c01b13bc --- /dev/null +++ b/pybamm/parameters/standard_current_functions/user_current.py @@ -0,0 +1,31 @@ +# +# Allow a user-defined current function +# +import pybamm + + +class UserCurrent(pybamm.BaseCurrent): + """ + Sets a user-defined function as the input current for a simulation. + + Parameters + ---------- + function : method + The method which returns the current (in Amperes) as a function of time + (in seconds). The first argument of function must be time, followed by + any keyword arguments, i.e. function(t, **kwargs). + **kwargs : Any keyword arguments required by function. + + **Extends:"": :class:`pybamm.BaseCurrent` + """ + + def __init__(self, function, **kwargs): + self.parameters = kwargs + self.parameters_eval = kwargs + self.function = function + + def __str__(self): + return "User defined current" + + def __call__(self, t): + return self.function(t, **self.parameters_eval) diff --git a/results/drive_cycles/US06_simulation.py b/results/drive_cycles/US06_simulation.py index 3f5ae2bb64..70edc7fef7 100644 --- a/results/drive_cycles/US06_simulation.py +++ b/results/drive_cycles/US06_simulation.py @@ -13,7 +13,7 @@ # load parameter values and process model and geometry param = model.default_parameter_values -param["Current function"] = pybamm.GetCurrentData("US06.csv", units="[A]") +param["Current function"] = "[current data]US06" param.process_model(model) param.process_geometry(geometry) @@ -31,7 +31,7 @@ t_eval = np.linspace(0, 600 / tau, 600) # need to increase max solver steps if solving DAEs along with an erratic drive cycle -solver = model.default_solver +solver = pybamm.CasadiSolver(mode="fast") # model.default_solver if isinstance(solver, pybamm.DaeSolver): solver.max_steps = 10000 diff --git a/tests/unit/test_parameters/test_current_functions.py b/tests/unit/test_parameters/test_current_functions.py index 11e48cd00e..0581511bb9 100644 --- a/tests/unit/test_parameters/test_current_functions.py +++ b/tests/unit/test_parameters/test_current_functions.py @@ -9,7 +9,7 @@ class TestCurrentFunctions(unittest.TestCase): def test_base_current(self): - function = pybamm.GetCurrent() + function = pybamm.BaseCurrent() self.assertEqual(function(10), 1) def test_constant_current(self): @@ -31,23 +31,13 @@ def test_constant_current(self): self.assertIsInstance(processed_current.simplify(), pybamm.Scalar) def test_get_current_data(self): - # test units - function_list = [ - pybamm.GetCurrentData("US06.csv", units="[A]"), - pybamm.GetCurrentData("car_current.csv", units="[]", current_scale=10), - ] - for function in function_list: - function.interpolate() - # test process parameters dimensional_current = pybamm.electrical_parameters.dimensional_current_with_time parameter_values = pybamm.ParameterValues( { "Typical current [A]": 2, "Typical timescale [s]": 1, - "Current function": pybamm.GetCurrentData( - "car_current.csv", units="[]" - ), + "Current function": "[current data]car_current", } ) dimensional_current_eval = parameter_values.process_symbol(dimensional_current) @@ -55,9 +45,7 @@ def test_get_current_data(self): def current(t): return dimensional_current_eval.evaluate(t=t) - function_list.append(current) - - standard_tests = StandardCurrentFunctionTests(function_list, always_array=True) + standard_tests = StandardCurrentFunctionTests([current], always_array=True) standard_tests.test_all() def test_user_current(self): From 57404c37d050078c36ae67fef0df23c039d5b876 Mon Sep 17 00:00:00 2001 From: tinosulzer Date: Tue, 5 Nov 2019 12:41:39 -0500 Subject: [PATCH 03/15] #685 change defaults to IDAKLU or casadi --- pybamm/models/base_model.py | 2 +- pybamm/models/full_battery_models/base_battery_model.py | 2 +- pybamm/models/full_battery_models/lead_acid/full.py | 4 +++- pybamm/models/full_battery_models/lead_acid/higher_order.py | 5 ++++- pybamm/models/full_battery_models/lead_acid/loqs.py | 5 ++++- pybamm/models/full_battery_models/lithium_ion/dfn.py | 5 ++++- pybamm/models/full_battery_models/lithium_ion/spm.py | 5 ++++- pybamm/models/full_battery_models/lithium_ion/spme.py | 5 ++++- pybamm/models/submodels/electrode/base_electrode.py | 5 ++++- pybamm/models/submodels/electrode/ohm/base_ohm.py | 5 ++++- pybamm/models/submodels/electrode/ohm/full_ohm.py | 5 ++++- pybamm/models/submodels/electrode/ohm/leading_ohm.py | 5 ++++- pybamm/models/submodels/electrode/ohm/surface_form_ohm.py | 5 ++++- .../conductivity/full_stefan_maxwell_conductivity.py | 5 ++++- 14 files changed, 49 insertions(+), 14 deletions(-) diff --git a/pybamm/models/base_model.py b/pybamm/models/base_model.py index 9d192af47a..c33f89b0c3 100644 --- a/pybamm/models/base_model.py +++ b/pybamm/models/base_model.py @@ -103,7 +103,7 @@ def __init__(self, name="Unnamed model"): # Default behaviour is to use the jacobian and simplify self.use_jacobian = True self.use_simplify = True - self.convert_to_format = "python" + self.convert_to_format = "casadi" def _set_dictionary(self, dict, name): """ diff --git a/pybamm/models/full_battery_models/base_battery_model.py b/pybamm/models/full_battery_models/base_battery_model.py index a0767a4573..e3e3e19559 100644 --- a/pybamm/models/full_battery_models/base_battery_model.py +++ b/pybamm/models/full_battery_models/base_battery_model.py @@ -139,7 +139,7 @@ def default_solver(self): """ Create and return the default solver for this model """ - return pybamm.ScipySolver() + return pybamm.CasadiSolver() @property def options(self): diff --git a/pybamm/models/full_battery_models/lead_acid/full.py b/pybamm/models/full_battery_models/lead_acid/full.py index 5e13d911bf..576a79280f 100644 --- a/pybamm/models/full_battery_models/lead_acid/full.py +++ b/pybamm/models/full_battery_models/lead_acid/full.py @@ -134,5 +134,7 @@ def default_solver(self): and self.options["current collector"] == "uniform" ): return pybamm.ScipySolver() + elif pybamm.have_idaklu(): + return pybamm.IDAKLUSolver() else: - return pybamm.ScikitsDaeSolver() + return pybamm.CasadiSolver() diff --git a/pybamm/models/full_battery_models/lead_acid/higher_order.py b/pybamm/models/full_battery_models/lead_acid/higher_order.py index 4f3e424d97..39cc87ceb9 100644 --- a/pybamm/models/full_battery_models/lead_acid/higher_order.py +++ b/pybamm/models/full_battery_models/lead_acid/higher_order.py @@ -176,7 +176,10 @@ def default_solver(self): self.options["current collector"] != "uniform" or self.options["surface form"] == "algebraic" ): - return pybamm.ScikitsDaeSolver() + if pybamm.have_idaklu(): + return pybamm.IDAKLUSolver() + else: + return pybamm.CasadiSolver() else: return pybamm.ScipySolver() diff --git a/pybamm/models/full_battery_models/lead_acid/loqs.py b/pybamm/models/full_battery_models/lead_acid/loqs.py index 8814d3268c..7de7050083 100644 --- a/pybamm/models/full_battery_models/lead_acid/loqs.py +++ b/pybamm/models/full_battery_models/lead_acid/loqs.py @@ -183,6 +183,9 @@ def default_solver(self): self.options["current collector"] != "uniform" or self.options["surface form"] == "algebraic" ): - return pybamm.ScikitsDaeSolver() + if pybamm.have_idaklu(): + return pybamm.IDAKLUSolver() + else: + return pybamm.CasadiSolver() else: return pybamm.ScipySolver() diff --git a/pybamm/models/full_battery_models/lithium_ion/dfn.py b/pybamm/models/full_battery_models/lithium_ion/dfn.py index c448c048b6..bfdfc35c71 100644 --- a/pybamm/models/full_battery_models/lithium_ion/dfn.py +++ b/pybamm/models/full_battery_models/lithium_ion/dfn.py @@ -117,4 +117,7 @@ def default_solver(self): """ # Default solver to DAE - return pybamm.ScikitsDaeSolver() + if pybamm.have_idaklu(): + return pybamm.IDAKLUSolver() + else: + return pybamm.CasadiSolver() diff --git a/pybamm/models/full_battery_models/lithium_ion/spm.py b/pybamm/models/full_battery_models/lithium_ion/spm.py index dcab9c6ada..f5ddfcd659 100644 --- a/pybamm/models/full_battery_models/lithium_ion/spm.py +++ b/pybamm/models/full_battery_models/lithium_ion/spm.py @@ -128,4 +128,7 @@ def default_solver(self): if dimensionality == 0: return pybamm.ScipySolver() else: - return pybamm.ScikitsDaeSolver() + if pybamm.have_idaklu(): + return pybamm.IDAKLUSolver() + else: + return pybamm.CasadiSolver() diff --git a/pybamm/models/full_battery_models/lithium_ion/spme.py b/pybamm/models/full_battery_models/lithium_ion/spme.py index e5e6167592..383eb67cb4 100644 --- a/pybamm/models/full_battery_models/lithium_ion/spme.py +++ b/pybamm/models/full_battery_models/lithium_ion/spme.py @@ -126,4 +126,7 @@ def default_solver(self): if dimensionality == 0: return pybamm.ScipySolver() else: - return pybamm.ScikitsDaeSolver() + if pybamm.have_idaklu(): + return pybamm.IDAKLUSolver() + else: + return pybamm.CasadiSolver() diff --git a/pybamm/models/submodels/electrode/base_electrode.py b/pybamm/models/submodels/electrode/base_electrode.py index fc986a694d..86cd970404 100644 --- a/pybamm/models/submodels/electrode/base_electrode.py +++ b/pybamm/models/submodels/electrode/base_electrode.py @@ -148,4 +148,7 @@ def default_solver(self): """ Create and return the default solver for this model """ - return pybamm.ScikitsDaeSolver() + if pybamm.have_idaklu(): + return pybamm.IDAKLUSolver() + else: + return pybamm.CasadiSolver() diff --git a/pybamm/models/submodels/electrode/ohm/base_ohm.py b/pybamm/models/submodels/electrode/ohm/base_ohm.py index 780f2790f0..ec8361c0ea 100644 --- a/pybamm/models/submodels/electrode/ohm/base_ohm.py +++ b/pybamm/models/submodels/electrode/ohm/base_ohm.py @@ -49,4 +49,7 @@ def default_solver(self): """ Create and return the default solver for this model """ - return pybamm.ScikitsDaeSolver() + if pybamm.have_idaklu(): + return pybamm.IDAKLUSolver() + else: + return pybamm.CasadiSolver() diff --git a/pybamm/models/submodels/electrode/ohm/full_ohm.py b/pybamm/models/submodels/electrode/ohm/full_ohm.py index 61a10911f4..30dbac2602 100644 --- a/pybamm/models/submodels/electrode/ohm/full_ohm.py +++ b/pybamm/models/submodels/electrode/ohm/full_ohm.py @@ -108,4 +108,7 @@ def default_solver(self): """ Create and return the default solver for this model """ - return pybamm.ScikitsDaeSolver() + if pybamm.have_idaklu(): + return pybamm.IDAKLUSolver() + else: + return pybamm.CasadiSolver() diff --git a/pybamm/models/submodels/electrode/ohm/leading_ohm.py b/pybamm/models/submodels/electrode/ohm/leading_ohm.py index 654aa8399b..9f99f26cdc 100644 --- a/pybamm/models/submodels/electrode/ohm/leading_ohm.py +++ b/pybamm/models/submodels/electrode/ohm/leading_ohm.py @@ -77,4 +77,7 @@ def default_solver(self): """ Create and return the default solver for this model """ - return pybamm.ScikitsOdeSolver() + if pybamm.have_idaklu(): + return pybamm.IDAKLUSolver() + else: + return pybamm.CasadiSolver() diff --git a/pybamm/models/submodels/electrode/ohm/surface_form_ohm.py b/pybamm/models/submodels/electrode/ohm/surface_form_ohm.py index 6dad293054..61c773c8a9 100644 --- a/pybamm/models/submodels/electrode/ohm/surface_form_ohm.py +++ b/pybamm/models/submodels/electrode/ohm/surface_form_ohm.py @@ -72,4 +72,7 @@ def default_solver(self): """ Create and return the default solver for this model """ - return pybamm.ScikitsDaeSolver() + if pybamm.have_idaklu(): + return pybamm.IDAKLUSolver() + else: + return pybamm.CasadiSolver() diff --git a/pybamm/models/submodels/electrolyte/stefan_maxwell/conductivity/full_stefan_maxwell_conductivity.py b/pybamm/models/submodels/electrolyte/stefan_maxwell/conductivity/full_stefan_maxwell_conductivity.py index f4fae2f790..c6f8f8ddb9 100644 --- a/pybamm/models/submodels/electrolyte/stefan_maxwell/conductivity/full_stefan_maxwell_conductivity.py +++ b/pybamm/models/submodels/electrolyte/stefan_maxwell/conductivity/full_stefan_maxwell_conductivity.py @@ -71,4 +71,7 @@ def default_solver(self): """ Create and return the default solver for this model """ - return pybamm.ScikitsDaeSolver() + if pybamm.have_idaklu(): + return pybamm.IDAKLUSolver() + else: + return pybamm.CasadiSolver() From 53c0b56c7c2086648bda0926534f58cf9a177e5e Mon Sep 17 00:00:00 2001 From: tinosulzer Date: Tue, 5 Nov 2019 12:52:09 -0500 Subject: [PATCH 04/15] #685 remove skips from tests as they should use casadi --- pybamm/solvers/idaklu_solver.py | 2 +- pybamm/solvers/scikits_ode_solver.py | 2 +- .../test_lead_acid/test_asymptotics_convergence.py | 1 - .../test_lead_acid/test_compare_outputs.py | 1 - .../test_lead_acid/test_composite.py | 1 - .../test_full_battery_models/test_lead_acid/test_foqs.py | 1 - .../test_full_battery_models/test_lead_acid/test_full.py | 5 ----- .../test_side_reactions/test_composite_side_reactions.py | 5 +---- .../test_side_reactions/test_full_side_reactions.py | 6 +----- .../test_side_reactions/test_loqs_side_reactions.py | 5 +---- .../test_full_battery_models/test_lithium_ion/test_dfn.py | 3 --- .../test_full_battery_models/test_lithium_ion/test_spm.py | 6 +----- .../test_full_battery_models/test_lithium_ion/test_spme.py | 2 -- tests/integration/test_quick_plot.py | 2 -- tests/integration/test_solvers/test_idaklu.py | 2 +- .../test_lead_acid/test_composite.py | 2 -- .../test_full_battery_models/test_lead_acid/test_full.py | 2 -- .../test_full_battery_models/test_lead_acid/test_loqs.py | 1 - .../test_full_battery_models/test_lithium_ion/test_dfn.py | 7 ------- .../test_full_battery_models/test_lithium_ion/test_spm.py | 7 ------- .../test_full_battery_models/test_lithium_ion/test_spme.py | 7 ------- tests/unit/test_solvers/test_idaklu_solver.py | 2 +- tests/unit/test_solvers/test_scikits_solvers.py | 2 +- 23 files changed, 9 insertions(+), 65 deletions(-) diff --git a/pybamm/solvers/idaklu_solver.py b/pybamm/solvers/idaklu_solver.py index 716e20b70c..e5b2ecdca1 100644 --- a/pybamm/solvers/idaklu_solver.py +++ b/pybamm/solvers/idaklu_solver.py @@ -14,7 +14,7 @@ def have_idaklu(): - return idaklu_spec is None + return idaklu_spec is not None class IDAKLUSolver(pybamm.DaeSolver): diff --git a/pybamm/solvers/scikits_ode_solver.py b/pybamm/solvers/scikits_ode_solver.py index 6fbe70127d..1f8b78b5e8 100644 --- a/pybamm/solvers/scikits_ode_solver.py +++ b/pybamm/solvers/scikits_ode_solver.py @@ -16,7 +16,7 @@ def have_scikits_odes(): - return scikits_odes_spec is None + return scikits_odes_spec is not None class ScikitsOdeSolver(pybamm.OdeSolver): diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_asymptotics_convergence.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_asymptotics_convergence.py index 62cf64f8f1..7efc5b9729 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_asymptotics_convergence.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_asymptotics_convergence.py @@ -8,7 +8,6 @@ class TestAsymptoticConvergence(unittest.TestCase): - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_leading_order_convergence(self): """ Check that the leading-order model solution converges linearly in C_e to the diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_compare_outputs.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_compare_outputs.py index 5dbd216562..aa31ad8386 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_compare_outputs.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_compare_outputs.py @@ -7,7 +7,6 @@ from tests import StandardOutputComparison -@unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") class TestCompareOutputs(unittest.TestCase): def test_compare_averages_asymptotics(self): """ diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_composite.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_composite.py index 97feb0c297..1b96658772 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_composite.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_composite.py @@ -55,7 +55,6 @@ def test_basic_processing_differential(self): modeltest = tests.StandardModelTest(model, parameter_values=param) modeltest.test_all() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_basic_processing_algebraic(self): options = {"surface form": "algebraic"} model = pybamm.lead_acid.Composite(options) diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_foqs.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_foqs.py index 737a408dc6..8bb33e789e 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_foqs.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_foqs.py @@ -64,7 +64,6 @@ def test_basic_processing_differential(self): modeltest = tests.StandardModelTest(model, parameter_values=param) modeltest.test_all() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_basic_processing_algebraic(self): options = { "surface form": "algebraic", diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_full.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_full.py index e09ec47eaa..6d05b7cc74 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_full.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_full.py @@ -9,14 +9,12 @@ class TestLeadAcidFull(unittest.TestCase): - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_basic_processing(self): options = {"thermal": "isothermal"} model = pybamm.lead_acid.Full(options) modeltest = tests.StandardModelTest(model) modeltest.test_all(t_eval=np.linspace(0, 0.6)) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_basic_processing_with_convection(self): options = {"thermal": "isothermal", "convection": True} model = pybamm.lead_acid.Full(options) @@ -40,7 +38,6 @@ def test_optimisations(self): np.testing.assert_array_almost_equal(original, simp_and_known) np.testing.assert_array_almost_equal(original, simp_and_python) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_set_up(self): options = {"thermal": "isothermal"} model = pybamm.lead_acid.Full(options) @@ -58,7 +55,6 @@ def test_basic_processing_differential(self): modeltest = tests.StandardModelTest(model) modeltest.test_all() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_basic_processing_algebraic(self): options = {"surface form": "algebraic"} model = pybamm.lead_acid.Full(options) @@ -78,7 +74,6 @@ def test_optimisations(self): np.testing.assert_array_almost_equal(original, using_known_evals) np.testing.assert_array_almost_equal(original, simp_and_known, decimal=5) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_set_up(self): options = {"surface form": "differential"} model = pybamm.lead_acid.Full(options) diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_composite_side_reactions.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_composite_side_reactions.py index e172dcd3d1..ab27afcc30 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_composite_side_reactions.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_composite_side_reactions.py @@ -15,7 +15,6 @@ def test_basic_processing_differential(self): modeltest = tests.StandardModelTest(model) modeltest.test_all(skip_output_tests=True) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_basic_processing_algebraic(self): options = {"side reactions": ["oxygen"], "surface form": "algebraic"} model = pybamm.lead_acid.Composite(options) @@ -36,9 +35,7 @@ def test_basic_processing_zero_current(self): options = {"side reactions": ["oxygen"], "surface form": "differential"} model = pybamm.lead_acid.Composite(options) parameter_values = model.default_parameter_values - parameter_values.update( - {"Current function": pybamm.ConstantCurrent(current=0)} - ) + parameter_values.update({"Current function": pybamm.ConstantCurrent(current=0)}) modeltest = tests.StandardModelTest(model, parameter_values=parameter_values) modeltest.test_all(skip_output_tests=True) diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_full_side_reactions.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_full_side_reactions.py index 0478e4c07d..7ea41e2e34 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_full_side_reactions.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_full_side_reactions.py @@ -9,7 +9,6 @@ class TestLeadAcidFullSideReactions(unittest.TestCase): - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_basic_processing(self): options = {"side reactions": ["oxygen"]} model = pybamm.lead_acid.Full(options) @@ -22,7 +21,6 @@ def test_basic_processing_differential(self): modeltest = tests.StandardModelTest(model) modeltest.test_all(skip_output_tests=True) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_basic_processing_algebraic(self): options = {"side reactions": ["oxygen"], "surface form": "algebraic"} model = pybamm.lead_acid.Full(options) @@ -43,9 +41,7 @@ def test_basic_processing_zero_current(self): options = {"side reactions": ["oxygen"], "surface form": "differential"} model = pybamm.lead_acid.Full(options) parameter_values = model.default_parameter_values - parameter_values.update( - {"Current function": pybamm.ConstantCurrent(current=0)} - ) + parameter_values.update({"Current function": pybamm.ConstantCurrent(current=0)}) modeltest = tests.StandardModelTest(model, parameter_values=parameter_values) modeltest.test_all(skip_output_tests=True) diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_loqs_side_reactions.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_loqs_side_reactions.py index 4c6a15c511..50685e37b9 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_loqs_side_reactions.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_side_reactions/test_loqs_side_reactions.py @@ -23,7 +23,6 @@ def test_discharge_differential_varying_surface_area(self): modeltest = tests.StandardModelTest(model) modeltest.test_all() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_discharge_algebraic(self): options = {"surface form": "algebraic", "side reactions": ["oxygen"]} model = pybamm.lead_acid.LOQS(options) @@ -44,9 +43,7 @@ def test_zero_current(self): options = {"surface form": "differential", "side reactions": ["oxygen"]} model = pybamm.lead_acid.LOQS(options) parameter_values = model.default_parameter_values - parameter_values.update( - {"Current function": pybamm.ConstantCurrent(current=0)} - ) + parameter_values.update({"Current function": pybamm.ConstantCurrent(current=0)}) modeltest = tests.StandardModelTest(model, parameter_values=parameter_values) modeltest.test_all(skip_output_tests=True) diff --git a/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_dfn.py b/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_dfn.py index 9dd672ebec..b8ac651251 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_dfn.py +++ b/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_dfn.py @@ -8,7 +8,6 @@ import unittest -@unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") class TestDFN(unittest.TestCase): def test_basic_processing(self): options = {"thermal": "isothermal"} @@ -18,7 +17,6 @@ def test_basic_processing(self): modeltest = tests.StandardModelTest(model, var_pts=var_pts) modeltest.test_all() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_basic_processing_1plus1D(self): options = {"current collector": "potential pair", "dimensionality": 1} model = pybamm.lithium_ion.DFN(options) @@ -35,7 +33,6 @@ def test_basic_processing_1plus1D(self): modeltest = tests.StandardModelTest(model, var_pts=var_pts) modeltest.test_all(skip_output_tests=True) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_basic_processing_2plus1D(self): options = {"current collector": "potential pair", "dimensionality": 2} model = pybamm.lithium_ion.DFN(options) diff --git a/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_spm.py b/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_spm.py index d9e8f696e5..3f77fa6e85 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_spm.py +++ b/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_spm.py @@ -14,7 +14,6 @@ def test_basic_processing(self): modeltest = tests.StandardModelTest(model) modeltest.test_all() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_basic_processing_1plus1D(self): options = {"current collector": "potential pair", "dimensionality": 1} model = pybamm.lithium_ion.SPM(options) @@ -31,7 +30,6 @@ def test_basic_processing_1plus1D(self): modeltest = tests.StandardModelTest(model, var_pts=var_pts) modeltest.test_all(skip_output_tests=True) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_basic_processing_2plus1D(self): options = {"current collector": "potential pair", "dimensionality": 2} model = pybamm.lithium_ion.SPM(options) @@ -83,9 +81,7 @@ def test_zero_current(self): options = {"thermal": "isothermal"} model = pybamm.lithium_ion.SPM(options) parameter_values = model.default_parameter_values - parameter_values.update( - {"Current function": pybamm.ConstantCurrent(current=0)} - ) + parameter_values.update({"Current function": pybamm.ConstantCurrent(current=0)}) modeltest = tests.StandardModelTest(model, parameter_values=parameter_values) modeltest.test_all() diff --git a/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_spme.py b/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_spme.py index 46199f70d8..0dc59f881c 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_spme.py +++ b/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_spme.py @@ -15,7 +15,6 @@ def test_basic_processing(self): modeltest = tests.StandardModelTest(model) modeltest.test_all() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_basic_processing_1plus1D(self): options = {"current collector": "potential pair", "dimensionality": 1} model = pybamm.lithium_ion.SPMe(options) @@ -32,7 +31,6 @@ def test_basic_processing_1plus1D(self): modeltest = tests.StandardModelTest(model, var_pts=var_pts) modeltest.test_all(skip_output_tests=True) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_basic_processing_2plus1D(self): options = {"current collector": "potential pair", "dimensionality": 2} model = pybamm.lithium_ion.SPMe(options) diff --git a/tests/integration/test_quick_plot.py b/tests/integration/test_quick_plot.py index 8863d5b89e..0ebc03d08b 100644 --- a/tests/integration/test_quick_plot.py +++ b/tests/integration/test_quick_plot.py @@ -8,7 +8,6 @@ class TestQuickPlot(unittest.TestCase): Tests that QuickPlot is created correctly """ - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_plot_lithium_ion(self): spm = pybamm.lithium_ion.SPM() spme = pybamm.lithium_ion.SPMe() @@ -73,7 +72,6 @@ def test_plot_lithium_ion(self): quick_plot.update(0.01) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_plot_lead_acid(self): loqs = pybamm.lead_acid.LOQS() geometry = loqs.default_geometry diff --git a/tests/integration/test_solvers/test_idaklu.py b/tests/integration/test_solvers/test_idaklu.py index b8fcca1c34..ac00023692 100644 --- a/tests/integration/test_solvers/test_idaklu.py +++ b/tests/integration/test_solvers/test_idaklu.py @@ -4,7 +4,7 @@ import unittest -@unittest.skipIf(pybamm.have_idaklu(), "idaklu solver is not installed") +@unittest.skipIf(~pybamm.have_idaklu(), "idaklu solver is not installed") class TestIDAKLUSolver(unittest.TestCase): def test_on_spme(self): model = pybamm.lithium_ion.SPMe() diff --git a/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_composite.py b/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_composite.py index 33a86fc467..3e3c3b3190 100644 --- a/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_composite.py +++ b/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_composite.py @@ -22,7 +22,6 @@ def test_well_posed_differential(self): class TestLeadAcidCompositeMultiDimensional(unittest.TestCase): - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_well_posed(self): model = pybamm.lead_acid.Composite( {"dimensionality": 1, "current collector": "potential pair"} @@ -58,7 +57,6 @@ def test_well_posed_differential(self): model = pybamm.lead_acid.Composite(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_well_posed_algebraic(self): options = {"surface form": "algebraic", "side reactions": ["oxygen"]} model = pybamm.lead_acid.Composite(options) diff --git a/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_full.py b/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_full.py index 8683ec464c..785e7f6d12 100644 --- a/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_full.py +++ b/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_full.py @@ -15,7 +15,6 @@ def test_well_posed_with_convection(self): model = pybamm.lead_acid.Full(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_default_solver(self): model = pybamm.lead_acid.Full() self.assertIsInstance(model.default_solver, pybamm.ScikitsDaeSolver) @@ -37,7 +36,6 @@ def test_well_posed_algebraic(self): model = pybamm.lead_acid.Full(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_default_solver(self): options = {"surface form": "differential"} model = pybamm.lead_acid.Full(options) diff --git a/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_loqs.py b/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_loqs.py index c4bbfd75a5..e48ad9f8be 100644 --- a/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_loqs.py +++ b/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_loqs.py @@ -146,7 +146,6 @@ def test_well_posed_1plus1D(self): model = pybamm.lead_acid.LOQS(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_default_solver(self): options = {"surface form": "differential"} model = pybamm.lead_acid.LOQS(options) diff --git a/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_dfn.py b/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_dfn.py index 3fb5480675..7e1384c4e6 100644 --- a/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_dfn.py +++ b/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_dfn.py @@ -48,7 +48,6 @@ def test_x_full_thermal_model_no_current_collector(self): with self.assertRaises(NotImplementedError): model = pybamm.lithium_ion.DFN(options) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_x_full_Nplus1D_not_implemented(self): # 1plus1D options = { @@ -91,7 +90,6 @@ def test_x_lumped_thermal_model_0D_current_collector(self): model = pybamm.lithium_ion.DFN(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_xyz_lumped_thermal_1D_current_collector(self): options = { "current collector": "potential pair", @@ -109,7 +107,6 @@ def test_xyz_lumped_thermal_1D_current_collector(self): model = pybamm.lithium_ion.DFN(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_xyz_lumped_thermal_2D_current_collector(self): options = { "current collector": "potential pair", @@ -127,7 +124,6 @@ def test_xyz_lumped_thermal_2D_current_collector(self): model = pybamm.lithium_ion.DFN(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_x_lumped_thermal_1D_current_collector(self): options = { "current collector": "potential pair", @@ -137,7 +133,6 @@ def test_x_lumped_thermal_1D_current_collector(self): model = pybamm.lithium_ion.DFN(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_x_lumped_thermal_2D_current_collector(self): options = { "current collector": "potential pair", @@ -147,7 +142,6 @@ def test_x_lumped_thermal_2D_current_collector(self): model = pybamm.lithium_ion.DFN(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_x_lumped_thermal_set_temperature_1D(self): options = { "current collector": "potential pair", @@ -165,7 +159,6 @@ def test_x_lumped_thermal_set_temperature_1D(self): with self.assertRaises(NotImplementedError): model = pybamm.lithium_ion.DFN(options) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_default_solver(self): options = {"thermal": "isothermal"} model = pybamm.lithium_ion.DFN(options) diff --git a/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spm.py b/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spm.py index 6600c68c9d..2ddefc7022 100644 --- a/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spm.py +++ b/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spm.py @@ -75,7 +75,6 @@ def test_x_full_thermal_model_no_current_collector(self): with self.assertRaises(NotImplementedError): model = pybamm.lithium_ion.SPM(options) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_x_full_Nplus1D_not_implemented(self): # 1plus1D options = { @@ -118,7 +117,6 @@ def test_x_lumped_thermal_model_0D_current_collector(self): model = pybamm.lithium_ion.SPM(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_xyz_lumped_thermal_1D_current_collector(self): options = { "current collector": "potential pair", @@ -136,7 +134,6 @@ def test_xyz_lumped_thermal_1D_current_collector(self): model = pybamm.lithium_ion.SPM(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_xyz_lumped_thermal_2D_current_collector(self): options = { "current collector": "potential pair", @@ -154,7 +151,6 @@ def test_xyz_lumped_thermal_2D_current_collector(self): model = pybamm.lithium_ion.SPM(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_x_lumped_thermal_1D_current_collector(self): options = { "current collector": "potential pair", @@ -164,7 +160,6 @@ def test_x_lumped_thermal_1D_current_collector(self): model = pybamm.lithium_ion.SPM(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_x_lumped_thermal_2D_current_collector(self): options = { "current collector": "potential pair", @@ -174,7 +169,6 @@ def test_x_lumped_thermal_2D_current_collector(self): model = pybamm.lithium_ion.SPM(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_x_lumped_thermal_set_temperature_1D(self): options = { "current collector": "potential pair", @@ -192,7 +186,6 @@ def test_x_lumped_thermal_set_temperature_1D(self): with self.assertRaises(NotImplementedError): model = pybamm.lithium_ion.SPM(options) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_default_solver(self): options = {"thermal": "isothermal"} model = pybamm.lithium_ion.SPM(options) diff --git a/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spme.py b/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spme.py index 53f2fee5a7..60ef953623 100644 --- a/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spme.py +++ b/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spme.py @@ -62,7 +62,6 @@ def test_x_full_thermal_model_no_current_collector(self): with self.assertRaises(NotImplementedError): model = pybamm.lithium_ion.SPMe(options) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_x_full_Nplus1D_not_implemented(self): # 1plus1D options = { @@ -105,7 +104,6 @@ def test_x_lumped_thermal_model_0D_current_collector(self): model = pybamm.lithium_ion.SPMe(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_xyz_lumped_thermal_1D_current_collector(self): options = { "current collector": "potential pair", @@ -123,7 +121,6 @@ def test_xyz_lumped_thermal_1D_current_collector(self): model = pybamm.lithium_ion.SPMe(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_xyz_lumped_thermal_2D_current_collector(self): options = { "current collector": "potential pair", @@ -133,7 +130,6 @@ def test_xyz_lumped_thermal_2D_current_collector(self): model = pybamm.lithium_ion.SPMe(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_x_lumped_thermal_1D_current_collector(self): options = { "current collector": "potential pair", @@ -151,7 +147,6 @@ def test_x_lumped_thermal_1D_current_collector(self): model = pybamm.lithium_ion.SPMe(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_x_lumped_thermal_2D_current_collector(self): options = { "current collector": "potential pair", @@ -161,7 +156,6 @@ def test_x_lumped_thermal_2D_current_collector(self): model = pybamm.lithium_ion.SPMe(options) model.check_well_posedness() - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_x_lumped_thermal_set_temperature_1D(self): options = { "current collector": "potential pair", @@ -179,7 +173,6 @@ def test_x_lumped_thermal_set_temperature_1D(self): with self.assertRaises(NotImplementedError): model = pybamm.lithium_ion.SPMe(options) - @unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") def test_default_solver(self): options = {"thermal": "isothermal"} model = pybamm.lithium_ion.SPMe(options) diff --git a/tests/unit/test_solvers/test_idaklu_solver.py b/tests/unit/test_solvers/test_idaklu_solver.py index 6d7977a8b7..4cf4f5af02 100644 --- a/tests/unit/test_solvers/test_idaklu_solver.py +++ b/tests/unit/test_solvers/test_idaklu_solver.py @@ -7,7 +7,7 @@ import unittest -@unittest.skipIf(pybamm.have_idaklu(), "idaklu solver is not installed") +@unittest.skipIf(~pybamm.have_idaklu(), "idaklu solver is not installed") class TestIDAKLUSolver(unittest.TestCase): def test_ida_roberts_klu(self): # this test implements a python version of the ida Roberts diff --git a/tests/unit/test_solvers/test_scikits_solvers.py b/tests/unit/test_solvers/test_scikits_solvers.py index b264921202..f9c4e5395e 100644 --- a/tests/unit/test_solvers/test_scikits_solvers.py +++ b/tests/unit/test_solvers/test_scikits_solvers.py @@ -9,7 +9,7 @@ from tests import get_mesh_for_testing, get_discretisation_for_testing -@unittest.skipIf(pybamm.have_scikits_odes(), "scikits.odes not installed") +@unittest.skipIf(~pybamm.have_scikits_odes(), "scikits.odes not installed") class TestScikitsSolvers(unittest.TestCase): def test_ode_integrate(self): # Constant From f632714c9b06b14c119041a43c8920e1acc2ec3d Mon Sep 17 00:00:00 2001 From: tinosulzer Date: Wed, 6 Nov 2019 08:44:28 -0500 Subject: [PATCH 05/15] #685 move default solver to base model --- pybamm/models/base_model.py | 11 +++++++++++ .../full_battery_models/base_battery_model.py | 7 ------- .../full_battery_models/lead_acid/full.py | 16 ---------------- .../lead_acid/higher_order.py | 17 ----------------- .../full_battery_models/lead_acid/loqs.py | 17 ----------------- .../full_battery_models/lithium_ion/dfn.py | 12 ------------ .../full_battery_models/lithium_ion/spm.py | 15 --------------- .../full_battery_models/lithium_ion/spme.py | 15 --------------- .../effective_resistance_current_collector.py | 4 ---- .../submodels/electrode/base_electrode.py | 10 ---------- .../models/submodels/electrode/ohm/base_ohm.py | 10 ---------- .../models/submodels/electrode/ohm/full_ohm.py | 10 ---------- .../submodels/electrode/ohm/leading_ohm.py | 10 ---------- .../submodels/electrode/ohm/surface_form_ohm.py | 10 ---------- .../full_stefan_maxwell_conductivity.py | 10 ---------- 15 files changed, 11 insertions(+), 163 deletions(-) diff --git a/pybamm/models/base_model.py b/pybamm/models/base_model.py index c33f89b0c3..a65a171725 100644 --- a/pybamm/models/base_model.py +++ b/pybamm/models/base_model.py @@ -479,3 +479,14 @@ def check_variables(self): var ) ) + + @property + def default_solver(self): + "Return default solver based on whether model is ODE model or DAE model" + if len(self.algebraic) == 0: + return pybamm.ScipySolver() + elif pybamm.have_idaklu(): + return pybamm.IDAKLUSolver() + else: + return pybamm.CasadiSolver() + diff --git a/pybamm/models/full_battery_models/base_battery_model.py b/pybamm/models/full_battery_models/base_battery_model.py index e3e3e19559..a6b0a7779a 100644 --- a/pybamm/models/full_battery_models/base_battery_model.py +++ b/pybamm/models/full_battery_models/base_battery_model.py @@ -134,13 +134,6 @@ def default_spatial_methods(self): base_spatial_methods["current collector"] = pybamm.ScikitFiniteElement return base_spatial_methods - @property - def default_solver(self): - """ - Create and return the default solver for this model - """ - return pybamm.CasadiSolver() - @property def options(self): return self._options diff --git a/pybamm/models/full_battery_models/lead_acid/full.py b/pybamm/models/full_battery_models/lead_acid/full.py index 576a79280f..056a3efc31 100644 --- a/pybamm/models/full_battery_models/lead_acid/full.py +++ b/pybamm/models/full_battery_models/lead_acid/full.py @@ -122,19 +122,3 @@ def set_side_reaction_submodels(self): self.submodels[ "negative oxygen interface" ] = pybamm.interface.lead_acid_oxygen.NoReaction(self.param, "Negative") - - @property - def default_solver(self): - """ - Create and return the default solver for this model - """ - # Different solver depending on whether we solve ODEs or DAEs - if ( - self.options["surface form"] == "differential" - and self.options["current collector"] == "uniform" - ): - return pybamm.ScipySolver() - elif pybamm.have_idaklu(): - return pybamm.IDAKLUSolver() - else: - return pybamm.CasadiSolver() diff --git a/pybamm/models/full_battery_models/lead_acid/higher_order.py b/pybamm/models/full_battery_models/lead_acid/higher_order.py index 39cc87ceb9..a03afdc51b 100644 --- a/pybamm/models/full_battery_models/lead_acid/higher_order.py +++ b/pybamm/models/full_battery_models/lead_acid/higher_order.py @@ -166,23 +166,6 @@ def set_full_porosity_submodel(self): """ self.submodels["full porosity"] = pybamm.porosity.Full(self.param) - @property - def default_solver(self): - """ - Create and return the default solver for this model - """ - # Different solver depending on whether we solve ODEs or DAEs - if ( - self.options["current collector"] != "uniform" - or self.options["surface form"] == "algebraic" - ): - if pybamm.have_idaklu(): - return pybamm.IDAKLUSolver() - else: - return pybamm.CasadiSolver() - else: - return pybamm.ScipySolver() - class FOQS(BaseHigherOrderModel): """First-order quasi-static model for lead-acid, from [1]_. diff --git a/pybamm/models/full_battery_models/lead_acid/loqs.py b/pybamm/models/full_battery_models/lead_acid/loqs.py index 7de7050083..cf6bea3ed1 100644 --- a/pybamm/models/full_battery_models/lead_acid/loqs.py +++ b/pybamm/models/full_battery_models/lead_acid/loqs.py @@ -172,20 +172,3 @@ def set_side_reaction_submodels(self): self.reaction_submodels["Positive"].append( self.submodels["leading-order positive oxygen interface"] ) - - @property - def default_solver(self): - """ - Create and return the default solver for this model - """ - - if ( - self.options["current collector"] != "uniform" - or self.options["surface form"] == "algebraic" - ): - if pybamm.have_idaklu(): - return pybamm.IDAKLUSolver() - else: - return pybamm.CasadiSolver() - else: - return pybamm.ScipySolver() diff --git a/pybamm/models/full_battery_models/lithium_ion/dfn.py b/pybamm/models/full_battery_models/lithium_ion/dfn.py index bfdfc35c71..6268229624 100644 --- a/pybamm/models/full_battery_models/lithium_ion/dfn.py +++ b/pybamm/models/full_battery_models/lithium_ion/dfn.py @@ -109,15 +109,3 @@ def default_geometry(self): return pybamm.Geometry("1+1D macro", "(1+1)+1D micro") elif dimensionality == 2: return pybamm.Geometry("2+1D macro", "(2+1)+1D micro") - - @property - def default_solver(self): - """ - Create and return the default solver for this model - """ - - # Default solver to DAE - if pybamm.have_idaklu(): - return pybamm.IDAKLUSolver() - else: - return pybamm.CasadiSolver() diff --git a/pybamm/models/full_battery_models/lithium_ion/spm.py b/pybamm/models/full_battery_models/lithium_ion/spm.py index f5ddfcd659..d11f38abe1 100644 --- a/pybamm/models/full_battery_models/lithium_ion/spm.py +++ b/pybamm/models/full_battery_models/lithium_ion/spm.py @@ -117,18 +117,3 @@ def default_geometry(self): return pybamm.Geometry("1+1D macro", "(1+0)+1D micro") elif dimensionality == 2: return pybamm.Geometry("2+1D macro", "(2+0)+1D micro") - - @property - def default_solver(self): - """ - Create and return the default solver for this model - """ - # Different solver depending on whether we solve ODEs or DAEs - dimensionality = self.options["dimensionality"] - if dimensionality == 0: - return pybamm.ScipySolver() - else: - if pybamm.have_idaklu(): - return pybamm.IDAKLUSolver() - else: - return pybamm.CasadiSolver() diff --git a/pybamm/models/full_battery_models/lithium_ion/spme.py b/pybamm/models/full_battery_models/lithium_ion/spme.py index 383eb67cb4..974b60759d 100644 --- a/pybamm/models/full_battery_models/lithium_ion/spme.py +++ b/pybamm/models/full_battery_models/lithium_ion/spme.py @@ -115,18 +115,3 @@ def default_geometry(self): return pybamm.Geometry("1+1D macro", "(1+0)+1D micro") elif dimensionality == 2: return pybamm.Geometry("2+1D macro", "(2+0)+1D micro") - - @property - def default_solver(self): - """ - Create and return the default solver for this model - """ - # Different solver depending on whether we solve ODEs or DAEs - dimensionality = self.options["dimensionality"] - if dimensionality == 0: - return pybamm.ScipySolver() - else: - if pybamm.have_idaklu(): - return pybamm.IDAKLUSolver() - else: - return pybamm.CasadiSolver() diff --git a/pybamm/models/submodels/current_collector/effective_resistance_current_collector.py b/pybamm/models/submodels/current_collector/effective_resistance_current_collector.py index 793adeff00..a061994f12 100644 --- a/pybamm/models/submodels/current_collector/effective_resistance_current_collector.py +++ b/pybamm/models/submodels/current_collector/effective_resistance_current_collector.py @@ -224,7 +224,3 @@ def default_submesh_types(self): @property def default_spatial_methods(self): return {"current collector": pybamm.ScikitFiniteElement} - - @property - def default_solver(self): - return pybamm.AlgebraicSolver() diff --git a/pybamm/models/submodels/electrode/base_electrode.py b/pybamm/models/submodels/electrode/base_electrode.py index 86cd970404..146c8c916d 100644 --- a/pybamm/models/submodels/electrode/base_electrode.py +++ b/pybamm/models/submodels/electrode/base_electrode.py @@ -142,13 +142,3 @@ def _get_standard_whole_cell_variables(self, variables): variables = {"Electrode current density": i_s} return variables - - @property - def default_solver(self): - """ - Create and return the default solver for this model - """ - if pybamm.have_idaklu(): - return pybamm.IDAKLUSolver() - else: - return pybamm.CasadiSolver() diff --git a/pybamm/models/submodels/electrode/ohm/base_ohm.py b/pybamm/models/submodels/electrode/ohm/base_ohm.py index ec8361c0ea..b2bb673e5a 100644 --- a/pybamm/models/submodels/electrode/ohm/base_ohm.py +++ b/pybamm/models/submodels/electrode/ohm/base_ohm.py @@ -43,13 +43,3 @@ def set_boundary_conditions(self, variables): ) self.boundary_conditions[phi_s] = {"left": lbc, "right": rbc} - - @property - def default_solver(self): - """ - Create and return the default solver for this model - """ - if pybamm.have_idaklu(): - return pybamm.IDAKLUSolver() - else: - return pybamm.CasadiSolver() diff --git a/pybamm/models/submodels/electrode/ohm/full_ohm.py b/pybamm/models/submodels/electrode/ohm/full_ohm.py index 30dbac2602..fac16021bc 100644 --- a/pybamm/models/submodels/electrode/ohm/full_ohm.py +++ b/pybamm/models/submodels/electrode/ohm/full_ohm.py @@ -102,13 +102,3 @@ def set_initial_conditions(self, variables): ) self.initial_conditions[phi_s] = phi_s_init - - @property - def default_solver(self): - """ - Create and return the default solver for this model - """ - if pybamm.have_idaklu(): - return pybamm.IDAKLUSolver() - else: - return pybamm.CasadiSolver() diff --git a/pybamm/models/submodels/electrode/ohm/leading_ohm.py b/pybamm/models/submodels/electrode/ohm/leading_ohm.py index 9f99f26cdc..2cc50a6e54 100644 --- a/pybamm/models/submodels/electrode/ohm/leading_ohm.py +++ b/pybamm/models/submodels/electrode/ohm/leading_ohm.py @@ -71,13 +71,3 @@ def set_boundary_conditions(self, variables): rbc = (pybamm.Scalar(0), "Neumann") self.boundary_conditions[phi_s] = {"left": lbc, "right": rbc} - - @property - def default_solver(self): - """ - Create and return the default solver for this model - """ - if pybamm.have_idaklu(): - return pybamm.IDAKLUSolver() - else: - return pybamm.CasadiSolver() diff --git a/pybamm/models/submodels/electrode/ohm/surface_form_ohm.py b/pybamm/models/submodels/electrode/ohm/surface_form_ohm.py index 61c773c8a9..f78453e495 100644 --- a/pybamm/models/submodels/electrode/ohm/surface_form_ohm.py +++ b/pybamm/models/submodels/electrode/ohm/surface_form_ohm.py @@ -66,13 +66,3 @@ def get_coupled_variables(self, variables): variables.update(self._get_standard_whole_cell_variables(variables)) return variables - - @property - def default_solver(self): - """ - Create and return the default solver for this model - """ - if pybamm.have_idaklu(): - return pybamm.IDAKLUSolver() - else: - return pybamm.CasadiSolver() diff --git a/pybamm/models/submodels/electrolyte/stefan_maxwell/conductivity/full_stefan_maxwell_conductivity.py b/pybamm/models/submodels/electrolyte/stefan_maxwell/conductivity/full_stefan_maxwell_conductivity.py index c6f8f8ddb9..89272892c8 100644 --- a/pybamm/models/submodels/electrolyte/stefan_maxwell/conductivity/full_stefan_maxwell_conductivity.py +++ b/pybamm/models/submodels/electrolyte/stefan_maxwell/conductivity/full_stefan_maxwell_conductivity.py @@ -65,13 +65,3 @@ def set_initial_conditions(self, variables): phi_e = variables["Electrolyte potential"] T_ref = self.param.T_ref self.initial_conditions = {phi_e: -self.param.U_n(self.param.c_n_init, T_ref)} - - @property - def default_solver(self): - """ - Create and return the default solver for this model - """ - if pybamm.have_idaklu(): - return pybamm.IDAKLUSolver() - else: - return pybamm.CasadiSolver() From cc33c9569012cd06f865d1e0a70d52805ad5500c Mon Sep 17 00:00:00 2001 From: tinosulzer Date: Wed, 6 Nov 2019 08:51:48 -0500 Subject: [PATCH 06/15] #685 update (remove) solver tests --- .../effective_resistance_current_collector.py | 4 ++++ tests/unit/test_models/test_base_model.py | 7 +++++++ .../test_lead_acid/test_full.py | 12 ------------ .../test_lead_acid/test_loqs.py | 15 --------------- .../test_lithium_ion/test_dfn.py | 5 ----- .../test_lithium_ion/test_spm.py | 9 --------- .../test_lithium_ion/test_spme.py | 8 -------- 7 files changed, 11 insertions(+), 49 deletions(-) diff --git a/pybamm/models/submodels/current_collector/effective_resistance_current_collector.py b/pybamm/models/submodels/current_collector/effective_resistance_current_collector.py index a061994f12..793adeff00 100644 --- a/pybamm/models/submodels/current_collector/effective_resistance_current_collector.py +++ b/pybamm/models/submodels/current_collector/effective_resistance_current_collector.py @@ -224,3 +224,7 @@ def default_submesh_types(self): @property def default_spatial_methods(self): return {"current collector": pybamm.ScikitFiniteElement} + + @property + def default_solver(self): + return pybamm.AlgebraicSolver() diff --git a/tests/unit/test_models/test_base_model.py b/tests/unit/test_models/test_base_model.py index 1e6e54579c..3978c06844 100644 --- a/tests/unit/test_models/test_base_model.py +++ b/tests/unit/test_models/test_base_model.py @@ -374,6 +374,13 @@ def test_default_solver(self): ) self.assertIsInstance(solver, pybamm.BaseModel) + # check that adding algebraic variables gives DAE solver + a = pybamm.Variable("a") + model.algebraic = {a: a - 1} + self.assertIsInstance( + model.default_solver, (pybamm.IDAKLUSolver, pybamm.CasadiSolver) + ) + def test_default_parameters(self): # check parameters are read in ok model = pybamm.BaseBatteryModel() diff --git a/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_full.py b/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_full.py index 785e7f6d12..a30b2c76f7 100644 --- a/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_full.py +++ b/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_full.py @@ -15,10 +15,6 @@ def test_well_posed_with_convection(self): model = pybamm.lead_acid.Full(options) model.check_well_posedness() - def test_default_solver(self): - model = pybamm.lead_acid.Full() - self.assertIsInstance(model.default_solver, pybamm.ScikitsDaeSolver) - class TestLeadAcidFullSurfaceForm(unittest.TestCase): def test_well_posed_differential(self): @@ -36,14 +32,6 @@ def test_well_posed_algebraic(self): model = pybamm.lead_acid.Full(options) model.check_well_posedness() - def test_default_solver(self): - options = {"surface form": "differential"} - model = pybamm.lead_acid.Full(options) - self.assertIsInstance(model.default_solver, pybamm.ScipySolver) - options = {"surface form": "algebraic"} - model = pybamm.lead_acid.Full(options) - self.assertIsInstance(model.default_solver, pybamm.ScikitsDaeSolver) - class TestLeadAcidFullSideReactions(unittest.TestCase): def test_well_posed(self): diff --git a/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_loqs.py b/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_loqs.py index e48ad9f8be..89e76f1801 100644 --- a/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_loqs.py +++ b/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_loqs.py @@ -146,21 +146,6 @@ def test_well_posed_1plus1D(self): model = pybamm.lead_acid.LOQS(options) model.check_well_posedness() - def test_default_solver(self): - options = {"surface form": "differential"} - model = pybamm.lead_acid.LOQS(options) - self.assertIsInstance(model.default_solver, pybamm.ScipySolver) - options = { - "surface form": "differential", - "current collector": "potential pair", - "dimensionality": 1, - } - model = pybamm.lead_acid.LOQS(options) - self.assertIsInstance(model.default_solver, pybamm.ScikitsDaeSolver) - options = {"surface form": "algebraic"} - model = pybamm.lead_acid.LOQS(options) - self.assertIsInstance(model.default_solver, pybamm.ScikitsDaeSolver) - def test_default_geometry(self): options = {"surface form": "differential"} model = pybamm.lead_acid.LOQS(options) diff --git a/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_dfn.py b/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_dfn.py index 7e1384c4e6..4fcabbccb0 100644 --- a/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_dfn.py +++ b/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_dfn.py @@ -159,11 +159,6 @@ def test_x_lumped_thermal_set_temperature_1D(self): with self.assertRaises(NotImplementedError): model = pybamm.lithium_ion.DFN(options) - def test_default_solver(self): - options = {"thermal": "isothermal"} - model = pybamm.lithium_ion.DFN(options) - self.assertIsInstance(model.default_solver, pybamm.ScikitsDaeSolver) - def test_particle_fast_diffusion(self): options = {"particle": "fast diffusion"} model = pybamm.lithium_ion.DFN(options) diff --git a/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spm.py b/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spm.py index 2ddefc7022..3115655336 100644 --- a/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spm.py +++ b/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spm.py @@ -186,15 +186,6 @@ def test_x_lumped_thermal_set_temperature_1D(self): with self.assertRaises(NotImplementedError): model = pybamm.lithium_ion.SPM(options) - def test_default_solver(self): - options = {"thermal": "isothermal"} - model = pybamm.lithium_ion.SPM(options) - self.assertIsInstance(model.default_solver, pybamm.ScipySolver) - - options = {"current collector": "potential pair", "dimensionality": 2} - model = pybamm.lithium_ion.SPM(options) - self.assertIsInstance(model.default_solver, pybamm.ScikitsDaeSolver) - def test_particle_fast_diffusion(self): options = {"particle": "fast diffusion"} model = pybamm.lithium_ion.SPM(options) diff --git a/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spme.py b/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spme.py index 60ef953623..8b73fdbffb 100644 --- a/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spme.py +++ b/tests/unit/test_models/test_full_battery_models/test_lithium_ion/test_spme.py @@ -173,14 +173,6 @@ def test_x_lumped_thermal_set_temperature_1D(self): with self.assertRaises(NotImplementedError): model = pybamm.lithium_ion.SPMe(options) - def test_default_solver(self): - options = {"thermal": "isothermal"} - model = pybamm.lithium_ion.SPMe(options) - self.assertIsInstance(model.default_solver, pybamm.ScipySolver) - options = {"current collector": "potential pair", "dimensionality": 2} - model = pybamm.lithium_ion.SPMe(options) - self.assertIsInstance(model.default_solver, pybamm.ScikitsDaeSolver) - def test_particle_fast_diffusion(self): options = {"particle": "fast diffusion"} model = pybamm.lithium_ion.SPMe(options) From 52e09a8a23d53597d40fe8dc00a5a279e9bf38de Mon Sep 17 00:00:00 2001 From: tinosulzer Date: Wed, 6 Nov 2019 08:54:52 -0500 Subject: [PATCH 07/15] #685 remove some slow tests --- .../test_lead_acid/test_composite.py | 24 -------------- .../test_lead_acid/test_foqs.py | 32 ------------------- 2 files changed, 56 deletions(-) diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_composite.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_composite.py index 1b96658772..1b81910416 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_composite.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_composite.py @@ -63,30 +63,6 @@ def test_basic_processing_algebraic(self): modeltest = tests.StandardModelTest(model, parameter_values=param) modeltest.test_all() - def test_optimisations(self): - options = {"surface form": "differential"} - model = pybamm.lead_acid.Composite(options) - optimtest = tests.OptimisationsTest(model) - - original = optimtest.evaluate_model() - simplified = optimtest.evaluate_model(simplify=True) - using_known_evals = optimtest.evaluate_model(use_known_evals=True) - simp_and_known = optimtest.evaluate_model(simplify=True, use_known_evals=True) - simp_and_python = optimtest.evaluate_model(simplify=True, to_python=True) - np.testing.assert_array_almost_equal(original, simplified) - np.testing.assert_array_almost_equal(original, using_known_evals) - np.testing.assert_array_almost_equal(original, simp_and_known) - np.testing.assert_array_almost_equal(original, simp_and_python) - - def test_set_up(self): - options = {"surface form": "differential"} - model = pybamm.lead_acid.Composite(options) - optimtest = tests.OptimisationsTest(model) - optimtest.set_up_model(simplify=False, to_python=True) - optimtest.set_up_model(simplify=True, to_python=True) - optimtest.set_up_model(simplify=False, to_python=False) - optimtest.set_up_model(simplify=True, to_python=False) - class TestLeadAcidCompositeExtended(unittest.TestCase): def test_basic_processing(self): diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_foqs.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_foqs.py index 8bb33e789e..be8c4cbca0 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_foqs.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_foqs.py @@ -76,38 +76,6 @@ def test_basic_processing_algebraic(self): modeltest = tests.StandardModelTest(model, parameter_values=param) modeltest.test_all() - def test_optimisations(self): - options = { - "surface form": "differential", - "thermal": "isothermal", - "convection": False, - } - model = pybamm.lead_acid.FOQS(options) - optimtest = tests.OptimisationsTest(model) - - original = optimtest.evaluate_model() - simplified = optimtest.evaluate_model(simplify=True) - using_known_evals = optimtest.evaluate_model(use_known_evals=True) - simp_and_known = optimtest.evaluate_model(simplify=True, use_known_evals=True) - simp_and_python = optimtest.evaluate_model(simplify=True, to_python=True) - np.testing.assert_array_almost_equal(original, simplified) - np.testing.assert_array_almost_equal(original, using_known_evals) - np.testing.assert_array_almost_equal(original, simp_and_known) - np.testing.assert_array_almost_equal(original, simp_and_python) - - def test_set_up(self): - options = { - "surface form": "differential", - "thermal": "isothermal", - "convection": False, - } - model = pybamm.lead_acid.FOQS(options) - optimtest = tests.OptimisationsTest(model) - optimtest.set_up_model(simplify=False, to_python=True) - optimtest.set_up_model(simplify=True, to_python=True) - optimtest.set_up_model(simplify=False, to_python=False) - optimtest.set_up_model(simplify=True, to_python=False) - if __name__ == "__main__": print("Add -v for more debug output") From 1175cbf6a2e17d86c801cc0d5b04f235ead7297f Mon Sep 17 00:00:00 2001 From: tinosulzer Date: Wed, 6 Nov 2019 22:01:07 -0500 Subject: [PATCH 08/15] #685 get drive cycle example working --- pybamm/expression_tree/interpolant.py | 15 +++++++++++++++ .../operations/convert_to_casadi.py | 2 +- pybamm/parameters/parameter_values.py | 4 +++- pybamm/solvers/casadi_solver.py | 1 + pybamm/solvers/dae_solver.py | 1 + results/drive_cycles/US06_simulation.py | 10 +++++----- 6 files changed, 26 insertions(+), 7 deletions(-) diff --git a/pybamm/expression_tree/interpolant.py b/pybamm/expression_tree/interpolant.py index ef3c9a54b8..d60f7b23c1 100644 --- a/pybamm/expression_tree/interpolant.py +++ b/pybamm/expression_tree/interpolant.py @@ -60,7 +60,22 @@ def __init__( interpolating_function, child, name=name, derivative="derivative" ) # Store information as attributes + self.data = data self.x = data[:, 0] self.y = data[:, 1] self.interpolator = interpolator self.extrapolate = extrapolate + + def _function_new_copy(self, children): + """ See :meth:`Function._function_new_copy()` """ + return pybamm.Interpolant( + self.data, + *children, + name=self.name, + interpolator=self.interpolator, + extrapolate=self.extrapolate, + ) + + def _function_simplify(self, simplified_children): + """ See :meth:`Function._function_new_simplify()` """ + return self._function_new_copy(simplified_children) diff --git a/pybamm/expression_tree/operations/convert_to_casadi.py b/pybamm/expression_tree/operations/convert_to_casadi.py index 50335241e5..5deac9ce59 100644 --- a/pybamm/expression_tree/operations/convert_to_casadi.py +++ b/pybamm/expression_tree/operations/convert_to_casadi.py @@ -40,7 +40,7 @@ def convert(self, symbol, t=None, y=None): def _convert(self, symbol, t, y): """ See :meth:`CasadiConverter.convert()`. """ if isinstance(symbol, (pybamm.Scalar, pybamm.Array, pybamm.Time)): - return casadi.SX(symbol.evaluate(t, y)) + return casadi.MX(symbol.evaluate(t, y)) elif isinstance(symbol, pybamm.StateVector): if y is None: diff --git a/pybamm/parameters/parameter_values.py b/pybamm/parameters/parameter_values.py index e9826c2a23..fbc388bb95 100644 --- a/pybamm/parameters/parameter_values.py +++ b/pybamm/parameters/parameter_values.py @@ -170,13 +170,15 @@ def update(self, values, check_conflict=False, path=""): pybamm.root_dir(), "input", "drive_cycles" ) filename = os.path.join(data_path, value[14:] + ".csv") + function_name = value[14:] else: filename = os.path.join(path, value[6:] + ".csv") + function_name = value[6:] data = pd.read_csv( filename, comment="#", skip_blank_lines=True ).to_numpy() # Save name and data - self.setitemsuper(name, (value[6:], data)) + self.setitemsuper(name, (function_name, data)) # Anything else should be a converted to a float else: self.setitemsuper(name, float(value)) diff --git a/pybamm/solvers/casadi_solver.py b/pybamm/solvers/casadi_solver.py index b31b5f32e8..c14f49802b 100644 --- a/pybamm/solvers/casadi_solver.py +++ b/pybamm/solvers/casadi_solver.py @@ -226,6 +226,7 @@ def integrate_casadi(self, problem, y0, t_eval, mass_matrix=None): "reltol": self.rtol, "abstol": self.atol, "output_t0": True, + "max_num_steps": self.max_steps, } options.update(self.extra_options) if self.method == "idas": diff --git a/pybamm/solvers/dae_solver.py b/pybamm/solvers/dae_solver.py index 46f8bfb001..1ee69adfe7 100644 --- a/pybamm/solvers/dae_solver.py +++ b/pybamm/solvers/dae_solver.py @@ -329,6 +329,7 @@ def eval_event(t, y): # Create CasADi problem for the CasADi solver self.casadi_problem = { + "t": t_casadi, "x": y_diff, "z": y_alg, "ode": concatenated_rhs, diff --git a/results/drive_cycles/US06_simulation.py b/results/drive_cycles/US06_simulation.py index 70edc7fef7..64f47fd5e5 100644 --- a/results/drive_cycles/US06_simulation.py +++ b/results/drive_cycles/US06_simulation.py @@ -18,20 +18,20 @@ param.process_geometry(geometry) # set mesh -mesh = pybamm.Mesh(geometry, model.default_submesh_types, model.default_var_pts) +var = pybamm.standard_spatial_vars +var_pts = {var.x_n: 10, var.x_s: 10, var.x_p: 10, var.r_n: 5, var.r_p: 5} +mesh = pybamm.Mesh(geometry, model.default_submesh_types, var_pts) # discretise model disc = pybamm.Discretisation(mesh, model.default_spatial_methods) disc.process_model(model) # simulate US06 drive cycle -tau = param.process_symbol( - pybamm.standard_parameters_lithium_ion.tau_discharge -).evaluate(0) +tau = param.evaluate(pybamm.standard_parameters_lithium_ion.tau_discharge) t_eval = np.linspace(0, 600 / tau, 600) # need to increase max solver steps if solving DAEs along with an erratic drive cycle -solver = pybamm.CasadiSolver(mode="fast") # model.default_solver +solver = pybamm.CasadiSolver() if isinstance(solver, pybamm.DaeSolver): solver.max_steps = 10000 From 9911d4130711ac3c76edd0f861d2c7cfc5e057f6 Mon Sep 17 00:00:00 2001 From: tinosulzer Date: Thu, 7 Nov 2019 11:32:59 -0500 Subject: [PATCH 09/15] #685 fix casadi tests --- .../test_operations/test_convert_to_casadi.py | 70 +++++++++++-------- .../test_lead_acid/test_composite.py | 8 ++- 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/tests/unit/test_expression_tree/test_operations/test_convert_to_casadi.py b/tests/unit/test_expression_tree/test_operations/test_convert_to_casadi.py index 9ebc374672..7f8287591e 100644 --- a/tests/unit/test_expression_tree/test_operations/test_convert_to_casadi.py +++ b/tests/unit/test_expression_tree/test_operations/test_convert_to_casadi.py @@ -10,52 +10,58 @@ class TestCasadiConverter(unittest.TestCase): + def assert_casadi_equal(self, a, b, evalf=False): + if evalf is True: + self.assertTrue((casadi.evalf(a) - casadi.evalf(b)).is_zero()) + else: + self.assertTrue((a - b).is_zero()) + def test_convert_scalar_symbols(self): a = pybamm.Scalar(0) b = pybamm.Scalar(1) c = pybamm.Scalar(-1) d = pybamm.Scalar(2) - self.assertEqual(a.to_casadi(), casadi.SX(0)) - self.assertEqual(d.to_casadi(), casadi.SX(2)) + self.assertEqual(a.to_casadi(), casadi.MX(0)) + self.assertEqual(d.to_casadi(), casadi.MX(2)) # negate - self.assertEqual((-b).to_casadi(), casadi.SX(-1)) + self.assertEqual((-b).to_casadi(), casadi.MX(-1)) # absolute value - self.assertEqual(abs(c).to_casadi(), casadi.SX(1)) + self.assertEqual(abs(c).to_casadi(), casadi.MX(1)) # function def sin(x): return np.sin(x) f = pybamm.Function(sin, b) - self.assertEqual(f.to_casadi(), casadi.SX(np.sin(1))) + self.assertEqual(f.to_casadi(), casadi.MX(np.sin(1))) def myfunction(x, y): return x + y f = pybamm.Function(myfunction, b, d) - self.assertEqual(f.to_casadi(), casadi.SX(3)) + self.assertEqual(f.to_casadi(), casadi.MX(3)) # addition - self.assertEqual((a + b).to_casadi(), casadi.SX(1)) + self.assertEqual((a + b).to_casadi(), casadi.MX(1)) # subtraction - self.assertEqual((c - d).to_casadi(), casadi.SX(-3)) + self.assertEqual((c - d).to_casadi(), casadi.MX(-3)) # multiplication - self.assertEqual((c * d).to_casadi(), casadi.SX(-2)) + self.assertEqual((c * d).to_casadi(), casadi.MX(-2)) # power - self.assertEqual((c ** d).to_casadi(), casadi.SX(1)) + self.assertEqual((c ** d).to_casadi(), casadi.MX(1)) # division - self.assertEqual((b / d).to_casadi(), casadi.SX(1 / 2)) + self.assertEqual((b / d).to_casadi(), casadi.MX(1 / 2)) def test_convert_array_symbols(self): # Arrays a = np.array([1, 2, 3, 4, 5]) pybamm_a = pybamm.Array(a) - self.assertTrue(casadi.is_equal(pybamm_a.to_casadi(), casadi.SX(a))) + self.assert_casadi_equal(pybamm_a.to_casadi(), casadi.MX(a)) - casadi_t = casadi.SX.sym("t") - casadi_y = casadi.SX.sym("y", 10) + casadi_t = casadi.MX.sym("t") + casadi_y = casadi.MX.sym("y", 10) pybamm_t = pybamm.Time() pybamm_y = pybamm.StateVector(slice(0, 10)) @@ -64,22 +70,26 @@ def test_convert_array_symbols(self): self.assertEqual(pybamm_t.to_casadi(casadi_t, casadi_y), casadi_t) # State Vector - self.assertTrue( - casadi.is_equal(pybamm_y.to_casadi(casadi_t, casadi_y), casadi_y) - ) + self.assert_casadi_equal(pybamm_y.to_casadi(casadi_t, casadi_y), casadi_y) # outer product outer = pybamm.Outer(pybamm_a, pybamm_a) - self.assertTrue(casadi.is_equal(outer.to_casadi(), casadi.SX(outer.evaluate()))) + self.assert_casadi_equal( + outer.to_casadi(), casadi.MX(outer.evaluate()), evalf=True + ) def test_special_functions(self): a = pybamm.Array(np.array([1, 2, 3, 4, 5])) - self.assertEqual(pybamm.max(a).to_casadi(), casadi.SX(5)) - self.assertEqual(pybamm.min(a).to_casadi(), casadi.SX(1)) + self.assert_casadi_equal(pybamm.max(a).to_casadi(), casadi.MX(5), evalf=True) + self.assert_casadi_equal(pybamm.min(a).to_casadi(), casadi.MX(1), evalf=True) b = pybamm.Array(np.array([-2])) c = pybamm.Array(np.array([3])) - self.assertEqual(pybamm.Function(np.abs, b).to_casadi(), casadi.SX(2)) - self.assertEqual(pybamm.Function(np.abs, c).to_casadi(), casadi.SX(3)) + self.assert_casadi_equal( + pybamm.Function(np.abs, b).to_casadi(), casadi.MX(2), evalf=True + ) + self.assert_casadi_equal( + pybamm.Function(np.abs, c).to_casadi(), casadi.MX(3), evalf=True + ) def test_interpolation(self): x = np.linspace(0, 1)[:, np.newaxis] @@ -108,7 +118,9 @@ def test_concatenations(self): b = pybamm.Scalar(16) c = pybamm.Scalar(3) conc = pybamm.NumpyConcatenation(a, b, c) - self.assertTrue(casadi.is_equal(conc.to_casadi(), casadi.SX(conc.evaluate()))) + self.assert_casadi_equal( + conc.to_casadi(), casadi.MX(conc.evaluate()), evalf=True + ) # Domain concatenation mesh = get_mesh_for_testing() @@ -117,7 +129,9 @@ def test_concatenations(self): a = 2 * pybamm.Vector(np.ones_like(mesh[a_dom[0]][0].nodes), domain=a_dom) b = pybamm.Vector(np.ones_like(mesh[b_dom[0]][0].nodes), domain=b_dom) conc = pybamm.DomainConcatenation([b, a], mesh) - self.assertTrue(casadi.is_equal(conc.to_casadi(), casadi.SX(conc.evaluate()))) + self.assert_casadi_equal( + conc.to_casadi(), casadi.MX(conc.evaluate()), evalf=True + ) # 2d disc = get_1p1d_discretisation_for_testing() @@ -130,7 +144,7 @@ def test_concatenations(self): x = expr.to_casadi(None, y) f = casadi.Function("f", [x], [x]) y_eval = np.linspace(0, 1, expr.size) - self.assertTrue(casadi.is_equal(f(y_eval), casadi.SX(expr.evaluate(y=y_eval)))) + self.assert_casadi_equal(f(y_eval), casadi.SX(expr.evaluate(y=y_eval))) def test_convert_differentiated_function(self): a = pybamm.Scalar(0) @@ -141,15 +155,15 @@ def sin(x): return anp.sin(x) f = pybamm.Function(sin, b).diff(b) - self.assertEqual(f.to_casadi(), casadi.SX(np.cos(1))) + self.assert_casadi_equal(f.to_casadi(), casadi.MX(np.cos(1)), evalf=True) def myfunction(x, y): return x + y ** 3 f = pybamm.Function(myfunction, a, b).diff(a) - self.assertEqual(f.to_casadi(), casadi.SX(1)) + self.assert_casadi_equal(f.to_casadi(), casadi.MX(1), evalf=True) f = pybamm.Function(myfunction, a, b).diff(b) - self.assertEqual(f.to_casadi(), casadi.SX(3)) + self.assert_casadi_equal(f.to_casadi(), casadi.MX(3), evalf=True) def test_errors(self): y = pybamm.StateVector(slice(0, 10)) diff --git a/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_composite.py b/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_composite.py index 3e3c3b3190..4550c3caff 100644 --- a/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_composite.py +++ b/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_composite.py @@ -26,7 +26,9 @@ def test_well_posed(self): model = pybamm.lead_acid.Composite( {"dimensionality": 1, "current collector": "potential pair"} ) - self.assertIsInstance(model.default_solver, pybamm.ScikitsDaeSolver) + self.assertIsInstance( + model.default_solver, (pybamm.IDAKLUSolver, pybamm.CasadiSolver) + ) model.check_well_posedness() model = pybamm.lead_acid.Composite( @@ -61,7 +63,9 @@ def test_well_posed_algebraic(self): options = {"surface form": "algebraic", "side reactions": ["oxygen"]} model = pybamm.lead_acid.Composite(options) model.check_well_posedness() - self.assertIsInstance(model.default_solver, pybamm.ScikitsDaeSolver) + self.assertIsInstance( + model.default_solver, (pybamm.IDAKLUSolver, pybamm.CasadiSolver) + ) class TestLeadAcidCompositeExtended(unittest.TestCase): From bc31cd9e146f7a2a937df490f0c665b10ea4b195 Mon Sep 17 00:00:00 2001 From: tinosulzer Date: Thu, 7 Nov 2019 11:42:38 -0500 Subject: [PATCH 10/15] #685 fix interpolation example --- .../lico2_Marquis2019/lico2_data_example.csv | 100 +++++++++--------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/input/parameters/lithium-ion/cathodes/lico2_Marquis2019/lico2_data_example.csv b/input/parameters/lithium-ion/cathodes/lico2_Marquis2019/lico2_data_example.csv index f2f1809c79..5f2f5fef15 100644 --- a/input/parameters/lithium-ion/cathodes/lico2_Marquis2019/lico2_data_example.csv +++ b/input/parameters/lithium-ion/cathodes/lico2_Marquis2019/lico2_data_example.csv @@ -1,50 +1,50 @@ -0.000000000000000000e+00 4.714135898019971016e+00 -2.040816326530612082e-02 4.708899441575220557e+00 -4.081632653061224164e-02 4.702448345762175741e+00 -6.122448979591836593e-02 4.694558534379876136e+00 -8.163265306122448328e-02 4.684994372928071193e+00 -1.020408163265306006e-01 4.673523893805322516e+00 -1.224489795918367319e-01 4.659941254449398329e+00 -1.428571428571428492e-01 4.644096031712390271e+00 -1.632653061224489666e-01 4.625926611260677390e+00 -1.836734693877550839e-01 4.605491824833229053e+00 -2.040816326530612013e-01 4.582992038370575116e+00 -2.244897959183673186e-01 4.558769704421606228e+00 -2.448979591836734637e-01 4.533281647154224103e+00 -2.653061224489795533e-01 4.507041620859735254e+00 -2.857142857142856984e-01 4.480540404981123714e+00 -3.061224489795917880e-01 4.454158468368703439e+00 -3.265306122448979331e-01 4.428089899175588151e+00 -3.469387755102040782e-01 4.402295604083254155e+00 -3.673469387755101678e-01 4.376502631465185367e+00 -3.877551020408163129e-01 4.350272100879827519e+00 -4.081632653061224025e-01 4.323179536958428493e+00 -4.285714285714285476e-01 4.295195829713853719e+00 -4.489795918367346372e-01 4.267407675466301065e+00 -4.693877551020407823e-01 4.243081968022011985e+00 -4.897959183673469274e-01 4.220583168834260768e+00 -5.102040816326530726e-01 4.177032236370062712e+00 -5.306122448979591066e-01 4.134943568540559333e+00 -5.510204081632652517e-01 4.075402582839823928e+00 -5.714285714285713969e-01 4.055407164381796825e+00 -5.918367346938775420e-01 4.036052896449991323e+00 -6.122448979591835760e-01 4.012970397550268409e+00 -6.326530612244897211e-01 3.990385577539371287e+00 -6.530612244897958663e-01 3.970744780585252709e+00 -6.734693877551020114e-01 3.954753574690877738e+00 -6.938775510204081565e-01 3.942237451863396025e+00 -7.142857142857141906e-01 3.932683425747200534e+00 -7.346938775510203357e-01 3.925509771581312979e+00 -7.551020408163264808e-01 3.920182838859009422e+00 -7.755102040816326259e-01 3.916256861206461881e+00 -7.959183673469386600e-01 3.913378070528176877e+00 -8.163265306122448051e-01 3.911274218446639583e+00 -8.367346938775509502e-01 3.909739285381772067e+00 -8.571428571428570953e-01 3.908613829807601192e+00 -8.775510204081632404e-01 3.907726324580658162e+00 -8.979591836734692745e-01 3.906474088522892796e+00 -9.183673469387754196e-01 3.900204875423951556e+00 -9.387755102040815647e-01 3.848912814816038974e+00 -9.591836734693877098e-01 3.445226042113884724e+00 -9.795918367346938549e-01 1.687177743081021308e+00 -1.000000000000000000e+00 6.378908986260003328e-03 +0.000000000000000000e+00, 4.714135898019971016e+00 +2.040816326530612082e-02, 4.708899441575220557e+00 +4.081632653061224164e-02, 4.702448345762175741e+00 +6.122448979591836593e-02, 4.694558534379876136e+00 +8.163265306122448328e-02, 4.684994372928071193e+00 +1.020408163265306006e-01, 4.673523893805322516e+00 +1.224489795918367319e-01, 4.659941254449398329e+00 +1.428571428571428492e-01, 4.644096031712390271e+00 +1.632653061224489666e-01, 4.625926611260677390e+00 +1.836734693877550839e-01, 4.605491824833229053e+00 +2.040816326530612013e-01, 4.582992038370575116e+00 +2.244897959183673186e-01, 4.558769704421606228e+00 +2.448979591836734637e-01, 4.533281647154224103e+00 +2.653061224489795533e-01, 4.507041620859735254e+00 +2.857142857142856984e-01, 4.480540404981123714e+00 +3.061224489795917880e-01, 4.454158468368703439e+00 +3.265306122448979331e-01, 4.428089899175588151e+00 +3.469387755102040782e-01, 4.402295604083254155e+00 +3.673469387755101678e-01, 4.376502631465185367e+00 +3.877551020408163129e-01, 4.350272100879827519e+00 +4.081632653061224025e-01, 4.323179536958428493e+00 +4.285714285714285476e-01, 4.295195829713853719e+00 +4.489795918367346372e-01, 4.267407675466301065e+00 +4.693877551020407823e-01, 4.243081968022011985e+00 +4.897959183673469274e-01, 4.220583168834260768e+00 +5.102040816326530726e-01, 4.177032236370062712e+00 +5.306122448979591066e-01, 4.134943568540559333e+00 +5.510204081632652517e-01, 4.075402582839823928e+00 +5.714285714285713969e-01, 4.055407164381796825e+00 +5.918367346938775420e-01, 4.036052896449991323e+00 +6.122448979591835760e-01, 4.012970397550268409e+00 +6.326530612244897211e-01, 3.990385577539371287e+00 +6.530612244897958663e-01, 3.970744780585252709e+00 +6.734693877551020114e-01, 3.954753574690877738e+00 +6.938775510204081565e-01, 3.942237451863396025e+00 +7.142857142857141906e-01, 3.932683425747200534e+00 +7.346938775510203357e-01, 3.925509771581312979e+00 +7.551020408163264808e-01, 3.920182838859009422e+00 +7.755102040816326259e-01, 3.916256861206461881e+00 +7.959183673469386600e-01, 3.913378070528176877e+00 +8.163265306122448051e-01, 3.911274218446639583e+00 +8.367346938775509502e-01, 3.909739285381772067e+00 +8.571428571428570953e-01, 3.908613829807601192e+00 +8.775510204081632404e-01, 3.907726324580658162e+00 +8.979591836734692745e-01, 3.906474088522892796e+00 +9.183673469387754196e-01, 3.900204875423951556e+00 +9.387755102040815647e-01, 3.848912814816038974e+00 +9.591836734693877098e-01, 3.445226042113884724e+00 +9.795918367346938549e-01, 1.687177743081021308e+00 +1.000000000000000000e+00, 6.378908986260003328e-03 From bbc9bce8d36af31c7c6dc1a1d9668afd0abe43d6 Mon Sep 17 00:00:00 2001 From: tinosulzer Date: Thu, 7 Nov 2019 12:53:58 -0500 Subject: [PATCH 11/15] #685 fix integration tests --- pybamm/models/base_model.py | 5 +++-- .../lead_acid/base_lead_acid_model.py | 16 +++++++++++++++- pybamm/solvers/dae_solver.py | 12 ++++++++---- .../test_lead_acid/test_composite.py | 2 +- .../test_lead_acid/test_full.py | 1 + tests/integration/test_solvers/test_idaklu.py | 2 +- tests/unit/test_models/test_base_model.py | 4 ++++ tests/unit/test_solvers/test_idaklu_solver.py | 2 +- tests/unit/test_solvers/test_scikits_solvers.py | 2 +- 9 files changed, 35 insertions(+), 11 deletions(-) diff --git a/pybamm/models/base_model.py b/pybamm/models/base_model.py index a65a171725..08b33033ed 100644 --- a/pybamm/models/base_model.py +++ b/pybamm/models/base_model.py @@ -485,8 +485,9 @@ def default_solver(self): "Return default solver based on whether model is ODE model or DAE model" if len(self.algebraic) == 0: return pybamm.ScipySolver() - elif pybamm.have_idaklu(): + elif pybamm.have_idaklu() and self.use_jacobian is True: + # KLU solver requires jacobian to be provided return pybamm.IDAKLUSolver() else: - return pybamm.CasadiSolver() + return pybamm.CasadiSolver(mode="safe") diff --git a/pybamm/models/full_battery_models/lead_acid/base_lead_acid_model.py b/pybamm/models/full_battery_models/lead_acid/base_lead_acid_model.py index b0a50dd623..a25c7db88c 100644 --- a/pybamm/models/full_battery_models/lead_acid/base_lead_acid_model.py +++ b/pybamm/models/full_battery_models/lead_acid/base_lead_acid_model.py @@ -34,8 +34,22 @@ def default_geometry(self): @property def default_var_pts(self): + # Choose points that give uniform grid for the standard parameter values var = pybamm.standard_spatial_vars - return {var.x_n: 30, var.x_s: 30, var.x_p: 30, var.y: 10, var.z: 10} + return {var.x_n: 25, var.x_s: 41, var.x_p: 34, var.y: 10, var.z: 10} + + @property + def default_solver(self): + """ + Return default solver based on whether model is ODE model or DAE model. + There are bugs with KLU on the lead-acid models. + """ + if len(self.algebraic) == 0: + return pybamm.ScipySolver() + elif pybamm.have_scikits_odes(): + return pybamm.ScikitsDaeSolver() + else: + return pybamm.CasadiSolver(mode="safe") def set_standard_output_variables(self): super().set_standard_output_variables() diff --git a/pybamm/solvers/dae_solver.py b/pybamm/solvers/dae_solver.py index 1ee69adfe7..6032f8247a 100644 --- a/pybamm/solvers/dae_solver.py +++ b/pybamm/solvers/dae_solver.py @@ -282,10 +282,11 @@ def jacobian_alg(t, y): def rhs(t, y): return concatenated_rhs_fn(t, y).full()[:, 0] - def algebraic(t, y): - return concatenated_algebraic_fn(t, y).full()[:, 0] - if len(model.algebraic) > 0: + + def algebraic(t, y): + return concatenated_algebraic_fn(t, y).full()[:, 0] + y0 = self.calculate_consistent_initial_conditions( rhs, algebraic, @@ -293,7 +294,10 @@ def algebraic(t, y): jacobian_alg, ) else: - # can use DAE solver to solve ODE model + # can use DAE solver to solve ODE model (just return empty algebraic) + def algebraic(t, y): + return np.empty(0) + y0 = model.concatenated_initial_conditions[:, 0] # Create functions to evaluate residuals diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_composite.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_composite.py index 1b81910416..05c2d9bb16 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_composite.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_composite.py @@ -61,7 +61,7 @@ def test_basic_processing_algebraic(self): param = model.default_parameter_values param.update({"Typical current [A]": 1}) modeltest = tests.StandardModelTest(model, parameter_values=param) - modeltest.test_all() + modeltest.test_all() # solver=pybamm.CasadiSolver()) class TestLeadAcidCompositeExtended(unittest.TestCase): diff --git a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_full.py b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_full.py index 6d05b7cc74..0fe2b5f688 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_full.py +++ b/tests/integration/test_models/test_full_battery_models/test_lead_acid/test_full.py @@ -86,6 +86,7 @@ def test_set_up(self): if __name__ == "__main__": print("Add -v for more debug output") + # pybamm.set_logging_level("DEBUG") import sys if "-v" in sys.argv: diff --git a/tests/integration/test_solvers/test_idaklu.py b/tests/integration/test_solvers/test_idaklu.py index ac00023692..4ba46238f2 100644 --- a/tests/integration/test_solvers/test_idaklu.py +++ b/tests/integration/test_solvers/test_idaklu.py @@ -4,7 +4,7 @@ import unittest -@unittest.skipIf(~pybamm.have_idaklu(), "idaklu solver is not installed") +@unittest.skipIf(not pybamm.have_idaklu(), "idaklu solver is not installed") class TestIDAKLUSolver(unittest.TestCase): def test_on_spme(self): model = pybamm.lithium_ion.SPMe() diff --git a/tests/unit/test_models/test_base_model.py b/tests/unit/test_models/test_base_model.py index 3978c06844..6421e41bce 100644 --- a/tests/unit/test_models/test_base_model.py +++ b/tests/unit/test_models/test_base_model.py @@ -381,6 +381,10 @@ def test_default_solver(self): model.default_solver, (pybamm.IDAKLUSolver, pybamm.CasadiSolver) ) + # Check that turning off jacobian gives casadi solver + model.use_jacobian = False + self.assertIsInstance(model.default_solver, pybamm.CasadiSolver) + def test_default_parameters(self): # check parameters are read in ok model = pybamm.BaseBatteryModel() diff --git a/tests/unit/test_solvers/test_idaklu_solver.py b/tests/unit/test_solvers/test_idaklu_solver.py index 4cf4f5af02..ac01bf66ca 100644 --- a/tests/unit/test_solvers/test_idaklu_solver.py +++ b/tests/unit/test_solvers/test_idaklu_solver.py @@ -7,7 +7,7 @@ import unittest -@unittest.skipIf(~pybamm.have_idaklu(), "idaklu solver is not installed") +@unittest.skipIf(not pybamm.have_idaklu(), "idaklu solver is not installed") class TestIDAKLUSolver(unittest.TestCase): def test_ida_roberts_klu(self): # this test implements a python version of the ida Roberts diff --git a/tests/unit/test_solvers/test_scikits_solvers.py b/tests/unit/test_solvers/test_scikits_solvers.py index f9c4e5395e..af36063ff2 100644 --- a/tests/unit/test_solvers/test_scikits_solvers.py +++ b/tests/unit/test_solvers/test_scikits_solvers.py @@ -9,7 +9,7 @@ from tests import get_mesh_for_testing, get_discretisation_for_testing -@unittest.skipIf(~pybamm.have_scikits_odes(), "scikits.odes not installed") +@unittest.skipIf(not pybamm.have_scikits_odes(), "scikits.odes not installed") class TestScikitsSolvers(unittest.TestCase): def test_ode_integrate(self): # Constant From 0029b95bc69fd0a8e76184e7ded4736d01d05dbf Mon Sep 17 00:00:00 2001 From: Valentin Sulzer Date: Thu, 7 Nov 2019 14:34:44 -0500 Subject: [PATCH 12/15] #715 update sundials to 4.1.0 --- INSTALL-LINUX.md | 16 ++++++++-------- scripts/install_scikits_odes.sh | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/INSTALL-LINUX.md b/INSTALL-LINUX.md index fb0766a89b..34ef1f2a57 100644 --- a/INSTALL-LINUX.md +++ b/INSTALL-LINUX.md @@ -94,7 +94,7 @@ Before installing scikits.odes, you need to have installed: - Fortran compiler (e.g. gfortran) - BLAS/LAPACK install (OpenBLAS is recommended by the scikits.odes developers) - CMake (for building Sundials) -- Sundials 3.1.1 +- Sundials 4.1.0 You can install these on Ubuntu or Debian using apt-get: @@ -102,17 +102,17 @@ You can install these on Ubuntu or Debian using apt-get: sudo apt-get install python3-dev gfortran gcc cmake libopenblas-dev ``` -To install Sundials 3.1.1, on the command-line type: +To install Sundials 4.1.0, on the command-line type: ```bash INSTALL_DIR=`pwd`/sundials -wget https://computation.llnl.gov/projects/sundials/download/sundials-3.1.1.tar.gz -tar -xvf sundials-3.1.1.tar.gz -mkdir build-sundials-3.1.1 -cd build-sundials-3.1.1/ -cmake -DLAPACK_ENABLE=ON -DSUNDIALS_INDEX_TYPE=int32_t -DBUILD_ARKODE:BOOL=OFF -DEXAMPLES_ENABLE:BOOL=OFF -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR ../sundials-3.1.1/ +wget https://computation.llnl.gov/projects/sundials/download/sundials-4.1.0.tar.gz +tar -xvf sundials-4.1.0.tar.gz +mkdir build-sundials-4.1.0 +cd build-sundials-4.1.0/ +cmake -DLAPACK_ENABLE=ON -DSUNDIALS_INDEX_TYPE=int32_t -DBUILD_ARKODE:BOOL=OFF -DEXAMPLES_ENABLE:BOOL=OFF -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR ../sundials-4.1.0/ make install -rm -r ../sundials-3.1.1 +rm -r ../sundials-4.1.0 ``` Then install [scikits.odes](https://github.com/bmcage/odes), letting it know the sundials install location: diff --git a/scripts/install_scikits_odes.sh b/scripts/install_scikits_odes.sh index 8d91aef507..f88135b413 100755 --- a/scripts/install_scikits_odes.sh +++ b/scripts/install_scikits_odes.sh @@ -1,7 +1,7 @@ #!/bin/bash -SUNDIALS_URL=https://github.com/LLNL/sundials/archive/v3.1.1.tar.gz -SUNDIALS_NAME=sundials-3.1.1.tar.gz +SUNDIALS_URL=https://github.com/LLNL/sundials/archive/v4.1.0.tar.gz +SUNDIALS_NAME=sundials-4.1.0.tar.gz CURRENT_DIR=`pwd` TMP_DIR=$CURRENT_DIR/tmp mkdir $TMP_DIR @@ -10,9 +10,9 @@ INSTALL_DIR=$CURRENT_DIR/sundials cd $TMP_DIR wget $SUNDIALS_URL -O $SUNDIALS_NAME tar -xvf $SUNDIALS_NAME -mkdir build-sundials-3.1.1 -cd build-sundials-3.1.1/ -cmake -DLAPACK_ENABLE=ON -DSUNDIALS_INDEX_TYPE=int32_t -DBUILD_ARKODE:BOOL=OFF -DEXAMPLES_ENABLE:BOOL=OFF -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR ../sundials-3.1.1/ +mkdir build-sundials-4.1.0 +cd build-sundials-4.1.0/ +cmake -DLAPACK_ENABLE=ON -DSUNDIALS_INDEX_TYPE=int32_t -DBUILD_ARKODE:BOOL=OFF -DEXAMPLES_ENABLE:BOOL=OFF -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR ../sundials-4.1.0/ make install cd $CURRENT_DIR rm -rf $TMP_DIR From 6ffcf8182fda9111253a3a0b83fdb1624888b258 Mon Sep 17 00:00:00 2001 From: tinosulzer Date: Thu, 7 Nov 2019 15:12:44 -0500 Subject: [PATCH 13/15] #685 update changelog --- CHANGELOG.md | 29 ++++++++++++++------------- pybamm/expression_tree/interpolant.py | 2 +- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00f1f641b4..066d81d63e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,30 +3,31 @@ ## Features - Added Simulation class ([#693](https://github.com/pybamm-team/PyBaMM/pull/693)) -- Add interface to CasADi solver ([#687](https://github.com/pybamm-team/PyBaMM/pull/687), [#691](https://github.com/pybamm-team/PyBaMM/pull/691)) -- Add option to use CasADi's Algorithmic Differentiation framework to calculate Jacobians ([#687](https://github.com/pybamm-team/PyBaMM/pull/687)) -- Add method to evaluate parameters more easily ([#669](https://github.com/pybamm-team/PyBaMM/pull/669)) -- Add `Jacobian` class to reuse known Jacobians of expressions ([#665](https://github.com/pybamm-team/PyBaMM/pull/670)) -- Add `Interpolant` class to interpolate experimental data (e.g. OCP curves) ([#661](https://github.com/pybamm-team/PyBaMM/pull/661)) +- Added interface to CasADi solver ([#687](https://github.com/pybamm-team/PyBaMM/pull/687), [#691](https://github.com/pybamm-team/PyBaMM/pull/691), [#714](https://github.com/pybamm-team/PyBaMM/pull/714)). This makes the SUNDIALS DAE solvers (Scikits and KLU) truly optional (though IDA KLU is recommended for solving the DFN). +- Added option to use CasADi's Algorithmic Differentiation framework to calculate Jacobians ([#687](https://github.com/pybamm-team/PyBaMM/pull/687)) +- Added method to evaluate parameters more easily ([#669](https://github.com/pybamm-team/PyBaMM/pull/669)) +- Added `Jacobian` class to reuse known Jacobians of expressions ([#665](https://github.com/pybamm-team/PyBaMM/pull/670)) +- Added `Interpolant` class to interpolate experimental data (e.g. OCP curves) ([#661](https://github.com/pybamm-team/PyBaMM/pull/661)) - Added interface (via pybind11) to sundials with the IDA KLU sparse linear solver ([#657](https://github.com/pybamm-team/PyBaMM/pull/657)) -- Allow parameters to be set by material or by specifying a particular paper ([#647](https://github.com/pybamm-team/PyBaMM/pull/647)) +- Allowed parameters to be set by material or by specifying a particular paper ([#647](https://github.com/pybamm-team/PyBaMM/pull/647)) - Set relative and absolute tolerances independently in solvers ([#645](https://github.com/pybamm-team/PyBaMM/pull/645)) -- Add basic method to allow (a part of) the State Vector to be updated with results obtained from another solution or package ([#624](https://github.com/pybamm-team/PyBaMM/pull/624)) -- Add some non-uniform meshes in 1D and 2D ([#617](https://github.com/pybamm-team/PyBaMM/pull/617)) +- Added basic method to allow (a part of) the State Vector to be updated with results obtained from another solution or package ([#624](https://github.com/pybamm-team/PyBaMM/pull/624)) +- Added some non-uniform meshes in 1D and 2D ([#617](https://github.com/pybamm-team/PyBaMM/pull/617)) ## Optimizations +- Use CasADi's automatic differentation algorithms by default when solving a model ([#714](https://github.com/pybamm-team/PyBaMM/pull/714)) - Avoid re-checking size when making a copy of an `Index` object ([#656](https://github.com/pybamm-team/PyBaMM/pull/656)) - Avoid recalculating `_evaluation_array` when making a copy of a `StateVector` object ([#653](https://github.com/pybamm-team/PyBaMM/pull/653)) ## Bug fixes -- Correct a sign error in Dirichlet boundary conditions in the Finite Element Method ([#706](https://github.com/pybamm-team/PyBaMM/pull/706)) -- Pass the correct dimensional temperature to open circuit potential ([#702](https://github.com/pybamm-team/PyBaMM/pull/702)) -- Adds missing temperature dependence in electrolyte and interface submodels ([#698](https://github.com/pybamm-team/PyBaMM/pull/698)) -- Fix differentiation of functions that have more than one argument ([#687](https://github.com/pybamm-team/PyBaMM/pull/687)) -- Add warning if `ProcessedVariable` is called outside its interpolation range ([#681](https://github.com/pybamm-team/PyBaMM/pull/681)) -- Improve the way `ProcessedVariable` objects are created in higher dimensions ([#581](https://github.com/pybamm-team/PyBaMM/pull/581)) +- Corrected a sign error in Dirichlet boundary conditions in the Finite Element Method ([#706](https://github.com/pybamm-team/PyBaMM/pull/706)) +- Passed the correct dimensional temperature to open circuit potential ([#702](https://github.com/pybamm-team/PyBaMM/pull/702)) +- Added missing temperature dependence in electrolyte and interface submodels ([#698](https://github.com/pybamm-team/PyBaMM/pull/698)) +- Fixed differentiation of functions that have more than one argument ([#687](https://github.com/pybamm-team/PyBaMM/pull/687)) +- Added warning if `ProcessedVariable` is called outside its interpolation range ([#681](https://github.com/pybamm-team/PyBaMM/pull/681)) +- Improved the way `ProcessedVariable` objects are created in higher dimensions ([#581](https://github.com/pybamm-team/PyBaMM/pull/581)) # [v0.1.0](https://github.com/pybamm-team/PyBaMM/tree/v0.1.0) - 2019-10-08 diff --git a/pybamm/expression_tree/interpolant.py b/pybamm/expression_tree/interpolant.py index d60f7b23c1..d3e3758602 100644 --- a/pybamm/expression_tree/interpolant.py +++ b/pybamm/expression_tree/interpolant.py @@ -73,7 +73,7 @@ def _function_new_copy(self, children): *children, name=self.name, interpolator=self.interpolator, - extrapolate=self.extrapolate, + extrapolate=self.extrapolate ) def _function_simplify(self, simplified_children): From 8829213a6408a2f64668075065fca6db4b80f26a Mon Sep 17 00:00:00 2001 From: Valentin Sulzer Date: Thu, 7 Nov 2019 16:02:26 -0500 Subject: [PATCH 14/15] #685 update solver tests --- .../test_full_battery_models/test_lead_acid/test_composite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_composite.py b/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_composite.py index 4550c3caff..183fe3cc46 100644 --- a/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_composite.py +++ b/tests/unit/test_models/test_full_battery_models/test_lead_acid/test_composite.py @@ -27,7 +27,7 @@ def test_well_posed(self): {"dimensionality": 1, "current collector": "potential pair"} ) self.assertIsInstance( - model.default_solver, (pybamm.IDAKLUSolver, pybamm.CasadiSolver) + model.default_solver, (pybamm.ScikitsDaeSolver, pybamm.CasadiSolver) ) model.check_well_posedness() @@ -64,7 +64,7 @@ def test_well_posed_algebraic(self): model = pybamm.lead_acid.Composite(options) model.check_well_posedness() self.assertIsInstance( - model.default_solver, (pybamm.IDAKLUSolver, pybamm.CasadiSolver) + model.default_solver, (pybamm.ScikitsDaeSolver, pybamm.CasadiSolver) ) From 234e7e8fc92278c5eac4e80018a670e1679549a9 Mon Sep 17 00:00:00 2001 From: Valentin Sulzer Date: Thu, 7 Nov 2019 19:16:13 -0500 Subject: [PATCH 15/15] #685 coverage --- pybamm/expression_tree/interpolant.py | 2 +- .../lead_acid/base_lead_acid_model.py | 2 +- .../get_user_current.py | 31 ---------- .../user_current.py | 2 +- pybamm/solvers/dae_solver.py | 11 ++-- pybamm/solvers/idaklu_solver.py | 2 +- .../test_expression_tree/test_interpolant.py | 9 +++ .../test_parameters/test_current_functions.py | 1 + .../unit/test_solvers/test_scikits_solvers.py | 56 ++++++++++++------- tests/unit/test_solvers/test_scipy_solver.py | 12 ++-- 10 files changed, 62 insertions(+), 66 deletions(-) delete mode 100644 pybamm/parameters/standard_current_functions/get_user_current.py diff --git a/pybamm/expression_tree/interpolant.py b/pybamm/expression_tree/interpolant.py index d3e3758602..2ee16ae644 100644 --- a/pybamm/expression_tree/interpolant.py +++ b/pybamm/expression_tree/interpolant.py @@ -52,7 +52,7 @@ def __init__( else: raise ValueError("interpolator '{}' not recognised".format(interpolator)) # Set name - if name is not None: + if name is not None and not name.startswith("interpolating function"): name = "interpolating function ({})".format(name) else: name = "interpolating function" diff --git a/pybamm/models/full_battery_models/lead_acid/base_lead_acid_model.py b/pybamm/models/full_battery_models/lead_acid/base_lead_acid_model.py index a25c7db88c..f233d13c40 100644 --- a/pybamm/models/full_battery_models/lead_acid/base_lead_acid_model.py +++ b/pybamm/models/full_battery_models/lead_acid/base_lead_acid_model.py @@ -48,7 +48,7 @@ def default_solver(self): return pybamm.ScipySolver() elif pybamm.have_scikits_odes(): return pybamm.ScikitsDaeSolver() - else: + else: # pragma: no cover return pybamm.CasadiSolver(mode="safe") def set_standard_output_variables(self): diff --git a/pybamm/parameters/standard_current_functions/get_user_current.py b/pybamm/parameters/standard_current_functions/get_user_current.py deleted file mode 100644 index c4c01b13bc..0000000000 --- a/pybamm/parameters/standard_current_functions/get_user_current.py +++ /dev/null @@ -1,31 +0,0 @@ -# -# Allow a user-defined current function -# -import pybamm - - -class UserCurrent(pybamm.BaseCurrent): - """ - Sets a user-defined function as the input current for a simulation. - - Parameters - ---------- - function : method - The method which returns the current (in Amperes) as a function of time - (in seconds). The first argument of function must be time, followed by - any keyword arguments, i.e. function(t, **kwargs). - **kwargs : Any keyword arguments required by function. - - **Extends:"": :class:`pybamm.BaseCurrent` - """ - - def __init__(self, function, **kwargs): - self.parameters = kwargs - self.parameters_eval = kwargs - self.function = function - - def __str__(self): - return "User defined current" - - def __call__(self, t): - return self.function(t, **self.parameters_eval) diff --git a/pybamm/parameters/standard_current_functions/user_current.py b/pybamm/parameters/standard_current_functions/user_current.py index c4c01b13bc..76f4afc945 100644 --- a/pybamm/parameters/standard_current_functions/user_current.py +++ b/pybamm/parameters/standard_current_functions/user_current.py @@ -25,7 +25,7 @@ def __init__(self, function, **kwargs): self.function = function def __str__(self): - return "User defined current" + return "User defined current ({})".format(self.function.__name__) def __call__(self, t): return self.function(t, **self.parameters_eval) diff --git a/pybamm/solvers/dae_solver.py b/pybamm/solvers/dae_solver.py index 6032f8247a..d717a36530 100644 --- a/pybamm/solvers/dae_solver.py +++ b/pybamm/solvers/dae_solver.py @@ -282,10 +282,10 @@ def jacobian_alg(t, y): def rhs(t, y): return concatenated_rhs_fn(t, y).full()[:, 0] - if len(model.algebraic) > 0: + def algebraic(t, y): + return concatenated_algebraic_fn(t, y).full()[:, 0] - def algebraic(t, y): - return concatenated_algebraic_fn(t, y).full()[:, 0] + if len(model.algebraic) > 0: y0 = self.calculate_consistent_initial_conditions( rhs, @@ -294,10 +294,7 @@ def algebraic(t, y): jacobian_alg, ) else: - # can use DAE solver to solve ODE model (just return empty algebraic) - def algebraic(t, y): - return np.empty(0) - + # can use DAE solver to solve ODE model y0 = model.concatenated_initial_conditions[:, 0] # Create functions to evaluate residuals diff --git a/pybamm/solvers/idaklu_solver.py b/pybamm/solvers/idaklu_solver.py index e5b2ecdca1..7b7cec960e 100644 --- a/pybamm/solvers/idaklu_solver.py +++ b/pybamm/solvers/idaklu_solver.py @@ -211,7 +211,7 @@ def rootfn(t, y): # get ids of rhs and algebraic variables rhs_ids = np.ones(self.rhs(0, y0).shape) - alg_ids = np.zeros(self.algebraic(0, y0).shape) + alg_ids = np.zeros(len(y0) - len(rhs_ids)) ids = np.concatenate((rhs_ids, alg_ids)) # solve diff --git a/tests/unit/test_expression_tree/test_interpolant.py b/tests/unit/test_expression_tree/test_interpolant.py index 84de9eef76..edce07bde9 100644 --- a/tests/unit/test_expression_tree/test_interpolant.py +++ b/tests/unit/test_expression_tree/test_interpolant.py @@ -72,6 +72,15 @@ def test_diff(self): decimal=3, ) + def test_processing(self): + x = np.linspace(0, 1)[:, np.newaxis] + y = pybamm.StateVector(slice(0, 2)) + linear = np.hstack([x, 2 * x]) + interp = pybamm.Interpolant(linear, y) + + self.assertEqual(interp.id, interp.new_copy().id) + self.assertEqual(interp.id, interp.simplify().id) + if __name__ == "__main__": print("Add -v for more debug output") diff --git a/tests/unit/test_parameters/test_current_functions.py b/tests/unit/test_parameters/test_current_functions.py index 0581511bb9..6f91982bb4 100644 --- a/tests/unit/test_parameters/test_current_functions.py +++ b/tests/unit/test_parameters/test_current_functions.py @@ -60,6 +60,7 @@ def my_fun(t, A, omega): # pass my_fun to UserCurrent class, giving the additonal parameters as # keyword arguments current = pybamm.UserCurrent(my_fun, A=A, omega=omega) + self.assertEqual(str(current), "User defined current (my_fun)") # set and process parameters parameter_values = pybamm.ParameterValues( diff --git a/tests/unit/test_solvers/test_scikits_solvers.py b/tests/unit/test_solvers/test_scikits_solvers.py index af36063ff2..7ac16b5af3 100644 --- a/tests/unit/test_solvers/test_scikits_solvers.py +++ b/tests/unit/test_solvers/test_scikits_solvers.py @@ -394,9 +394,9 @@ def jacobian(t, y): np.testing.assert_allclose(0.125 * solution.t, solution.y[0]) np.testing.assert_allclose(0.25 * solution.t, solution.y[1]) - def test_model_solver_ode(self): - # Create model + def test_model_solver_ode_python(self): model = pybamm.BaseModel() + model.convert_to_format = "python" whole_cell = ["negative electrode", "separator", "positive electrode"] var = pybamm.Variable("var", domain=whole_cell) model.rhs = {var: 0.1 * var} @@ -411,9 +411,9 @@ def test_model_solver_ode(self): np.testing.assert_array_equal(solution.t, t_eval) np.testing.assert_allclose(solution.y[0], np.exp(0.1 * solution.t)) - def test_model_solver_ode_events(self): - # Create model + def test_model_solver_ode_events_python(self): model = pybamm.BaseModel() + model.convert_to_format = "python" whole_cell = ["negative electrode", "separator", "positive electrode"] var = pybamm.Variable("var", domain=whole_cell) model.rhs = {var: 0.1 * var} @@ -433,9 +433,9 @@ def test_model_solver_ode_events(self): np.testing.assert_array_less(solution.y[0], 1.5) np.testing.assert_array_less(solution.y[0], 1.25) - def test_model_solver_ode_jacobian(self): - # Create model + def test_model_solver_ode_jacobian_python(self): model = pybamm.BaseModel() + model.convert_to_format = "python" whole_cell = ["negative electrode", "separator", "positive electrode"] var1 = pybamm.Variable("var1", domain=whole_cell) var2 = pybamm.Variable("var2", domain=whole_cell) @@ -482,9 +482,9 @@ def jacobian(t, y): np.ones((N, T.size)) * (T[np.newaxis, :] - np.exp(T[np.newaxis, :])), ) - def test_model_solver_dae(self): - # Create model + def test_model_solver_dae_python(self): model = pybamm.BaseModel() + model.convert_to_format = "python" whole_cell = ["negative electrode", "separator", "positive electrode"] var1 = pybamm.Variable("var1", domain=whole_cell) var2 = pybamm.Variable("var2", domain=whole_cell) @@ -503,9 +503,9 @@ def test_model_solver_dae(self): np.testing.assert_allclose(solution.y[0], np.exp(0.1 * solution.t)) np.testing.assert_allclose(solution.y[-1], 2 * np.exp(0.1 * solution.t)) - def test_model_solver_dae_bad_ics(self): - # Create model + def test_model_solver_dae_bad_ics_python(self): model = pybamm.BaseModel() + model.convert_to_format = "python" whole_cell = ["negative electrode", "separator", "positive electrode"] var1 = pybamm.Variable("var1", domain=whole_cell) var2 = pybamm.Variable("var2", domain=whole_cell) @@ -523,9 +523,9 @@ def test_model_solver_dae_bad_ics(self): np.testing.assert_allclose(solution.y[0], np.exp(0.1 * solution.t)) np.testing.assert_allclose(solution.y[-1], 2 * np.exp(0.1 * solution.t)) - def test_model_solver_dae_events(self): - # Create model + def test_model_solver_dae_events_python(self): model = pybamm.BaseModel() + model.convert_to_format = "python" whole_cell = ["negative electrode", "separator", "positive electrode"] var1 = pybamm.Variable("var1", domain=whole_cell) var2 = pybamm.Variable("var2", domain=whole_cell) @@ -548,9 +548,9 @@ def test_model_solver_dae_events(self): np.testing.assert_allclose(solution.y[0], np.exp(0.1 * solution.t)) np.testing.assert_allclose(solution.y[-1], 2 * np.exp(0.1 * solution.t)) - def test_model_solver_dae_with_jacobian(self): - # Create simple test model + def test_model_solver_dae_with_jacobian_python(self): model = pybamm.BaseModel() + model.convert_to_format = "python" whole_cell = ["negative electrode", "separator", "positive electrode"] var1 = pybamm.Variable("var1", domain=whole_cell) var2 = pybamm.Variable("var2", domain=whole_cell) @@ -584,9 +584,9 @@ def jacobian(t, y): np.testing.assert_allclose(solution.y[0], np.exp(0.1 * solution.t)) np.testing.assert_allclose(solution.y[-1], 2 * np.exp(0.1 * solution.t)) - def test_solve_ode_model_with_dae_solver(self): - # Create model + def test_solve_ode_model_with_dae_solver_python(self): model = pybamm.BaseModel() + model.convert_to_format = "python" var = pybamm.Variable("var") model.rhs = {var: 0.1 * var} model.initial_conditions = {var: 1} @@ -600,9 +600,9 @@ def test_solve_ode_model_with_dae_solver(self): np.testing.assert_array_equal(solution.t, t_eval) np.testing.assert_allclose(solution.y[0], np.exp(0.1 * solution.t)) - def test_model_step_ode(self): - # Create model + def test_model_step_ode_python(self): model = pybamm.BaseModel() + model.convert_to_format = "python" whole_cell = ["negative electrode", "separator", "positive electrode"] var = pybamm.Variable("var", domain=whole_cell) model.rhs = {var: 0.1 * var} @@ -629,9 +629,9 @@ def test_model_step_ode(self): concatenated_steps = np.concatenate((step_sol.y[0], step_sol_2.y[0, 1:])) np.testing.assert_allclose(solution.y[0], concatenated_steps) - def test_model_step_dae(self): - # Create model + def test_model_step_dae_python(self): model = pybamm.BaseModel() + model.convert_to_format = "python" whole_cell = ["negative electrode", "separator", "positive electrode"] var1 = pybamm.Variable("var1", domain=whole_cell) var2 = pybamm.Variable("var2", domain=whole_cell) @@ -717,6 +717,22 @@ def test_model_solver_dae_events_casadi(self): np.testing.assert_allclose(solution.y[0], np.exp(0.1 * solution.t)) np.testing.assert_allclose(solution.y[-1], 2 * np.exp(0.1 * solution.t)) + def test_solve_ode_model_with_dae_solver_casadi(self): + model = pybamm.BaseModel() + model.convert_to_format = "casadi" + var = pybamm.Variable("var") + model.rhs = {var: 0.1 * var} + model.initial_conditions = {var: 1} + disc = get_discretisation_for_testing() + disc.process_model(model) + + # Solve + solver = pybamm.ScikitsDaeSolver(rtol=1e-8, atol=1e-8) + t_eval = np.linspace(0, 1, 100) + solution = solver.solve(model, t_eval) + np.testing.assert_array_equal(solution.t, t_eval) + np.testing.assert_allclose(solution.y[0], np.exp(0.1 * solution.t)) + if __name__ == "__main__": print("Add -v for more debug output") diff --git a/tests/unit/test_solvers/test_scipy_solver.py b/tests/unit/test_solvers/test_scipy_solver.py index c083dbabc7..98f2e70e2c 100644 --- a/tests/unit/test_solvers/test_scipy_solver.py +++ b/tests/unit/test_solvers/test_scipy_solver.py @@ -132,9 +132,10 @@ def jacobian(t, y): np.exp(1 + solution.t - np.exp(solution.t)), solution.y[1], rtol=1e-4 ) - def test_model_solver(self): + def test_model_solver_python(self): # Create model model = pybamm.BaseModel() + model.convert_to_format = "python" domain = ["negative electrode", "separator", "positive electrode"] var = pybamm.Variable("var", domain=domain) model.rhs = {var: 0.1 * var} @@ -158,9 +159,10 @@ def test_model_solver(self): solution.total_time, solution.solve_time + solution.set_up_time ) - def test_model_solver_with_event(self): + def test_model_solver_with_event_python(self): # Create model model = pybamm.BaseModel() + model.convert_to_format = "python" domain = ["negative electrode", "separator", "positive electrode"] var = pybamm.Variable("var", domain=domain) model.rhs = {var: -0.1 * var} @@ -181,9 +183,10 @@ def test_model_solver_with_event(self): np.testing.assert_array_equal(solution.t, t_eval[: len(solution.t)]) np.testing.assert_allclose(solution.y[0], np.exp(-0.1 * solution.t)) - def test_model_solver_ode_with_jacobian(self): + def test_model_solver_ode_with_jacobian_python(self): # Create model model = pybamm.BaseModel() + model.convert_to_format = "python" whole_cell = ["negative electrode", "separator", "positive electrode"] var1 = pybamm.Variable("var1", domain=whole_cell) var2 = pybamm.Variable("var2", domain=whole_cell) @@ -232,9 +235,10 @@ def jacobian(t, y): np.ones((N, T.size)) * (T[np.newaxis, :] - np.exp(T[np.newaxis, :])), ) - def test_model_step(self): + def test_model_step_python(self): # Create model model = pybamm.BaseModel() + model.convert_to_format = "python" domain = ["negative electrode", "separator", "positive electrode"] var = pybamm.Variable("var", domain=domain) model.rhs = {var: 0.1 * var}