モータNVH用にトルク、電磁力をCSVファイル出力する。
import locale
import os
import designer
import subprocess
import csv
import time
CSV_VERSION = "1.0.0"
OUTPUT_FILE_PATH = "outputFilePath"
SET_PREFIX = "prefix"
TORQUE_COND_TITLE = "condition_title"
#for surface force
INVERSE_RESULT = "inverse_result"
TEETH_CENTER_SPECIFYING_TYPE = "teeth_center_specifying_type"
TEETH_CENTER_DIR_X = "teeth_center_dir_x"
TEETH_CENTER_DIR_Y = "teeth_center_dir_y"
TEETH_CENTER_DIR_Z = "teeth_center_dir_z"
TEETH_CENTER_POS_X = "teeth_center_pos_x"
TEETH_CENTER_POS_Y = "teeth_center_pos_y"
TEETH_CENTER_POS_Z = "teeth_center_pos_z"
NUM_POLES = "numPoles"
COORD_TYPE = "coord_type"
USE_COPY_CYCLE = "use_copy_cycle"
DIVIDE_TEETH_FORCE = "divide_teeth_force"
AXIAL_COORDINATES = "axial_coordnates"
OUTPUT_FORMAT_TYPE = "output_format_type"
OUTPUT_CASE_TYPE = "output_case_type"
SPECIFIED_CASES = "specified_cases"
EPSILON = 0.000001
OUTPUT_DIMENSION = 3
app = designer.GetApplication()
def main():
app.SetShowProgressDialog(False)
if (check_model(app) == False):
return
parameters = get_parameters_from_dialog(app)
if (check_dialog_parameters(app, parameters) == False):
return
output_csv(app, parameters)
def check_model(app):
model = app.GetCurrentModel()
study = app.GetCurrentStudy()
if (model.IsValid() == False):
message = "No model."
message_jp = "モデルがありません。"
show_error_message(message, message_jp)
return False
setList = model.GetSetList()
if (setList.NumSet()<1):
message = "There is no set."
message_jp = "セットがありません。"
show_error_message(message, message_jp)
return False
if (study.IsValid() == False):
message = "No study."
message_jp = "スタディがありません。"
show_error_message(message, message_jp)
return False
motionList = get_conditions(study, "RotationMotion")
if (len(motionList)<1):
message = "Current study has no rotation motion condition."
message_jp = "現スタディは回転運動条件がありません。"
show_error_message(message, message_jp)
return False
surf_forceList = get_conditions(study, "Torque_Surface")
if (len(surf_forceList)<1):
message = "Current study has no force condition."
message_jp = "現スタディは表面力条件がありません。"
show_error_message(message, message_jp)
return False
if (study.AnyCaseHasResult() == False):
message = "Current study has no result."
message_jp = "現スタディは結果がありません。"
show_error_message(message, message_jp)
return False
if (has_zero_speed(app)==True):
message = "There is the case that rotation speed is zero. Please review setting."
message_jp = "回転速度がゼロのケースがあります。設定を見直してください。"
show_error_message(message, message_jp)
return False
return True
def show_error_message(message, message_jp):
msgdlg = app.CreateDialogBox()
title = "Error"
title_jp = "エラー"
msgdlg.SetTranslation(title, title_jp)
msgdlg.SetTranslation(message, message_jp)
msgdlg.SetCancelButtonVisible(False)
msgdlg.SetTitle(title)
msgdlg.AddLabel(message)
msgdlg.Show()
def show_warning_message(message, message_jp):
msgdlg = app.CreateDialogBox()
title = "Warning"
title_jp = "警告"
msgdlg.SetTranslation(title, title_jp)
msgdlg.SetTranslation(message, message_jp)
msgdlg.SetCancelButtonVisible(False)
msgdlg.SetTitle(title)
msgdlg.AddLabel(message)
msgdlg.Show()
def get_parameters_from_dialog(app):
dialog = app.CreateDialogBox()
setup_param_input_dialog(app, dialog)
dialog.Show()
return dialog
def setup_param_input_dialog(app, dialog):
model = app.GetCurrentModel()
study = app.GetCurrentStudy()
modelDimension = model.GetDimension()
is2D = (modelDimension == 2)
isCutPlane = study.IsCutPlaneStudy()
dialogTitle = "JMAG-Designer: NVH Force Export Setting"
dialogTitle_jp = "JMAG-Designer: NVH電磁力出力設定"
dialog.SetTranslation(dialogTitle, dialogTitle_jp)
label_1 = "Output File:"
label_1_jp = "出力ファイル:"
dialog.SetTranslation(label_1, label_1_jp)
label_2 = "Set Prefix:"
label_2_jp = "セットの先頭文字:"
dialog.SetTranslation(label_2, label_2_jp)
label_3 = "Torque Condition:"
label_3_jp = "トルク条件:"
dialog.SetTranslation(label_3, label_3_jp)
# for surface force setting
label_3_1 = "Invert the result of electromagnetic force"
label_3_1_jp = "電磁力の結果を反転する"
dialog.SetTranslation(label_3_1, label_3_1_jp)
label_3_2 = "Center of Teeth:"
label_3_2_jp = "ティースの中心軸:"
dialog.SetTranslation(label_3_2, label_3_2_jp)
label_3_2_a = "Same as torque condition:"
label_3_2_a_jp = "トルク条件の軸と同じ"
dialog.SetTranslation(label_3_2_a, label_3_2_a_jp)
label_3_2_b = "Specify the central axis with a direction vector and a point on the axis"
label_3_2_b_jp = "軸方向ベクトルと軸上の点で指定"
dialog.SetTranslation(label_3_2_b, label_3_2_b_jp)
label_3_2_b_dir = "Axis Direction:"
label_3_2_b_dir_jp = "軸方向ベクトル:"
dialog.SetTranslation(label_3_2_b_dir, label_3_2_b_dir_jp)
label_3_2_b_pos = "Point on Axis:"
label_3_2_b_pos_jp = "軸上の1点:"
dialog.SetTranslation(label_3_2_b_pos, label_3_2_b_pos_jp)
label_4 = "Number of Poles:"
label_4_jp = "極数:"
dialog.SetTranslation(label_4, label_4_jp)
# label_5 = "Force Coordinates:"
# label_5_jp = "節点力の座標系:"
# dialog.SetTranslation(label_5, label_5_jp)
label_5 = "Cycle:"
label_5_jp = "周期:"
dialog.SetTranslation(label_5, label_5_jp)
label_6 = "Rectangular"
label_6_jp = "直交座標系"
dialog.SetTranslation(label_6, label_6_jp)
# label_7 = "Cylindrical"
# label_7_jp = "円筒座標系"
# dialog.SetTranslation(label_7, label_7_jp)
label_8 = "Copy 1 electrical cycle to mechanical cycle"
label_8_jp = "電気角1周期分をコピーして機械角1周期分にする"
dialog.SetTranslation(label_8, label_8_jp)
label_16 = "Output Option:"
label_16_jp = "出力オプション:"
dialog.SetTranslation(label_16, label_16_jp)
label_17 = "Divide the teeth force in the axial direction(Sample:0.0, 0.01, 0.02, 0.03)"
label_17_jp = "ティースの電磁力を軸方向に分ける(例:0.0, 0.01, 0.02, 0.03)"
dialog.SetTranslation(label_17, label_17_jp)
label_9 = "Output Cases:"
label_9_jp = "出力ケース:"
dialog.SetTranslation(label_9, label_9_jp)
label_10 = "All Cases"
label_10_jp = "全ケース"
dialog.SetTranslation(label_10, label_10_jp)
label_11 = "Specified Cases (Example: 1, 2, 5-8)"
label_11_jp = "指定ケース(例: 1, 2, 5-8)"
dialog.SetTranslation(label_11, label_11_jp)
label_12 = "Output Format:"
label_12_jp = "出力フォーマット:"
dialog.SetTranslation(label_12, label_12_jp)
label_13 = "Single File Including Torque(Force Coordinates=Cylindrical)"
label_13_jp = "トルクデータ含む1ファイル出力(電磁力の座標系=円筒座標系)"
dialog.SetTranslation(label_13, label_13_jp)
label_14 = "File Per Case: Time Domain Tooth Forces(Force Coordinates=Rectangular)"
label_14_jp = "ケースごとにファイル出力:時刻依存性ティース電磁力(電磁力の座標系=直交座標系)"
dialog.SetTranslation(label_14, label_14_jp)
label_15 = "File Per Case: Frequency Domain Tooth Forces(Force Coordinates=Rectangular)"
label_15_jp = "ケースごとにファイル出力:周波数依存性ティース電磁力(電磁力の座標系=直交座標系)"
dialog.SetTranslation(label_15, label_15_jp)
dialog.SetTitle(dialogTitle)
dialog.AddLabel(label_1, 0, 1)
dialog.AddSaveFilename(OUTPUT_FILE_PATH, "", "", "*.csv", 1, 2)
dialog.AddLabel(label_2, 0, 1)
dialog.AddString(SET_PREFIX, "", "TOOTH", 1, 2)
dialog.AddLabel(label_3, 0, 1)
dialog.AddComboBox(TORQUE_COND_TITLE, "", torque_condition_title_list(app), 0, 1, 2)
# for surface force
dialog.AddLabel("", 0, 1)
dialog.AddCheckBox(INVERSE_RESULT, label_3_1, True, 1, 2)
dialog.AddLabel(label_3_2, 0, 1)
dialog.AddRadio(TEETH_CENTER_SPECIFYING_TYPE, label_3_2_a, 0, 1, 2)
dialog.AddLabel("", 0, 1)
dialog.AddRadio(TEETH_CENTER_SPECIFYING_TYPE, label_3_2_b, 1, 1, 2)
dialog.AddLabel("", 0, 1)
dialog.AddLabel(label_3_2_b_dir, 1, 1)
dialog.AddReal(TEETH_CENTER_DIR_X, "X:", 0.0, 2, 1)
dialog.AddLabel("", 0, 2)
dialog.AddReal(TEETH_CENTER_DIR_Y, "Y:", 0.0, 2, 1)
dialog.AddLabel("", 0, 2)
dialog.AddReal(TEETH_CENTER_DIR_Z, "Z:", 1.0, 2, 1)
dialog.AddLabel("", 0, 1)
dialog.AddLabel(label_3_2_b_pos, 1, 1)
dialog.AddReal(TEETH_CENTER_POS_X, "X:", 0.0, 2, 1)
dialog.AddLabel("m", 3, 1)
dialog.AddLabel("", 0, 2)
dialog.AddReal(TEETH_CENTER_POS_Y, "Y:", 0.0, 2, 1)
dialog.AddLabel("m", 3, 1)
dialog.AddLabel("", 0, 2)
dialog.AddReal(TEETH_CENTER_POS_Z, "Z:", 0.0, 2, 1)
dialog.AddLabel("m", 3, 1)
# for surface force(end)
dialog.AddLabel(label_4, 0, 1)
dialog.AddInteger(NUM_POLES, "", 4, 1, 2)
dialog.AddLabel(label_5)
#dialog.AddRadio(COORD_TYPE, label_7, 1, 1)
#dialog.AddRadio(COORD_TYPE, label_6, 0, 1)
dialog.AddCheckBox(USE_COPY_CYCLE, label_8, True, 1, 2)
if(not is2D and not isCutPlane):
dialog.AddLabel(label_16, 0, 1)
dialog.AddCheckBox(DIVIDE_TEETH_FORCE, label_17, False, 1, 2)
dialog.AddLabel("", 0, 1)
dialog.AddString(AXIAL_COORDINATES, "", "0.0, 0.01, 0.02", 1, 2)
dialog.AddLabel("m", 3, 1)
dialog.AddLabel("", 0, 1)
dialog.AddLabel(label_12, 0, 1)
dialog.AddRadio(OUTPUT_FORMAT_TYPE, label_13, 0, 1, 2)
dialog.AddRadio(OUTPUT_FORMAT_TYPE, label_14, 1, 1, 2)
dialog.AddRadio(OUTPUT_FORMAT_TYPE, label_15, 2, 1, 2)
dialog.AddLabel("", 0, 1)
dialog.AddLabel(label_9, 0, 1)
dialog.AddRadio(OUTPUT_CASE_TYPE, label_10, 0, 1, 1)
dialog.AddRadio(OUTPUT_CASE_TYPE, label_11, 1, 1, 1)
dialog.AddLabel("", 0, 1)
dialog.AddIntegerList(SPECIFIED_CASES, "", "1", 1, 2)
def check_dialog_parameters(app, parameters):
if (parameters.WasCancelled()):
return False
if (parameters.GetValue(OUTPUT_FILE_PATH)==""):
message = "Output file path is invalid."
message_jp = "出力ファイルパスが不正です。"
show_error_message(message, message_jp)
return False
model = app.GetCurrentModel()
setList = model.GetSetList()
targetSetList = get_target_set(model, parameters)
if (len(targetSetList)<1):
message = "Can not find sequential number set by the specified prefix."
message_jp = "指定された頭文字では連番セットが見つかりませんでした。"
show_error_message(message, message_jp)
return False
if (parameters.GetValue(TEETH_CENTER_SPECIFYING_TYPE) == 1):
if (parameters.GetValue(TEETH_CENTER_DIR_X) == 0.0):
if (parameters.GetValue(TEETH_CENTER_DIR_Y) == 0.0):
if (parameters.GetValue(TEETH_CENTER_DIR_Z) == 0.0):
message = "Center of Teeth is invalid. Please set the axis direction so that it does not become a zero vector."
message_jp = "ティースの中心軸が不正です。軸の方向が零ベクトルにならないように設定してください。"
show_error_message(message, message_jp)
return False
if (parameters.GetValue(NUM_POLES) % 2 != 0):
message = "The number of poles is invalid. Please set even number."
message_jp = "極数が不正です。偶数を設定してください。"
show_error_message(message, message_jp)
return False
coords = []
is3D = (model.GetDimension()==3)
isCutPlane = app.GetCurrentStudy().IsCutPlaneStudy()
if (is3D and not isCutPlane and parameters.GetValue(DIVIDE_TEETH_FORCE) == 1):
coords = [x.strip() for x in parameters.GetValue(AXIAL_COORDINATES).decode('utf-8').split(",")]
if(len(coords)<2):
message = "Coordinate values of output option is invalid. Please set two or more coordinate values by comma-delimited array."
message_jp = "出力オプションの座標値が不正です。カンマ区切りで座標値を2つ以上設定してください。"
show_error_message(message, message_jp)
return False
for i in range(len(coords)-1):
value1 = 0.0
value2 = 0.0
try:
value1 = float(coords[i])
value2 = float(coords[i+1])
except ValueError:
message = "Coordinate values of output option is invalid. Please set the coordinate values as numerical value."
message_jp = "出力オプションの座標値が不正です。座標値は数値を設定してください。"
show_error_message(message, message_jp)
return False
if(value1 > value2):
message = "Coordinate values of output option is invalid. Please set the coordinate values in ascending order."
message_jp = "出力オプションの座標値が不正です。座標値は昇順に設定してください。"
show_error_message(message, message_jp)
return False
outputCaseType = parameters.GetValue(OUTPUT_CASE_TYPE)
caseIndexList = []
if (outputCaseType == 1): # Specified Cases
study = app.GetCurrentStudy()
caseNoList = parameters.GetValueAsIntegerList(SPECIFIED_CASES)
caseIndexList = get_caseIndexList_from_caseNoList(study, caseNoList)
if (len(caseIndexList)==0):
message = "There is no valid case. Please review the setting on Specified Cases."
message_jp = "有効なケースがありません。指定ケースの設定を見直してください。"
show_error_message(message, message_jp)
return False
else:
study = app.GetCurrentStudy()
numCases = study.GetDesignTable().NumCases()
caseIndexList = range(numCases)
hasNot1CycleStepCases = False
hasNot1CycleStepCases = check_has_not_1cycle_step_cases(app, parameters, caseIndexList)
if (hasNot1CycleStepCases):
message = "Insufficient number of result time steps. The file output must have more than one cycle mechanical angle or more than one cycle electrical angle time step number. Please check the results of the specified cases."
message_jp = "結果の時間ステップ数が不十分です。ファイル出力には1周期機械角分または1周期電気角分の時間ステップ数以上の結果が必要です。指定ケースの結果を見直してください。"
show_error_message(message, message_jp)
return False
return True
def output_csv(app, dialog):
outputFormatType = dialog.GetValue(OUTPUT_FORMAT_TYPE)
if (outputFormatType == 0):
output_single_file_including_torque(app, dialog)
elif (outputFormatType == 1):
output_time_domain_tooth_forces(app, dialog)
elif (outputFormatType == 2):
output_frequency_domain_tooth_forces(app, dialog)
def get_node_list_on_tooth1(targetStudy, targetSetList):
removedList = []
curset = targetSetList[0]
selectedIds = []
sel = curset.GetSelection()
if sel.NumEdges()>0:
for i in range(sel.NumEdges()):
selectedIds.append(sel.EdgeID(i))
elif sel.NumFaces()>0:
for i in range(sel.NumFaces()):
selectedIds.append(sel.FaceID(i))
nodeIds = []
for entityId in selectedIds:
if sel.NumEdges()>0:
nodeIds.extend(targetStudy.GetNodeIdsOnEdge(entityId))
elif sel.NumFaces()>0:
nodeIds.extend(targetStudy.GetNodeIdsOnFace(entityId))
##Remove duplicate nodes
nodeIds = list(set(nodeIds))
##Remove nodes on boundary
nodeIds = remove_nodes_on_boundary(targetStudy, nodeIds)
return nodeIds
class SubModuleSetting:
outputFilePath = ""
setPrefix = ""
selectedIndex = -1
invertResult = False
teethCenterType = 0
teethCenterDirX = 0.0
teethCenterDirY = 0.0
teethCenterDirZ = 0.0
teethCenterPosX = 0.0
teethCenterPosY = 0.0
teethCenterPosZ = 0.0
outputFormatType = 0
divideTeethForceFlag = 0
aixalCoords = []
is3D = 0
def __init__(self, app, dialog):
self.is3D = (app.GetCurrentModel().GetDimension()==3)
self.outputFilePath = dialog.GetValue(OUTPUT_FILE_PATH).decode('utf-8')
self.setPrefix = dialog.GetValue(SET_PREFIX).decode('utf-8')
self.selectedIndex = dialog.GetValue(TORQUE_COND_TITLE)
self.invertResult = dialog.GetValue(INVERSE_RESULT)
self.teethCenterType = dialog.GetValue(TEETH_CENTER_SPECIFYING_TYPE)
self.teethCenterDirX = dialog.GetValue(TEETH_CENTER_DIR_X)
self.teethCenterDirY = dialog.GetValue(TEETH_CENTER_DIR_Y)
self.teethCenterDirZ = dialog.GetValue(TEETH_CENTER_DIR_Z)
self.teethCenterPosX = dialog.GetValue(TEETH_CENTER_POS_X)
self.teethCenterPosY = dialog.GetValue(TEETH_CENTER_POS_Y)
self.teethCenterPosZ = dialog.GetValue(TEETH_CENTER_POS_Z)
self.outputFormatType = dialog.GetValue(OUTPUT_FORMAT_TYPE)
if (not self.is3D or app.GetCurrentStudy().IsCutPlaneStudy()) :
self.divideTeethForceFlag = 0
else :
self.divideTeethForceFlag = dialog.GetValue(DIVIDE_TEETH_FORCE)
self.aixalCoords = [x.strip() for x in dialog.GetValue(AXIAL_COORDINATES).decode('utf-8').split(",")]
def write_conf_file(self):
file = open(self.get_file_path(), 'w')
write_line2(file,"outputPath", self.outputFilePath)
write_line2(file,"setPrefix", self.setPrefix)
write_line2(file, "selectedIndex", str(self.selectedIndex))
write_line2(file, "invertResult", str(self.invertResult))
write_line2(file, "teethCenterType", str(self.teethCenterType))
write_line2(file, "teethCenterDirX", str(self.teethCenterDirX))
write_line2(file, "teethCenterDirY", str(self.teethCenterDirY))
write_line2(file, "teethCenterDirZ", str(self.teethCenterDirZ))
write_line2(file, "teethCenterPosX", str(self.teethCenterPosX))
write_line2(file, "teethCenterPosY", str(self.teethCenterPosY))
write_line2(file, "teethCenterPosZ", str(self.teethCenterPosZ))
write_line2(file, "outputFormatType", str(self.outputFormatType))
if(self.is3D and self.divideTeethForceFlag==1):
file.write("stackpos")
for coord in self.aixalCoords:
file.write(", " + str(coord))
file.write("\n")
file.close()
def get_file_path(self):
dir = os.path.dirname(self.outputFilePath)
filePath = os.path.join(dir, "NVHSubmod.conf")
return filePath
class SubModuleRunner:
modulePath = ""
setting = []
def __init__(self, app, dialog):
moduleName = "NVHSurfaceForceExtractor"
if (os.name == "nt"):
moduleName += ".exe"
moduleDir = app.GetAppDir()
self.modulePath = moduleDir + "/" + moduleName
self.setting = SubModuleSetting(app,dialog)
self.setting.write_conf_file()
def __del__(self):
os.remove(self.setting.get_file_path())
def readstep(self, stepFilePath):
step = 0
try:
f = open(stepFilePath)
line = f.readline()
step = int(line.strip())
f.close()
except:
pass
return step
def run(self, app, study, caseIndex, useMultiSlice, sliceIndex, targetSetList, steps):
jplotPath = self.get_jplot_path(study, caseIndex, useMultiSlice, sliceIndex)
workingDir = os.path.dirname(self.setting.outputFilePath)
filename = "submodoutput" +str(caseIndex)+"_"+str(sliceIndex)+".csv"
subModSettingPath = self.setting.get_file_path()
subModOutputPath = os.path.join(workingDir , filename)
tooth1NodeFilePath = os.path.join(workingDir, "tooth1.dat")
tooth1NodeIds = get_node_list_on_tooth1(study, targetSetList)
stepFilePath = os.path.join(workingDir , "step.txt")
self.write_node_ids(len(targetSetList), tooth1NodeIds, tooth1NodeFilePath)
#runResult = subprocess.run([self.modulePath, jplotPath, subModSettingPath, subModOutputPath, tooth1NodeFilePath], cwd=workingDir)
runResult = subprocess.Popen([self.modulePath, jplotPath, subModSettingPath, subModOutputPath, tooth1NodeFilePath], cwd=workingDir, stdout=subprocess.PIPE)
count = 0
wasCanceled = False
while runResult.poll() is None:
time.sleep(0.5)
if (app.UserProgressWasCanceled()):
app.UserProgressFinish()
wasCanceled = True
runResult.stdout.close()
runResult.kill()
break
if os.path.isfile(stepFilePath):
try:
step = 0
step = self.readstep(stepFilePath)
for i in range(count+1,step+1):
app.UserProgressStep()
count+=1
except:
pass
if os.path.isfile(tooth1NodeFilePath):
os.remove(tooth1NodeFilePath)
if os.path.isfile(stepFilePath):
os.remove(stepFilePath)
if(wasCanceled):
resultData = []
return (resultData, wasCanceled)
if (count < steps):
for i in range(count+1,steps+1):
app.UserProgressStep()
with open(subModOutputPath) as f:
reader = csv.reader(f)
l = [row for row in reader]
resultData = [[float(v) for v in row] for row in l]
os.remove(subModOutputPath)
return (resultData, wasCanceled)
def get_jplot_path(self, study, caseIndex, useMultiSlice, sliceIndex):
folder = study.CalculationFolder(caseIndex + 1)+os.path.sep
filename = "Designer.jplot"
if (useMultiSlice):
filename = "Designer_slice_"+str(sliceIndex+1)+".jplot"
jplotPath = os.path.join(folder, filename)
return jplotPath
def write_node_ids(self, nTooth, tooth1NodeIds, tooth1NodeFilePath):
file = open(tooth1NodeFilePath, 'w')
write_line(file, str(nTooth))
for nodeId in tooth1NodeIds:
write_line(file,str(nodeId))
file.close()
def output_single_file_including_torque(app, dialog):
outputPath = dialog.GetValue(OUTPUT_FILE_PATH)
file = open(outputPath.decode('utf-8'), 'w')
write_header(file, app, dialog)
[caseIndexList, noResultCaseIndexList, speedList, avTorqList, startIndices, outX, outYT] = create_torque_data(app, dialog)
write_torque(file, speedList, avTorqList, outX, outYT)
wasCanceled = write_force(file, app, dialog, caseIndexList, speedList, avTorqList, startIndices, outX)
file.close()
ShowFinishMessage(app, wasCanceled)
def output_time_domain_tooth_forces(app, dialog):
## Get app data
targetStudy = app.GetCurrentStudy()
targetModel = app.GetCurrentModel()
## Get dialog values
useElectricCycle = dialog.GetValue(USE_COPY_CYCLE)
numPoles = dialog.GetValue(NUM_POLES)
coordType = 0 # Fixed to Global Rectangular
targetSetList = get_target_set(targetModel, dialog)
setPrefix = dialog.GetValue(SET_PREFIX).decode('utf-8')
## Setup parameters
outputDimension = OUTPUT_DIMENSION
modelDimension = targetModel.GetDimension()
is2D = (modelDimension == 2)
isCutPlane = targetStudy.IsCutPlaneStudy()
thickness = 0
useMultiSlice = False
numSlice = 1
if (is2D):
thickness = targetStudy.GetStudyProperties().GetValueWithUnit("ModelThickness", "m")
useMultiSlice = use_multi_slice(targetStudy)
numSlice = get_slice_number(targetStudy)
caseIndexList = get_case_index_list(dialog, targetStudy)
periodicity = get_periodicity(targetStudy)
needConvertTwice = (not is2D) and has_symmetry_boundary(targetStudy, dialog)
divideTeethForceFlag = 0
if (not is2D and not isCutPlane):
divideTeethForceFlag = dialog.GetValue(DIVIDE_TEETH_FORCE)
stepsList = get_numsteps(app, caseIndexList)
if (divideTeethForceFlag):
needConvertTwice = False
## Setup progress dialog
setup_progress(app, outputDimension, caseIndexList, numSlice, stepsList)
wasCanceled = False
## Case loop
numCases = len(caseIndexList)
subModuleRunner = SubModuleRunner(app, dialog)
allCaseData = []
for caseLoopIndex in range(numCases):
caseData = []
caseIndex = caseIndexList[caseLoopIndex]
targetStudy.SetCurrentCase(caseIndex)
for sliceIndex in range(numSlice):
[sliceData, wasCanceled] = subModuleRunner.run(app, targetStudy, caseIndex, useMultiSlice, sliceIndex, targetSetList, stepsList[caseLoopIndex])
if(wasCanceled):
return True
if(is2D) :
caseData.append(sliceData)
else :
if(divideTeethForceFlag) :
coords = [x.strip() for x in dialog.GetValue(AXIAL_COORDINATES).decode('utf-8').split(",")]
numSlice = len(coords)-1
num_block = len(sliceData[0]) // numSlice
for i in range(numSlice) :
start = num_block*i
end = num_block*(i+1)
data = []
for x in sliceData:
data.append(x[start:end])
caseData.append(data)
else :
caseData.append(sliceData)
allCaseData.append(caseData)
for caseLoopIndex in range(numCases):
caseIndex = caseIndexList[caseLoopIndex]
targetStudy.SetCurrentCase(caseIndex)
if (targetStudy.CaseHasResult(caseIndex) == False):
continue
## Slice loop
for sliceIndex in range(numSlice):
# Write file
outputPath = create_file_name(dialog.GetValue(OUTPUT_FILE_PATH), numCases, caseIndex+1, useMultiSlice, numSlice, sliceIndex+1)
file = open(outputPath.decode('utf-8'), 'w')
## Write header
write_header_for_time_domain_tooth_force_only(file, setPrefix, len(targetSetList)*periodicity)
## Get start index for last 1 cycle
torqResultName = get_torq_result_name(app)
dataset = targetStudy.GetDataSet(torqResultName, caseIndex+1)
startIndex = get_last_1_cycle_start_index(dialog, targetStudy, dataset)
timeData = list(dataset.GetColumn(0))
timeData = timeData[startIndex:]
timeData = create_1_electric_cycle_time_to_1_mechanical_cycle_time(useElectricCycle, numPoles, timeData)
## Each Tooth loop
fullModelF = []
##Add Time
fullModelF.append(timeData)
nfullModelTarget = int(len(allCaseData[caseLoopIndex][sliceIndex][0])/3)
for setIndex in range(nfullModelTarget):
eachSetF = []
## Component loop
for compIndex in range(outputDimension):
if (app.UserProgressWasCanceled()):
app.UserProgressFinish()
wasCanceled = True
break
colIndex = setIndex*3 + compIndex;
data = [allCaseData[caseLoopIndex][sliceIndex][stepIndex][colIndex] for stepIndex in range(len(allCaseData[caseLoopIndex][sliceIndex]))]
## Considering 1/2 model lengthwise if symmetry boundary is set on XY plane
convertedData = convert_twice(needConvertTwice, data)
## Get last 1 cycle data
lastCycleF = convertedData[startIndex:]
##Copy 1 electric cycle to 1 mechanical cycle
lastCycleF = copy_1_electric_cycle_to_1_mechanical_cycle(useElectricCycle, numPoles, lastCycleF)
##If 2D model times thickness
if useMultiSlice:
lastCycleF = [f /numSlice for f in lastCycleF]
##Add each component data
fullModelF.append(lastCycleF)
if (wasCanceled == False):
app.UserProgressStep()
##Write TOOTH value of full model
WriteByAllComponentsInSetForOneCase(file, fullModelF)
file.close()
app.UserProgressFinish()
ShowFinishMessage(app, wasCanceled)
def output_frequency_domain_tooth_forces(app, dialog):
## Get app data
targetStudy = app.GetCurrentStudy()
targetModel = app.GetCurrentModel()
dataManager = app.GetDataManager()
## Get dialog values
numPoles = dialog.GetValue(NUM_POLES)
coordType = 0 # Fixed to Global Rectangular
targetSetList = get_target_set(targetModel, dialog)
setPrefix = dialog.GetValue(SET_PREFIX).decode('utf-8')
## Setup parameters
outputDimension = OUTPUT_DIMENSION
modelDimension = targetModel.GetDimension()
is2D = (modelDimension == 2)
isCutPlane = targetStudy.IsCutPlaneStudy()
useMultiSlice = False
numSlice = 1
if (is2D):
useMultiSlice = use_multi_slice(targetStudy)
numSlice = get_slice_number(targetStudy)
caseIndexList = get_case_index_list(dialog, targetStudy)
periodicity = get_periodicity(targetStudy)
needConvertTwice = (not is2D) and has_symmetry_boundary(targetStudy, dialog)
divideTeethForceFlag = 0
if (not is2D and not isCutPlane):
divideTeethForceFlag = dialog.GetValue(DIVIDE_TEETH_FORCE)
stepsList = get_numsteps(app, caseIndexList)
if (divideTeethForceFlag):
needConvertTwice = False
## Setup progress dialog
setup_progress(app, outputDimension, caseIndexList, numSlice, stepsList)
wasCanceled = False
## Case loop
numCases = len(caseIndexList)
subModuleRunner = SubModuleRunner(app, dialog)
allCaseData = []
for caseLoopIndex in range(numCases):
caseData = []
caseIndex = caseIndexList[caseLoopIndex]
targetStudy.SetCurrentCase(caseIndex)
for sliceIndex in range(numSlice):
[sliceData, wasCanceled] = subModuleRunner.run(app, targetStudy, caseIndex, useMultiSlice, sliceIndex, targetSetList, stepsList[caseLoopIndex])
if(wasCanceled):
return True
if(is2D) :
caseData.append(sliceData)
else :
if(divideTeethForceFlag) :
coords = [x.strip() for x in dialog.GetValue(AXIAL_COORDINATES).decode('utf-8').split(",")]
numSlice = len(coords)-1
num_block = len(sliceData[0]) // numSlice
for i in range(numSlice) :
start = num_block*i
end = num_block*(i+1)
data = []
for x in sliceData:
data.append(x[start:end])
caseData.append(data)
else :
caseData.append(sliceData)
allCaseData.append(caseData)
for caseLoopIndex in range(numCases):
caseIndex = caseIndexList[caseLoopIndex]
targetStudy.SetCurrentCase(caseIndex)
if (targetStudy.CaseHasResult(caseIndex) == False):
continue
## Slice loop
for sliceIndex in range(numSlice):
## Write file
outputPath = create_file_name(dialog.GetValue(OUTPUT_FILE_PATH), numCases, caseIndex+1, useMultiSlice, numSlice, sliceIndex+1)
file = open(outputPath.decode('utf-8'), 'w')
## Write header
write_header_for_frequency_domain_tooth_force_only(file, setPrefix, len(targetSetList)*periodicity)
## Get start index for last 1 cycle
torqResultName = get_torq_result_name(app)
dataset = targetStudy.GetDataSet(torqResultName, caseIndex+1)
startIndex = get_last_1_cycle_start_index(dialog, targetStudy, dataset)
timeData = list(dataset.GetColumn(0))
## Each Tooth loop
fullModelF = []
nfullModelTarget = int(len(allCaseData[caseLoopIndex][sliceIndex][0])/3)
for setIndex in range(nfullModelTarget):
eachSetF = []
## Component loop
for compIndex in range(outputDimension):
if (app.UserProgressWasCanceled()):
app.UserProgressFinish()
wasCanceled = True
break
colIndex = setIndex*3 + compIndex
forceData = [allCaseData[caseLoopIndex][sliceIndex][stepIndex][colIndex] for stepIndex in range(len(allCaseData[caseLoopIndex][sliceIndex]))]
dataSetTitle = "fft_for_nvf_force_export"
[fftDataSet, wasCanceled] = calc_force_with_FFT(dataManager, timeData, forceData, dataSetTitle, needConvertTwice, startIndex, useMultiSlice, numSlice)
## Real/Imaginary Loop
numFFTColmuns = fftDataSet.GetCols()
if (numFFTColmuns < 3):
continue
if (setIndex == 0 and compIndex == 0):
freqData = list(fftDataSet.GetColumn(0))
## Add Time/Frequency
fullModelF.append(freqData)
for realImagIndex in range(1, numFFTColmuns):
data = list(fftDataSet.GetColumn(realImagIndex))
## Add each component data
fullModelF.append(data)
if (wasCanceled == False):
app.UserProgressStep()
dataManager.DeleteDataSet(dataSetTitle)
## Write TOOTH value of full model
WriteByAllComponentsInSetForOneCase(file, fullModelF)
file.close()
app.UserProgressFinish()
ShowFinishMessage(app, wasCanceled)
def write_header(file, app, dialog):
targetModel = app.GetCurrentModel()
targetStudy = app.GetCurrentStudy()
is2D = (targetModel.GetDimension()==2)
isCutPlane = targetStudy.IsCutPlaneStudy()
setList = targetModel.GetSetList()
targetSetList = get_target_set(targetModel, dialog)
numPoles = dialog.GetValue(NUM_POLES)
dimString = "3D"
coordString = get_coordName(1) # Fixed to cylindrical in V18.1
periodicity = get_periodicity(targetStudy)
numTeeth = int(len(targetSetList)*periodicity)
coords = []
if(not is2D and not isCutPlane):
coords = [x.strip() for x in dialog.GetValue(AXIAL_COORDINATES).decode('utf-8').split(",")]
modelThickness = 0
numSlice = 1
if (is2D):
dimString = "2D"
modelThickness = targetStudy.GetStudyProperties().GetValueWithUnit("ModelThickness", "mm")
numSlice = get_slice_number(targetStudy)
write_line2(file, "CSV Version", CSV_VERSION)
write_line2(file, "Dimension", dimString)
write_line2(file, "Coordinate", coordString)
if(is2D or isCutPlane or dialog.GetValue(DIVIDE_TEETH_FORCE)==0):
write_line2(file, "Teeth", str(numTeeth))
else :
write_line3(file, "Teeth", str(numTeeth), str(len(coords)-1))
if (is2D):
write_line2(file, "StackLength(mm)", str(modelThickness))
write_line2(file, "Slice", str(numSlice))
file.write("\n")
def create_torque_data(app, dialog):
##Initialize
speedList = []
avTorqList = []
startIndices = []
caseIndexList = []
noResultCaseIndexList = []
outX = []
outYT = []
##Get dialog parameters
useElectricCycle = dialog.GetValue(USE_COPY_CYCLE)
numPoles = dialog.GetValue(NUM_POLES)
outputCaseType = dialog.GetValue(OUTPUT_CASE_TYPE)
caseNoList = dialog.GetValueAsIntegerList(SPECIFIED_CASES)
##Get app data
targetStudy = app.GetCurrentStudy()
torqResultName = get_torq_result_name(app)
##Create output case list
numCases = targetStudy.GetDesignTable().NumCases()
if (outputCaseType == 0): # Output all cases
caseIndexList = range(numCases)
elif (outputCaseType == 1): # Output specified cases
caseIndexList = get_caseIndexList_from_caseNoList(targetStudy, caseNoList)
##Create each case data
for caseIndex in caseIndexList:
if (targetStudy.CaseHasResult(caseIndex) == False):
noResultCaseIndexList.append(caseIndex)
continue
##Calculate 1 mechanical cycle time from rotation speed
targetStudy.SetCurrentCase(caseIndex)
speed = get_speed(targetStudy)
if (useElectricCycle):
T = 60.0/speed/numPoles*2
else :
T = 60.0/speed
##Get torque data for 1 last cycle
lastCycleTorq = []
dataset = targetStudy.GetDataSet(torqResultName, caseIndex+1)
numSteps = dataset.GetRows()
if (dataset.GetCols() < 2 or numSteps==0):
noResultCaseIndexList.append(caseIndex)
continue
time = list(dataset.GetColumn(0))
torque = get_target_torque(dataset, dialog)
lastCycleStartTime = time[-1] - T + EPSILON*(time[-1] - time[-2])
index = len(time)-1
t = time[index]
while t > lastCycleStartTime:
lastCycleTorq.insert(0, torque[index])
index -= 1
if (index < 0 or len(time) <= index):
break
t = time[index]
##Calculate average torque
aveTorq = sum(lastCycleTorq)/len(lastCycleTorq)
##Copy 1 electric cycle to 1 mechanical cycle
lastCycleTorq = copy_1_electric_cycle_to_1_mechanical_cycle(useElectricCycle, numPoles, lastCycleTorq,True)
##Create angle data
angleData = []
deltaAngle = 360.0/(len(lastCycleTorq))
for i in range(len(lastCycleTorq)):
angleData.append(deltaAngle*i)
##Set each case data
speedList.append(speed)
avTorqList.append(aveTorq)
startIndices.append(index+1)
outX.append(angleData)
outYT.append(lastCycleTorq)
##Remove no result case
for index in noResultCaseIndexList:
caseIndexList.remove(index)
return (caseIndexList, noResultCaseIndexList, speedList, avTorqList, startIndices, outX, outYT)
def write_torque(file, speed, aveTorq, outX, outYT):
##Write torque header
write_line(file, "*Torque")
##Write torque data per case
for i in range(len(speed)):
write_line2(file, "Speed(RPM)", str(speed[i]))
write_line2(file, "Torque(Nm)", str(aveTorq[i]))
for j in range(len(outX[i])):
write_line2(file, str(outX[i][j]), str(outYT[i][j]))
file.write("\n")
def write_force(file, app, dialog, caseIndexList, speedList, avTorqList, startIndices, outX):
##Get Study value
targetModel = app.GetCurrentModel()
targetStudy = app.GetCurrentStudy()
is2D = (targetModel.GetDimension()==2)
isCutPlane = app.GetCurrentStudy().IsCutPlaneStudy()
periodicity = get_periodicity(targetStudy)
useMultiSlice = use_multi_slice(targetStudy)
numSlice = 1
if (useMultiSlice):
numSlice = get_slice_number(targetStudy)
needConvertTwice = (not is2D) and has_symmetry_boundary(targetStudy, dialog)
##Get dialog parameters
useElectricCycle = dialog.GetValue(USE_COPY_CYCLE)
numPoles = dialog.GetValue(NUM_POLES)
coordType = 1 # Fixed to cylindrical in V18.1
divideTeethForceFlag = 0
if (not is2D and not isCutPlane):
divideTeethForceFlag = dialog.GetValue(DIVIDE_TEETH_FORCE)
if (divideTeethForceFlag):
needConvertTwice = False
##Pick up target set list
targetSetList = get_target_set(targetModel, dialog)
##Create data for each component and each case
dimension = app.GetCurrentModel().GetDimension()
numCases = targetStudy.GetDesignTable().NumCases()
stepsList = get_numsteps(app, caseIndexList)
##Setup progress dialog
setup_progress(app, dimension, caseIndexList, numSlice, stepsList)
wasCanceled = False
subModuleRunner = SubModuleRunner(app, dialog)
allCaseData = []
for outputIndex in range(len(caseIndexList)):
caseData = []
caseIndex = caseIndexList[outputIndex]
targetStudy.SetCurrentCase(caseIndex)
for sliceIndex in range(numSlice):
[sliceData, wasCanceled] = subModuleRunner.run(app, targetStudy, caseIndex, useMultiSlice, sliceIndex, targetSetList, stepsList[outputIndex])
if(wasCanceled):
file.close()
return True
if(is2D) :
caseData.append(sliceData)
else :
if(divideTeethForceFlag) :
list = [x.strip() for x in dialog.GetValue(AXIAL_COORDINATES).decode('utf-8').split(",")]
numSlice = len(list)-1
num_block = len(sliceData[0]) // numSlice
for i in range(numSlice) :
start = num_block*i
end = num_block*(i+1)
data = []
for x in sliceData:
data.append(x[start:end])
caseData.append(data)
else :
caseData.append(sliceData)
allCaseData.append(caseData)
for compIndex in range(dimension):
write_line2(file, "*Force", str(compIndex+1))
for outputIndex in range(len(caseIndexList)):
if (app.UserProgressWasCanceled()):
app.UserProgressFinish()
file.close()
return True
caseIndex = caseIndexList[outputIndex]
targetStudy.SetCurrentCase(caseIndex)
##Get nodeIds on each set
write_line2(file, "Speed(RPM)", str(speedList[outputIndex]))
write_line2(file, "Torque(Nm)", str(avTorqList[outputIndex]))
fullModelF=[]
for sliceIndex in range(numSlice):
##Get TOOTH value
nfullModelTarget = int(len(allCaseData[outputIndex][sliceIndex][0])/3)
for setIndex in range(nfullModelTarget):
colIndex = setIndex*3 + compIndex
data = [allCaseData[outputIndex][sliceIndex][stepIndex][colIndex] for stepIndex in range(len(allCaseData[outputIndex][sliceIndex]))]
##Considering 1/2 model lengthwise if symmetry boundary is set on XY plane
convertedData = convert_twice(needConvertTwice, data)
##Get last 1 cycle data
lastCycleF = convertedData[startIndices[outputIndex]:]
##Copy 1 electric cycle to 1 mechanical cycle
lastCycleF = copy_1_electric_cycle_to_1_mechanical_cycle(useElectricCycle, numPoles, lastCycleF,True)
if (useMultiSlice):
lastCycleF = [f / numSlice for f in lastCycleF]
##Add each set data
fullModelF.append(lastCycleF)
##Write TOOTH value
for i in range(len(outX[outputIndex])):
file.write(str(outX[outputIndex][i]) + ",")
for j in range(len(fullModelF)):
file.write(str(fullModelF[j][i]))
if j == len(fullModelF)-1:
file.write("\n")
else:
file.write(",")
file.write("\n")
if (wasCanceled == False):
app.UserProgressStep()
app.UserProgressFinish()
return wasCanceled
def write_line(file, str1):
file.write(str1)
file.write("\n")
def write_line2(file, str1, str2):
file.write(str1)
file.write(",")
file.write(str2)
file.write("\n")
def write_line3(file, str1, str2, str3):
file.write(str1)
file.write(",")
file.write(str2)
file.write(",")
file.write(str3)
file.write("\n")
def get_speed(targetStudy):
result = 0;
motionList = get_conditions(targetStudy, "RotationMotion")
motion = motionList[0]
return motion.GetValue("AngularVelocity")
def torque_condition_title_list(app):
result = []
torqueList = get_conditions(app.GetCurrentStudy(), "Torque_Surface")
for cond in torqueList:
result.append(cond.GetName())
return result
def get_periodicity(targetStudy):
result=1
for i in range(targetStudy.NumConditions()):
cond = targetStudy.GetCondition(i)
if cond.GetScriptTypeName()=="RotationPeriodicBoundary":
result = 360//int(cond.GetValue(u"Angle"))
break
return result
def get_coordName(coordType):
result = "Global Rectangular"
if (coordType == 0): # 0: Rectangular
result = "Global Rectangular"
elif (coordType == 1): # 1: Cylindrical
result = "Cylindrical"
return result
def get_component(coordType, compIndex):
result = "X"
if (coordType == 0): # 0: Rectangular
if (compIndex==0):
result = "X"
elif (compIndex==1):
result = "Y"
elif (compIndex==2):
result = "Z"
elif (coordType == 1): # 1: Cylindrical
if (compIndex==0):
result = "Radial"
elif (compIndex==1):
result = "Theta"
elif (compIndex==2):
result = "Z"
return result
def get_caseIndexList_from_caseNoList(targetStudy, caseNoList):
result = []
numCases = targetStudy.GetDesignTable().NumCases()
for no in caseNoList:
index = no-1
if (index>-1 and index 0
def get_ms_conditions(study):
result = []
for i in range(study.NumConditions()):
cond = study.GetCondition(i)
typeName = cond.GetScriptTypeName()
if (typeName == "MultiSlice"):
result.append(cond)
return result
def get_slice_number(study):
result = 1
condList = get_ms_conditions(study)
if (len(condList)>0):
cond = condList[0]
if (cond.IsValid()):
result = int(cond.GetValue("NumberOfSlices"))
return result
def get_target_set(targetModel, dialog):
targetSetList = []
numSet = set()
prefix = dialog.GetValue(SET_PREFIX).decode('utf-8')
nPrefix = len(prefix)
setList = targetModel.GetSetList()
if (setList.IsValid() == False):
return targetSetList
for i in range(setList.NumSet()):
entitySet = setList.GetSet(i)
if entitySet.IsValid():
setName = entitySet.GetName()
if sys.version_info.major == 2:
setName = setName.decode('utf-8')
if setName.startswith(prefix) and len(setName) > nPrefix:
numStr = setName[nPrefix:]
if numStr.isdecimal():
numSet.add(int(numStr))
targetSetList.append(entitySet)
if len(targetSetList)==0:
return targetSetList
if len(targetSetList)!=len(numSet):
targetSetList.clear()
return targetSetList
numList = sorted(numSet)
if numList[0]!= 1 or numList[-1]!=len(numSet):
targetSetList.clear()
return targetSetList
def is_japanese(app):
lang = app.GetPreference("Language").decode('utf-8')
if (lang == "Japanese"):
return True
elif (lang == "System"):
localeInfo = locale.getlocale()
if ("ja" in localeInfo[0].lower()):
return True
else:
return False
return False
def get_target_torque(dataset, dialog):
result = []
selectedIndex = dialog.GetValue(TORQUE_COND_TITLE)
titleList = torque_condition_title_list(app)
targetName = titleList[selectedIndex]
for i in range(dataset.GetCols()):
if (dataset.GetColumnName(i)==targetName):
result = list(dataset.GetColumn(i))
return result
def has_zero_speed(app):
targetStudy = app.GetCurrentStudy()
numCases = targetStudy.GetDesignTable().NumCases()
for caseIndex in range(numCases):
targetStudy.SetCurrentCase(caseIndex)
if (targetStudy.HasResult()==False):
continue
motionList = get_conditions(targetStudy, "RotationMotion")
motion = motionList[0]
speed = motion.GetValue("AngularVelocity")
if (speed==0.0):
return True
return False
def has_symmetry_boundary(study, dialog):
axisType = dialog.GetValue(TEETH_CENTER_SPECIFYING_TYPE)
axisDir_X = 0.0
axisDir_Y = 0.0
axisDir_Z = 0.0
if axisType==0:
torqueList = get_conditions(study, "Torque_Surface")
selectedIndex = dialog.GetValue(TORQUE_COND_TITLE)
axisDirVec = torqueList[selectedIndex].GetPoint("Axis")
axisDir_X = axisDirVec.x()
axisDir_Y = axisDirVec.y()
axisDir_Z = axisDirVec.z()
else:
axisDir_X = dialog.GetValue(TEETH_CENTER_DIR_X)
axisDir_Y = dialog.GetValue(TEETH_CENTER_DIR_Y)
axisDir_Z = dialog.GetValue(TEETH_CENTER_DIR_Z)
axisDir = -1
if (axisDir_Y==0.0 and axisDir_Z==0.0):
axisDir=0
elif (axisDir_Z==0.0 and axisDir_X==0.0):
axisDir=1
elif (axisDir_X==0.0 and axisDir_Y==0.0):
axisDir=2
condList = get_conditions(study, "SymmetryBoundary")
for symmetry in condList:
if axisDir==0 and symmetry.HasTargetOnYZPlane():
return True
elif axisDir==1 and symmetry.HasTargetOnZXPlane():
return True
elif axisDir==2 and symmetry.HasTargetOnXYPlane():
return True
return False
def get_case_index_list(dialog, targetStudy):
caseIndexList = []
caseNoList = dialog.GetValueAsIntegerList(SPECIFIED_CASES)
outputCaseType = dialog.GetValue(OUTPUT_CASE_TYPE)
numCases = targetStudy.GetDesignTable().NumCases()
if (outputCaseType == 0): # Output all cases
caseIndexList = range(numCases)
elif (outputCaseType == 1): # Output specified cases
caseIndexList = get_caseIndexList_from_caseNoList(targetStudy, caseNoList)
return caseIndexList
def get_numsteps(app, caseIndexList):
targetStudy = app.GetCurrentStudy()
torqResultName = get_torq_result_name(app)
stepsList = []
for caseIndex in caseIndexList:
if (targetStudy.CaseHasResult(caseIndex) == False):
return True
targetStudy.SetCurrentCase(caseIndex)
dataset = targetStudy.GetDataSet(torqResultName, caseIndex+1)
numSteps = dataset.GetRows()
stepsList.append(numSteps)
return stepsList
def check_has_not_1cycle_step_cases(app, parameters, caseIndexList):
result = False
useElectricCycle = parameters.GetValue(USE_COPY_CYCLE)
numPoles = parameters.GetValue(NUM_POLES)
targetStudy = app.GetCurrentStudy()
torqResultName = get_torq_result_name(app)
for caseIndex in caseIndexList:
if (targetStudy.CaseHasResult(caseIndex) == False):
return True
##Calculate 1 mechanical cycle time from rotation speed
targetStudy.SetCurrentCase(caseIndex)
speed = get_speed(targetStudy)
T = get_1_mechanical_cycle_time(speed, useElectricCycle, numPoles)
##Get torque data for 1 last cycle
lastCycleTorq = []
dataset = targetStudy.GetDataSet(torqResultName, caseIndex+1)
numSteps = dataset.GetRows()
if (dataset.GetCols()<2 or numSteps==0):
continue
time = list(dataset.GetColumn(0))
if (len(time)<=1):
result = True
break
lastCycleStartTime = time[-1] - T + time[1]
timeScale = time[1]
if (lastCycleStartTime < -EPSILON * T):
result = True
break
return result
def get_torq_result_name(app):
targetStudy = app.GetCurrentStudy()
useMultiSlice = use_multi_slice(targetStudy)
result = "Torque"
numSlice = 1
if (useMultiSlice):
numSlice = get_slice_number(targetStudy)
if (is_japanese(app)):
result = "トルク <モデル全体>"
else:
result = "Torque "
return result
def create_file_name(originalFilePath, numCases, caseNo, useMultiSlice, numSlice, sliceNo):
if (useMultiSlice or numSlice>1):
if (numCases > 1):
absFilePathWithoutExt = os.path.splitext(originalFilePath)[0]
postFixLabel = b"_Case%d_Slice%d.csv" % (caseNo, sliceNo)
return (absFilePathWithoutExt + postFixLabel)
else:
absFilePathWithoutExt = os.path.splitext(originalFilePath)[0]
sliceLabel = b"_Slice%d.csv" % sliceNo
return (absFilePathWithoutExt + sliceLabel)
else:
if (numCases > 1):
absFilePathWithoutExt = os.path.splitext(originalFilePath)[0]
caseLabel = b"_Case%d.csv" % caseNo
return (absFilePathWithoutExt + caseLabel)
else:
return originalFilePath
def get_1_mechanical_cycle_time(speed, useElectricCycle, numPoles):
if (speed == 0.0 or numPoles == 0):
return 0
if (useElectricCycle):
T = 60.0/speed/numPoles*2
else :
T = 60.0/speed
return T
def setup_progress(app, dimension, caseIndexList, numSlice, stepsList):
progressLabel = "Exporting to CSV File..."
if (is_japanese(app)):
progressLabel = "CSVファイルへ出力中..."
app.SetupUserProgress(progressLabel)
app.SetUserProgressUseCancel(True)
total_steps = 0
for steps in stepsList:
total_steps += steps
maxSteps = (numSlice * total_steps) + (dimension * len(caseIndexList))
app.SetUserProgressMaxSteps(maxSteps)
app.UserProgressStart()
def convert_twice(needConvertTwice, data):
convertedData = []
if needConvertTwice:
convertedData = [n*2 for n in data]
else:
convertedData = data
return convertedData
def copy_1_electric_cycle_to_1_mechanical_cycle(useElectricCycle, numPoles, originalData,includeFirst = False):
result = []
if (useElectricCycle):
for i in range(numPoles//2):
if (i == 0) or (includeFirst == True):
result.extend(originalData)
else:
result.extend(originalData[1:])
else:
result = originalData
return result
def create_1_electric_cycle_time_to_1_mechanical_cycle_time(useElectricCycle, numPoles, originalData):
result = []
offsetData = []
numSize = len(originalData)
if (numSize) < 2:
return result
deltaT = originalData[1] - originalData[0]
startTime = originalData[0]
offsetData = []
for i in range(len(originalData)):
offsetData.append(i*deltaT)
lastT = offsetData[-1]
if (useElectricCycle):
for i in range(numPoles//2):
tmp = []
if (i == 0):
tmp = offsetData
else:
offsetTime = lastT + deltaT
tmp = [n + offsetTime for n in offsetData][:-1]
lastT = tmp[-1]
result.extend(tmp)
else:
result = originalData
return result
def WriteByAllComponentsInSetForOneCase(file, fullModelF):
for timeIndex in range(len(fullModelF[0])):
for colIndex in range(len(fullModelF)):
file.write(str(fullModelF[colIndex][timeIndex]))
if (colIndex == len(fullModelF)-1):
file.write("\n")
else:
file.write(",")
def get_last_1_cycle_start_index(dialog, targetStudy, dataset):
startIndex = 0
##Get dialog parameters
useElectricCycle = dialog.GetValue(USE_COPY_CYCLE)
numPoles = dialog.GetValue(NUM_POLES)
##Calculate 1 mechanical cycle time from rotation speed
speed = get_speed(targetStudy)
T = get_1_mechanical_cycle_time(speed, useElectricCycle, numPoles)
##Get torque data for 1 last cycle
lastCycleTorq = []
numSteps = dataset.GetRows()
if (dataset.GetCols()<2 or numSteps==0):
return 0
time = list(dataset.GetColumn(0))
##Search last 1 cycle start index
lastCycleStartTime = time[-1] - T
index = len(time)-1
t = time[index]
while t > lastCycleStartTime - EPSILON:
index -= 1
if (index < 0 or len(time) <= index):
break
t = time[index]
startIndex = index + 1
return startIndex
def write_header_for_time_domain_tooth_force_only(file, setPrefix, numFullModelSets):
numComponents = OUTPUT_DIMENSION
file.write(",")
##Write a line for set names
for setIndex in range(numFullModelSets):
for componentIndex in range(numComponents):
if (componentIndex == 0):
setName = setPrefix + " " + str(setIndex+1)
file.write(setName)
file.write(",")
elif (setIndex == numFullModelSets-1 and componentIndex == numComponents-1):
file.write("\n")
else:
file.write(",")
##Write a line for time and each set components
file.write("Time")
file.write(",")
for setIndex in range(numFullModelSets):
for componentIndex in range(numComponents):
componentName = "F" + get_component(0, componentIndex).lower()
file.write(componentName)
if (setIndex == numFullModelSets-1 and componentIndex == numComponents-1):
file.write("\n")
else:
file.write(",")
def write_header_for_frequency_domain_tooth_force_only(file, setPrefix, numFullModelSets):
numComponents = OUTPUT_DIMENSION
file.write(",")
##Write a line for set names
for setIndex in range(numFullModelSets):
for componentIndex in range(numComponents):
for realImagIndex in range(2):
if (componentIndex == 0 and realImagIndex == 0):
setName = setPrefix + " " + str(setIndex+1)
file.write(setName)
file.write(",")
elif (setIndex == numFullModelSets-1 and componentIndex == numComponents-1 and realImagIndex == 1):
file.write("\n")
else:
file.write(",")
##Write a line for time and each set components
file.write("Frequency")
file.write(",")
for setIndex in range(numFullModelSets):
for componentIndex in range(numComponents):
coordComponentName = "F" + get_component(0, componentIndex).lower()
for realImagIndex in range(2):
if (realImagIndex == 0):
componentName = coordComponentName + "(real)"
else:
componentName = coordComponentName + "(imag)"
file.write(componentName)
if (setIndex == numFullModelSets-1 and componentIndex == numComponents-1 and realImagIndex == 1):
file.write("\n")
else:
file.write(",")
def ShowFinishMessage(app, wasCanceled):
message = "The csv file was created.\n"
message_jp = "CSVファイルが作成されました。"
if (wasCanceled==True):
message = "The csv file export was canceled.\n"
message_jp = "CSVファイル出力がキャンセルされました。"
confirmation = app.CreateDialogBox()
confirmation.SetTranslation(message, message_jp)
confirmation.AddLabel(message, 0, 2)
confirmation.SetCancelButtonVisible(False)
confirmation.Show()
main()


