Coverage for src/python/dandeliion/client/__init__.py: 97%

1# built-in modules

2 from pathlib import Path

3 from typing import Union

4

5# custom modules

6 from .simulator import Simulator

7 from .solution import Solution

8

9# third-party modules

10 from pybamm import Experiment

11 from bpx import parse_bpx_obj, parse_bpx_file, BPX

12

13

14 def _convert_experiment(experiment: Experiment):

15 """

16 converts pybamm experiment into dict

17 """

18 operating_conditions, period, temperature, termination = experiment.args

19 steps = []

20 for cond in operating_conditions:

21 if isinstance(cond, tuple):

22 steps += list(cond)

23 else:

24 steps.append(cond)

25

26 return {

27 "Instructions": steps,

28 "Period": period,

29 "Temperature": temperature,

30 "Termination": termination,

31 }

32

33

34 def solve(

35 simulator: Simulator,

36 params: Union[str, Path, dict, BPX],

37 experiment: Experiment,

38 extra_params: dict = None,

39) -> Solution:

40

41 """Method for submitting/running a Dandeliion simulation.

42

43 Args:

44 simulator (Simulator): instance of simulator class providing information

45 to connect to simulation server

46 params (str|Path|dict|BPX): path to BPX parameter file or already read-in valid BPX as dict or BPX object

47 experiment (Experiment): instance of pybamm Experiment defining steps

48 extra_params (dict, optional): extra parameters e.g. simulation mesh, choice of discretisation method

49 and initial conditions specified in the dictionary

50 (if none or only subset is provided, either user-defined values

51 stored in the bpx or, if not present, default values will be used instead)

52 Returns:

53 :class:`Solution`: solution for this simulation run

54 """

55

56 # load & validate BPX

57 if isinstance(params, dict):

58 params = parse_bpx_obj(params)

59 elif isinstance(params, str) or isinstance(params, Path):

60 params = parse_bpx_file(params)

61 elif not isinstance(params, BPX):

62 raise ValueError("`params` has to be either `dict`, `str`, `Path` or `BPX`")

63

64 # turn back into dict

65 params = params.model_dump(by_alias=True, exclude_unset=True)

66

67 if (

68 "User-defined" not in params['Parameterisation'] or

69 params['Parameterisation']["User-defined"] is None

70 ):

71 params['Parameterisation']["User-defined"] = {}

72

73 # add experiment

74 params['Parameterisation']["User-defined"]["DandeLiion: Experiment"] = _convert_experiment(experiment)

75

76 # add/overwrite extra parameters

77 if extra_params:

78 for param, value in extra_params.items():

79 params['Parameterisation']["User-defined"][f"DandeLiion: {param}"] = value

80

81 return simulator.submit(parameters=params, is_blocking=True)