Eomys/pyleecan

[CO] EEC reorganization and LUT as a daughter of XOutput

Closed this issue · 13 comments

Hello all,

As a follow up of our discussions in #481 and EOMYS-Public#12, we would like to gather in a single issue a fully detailed proposal on how to organize the Electrical module, EEC and LUT objects based on @SebGue idea to have LUT as a daughter of XOutput.

The first point is regarding the EEC objects. For now, to store the parameters we use a dictionary which is flexible but not standard. EEC_SCIM, EEC_LSRPM and EEC_PMSM are linked to specific and unique equivalent circuit with a frozen list of parameters. We propose to replace the parameters dict by the correct set of properties (R1, R2, L1, L2…) with the proper type, description, and min/max in the corresponding EEC objects csv files.

Then we would use EEC objects both in Simulation.elec and in OutputElec (instead of the param dict). In a Simulation object, if a EEC value is at None it means that this parameter needs to be computed else it is enforced. comp_parameter would copy the simulation.elec.eec object and compute/enforce the corresponding parameters to get a full EEC (at the proper temperature and OP). So simu.elec.eec is the “initial state” of the EEC, Out.elec.ecc is the complete state for the corresponding temperature / OP. When a parameter is enforced, there is no computation to adapt the temperature and OP on this parameter, we assume that the user has provided the correct one.

If new EEC or variation of the existing ones needs to be added, other objects with the proper properties/methods can be added (including by using polymorphism).

Regarding the use of LUT in Electrical module it would be as follow:

  • the property would be moved from simu.elec.eec.LUT_enforced to simu.elec.LUT_enforced
  • LUT will contains an EEC at a given temperature and OP (known and stored in the LUT) and some tables (Phid, Phiq = fct(Id, Iq) for PMSM, Lm=fct(Im) for SCIM)
  • LUT would have method named “get_EEC(T=X, OP=Y)” that would adapt the parameter of its EEC to match T=X, OP=Y (if a parameter is missing from the LUT EEC, it would be computed directly). This method would encapsulate a call to eec methods with the same purpose adapted to the eec actual properties.
  • Electrical.run would first check for Elut to adapt a EEC, if not provided eec.comp_parameters would be called. In both cases a output.elec.eec is generated and output.elec.eec.solve can be called.
  • These modifications should simplify the comp_parameter methods

With this new standard for EEC, the LUT organization as a daughter of XOutput can be defined as follow:

  • LUT.simu as for all XOutput it should be the “simulation that generated the XOutput”
  • We differentiate two kinds of LUT (same object different content):
    • the MLUT elec=None, mag != None var_simu=VarLoadCurrent
    • the ELUT elec != None, mag != None and var_simu=VarLoadVoltage.
  • There are two daughters of LUT, LUTdq and LUTslip that store some tables (Phid, Phiq = fct(Id, Iq) for PMSM, Lm=fct(Im) for SCIM) and provide the dedicated methods to adapt the EEC
  • the machine is stored in LUT.simu.machine
  • the EEC is stored both in ELUT.simu.elec.eec and ELUT.elec.eec
  • The magnetic model needed to compute the flux, torque and inductances can be stored in LUT.simu.mag and the resulting data stored in LUT.output_list.mag
  • The usual DataKeeper (N0, Id, Iq…) can be added to enable some plot
  • All the plot are natively available since the LUT is a XOutput object

A method ELUT.get_electrical would enable to retrieve Data object of the eec parameters as a function of (N0, frequency) => Plot

@SebGue what do you think about this organization proposal? We are currently working on Manatee SCIM models and we would like to include the “LUT as a daughter of XOutput” to handle the retro-compatibility with our old format. We plan to work on that on next week, do you think that you would have some time to review this issue so we can agree on the LUT format and usage? If we both agree we can introduce these modifications directly within pyleecan otherwise we will work in Manatee and handle the merge latter one. For PMSM this rework won't have a major impact, it's only code refactoring around EEC. One part of the eec will be generated by the MLUT (values for Phid/Phiq/Phi_mag/Ld/Lq) and the other part by the eec itself (stator resistance accounting for temperature and skin effect).

As always we are open to any suggestion to improve/correct this proposal to make sure that it will be compatible with your usage as well.

Best regards,
Pierre

Hello @BonneelP,
I will take the time and review this issue and come back with a lot of questions soon ;-)

Thanks :)

Hello Pierre,

at first I think we got somehow different use cases for EEC and LUT. I guess you are more likely to analyse single OPs in terms of 'harmonic behavior' (for NVH, ...). While I mostly want to calculate general machine performance, i.e. datasheets with current, voltage and efficiency maps and so on. Therefore, there may be some inherent issues when trying to merge our ideas.
Nevertheless, I'm not quite sure about some aspects, e.g. the copying of the EEC you mention in section 3 of your proposal. Wouldn't this increase the amoung of data significantly? (OT: Have you tried H5 compression results when there is the same object is nested in another object multiple times?)
But the copying aspect may not be a problem if I use an independent 'Performance Charaterization' class for my purpose.

The maybe most important aspect I don't understand yet is the section regarding LUT. There you propose ...

LUT will contains an EEC at a given temperature and OP (known and stored in the LUT) and some tables (Phid, Phiq = fct(Id, Iq) for PMSM, Lm=fct(Im) for SCIM)
LUT would have method ...

Why should the EEC be in LUT? For now in my implementation the LUT is in the EEC. Where do you see the benefit of you proposal? Does your EEC have fixed parameter depending on only one OP?
In that context we should maybe also clarify what EEC means to both of us.

On the other hand, I really like your idea of dynamically extending the LUT if some parameter is missing.

For now, I think this is enough aspect to discuss. I really seeing forward for you answer.

Best regards, Sebastian

Hello Sebastian,
Thank you for your feedback :)
Regarding the usage of the EEC, our usual simulation will include a VarLoadVoltage to iterate on several operating point as we do for the VarLoadCurrent. We keep the assumption of Simu1 that each OP is independent and that each model is sequential (which for some usage won't be right). This is why we are more focusing on a "single OP" (and float parameters) approach for the EEC, but indeed we already have some scripts where we use array of Id/Iq/EEC parameters (Tests\Validation\Electrical\test_EEC_ELUT_PMSM.py) but we can provide dedicated methods to handle them.

Regarding the copying of the EEC, for now we have a eec.parameters that is duplicate to initialized the output dict of comp_parameters. If eec.parameters is set with all the parameters then the copy mechanism is already in the code. We want to remove this dictionary because it can be source of error and confusion for the user (which parameter of which type...). Having the parameters within the csv should be more clear. But then the output of comp_parameters should also be an EEC object to have all its output (the same as the enforced one) in a csv as well. We think about the copy to avoid updating the input EEC (which could create some error if running the simulation twice).
With your remark, I realized that maybe rather than introducing all the parameters property into EEC_X we should create a new object EEC_X_Param that will be included in the EEC_X object (to enforce or not) and in the OutElec (the result/updated values). This new object would only contains the parameters of the EEC (R1, L1, ...) as float so saving them shouldn't be too costly. Then we won't copy all the other property of the EEC object (like all the model related ones). Then in each OP of the VarLoadVoltage we need to adapt the parameter to the frequency/temperature and so these parameters can be different in each output_list then it would make sense to save them all for plotting. But as the next step after comp_parameter is eec.solve maybe it would be more convenient to return an eec object with completed parameters.

We haven't investigated H5 since the "type_handle_ndarray" modification but we know that we need to further investigate the save/load procedure to improve their performances.

For now the LUT contains the parameters of the EEC to be enforced/updated into the parameter dict. If EEC_X (or EEC_X_Param) contains the same properties then it would be more efficient to remove the properties of LUT and to use directly the EEC ones. Otherwise when introducing new EEC or extending the current ones with new parameters it would require to change the LUT csv. With a EEC object within the LUT, we can benefit from the polymorphism of the EEC class and we have the models to compute the missing parameters if needed.

Does your EEC have fixed parameter depending on only one OP?

For me the EEC_X_Param/EEC_X would be the parameter of an EEC at a given OP and a given temperature (stored within the EEC_X_Param). Then LUT would contain a "reference" EEC_X_Param that would be updated for each OP of the VarLoadVoltage.

Thank you again for your questions, they are always helpful :) I hope that our aim is more clear now and we can carry on the discussion if you have other questions.
Best regards,
Pierre

Hello Pierre,

I think I'm slowly getting used to your point of view. Further I think I can adapt to it. But first let me recap your proposal, skipping some details.
One got some LUT (a magnetic look up table with flux linkage and some losses, e.g. iron losses) and derive a single OP (i.e. fixed parameter) EEC by calling LUT.get_EEC(OP, ...). The EEC then will be used to calculate some machine behaviour, e.g. voltages, torque, ...
That seems resonable on the given assumptions but also has some drawbacks. I.e. with the 'float' parameters of EEC you can at most only simulate the small signal behavoir of the machine in the OP. You won't be able to e.g. simulate a ramp up or some changes in current. For (e.g. input voltage) harmonics calculations there had to be some frequency dependence in the parameters to get valid results.

But thats okay for me (at least at the moment). What I need would be some OPs with mechanical reference values and the possibility to imply some control strategy (mostly MTPA) to get the EECs.

What do you think, how can we go ahead with this issue?

BR S

One got some LUT (a magnetic look up table with flux linkage and some losses, e.g. iron losses) and derive a single OP (i.e. fixed parameter) EEC by calling LUT.get_EEC(OP, ...). The EEC then will be used to calculate some machine behaviour, e.g. voltages, torque, ...

Yes the user usually will provide all the EEC parameters at a given temperature/OP and then we will adapt that within the simulation.

ou won't be able to e.g. simulate a ramp up or some changes in current

That is also an assumption in the structure of the Simu1 and Magnetics models (which is fixed speed only and use time periodicity to speed-up). The "Variable speed" in pyleecan Simu1 is a superposition of fixed speed simulations. We plan to create dedicated models and simulations objects to handle transient simulation in the future for instance.
Regarding the harmonics in the current and voltage (cf PWM) we handle them by superposition but still within the previous assumptions.

What I need would be some OPs with mechanical reference values and the possibility to imply some control strategy (mostly MTPA) to get the EECs.

This is an interesting workflow that we need to include in pyleecan somehow. Do you plan to carry on the computation into the Magnetic modules or can it be a "Electrical only" simulation ? We had several thought on how we could extend the Electrical module outside of Simu1. We could for instance have a Simu2 objects that would handle loops between an electrical/heat transfer models and have a dedicated Input object with a N0(t) axes in it. It will be really interesting to find ways of sharing objects and methods between several kinds of simulations with different structure/assumptions.

For the next steps we have the following strategy in mind:
First we update pyleecan models to match our latest work to make sure that the models are validated: #504
Then we update all 3 EEC to have the parameters as properties and the dedicated comp_X/adapt_X/get_X methods (basically we reorganized comp_parameters). (A dedicated PR will be done to close/validate this step)
Finally we reorganise the LUT object as a daughter of XOutput and to use EEC objects.

Best regards,
Pierre

Hello @BonneelP ,

so here are some thoughts, concerns and questions on some details of this issue and #506.
First I just realized that EEC_SCIM uses lookup tables while EEC_PMSM is float parameters only. Why's that?

Now with the actual implemention, I again question the benefits of your proposal (at least for PMSM). Maybe you could give me some more detail how you use Electrical/EEC and what your results are.

  1. The inductances used are absolute inductances, i.e. (Psi_d - Psi_mag) / I_d. For calculation of e.g. PWM current harmonics (i.e. small deviations of current around the OP), the use of differential inductances would be beneficial. At least if there is some saturation of the machine.
  2. The LUT EEC setup (EEC.update_from_ref) will only work if the current is known a priori. Otherwise the parameters will be off. Especially if Electrical is voltage driven. Do you see any chance to implement the above workflow with a torque reference OP? Maybe the EEC itself (EEC.solve in a loop or an optimization) could find the respective current here?! But then we also need some control strategy to apply here too.

Further EEC_PMSM should also include (iron) losses as EEC_SCIM do.

And last but not least, the LUT should adapt the EECs to 'similar machines', i.e. machines that fulfill certain critiria. E.g. if one modify the length or the number of turns of a maschine, it would be a waste of computational time if the LUT was recomputed. Rather the LUT should scale results to the new machine by length, winding factor, etc.

So, I think this is enough input for now. :-)

Best regards, Sebastian

Hello @SebGue,

The EEC_SCIM uses a look up table for the magnetizing inductance that the user fills as a prerequisite. It could also be calculated with Pyleecan of course.

In EEC_PMSM.solve_PWM(), PWM current harmonics are calculated using absolute inductances as a first approximation. No problem to add new methods to calculate differential inductances from the LUTdq and then add a new solve_PWM() to the EEC_PMSM object.

For voltage driven and torque driven workflows, I think that we just have to include the methods that you developed on your side. The EEC_PMSM could call different solve() method depending on Input type (InputCurrent / InputVoltage / InputTorque or InputPower that we don't have for now) and a control strategy (e.g. MTPA or other strategy), and find a solution as long as the input LUT is relevant.

Finally, I don't see any problem to extend existing EEC_PMSM object to iron losses and adapt it to similar machines, we just need to include your methods that already account for that.

Best regards,
Emile

Hello @EmileDvs,

the question about EEC_SCIM mag. table was, why you use a table there but don't want to use it in EEC_PMSM.

Is EEC_PMSM.solve_PWM() somehow limited to PWM. Looking though the code it doesn't seems to be. So my proposal would be to rename it more general 'solve_harmonics'.
Further I would vote for the use of differential inductances (including cross coupling) right now, since EEC also has OP's fluxlinkage as a parameter too. With current driven EEC_solve() you use fluxlinkage anyway. For voltage driven mode if the current is off the inital guess by some small amoung, differential inductance results should be better.

Since differential inductance is not always known (e.g. if there is no LUT), we could allow some sparse input of parameters (eigther fluxlinkage or inductance) and assume/set differential inductance equal to absolute inductance.

Regarding the workflows, I think you got to decide on how and where we integrate that in the organization of the objects and the actual implementation. (One way could be the use of EEC methods itself as in 2. of my previous answer.)
For the actual algorithym and control strategy, we should discuss that seperatly, since I'm not too much satisfied with my implementation. (Robustness seems to be an issue.)

So if you got further things to do for me, other than discussion, just tell me.
I'm really interested in your response.

Best regards, Sebastian

Hello Sebastian,

Regarding the MTPA we thought about the following solution (it would be available with the LUT as a daughter of XOutput):

  • First we compute a LUTdq on a Id/Iq grid with a VarLoadCurrent and a MagFEMM to get the Phi_wind (we may introduce a "XOutput.to_LUT" method)
  • Then we add a method to LUTdq to compute the MTPA from the Id/Iq/Phi_wind table.
  • The Electrical / EEC_PMSM objects could then be adapted to call this method within an InputVoltage/InputTorque (we need to clarify the workflow for that)

We could also call a the MTPA method of the LUT to generate a VarLoadCurrent to create a new simulation.

Best regards,
Pierre

Hello Pierre,

I think, getting MTPA curves from LUT is a great thing.
I just wonder if/how we can adapt the resulting workflow to other strategies as well, i.e. MTPV (min. voltage) or some minimal loss (or even temperature) strategy. For now maybe some 'type_control_stratey' property is sufficient.

The Electrical / EEC_PMSM objects could then be adapted to call this method within an InputVoltage/InputTorque (we need to clarify the workflow for that)

Still this point is the most interessting for me (see above).

BR S

the question about EEC_SCIM mag. table was, why you use a table there but don't want to use it in EEC_PMSM.

We need the tables to be copied from the LUT object to the EEC_SCIM object because they are used inside the solve() method to solve the circuit accounting for non-linear magnetizing inductance. It is also something we can do for EEC_PMSM if some tables are required in the solve() method.

Is EEC_PMSM.solve_PWM() somehow limited to PWM. Looking though the code it doesn't seems to be. So my proposal would be to rename it more general 'solve_harmonics'.

It is something I wanted to do first but then I realized that inputs to calculate current harmonics due to PWM voltage harmonics or due to BEMF/saturation voltage harmonics are not the same, and also the EEC differs somehow since we have to account for harmonics in the flux linkage whereas it is not required for PWM calculation. That's why I created a specific method to only deal with PWM harmonics, and I was more inclined to add another method "solve_BEMF" if I had to include them in the current calculation as well.

Concerning differential inductances I've never used them so. I think it's would be very interesting to have another method to calculate current harmonics based on their knowledge, while keeping the model with absolute inductances.

Once we'll have reworked the LUT as child of XOutput, we'll have the possibility to call several methods to get (Id,Iq) for a given control strategy using the LUT methods.

Best regards,
Emile

Done in #507