[D0014] 走行モードから効率を計算

 

効率マップ解析スタディの結果を使用して、指定された走行モードにおける電気自動車などの効率を算出します。

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()

Download Python source code

ファイルご利用の注意点

JMAGスクリプトライブラリをご利用されるに際し、以下の利用規約をよくお読みいただき、ご同意の上ご利用下さるようお願い申し上げます。