Using Parallel Computing in fmdtools

This notebook will discuss how to use parallel programming in fmdtools, including: - how to set up a model for parallelism - syntax for using parallelism in simulation functions - considerations for optimizing computational performance in a model

[1]:
from ex_pump import *
from fmdtools.sim.sample import FaultDomain, FaultSample
import fmdtools.sim.propagate as propagate
import fmdtools.analyze as an

This notebook uses the pump example (see ex_pump.py) to illustrate the use of parallelism in fmdtools. This is fairly simple model, and thus it should be noted that there may be considerations with more complex models which may not be adequately covered here.

[2]:
mdl = Pump()
[3]:
result, mdlhist = propagate.nominal(mdl, desired_result='graph')
[4]:
fig, ax = result.graph.draw()
../../_images/examples_pump_Parallelism_Tutorial_5_0.png
[5]:
fig, ax = mdlhist.plot_line('flows.ee_1.s.current', 'flows.wat_2.s.flowrate')
../../_images/examples_pump_Parallelism_Tutorial_6_0.png

Model Checks

Before attempting to leverage parallelism in model execution, it can be helpful to check whether a model is compatible with python parallel computing libraries. In order for a model to be parallelized, it must be compatible with pickling–python’s method of data serialization. This is used in parallel programming methods to copy the model from the main process thread to the seperate processes of the pool.

fmdtools has two methods to check whether a model can be pickled, check_pickleability and check_model_pickleability. The main difference between these is that check_pickleability works for all objects (e.g. functions and flows), while check_model_pickleability gives more information for an overall model structure

[6]:
from fmdtools.define.object.base import check_pickleability
from fmdtools.define.architecture.base import check_model_pickleability
[7]:
unpickleable_attributes = check_pickleability(mdl)
The object is pickleable
[8]:
check_model_pickleability(mdl)
FLOWS
ee_1
The object is pickleable
sig_1
The object is pickleable
wat_1
The object is pickleable
wat_2
The object is pickleable
FUNCTIONS
import_ee
ee_out
The object is pickleable
import_water
wat_out
The object is pickleable
import_signal
sig_out
The object is pickleable
move_water
ee_in
sig_in
wat_in
wat_out
The object is pickleable
export_water
wat_in
The object is pickleable
MODEL
The object is pickleable

As you can see, this model is pickleable. However, this may not be the case for all structures if they rely on unpickleable data structures, one common one being iterators like .values().

Using Parallelism in Simulation

Parallelism generally requires using some external parallel processing toolkit. The syntax used by fmdtools methods is compatible with: - multiprocessing, python’s default parallel computing library - multiprocess, a fork of multiprocessing developed by The UQ Foundation - pathos, a broader parallel computing package developed by The UQ Foundation

And any other package that emulates multiprocessing.Pool

[9]:
import multiprocessing as mp
import multiprocess as ms

Parallelism can speed up simulation time when there is a large number of independent simulations to run. The prefered methods for using parallelism are to use a NominalApproach or SampleApproach with the methods: - propagate.singlefaults (for all single-fault scenarios in a static model with no approach) - propagate.approach (for sampling a set of faults) - propagate.nominal_approach (for simulating the model nominally over a set of parameters) - propagate.nested_approach (for sampling a set of faults over a set of model parameters)

These methods can be run in parallel by sending them a pool object from one of these modules as the optional pool argument. Further details on setting up and running an approach are provided in docs/Approach Use-Cases.ipynb

[10]:
pool = mp.Pool(4)
fd = FaultDomain(mdl)
fd.add_all()
fs = FaultSample(fd)
fs.add_fault_phases()
endclasses, mdlhists = propagate.fault_sample(mdl, fs, pool=pool)
#an.tabulate.simplefmea(endclasses)
SCENARIOS COMPLETE: 100%|██████████| 24/24 [00:01<00:00, 12.60it/s]
[11]:
pool
[11]:
<multiprocessing.pool.Pool state=TERMINATE pool_size=4>

Sometimes, it helps to “warm up” the pool. See, for example, how much longer per-second iterations take for the above compared to below:

[12]:
pool = mp.Pool(4)
endclasses, mdlhists = propagate.single_faults(mdl, pool=pool)
#an.tabulate.simplefmea(endclasses)
SCENARIOS COMPLETE: 100%|██████████| 8/8 [00:01<00:00,  4.94it/s]

It can also be helpful to verify that the results of parallel simulation and normal serial execution are the same:

[13]:
pool = mp.Pool(4)
endclasses_par, mdlhists = propagate.single_faults(mdl, pool=pool, close_pool=False)
#tab_par = an.tabulate.simplefmea(endclasses_par)
endclasses, mdlhists = propagate.single_faults(mdl)
#tab = an.tabulate.simplefmea(endclasses)
#tab - tab_par
SCENARIOS COMPLETE: 100%|██████████| 8/8 [00:01<00:00,  4.88it/s]
SCENARIOS COMPLETE: 100%|██████████| 8/8 [00:00<00:00, 38.65it/s]
[14]:
# pool = mp.Pool(4)
endclasses_par, mdlhists = propagate.fault_sample(mdl, fs, pool=pool)
#tab_par = an.tabulate.simplefmea(endclasses_par)
endclasses, mdlhists = propagate.fault_sample(mdl, fs)
#tab = an.tabulate.simplefmea(endclasses)
#tab - tab_par
pool
SCENARIOS COMPLETE: 100%|██████████| 24/24 [00:00<00:00, 125.74it/s]
SCENARIOS COMPLETE: 100%|██████████| 24/24 [00:00<00:00, 38.55it/s]
[14]:
<multiprocessing.pool.Pool state=TERMINATE pool_size=4>

While fmdtools built-in methods are the easiest way to leverage parallelism, it can also be used with custom arguments/methods to meet the needs of simulation. However, (on Windows) these methods need to be defined in an external module with an “if name==’main’:” statement, otherwise execution will hang from spawning new processes. This has to do with how multiprocessing works in windows.

To show how parellism can be leveraged manually for a desired use-case, below the model is run over the blockage fault mode at time t=1 with a different model parameter (delayed failure behavior), as defined in the parallelism_methods.py module in this folder.

[15]:
from parallelism_methods import delay_test
[16]:
results = delay_test()
results
[16]:
[endclass.rate:                     1e-05
 endclass.cost:        20125.000000000007
 endclass.expected_cost: 20125.000000000007,
 endclass.rate:                     1e-05
 endclass.cost:        20102.500000000007
 endclass.expected_cost: 20102.500000000007,
 endclass.rate:                     1e-05
 endclass.cost:        20080.000000000007
 endclass.expected_cost: 20080.000000000007,
 endclass.rate:                     1e-05
 endclass.cost:        20057.500000000007
 endclass.expected_cost: 20057.500000000007,
 endclass.rate:                     1e-05
 endclass.cost:        20035.000000000007
 endclass.expected_cost: 20035.000000000007,
 endclass.rate:                     1e-05
 endclass.cost:        15023.750000000005
 endclass.expected_cost: 15023.750000000005,
 endclass.rate:                     1e-05
 endclass.cost:        15023.750000000005
 endclass.expected_cost: 15023.750000000005,
 endclass.rate:                     1e-05
 endclass.cost:        15023.750000000005
 endclass.expected_cost: 15023.750000000005,
 endclass.rate:                     1e-05
 endclass.cost:        15023.750000000005
 endclass.expected_cost: 15023.750000000005,
 endclass.rate:                     1e-05
 endclass.cost:        15023.750000000005
 endclass.expected_cost: 15023.750000000005]

In this method, the model is run many times over a given fault with different delay parameters. It should be noted that this approach is not especially efficient, since the nominal scenario is simulated at each call of propagate.one_fault(). It is thus preferred to use the appropriate fault/parameter sampling approaches and propagate methods, since these methods only run the nominal simulation once for fault scenarios and can also use staged execution (copying the model at fault time for fault scenarios) to reduce the cost of each simulation.

Performance Comparison

Parallelism is often used in computation to speed up up a set of independent simulations. Conventionally, one might say it leads to a reduced computational cost of \(t/n\), where t was the original time of the set of processes, and n is the number of cores.

However, this computational performance increase is dependent on the implementation. In Python, there is some overhead from from communicating data structures in and out of parallel threads which can become a significant consideration when the data structures are large. Additionally, different Pools can execute more or less efficiently. Below these are each compared.

[17]:
import matplotlib.pyplot as plt
from parallelism_methods import compare_pools, instantiate_pools, terminate_pools
[18]:
cores=4
pools = instantiate_pools(cores)

Below is the baseline comparison, where the the following parameters characterize the sampling approach: - single faults: only the single-fault scenarios are considered - 3 points per phase: an evenly-spaced quadrature is sampled at each phase of operation (start, on, end) for the model - staged: the model is copied at each point in time where faults is injected during the model time to save computation - track: the entire model history is returned for each simulation

This is typical for a small model like this where the per-model expense is low.

[19]:
mdl=Pump(track='all')
fs = FaultSample(fd)
fs.add_fault_phases(args = (3,))

pools = instantiate_pools(5)
_ = compare_pools(mdl, fs, pools, staged=True, verbose=False)
C:\Users\dhulse\AppData\Local\anaconda3\lib\multiprocessing\pool.py:268: ResourceWarning: unclosed running multiprocessing pool <multiprocessing.pool.Pool state=RUN pool_size=4>
  _warn(f"unclosed running multiprocessing pool {self!r}",
ResourceWarning: Enable tracemalloc to get the object allocation traceback
C:\Users\dhulse\AppData\Local\anaconda3\lib\site-packages\multiprocess\pool.py:268: ResourceWarning: unclosed running multiprocessing pool <multiprocess.pool.Pool state=RUN pool_size=4>
  _warn(f"unclosed running multiprocessing pool {self!r}",
ResourceWarning: Enable tracemalloc to get the object allocation traceback
[20]:
exectimes = compare_pools(mdl, fs, pools, staged=True, verbose=False)
exectimes_baseline = exectimes
[21]:
fig = plt.figure(figsize=(9, 3),)
plt.bar(range(len(exectimes)), list(exectimes.values()), align='center')
plt.xticks(range(len(exectimes)), list(exectimes.keys()))
plt.title("Baseline Performance - Some faults, Staged, Normal Simulation, Full Model History")
plt.ylabel("Computational Time (s)")
plt.grid(axis='y')
../../_images/examples_pump_Parallelism_Tutorial_33_0.png

As shown, in this situation, both the multiprocessing and threadpool pools give computational performance increases.

Comparison: No Histories

In the below comparison, the same simulation approach is run, except without tracking a history of model states through the simulation.

[22]:
mdl=Pump(track='none')
exectimes = compare_pools(mdl, fs, pools, staged=True, verbose=False)
[23]:
fig = plt.figure(figsize=(9, 3),)
width = 0.8
plt.bar(range(len(exectimes)), list(exectimes.values()), align='center', color="blue", label="comparison")
plt.bar(range(len(exectimes_baseline)), list(exectimes_baseline.values()), align='center', color="gray", alpha=0.5, label="baseline")
plt.xticks(range(len(exectimes)), list(exectimes.keys()))
plt.title("Computational Performance - Many Faults, Staged, Normal Simulation, No Model History")
plt.ylabel("Computational Time (s)")
plt.grid(axis='y')
plt.legend()
[23]:
<matplotlib.legend.Legend at 0x2267cdcafb0>
../../_images/examples_pump_Parallelism_Tutorial_37_1.png

As shown, in this situation, the overall simulation expense decreases, even in the serial execution case.

Additionally, the case for using a parallel processing pool increases somewhat. This is because passing the model history back to the main process is nearly comparable in time to simulation itself.

As a result, removing it saves a large amount of computational time when using parallel processing.

Comparison: Many Faults

In the below comparison, many faults are injected in the system to increase the number of scenarios (ostensibly making the case better for parallelism)

[24]:
fs_many = FaultSample(fd)
fs_many.add_fault_phases(args = (7,))
mdl=Pump(track='all')
exectimes = compare_pools(mdl, fs_many, pools, staged=True, verbose=False)
[25]:
fig = plt.figure(figsize=(9, 3),)
width = 0.8
plt.bar(range(len(exectimes)), list(exectimes.values()), align='center', color="blue", label="comparison")
plt.bar(range(len(exectimes_baseline)), list(exectimes_baseline.values()), align='center', color="gray", alpha=0.8, label="baseline")
plt.xticks(range(len(exectimes)), list(exectimes.keys()))
plt.title("Computational Performance - Many Faults, Staged, Normal Simulation, Full Model History")
plt.ylabel("Computational Time (s)")
plt.grid(axis='y')
plt.legend()
[25]:
<matplotlib.legend.Legend at 0x2267ce85e70>
../../_images/examples_pump_Parallelism_Tutorial_41_1.png

As shown, increasing the number of joint-fault scenarios increases computational costs significantly–as would be expected.

In this situation, multiprocessing performs comparatively better, but only slightly–instead of taking 1/4 the time, it only takes about 1/2 the time.

Comparison: Long simulation

It may be of interest to simulate how the comparative performance changes for longer simulations. In this comparison, the simulation time is extended tenfold.

[26]:
mdl=Pump(sp=dict(times=(0,20, 500)), track='all')
exectimes = compare_pools(mdl, fs, pools, staged=True, verbose=False)
[27]:
fig = plt.figure(figsize=(9, 3),)
width = 0.8
plt.bar(range(len(exectimes)), list(exectimes.values()), align='center', color="blue", label="comparison")
plt.bar(range(len(exectimes_baseline)), list(exectimes_baseline.values()), align='center', color="gray", alpha=0.8, label="baseline")
plt.xticks(range(len(exectimes)), list(exectimes.keys()))
plt.title("Computational Performance - Normal Faults, Staged, Long Simulation, Full Model History")
plt.ylabel("Computational Time (s)")
plt.grid(axis='y')
plt.legend()
[27]:
<matplotlib.legend.Legend at 0x2267cef2110>
../../_images/examples_pump_Parallelism_Tutorial_45_1.png

As shown, the simulation time does increase significantly–about tenfold. In terms of comparative performance, pools other than multiprocessing now become competitive, though multiprocessing is still the fastest overall.

This shows the main case for using parallesism–speeding up long simulations. Short simulations unfortunately require a significant amount of overhead due to copying in and out of the individual thread and we thus see less of a case for them there.

Comparison: Long Simulation No Tracking

Finally, it may be interesting to see how performance is affected in long simulations when there is no tracking. This is because in these simulations, there should be very little overhead from creating the respective data structures, even when there is a long simulation. This comparison is shown below.

[28]:
mdl=Pump(sp=dict(times=(0,20, 500)), track='none')
exectimes = compare_pools(mdl, fs, pools, staged=True, verbose=False)
[29]:
fig = plt.figure(figsize=(9, 3),)
width = 0.8
plt.bar(range(len(exectimes)), list(exectimes.values()), align='center', color="blue", label="comparison")
plt.bar(range(len(exectimes_baseline)), list(exectimes_baseline.values()), align='center', color="gray", alpha=0.8, label="baseline")
plt.xticks(range(len(exectimes)), list(exectimes.keys()))
plt.title("Computational Performance - Normal Faults, Staged, Long Simulation, No Model History")
plt.ylabel("Computational Time (s)")
plt.grid(axis='y')
plt.legend()
[29]:
<matplotlib.legend.Legend at 0x2267d078760>
../../_images/examples_pump_Parallelism_Tutorial_49_1.png

As shown, removing the tracking makes the long simulations much take less time than the short simulation!

Comparison: Long Simulation Only Necessary Tracking

In practice, it can be necessary to track some states over time. Here we perform the same comparison using the ‘valstates’ option, which only tracks states which have been defined in the model to be necessary to track (using ‘valparams’)

[30]:
mdl=Pump(sp=dict(times=(0,20, 500))) # see default track for Pump
exectimes = compare_pools(mdl, fs, pools, staged=True, verbose=False)
[31]:
fig = plt.figure(figsize=(9, 3),)
width = 0.8
plt.bar(range(len(exectimes)), list(exectimes.values()), align='center', color="blue", label="comparison")
plt.bar(range(len(exectimes_baseline)), list(exectimes_baseline.values()), align='center', color="gray", alpha=0.8, label="baseline")
plt.xticks(range(len(exectimes)), list(exectimes.keys()))
plt.title("Computational Performance - Normal Faults, Staged, Long Simulation, Only Necessary History")
plt.ylabel("Computational Time (s)")
plt.grid(axis='y')
plt.legend()
[31]:
<matplotlib.legend.Legend at 0x2267d0e8460>
../../_images/examples_pump_Parallelism_Tutorial_53_1.png

As shown, only tracking a few variables results in similar computational time no tracking.

This is because a major computational performance limitation in this model is not necessarily the model simulation itself, but the generation, update, and passing of the history. So it is often best to only track necessary parameters when possible, rather than the entire model history.

Comparison: Lower Tracking Time Resolution

Finally, the number of recorded timesteps can be lowered to lower computational costs while still returning all relevant variables.

[32]:
mdl=Pump(sp=dict(times=(0,20, 500), track_times=("interval", 5)), track='all')
exectimes = compare_pools(mdl, fs, pools, staged=True, verbose=False)
[33]:
fig = plt.figure(figsize=(9, 3),)
width = 0.8
plt.bar(range(len(exectimes)), list(exectimes.values()), align='center', color="blue", label="comparison")
plt.bar(range(len(exectimes_baseline)), list(exectimes_baseline.values()), align='center', color="gray", alpha=0.8, label="baseline")
plt.xticks(range(len(exectimes)), list(exectimes.keys()))
plt.title("Computational Performance - Many Faults, Staged, Normal Simulation, Lower Time Resolution")
plt.ylabel("Computational Time (s)")
plt.grid(axis='y')
plt.legend()
[33]:
<matplotlib.legend.Legend at 0x2267cef2ad0>
../../_images/examples_pump_Parallelism_Tutorial_57_1.png

As shown, while lowering time resolution could theoretically lower computational time, it does not significantly change much in this example.

[34]:
terminate_pools(pools)

Comparison Conclusions:

Parallelism can the improve computational performance of a given resilience simulation approach. However, this improvement is dependent on the parameters of the simulation. Generally, the official python multiprocessing module seems consistently give the best performance improvement over a single-process execution, although this can change depending on the underlying model and modelling approach. There are additionally reasons you might choose other pools– multiprocess pools may enable more data structures in the model because they extend what can be communicated in and out of threads.

In general, one of the major considerations for optimization compuational time is not just the simulation of the model, but the size of the returned data structures. Minimizing the size of the returned data structures can reduce computational time both by reducing the time of an individual simulation and by reducing the parallelism overhead from copying these data structures in and out of parallel threads. However, it is important to recognize that for resilience assessment, one often needs a history of model states (or, at least, states of interest) to properly quantify the dynamic costs (i.e., \(\int C_f(t) dt\)). Indeed, in this model, only repair costs were able to be used in the comparison of non-tracked states, because the other dynamic costs required a history of their corresponding flows. Changing the number and size of tracked model states can influence the computational time, but only to a point–while one would expect lowering time-fidelity to have a significant effect, it does not because the overhead is less to do with filling the underlying data structures as it has to do with instantiating and returning them–a far more effective method is to only return the functions/flows which are needed by the model.

Further Computational Cost Reduction via Profiling

While parallelism and staged execution are helpful and relatively easy-to-implement methods of computational cost reduction, it can be helpful (especially for more complex models) to see what aspects of the model are taking the most computational time.

While staged execution was not explored here, it can make a difference when faults are to be injected near the end of the simulation by making it unnecessary to simulate up to the fault time. However, it is less helpful when model instantiation/copy time is a significant fraction of simulation time.

Python’s builtin cProfile package can ge used to see the relative computational times of different functions/processes.

[35]:
import cProfile
[36]:
mdl=Pump(sp=dict(track='all'))
prof = cProfile.run('propagate.nominal(mdl)', sort='tottime')
         72852 function calls (72428 primitive calls) in 0.037 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     2268    0.003    0.000    0.004    0.000 base.py:395(<listcomp>)
       56    0.002    0.000    0.025    0.000 function.py:403(prop_static)
     1124    0.002    0.000    0.002    0.000 base.py:374(<listcomp>)
     1124    0.002    0.000    0.006    0.000 base.py:406(get_all_roles)
     1124    0.002    0.000    0.005    0.000 base.py:388(<listcomp>)
      562    0.002    0.000    0.007    0.000 function.py:136(__call__)
     1124    0.001    0.000    0.002    0.000 time.py:96(return_mutables)
     2268    0.001    0.000    0.005    0.000 base.py:391(get_roles)
    10668    0.001    0.000    0.001    0.000 {built-in method builtins.getattr}
       50    0.001    0.000    0.001    0.000 base.py:194(<listcomp>)
       72    0.001    0.000    0.001    0.000 {built-in method builtins.dir}
     1124    0.001    0.000    0.009    0.000 base.py:372(find_mutables)
     1124    0.001    0.000    0.015    0.000 base.py:377(return_mutables)
  560/224    0.001    0.000    0.001    0.000 base.py:19(get_var)
       56    0.001    0.000    0.002    0.000 history.py:254(log)
     1124    0.001    0.000    0.001    0.000 base.py:399(get_roledicts)
     3970    0.001    0.000    0.001    0.000 {built-in method builtins.hasattr}
     1218    0.001    0.000    0.001    0.000 copy.py:66(copy)
     2710    0.001    0.000    0.001    0.000 base.py:68(return_mutables)
     1124    0.001    0.000    0.001    0.000 mode.py:266(return_mutables)
     7342    0.000    0.000    0.000    0.000 {method 'startswith' of 'str' objects}
      900    0.000    0.000    0.001    0.000 mode.py:440(has_fault)
       22    0.000    0.000    0.001    0.000 base.py:318(<listcomp>)
      113    0.000    0.000    0.002    0.000 ex_pump.py:396(behavior)
       40    0.000    0.000    0.005    0.000 base.py:197(init_roles)
       30    0.000    0.000    0.001    0.000 inspect.py:2279(_signature_from_function)
  257/229    0.000    0.000    0.000    0.000 copy.py:128(deepcopy)
      562    0.000    0.000    0.001    0.000 function.py:114(prop_arch_behaviors)
     3162    0.000    0.000    0.000    0.000 {built-in method recordclass._dataobject.astuple}
      226    0.000    0.000    0.001    0.000 base.py:239(set_field)
      562    0.000    0.000    0.001    0.000 function.py:129(prop_arch_faults_up)
      113    0.000    0.000    0.001    0.000 base.py:202(assign)
     1350    0.000    0.000    0.000    0.000 time.py:97(<genexpr>)
       60    0.000    0.000    0.000    0.000 inspect.py:2919(__init__)
     1124    0.000    0.000    0.000    0.000 base.py:403(<listcomp>)
     1124    0.000    0.000    0.000    0.000 base.py:410(<listcomp>)
      113    0.000    0.000    0.000    0.000 base.py:141(get_field_dict)
    60/30    0.000    0.000    0.001    0.000 inspect.py:2374(_signature_from_callable)
      300    0.000    0.000    0.000    0.000 __init__.py:180(add)
        1    0.000    0.000    0.028    0.028 propagate.py:1032(prop_one_scen)
     2335    0.000    0.000    0.000    0.000 {method 'get' of 'dict' objects}
       26    0.000    0.000    0.002    0.000 parameter.py:50(__init__)
      154    0.000    0.000    0.000    0.000 inspect.py:2636(__init__)
     1764    0.000    0.000    0.000    0.000 {built-in method builtins.isinstance}
      116    0.000    0.000    0.000    0.000 _collections_abc.py:767(__ior__)
       56    0.000    0.000    0.026    0.000 function.py:366(propagate)
       26    0.000    0.000    0.000    0.000 inspect.py:3205(__str__)
       26    0.000    0.000    0.000    0.000 base.py:97(set_arg_type)
      113    0.000    0.000    0.000    0.000 ex_pump.py:212(behavior)
     1257    0.000    0.000    0.000    0.000 {method 'copy' of 'set' objects}
       26    0.000    0.000    0.000    0.000 parameter.py:120(check_immutable)
1836/1826    0.000    0.000    0.000    0.000 {built-in method builtins.len}
      452    0.000    0.000    0.000    0.000 base.py:381(return_mutables)
    42/32    0.000    0.000    0.000    0.000 result.py:464(flatten)
      112    0.000    0.000    0.000    0.000 ex_pump.py:243(behavior)
      112    0.000    0.000    0.000    0.000 ex_pump.py:290(behavior)
       33    0.000    0.000    0.000    0.000 {method 'round' of 'numpy.ndarray' objects}
      900    0.000    0.000    0.000    0.000 {method 'intersection' of 'set' objects}
     1152    0.000    0.000    0.000    0.000 {method 'values' of 'dict' objects}
       10    0.000    0.000    0.005    0.000 base.py:428(__init__)
      909    0.000    0.000    0.000    0.000 {built-in method builtins.any}
       56    0.000    0.000    0.000    0.000 __init__.py:353(union)
       18    0.000    0.000    0.006    0.000 base.py:73(add_flex_role_obj)
       10    0.000    0.000    0.000    0.000 mode.py:269(init_faultmodes)
       56    0.000    0.000    0.002    0.000 base.py:202(log_hist)
      112    0.000    0.000    0.000    0.000 inspect.py:2720(__str__)
       14    0.000    0.000    0.000    0.000 base.py:69(find_any_phase_overlap)
      113    0.000    0.000    0.000    0.000 ex_pump.py:363(condfaults)
       30    0.000    0.000    0.001    0.000 base.py:431(create_hist)
      118    0.000    0.000    0.000    0.000 parameter.py:92(check_lim)
      113    0.000    0.000    0.000    0.000 base.py:189(<dictcomp>)
       30    0.000    0.000    0.000    0.000 inspect.py:1967(_signature_bound_method)
      118    0.000    0.000    0.001    0.000 __init__.py:65(__init__)
      280    0.000    0.000    0.000    0.000 history.py:34(is_known_mutable)
       26    0.000    0.000    0.000    0.000 base.py:70(get_true_fields)
       26    0.000    0.000    0.000    0.000 parameter.py:141(check_type)
      154    0.000    0.000    0.000    0.000 enum.py:359(__call__)
       12    0.000    0.000    0.000    0.000 time.py:103(set_timestep)
      624    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
    32/30    0.000    0.000    0.005    0.000 base.py:173(init_roletypes)
      184    0.000    0.000    0.000    0.000 inspect.py:2968(<genexpr>)
       56    0.000    0.000    0.000    0.000 function.py:312(set_vars)
    22/20    0.000    0.000    0.005    0.000 base.py:106(__init__)
      344    0.000    0.000    0.000    0.000 {method 'split' of 'str' objects}
      112    0.000    0.000    0.000    0.000 ex_pump.py:269(behavior)
       33    0.000    0.000    0.000    0.000 base.py:83(get_timerange)
      224    0.000    0.000    0.000    0.000 __init__.py:304(__iter__)
      474    0.000    0.000    0.000    0.000 {method 'join' of 'str' objects}
       50    0.000    0.000    0.002    0.000 base.py:193(find_roletype_initiators)
      293    0.000    0.000    0.000    0.000 {method 'update' of 'set' objects}
       78    0.000    0.000    0.000    0.000 result.py:317(__setattr__)
       26    0.000    0.000    0.002    0.000 parameter.py:164(check_pickle)
      344    0.000    0.000    0.000    0.000 {built-in method builtins.setattr}
      105    0.000    0.000    0.000    0.000 result.py:298(items)
       14    0.000    0.000    0.001    0.000 base.py:61(__init__)
       10    0.000    0.000    0.000    0.000 mode.py:204(__init__)
      113    0.000    0.000    0.000    0.000 ex_pump.py:387(indicate_over_pressure)
       64    0.000    0.000    0.000    0.000 common.py:26(get_sub_include)
       30    0.000    0.000    0.000    0.000 inspect.py:66(get_annotations)
       78    0.000    0.000    0.000    0.000 __init__.py:1091(__init__)
      113    0.000    0.000    0.000    0.000 ex_pump.py:194(condfaults)
        6    0.000    0.000    0.000    0.000 result.py:348(all_with)
      226    0.000    0.000    0.000    0.000 {built-in method builtins.min}
       30    0.000    0.000    0.000    0.000 inspect.py:612(unwrap)
       26    0.000    0.000    0.000    0.000 base.py:77(<listcomp>)
      168    0.000    0.000    0.000    0.000 __init__.py:74(__len__)
       26    0.000    0.000    0.000    0.000 base.py:148(init_track)
       18    0.000    0.000    0.005    0.000 base.py:509(init_obj)
       10    0.000    0.000    0.005    0.001 base.py:160(add_sim)
      408    0.000    0.000    0.000    0.000 inspect.py:2698(kind)
       28    0.000    0.000    0.000    0.000 fromnumeric.py:865(sort)
      118    0.000    0.000    0.000    0.000 base.py:137(set_arg_as_type)
       33    0.000    0.000    0.000    0.000 {built-in method numpy.arange}
       10    0.000    0.000    0.005    0.001 function.py:153(add_fxn)
       56    0.000    0.000    0.000    0.000 base.py:129(get_hist_ind)
       12    0.000    0.000    0.004    0.000 base.py:174(__init__)
       56    0.000    0.000    0.000    0.000 __init__.py:130(copy)
      313    0.000    0.000    0.000    0.000 {built-in method builtins.id}
       56    0.000    0.000    0.000    0.000 propagate.py:1004(check_end_condition)
       22    0.000    0.000    0.001    0.000 base.py:316(init_indicators)
      263    0.000    0.000    0.000    0.000 {method 'items' of 'dict' objects}
       30    0.000    0.000    0.001    0.000 inspect.py:2997(from_callable)
      245    0.000    0.000    0.000    0.000 copy.py:182(_deepcopy_atomic)
       26    0.000    0.000    0.000    0.000 numerictypes.py:357(issubdtype)
       31    0.000    0.000    0.000    0.000 base.py:98(get_histrange)
       30    0.000    0.000    0.000    0.000 inspect.py:3013(replace)
       33    0.000    0.000    0.000    0.000 fromnumeric.py:53(_wrapfunc)
       26    0.000    0.000    0.000    0.000 common.py:60(is_numeric)
      278    0.000    0.000    0.000    0.000 inspect.py:2686(name)
       86    0.000    0.000    0.000    0.000 {method 'format' of 'str' objects}
        1    0.000    0.000    0.000    0.000 ex_pump.py:494(find_classification)
       12    0.000    0.000    0.000    0.000 time.py:82(__init__)
       42    0.000    0.000    0.000    0.000 result.py:141(check_include_errors)
       56    0.000    0.000    0.000    0.000 ex_pump.py:471(indicate_finished)
       56    0.000    0.000    0.000    0.000 ex_pump.py:490(indicate_on)
       33    0.000    0.000    0.000    0.000 fromnumeric.py:3269(round)
      154    0.000    0.000    0.000    0.000 enum.py:678(__new__)
        2    0.000    0.000    0.000    0.000 graph.py:961(add_edges_from)
        1    0.000    0.000    0.037    0.037 {built-in method builtins.exec}
       58    0.000    0.000    0.000    0.000 base.py:23(check_role)
       63    0.000    0.000    0.000    0.000 __init__.py:1118(__contains__)
       52    0.000    0.000    0.000    0.000 numerictypes.py:283(issubclass_)
        4    0.000    0.000    0.000    0.000 parameter.py:160(copy_with_vals)
        8    0.000    0.000    0.000    0.000 result.py:307(__getattr__)
       28    0.000    0.000    0.000    0.000 {built-in method numpy.asanyarray}
       30    0.000    0.000    0.001    0.000 inspect.py:3251(signature)
        2    0.000    0.000    0.007    0.003 ex_pump.py:443(init_architecture)
        8    0.000    0.000    0.000    0.000 history.py:184(init_att)
       10    0.000    0.000    0.005    0.000 function.py:58(__init__)
       10    0.000    0.000    0.000    0.000 base.py:505(check_flows)
       12    0.000    0.000    0.000    0.000 base.py:188(init_hist)
      246    0.000    0.000    0.000    0.000 {built-in method builtins.iter}
       10    0.000    0.000    0.000    0.000 base.py:463(create_arch_kwargs)
       60    0.000    0.000    0.000    0.000 inspect.py:277(isfunction)
       52    0.000    0.000    0.000    0.000 __init__.py:1098(__len__)
        4    0.000    0.000    0.000    0.000 graph.py:563(add_nodes_from)
       55    0.000    0.000    0.000    0.000 __init__.py:1108(__setitem__)
       10    0.000    0.000    0.000    0.000 function.py:97(update_seed)
        1    0.000    0.000    0.037    0.037 propagate.py:484(nom_helper)
       28    0.000    0.000    0.000    0.000 {method 'copy' of 'numpy.ndarray' objects}
       10    0.000    0.000    0.000    0.000 function.py:73(return_faultmodes)
       14    0.000    0.000    0.000    0.000 base.py:74(<listcomp>)
       26    0.000    0.000    0.000    0.000 {built-in method numpy.array}
        6    0.000    0.000    0.000    0.000 base.py:350(init_indicator_hist)
       14    0.000    0.000    0.000    0.000 {built-in method recordclass._dataobject.asdict}
      8/2    0.000    0.000    0.000    0.000 copy.py:227(_deepcopy_dict)
      154    0.000    0.000    0.000    0.000 {method 'isidentifier' of 'str' objects}
        2    0.000    0.000    0.008    0.004 base.py:34(__init__)
       28    0.000    0.000    0.000    0.000 {method 'sort' of 'numpy.ndarray' objects}
       12    0.000    0.000    0.000    0.000 function.py:448(<listcomp>)
      113    0.000    0.000    0.000    0.000 {method 'clear' of 'set' objects}
       33    0.000    0.000    0.000    0.000 {built-in method _abc._abc_instancecheck}
       14    0.000    0.000    0.000    0.000 base.py:71(<dictcomp>)
      113    0.000    0.000    0.000    0.000 {method 'copy' of 'list' objects}
        1    0.000    0.000    0.000    0.000 propagate.py:1132(get_result)
       10    0.000    0.000    0.000    0.000 base.py:525(<listcomp>)
       32    0.000    0.000    0.000    0.000 base.py:142(check_slots)
        2    0.000    0.000    0.000    0.000 function.py:207(build)
        2    0.000    0.000    0.001    0.000 base.py:240(new_params)
        1    0.000    0.000    0.000    0.000 {method 'reduce' of 'numpy.ufunc' objects}
        1    0.000    0.000    0.037    0.037 propagate.py:196(nominal)
        8    0.000    0.000    0.001    0.000 base.py:120(add_flow)
      112    0.000    0.000    0.000    0.000 {method 'index' of 'list' objects}
        2    0.000    0.000    0.000    0.000 function.py:215(<listcomp>)
       80    0.000    0.000    0.000    0.000 {built-in method builtins.issubclass}
        2    0.000    0.000    0.000    0.000 function.py:219(construct_graph)
       56    0.000    0.000    0.000    0.000 {method 'values' of 'mappingproxy' objects}
       33    0.000    0.000    0.000    0.000 abc.py:117(__instancecheck__)
       10    0.000    0.000    0.000    0.000 base.py:443(<dictcomp>)
        4    0.000    0.000    0.000    0.000 base.py:333(create_hist)
       10    0.000    0.000    0.000    0.000 base.py:482(update_contained_modes)
        2    0.000    0.000    0.000    0.000 base.py:190(build)
        1    0.000    0.000    0.037    0.037 <string>:1(<module>)
       20    0.000    0.000    0.000    0.000 graph.py:1315(neighbors)
       30    0.000    0.000    0.000    0.000 inspect.py:632(_is_wrapper)
        2    0.000    0.000    0.000    0.000 function.py:258(return_faultmodes)
       42    0.000    0.000    0.000    0.000 result.py:149(check_include_error)
        1    0.000    0.000    0.000    0.000 history.py:320(cut)
       10    0.000    0.000    0.000    0.000 __init__.py:201(update)
        8    0.000    0.000    0.000    0.000 base.py:87(create_hist)
       20    0.000    0.000    0.000    0.000 reportviews.py:527(__iter__)
       14    0.000    0.000    0.000    0.000 base.py:73(<listcomp>)
        4    0.000    0.000    0.000    0.000 base.py:320(init_hist_att)
       10    0.000    0.000    0.000    0.000 base.py:212(get_flows)
        8    0.000    0.000    0.000    0.000 result.py:122(get_dict_attr)
        2    0.000    0.000    0.008    0.004 function.py:126(__init__)
       56    0.000    0.000    0.000    0.000 {built-in method from_iterable}
       12    0.000    0.000    0.000    0.000 copy.py:243(_keep_alive)
        8    0.000    0.000    0.000    0.000 function.py:216(<listcomp>)
        1    0.000    0.000    0.000    0.000 function.py:231(calc_repaircost)
       60    0.000    0.000    0.000    0.000 {method 'keys' of 'dict' objects}
        2    0.000    0.000    0.000    0.000 functools.py:961(__get__)
       10    0.000    0.000    0.000    0.000 base.py:470(<dictcomp>)
       90    0.000    0.000    0.000    0.000 {built-in method builtins.callable}
        2    0.000    0.000    0.008    0.004 base.py:274(new)
       10    0.000    0.000    0.000    0.000 base.py:520(<listcomp>)
       60    0.000    0.000    0.000    0.000 inspect.py:3005(parameters)
        1    0.000    0.000    0.000    0.000 fromnumeric.py:71(_wrapreduction)
        2    0.000    0.000    0.000    0.000 {built-in method builtins.sum}
        2    0.000    0.000    0.000    0.000 copy.py:259(_reconstruct)
       40    0.000    0.000    0.000    0.000 __init__.py:165(__contains__)
        2    0.000    0.000    0.000    0.000 graph.py:332(__init__)
       18    0.000    0.000    0.000    0.000 inspect.py:191(isclass)
        2    0.000    0.000    0.000    0.000 function.py:210(<listcomp>)
       10    0.000    0.000    0.000    0.000 base.py:216(<dictcomp>)
        2    0.000    0.000    0.000    0.000 _collections_abc.py:991(update)
        2    0.000    0.000    0.000    0.000 isolate.py:85(<genexpr>)
       48    0.000    0.000    0.000    0.000 copy.py:107(_copy_immutable)
        4    0.000    0.000    0.000    0.000 base.py:205(<dictcomp>)
       33    0.000    0.000    0.000    0.000 fromnumeric.py:3265(_round_dispatcher)
        4    0.000    0.000    0.000    0.000 state.py:296(init_hist_att)
       10    0.000    0.000    0.000    0.000 base.py:552(is_dynamic)
       60    0.000    0.000    0.000    0.000 {built-in method builtins.repr}
       52    0.000    0.000    0.000    0.000 {method 'update' of 'dict' objects}
        2    0.000    0.000    0.000    0.000 function.py:212(<listcomp>)
        2    0.000    0.000    0.000    0.000 base.py:52(init_flexible_roles)
       28    0.000    0.000    0.000    0.000 fromnumeric.py:861(_sort_dispatcher)
        8    0.000    0.000    0.000    0.000 {built-in method numpy.empty}
        2    0.000    0.000    0.000    0.000 isolate.py:42(isolates)
        4    0.000    0.000    0.000    0.000 base.py:41(get_track)
        2    0.000    0.000    0.000    0.000 timer.py:34(__init__)
       16    0.000    0.000    0.000    0.000 base.py:56(check_role)
        6    0.000    0.000    0.000    0.000 base.py:452(<listcomp>)
       36    0.000    0.000    0.000    0.000 {method 'copy' of 'dict' objects}
       26    0.000    0.000    0.000    0.000 inspect.py:3009(return_annotation)
        2    0.000    0.000    0.000    0.000 copy.py:201(_deepcopy_list)
        1    0.000    0.000    0.000    0.000 fromnumeric.py:2836(min)
        7    0.000    0.000    0.000    0.000 __init__.py:1101(__getitem__)
        2    0.000    0.000    0.000    0.000 reportviews.py:417(__init__)
       10    0.000    0.000    0.000    0.000 base.py:546(is_static)
       30    0.000    0.000    0.000    0.000 {built-in method sys.getrecursionlimit}
       10    0.000    0.000    0.000    0.000 {built-in method builtins.max}
        2    0.000    0.000    0.000    0.000 backends.py:129(wrapper)
        7    0.000    0.000    0.000    0.000 propagate.py:110(<genexpr>)
        4    0.000    0.000    0.000    0.000 result.py:295(keys)
       10    0.000    0.000    0.000    0.000 base.py:208(update_seed)
        2    0.000    0.000    0.000    0.000 base.py:330(<dictcomp>)
       12    0.000    0.000    0.000    0.000 {built-in method fromkeys}
        1    0.000    0.000    0.000    0.000 scenario.py:119(__init__)
        1    0.000    0.000    0.000    0.000 base.py:196(init_time_hist)
       10    0.000    0.000    0.000    0.000 function.py:85(<listcomp>)
        2    0.000    0.000    0.000    0.000 {method '__reduce_ex__' of 'object' objects}
        1    0.000    0.000    0.000    0.000 base.py:109(get_shift)
        4    0.000    0.000    0.000    0.000 copy.py:264(<genexpr>)
       10    0.000    0.000    0.000    0.000 base.py:459(init_block)
        1    0.000    0.000    0.000    0.000 propagate.py:230(save_helper)
        1    0.000    0.000    0.000    0.000 fromnumeric.py:72(<dictcomp>)
        2    0.000    0.000    0.000    0.000 base.py:321(get_indicators)
        2    0.000    0.000    0.000    0.000 graph.py:1481(degree)
        1    0.000    0.000    0.000    0.000 propagate.py:860(check_overwrite)
        1    0.000    0.000    0.000    0.000 propagate.py:108(unpack_sim_kwargs)
       12    0.000    0.000    0.000    0.000 inspect.py:2690(default)
        2    0.000    0.000    0.000    0.000 graph.py:59(__set__)
        2    0.000    0.000    0.000    0.000 function.py:227(<listcomp>)
        2    0.000    0.000    0.000    0.000 __init__.py:1114(__iter__)
        2    0.000    0.000    0.000    0.000 base.py:243(update_seed)
        4    0.000    0.000    0.000    0.000 {method 'endswith' of 'str' objects}
        1    0.000    0.000    0.000    0.000 propagate.py:1148(<listcomp>)
        2    0.000    0.000    0.000    0.000 parameter.py:89(keys)
        1    0.000    0.000    0.000    0.000 propagate.py:1171(<listcomp>)
        2    0.000    0.000    0.000    0.000 graph.py:37(__set__)
        2    0.000    0.000    0.000    0.000 reportviews.py:424(__call__)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        2    0.000    0.000    0.000    0.000 {method '__exit__' of '_thread.RLock' objects}
        1    0.000    0.000    0.000    0.000 {method 'pop' of 'dict' objects}
        1    0.000    0.000    0.000    0.000 fromnumeric.py:2831(_min_dispatcher)
        1    0.000    0.000    0.000    0.000 function.py:253(<listcomp>)
        1    0.000    0.000    0.000    0.000 scenario.py:121(<dictcomp>)


[37]:
prof = cProfile.run('propagate.fault_sample(mdl, fs)', sort='tottime')
SCENARIOS COMPLETE: 100%|██████████| 72/72 [00:02<00:00, 27.91it/s]
         4736681 function calls (4708317 primitive calls) in 2.621 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   165096    0.241    0.000    0.289    0.000 base.py:395(<listcomp>)
     4088    0.172    0.000    1.994    0.000 function.py:403(prop_static)
    82106    0.134    0.000    0.496    0.000 base.py:406(get_all_roles)
    82106    0.132    0.000    0.156    0.000 base.py:374(<listcomp>)
    82106    0.131    0.000    0.417    0.000 base.py:388(<listcomp>)
    41125    0.128    0.000    0.544    0.000 function.py:136(__call__)
    82106    0.113    0.000    0.137    0.000 time.py:96(return_mutables)
   165096    0.102    0.000    0.391    0.000 base.py:391(get_roles)
   751841    0.086    0.000    0.086    0.000 {built-in method builtins.getattr}
    82106    0.075    0.000    0.727    0.000 base.py:372(find_mutables)
    82106    0.074    0.000    1.218    0.000 base.py:377(return_mutables)
     4088    0.064    0.000    0.165    0.000 history.py:254(log)
40880/16352    0.062    0.000    0.083    0.000 base.py:19(get_var)
    82106    0.051    0.000    0.067    0.000 base.py:399(get_roledicts)
     1850    0.044    0.000    0.057    0.000 base.py:194(<listcomp>)
   282945    0.043    0.000    0.043    0.000 {built-in method builtins.hasattr}
   198010    0.042    0.000    0.060    0.000 base.py:68(return_mutables)
    85584    0.042    0.000    0.058    0.000 copy.py:66(copy)
     2664    0.040    0.000    0.040    0.000 {built-in method builtins.dir}
    82106    0.040    0.000    0.095    0.000 mode.py:266(return_mutables)
    63225    0.037    0.000    0.051    0.000 mode.py:440(has_fault)
     8258    0.029    0.000    0.145    0.000 ex_pump.py:396(behavior)
    41125    0.024    0.000    0.079    0.000 function.py:114(prop_arch_behaviors)
    41125    0.022    0.000    0.077    0.000 function.py:129(prop_arch_faults_up)
    16516    0.022    0.000    0.053    0.000 base.py:239(set_field)
17702/16666    0.022    0.000    0.030    0.000 copy.py:128(deepcopy)
   231036    0.021    0.000    0.021    0.000 {built-in method recordclass._dataobject.astuple}
   280294    0.021    0.000    0.021    0.000 {method 'startswith' of 'str' objects}
     8258    0.021    0.000    0.100    0.000 base.py:202(assign)
    98622    0.017    0.000    0.017    0.000 time.py:97(<genexpr>)
       73    0.016    0.000    2.246    0.031 propagate.py:1032(prop_one_scen)
      814    0.016    0.000    0.021    0.000 base.py:318(<listcomp>)
    82106    0.016    0.000    0.016    0.000 base.py:403(<listcomp>)
     8258    0.015    0.000    0.025    0.000 base.py:141(get_field_dict)
    82106    0.015    0.000    0.015    0.000 base.py:410(<listcomp>)
    21252    0.014    0.000    0.017    0.000 __init__.py:180(add)
      215    0.014    0.000    0.014    0.000 {method 'acquire' of '_thread.lock' objects}
     1480    0.013    0.000    0.190    0.000 base.py:197(init_roles)
     8324    0.013    0.000    0.033    0.000 _collections_abc.py:767(__ior__)
     1110    0.013    0.000    0.034    0.000 inspect.py:2279(_signature_from_function)
     4088    0.012    0.000    2.032    0.000 function.py:366(propagate)
   143648    0.012    0.000    0.012    0.000 {method 'get' of 'dict' objects}
    94782    0.011    0.000    0.012    0.000 {built-in method builtins.isinstance}
     8255    0.010    0.000    0.022    0.000 ex_pump.py:212(behavior)
    91104    0.009    0.000    0.009    0.000 {method 'copy' of 'set' objects}
     2220    0.009    0.000    0.012    0.000 inspect.py:2919(__init__)
    33026    0.009    0.000    0.012    0.000 base.py:381(return_mutables)
2220/1110    0.008    0.000    0.056    0.000 inspect.py:2374(_signature_from_callable)
     8185    0.008    0.000    0.020    0.000 ex_pump.py:243(behavior)
     8170    0.008    0.000    0.015    0.000 ex_pump.py:290(behavior)
      962    0.008    0.000    0.094    0.000 parameter.py:50(__init__)
     5698    0.007    0.000    0.012    0.000 inspect.py:2636(__init__)
112579/111848    0.007    0.000    0.008    0.000 {built-in method builtins.len}
     4088    0.007    0.000    0.019    0.000 __init__.py:353(union)
    63225    0.007    0.000    0.007    0.000 {method 'intersection' of 'set' objects}
     4088    0.007    0.000    0.174    0.000 base.py:202(log_hist)
    83298    0.007    0.000    0.007    0.000 {method 'values' of 'dict' objects}
    63522    0.007    0.000    0.007    0.000 {built-in method builtins.any}
     8276    0.006    0.000    0.009    0.000 ex_pump.py:363(condfaults)
1776/1187    0.006    0.000    0.018    0.000 result.py:464(flatten)
     8398    0.006    0.000    0.039    0.000 __init__.py:65(__init__)
      962    0.006    0.000    0.012    0.000 inspect.py:3205(__str__)
     8258    0.006    0.000    0.007    0.000 base.py:189(<dictcomp>)
      962    0.005    0.000    0.007    0.000 base.py:97(set_arg_type)
    20440    0.005    0.000    0.005    0.000 history.py:34(is_known_mutable)
     1329    0.005    0.000    0.005    0.000 {method 'round' of 'numpy.ndarray' objects}
      962    0.004    0.000    0.006    0.000 parameter.py:120(check_immutable)
     8185    0.004    0.000    0.012    0.000 ex_pump.py:269(behavior)
    25112    0.004    0.000    0.004    0.000 {method 'split' of 'str' objects}
     4088    0.004    0.000    0.005    0.000 function.py:312(set_vars)
    16352    0.004    0.000    0.005    0.000 __init__.py:304(__iter__)
    33666    0.004    0.000    0.004    0.000 {method 'join' of 'str' objects}
      370    0.004    0.000    0.192    0.001 base.py:428(__init__)
      666    0.004    0.000    0.249    0.000 base.py:73(add_flex_role_obj)
    21482    0.004    0.000    0.004    0.000 {method 'update' of 'set' objects}
      370    0.004    0.000    0.008    0.000 mode.py:269(init_faultmodes)
      518    0.003    0.000    0.009    0.000 base.py:69(find_any_phase_overlap)
     4144    0.003    0.000    0.004    0.000 inspect.py:2720(__str__)
      444    0.003    0.000    0.003    0.000 time.py:103(set_timestep)
     1110    0.003    0.000    0.025    0.000 base.py:431(create_hist)
     6377    0.003    0.000    0.004    0.000 result.py:298(items)
     1110    0.003    0.000    0.010    0.000 inspect.py:1967(_signature_bound_method)
     8273    0.003    0.000    0.003    0.000 ex_pump.py:194(condfaults)
     4366    0.003    0.000    0.005    0.000 parameter.py:92(check_lim)
    15111    0.003    0.000    0.003    0.000 {built-in method builtins.min}
     8276    0.003    0.000    0.003    0.000 ex_pump.py:387(indicate_over_pressure)
      962    0.003    0.000    0.003    0.000 parameter.py:141(check_type)
      962    0.003    0.000    0.007    0.000 base.py:70(get_true_fields)
    33240    0.003    0.000    0.003    0.000 {method 'append' of 'list' objects}
      438    0.003    0.000    0.005    0.000 result.py:348(all_with)
    12264    0.003    0.000    0.003    0.000 __init__.py:74(__len__)
     5698    0.003    0.000    0.004    0.000 enum.py:359(__call__)
    20882    0.003    0.000    0.003    0.000 {built-in method builtins.setattr}
     1329    0.002    0.000    0.012    0.000 base.py:83(get_timerange)
1184/1110    0.002    0.000    0.192    0.000 base.py:173(init_roletypes)
  814/740    0.002    0.000    0.210    0.000 base.py:106(__init__)
     6808    0.002    0.000    0.003    0.000 inspect.py:2968(<genexpr>)
     4088    0.002    0.000    0.030    0.000 __init__.py:130(copy)
     3251    0.002    0.000    0.002    0.000 result.py:317(__setattr__)
     1850    0.002    0.000    0.086    0.000 base.py:193(find_roletype_initiators)
     1329    0.002    0.000    0.002    0.000 {built-in method numpy.arange}
     4088    0.002    0.000    0.002    0.000 base.py:129(get_hist_ind)
     4088    0.002    0.000    0.002    0.000 propagate.py:1004(check_end_condition)
      962    0.002    0.000    0.065    0.000 parameter.py:164(check_pickle)
      518    0.002    0.000    0.061    0.000 base.py:61(__init__)
     3251    0.002    0.000    0.004    0.000 __init__.py:1091(__init__)
    19782    0.002    0.000    0.002    0.000 {built-in method builtins.id}
    17256    0.002    0.000    0.002    0.000 copy.py:182(_deepcopy_atomic)
     4088    0.002    0.000    0.002    0.000 ex_pump.py:490(indicate_on)
      370    0.002    0.000    0.012    0.000 mode.py:204(__init__)
     1779    0.002    0.000    0.004    0.000 numerictypes.py:357(issubdtype)
     2587    0.002    0.000    0.002    0.000 common.py:26(get_sub_include)
     4088    0.002    0.000    0.002    0.000 ex_pump.py:471(indicate_finished)
     1770    0.002    0.000    0.006    0.000 common.py:60(is_numeric)
    16412    0.002    0.000    0.002    0.000 {method 'items' of 'dict' objects}
       73    0.002    0.000    0.013    0.000 ex_pump.py:494(find_classification)
     1110    0.002    0.000    0.002    0.000 inspect.py:66(get_annotations)
     4599    0.002    0.000    0.002    0.000 __init__.py:1118(__contains__)
      814    0.002    0.000    0.036    0.000 base.py:316(init_indicators)
        1    0.001    0.001    2.577    2.577 propagate.py:760(scenlist_helper)
     1110    0.001    0.000    0.002    0.000 inspect.py:612(unwrap)
      666    0.001    0.000    0.221    0.000 base.py:509(init_obj)
    17658    0.001    0.000    0.001    0.000 {built-in method builtins.iter}
      584    0.001    0.000    0.007    0.000 result.py:307(__getattr__)
     3558    0.001    0.000    0.002    0.000 numerictypes.py:283(issubclass_)
      370    0.001    0.000    0.204    0.001 base.py:160(add_sim)
      962    0.001    0.000    0.004    0.000 base.py:77(<listcomp>)
      962    0.001    0.000    0.001    0.000 base.py:148(init_track)
     3354    0.001    0.000    0.001    0.000 {method 'format' of 'str' objects}
    15096    0.001    0.000    0.001    0.000 inspect.py:2698(kind)
     1036    0.001    0.000    0.001    0.000 {method 'copy' of 'numpy.ndarray' objects}
     1036    0.001    0.000    0.004    0.000 fromnumeric.py:865(sort)
       73    0.001    0.000    0.001    0.000 {method 'reduce' of 'numpy.ufunc' objects}
     4366    0.001    0.000    0.001    0.000 base.py:137(set_arg_as_type)
      370    0.001    0.000    0.206    0.001 function.py:153(add_fxn)
      444    0.001    0.000    0.162    0.000 base.py:174(__init__)
     8258    0.001    0.000    0.001    0.000 {method 'clear' of 'set' objects}
     3531    0.001    0.000    0.001    0.000 __init__.py:1108(__setitem__)
     1110    0.001    0.000    0.057    0.000 inspect.py:2997(from_callable)
      864    0.001    0.000    0.001    0.000 function.py:448(<listcomp>)
     1770    0.001    0.000    0.001    0.000 {built-in method numpy.array}
      444    0.001    0.000    0.007    0.000 time.py:82(__init__)
     8258    0.001    0.000    0.001    0.000 {method 'copy' of 'list' objects}
     1183    0.001    0.000    0.011    0.000 base.py:98(get_histrange)
     1329    0.001    0.000    0.007    0.000 fromnumeric.py:3269(round)
     1329    0.001    0.000    0.006    0.000 fromnumeric.py:53(_wrapfunc)
     1110    0.001    0.000    0.007    0.000 inspect.py:3013(replace)
     1776    0.001    0.000    0.001    0.000 result.py:141(check_include_errors)
       73    0.001    0.000    0.015    0.000 propagate.py:1132(get_result)
    10286    0.001    0.000    0.001    0.000 inspect.py:2686(name)
      148    0.001    0.000    0.021    0.000 parameter.py:160(copy_with_vals)
     5698    0.001    0.000    0.001    0.000 enum.py:678(__new__)
     1036    0.001    0.000    0.001    0.000 {method 'sort' of 'numpy.ndarray' objects}
     1036    0.001    0.000    0.001    0.000 {built-in method numpy.asanyarray}
       74    0.001    0.000    0.001    0.000 graph.py:961(add_edges_from)
     2146    0.001    0.000    0.001    0.000 base.py:23(check_role)
     1110    0.001    0.000    0.058    0.000 inspect.py:3251(signature)
       80    0.001    0.000    0.001    0.000 socket.py:543(send)
     8176    0.001    0.000    0.001    0.000 {method 'index' of 'list' objects}
      296    0.001    0.000    0.001    0.000 history.py:184(init_att)
       74    0.001    0.000    0.278    0.004 ex_pump.py:443(init_architecture)
     2140    0.001    0.000    0.001    0.000 {built-in method _abc._abc_instancecheck}
      370    0.001    0.000    0.193    0.001 function.py:58(__init__)
      370    0.001    0.000    0.001    0.000 function.py:73(return_faultmodes)
     2357    0.001    0.000    0.001    0.000 __init__.py:1098(__len__)
      148    0.001    0.000    0.001    0.000 graph.py:563(add_nodes_from)
      370    0.001    0.000    0.019    0.000 base.py:463(create_arch_kwargs)
      444    0.001    0.000    0.014    0.000 base.py:188(init_hist)
      370    0.001    0.000    0.002    0.000 base.py:505(check_flows)
       74    0.001    0.000    0.002    0.000 history.py:320(cut)
       25    0.001    0.000    0.001    0.000 std.py:352(format_meter)
     2220    0.001    0.000    0.001    0.000 inspect.py:277(isfunction)
       74    0.001    0.000    0.320    0.004 base.py:34(__init__)
      171    0.001    0.000    0.001    0.000 {built-in method builtins.sum}
      222    0.001    0.000    0.002    0.000 base.py:350(init_indicator_hist)
     5411    0.001    0.000    0.001    0.000 {built-in method builtins.issubclass}
      370    0.001    0.000    0.001    0.000 function.py:97(update_seed)
   298/76    0.001    0.000    0.003    0.000 copy.py:227(_deepcopy_dict)
     2140    0.001    0.000    0.001    0.000 abc.py:117(__instancecheck__)
      518    0.001    0.000    0.001    0.000 {built-in method recordclass._dataobject.asdict}
     5698    0.001    0.000    0.001    0.000 {method 'isidentifier' of 'str' objects}
       74    0.001    0.000    0.004    0.000 function.py:219(construct_graph)
       74    0.001    0.000    0.012    0.000 function.py:207(build)
      518    0.001    0.000    0.001    0.000 base.py:74(<listcomp>)
     4088    0.001    0.000    0.001    0.000 {built-in method from_iterable}
      518    0.001    0.000    0.001    0.000 base.py:71(<dictcomp>)
     1160    0.001    0.000    0.001    0.000 graph.py:1315(neighbors)
      370    0.001    0.000    0.001    0.000 base.py:525(<listcomp>)
     4381    0.001    0.000    0.001    0.000 {method 'keys' of 'dict' objects}
     1184    0.000    0.000    0.001    0.000 base.py:142(check_slots)
      584    0.000    0.000    0.001    0.000 result.py:122(get_dict_attr)
      296    0.000    0.000    0.047    0.000 base.py:120(add_flow)
      296    0.000    0.000    0.015    0.000 base.py:87(create_hist)
       74    0.000    0.000    0.025    0.000 base.py:240(new_params)
       73    0.000    0.000    0.004    0.000 function.py:231(calc_repaircost)
     2320    0.000    0.000    0.000    0.000 __init__.py:165(__contains__)
      148    0.000    0.000    0.002    0.000 base.py:333(create_hist)
     1688    0.000    0.000    0.001    0.000 utils.py:306(<genexpr>)
       74    0.000    0.000    0.001    0.000 function.py:258(return_faultmodes)
      146    0.000    0.000    0.001    0.000 _collections_abc.py:991(update)
       72    0.000    0.000    2.218    0.031 propagate.py:809(exec_scen)
       74    0.000    0.000    0.004    0.000 base.py:190(build)
     2072    0.000    0.000    0.000    0.000 {method 'values' of 'mappingproxy' objects}
      370    0.000    0.000    0.000    0.000 base.py:443(<dictcomp>)
       74    0.000    0.000    0.001    0.000 function.py:215(<listcomp>)
     1776    0.000    0.000    0.000    0.000 result.py:149(check_include_error)
       73    0.000    0.000    0.002    0.000 fromnumeric.py:71(_wrapreduction)
      370    0.000    0.000    0.001    0.000 __init__.py:201(update)
      370    0.000    0.000    0.001    0.000 base.py:482(update_contained_modes)
       74    0.000    0.000    0.346    0.005 base.py:274(new)
     1110    0.000    0.000    0.000    0.000 inspect.py:632(_is_wrapper)
       74    0.000    0.000    0.321    0.004 function.py:126(__init__)
      446    0.000    0.000    0.000    0.000 copy.py:243(_keep_alive)
      148    0.000    0.000    0.001    0.000 base.py:320(init_hist_att)
      740    0.000    0.000    0.000    0.000 reportviews.py:527(__iter__)
       74    0.000    0.000    0.001    0.000 functools.py:961(__get__)
      518    0.000    0.000    0.000    0.000 base.py:73(<listcomp>)
       23    0.000    0.000    0.019    0.001 std.py:1195(update)
      370    0.000    0.000    0.000    0.000 base.py:212(get_flows)
      656    0.000    0.000    0.000    0.000 __init__.py:1101(__getitem__)
     3330    0.000    0.000    0.000    0.000 {built-in method builtins.callable}
      370    0.000    0.000    0.000    0.000 base.py:470(<dictcomp>)
     2220    0.000    0.000    0.000    0.000 inspect.py:3005(parameters)
      296    0.000    0.000    0.000    0.000 function.py:216(<listcomp>)
       80    0.000    0.000    0.001    0.000 iostream.py:243(schedule)
       74    0.000    0.000    0.000    0.000 graph.py:332(__init__)
      370    0.000    0.000    0.000    0.000 base.py:520(<listcomp>)
     1329    0.000    0.000    0.000    0.000 fromnumeric.py:3265(_round_dispatcher)
      296    0.000    0.000    0.000    0.000 {built-in method numpy.empty}
       27    0.000    0.000    0.016    0.001 iostream.py:547(flush)
       74    0.000    0.000    0.001    0.000 isolate.py:42(isolates)
       73    0.000    0.000    0.002    0.000 fromnumeric.py:2836(min)
      139    0.000    0.000    0.000    0.000 std.py:230(__call__)
      666    0.000    0.000    0.000    0.000 inspect.py:191(isclass)
       74    0.000    0.000    0.000    0.000 function.py:210(<listcomp>)
       74    0.000    0.000    0.001    0.000 copy.py:259(_reconstruct)
       27    0.000    0.000    0.015    0.001 threading.py:589(wait)
     2220    0.000    0.000    0.000    0.000 {built-in method builtins.repr}
      370    0.000    0.000    0.000    0.000 base.py:216(<dictcomp>)
      148    0.000    0.000    0.001    0.000 state.py:296(init_hist_att)
      148    0.000    0.000    0.000    0.000 base.py:205(<dictcomp>)
      511    0.000    0.000    0.000    0.000 propagate.py:110(<genexpr>)
     1950    0.000    0.000    0.000    0.000 {method 'update' of 'dict' objects}
       73    0.000    0.000    0.020    0.000 std.py:1157(__iter__)
       74    0.000    0.000    0.001    0.000 isolate.py:85(<genexpr>)
      370    0.000    0.000    0.000    0.000 base.py:552(is_dynamic)
       27    0.000    0.000    0.001    0.000 iostream.py:610(write)
       74    0.000    0.000    0.001    0.000 function.py:212(<listcomp>)
     1776    0.000    0.000    0.000    0.000 copy.py:107(_copy_immutable)
       27    0.000    0.000    0.014    0.001 threading.py:288(wait)
       74    0.000    0.000    0.000    0.000 base.py:52(init_flexible_roles)
       74    0.000    0.000    0.003    0.000 timer.py:34(__init__)
     1036    0.000    0.000    0.000    0.000 fromnumeric.py:861(_sort_dispatcher)
      293    0.000    0.000    0.000    0.000 result.py:295(keys)
       74    0.000    0.000    0.000    0.000 reportviews.py:417(__init__)
      107    0.000    0.000    0.000    0.000 threading.py:1169(is_alive)
       73    0.000    0.000    0.001    0.000 base.py:109(get_shift)
       25    0.000    0.000    0.000    0.000 std.py:1443(format_dict)
       74    0.000    0.000    0.000    0.000 propagate.py:230(save_helper)
       50    0.000    0.000    0.000    0.000 utils.py:204(_is_ascii)
       52    0.000    0.000    0.017    0.000 utils.py:125(inner)
       54    0.000    0.000    0.000    0.000 {built-in method _thread.allocate_lock}
      517    0.000    0.000    0.000    0.000 {built-in method fromkeys}
       27    0.000    0.000    0.000    0.000 threading.py:236(__init__)
        1    0.000    0.000    2.621    2.621 <string>:1(<module>)
      592    0.000    0.000    0.000    0.000 base.py:56(check_role)
     1663    0.000    0.000    0.000    0.000 {built-in method unicodedata.east_asian_width}
       74    0.000    0.000    0.001    0.000 backends.py:129(wrapper)
      148    0.000    0.000    0.000    0.000 base.py:41(get_track)
      395    0.000    0.000    0.000    0.000 {built-in method builtins.max}
       73    0.000    0.000    0.001    0.000 base.py:196(init_time_hist)
       73    0.000    0.000    0.000    0.000 function.py:253(<listcomp>)
      962    0.000    0.000    0.000    0.000 inspect.py:3009(return_annotation)
       74    0.000    0.000    0.000    0.000 graph.py:1481(degree)
      370    0.000    0.000    0.000    0.000 base.py:546(is_static)
       27    0.000    0.000    0.000    0.000 iostream.py:505(_is_master_process)
       24    0.000    0.000    0.019    0.001 std.py:1322(refresh)
      222    0.000    0.000    0.000    0.000 base.py:452(<listcomp>)
     1110    0.000    0.000    0.000    0.000 {built-in method sys.getrecursionlimit}
       74    0.000    0.000    0.000    0.000 copy.py:201(_deepcopy_list)
       25    0.000    0.000    0.002    0.000 std.py:1147(__str__)
       25    0.000    0.000    0.019    0.001 std.py:1461(display)
     1332    0.000    0.000    0.000    0.000 {method 'copy' of 'dict' objects}
       28    0.000    0.000    0.000    0.000 {method 'acquire' of '_multiprocessing.SemLock' objects}
      370    0.000    0.000    0.000    0.000 function.py:85(<listcomp>)
       74    0.000    0.000    0.000    0.000 base.py:330(<dictcomp>)
      146    0.000    0.000    0.000    0.000 __init__.py:1114(__iter__)
       73    0.000    0.000    0.000    0.000 fromnumeric.py:72(<dictcomp>)
       25    0.000    0.000    0.000    0.000 std.py:185(__format__)
      144    0.000    0.000    0.000    0.000 scenario.py:30(get)
       25    0.000    0.000    0.018    0.001 std.py:345(print_status)
       73    0.000    0.000    0.000    0.000 propagate.py:108(unpack_sim_kwargs)
       25    0.000    0.000    0.017    0.001 std.py:339(fp_write)
       74    0.000    0.000    0.000    0.000 {method '__reduce_ex__' of 'object' objects}
       28    0.000    0.000    0.000    0.000 std.py:101(acquire)
       74    0.000    0.000    0.000    0.000 base.py:321(get_indicators)
      370    0.000    0.000    0.000    0.000 base.py:208(update_seed)
       49    0.000    0.000    0.000    0.000 std.py:285(format_interval)
       90    0.000    0.000    0.000    0.000 mode.py:480(add_fault)
       80    0.000    0.000    0.000    0.000 iostream.py:127(_event_pipe)
      292    0.000    0.000    0.000    0.000 {method 'endswith' of 'str' objects}
      195    0.000    0.000    0.000    0.000 time.py:90(__getattr__)
      107    0.000    0.000    0.000    0.000 threading.py:1102(_wait_for_tstate_lock)
       72    0.000    0.000    0.000    0.000 mode.py:393(update_modestates)
       28    0.000    0.000    0.000    0.000 std.py:105(release)
      370    0.000    0.000    0.000    0.000 base.py:459(init_block)
       60    0.000    0.000    0.000    0.000 timer.py:57(inc)
       27    0.000    0.000    0.001    0.000 iostream.py:532(_schedule_flush)
       27    0.000    0.000    0.000    0.000 threading.py:545(__init__)
       73    0.000    0.000    0.000    0.000 propagate.py:1148(<listcomp>)
       74    0.000    0.000    0.000    0.000 graph.py:59(__set__)
      148    0.000    0.000    0.000    0.000 copy.py:264(<genexpr>)
      444    0.000    0.000    0.000    0.000 inspect.py:2690(default)
        1    0.000    0.000    2.621    2.621 propagate.py:571(fault_sample)
       25    0.000    0.000    0.000    0.000 std.py:152(__init__)
       25    0.000    0.000    0.001    0.000 utils.py:309(disp_len)
       74    0.000    0.000    0.000    0.000 base.py:243(update_seed)
       24    0.000    0.000    0.000    0.000 {built-in method now}
       74    0.000    0.000    0.000    0.000 graph.py:37(__set__)
       25    0.000    0.000    0.000    0.000 {method 'sub' of 're.Pattern' objects}
       28    0.000    0.000    0.000    0.000 {method 'release' of '_multiprocessing.SemLock' objects}
       74    0.000    0.000    0.001    0.000 function.py:227(<listcomp>)
       27    0.000    0.000    0.000    0.000 threading.py:1430(current_thread)
        1    0.000    0.000    2.621    2.621 {built-in method builtins.exec}
       73    0.000    0.000    0.000    0.000 propagate.py:1171(<listcomp>)
       25    0.000    0.000    0.001    0.000 utils.py:305(_text_width)
      525    0.000    0.000    0.000    0.000 {built-in method builtins.ord}
       74    0.000    0.000    0.000    0.000 reportviews.py:424(__call__)
       77    0.000    0.000    0.000    0.000 {method 'pop' of 'dict' objects}
       27    0.000    0.000    0.000    0.000 threading.py:267(__exit__)
       27    0.000    0.000    0.000    0.000 threading.py:276(_acquire_restore)
        1    0.000    0.000    0.001    0.001 std.py:837(__init__)
       74    0.000    0.000    0.000    0.000 parameter.py:89(keys)
       54    0.000    0.000    0.000    0.000 threading.py:1145(ident)
        1    0.000    0.000    0.000    0.000 __init__.py:48(create_string_buffer)
       99    0.000    0.000    0.000    0.000 {built-in method time.time}
      101    0.000    0.000    0.000    0.000 {method '__exit__' of '_thread.RLock' objects}
      108    0.000    0.000    0.000    0.000 threading.py:553(is_set)
        1    0.000    0.000    0.000    0.000 utils.py:228(_screen_shape_windows)
      123    0.000    0.000    0.000    0.000 {built-in method builtins.divmod}
       27    0.000    0.000    0.000    0.000 threading.py:264(__enter__)
       73    0.000    0.000    0.000    0.000 fromnumeric.py:2831(_min_dispatcher)
       25    0.000    0.000    0.000    0.000 utils.py:39(__init__)
      107    0.000    0.000    0.000    0.000 {method 'append' of 'collections.deque' objects}
       27    0.000    0.000    0.000    0.000 threading.py:273(_release_save)
       28    0.000    0.000    0.000    0.000 {method 'acquire' of '_thread.RLock' objects}
       27    0.000    0.000    0.000    0.000 {built-in method nt.getpid}
       27    0.000    0.000    0.000    0.000 threading.py:279(_is_owned)
       27    0.000    0.000    0.000    0.000 {method 'write' of '_io.StringIO' objects}
        1    0.000    0.000    0.039    0.039 propagate.py:484(nom_helper)
       25    0.000    0.000    0.000    0.000 std.py:166(colour)
        1    0.000    0.000    0.001    0.001 std.py:326(status_printer)
        1    0.000    0.000    0.000    0.000 result.py:522(get_memory)
       25    0.000    0.000    0.000    0.000 utils.py:43(__format__)
        1    0.000    0.000    0.000    0.000 std.py:551(__new__)
        2    0.000    0.000    0.001    0.000 std.py:1262(close)
       27    0.000    0.000    0.000    0.000 {built-in method builtins.abs}
       27    0.000    0.000    0.000    0.000 {built-in method _thread.get_ident}
        1    0.000    0.000    0.000    0.000 propagate.py:689(process_nominal)
       25    0.000    0.000    0.000    0.000 std.py:162(colour)
        1    0.000    0.000    0.000    0.000 std.py:574(_decr_instances)
       28    0.000    0.000    0.000    0.000 {method 'release' of '_thread.RLock' objects}
        3    0.000    0.000    0.000    0.000 _weakrefset.py:63(__iter__)
        1    0.000    0.000    0.000    0.000 propagate.py:158(<dictcomp>)
       27    0.000    0.000    0.000    0.000 {method '__enter__' of '_thread.lock' objects}
       27    0.000    0.000    0.000    0.000 {method '__exit__' of '_thread.lock' objects}
        2    0.000    0.000    0.000    0.000 std.py:1283(fp_write)
        1    0.000    0.000    0.000    0.000 utils.py:144(__init__)
        1    0.000    0.000    0.000    0.000 std.py:567(_get_free_pos)
        1    0.000    0.000    0.000    0.000 propagate.py:156(pack_run_kwargs)
       27    0.000    0.000    0.000    0.000 {method 'release' of '_thread.lock' objects}
        2    0.000    0.000    0.000    0.000 _weakrefset.py:53(_commit_removals)
        2    0.000    0.000    0.000    0.000 _weakrefset.py:27(__exit__)
        4    0.000    0.000    0.000    0.000 std.py:109(__enter__)
        3    0.000    0.000    0.000    0.000 {method 'remove' of 'set' objects}
        1    0.000    0.000    0.000    0.000 sample.py:790(times)
        5    0.000    0.000    0.000    0.000 propagate.py:191(<genexpr>)
        4    0.000    0.000    0.000    0.000 std.py:112(__exit__)
        2    0.000    0.000    0.000    0.000 _weakrefset.py:21(__enter__)
        1    0.000    0.000    0.000    0.000 _weakrefset.py:86(add)
        2    0.000    0.000    0.000    0.000 utils.py:118(disable_on_exception)
        1    0.000    0.000    0.000    0.000 utils.py:197(_supports_unicode)
        1    0.000    0.000    0.000    0.000 sample.py:794(scenarios)
        1    0.000    0.000    0.000    0.000 _weakrefset.py:111(remove)
        3    0.000    0.000    0.000    0.000 utils.py:83(wrapper_setattr)
        1    0.000    0.000    0.000    0.000 scenario.py:119(__init__)
        2    0.000    0.000    0.000    0.000 _weakrefset.py:17(__init__)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:1053(_handle_fromlist)
        1    0.000    0.000    0.000    0.000 _monitor.py:94(report)
        3    0.000    0.000    0.000    0.000 std.py:225(__init__)
        1    0.000    0.000    0.000    0.000 {built-in method utcfromtimestamp}
        4    0.000    0.000    0.000    0.000 utils.py:153(__eq__)
        3    0.000    0.000    0.000    0.000 {method 'add' of 'set' objects}
        1    0.000    0.000    0.000    0.000 {method 'encode' of 'str' objects}
        1    0.000    0.000    0.000    0.000 propagate.py:189(unpack_mult_kwargs)
        1    0.000    0.000    0.000    0.000 utils.py:87(__init__)
        1    0.000    0.000    0.000    0.000 std.py:570(<setcomp>)
        1    0.000    0.000    0.000    0.000 utils.py:56(__eq__)
        1    0.000    0.000    0.000    0.000 utils.py:183(_is_utf)
        2    0.000    0.000    0.000    0.000 std.py:1150(_comparable)
        2    0.000    0.000    0.000    0.000 std.py:1154(__hash__)
        1    0.000    0.000    0.000    0.000 propagate.py:796(close_pool)
        1    0.000    0.000    0.000    0.000 propagate.py:860(check_overwrite)
        1    0.000    0.000    0.000    0.000 std.py:1144(__del__)
        2    0.000    0.000    0.000    0.000 {method 'pop' of 'list' objects}
        1    0.000    0.000    0.000    0.000 std.py:648(get_lock)
        1    0.000    0.000    0.000    0.000 utils.py:70(__getattr__)
        1    0.000    0.000    0.000    0.000 utils.py:213(_screen_shape_wrapper)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        2    0.000    0.000    0.000    0.000 {built-in method _weakref.proxy}
        1    0.000    0.000    0.000    0.000 {method 'difference' of 'set' objects}
        1    0.000    0.000    0.000    0.000 scenario.py:121(<dictcomp>)
        1    0.000    0.000    0.000    0.000 {built-in method __new__ of type object at 0x00007FFD44BEAD50}
        1    0.000    0.000    0.000    0.000 std.py:1298(<lambda>)
        1    0.000    0.000    0.000    0.000 {built-in method sys.audit}



[38]:
prof = cProfile.run('propagate.fault_sample(mdl, fs)', sort='cumtime')
SCENARIOS COMPLETE: 100%|██████████| 72/72 [00:02<00:00, 28.15it/s]
         4736406 function calls (4708042 primitive calls) in 2.612 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    2.612    2.612 {built-in method builtins.exec}
        1    0.000    0.000    2.612    2.612 <string>:1(<module>)
        1    0.000    0.000    2.612    2.612 propagate.py:571(fault_sample)
        1    0.001    0.001    2.559    2.559 propagate.py:760(scenlist_helper)
       73    0.016    0.000    2.236    0.031 propagate.py:1032(prop_one_scen)
       72    0.000    0.000    2.204    0.031 propagate.py:809(exec_scen)
     4088    0.012    0.000    2.020    0.000 function.py:366(propagate)
     4088    0.171    0.000    1.981    0.000 function.py:403(prop_static)
    82106    0.073    0.000    1.213    0.000 base.py:377(return_mutables)
    82106    0.073    0.000    0.725    0.000 base.py:372(find_mutables)
    41125    0.125    0.000    0.538    0.000 function.py:136(__call__)
    82106    0.134    0.000    0.497    0.000 base.py:406(get_all_roles)
    82106    0.130    0.000    0.416    0.000 base.py:388(<listcomp>)
   165096    0.102    0.000    0.390    0.000 base.py:391(get_roles)
       74    0.000    0.000    0.350    0.005 base.py:274(new)
       74    0.000    0.000    0.324    0.004 function.py:126(__init__)
       74    0.001    0.000    0.324    0.004 base.py:34(__init__)
   165096    0.239    0.000    0.288    0.000 base.py:395(<listcomp>)
       74    0.002    0.000    0.281    0.004 ex_pump.py:443(init_architecture)
      666    0.004    0.000    0.248    0.000 base.py:73(add_flex_role_obj)
      666    0.001    0.000    0.220    0.000 base.py:509(init_obj)
  814/740    0.002    0.000    0.212    0.000 base.py:106(__init__)
      370    0.001    0.000    0.206    0.001 function.py:153(add_fxn)
      370    0.001    0.000    0.204    0.001 base.py:160(add_sim)
1184/1110    0.002    0.000    0.193    0.000 base.py:173(init_roletypes)
      370    0.001    0.000    0.192    0.001 function.py:58(__init__)
      370    0.004    0.000    0.192    0.001 base.py:428(__init__)
     1480    0.013    0.000    0.191    0.000 base.py:197(init_roles)
     4088    0.007    0.000    0.177    0.000 base.py:202(log_hist)
     4088    0.066    0.000    0.168    0.000 history.py:254(log)
      444    0.001    0.000    0.162    0.000 base.py:174(__init__)
    82106    0.130    0.000    0.154    0.000 base.py:374(<listcomp>)
     8258    0.029    0.000    0.144    0.000 ex_pump.py:396(behavior)
    82106    0.113    0.000    0.137    0.000 time.py:96(return_mutables)
     8258    0.020    0.000    0.100    0.000 base.py:202(assign)
    82106    0.040    0.000    0.094    0.000 mode.py:266(return_mutables)
      962    0.007    0.000    0.094    0.000 parameter.py:50(__init__)
     1850    0.002    0.000    0.086    0.000 base.py:193(find_roletype_initiators)
   751841    0.085    0.000    0.085    0.000 {built-in method builtins.getattr}
40880/16352    0.063    0.000    0.084    0.000 base.py:19(get_var)
    41125    0.024    0.000    0.079    0.000 function.py:114(prop_arch_behaviors)
    41125    0.022    0.000    0.076    0.000 function.py:129(prop_arch_faults_up)
    82106    0.051    0.000    0.068    0.000 base.py:399(get_roledicts)
      962    0.002    0.000    0.065    0.000 parameter.py:164(check_pickle)
      518    0.002    0.000    0.061    0.000 base.py:61(__init__)
   198010    0.043    0.000    0.060    0.000 base.py:68(return_mutables)
     1110    0.001    0.000    0.058    0.000 inspect.py:3251(signature)
    85584    0.042    0.000    0.057    0.000 copy.py:66(copy)
     1110    0.001    0.000    0.057    0.000 inspect.py:2997(from_callable)
2220/1110    0.008    0.000    0.056    0.000 inspect.py:2374(_signature_from_callable)
     1850    0.043    0.000    0.056    0.000 base.py:194(<listcomp>)
    16516    0.022    0.000    0.053    0.000 base.py:239(set_field)
    63225    0.037    0.000    0.051    0.000 mode.py:440(has_fault)
        1    0.000    0.000    0.048    0.048 propagate.py:484(nom_helper)
      296    0.000    0.000    0.048    0.000 base.py:120(add_flow)
   282943    0.043    0.000    0.043    0.000 {built-in method builtins.hasattr}
     2664    0.041    0.000    0.041    0.000 {built-in method builtins.dir}
     8398    0.006    0.000    0.039    0.000 __init__.py:65(__init__)
      814    0.001    0.000    0.036    0.000 base.py:316(init_indicators)
     1110    0.012    0.000    0.035    0.000 inspect.py:2279(_signature_from_function)
     8324    0.012    0.000    0.033    0.000 _collections_abc.py:767(__ior__)
17702/16666    0.022    0.000    0.030    0.000 copy.py:128(deepcopy)
     4088    0.002    0.000    0.029    0.000 __init__.py:130(copy)
     1110    0.003    0.000    0.026    0.000 base.py:431(create_hist)
       74    0.000    0.000    0.025    0.000 base.py:240(new_params)
     8258    0.015    0.000    0.025    0.000 base.py:141(get_field_dict)
     8255    0.010    0.000    0.023    0.000 ex_pump.py:212(behavior)
      814    0.016    0.000    0.021    0.000 base.py:318(<listcomp>)
      148    0.001    0.000    0.021    0.000 parameter.py:160(copy_with_vals)
   231036    0.021    0.000    0.021    0.000 {built-in method recordclass._dataobject.astuple}
   280294    0.021    0.000    0.021    0.000 {method 'startswith' of 'str' objects}
     8185    0.008    0.000    0.020    0.000 ex_pump.py:243(behavior)
     4088    0.007    0.000    0.019    0.000 __init__.py:353(union)
1776/1187    0.007    0.000    0.019    0.000 result.py:464(flatten)
      370    0.001    0.000    0.018    0.000 base.py:463(create_arch_kwargs)
       73    0.000    0.000    0.018    0.000 std.py:1157(__iter__)
       24    0.000    0.000    0.018    0.001 std.py:1461(display)
       23    0.000    0.000    0.017    0.001 std.py:1322(refresh)
       22    0.000    0.000    0.017    0.001 std.py:1195(update)
    21252    0.014    0.000    0.017    0.000 __init__.py:180(add)
    98622    0.017    0.000    0.017    0.000 time.py:97(<genexpr>)
    82106    0.016    0.000    0.016    0.000 base.py:403(<listcomp>)
       24    0.000    0.000    0.016    0.001 std.py:345(print_status)
    82106    0.016    0.000    0.016    0.000 base.py:410(<listcomp>)
      296    0.000    0.000    0.015    0.000 base.py:87(create_hist)
       24    0.000    0.000    0.015    0.001 std.py:339(fp_write)
       50    0.000    0.000    0.015    0.000 utils.py:125(inner)
       73    0.001    0.000    0.015    0.000 propagate.py:1132(get_result)
     8170    0.008    0.000    0.014    0.000 ex_pump.py:290(behavior)
      444    0.001    0.000    0.014    0.000 base.py:188(init_hist)
       74    0.001    0.000    0.013    0.000 function.py:207(build)
       26    0.000    0.000    0.013    0.001 iostream.py:547(flush)
       73    0.002    0.000    0.013    0.000 ex_pump.py:494(find_classification)
     5698    0.008    0.000    0.013    0.000 inspect.py:2636(__init__)
      370    0.002    0.000    0.012    0.000 mode.py:204(__init__)
     2220    0.009    0.000    0.012    0.000 inspect.py:2919(__init__)
       26    0.000    0.000    0.012    0.000 threading.py:589(wait)
      962    0.006    0.000    0.012    0.000 inspect.py:3205(__str__)
       26    0.000    0.000    0.012    0.000 threading.py:288(wait)
   143648    0.012    0.000    0.012    0.000 {method 'get' of 'dict' objects}
     1329    0.002    0.000    0.012    0.000 base.py:83(get_timerange)
      207    0.012    0.000    0.012    0.000 {method 'acquire' of '_thread.lock' objects}
    33026    0.008    0.000    0.011    0.000 base.py:381(return_mutables)
     1183    0.001    0.000    0.011    0.000 base.py:98(get_histrange)
    94779    0.010    0.000    0.011    0.000 {built-in method builtins.isinstance}
     8185    0.004    0.000    0.011    0.000 ex_pump.py:269(behavior)
     1110    0.003    0.000    0.011    0.000 inspect.py:1967(_signature_bound_method)
      518    0.003    0.000    0.010    0.000 base.py:69(find_any_phase_overlap)
    91104    0.009    0.000    0.009    0.000 {method 'copy' of 'set' objects}
     8276    0.006    0.000    0.009    0.000 ex_pump.py:363(condfaults)
      370    0.004    0.000    0.008    0.000 mode.py:269(init_faultmodes)
112577/111846    0.007    0.000    0.008    0.000 {built-in method builtins.len}
      444    0.001    0.000    0.008    0.000 time.py:82(__init__)
     1329    0.001    0.000    0.007    0.000 fromnumeric.py:3269(round)
    63225    0.007    0.000    0.007    0.000 {method 'intersection' of 'set' objects}
      962    0.005    0.000    0.007    0.000 base.py:97(set_arg_type)
     1110    0.001    0.000    0.007    0.000 inspect.py:3013(replace)
    63522    0.007    0.000    0.007    0.000 {built-in method builtins.any}
    83298    0.007    0.000    0.007    0.000 {method 'values' of 'dict' objects}
     8258    0.006    0.000    0.007    0.000 base.py:189(<dictcomp>)
      584    0.001    0.000    0.007    0.000 result.py:307(__getattr__)
      962    0.003    0.000    0.007    0.000 base.py:70(get_true_fields)
     1770    0.002    0.000    0.006    0.000 common.py:60(is_numeric)
     1329    0.001    0.000    0.006    0.000 fromnumeric.py:53(_wrapfunc)
      962    0.004    0.000    0.006    0.000 parameter.py:120(check_immutable)
       74    0.000    0.000    0.006    0.000 base.py:190(build)
    20440    0.005    0.000    0.005    0.000 history.py:34(is_known_mutable)
    16352    0.004    0.000    0.005    0.000 __init__.py:304(__iter__)
     1036    0.001    0.000    0.005    0.000 fromnumeric.py:865(sort)
     1329    0.005    0.000    0.005    0.000 {method 'round' of 'numpy.ndarray' objects}
      438    0.003    0.000    0.005    0.000 result.py:348(all_with)
     4144    0.003    0.000    0.005    0.000 inspect.py:2720(__str__)
     4366    0.003    0.000    0.005    0.000 parameter.py:92(check_lim)
     4088    0.004    0.000    0.005    0.000 function.py:312(set_vars)
       74    0.001    0.000    0.004    0.000 function.py:219(construct_graph)
     3251    0.002    0.000    0.004    0.000 __init__.py:1091(__init__)
    25112    0.004    0.000    0.004    0.000 {method 'split' of 'str' objects}
    33666    0.004    0.000    0.004    0.000 {method 'join' of 'str' objects}
      962    0.001    0.000    0.004    0.000 base.py:77(<listcomp>)
       73    0.000    0.000    0.004    0.000 function.py:231(calc_repaircost)
     5698    0.003    0.000    0.004    0.000 enum.py:359(__call__)
    21482    0.004    0.000    0.004    0.000 {method 'update' of 'set' objects}
     6377    0.003    0.000    0.003    0.000 result.py:298(items)
      444    0.003    0.000    0.003    0.000 time.py:103(set_timestep)
   298/76    0.001    0.000    0.003    0.000 copy.py:227(_deepcopy_dict)
     1779    0.002    0.000    0.003    0.000 numerictypes.py:357(issubdtype)
    12264    0.003    0.000    0.003    0.000 __init__.py:74(__len__)
      962    0.003    0.000    0.003    0.000 parameter.py:141(check_type)
       74    0.000    0.000    0.003    0.000 timer.py:34(__init__)
     8273    0.003    0.000    0.003    0.000 ex_pump.py:194(condfaults)
     8276    0.003    0.000    0.003    0.000 ex_pump.py:387(indicate_over_pressure)
     6808    0.002    0.000    0.003    0.000 inspect.py:2968(<genexpr>)
    15111    0.003    0.000    0.003    0.000 {built-in method builtins.min}
    33240    0.003    0.000    0.003    0.000 {method 'append' of 'list' objects}
    20882    0.003    0.000    0.003    0.000 {built-in method builtins.setattr}
       77    0.000    0.000    0.002    0.000 iostream.py:243(schedule)
       26    0.000    0.000    0.002    0.000 iostream.py:610(write)
      148    0.001    0.000    0.002    0.000 base.py:333(create_hist)
       26    0.000    0.000    0.002    0.000 iostream.py:532(_schedule_flush)
     1110    0.001    0.000    0.002    0.000 inspect.py:612(unwrap)
     1110    0.002    0.000    0.002    0.000 inspect.py:66(get_annotations)
     3251    0.002    0.000    0.002    0.000 result.py:317(__setattr__)
     4088    0.002    0.000    0.002    0.000 base.py:129(get_hist_ind)
       77    0.002    0.000    0.002    0.000 socket.py:543(send)
     4088    0.002    0.000    0.002    0.000 propagate.py:1004(check_end_condition)
      222    0.001    0.000    0.002    0.000 base.py:350(init_indicator_hist)
       73    0.000    0.000    0.002    0.000 fromnumeric.py:2836(min)
     1329    0.002    0.000    0.002    0.000 {built-in method numpy.arange}
     1036    0.002    0.000    0.002    0.000 {built-in method numpy.asanyarray}
    19782    0.002    0.000    0.002    0.000 {built-in method builtins.id}
    17256    0.002    0.000    0.002    0.000 copy.py:182(_deepcopy_atomic)
     4088    0.002    0.000    0.002    0.000 ex_pump.py:490(indicate_on)
       24    0.000    0.000    0.002    0.000 std.py:1147(__str__)
     4088    0.002    0.000    0.002    0.000 ex_pump.py:471(indicate_finished)
     3558    0.001    0.000    0.002    0.000 numerictypes.py:283(issubclass_)
       73    0.000    0.000    0.002    0.000 fromnumeric.py:71(_wrapreduction)
     2587    0.002    0.000    0.002    0.000 common.py:26(get_sub_include)
      370    0.001    0.000    0.002    0.000 base.py:505(check_flows)
    16412    0.002    0.000    0.002    0.000 {method 'items' of 'dict' objects}
     3347    0.001    0.000    0.001    0.000 {method 'format' of 'str' objects}
      962    0.001    0.000    0.001    0.000 base.py:148(init_track)
     4366    0.001    0.000    0.001    0.000 base.py:137(set_arg_as_type)
     4599    0.001    0.000    0.001    0.000 __init__.py:1118(__contains__)
      296    0.001    0.000    0.001    0.000 history.py:184(init_att)
       24    0.001    0.000    0.001    0.000 std.py:352(format_meter)
       74    0.000    0.000    0.001    0.000 function.py:258(return_faultmodes)
    17658    0.001    0.000    0.001    0.000 {built-in method builtins.iter}
      864    0.001    0.000    0.001    0.000 function.py:448(<listcomp>)
     1776    0.001    0.000    0.001    0.000 result.py:141(check_include_errors)
        1    0.000    0.000    0.001    0.001 std.py:837(__init__)
     2140    0.001    0.000    0.001    0.000 abc.py:117(__instancecheck__)
    15096    0.001    0.000    0.001    0.000 inspect.py:2698(kind)
       74    0.001    0.000    0.001    0.000 history.py:320(cut)
      370    0.001    0.000    0.001    0.000 function.py:97(update_seed)
      148    0.000    0.000    0.001    0.000 state.py:296(init_hist_att)
       73    0.001    0.000    0.001    0.000 {method 'reduce' of 'numpy.ufunc' objects}
      370    0.000    0.000    0.001    0.000 base.py:482(update_contained_modes)
      170    0.001    0.000    0.001    0.000 {built-in method builtins.sum}
     1036    0.001    0.000    0.001    0.000 {method 'copy' of 'numpy.ndarray' objects}
     8258    0.001    0.000    0.001    0.000 {method 'clear' of 'set' objects}
     3531    0.001    0.000    0.001    0.000 __init__.py:1108(__setitem__)
       74    0.001    0.000    0.001    0.000 graph.py:961(add_edges_from)
       74    0.000    0.000    0.001    0.000 backends.py:129(wrapper)
     8258    0.001    0.000    0.001    0.000 {method 'copy' of 'list' objects}
      148    0.000    0.000    0.001    0.000 base.py:320(init_hist_att)
      370    0.001    0.000    0.001    0.000 function.py:73(return_faultmodes)
      518    0.001    0.000    0.001    0.000 base.py:74(<listcomp>)
     1770    0.001    0.000    0.001    0.000 {built-in method numpy.array}
     2357    0.001    0.000    0.001    0.000 __init__.py:1098(__len__)
    10286    0.001    0.000    0.001    0.000 inspect.py:2686(name)
       74    0.000    0.000    0.001    0.000 isolate.py:42(isolates)
     5698    0.001    0.000    0.001    0.000 enum.py:678(__new__)
     5698    0.001    0.000    0.001    0.000 {method 'isidentifier' of 'str' objects}
       74    0.000    0.000    0.001    0.000 function.py:215(<listcomp>)
     2146    0.001    0.000    0.001    0.000 base.py:23(check_role)
     8176    0.001    0.000    0.001    0.000 {method 'index' of 'list' objects}
       73    0.000    0.000    0.001    0.000 base.py:109(get_shift)
       24    0.000    0.000    0.001    0.000 utils.py:309(disp_len)
     1036    0.001    0.000    0.001    0.000 {method 'sort' of 'numpy.ndarray' objects}
      146    0.000    0.000    0.001    0.000 _collections_abc.py:991(update)
      370    0.000    0.000    0.001    0.000 __init__.py:201(update)
     2220    0.001    0.000    0.001    0.000 inspect.py:277(isfunction)
     2140    0.001    0.000    0.001    0.000 {built-in method _abc._abc_instancecheck}
       24    0.000    0.000    0.001    0.000 utils.py:305(_text_width)
      148    0.001    0.000    0.001    0.000 graph.py:563(add_nodes_from)
        2    0.000    0.000    0.001    0.000 std.py:1262(close)
       74    0.000    0.000    0.001    0.000 copy.py:259(_reconstruct)
       74    0.000    0.000    0.001    0.000 functools.py:961(__get__)
       73    0.000    0.000    0.001    0.000 base.py:196(init_time_hist)
     1160    0.001    0.000    0.001    0.000 graph.py:1315(neighbors)
        1    0.000    0.000    0.001    0.001 std.py:326(status_printer)
     1184    0.000    0.000    0.001    0.000 base.py:142(check_slots)
      518    0.001    0.000    0.001    0.000 {built-in method recordclass._dataobject.asdict}
      370    0.001    0.000    0.001    0.000 base.py:525(<listcomp>)
       74    0.000    0.000    0.001    0.000 function.py:227(<listcomp>)
     5411    0.001    0.000    0.001    0.000 {built-in method builtins.issubclass}
      370    0.000    0.000    0.001    0.000 base.py:212(get_flows)
     4088    0.001    0.000    0.001    0.000 {built-in method from_iterable}
       74    0.000    0.000    0.001    0.000 function.py:212(<listcomp>)
       74    0.000    0.000    0.001    0.000 isolate.py:85(<genexpr>)
     4381    0.001    0.000    0.001    0.000 {method 'keys' of 'dict' objects}
      518    0.001    0.000    0.001    0.000 base.py:71(<dictcomp>)
     1620    0.000    0.000    0.000    0.000 utils.py:306(<genexpr>)
      584    0.000    0.000    0.000    0.000 result.py:122(get_dict_attr)
      148    0.000    0.000    0.000    0.000 copy.py:264(<genexpr>)
     1110    0.000    0.000    0.000    0.000 inspect.py:632(_is_wrapper)
      370    0.000    0.000    0.000    0.000 base.py:443(<dictcomp>)
      370    0.000    0.000    0.000    0.000 base.py:470(<dictcomp>)
       74    0.000    0.000    0.000    0.000 function.py:210(<listcomp>)
       74    0.000    0.000    0.000    0.000 graph.py:332(__init__)
     2320    0.000    0.000    0.000    0.000 __init__.py:165(__contains__)
     2072    0.000    0.000    0.000    0.000 {method 'values' of 'mappingproxy' objects}
      370    0.000    0.000    0.000    0.000 base.py:552(is_dynamic)
     1776    0.000    0.000    0.000    0.000 result.py:149(check_include_error)
      446    0.000    0.000    0.000    0.000 copy.py:243(_keep_alive)
      296    0.000    0.000    0.000    0.000 function.py:216(<listcomp>)
      740    0.000    0.000    0.000    0.000 reportviews.py:527(__iter__)
       74    0.000    0.000    0.000    0.000 graph.py:1481(degree)
      518    0.000    0.000    0.000    0.000 base.py:73(<listcomp>)
      370    0.000    0.000    0.000    0.000 base.py:520(<listcomp>)
      656    0.000    0.000    0.000    0.000 __init__.py:1101(__getitem__)
     3330    0.000    0.000    0.000    0.000 {built-in method builtins.callable}
      666    0.000    0.000    0.000    0.000 inspect.py:191(isclass)
       26    0.000    0.000    0.000    0.000 threading.py:545(__init__)
      103    0.000    0.000    0.000    0.000 threading.py:1169(is_alive)
     2220    0.000    0.000    0.000    0.000 inspect.py:3005(parameters)
      370    0.000    0.000    0.000    0.000 base.py:216(<dictcomp>)
      296    0.000    0.000    0.000    0.000 {built-in method numpy.empty}
     1329    0.000    0.000    0.000    0.000 fromnumeric.py:3265(_round_dispatcher)
      511    0.000    0.000    0.000    0.000 propagate.py:110(<genexpr>)
       74    0.000    0.000    0.000    0.000 copy.py:201(_deepcopy_list)
      133    0.000    0.000    0.000    0.000 std.py:230(__call__)
     2220    0.000    0.000    0.000    0.000 {built-in method builtins.repr}
       74    0.000    0.000    0.000    0.000 base.py:321(get_indicators)
      148    0.000    0.000    0.000    0.000 base.py:205(<dictcomp>)
      293    0.000    0.000    0.000    0.000 result.py:295(keys)
       27    0.000    0.000    0.000    0.000 std.py:101(acquire)
       47    0.000    0.000    0.000    0.000 std.py:285(format_interval)
      517    0.000    0.000    0.000    0.000 {built-in method fromkeys}
     1949    0.000    0.000    0.000    0.000 {method 'update' of 'dict' objects}
       24    0.000    0.000    0.000    0.000 std.py:1443(format_dict)
       48    0.000    0.000    0.000    0.000 utils.py:204(_is_ascii)
       74    0.000    0.000    0.000    0.000 reportviews.py:417(__init__)
     1776    0.000    0.000    0.000    0.000 copy.py:107(_copy_immutable)
      370    0.000    0.000    0.000    0.000 base.py:546(is_static)
       74    0.000    0.000    0.000    0.000 base.py:52(init_flexible_roles)
     1036    0.000    0.000    0.000    0.000 fromnumeric.py:861(_sort_dispatcher)
       74    0.000    0.000    0.000    0.000 propagate.py:230(save_helper)
       27    0.000    0.000    0.000    0.000 std.py:105(release)
      962    0.000    0.000    0.000    0.000 inspect.py:3009(return_annotation)
       74    0.000    0.000    0.000    0.000 base.py:330(<dictcomp>)
      592    0.000    0.000    0.000    0.000 base.py:56(check_role)
       52    0.000    0.000    0.000    0.000 {built-in method _thread.allocate_lock}
      222    0.000    0.000    0.000    0.000 base.py:452(<listcomp>)
     1596    0.000    0.000    0.000    0.000 {built-in method unicodedata.east_asian_width}
      148    0.000    0.000    0.000    0.000 base.py:41(get_track)
       26    0.000    0.000    0.000    0.000 threading.py:236(__init__)
      394    0.000    0.000    0.000    0.000 {built-in method builtins.max}
     1110    0.000    0.000    0.000    0.000 {built-in method sys.getrecursionlimit}
       73    0.000    0.000    0.000    0.000 function.py:253(<listcomp>)
      146    0.000    0.000    0.000    0.000 __init__.py:1114(__iter__)
      144    0.000    0.000    0.000    0.000 scenario.py:30(get)
     1332    0.000    0.000    0.000    0.000 {method 'copy' of 'dict' objects}
      370    0.000    0.000    0.000    0.000 function.py:85(<listcomp>)
       90    0.000    0.000    0.000    0.000 mode.py:480(add_fault)
      103    0.000    0.000    0.000    0.000 threading.py:1102(_wait_for_tstate_lock)
       27    0.000    0.000    0.000    0.000 {method 'acquire' of '_multiprocessing.SemLock' objects}
       24    0.000    0.000    0.000    0.000 std.py:185(__format__)
       73    0.000    0.000    0.000    0.000 propagate.py:108(unpack_sim_kwargs)
       74    0.000    0.000    0.000    0.000 {method '__reduce_ex__' of 'object' objects}
       73    0.000    0.000    0.000    0.000 fromnumeric.py:72(<dictcomp>)
      292    0.000    0.000    0.000    0.000 {method 'endswith' of 'str' objects}
      370    0.000    0.000    0.000    0.000 base.py:208(update_seed)
       74    0.000    0.000    0.000    0.000 base.py:243(update_seed)
      195    0.000    0.000    0.000    0.000 time.py:90(__getattr__)
       77    0.000    0.000    0.000    0.000 iostream.py:127(_event_pipe)
        2    0.000    0.000    0.000    0.000 std.py:1283(fp_write)
       74    0.000    0.000    0.000    0.000 graph.py:59(__set__)
       72    0.000    0.000    0.000    0.000 mode.py:393(update_modestates)
       24    0.000    0.000    0.000    0.000 std.py:152(__init__)
        1    0.000    0.000    0.000    0.000 result.py:522(get_memory)
        1    0.000    0.000    0.000    0.000 utils.py:228(_screen_shape_windows)
       73    0.000    0.000    0.000    0.000 propagate.py:1148(<listcomp>)
       27    0.000    0.000    0.000    0.000 {method 'release' of '_multiprocessing.SemLock' objects}
       60    0.000    0.000    0.000    0.000 timer.py:57(inc)
      370    0.000    0.000    0.000    0.000 base.py:459(init_block)
       26    0.000    0.000    0.000    0.000 iostream.py:505(_is_master_process)
      444    0.000    0.000    0.000    0.000 inspect.py:2690(default)
       23    0.000    0.000    0.000    0.000 {built-in method now}
       74    0.000    0.000    0.000    0.000 graph.py:37(__set__)
       24    0.000    0.000    0.000    0.000 {method 'sub' of 're.Pattern' objects}
       26    0.000    0.000    0.000    0.000 threading.py:1430(current_thread)
       26    0.000    0.000    0.000    0.000 threading.py:276(_acquire_restore)
        1    0.000    0.000    0.000    0.000 std.py:574(_decr_instances)
       73    0.000    0.000    0.000    0.000 propagate.py:1171(<listcomp>)
       77    0.000    0.000    0.000    0.000 {method 'pop' of 'dict' objects}
        1    0.000    0.000    0.000    0.000 std.py:551(__new__)
       74    0.000    0.000    0.000    0.000 reportviews.py:424(__call__)
      504    0.000    0.000    0.000    0.000 {built-in method builtins.ord}
       74    0.000    0.000    0.000    0.000 parameter.py:89(keys)
       26    0.000    0.000    0.000    0.000 threading.py:267(__exit__)
        1    0.000    0.000    0.000    0.000 __init__.py:48(create_string_buffer)
      104    0.000    0.000    0.000    0.000 threading.py:553(is_set)
       52    0.000    0.000    0.000    0.000 threading.py:1145(ident)
       97    0.000    0.000    0.000    0.000 {built-in method time.time}
      118    0.000    0.000    0.000    0.000 {built-in method builtins.divmod}
        1    0.000    0.000    0.000    0.000 propagate.py:689(process_nominal)
       26    0.000    0.000    0.000    0.000 threading.py:264(__enter__)
      100    0.000    0.000    0.000    0.000 {method '__exit__' of '_thread.RLock' objects}
       26    0.000    0.000    0.000    0.000 threading.py:273(_release_save)
        1    0.000    0.000    0.000    0.000 propagate.py:156(pack_run_kwargs)
        4    0.000    0.000    0.000    0.000 std.py:109(__enter__)
       26    0.000    0.000    0.000    0.000 threading.py:279(_is_owned)
        3    0.000    0.000    0.000    0.000 _weakrefset.py:63(__iter__)
       73    0.000    0.000    0.000    0.000 fromnumeric.py:2831(_min_dispatcher)
       24    0.000    0.000    0.000    0.000 utils.py:39(__init__)
        1    0.000    0.000    0.000    0.000 propagate.py:158(<dictcomp>)
        1    0.000    0.000    0.000    0.000 std.py:567(_get_free_pos)
        4    0.000    0.000    0.000    0.000 std.py:112(__exit__)
       27    0.000    0.000    0.000    0.000 {method 'acquire' of '_thread.RLock' objects}
        1    0.000    0.000    0.000    0.000 utils.py:144(__init__)
       26    0.000    0.000    0.000    0.000 {built-in method nt.getpid}
      103    0.000    0.000    0.000    0.000 {method 'append' of 'collections.deque' objects}
       26    0.000    0.000    0.000    0.000 {method 'write' of '_io.StringIO' objects}
       24    0.000    0.000    0.000    0.000 std.py:166(colour)
        1    0.000    0.000    0.000    0.000 std.py:570(<setcomp>)
       26    0.000    0.000    0.000    0.000 {built-in method builtins.abs}
       24    0.000    0.000    0.000    0.000 utils.py:43(__format__)
        2    0.000    0.000    0.000    0.000 _weakrefset.py:27(__exit__)
        1    0.000    0.000    0.000    0.000 _weakrefset.py:111(remove)
       26    0.000    0.000    0.000    0.000 {built-in method _thread.get_ident}
        3    0.000    0.000    0.000    0.000 {method 'remove' of 'set' objects}
       27    0.000    0.000    0.000    0.000 {method 'release' of '_thread.RLock' objects}
       24    0.000    0.000    0.000    0.000 std.py:162(colour)
        1    0.000    0.000    0.000    0.000 utils.py:197(_supports_unicode)
        2    0.000    0.000    0.000    0.000 _weakrefset.py:53(_commit_removals)
       26    0.000    0.000    0.000    0.000 {method '__enter__' of '_thread.lock' objects}
        1    0.000    0.000    0.000    0.000 _weakrefset.py:86(add)
       26    0.000    0.000    0.000    0.000 {method '__exit__' of '_thread.lock' objects}
        1    0.000    0.000    0.000    0.000 utils.py:56(__eq__)
       26    0.000    0.000    0.000    0.000 {method 'release' of '_thread.lock' objects}
        5    0.000    0.000    0.000    0.000 propagate.py:191(<genexpr>)
        2    0.000    0.000    0.000    0.000 _weakrefset.py:21(__enter__)
        1    0.000    0.000    0.000    0.000 utils.py:87(__init__)
        4    0.000    0.000    0.000    0.000 utils.py:153(__eq__)
        1    0.000    0.000    0.000    0.000 scenario.py:119(__init__)
        1    0.000    0.000    0.000    0.000 utils.py:183(_is_utf)
        1    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap>:1053(_handle_fromlist)
        2    0.000    0.000    0.000    0.000 utils.py:118(disable_on_exception)
        1    0.000    0.000    0.000    0.000 _monitor.py:94(report)
        3    0.000    0.000    0.000    0.000 utils.py:83(wrapper_setattr)
        1    0.000    0.000    0.000    0.000 sample.py:794(scenarios)
        1    0.000    0.000    0.000    0.000 sample.py:790(times)
        3    0.000    0.000    0.000    0.000 {method 'add' of 'set' objects}
        1    0.000    0.000    0.000    0.000 {built-in method utcfromtimestamp}
        2    0.000    0.000    0.000    0.000 std.py:1150(_comparable)
        2    0.000    0.000    0.000    0.000 _weakrefset.py:17(__init__)
        1    0.000    0.000    0.000    0.000 propagate.py:189(unpack_mult_kwargs)
        1    0.000    0.000    0.000    0.000 {method 'encode' of 'str' objects}
        3    0.000    0.000    0.000    0.000 std.py:225(__init__)
        2    0.000    0.000    0.000    0.000 std.py:1154(__hash__)
        1    0.000    0.000    0.000    0.000 std.py:648(get_lock)
        1    0.000    0.000    0.000    0.000 propagate.py:860(check_overwrite)
        1    0.000    0.000    0.000    0.000 utils.py:70(__getattr__)
        2    0.000    0.000    0.000    0.000 {method 'pop' of 'list' objects}
        1    0.000    0.000    0.000    0.000 propagate.py:796(close_pool)
        1    0.000    0.000    0.000    0.000 std.py:1144(__del__)
        1    0.000    0.000    0.000    0.000 {method 'difference' of 'set' objects}
        2    0.000    0.000    0.000    0.000 {built-in method _weakref.proxy}
        1    0.000    0.000    0.000    0.000 utils.py:213(_screen_shape_wrapper)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 {built-in method sys.audit}
        1    0.000    0.000    0.000    0.000 std.py:1298(<lambda>)
        1    0.000    0.000    0.000    0.000 scenario.py:121(<dictcomp>)
        1    0.000    0.000    0.000    0.000 {built-in method __new__ of type object at 0x00007FFD44BEAD50}


[39]:
prof = cProfile.run('Pump()', sort='tottime')
         7891 function calls (7870 primitive calls) in 0.004 seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       25    0.001    0.000    0.001    0.000 base.py:194(<listcomp>)
       36    0.001    0.000    0.001    0.000 {built-in method builtins.dir}
     3551    0.000    0.000    0.000    0.000 {method 'startswith' of 'str' objects}
       11    0.000    0.000    0.000    0.000 base.py:318(<listcomp>)
       20    0.000    0.000    0.003    0.000 base.py:197(init_roles)
       14    0.000    0.000    0.000    0.000 inspect.py:2279(_signature_from_function)
       74    0.000    0.000    0.000    0.000 inspect.py:2636(__init__)
       28    0.000    0.000    0.000    0.000 inspect.py:2919(__init__)
    28/14    0.000    0.000    0.001    0.000 inspect.py:2374(_signature_from_callable)
       12    0.000    0.000    0.001    0.000 parameter.py:50(__init__)
       12    0.000    0.000    0.000    0.000 inspect.py:3205(__str__)
       12    0.000    0.000    0.000    0.000 base.py:97(set_arg_type)
       12    0.000    0.000    0.000    0.000 parameter.py:120(check_immutable)
    21/16    0.000    0.000    0.000    0.000 result.py:464(flatten)
       15    0.000    0.000    0.000    0.000 {method 'round' of 'numpy.ndarray' objects}
      334    0.000    0.000    0.000    0.000 {built-in method builtins.getattr}
        5    0.000    0.000    0.002    0.000 base.py:428(__init__)
       74    0.000    0.000    0.000    0.000 enum.py:359(__call__)
        5    0.000    0.000    0.000    0.000 mode.py:269(init_faultmodes)
        9    0.000    0.000    0.003    0.000 base.py:73(add_flex_role_obj)
       54    0.000    0.000    0.000    0.000 inspect.py:2720(__str__)
      449    0.000    0.000    0.000    0.000 {built-in method builtins.isinstance}
        6    0.000    0.000    0.000    0.000 base.py:69(find_any_phase_overlap)
       15    0.000    0.000    0.000    0.000 base.py:431(create_hist)
       14    0.000    0.000    0.000    0.000 inspect.py:1967(_signature_bound_method)
        6    0.000    0.000    0.000    0.000 time.py:103(set_timestep)
       13    0.000    0.000    0.000    0.000 base.py:70(get_true_fields)
    11/10    0.000    0.000    0.003    0.000 base.py:106(__init__)
       12    0.000    0.000    0.000    0.000 parameter.py:141(check_type)
        1    0.000    0.000    0.004    0.004 {built-in method builtins.exec}
    16/15    0.000    0.000    0.003    0.000 base.py:173(init_roletypes)
       45    0.000    0.000    0.000    0.000 parameter.py:92(check_lim)
       88    0.000    0.000    0.000    0.000 inspect.py:2968(<genexpr>)
       15    0.000    0.000    0.000    0.000 base.py:83(get_timerange)
       25    0.000    0.000    0.001    0.000 base.py:193(find_roletype_initiators)
       47    0.000    0.000    0.000    0.000 copy.py:66(copy)
       12    0.000    0.000    0.001    0.000 parameter.py:164(check_pickle)
        5    0.000    0.000    0.000    0.000 mode.py:204(__init__)
       95    0.000    0.000    0.000    0.000 {built-in method builtins.hasattr}
      322    0.000    0.000    0.000    0.000 {method 'get' of 'dict' objects}
       32    0.000    0.000    0.000    0.000 common.py:26(get_sub_include)
       14    0.000    0.000    0.000    0.000 inspect.py:612(unwrap)
       34    0.000    0.000    0.000    0.000 result.py:317(__setattr__)
       14    0.000    0.000    0.000    0.000 inspect.py:66(get_annotations)
        6    0.000    0.000    0.001    0.000 base.py:61(__init__)
       13    0.000    0.000    0.000    0.000 base.py:77(<listcomp>)
        9    0.000    0.000    0.003    0.000 base.py:509(init_obj)
        5    0.000    0.000    0.003    0.001 base.py:160(add_sim)
       13    0.000    0.000    0.000    0.000 base.py:148(init_track)
       34    0.000    0.000    0.000    0.000 __init__.py:1091(__init__)
      196    0.000    0.000    0.000    0.000 inspect.py:2698(kind)
       59    0.000    0.000    0.000    0.000 {built-in method builtins.setattr}
       11    0.000    0.000    0.000    0.000 base.py:316(init_indicators)
       74    0.000    0.000    0.000    0.000 enum.py:678(__new__)
      289    0.000    0.000    0.000    0.000 {built-in method builtins.len}
       15    0.000    0.000    0.000    0.000 {built-in method numpy.arange}
       42    0.000    0.000    0.000    0.000 {method 'format' of 'str' objects}
       12    0.000    0.000    0.000    0.000 fromnumeric.py:865(sort)
       13    0.000    0.000    0.000    0.000 common.py:60(is_numeric)
       13    0.000    0.000    0.000    0.000 numerictypes.py:357(issubdtype)
        6    0.000    0.000    0.002    0.000 base.py:174(__init__)
        6    0.000    0.000    0.000    0.000 time.py:82(__init__)
       14    0.000    0.000    0.001    0.000 inspect.py:2997(from_callable)
        5    0.000    0.000    0.003    0.001 function.py:153(add_fxn)
        4    0.000    0.000    0.000    0.000 history.py:184(init_att)
      134    0.000    0.000    0.000    0.000 inspect.py:2686(name)
       15    0.000    0.000    0.000    0.000 base.py:98(get_histrange)
       12    0.000    0.000    0.000    0.000 {built-in method numpy.asanyarray}
       14    0.000    0.000    0.000    0.000 inspect.py:3013(replace)
      161    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
       29    0.000    0.000    0.000    0.000 base.py:23(check_role)
       21    0.000    0.000    0.000    0.000 result.py:141(check_include_errors)
       26    0.000    0.000    0.000    0.000 numerictypes.py:283(issubclass_)
       15    0.000    0.000    0.000    0.000 fromnumeric.py:3269(round)
       45    0.000    0.000    0.000    0.000 base.py:137(set_arg_as_type)
       14    0.000    0.000    0.001    0.000 inspect.py:3251(signature)
        1    0.000    0.000    0.000    0.000 graph.py:961(add_edges_from)
       15    0.000    0.000    0.000    0.000 fromnumeric.py:53(_wrapfunc)
        1    0.000    0.000    0.003    0.003 ex_pump.py:443(init_architecture)
        3    0.000    0.000    0.000    0.000 base.py:350(init_indicator_hist)
       12    0.000    0.000    0.000    0.000 {method 'copy' of 'numpy.ndarray' objects}
        6    0.000    0.000    0.000    0.000 base.py:188(init_hist)
        5    0.000    0.000    0.000    0.000 base.py:505(check_flows)
        5    0.000    0.000    0.002    0.000 function.py:58(__init__)
       28    0.000    0.000    0.000    0.000 inspect.py:277(isfunction)
        5    0.000    0.000    0.000    0.000 base.py:463(create_arch_kwargs)
        1    0.000    0.000    0.004    0.004 <string>:1(<module>)
       13    0.000    0.000    0.000    0.000 {built-in method numpy.array}
       12    0.000    0.000    0.000    0.000 {method 'sort' of 'numpy.ndarray' objects}
       21    0.000    0.000    0.000    0.000 result.py:298(items)
        2    0.000    0.000    0.000    0.000 graph.py:563(add_nodes_from)
        1    0.000    0.000    0.004    0.004 base.py:34(__init__)
       10    0.000    0.000    0.000    0.000 __init__.py:180(add)
       10    0.000    0.000    0.000    0.000 base.py:395(<listcomp>)
        5    0.000    0.000    0.000    0.000 function.py:97(update_seed)
        1    0.000    0.000    0.000    0.000 function.py:219(construct_graph)
       10    0.000    0.000    0.000    0.000 base.py:391(get_roles)
        1    0.000    0.000    0.000    0.000 function.py:207(build)
       74    0.000    0.000    0.000    0.000 {method 'isidentifier' of 'str' objects}
        6    0.000    0.000    0.000    0.000 base.py:74(<listcomp>)
        5    0.000    0.000    0.000    0.000 base.py:525(<listcomp>)
        1    0.000    0.000    0.004    0.004 function.py:126(__init__)
       21    0.000    0.000    0.000    0.000 __init__.py:1098(__len__)
       17    0.000    0.000    0.000    0.000 __init__.py:1108(__setitem__)
       16    0.000    0.000    0.000    0.000 base.py:142(check_slots)
        6    0.000    0.000    0.000    0.000 base.py:71(<dictcomp>)
        2    0.000    0.000    0.000    0.000 base.py:333(create_hist)
        4    0.000    0.000    0.001    0.000 base.py:120(add_flow)
        5    0.000    0.000    0.000    0.000 {built-in method recordclass._dataobject.asdict}
        5    0.000    0.000    0.000    0.000 base.py:482(update_contained_modes)
        1    0.000    0.000    0.000    0.000 function.py:215(<listcomp>)
        1    0.000    0.000    0.000    0.000 base.py:190(build)
       13    0.000    0.000    0.000    0.000 {built-in method _abc._abc_instancecheck}
        5    0.000    0.000    0.000    0.000 base.py:443(<dictcomp>)
       14    0.000    0.000    0.000    0.000 inspect.py:632(_is_wrapper)
        4    0.000    0.000    0.000    0.000 base.py:87(create_hist)
        3    0.000    0.000    0.000    0.000 __init__.py:65(__init__)
        1    0.000    0.000    0.000    0.000 functools.py:961(__get__)
       26    0.000    0.000    0.000    0.000 {method 'values' of 'mappingproxy' objects}
       39    0.000    0.000    0.000    0.000 {built-in method builtins.issubclass}
        5    0.000    0.000    0.000    0.000 __init__.py:201(update)
       10    0.000    0.000    0.000    0.000 reportviews.py:527(__iter__)
        2    0.000    0.000    0.000    0.000 base.py:320(init_hist_att)
       21    0.000    0.000    0.000    0.000 result.py:149(check_include_error)
        5    0.000    0.000    0.000    0.000 base.py:212(get_flows)
        1    0.000    0.000    0.000    0.000 graph.py:332(__init__)
        4    0.000    0.000    0.000    0.000 function.py:216(<listcomp>)
       13    0.000    0.000    0.000    0.000 abc.py:117(__instancecheck__)
        6    0.000    0.000    0.000    0.000 base.py:73(<listcomp>)
       36    0.000    0.000    0.000    0.000 {method 'items' of 'dict' objects}
       42    0.000    0.000    0.000    0.000 {built-in method builtins.callable}
        5    0.000    0.000    0.000    0.000 base.py:470(<dictcomp>)
        5    0.000    0.000    0.000    0.000 base.py:520(<listcomp>)
        1    0.000    0.000    0.000    0.000 function.py:210(<listcomp>)
        1    0.000    0.000    0.000    0.000 isolate.py:42(isolates)
        2    0.000    0.000    0.000    0.000 state.py:296(init_hist_att)
       30    0.000    0.000    0.000    0.000 {built-in method builtins.repr}
        5    0.000    0.000    0.000    0.000 base.py:552(is_dynamic)
        5    0.000    0.000    0.000    0.000 base.py:216(<dictcomp>)
        9    0.000    0.000    0.000    0.000 inspect.py:191(isclass)
       28    0.000    0.000    0.000    0.000 inspect.py:3005(parameters)
        2    0.000    0.000    0.000    0.000 base.py:205(<dictcomp>)
        4    0.000    0.000    0.000    0.000 graph.py:1315(neighbors)
        2    0.000    0.000    0.000    0.000 base.py:41(get_track)
        1    0.000    0.000    0.000    0.000 function.py:212(<listcomp>)
        4    0.000    0.000    0.000    0.000 {built-in method numpy.empty}
       26    0.000    0.000    0.000    0.000 {method 'update' of 'dict' objects}
       12    0.000    0.000    0.000    0.000 {method 'join' of 'str' objects}
       15    0.000    0.000    0.000    0.000 fromnumeric.py:3265(_round_dispatcher)
        8    0.000    0.000    0.000    0.000 base.py:56(check_role)
       24    0.000    0.000    0.000    0.000 copy.py:107(_copy_immutable)
        1    0.000    0.000    0.000    0.000 reportviews.py:417(__init__)
        1    0.000    0.000    0.000    0.000 isolate.py:85(<genexpr>)
        1    0.000    0.000    0.000    0.000 timer.py:34(__init__)
        3    0.000    0.000    0.000    0.000 base.py:452(<listcomp>)
       12    0.000    0.000    0.000    0.000 fromnumeric.py:861(_sort_dispatcher)
        1    0.000    0.000    0.000    0.000 base.py:52(init_flexible_roles)
       14    0.000    0.000    0.000    0.000 {built-in method builtins.id}
        2    0.000    0.000    0.000    0.000 _collections_abc.py:767(__ior__)
        1    0.000    0.000    0.000    0.000 backends.py:129(wrapper)
       12    0.000    0.000    0.000    0.000 inspect.py:3009(return_annotation)
        1    0.000    0.000    0.000    0.000 base.py:330(<dictcomp>)
        5    0.000    0.000    0.000    0.000 base.py:546(is_static)
        1    0.000    0.000    0.000    0.000 graph.py:1481(degree)
       18    0.000    0.000    0.000    0.000 {method 'copy' of 'dict' objects}
        5    0.000    0.000    0.000    0.000 {built-in method builtins.max}
        1    0.000    0.000    0.000    0.000 base.py:321(get_indicators)
       12    0.000    0.000    0.000    0.000 {method 'values' of 'dict' objects}
        2    0.000    0.000    0.000    0.000 __init__.py:1101(__getitem__)
        5    0.000    0.000    0.000    0.000 base.py:208(update_seed)
       14    0.000    0.000    0.000    0.000 {built-in method sys.getrecursionlimit}
        8    0.000    0.000    0.000    0.000 __init__.py:165(__contains__)
        5    0.000    0.000    0.000    0.000 {method 'copy' of 'set' objects}
        1    0.000    0.000    0.000    0.000 graph.py:59(__set__)
        1    0.000    0.000    0.000    0.000 graph.py:37(__set__)
        5    0.000    0.000    0.000    0.000 base.py:459(init_block)
        1    0.000    0.000    0.000    0.000 function.py:227(<listcomp>)
        6    0.000    0.000    0.000    0.000 inspect.py:2690(default)
        1    0.000    0.000    0.000    0.000 base.py:243(update_seed)
        4    0.000    0.000    0.000    0.000 {built-in method builtins.any}
        1    0.000    0.000    0.000    0.000 reportviews.py:424(__call__)
        1    0.000    0.000    0.000    0.000 {method 'lower' of 'str' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 {method '__exit__' of '_thread.RLock' objects}
        4    0.000    0.000    0.000    0.000 {built-in method builtins.iter}


As shown, running this model is not particularly computationally expensive. As a result, the majority of the computational expense is not actually because of the simulation itself, but because of the way the model is simulated: - the majority is spent simulating the model - a certain amount is spent re-initalizing the model at first so that the model object can be re-used without worrying about it being modified by any previous executions - another amount is spent recording the model history, wich can increase or decrease depending on tracking options (note the low number of values tracked in the pump model by default)

This is mostly because the model itself is computationally inexpensive. However, this example shows how one might easily speed up simulation for optimization or large-n simulations–avoiding unnecessary re-initialization, tracking fewer model states, or speeding up model execution. This can be done in the following ways: - using the options for track (as mentioned above) to track fewer states (reducing time spent recording the history) - using protect options, which specifies whether the model used is re-instantiated for the simulation (True) or used directly (False) - speeding up the model by using dynamic_behavior() methods instead of static_behavior() or behavior() methods (which can halve the simulation time at the expense of undirected propagation) - speeding up the model by using a longer global timestep ('tstep' in modelparams) or by speeding up paricularly expensive Function dynamic behaviors by setting (dt=local_tstep) in the SimParam

[ ]: