#--------------------------------------------------------------------- #Name: d0025_nvh_surface_force_export.py #Menu-en: NVH Force Export (Surface Force) #Menu-ja: NVH用の電磁力出力(表面力) #Type: Python #Create: April 17, 2023 JSOL Corporation #Comment-en: Export toque and force to the CSV file for motor NVH. #Comment-ja: モータNVH用にトルク、電磁力をCSVファイル出力する。 #Copyright: (c) JSOL Corporation. All Rights Reserved. #--------------------------------------------------------------------- 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()