効率マップ解析スタディの結果を使用して、指定された走行モードにおける電気自動車などの効率を算出します。
import csv
import os
import math
import sys
import numpy as np
def main():
confirm_title_en = "Warning"
confirm_title_ja = "ワーニング"
confirm_msg_en = "Running this script will delete all existing operating points. Do you wish to proceed?"
confirm_msg_ja = "スクリプトの実行によって既存の動作点は削除されます。実行を続けますか?"
check = show_confirm_message(confirm_title_en, confirm_title_ja, confirm_msg_en, confirm_msg_ja)
if check == 0:
cancel_message_en = "Process is canceled."
cancel_message_ja = "処理が中断されました。"
show_cancel_exit_message(cancel_message_en, cancel_message_ja)
return
app = designer.GetApplication()
study = app.GetCurrentStudy()
dialog = app.CreateDialogBox()
if study.NumEfficiencyMapDefinitions() > 1:
confirm_msg_en = "This script will use the first efficiency map plot for calculation."
confirm_msg_ja = "このスクリプトは、スタディの中で1番目の効率マップを計算に使用します。"
show_message(confirm_title_en, confirm_title_ja, confirm_msg_en, confirm_msg_ja)
title_ja = "走行モードから効率を計算"
title_en = "Calculate Efficiency from Drive Mode"
csv_file_en = "Drive Mode CSV File"
csv_file_ja = "走行モードCSVファイル"
tire_diameter_ja = "タイヤ直径, mm"
tire_diameter_en = "Tire Diameter, mm"
gear_ratio_ja = "最終減速比"
gear_ratio_en = "Final Reduction Ratio"
rolling_resistance_ja = "転がり抵抗係数"
rolling_resistance_en = "Rolling Resistance Coefficient"
air_density_ja = "空気密度, kg/m^3"
air_density_en = "Air Density, kg/m^3"
drag_coefficient_ja = "Cd値"
drag_coefficient_en = "Drag Coefficient"
cross_sectional_ja = "前面投影面積, m^2"
cross_sectional_en = "Cross Sectional Area of Vehicle, m^2"
total_weight_ja="総重量, kg"
total_weight_en = "Total Weight, kg"
gravity_ja = "重力加速度, m/s^2"
gravity_en = "Gravitational Acceleration, m/s^2"
loss_factor_ja = "駆動系損失係数"
loss_factor_en = "Drive System Loss Factor"
cancel_message_en = "Process is canceled."
cancel_message_ja = "処理が中断されました。"
map_plot_error_en = "Current Study has no map."
map_plot_error_ja = "選択されているスタディにマップが存在しません。"
study_select_error_en = "Current Study is not Efficiency Map Study."
study_select_error_ja = "選択されているスタディは効率マップ解析スタディではありません。"
currentStudyType = study.GetScriptTypeName()
if not currentStudyType.endswith("Response"):
show_error_exit_message(study_select_error_en, study_select_error_ja)
return
if study.NumEfficiencyMapDefinitions() == 0:
show_error_exit_message(map_plot_error_en, map_plot_error_ja)
return
plot = study.GetEfficiencyMapPlot(0)
if not plot.IsValid():
show_error_exit_message(map_plot_error_en, map_plot_error_ja)
return
plot_def = study.GetEfficiencyMapDefinition(0)
case = study.GetCurrentCase()
MaxI = plot_def.MaxVoltage()
MaxV = plot_def.MaxCurrent()
dialog.SetTranslation(title_en, title_ja)
dialog.SetTranslation(csv_file_en, csv_file_ja)
dialog.SetTranslation(tire_diameter_en, tire_diameter_ja)
dialog.SetTranslation(gear_ratio_en, gear_ratio_ja)
dialog.SetTranslation(rolling_resistance_en, rolling_resistance_ja)
dialog.SetTranslation(air_density_en, air_density_ja)
dialog.SetTranslation(drag_coefficient_en, drag_coefficient_ja)
dialog.SetTranslation(cross_sectional_en, cross_sectional_ja)
dialog.SetTranslation(total_weight_en, total_weight_ja)
dialog.SetTranslation(gravity_en, gravity_ja)
dialog.SetTranslation(loss_factor_en, loss_factor_ja)
dialog.SetTitle(title_en)
dialog.SetModal(False)
dialog.AddOpenFilename("File_drive_cycle", csv_file_en, "", "")
dialog.AddReal("TireD", tire_diameter_en, 742)
dialog.AddReal("GearRatio", gear_ratio_en, 8)
dialog.AddReal("Dair", air_density_en, 1.205)
dialog.AddReal("Cd", drag_coefficient_en, 0.3)
dialog.AddReal("Area", cross_sectional_en, 2.88)
dialog.AddReal("Rrote", rolling_resistance_en, 0.008)
dialog.AddReal("Mass", total_weight_en, 1760)
dialog.AddReal("Grav", gravity_en, 9.81)
ret = dialog.Show()
if ret==0:
show_cancel_exit_message(cancel_message_en, cancel_message_ja)
return
File_drive_cycle = dialog.GetValue("File_drive_cycle").decode("utf-8")
if len(File_drive_cycle) == 0:
message_en = "Please specify CSV file name."
message_ja = "CSVファイル名を指定してください."
show_error_exit_message(message_en, message_ja)
return
if not os.path.isfile(File_drive_cycle):
message_en = "The specified file does not exist."
message_ja = "指定されたファイルが存在しません。"
show_error_exit_message(message_en, message_ja)
return
#Parameter for the vehicle model
TireD = dialog.GetValue("TireD")
GearRatio = dialog.GetValue("GearRatio")
Dair = dialog.GetValue("Dair")
Cd = dialog.GetValue("Cd")
Area = dialog.GetValue("Area")
Rrote = dialog.GetValue("Rrote")
Mass = dialog.GetValue("Mass")
Grav = dialog.GetValue("Grav")
if TireD <= 0:
message_en = "The value for Tire Diameter is invalid."
message_ja = "タイヤ直径の値が無効です。"
show_error_exit_message(message_en, message_ja)
return
if GearRatio <= 0:
message_en = "The value for Gear Ratio is invalid."
message_ja = "最終減衰ギアの値が無効です。"
show_error_exit_message(message_en, message_ja)
return
if Rrote <= 0:
message_en = "The value for Rolling Resistance is invalid."
message_ja = "転がり抵抗の値が無効です。"
show_error_exit_message(message_en, message_ja)
return
if Dair <= 0:
message_en = "The value for Air Density is invalid."
message_ja = "空気密度の値が無効です。"
show_error_exit_message(message_en, message_ja)
return
if Cd <= 0:
message_en = "The value for Drag Coefficient is invalid."
message_ja = "Cd値が無効です。"
show_error_exit_message(message_en, message_ja)
return
if Area <= 0:
message_en = "The value for Cross Sectional Area of Vehicle is invalid."
message_ja = "前面投影面積の値が無効です。"
show_error_exit_message(message_en, message_ja)
return
if Mass <= 0:
message_en = "The value for Total Weight is invalid."
message_ja = "総重量の値が無効です。"
show_error_exit_message(message_en, message_ja)
return
if Grav <= 0:
message_en = "The value for Gravity is invalid."
message_ja = "重力加速度の値が無効です。"
show_error_exit_message(message_en, message_ja)
return
#Read drive cycle
try:
Drive_cycle = np.loadtxt(File_drive_cycle, delimiter=",", skiprows=1, ndmin=2)
except:
message_en = "Error opening CSV file."
message_ja = "CSVファイルの読み込みにエラーが発生しました。"
show_error_exit_message(message_en, message_ja)
return
Car_speed = Drive_cycle[:,1]
Time = Drive_cycle[:,0]
Length = Time.size
if Length < 2:
message_en = "There is insufficient data in the drive mode CSV file.\nAt least 2 data points must be included."
message_ja = "走行モードCSVファイルに含まれるデータが不足しています。\n2点以上のデータが含まれている必要があります。"
show_error_exit_message(message_en, message_ja)
return
for a, b in zip(Time[:-1], Time[1:]):
if a > b:
message_en = "The time data in the drive mode CSV file is not in ascending order.\nPlease sort the data by time in ascending order."
message_ja = "走行モードCSVファイルの速度点列の時刻が昇順ではありません。\n時刻を昇順に並べ替えてください。"
show_error_exit_message(message_en, message_ja)
return
#_______________________________________________________
#Calculate the Torque and speed from the Drive cycle
Speed = Car_speed*1/(TireD*math.pi*3.6/1000)*60*GearRatio
T1 = (0.5*Dair*Cd*Area*(np.square(Car_speed)/(3.6)**2)+Rrote*Mass*Grav)*TireD/2000/GearRatio
DSpeed = np.divide(Car_speed-np.concatenate((Car_speed[0], Car_speed[0:Length-1]), axis=None), Time-np.concatenate((-Time[1], Time[0:Length-1]), axis=None))
T2 = (DSpeed*Mass*1/3.6)*TireD/2/1000/GearRatio
Torque = T1 + T2
Duty_cycle = np.transpose(np.stack([Speed, Torque])) #resulting duty cycle
#_______________________________________________________
#Get max speed and max torque
max_speed = max(Speed)
max_torque = max(Torque)
is_outside_map = False
Eff = 0
Energy = 0
for i in range(Length):
if plot.IsValidPoint(Speed[i], Torque[i]):
res = plot.GetPointResult('efficiency', Speed[i], Torque[i])
Eff = Eff+res
if i==0:
Energy = 0
elif res==0:
dt = Time[i]-Time[i-1]
Energy=Energy+dt*3*MaxI*MaxV
else:
dt = Time[i]-Time[i-1]
if Torque[i] >= 0:
Energy = Energy+dt*math.pi*100*Speed[i]*Torque[i]/res/30
else:
Energy = Energy+dt*math.pi*Speed[i]*Torque[i]*res/100/30
else:
Eff = 0
Energy = 3*MaxI*MaxV*Time[Length-1]
is_outside_map = True
break
if is_outside_map:
outside_map_en = "The results are outside of the map."
outside_map_ja = "ポイントが効率マップに存在しません。"
show_error_exit_message(outside_map_en, outside_map_ja)
return
plot.DeleteAllPoints()
plot.AddPoints(list(zip(Speed, Torque)))
Eff=Eff/Length
Energy=Energy/1000000
# Set response variable
app.GetCurrentStudy().SetUserResponseVariable(u"AveEff", case, Eff)
app.GetCurrentStudy().SetUserResponseVariable(u"Energy", app.GetCurrentStudy().GetCurrentCase(), float(Energy))
app.GetCurrentStudy().SetUserResponseVariable(u"MaxSpeed", case, float(max_speed))
app.GetCurrentStudy().SetUserResponseVariable(u"MaxTorque", case, float(max_torque))
results_en = "Average Efficiency, % = " + str(round(Eff, 2)) + "\nTotal Energy, MJ = " + str(round(Energy, 2)) + "\nMaximum Speed of Drive Cycle, r/min = " + str(round(max_speed, 2)) + "\nMaximum Torque of Drive Cycle, Nm = " + str(round(max_torque, 2)) + "\n\nTo check the operating points, please close and re-open the efficiency map window."
results_ja = "平均効率, % = " + str(round(Eff, 2)) + "\n消費された全エネルギ, MJ = " + str(round(Energy, 2)) + "\n最大速度, r/min = " + str(round(max_speed, 2)) + "\n最大トルク, Nm = " + str(round(max_torque, 2)) + "\n\n動作点を確認するためには、効率マップウィンドウを一度閉じて、再度開いてください。"
result_title_en = "Results"
result_title_ja = "結果"
show_message(result_title_en, result_title_ja, results_en, results_ja)
def show_error_exit_message(message_en, message_ja):
title_en = "Error"
title_ja = "エラー"
show_message(title_en, title_ja, message_en, message_ja)
def show_cancel_exit_message(message_en, message_ja):
title_en = "Cancel"
title_ja = "キャンセル"
show_message(title_en, title_ja, message_en, message_ja)
def show_message(title_en, title_ja, message_en, message_ja):
app = designer.GetApplication()
msgdlg = app.CreateDialogBox()
msgdlg.SetTranslation(title_en, title_ja)
msgdlg.SetTranslation(message_en, message_ja)
msgdlg.SetCancelButtonVisible(False)
msgdlg.SetTitle(title_en)
msgdlg.AddLabel(message_en)
msgdlg.Show()
def show_confirm_message(title_en, title_ja, message_en, message_ja):
app = designer.GetApplication()
msgdlg = app.CreateDialogBox()
msgdlg.SetTranslation(title_en, title_ja)
msgdlg.SetTranslation(message_en, message_ja)
msgdlg.SetTitle(title_en)
msgdlg.AddLabel(message_en)
return msgdlg.Show()
main()


