pyleecan
pyleecan copied to clipboard
Calculate Maximum torque per ampere for PMSM using dq look up table
Hello,
An algorithm to calculate Maximum Torque Per Ampere for PMSM is implemented in PR #464. This enables to determine the torque/speed control law used that optimizes machine performances in variable speed/in traction application .
The algorithm is in branch EEC of EOMYS-public, in python file Tests\Validation\Electrical\test_EEC_ELUT_PMSM.py.
The algorithma relies on a pre-calculated look-up table for a rectangular grid of Id/Iq. The look up table LUTdq is calculated in test_EEC_ELUT_PMSM_calc() and saved as .h5 using postprocessing PostLUT class.
Then the LUTdq is loaded in the MTPA test function test_EEC_ELUT_PMSM_MTPA(). The algorithms inputs are:
- the aforementioned LUTdq to be able to calculate Phid/Phiq and therefore torque function of Id/Iq
- the maximum phase voltage U_max and current I_max
- the speed array (i.e. X speeds uniformly distributed between minimum and maximum speeds in rpm)
- the number of current load steps to consider, e.g. between I_load_min=0A (open circuit condition) and I_load_max=I_max. I_load_min can also be -I_max to include braking in MTPA.
The algorithm interpolates the Phid/Phiq distribution on a finner grid, calculate the voltage and torque distribution function of Id/Iq and find the maximum torque that fullfill U_max and I_max constraints for each speed and current load level.
The algorithm can be really improved in terms of accuracy as the MTPA solution depends on the refinment of the grid after reinterpolation. The resulting solution belongs to the predefined grid, so it is obvious that is not really the optimal solution (that could be found using an optimization algorithm around the solution I guess). By increasing the grid fineness, it is possible to smooth the resulting torque speed curve however it is still stepwise in the end.
Please let me know if you have any remarks. @SebGue don't hesitate to tell me if you wish to contribute on this part, we already talked about the fact that you implemented some optimization algorithms to determine voltage/current control law on your side so it can be quite relevant here to improve the algorithm quality.
Best regards, Emile
Hello @EmileDvs
the following method is the main part of my MTPA calculation. With some tricks, I guess it can also be used for other control strategies. Most of the time it will produce reasonable results but it is not 100% guarantied that it will always find a result. I had cases where it failed so it may need some fallback. I also haven't fully understood why it failed. I think it is linked to the LUT interpolation. I just recalculated the LUT with other settings in such cases.
def _minimize_SLSQP(self, Idq0, speed, torque, TRQ_ERR, param):
# --- set bounds ---
# bounds due to parameter space
Id_bnds = (param["Idmin"], param["Idmax"])
Iq_bnds = (param["Iqmin"], param["Iqmax"])
bnds = (Id_bnds, Iq_bnds)
# drive bounds
Imax = param["Imax"]
Umax = param["Umax"]
# start value
if Idq0 is None or None in Idq0:
Idq0 = [-0.1, 1]
# constraints
EXP = 1
torque_con = lambda x: TRQ_ERR ** EXP - (
comp_trq_diff(self, *x, speed, param, torque) ** EXP
)
cons = []
cons.append({"type": "ineq", "fun": torque_con})
if Imax is not None:
max_current_cons = lambda x: Imax - comp_current(self, *x, speed, param)[0]
cons.append({"type": "ineq", "fun": max_current_cons})
if Umax is not None:
max_voltage_con = lambda x: Umax - comp_voltage(self, *x, speed, param)[0]
cons.append({"type": "ineq", "fun": max_voltage_con})
cons = tuple(cons)
# objective: minimize the current
objectiv = lambda x: comp_current(self, *x, speed, param)[0]
res = minimize(objectiv, Idq0, method="SLSQP", constraints=cons, bounds=bnds)
return res
There are some other 'undefined' functions used in the code that all utilize the eec. But I think it is clear what they do by their name.
Let me know, what you think.
BR S
Hello @SebGue,
Thanks for the script, it is quite clear indeed! I couldn't manage to use the minimize function of scipy.optimize.minimize, I'll have a try with this.
Which function do you use to interpolate LUT ? I have implemented two possibilities in case the LUT is a regular grid in dq or a scatter grid (cf method LUTdq.interp_Phi_dqh):
- scipy.interpolate.RectangularGridInterpolator
- scipy.interpolate.LinearNDInterpolator
RectangularGridInterpolator is much faster and more accurate than LinearNDInterpolator which retriangulate scatter data.
Best regards, Emile
Hello @EmileDvs
I thought I have RectangularGridInterpolator but looking at my code I have these two
scipy.interpolate.interp2d(x, y, z, kind="cubic")but commented outscipy.interpolate.CloughTocher2DInterpolator(np.array([x, y]).T, z)
It's been some time since, so I can't exactly remember but I think I used the second on over 'RectGridInterp' due visually better results also for the derived inductances for low grid sample count. But it is definitely worth investigating. Maybe we could also establish some quality metric on actual LUT's with the possibility to select interpolation and to add further calculation data at points of highest uncertainity. Metrics that come to my mind right now is the behavior of inductance in general (e.g. monotonic behaviour) or equality of cross coupling inductances specifically. Further a model based approach instead of interpolation would be great here. I already started some discussion with @RaphaelPile on that, but had no time to get any further.
BTW have you checked inductances for your LinearNDInterp? The results should be really poor.
Best regards, Sebastian
Hello @SebGue,
It's been a while since the last time we discussed, I hope you're fine.
For your information I did a new proposition of MTPA workflow in Tests\Validation\Electrical\test_ElecLUTdq_solve_MTPA.py. I created a new Electrical child class called "ElecLUTdq" that can calculate or take as input a LUTdq to perform MTPA. The MTPA calculation is performed in pyleecan\Methods\Simulation\ElecLUTdq\solve_MTPA.py which integrates the old function "comp_MTPA" and directly shows the EEC calculation for all Id and Iq. There is a "while" loop to iterate on (Id, Iq) to get closer to the optimal values.
Best regards, Emile
I also tried to implement the minimization algorithm you shared with the "minimize" function. However I faced some issues with the minimize function not respecting the constraints, meaning I could find a solution that minimize the objective while complying all constraints although it was clearly achievable. I looked into the "minimize" documentation and I had the feeling that the constraint had to be linear with respect to the variables Id / Iq, which is clearly not the case.
Emile
Hello @EmileDvs,
thank you I'm fine but I'm busy on some other topics. So I didn't had time to try the latest changes. Regarding "minimize", I don't know if constraints have to be linear but I think thats not necessary. Of course I also had some issues getting resonable results from time to time. Using different initial values helped some time. Do you have some minimal example of your issue?
On the other hand, if you got some another idea on how to calculate constrained MTPA (or other control strategies), I don't mind since a stable algorythm would be really great.
Best regards, Sebastian