diff --git a/.gitignore b/.gitignore index 3eab70bba2..b130bb9287 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ !requirements* !LICENSE.txt !CMakeLists.txt +!pybamm/CITATIONS.txt !pybamm/input/**/*.csv # running files diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c04e94b38..d7a91a9593 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ - Added capacitance effects to lithium-ion models ([#842](https://github.com/pybamm-team/PyBaMM/pull/842)) - Added NCA parameter set ([#824](https://github.com/pybamm-team/PyBaMM/pull/824)) - Added functionality to `Solution` that automatically gets `t_eval` from the data when simulating drive cycles and performs checks to ensure the output has the required resolution to accurately capture the input current ([#819](https://github.com/pybamm-team/PyBaMM/pull/819)) -- Added options to export a solution to matlab or csv ([#811](https://github.com/pybamm-team/PyBaMM/pull/811)) +- Added `Citations` object to print references when specific functionality is used ([#818](https://github.com/pybamm-team/PyBaMM/pull/818)) +- Updated `Solution` to allow exporting to matlab and csv formats ([#811](https://github.com/pybamm-team/PyBaMM/pull/811)) - Allow porosity to vary in space ([#809](https://github.com/pybamm-team/PyBaMM/pull/809)) - Added functionality to solve DAE models with non-smooth current inputs ([#808](https://github.com/pybamm-team/PyBaMM/pull/808)) - Added functionality to simulate experiments and testing protocols ([#807](https://github.com/pybamm-team/PyBaMM/pull/807)) diff --git a/README.md b/README.md index e224145f59..d3e5b0831e 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,32 @@ For instructions on installing PyBaMM on Mac OS distributions, please see [here] We recommend using Windows Subsystem for Linux to install PyBaMM on a Windows OS, for instructions please see [here](INSTALL-WINDOWS.md) +## Citing PyBaMM + +If you use PyBaMM in your work, please cite our paper + +"Sulzer, V., Marquis, S. G., Timms, R., Robinson, M., & Chapman, S. J. (2020). Python Battery Mathematical Modelling (PyBaMM). _ECSarXiv. February, 7_." + +You can use the bibtex + +``` +@article{sulzer2020python, + title={Python Battery Mathematical Modelling (PyBaMM)}, + author={Sulzer, Valentin and Marquis, Scott G and Timms, Robert and Robinson, Martin and Chapman, S Jon}, + journal={ECSarXiv. February}, + volume={7}, + year={2020} +} +``` + +We would be grateful if you could also cite the relevant papers. These will change depending on what models and solvers you use. To find out which papers you should cite, add the line + +```python3 +pybamm.print_citations() +``` + +to the end of your script. This will print bibtex information to the terminal; passing a filename to `print_citations` will print the bibtex information to the specified file instead. A list of all citations can also be found in the [citations file](pybamm/CITATIONS.txt). In particular, PyBaMM relies heavily on [CasADi](https://web.casadi.org/publications/). + ## How can I contribute to PyBaMM? If you'd like to help us develop PyBaMM by adding new methods, writing documentation, or fixing embarrassing bugs, please have a look at these [guidelines](CONTRIBUTING.md) first. diff --git a/docs/index.rst b/docs/index.rst index 05ad15aeae..ebbecaca68 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -34,6 +34,7 @@ Contents source/processed_variable source/util source/simulation + source/citations source/parameters_cli Examples diff --git a/docs/source/citations.rst b/docs/source/citations.rst new file mode 100644 index 0000000000..cd560c9c28 --- /dev/null +++ b/docs/source/citations.rst @@ -0,0 +1,7 @@ +Citations +========= + +.. autoclass:: pybamm.Citations + :members: + +.. autofunction:: pybamm.print_citations diff --git a/examples/scripts/DFN.py b/examples/scripts/DFN.py index d46f466fa9..9155d9eaa7 100644 --- a/examples/scripts/DFN.py +++ b/examples/scripts/DFN.py @@ -30,7 +30,7 @@ # solve model t_eval = np.linspace(0, 3600, 100) -solver = model.default_solver +solver = pybamm.CasadiSolver() solver.rtol = 1e-3 solver.atol = 1e-6 solution = solver.solve(model, t_eval) diff --git a/pybamm/CITATIONS.txt b/pybamm/CITATIONS.txt new file mode 100644 index 0000000000..8b77fb4475 --- /dev/null +++ b/pybamm/CITATIONS.txt @@ -0,0 +1,125 @@ +@Article{Andersson2019, + author = {Joel A E Andersson and Joris Gillis and Greg Horn + and James B Rawlings and Moritz Diehl}, + title = {{CasADi} -- {A} software framework for nonlinear optimization + and optimal control}, + journal = {Mathematical Programming Computation}, + volume = {11}, + number = {1}, + pages = {1--36}, + year = {2019}, + publisher = {Springer}, + doi = {10.1007/s12532-018-0139-4} +} + +@article{Chen2020, +author = {Chen, Chang-Hui and Brosa Planella, Ferran and O'Regan, Kieran and Gastol, Dominika and Widanage, W. Dhammika and Kendrick, Emma}, +title = {{Development of Experimental Techniques for Parameterization of Multi-scale Lithium-ion Battery Models}}, +journal = {Submitted for publication}, +year = {2020} +} + +@article{doyle1993modeling, + title={Modeling of galvanostatic charge and discharge of the lithium/polymer/insertion cell}, + author={Doyle, M and Fuller, TF and Newman, J}, + journal={Journal of the Electrochemical society}, + volume={140}, + number={6}, + pages={1526--1533}, + year={1993}, + publisher={The Electrochemical Society}, + note = {\href{ http://dx.doi.org/10.1149/1.2221597}{doi: 10.1149/1.2221597}}, +} + +@techreport{hindmarsh2000pvode, + title={The {PVODE} and {IDA} algorithms}, + author={Hindmarsh, AC}, + year={2000}, + institution={Lawrence Livermore National Lab., CA (US)}, + note = {\href{ https://www.osti.gov/biblio/802599}{doi:10.2172/802599}}, +} + +@article{hindmarsh2005sundials, + title={SUNDIALS: Suite of nonlinear and differential/algebraic equation solvers}, + author={Hindmarsh, Alan C and Brown, Peter N and Grant, Keith E and Lee, Steven L and Serban, Radu and Shumaker, Dan E and Woodward, Carol S}, + journal={ACM Transactions on Mathematical Software (TOMS)}, + volume={31}, + number={3}, + pages={363--396}, + year={2005}, + publisher={ACM New York, NY, USA} +} + +@article{kim2011multi, + title={Multi-domain modeling of lithium-ion batteries encompassing multi-physics in varied length scales}, + author={Kim, Gi-Heon and Smith, Kandler and Lee, Kyu-Jin and Santhanagopalan, Shriram and Pesaran, Ahmad}, + journal={Journal of the electrochemical society}, + volume={158}, + number={8}, + pages={A955--A969}, + year={2011}, + publisher={The Electrochemical Society} +} + +@article{marquis2019asymptotic, +title={An asymptotic derivation of a single particle model with electrolyte}, +author={Marquis, Scott G and Sulzer, Valentin and Timms, Robert and Please, Colin P and Chapman, S Jon}, +journal={Journal of The Electrochemical Society}, +volume={166}, +number={15}, +pages={A3693--A3706}, +year={2019}, +publisher={The Electrochemical Society} +} + +@article{scikits-odes, + year = {2018}, + month = {feb}, + publisher = {The Open Journal}, + volume = {3}, + number = {22}, + pages = {165}, + author = {Malengier, B and Ki{\v{s}}on, P and Tocknell, J and Abert, C and Bruckner, F and Bisotti, M-A}, + title = {{ODES}: a high level interface to {ODE} and {DAE} solvers}, + journal = {The Journal of Open Source Software}, + note = {\href{ http://dx.doi.org/10.21105/joss.00165}{doi: 10.21105/joss.00165}}, +} + +@article{virtanen2020scipy, + title={SciPy 1.0: fundamental algorithms for scientific computing in Python}, + author={Virtanen, Pauli and Gommers, Ralf and Oliphant, Travis E and Haberland, Matt and Reddy, Tyler and Cournapeau, David and Burovski, Evgeni and Peterson, Pearu and Weckesser, Warren and Bright, Jonathan and others}, + journal={Nature Methods}, + pages={1--12}, + year={2020}, + publisher={Nature Publishing Group} +} + +@article{sulzer2019physical, + title={Faster Lead-Acid Battery Simulations from Porous-Electrode Theory: Part I. Physical Model}, + author={Sulzer, Valentin and Chapman, S Jon and Please, Colin P and Howey, David A and Monroe, Charles W}, + journal={Journal of The Electrochemical Society}, + volume={166}, + number={12}, + pages={A2363--A2371}, + year={2019}, + publisher={The Electrochemical Society} +} + +@article{sulzer2019asymptotic, + title={Faster Lead-Acid Battery Simulations from Porous-Electrode Theory: Part II. Asymptotic Analysis}, + author={Sulzer, Valentin and Chapman, S Jon and Please, Colin P and Howey, David A and Monroe, Charles W}, + journal={Journal of The Electrochemical Society}, + volume={166}, + number={12}, + pages={A2372--A2382}, + year={2019}, + publisher={The Electrochemical Society} +} + +@article{sulzer2020python, +title={Python Battery Mathematical Modelling (PyBaMM)}, +author={Sulzer, Valentin and Marquis, Scott G and Timms, Robert and Robinson, Martin and Chapman, S Jon}, +journal={ECSarXiv. February}, +volume={7}, +year={2020} +} diff --git a/pybamm/__init__.py b/pybamm/__init__.py index c958da664e..da9022e60a 100644 --- a/pybamm/__init__.py +++ b/pybamm/__init__.py @@ -60,6 +60,7 @@ def version(formatted=False): from .util import get_parameters_filepath from .logger import logger, set_logging_level from .settings import settings +from .citations import Citations, citations, print_citations # # Classes for the Expression Tree diff --git a/pybamm/citations.py b/pybamm/citations.py new file mode 100644 index 0000000000..c2e7608684 --- /dev/null +++ b/pybamm/citations.py @@ -0,0 +1,100 @@ +# +# Bibliographical information for PyBaMM +# Inspired by firedrake/PETSc citation workflow +# https://www.firedrakeproject.org/citing.html +# +import pybamm +import os + + +class Citations: + + """Entry point to citations management. + This object may be used to record Bibtex citation information and then register that + a particular citation is relevant for a particular simulation. For a list of all + possible citations, see `pybamm/CITATIONS.txt` + + Examples + -------- + >>> import pybamm + >>> pybamm.citations.register("sulzer2020python") + >>> pybamm.print_citations("citations.txt") + """ + + def __init__(self): + self.read_citations() + self._reset() + + def _reset(self): + "Reset citations to default only (only for testing purposes)" + # Initialize empty papers to cite + self._papers_to_cite = set() + # Register the PyBaMM paper + self.register("sulzer2020python") + + def read_citations(self): + "Read the citations text file" + self._all_citations = {} + + citations_file = os.path.join(pybamm.root_dir(), "pybamm", "CITATIONS.txt") + citation = "" + start = True + + for line in open(citations_file): + # if start is true, we need to find the key + if start is True: + # match everything between { and , in the first line to get the key + brace_idx = line.find("{") + comma_idx = line.find(",") + key = line[brace_idx + 1 : comma_idx] + # turn off start as we now have the right key + start = False + citation += line + # blank line means next block, add citation to dictionary and + # reset everything + if line == "\n": + self._all_citations[key] = citation + citation = "" + start = True + + # add the final citation + self._all_citations[key] = citation + + def register(self, key): + """Register a paper to be cited. The intended use is that :meth:`register` + should be called only when the referenced functionality is actually being used. + + Parameters + ---------- + key : str + The key for the paper to be cited + """ + if key not in self._all_citations: + raise KeyError("'{}' is not a known citation".format(key)) + self._papers_to_cite.add(key) + + def print(self, filename=None): + """Print all citations that were used for running simulations. + + Parameters + ---------- + filename : str, optional + Filename to which to print citations. If None, citations are printed to the + terminal. + """ + citations = "" + for key in self._papers_to_cite: + citations += self._all_citations[key] + "\n" + if filename is None: + print(citations) + else: + with open(filename, "w") as f: + f.write(citations) + + +def print_citations(filename=None): + "See :meth:`Citations.print`" + pybamm.citations.print(filename) + + +citations = Citations() diff --git a/pybamm/expression_tree/operations/convert_to_casadi.py b/pybamm/expression_tree/operations/convert_to_casadi.py index a04aec5b0a..5e89ab75cf 100644 --- a/pybamm/expression_tree/operations/convert_to_casadi.py +++ b/pybamm/expression_tree/operations/convert_to_casadi.py @@ -11,6 +11,8 @@ class CasadiConverter(object): def __init__(self, casadi_symbols=None): self._casadi_symbols = casadi_symbols or {} + pybamm.citations.register("Andersson2019") + def convert(self, symbol, t=None, y=None, u=None): """ This function recurses down the tree, converting the PyBaMM expression tree to diff --git a/pybamm/models/full_battery_models/lead_acid/full.py b/pybamm/models/full_battery_models/lead_acid/full.py index 4e0a508558..331b26b993 100644 --- a/pybamm/models/full_battery_models/lead_acid/full.py +++ b/pybamm/models/full_battery_models/lead_acid/full.py @@ -49,6 +49,8 @@ def __init__(self, options=None, name="Full model", build=True): if build: self.build_model() + pybamm.citations.register("sulzer2019physical") + def set_porosity_submodel(self): self.submodels["porosity"] = pybamm.porosity.Full(self.param) 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 7154583a02..4255856d39 100644 --- a/pybamm/models/full_battery_models/lead_acid/higher_order.py +++ b/pybamm/models/full_battery_models/lead_acid/higher_order.py @@ -57,6 +57,8 @@ def __init__(self, options=None, name="Composite model", build=True): if build: self.build_model() + pybamm.citations.register("sulzer2019asymptotic") + def set_current_collector_submodel(self): cc = pybamm.current_collector diff --git a/pybamm/models/full_battery_models/lead_acid/loqs.py b/pybamm/models/full_battery_models/lead_acid/loqs.py index fc5b0d66b4..18cdb4ea2e 100644 --- a/pybamm/models/full_battery_models/lead_acid/loqs.py +++ b/pybamm/models/full_battery_models/lead_acid/loqs.py @@ -52,6 +52,8 @@ def __init__(self, options=None, name="LOQS model", build=True): if self.options["dimensionality"] == 0: self.use_jacobian = False + pybamm.citations.register("sulzer2019asymptotic") + def set_external_circuit_submodel(self): """ Define how the external circuit defines the boundary conditions for the model, diff --git a/pybamm/models/full_battery_models/lithium_ion/dfn.py b/pybamm/models/full_battery_models/lithium_ion/dfn.py index 582629c921..74bf6ae34c 100644 --- a/pybamm/models/full_battery_models/lithium_ion/dfn.py +++ b/pybamm/models/full_battery_models/lithium_ion/dfn.py @@ -48,6 +48,8 @@ def __init__(self, options=None, name="Doyle-Fuller-Newman model", build=True): if build: self.build_model() + pybamm.citations.register("doyle1993modeling") + def set_porosity_submodel(self): self.submodels["porosity"] = pybamm.porosity.Constant(self.param) diff --git a/pybamm/models/full_battery_models/lithium_ion/spm.py b/pybamm/models/full_battery_models/lithium_ion/spm.py index 023b64bc76..127399bb69 100644 --- a/pybamm/models/full_battery_models/lithium_ion/spm.py +++ b/pybamm/models/full_battery_models/lithium_ion/spm.py @@ -48,6 +48,8 @@ def __init__(self, options=None, name="Single Particle Model", build=True): if build: self.build_model() + pybamm.citations.register("marquis2019asymptotic") + def set_porosity_submodel(self): self.submodels["porosity"] = pybamm.porosity.Constant(self.param) diff --git a/pybamm/models/full_battery_models/lithium_ion/spme.py b/pybamm/models/full_battery_models/lithium_ion/spme.py index a400d0dff2..18c5bf14d8 100644 --- a/pybamm/models/full_battery_models/lithium_ion/spme.py +++ b/pybamm/models/full_battery_models/lithium_ion/spme.py @@ -51,6 +51,8 @@ def __init__( if build: self.build_model() + pybamm.citations.register("marquis2019asymptotic") + def set_porosity_submodel(self): self.submodels["porosity"] = pybamm.porosity.Constant(self.param) diff --git a/pybamm/parameters/parameter_sets.py b/pybamm/parameters/parameter_sets.py index f959ca36d3..3b6747c683 100644 --- a/pybamm/parameters/parameter_sets.py +++ b/pybamm/parameters/parameter_sets.py @@ -2,35 +2,9 @@ # Parameter sets from papers # """ -Parameter sets from papers: - -Lithium-ion ------------ -Marquis2019 - Scott G. Marquis, Valentin Sulzer, Robert Timms, Colin P. Please, and S. Jon - Chapman. "An asymptotic derivation of a single particle model with electrolyte." - `arXiv preprint arXiv:1905.12553 `_ (2019). - -NCA_Kim2011 - Kim, G. H., Smith, K., Lee, K. J., Santhanagopalan, S., & Pesaran, A. - (2011). Multi-domain modeling of lithium-ion batteries encompassing - multi-physics in varied length scales. Journal of The Electrochemical - Society, 158(8), A955-A969. - -Chen2020 - Chang-Hui Chen, Ferran Brosa Planella, Kieran O’Regan, Dominika Gastol, W. Dhammika - Widanage, and Emma Kendrick. "Development of Experimental Techniques for - Parameterization of Multi-scale Lithium-ion Battery Models." Submitted for - publication (2020). - - -Lead-acid ---------- -Sulzer2019 - V. Sulzer, S. J. Chapman, C. P. Please, D. A. Howey, and C. W.Monroe, “Faster - lead-acid battery simulations from porous-electrode theory: Part I. Physical model.” - `Journal of the Electrochemical Society `_, - 166(12), 2363 (2019). +Parameter sets from papers. The 'citation' entry provides a reference to the appropriate +paper in the file "pybamm/CITATIONS.txt". To see which parameter sets have been used in +your simulation, add the line "pybamm.print_citations()" to your script. """ # @@ -44,6 +18,7 @@ "cathode": "lico2_Marquis2019", "electrolyte": "lipf6_Marquis2019", "experiment": "1C_discharge_from_full_Marquis2019", + "citation": "marquis2019asymptotic", } NCA_Kim2011 = { @@ -54,6 +29,7 @@ "cathode": "nca_Kim2011", "electrolyte": "lipf6_Kim2011", "experiment": "1C_discharge_from_full_Kim2011", + "citation": "kim2011multi", } Chen2020 = { @@ -64,6 +40,7 @@ "cathode": "nmc_Chen2020", "electrolyte": "lipf6_Nyman2008", "experiment": "1C_discharge_from_full_Chen2020", + "citation": "Chen2020", } # # Lead-acid @@ -76,4 +53,5 @@ "cathode": "lead_dioxide_Sulzer2019", "electrolyte": "sulfuric_acid_Sulzer2019", "experiment": "1C_discharge_from_full", + "citation": "sulzer2019physical", } diff --git a/pybamm/parameters/parameter_values.py b/pybamm/parameters/parameter_values.py index ad1dbd3a04..dd596e746f 100644 --- a/pybamm/parameters/parameter_values.py +++ b/pybamm/parameters/parameter_values.py @@ -143,6 +143,11 @@ def update_from_chemistry(self, chemistry): path=component_path, ) + # register citations + if "citation" in chemistry: + citation = chemistry["citation"] + pybamm.citations.register(citation) + def read_parameters_csv(self, filename): """Reads parameters from csv file into dict. diff --git a/pybamm/simulation.py b/pybamm/simulation.py index 2983a34d4e..2a5387feee 100644 --- a/pybamm/simulation.py +++ b/pybamm/simulation.py @@ -419,7 +419,11 @@ def solve( # Make sure we take at least 2 timesteps npts = max(int(round(dt / exp_inputs["period"])) + 1, 2) self.step( - dt, npts=npts, external_variables=external_variables, inputs=inputs + dt, + solver=solver, + npts=npts, + external_variables=external_variables, + inputs=inputs, ) # Only allow events specified by experiment if not ( diff --git a/pybamm/solvers/base_solver.py b/pybamm/solvers/base_solver.py index 806015e900..648edf6469 100644 --- a/pybamm/solvers/base_solver.py +++ b/pybamm/solvers/base_solver.py @@ -424,6 +424,8 @@ def jac_fn(y0_alg): method=self.root_method, tol=self.root_tol, ) + pybamm.citations.register("virtanen2020scipy") + # Set outputs y0_alg = sol.x success = sol.success diff --git a/pybamm/solvers/casadi_solver.py b/pybamm/solvers/casadi_solver.py index 34fd740438..1029a8560e 100644 --- a/pybamm/solvers/casadi_solver.py +++ b/pybamm/solvers/casadi_solver.py @@ -72,6 +72,8 @@ def __init__( self.options = {} self.methods = {} + pybamm.citations.register("Andersson2019") + def _integrate(self, model, t_eval, inputs=None): """ Solve a DAE model defined by residuals with initial conditions y0. diff --git a/pybamm/solvers/idaklu_solver.py b/pybamm/solvers/idaklu_solver.py index be4a1932cc..138524b5ad 100644 --- a/pybamm/solvers/idaklu_solver.py +++ b/pybamm/solvers/idaklu_solver.py @@ -45,6 +45,9 @@ def __init__( super().__init__("ida", rtol, atol, root_method, root_tol, max_steps) self.name = "IDA KLU solver" + pybamm.citations.register("hindmarsh2000pvode") + pybamm.citations.register("hindmarsh2005sundials") + def set_atol_by_variable(self, variables_with_tols, model): """ A method to set the absolute tolerances in the solver by state variable. diff --git a/pybamm/solvers/scikits_dae_solver.py b/pybamm/solvers/scikits_dae_solver.py index 74620cafed..65f06caf07 100644 --- a/pybamm/solvers/scikits_dae_solver.py +++ b/pybamm/solvers/scikits_dae_solver.py @@ -50,6 +50,10 @@ def __init__( super().__init__(method, rtol, atol, root_method, root_tol, max_steps) self.name = "Scikits DAE solver ({})".format(method) + pybamm.citations.register("scikits-odes") + pybamm.citations.register("hindmarsh2000pvode") + pybamm.citations.register("hindmarsh2005sundials") + def _integrate(self, model, t_eval, inputs=None): """ Solve a model defined by dydt with initial conditions y0. diff --git a/pybamm/solvers/scikits_ode_solver.py b/pybamm/solvers/scikits_ode_solver.py index 196c05e97a..b8bf57854c 100644 --- a/pybamm/solvers/scikits_ode_solver.py +++ b/pybamm/solvers/scikits_ode_solver.py @@ -43,6 +43,10 @@ def __init__(self, method="cvode", rtol=1e-6, atol=1e-6, linsolver="dense"): self.ode_solver = True self.name = "Scikits ODE solver ({})".format(method) + pybamm.citations.register("scikits-odes") + pybamm.citations.register("hindmarsh2000pvode") + pybamm.citations.register("hindmarsh2005sundials") + def _integrate(self, model, t_eval, inputs=None): """ Solve a model defined by dydt with initial conditions y0. diff --git a/pybamm/solvers/scipy_solver.py b/pybamm/solvers/scipy_solver.py index 100ecf8592..980332183b 100644 --- a/pybamm/solvers/scipy_solver.py +++ b/pybamm/solvers/scipy_solver.py @@ -24,6 +24,7 @@ def __init__(self, method="BDF", rtol=1e-6, atol=1e-6): super().__init__(method, rtol, atol) self.ode_solver = True self.name = "Scipy solver ({})".format(method) + pybamm.citations.register("virtanen2020scipy") def _integrate(self, model, t_eval, inputs=None): """ diff --git a/tests/unit/test_citations.py b/tests/unit/test_citations.py new file mode 100644 index 0000000000..cb7a064c7c --- /dev/null +++ b/tests/unit/test_citations.py @@ -0,0 +1,130 @@ +# +# Tests the citations class. +# +import pybamm +import unittest + + +class TestCitations(unittest.TestCase): + def test_citations(self): + citations = pybamm.citations + citations._reset() + # Default papers should be in both _all_citations dict and in the papers to cite + self.assertIn("sulzer2020python", citations._all_citations.keys()) + self.assertIn("sulzer2020python", citations._papers_to_cite) + # Non-default papers should only be in the _all_citations dict + self.assertIn("sulzer2019physical", citations._all_citations.keys()) + self.assertNotIn("sulzer2019physical", citations._papers_to_cite) + + # test key error + with self.assertRaises(KeyError): + citations.register("not a citation") + + def test_print_citations(self): + pybamm.citations._reset() + pybamm.print_citations("test_citations.txt") + pybamm.citations._papers_to_cite = set() + pybamm.print_citations() + + def test_Andersson_2019(self): + citations = pybamm.citations + citations._reset() + self.assertNotIn("Andersson2019", citations._papers_to_cite) + pybamm.CasadiConverter() + self.assertIn("Andersson2019", citations._papers_to_cite) + + def test_marquis_2019(self): + # Test that calling relevant bits of code adds the right paper to citations + citations = pybamm.citations + + citations._reset() + self.assertNotIn("marquis2019asymptotic", citations._papers_to_cite) + pybamm.lithium_ion.SPM(build=False) + self.assertIn("marquis2019asymptotic", citations._papers_to_cite) + + citations._reset() + pybamm.lithium_ion.SPMe(build=False) + self.assertIn("marquis2019asymptotic", citations._papers_to_cite) + + def test_doyle_1993(self): + citations = pybamm.citations + citations._reset() + self.assertNotIn("doyle1993modeling", citations._papers_to_cite) + pybamm.lithium_ion.DFN(build=False) + self.assertIn("doyle1993modeling", citations._papers_to_cite) + + def test_sulzer_2019(self): + # Test that calling relevant bits of code adds the right paper to citations + citations = pybamm.citations + + citations._reset() + self.assertNotIn("sulzer2019asymptotic", citations._papers_to_cite) + pybamm.lead_acid.LOQS(build=False) + self.assertIn("sulzer2019asymptotic", citations._papers_to_cite) + + citations._reset() + pybamm.lead_acid.FOQS(build=False) + self.assertIn("sulzer2019asymptotic", citations._papers_to_cite) + + citations._reset() + pybamm.lead_acid.Composite(build=False) + self.assertIn("sulzer2019asymptotic", citations._papers_to_cite) + + citations._reset() + pybamm.lead_acid.Full(build=False) + self.assertIn("sulzer2019physical", citations._papers_to_cite) + + def test_parameter_citations(self): + citations = pybamm.citations + + citations._reset() + pybamm.ParameterValues(chemistry=pybamm.parameter_sets.Chen2020) + self.assertIn("Chen2020", citations._papers_to_cite) + + citations._reset() + pybamm.ParameterValues(chemistry=pybamm.parameter_sets.NCA_Kim2011) + self.assertIn("kim2011multi", citations._papers_to_cite) + + citations._reset() + pybamm.ParameterValues(chemistry=pybamm.parameter_sets.Marquis2019) + self.assertIn("marquis2019asymptotic", citations._papers_to_cite) + + citations._reset() + pybamm.ParameterValues(chemistry=pybamm.parameter_sets.Sulzer2019) + self.assertIn("sulzer2019physical", citations._papers_to_cite) + + def test_solver_citations(self): + # Test that solving each solver adds the right citations + citations = pybamm.citations + + citations._reset() + self.assertNotIn("virtanen2020scipy", citations._papers_to_cite) + pybamm.ScipySolver() + self.assertIn("virtanen2020scipy", citations._papers_to_cite) + + if pybamm.have_scikits_odes(): + citations._reset() + self.assertNotIn("scikits-odes", citations._papers_to_cite) + pybamm.ScikitsOdeSolver() + self.assertIn("scikits-odes", citations._papers_to_cite) + + citations._reset() + self.assertNotIn("scikits-odes", citations._papers_to_cite) + pybamm.ScikitsDaeSolver() + self.assertIn("scikits-odes", citations._papers_to_cite) + + if pybamm.have_idaklu(): + citations._reset() + self.assertNotIn("hindmarsh2005sundials", citations._papers_to_cite) + pybamm.IDAKLUSolver() + self.assertIn("hindmarsh2005sundials", citations._papers_to_cite) + + +if __name__ == "__main__": + print("Add -v for more debug output") + import sys + + if "-v" in sys.argv: + debug = True + pybamm.settings.debug_mode = True + unittest.main()