How to run a multi-simulation

The objective of this tutorial is to explain the definition, the postprocessings and the storage of a multi-simulation in Pyleecan.

The following organization aims to enable:

  • multi-simulation of a single model or a complete workflow

  • multi-simulation of multi-simulations

  • parallelization to speed up calculations

  • errors management

  • built-in postprocessings

  • efficient storage

VarParam class

A simulation, as defined by the Simulation object, corresponds to the computation of machine quantities on a single operating point. A multi-simulation is defined as a list of simulations, all based on a reference simulation with variations of its parameters.

To define a multi-simulation in pyleecan, first the reference simulation must be defined as a Simulation object. Then an optional VarParam object (that inherits from an abstract VarSimu class) is set as a property of the reference simulation object. VarParam object defines how to generate the simulation list, how to parallelize (or not) the computation and which data to gather. To do so, VarParam class contains :

Attribute

Type

Description

paramexplorer_list

91ParamExplorer93

simulation parameters to variate

datakeeper_list

91DataKeeper93

output data to keep

nb_proc

int

number of processes used

is_keep_all_output

bool

True to keep every output

stop_if_error

bool

error tolerance

ref_simu_index

int

Index of the reference simulation, if None the
reference simulation is not in the multi-simulation

nb_simu

int

number of simulations

On a side note, as all pyleecan object, VarParam also has a parent property that links to the reference simulation.

Input parameters: ParamExplorerSet

The parameter to change in the reference simulation and how are defined with ParamExplorer objects. ParamExplorerSet is a ParamExplorer that enables to set the parameters variations from a list of values. The parameters to change are defined with a function (setter) which enables to do complex operation with the value as argument (cf example below). This setter can also be defined as a string to target directly a parameter. When generating the list of simulations to run, the function is executed before running the simulation to set the parameters as expected. The ParamExplorerSet has five attributes:

Attribute

Type

Description

name

str

name of the data

symbol

str

short name to access in XOutput

unit

str

data unit

setter

function

function that takes a Simulation and a
value in argument and modifies the
simulation

value

list

list that contains the different
parameter values to explore

When a VarParam is defined with several ParamExplorer, it will creates every simulation by making the cartesian product of every ParamExplorerSet values.

In the following example, two ParamExplorer are defined, the first one scales every parameter of the slot according to a single value, the second directly update the current matrix:

def slot_scale(simu, scale_factor):
   """Edit stator slot size according to a percentage

   Parameters
   ----------
   simu: Simulation
     simulation to modify
   scale_factor: float
     stator slot scale factor
   """
   simu.machine.stator.slot.W0 *= scale_factor
   simu.machine.stator.slot.W1 *= scale_factor
   simu.machine.stator.slot.W2 *= scale_factor
   simu.machine.stator.slot.H0 *= scale_factor
   simu.machine.stator.slot.H1 *= scale_factor

paramexplorer_list=[
    ParamExplorerSet(
        name = "Stator slot scale factor",
        symbol = "stat_slot",
        unit="",
        setter=slot_scale,
        value = [0.99, 1.01]
    ),
    ParamExplorerSet(
        name = "Current",
        symbol = "I",
        unit="A",
        setter="simu.input.Is.value",
        value = [array_current1, array_current2, array_current3]
    ),
]

A VarParam with both the ParamExplorer above creates the six following simulations:

simulation number

Stator slot scale factor

Stator current

1

0.99

array_current1

2

0.99

array_current2

3

0.99

array_current3

4

1.01

array_current1

5

1.01

array_current2

6

1.01

array_current3

Variables to keep: DataKeeper

VarParam contains a list of DataKeeper to specify which data to keep after each simulation by defining post-processing on Output object. A DataKeeper is a class with six attributes:

Attribute

Type

Description

name

str

name of the data

symbol

str

short name to access in XOutput

unit

str

data unit

keeper

function

function that takes an Output in argument and
returns a value

error_keeper

function

function that takes a Simulation in argument and
returns a value, this attribute permits to handle
errors and attribute permits to handle errors and
to put NaN values in the result matrices

result

list

list containing DataKeeper results for each simulation

This following datakeepers enable to store the average torque and the radial magnetic flux for each of the six simulations:

datakeeper_list = [
    DataKeeper(
        name = "Average Torque",
        unit = "N.m", 
        symbole = "Tem_av",
        keeper = lambda output: output.mag.Tem_av,
        error_keeper = lambda simu: np.nan
    ),
    DataKeeper(
        name = "Radial Magnetic Flux",
        unit = "H",
        symbol = "Br",
        keeper = lambda output: output.mag.Br,
        error_keeper = lambda simu: np.nan * np.zeros(
            len(simu.machine.time.value), len(simu.machine.angle.value)
        )
    )
]

DataKeepers with their results are stored in a dict whose keys are the data symbol. DataKeepers results contain results from DataKeeper.keeper(output) (or DataKeeper.error_keeper(simu) when the simulation raise an error).

Running VarParam

When the method Simulation.run is called, the reference simulation is executed first. Then, if a VarParam is defined, the corresponding list of simulations is generated and run. If a VarParam is defined, Simulation.run returns an XOutput object else it returns an Output.

XOutput class

XOutput is a daughter of Output that enables to store VarParam results:

Attribute

Type

Description

simu

Simulation

Reference Simulation

geo

OutGeo

Reference Simulation geometry output

elec

OutElec

Reference Simulation electrical module output

mag

OutMag

Reference Simulation magnetic module output

force

OutForce

Reference Simulation force module output

struct

OutStruct

Reference Simulation structural module output

post

OutPost

Reference Simulation post-processing settings

input_param

list

List of ParamExplorerSet containing
values for each simulation

output_list

list

List containing each Output

xoutput_dict

dict

Dictionnary containing VarParamDataKeeper

Reference simulation results are stored in the properties inherited from Output and other simulation results are stored in a list of Output and/or in a dict containing DataKeeper, according to VarParam parameters. Paramater variations are stored in a specific list of ParamExplorerSet created at the beginning of the simulation.

If VarParam.is_keep_all_output is True, then each output of each simulation is stored in the output_list. This option is set as False by default to avoid memory issues.

The class has some getters to gather results: list slices can be extracted according to some input values e.g. extract average torque for simulations with a specific value of slot angle or a specific speed. To ease the access to the results, XOutput behaves like a dictionary to access directly to XOutput.xout_dict and like a list to access directly to XOuput.output_list. Furthermore, len(XOutput) returns the number of simulations, which is 6 in this case. For this example, the following call returns a list containing the average torque for each simulation with the stator scale factor set to 0.99.

xouput['Tem_av'].result[0:3]