モータNVH用にトルク、電磁力をCSVファイル出力する。
import locale
import os
import designer
import math
from bisect import bisect_left
def CanUseScript():
app = designer.GetApplication()
studies = GetCanUseScriptStudies(app, False)
res = len(studies) > 0
return res
def GetCanUseScriptStudies(app, onlyHasResult):
model = app.GetCurrentModel()
study_list = []
if app.NumAnalysisGroups() > 0:
analysisGroup = app.GetCurrentAnalysisGroup()
designTable = analysisGroup.GetDesignTable()
start_study = app.GetCurrentStudy()
for i in range(analysisGroup.NumStudies()):
study = analysisGroup.GetStudy(i)
app.SetCurrentStudy(study.GetName())
if CanUseScriptModelStudy(model, study, designTable):
study_list.append(study)
app.SetCurrentStudy(start_study.GetName())
else:
study = app.GetCurrentStudy()
designTable = study.GetDesignTable()
if CanUseScriptModelStudy(model, study, designTable):
study_list.append(study)
if not onlyHasResult:
return study_list
has_result_list = []
for i in range(len(study_list)):
if study_list[i].AnyCaseHasResult():
has_result_list.append(study_list[i])
return has_result_list
def CanUseScriptModelStudy(model, study, designTable):
if (model.IsValid() == False):
debugShowErrorMessage_expr("No model.")
return False
if (study.IsValid() == False):
debugShowErrorMessage_expr("No study.")
return False
## Analysis Type Check
is2DTR = study.GetScriptTypeName() == "Transient2D"
is3DTR = study.GetScriptTypeName() == "Transient"
if ((not is2DTR) and (not is3DTR)):
debugShowErrorMessage_expr("Current study is unsupported analysis type.")
return False
## Motion Check
motion = get_valid_motion(study)
if motion is None:
debugShowErrorMessage_expr("Current study has no rotation motion condition with constant velocity.")
return False
caseIndexList = get_active_case_indices_expr(study)
## Pole Check
if has_invalid_pole_expr(designTable, caseIndexList):
debugShowErrorMessage_expr("There is the case that the parametric variable \"POLES\" does not exist or has an incorrect value.")
return False
## Torque Condition Check
torqueCond= findTorqueCondition_expr(study)
if (torqueCond is None):
debugShowErrorMessage_expr("Current study has no torque condition.")
return False
## Nodal Force Table Check
if is2DTR:
cd_R =findNodalForceCalculationDefinition_expr(study, "Radial")
cd_T =findNodalForceCalculationDefinition_expr(study, "Theta")
cd_X =findNodalForceCalculationDefinition_expr(study, "X")
cd_Y =findNodalForceCalculationDefinition_expr(study, "Y")
if (cd_R is None) or (cd_T is None) or (cd_X is None) or (cd_Y is None) :
debugShowErrorMessage_expr("NodalForce graph is not found.")
return False
elif is3DTR:
cd_R =findNodalForceCalculationDefinition_expr(study, "Radial")
cd_T =findNodalForceCalculationDefinition_expr(study, "Theta")
cd_X =findNodalForceCalculationDefinition_expr(study, "X")
cd_Y =findNodalForceCalculationDefinition_expr(study, "Y")
cd_Z =findNodalForceCalculationDefinition_expr(study, "Z")
if (cd_R is None) or (cd_T is None) or (cd_X is None) or (cd_Y is None) or (cd_Z is None) :
debugShowErrorMessage_expr("NodalForce graph is not found.")
return False
return True
CSV_VERSION = "1.0.0"
OUTPUT_FILE_PATH = "outputFilePath"
SET_PREFIX = "prefix"
TORQUE_COND_TITLE = "condition_title"
NUM_POLES = "numPoles"
COORD_TYPE = "coord_type"
USE_COPY_CYCLE = "use_copy_cycle"
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_designer():
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
torqueList = get_conditions(study, "Torque")
if (len(torqueList)<1):
message = "Current study has no torque condition."
message_jp = "現スタディはトルク条件がありません。"
show_error_message(message, message_jp)
return False
forceList = get_conditions(study, "Force")
if (len(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):
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)
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_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_16 = "Single File Including Torque(Force Coordinates=Cylindrical)[v22.2 and earlier]"
#label_16_jp = "トルクデータ含む1ファイル出力(節点力の座標系=円筒座標系)[v22.2以前の形式]"
#dialog.SetTranslation(label_16, label_16_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, 1)
dialog.AddLabel(label_2, 0, 1)
dialog.AddString(SET_PREFIX, "", "TOOTH", 1, 1)
dialog.AddLabel(label_3, 0, 1)
dialog.AddComboBox(TORQUE_COND_TITLE, "", torque_condition_title_list(app), 0, 1)
dialog.AddLabel(label_4, 0, 1)
dialog.AddInteger(NUM_POLES, "", 4, 1, 1)
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, 1)
dialog.AddLabel("", 0, 1)
dialog.AddLabel(label_12, 0, 1)
dialog.AddRadio(OUTPUT_FORMAT_TYPE, label_13, 0, 1)
#dialog.AddRadio(OUTPUT_FORMAT_TYPE, label_16, 1, 1)
dialog.AddRadio(OUTPUT_FORMAT_TYPE, label_14, 1, 1)
dialog.AddRadio(OUTPUT_FORMAT_TYPE, label_15, 2, 1)
dialog.AddLabel("", 0, 1)
dialog.AddLabel(label_9, 0, 1)
dialog.AddRadio(OUTPUT_CASE_TYPE, label_10, 0, 1)
dialog.AddRadio(OUTPUT_CASE_TYPE, label_11, 1, 1)
dialog.AddLabel("", 0, 1)
dialog.AddIntegerList(SPECIFIED_CASES, "", "1", 1, 1)
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 set by the specified prefix."
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
outputCaseType = parameters.GetValue(OUTPUT_CASE_TYPE)
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
hasNot1CycleStepCases = False
hasNot1CycleStepCases = check_has_not_1cycle_step_cases(app, parameters)
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, True)
elif (outputFormatType == 1):
output_time_domain_tooth_forces(app, dialog)
elif (outputFormatType == 2):
output_frequency_domain_tooth_forces(app, dialog)
def get_case_table(study, is2D, caseIndexList, nSet):
numTeethList = []
modelThicknessList = []
numSliceList = []
startCase = study.GetCurrentCase()
for i in range(len(caseIndexList)):
caseIndex = caseIndexList[i]
study.SetCurrentCase(caseIndex)
periodicity = get_periodicity(study)
numTeethList.append(nSet * periodicity)
if is2D:
modelThicknessList.append(study.GetStudyProperties().GetValueWithUnit("ModelThickness", "mm"))
else:
modelThicknessList.append(0.0)
if is2D and use_multi_slice(study):
numSliceList.append(get_slice_number(study))
else:
numSliceList.append(0)
study.SetCurrentCase(startCase)
return (numTeethList, modelThicknessList, numSliceList)
def output_single_file_including_torque(app, dialog, is100Format):
isJapanese = is_japanese(app)
is2D = (app.GetCurrentModel().GetDimension() == 2)
targetSetList = get_target_set(app.GetCurrentModel(), dialog)
study = app.GetCurrentStudy()
(caseIndexList, noResultCaseIndexList, speedList, avTorqList, startIndices, outX, outYT) = create_torque_data(app, dialog)
(numTeethList, modelThicknessList, numSliceList) = get_case_table(study, is2D, caseIndexList, len(targetSetList))
outputPath = dialog.GetValue(OUTPUT_FILE_PATH)
file = open(outputPath.decode('utf-8'), 'w')
if is100Format:
write_header_100(file, numTeethList[0], is2D, modelThicknessList[0], max(numSliceList) > 1 , numSliceList[0])
else:
write_header_110(file, is2D, caseIndexList, speedList, avTorqList, numTeethList, modelThicknessList, numSliceList)
write_torque(file, caseIndexList, speedList, avTorqList, outX, outYT, is100Format)
wasCanceled = write_force(file, app, dialog, caseIndexList, speedList, avTorqList, startIndices, outX, is100Format)
file.close()
ShowFinishMessage(app, wasCanceled)
def output_time_domain_tooth_forces(app, dialog):
## Get app data
isJap = is_japanese(app)
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)
thickness = 0
useMultiSlice = False
numSlice = 1
if (is2D):
thickness = targetStudy.GetStudyProperties().GetValueWithUnit("ModelThickness", "m")
useMultiSlice = use_multi_slice(targetStudy)
numSlice = get_slice_number(targetStudy)
if (useMultiSlice):
thickness = 1.0*thickness/numSlice
caseIndexList = get_case_index_list(dialog, targetStudy)
periodicity = get_periodicity(targetStudy)
needConvertTwice = (not is2D) and has_symmetry_boundary_on_XYPlane(targetStudy)
## Setup progress dialog
setup_progress(app, outputDimension, caseIndexList, numSlice, targetSetList)
wasCanceled = False
## Case loop
numCases = len(caseIndexList)
for caseLoopIndex in range(numCases):
caseIndex = caseIndexList[caseLoopIndex]
targetStudy.SetCurrentCase(caseIndex)
removedList = get_removed_node_list_on_boundary(targetStudy, targetSetList)
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, 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
partialModelF = []
for setIndex in range(len(targetSetList)):
eachSetF = []
## Component loop
for compIndex in range(outputDimension):
if (app.UserProgressWasCanceled()):
app.UserProgressFinish()
wasCanceled = True
break
##Setup probe
title = "Probe"
probe = create_probe(title, targetStudy, useMultiSlice, sliceIndex, isJap, coordType, compIndex)
[data, wasCanceled] = calc_force(targetStudy, removedList[setIndex], probe)
## 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 is2D:
lastCycleF = [f * thickness for f in lastCycleF]
##Add each component data
eachSetF.append(lastCycleF)
if (wasCanceled == False):
app.UserProgressStep()
targetStudy.DeleteProbe(title)
partialModelF.append(eachSetF)
fullModelF = []
##Add Time
fullModelF.append(timeData)
##Copy partial model teeth to full model
for i in range (periodicity):
if i==0:
fullModelF.append(partialModelF)
else:
rad = math.radians(360.0 * i / periodicity)
cos = math.cos(rad)
sin = math.sin(rad)
rotPartial = []
for setIndex in range(len(targetSetList)):
rotEachSet = []
rotfx = [cos * x - sin * y for x,y in zip(partialModelF[setIndex][0], partialModelF[setIndex][1])]
rotfy = [sin * x + cos * y for x,y in zip(partialModelF[setIndex][0], partialModelF[setIndex][1])]
rotEachSet.append(rotfx)
rotEachSet.append(rotfy)
rotEachSet.append(partialModelF[setIndex][2])
rotPartial.append(rotEachSet)
fullModelF.append(rotPartial)
##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
isJap = is_japanese(app)
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)
thickness = 0
useMultiSlice = False
numSlice = 1
if (is2D):
thickness = targetStudy.GetStudyProperties().GetValueWithUnit("ModelThickness", "m")
useMultiSlice = use_multi_slice(targetStudy)
numSlice = get_slice_number(targetStudy)
if (useMultiSlice):
thickness = 1.0*thickness/numSlice
caseIndexList = get_case_index_list(dialog, targetStudy)
periodicity = get_periodicity(targetStudy)
needConvertTwice = (not is2D) and has_symmetry_boundary_on_XYPlane(targetStudy)
## Setup progress dialog
setup_progress(app, outputDimension, caseIndexList, numSlice, targetSetList)
wasCanceled = False
## Case loop
numCases = len(caseIndexList)
for caseLoopIndex in range(numCases):
caseIndex = caseIndexList[caseLoopIndex]
targetStudy.SetCurrentCase(caseIndex)
removedList = get_removed_node_list_on_boundary(targetStudy, targetSetList)
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, 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)
## Each Tooth loop
partialModelF = []
freqData = []
for setIndex in range(len(targetSetList)):
eachSetF = []
## Component loop
for compIndex in range(outputDimension):
if (app.UserProgressWasCanceled()):
app.UserProgressFinish()
wasCanceled = True
break
## Setup probe
title = "Probe"
probe = create_probe(title, targetStudy, useMultiSlice, sliceIndex, isJap, coordType, compIndex)
dataSetTitle = "fft_for_nvf_force_export"
[fftDataSet, wasCanceled] = calc_force_with_FFT(dataManager, targetStudy, removedList[setIndex], probe, dataSetTitle, needConvertTwice, startIndex, is2D, thickness)
## Real/Imaginary Loop
numFFTColmuns = fftDataSet.GetCols()
if (numFFTColmuns < 3):
continue
for realImagIndex in range(1, numFFTColmuns):
data = list(fftDataSet.GetColumn(realImagIndex))
## Add each component data
eachSetF.append(data)
if (setIndex == 0 and compIndex == 0):
freqData = list(fftDataSet.GetColumn(0))
if (wasCanceled == False):
app.UserProgressStep()
targetStudy.DeleteProbe(title)
dataManager.DeleteDataSet(dataSetTitle)
partialModelF.append(eachSetF)
fullModelF = []
## Add Time/Frequency
fullModelF.append(freqData)
## Copy partial model teeth to full model
for i in range (periodicity):
if i==0:
fullModelF.append(partialModelF)
else:
rad = math.radians(360.0 * i / periodicity)
cos = math.cos(rad)
sin = math.sin(rad)
rotPartial = []
for setIndex in range(len(targetSetList)):
rotEachSet = []
rotfxr = [cos * x - sin * y for x,y in zip(partialModelF[setIndex][0], partialModelF[setIndex][2])]
rotfyr = [sin * x + cos * y for x,y in zip(partialModelF[setIndex][0], partialModelF[setIndex][2])]
rotfxi = [cos * x - sin * y for x,y in zip(partialModelF[setIndex][1], partialModelF[setIndex][3])]
rotfyi = [sin * x + cos * y for x,y in zip(partialModelF[setIndex][1], partialModelF[setIndex][3])]
rotEachSet.append(rotfxr)
rotEachSet.append(rotfxi)
rotEachSet.append(rotfyr)
rotEachSet.append(rotfyi)
rotEachSet.append(partialModelF[setIndex][4])
rotEachSet.append(partialModelF[setIndex][5])
rotPartial.append(rotEachSet)
fullModelF.append(rotPartial)
## Write TOOTH value of full model
WriteByAllComponentsInSetForOneCase(file, fullModelF)
file.close()
app.UserProgressFinish()
ShowFinishMessage(app, wasCanceled)
def write_header_100(file, numTeeth, is2D, modelThickness, useMultiSlice, numSlice):
dimString = ""
if (is2D):
dimString = "2D"
else:
dimString = "3D"
write_line2(file, "CSV Version", "1.0.0")
write_line2(file, "Dimension", dimString)
write_line2(file, "Coordinate", get_coordName(1))
write_line2(file, "Teeth", str(numTeeth))
if (is2D):
write_line2(file, "StackLength(mm)", str(modelThickness))
if useMultiSlice:
write_line2(file, "Slice", str(numSlice))
else:
write_line2(file, "Slice", "1")
file.write("\n")
def write_header_110(file, is2D, caseIndexList, speedList, avTorqList, numTeethList, modelThicknessList, numSliceList):
dimString = ""
if (is2D):
dimString = "2D"
else:
dimString = "3D"
write_line2(file, "CSV Version", "1.1.0")
write_line2(file, "Dimension", dimString)
write_line2(file, "Coordinate", get_coordName(1))
write_line2(file, "Number of Cases", str(len(caseIndexList)))
file.write("\n")
write_line(file, "*Case Table")
file.write("Case,Speed(RPM),Torque(Nm),Teeth,StackLength(mm),Slice\n")
for i in range(len(caseIndexList)):
line = str(caseIndexList[i] + 1)
line += "," + str(speedList[i])
line += "," + str(avTorqList[i])
line += "," + str(numTeethList[i])
line += "," + str(modelThicknessList[i])
line += "," + str(numSliceList[i])
write_line(file, line)
file.write("\n")
def write_header(file, app, dialog):
targetModel = app.GetCurrentModel()
targetStudy = app.GetCurrentStudy()
is2D = (targetModel.GetDimension()==2)
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)
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)
write_line2(file, "Teeth", str(numTeeth))
if (is2D):
write_line2(file, "StackLength(mm)", str(modelThickness))
write_line2(file, "Slice", str(numSlice))
file.write("\n")
def calc_ave_torque(lastCycleTorq):
return sum(lastCycleTorq[1:]) / (len(lastCycleTorq)-1)
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 = calc_ave_torque(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, caseIndexList, speed, aveTorq, outX, outYT, is100Format):
##Write torque header
write_line(file, "*Torque")
##Write torque data per case
for i in range(len(caseIndexList)):
if is100Format:
write_line2(file, "Speed(RPM)", str(speed[i]))
write_line2(file, "Torque(Nm)", str(aveTorq[i]))
else:
write_line2(file, "Case", str(caseIndexList[i] + 1))
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, is100Format):
##Get Study value
targetModel = app.GetCurrentModel()
targetStudy = app.GetCurrentStudy()
isJap = is_japanese(app)
is2D = (targetModel.GetDimension()==2)
thickness = 0
if (is2D):
thickness = targetStudy.GetStudyProperties().GetValueWithUnit("ModelThickness", "m")
periodicity = get_periodicity(targetStudy)
useMultiSlice = use_multi_slice(targetStudy)
numSlice = 1
if (useMultiSlice):
numSlice = get_slice_number(targetStudy)
thickness = 1.0*thickness/numSlice
needConvertTwice = (not is2D) and has_symmetry_boundary_on_XYPlane(targetStudy)
##Get dialog parameters
useElectricCycle = dialog.GetValue(USE_COPY_CYCLE)
numPoles = dialog.GetValue(NUM_POLES)
coordType = 1 # Fixed to cylindrical in V18.1
##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()
##Setup progress dialog
setup_progress(app, dimension, caseIndexList, numSlice, targetSetList)
wasCanceled = False
componentLabels = ["Radius", "Theta", "Z"]
for compIndex in range(dimension):
if is100Format:
write_line2(file, "*Force", str(compIndex+1))
elif (not is100Format) and compIndex == 0:
write_line(file, "*Force")
for outputIndex in range(len(caseIndexList)):
caseIndex = caseIndexList[outputIndex]
targetStudy.SetCurrentCase(caseIndex)
##Get nodeIds on each set
removedList = get_removed_node_list_on_boundary(targetStudy, targetSetList)
if is100Format:
write_line2(file, "Speed(RPM)", str(speedList[outputIndex]))
write_line2(file, "Torque(Nm)", str(avTorqList[outputIndex]))
else:
write_line2(file, "Case", str(caseIndex + 1))
write_line2(file, "Component", str(componentLabels[compIndex]))
fullModelF=[]
for sliceIndex in range(numSlice):
##Set probe
title = "Probe"
probe = create_probe(title, targetStudy, useMultiSlice, sliceIndex, isJap, coordType, compIndex)
##Calculate TOOTH value
partialModelF = []
for setIndex in range(len(targetSetList)):
if (app.UserProgressWasCanceled()):
app.UserProgressFinish()
file.close()
return True
[data, wasCanceled] = calc_force(targetStudy, removedList[setIndex], probe)
##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 2D model times thickness (How about multi-slice model?)
if is2D:
lastCycleF = [f * thickness for f in lastCycleF]
##Add each set data
partialModelF.append(lastCycleF)
if (wasCanceled == False):
app.UserProgressStep()
##Copy partial model teeth to full model
for i in range (periodicity):
for j in range (len(targetSetList)):
fullModelF.append(partialModelF[j])
targetStudy.DeleteProbe(title)
if (wasCanceled):
file.close()
return True
##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")
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_lineList(file, str1, numList):
line = str1
for i in range(len(numList)):
line += ("," + str(numList[i]))
file.write(line)
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")
for cond in torqueList:
result.append(cond.GetName())
return result
def get_periodicity(targetStudy):
cond = get_first_condition(targetStudy, "RotationPeriodicBoundary")
if (not cond is None) and (cond.IsValid()) and (not cond.GetValue("AutoPeriodicFromWinding")):
return 360//int(cond.GetValue(u"Angle"))
designTable = targetStudy.GetDesignTable()
if designTable.HasEquation("MODEL_DIVISION"):
modelDiv = designTable.GetEquation("MODEL_DIVISION").GetValue()
if modelDiv > 0:
return modelDiv
if designTable.HasEquation("POLES") and designTable.HasEquation("SLOTS"):
poles = int(designTable.GetEquation("POLES").GetValue())
slots = int(designTable.GetEquation("SLOTS").GetValue())
if poles > 0 and slots > 0:
return math.gcd(poles, slots)
return 1
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 index1):
tmp = list(dataProbe.GetColumn(1))
if (i==0):
result = tmp
else :
result = [x+y for (x,y) in zip(result, tmp)]
return (result, wasCanceled)
def calc_force_with_FFT(dataManager, targetStudy, removed, probe, dataSetTitle, needConvertTwice, startIndex, is2D, thickness):
wasCanceled = False
forceData = []
##Set probe on the nodeIds
if (len(removed)<1):
return (probe.GetDataSet(), wasCanceled)
tmp = []
for i in range(len(removed)):
if (app.UserProgressWasCanceled()):
wasCanceled = True
return (probe.GetDataSet(), wasCanceled)
id = removed[i]
probe.ClearPoints()
probe.SetId(0, id)
probe.RenamePoint(0, "Node_"+str(id))
probe.Build()
dataProbe = probe.GetDataSet()
##Sum on all nodes
if (dataProbe.GetCols()>1):
tmp = list(dataProbe.GetColumn(1))
if (i==0):
forceData = tmp
else :
forceData = [x+y for (x,y) in zip(forceData, tmp)]
## Considering 1/2 model lengthwise if symmetry boundary is set on XY plane
convertedForceData = convert_twice(needConvertTwice, forceData)
## Get last 1 cycle data
lastCycleF = convertedForceData[startIndex:]
timeData = list(dataProbe.GetColumn(0))
lastCycleT = timeData[startIndex:]
## If 2D model times thickness
if is2D:
lastCycleF = [f * thickness for f in lastCycleF]
xData = lastCycleT
yData = lastCycleF
xyPairList = []
xyPair = []
for i in range(len(xData)):
xyPair = [xData[i],yData[i]]
xyPairList.append(xyPair)
dataSet = dataManager.CreateFromDataSet(dataSetTitle, "xtitle", "ytitle", xyPairList)
fftDataSet = dataManager.CreateFFT(dataSet, 0, "RealAndImaginary", 0, xData[0], xData[-1])
return (fftDataSet, wasCanceled)
def remove_nodes_on_boundary(study, nodeIds):
condList = get_conditions(study, "RotationPeriodicBoundary")
if (len(condList)==0):
return nodeIds
result = []
cond = condList[0]
for id in nodeIds:
if (cond.NodeIsOnTarget(id)==False):
result.append(id)
return result
def get_first_condition(study, condScriptTypeName):
for i in range(study.NumConditions()):
cond = study.GetCondition(i)
typeName = cond.GetScriptTypeName()
if (typeName == condScriptTypeName):
return cond
return None
def get_conditions(study, condScriptTypeName):
result = []
for i in range(study.NumConditions()):
cond = study.GetCondition(i)
typeName = cond.GetScriptTypeName()
if (typeName == condScriptTypeName):
result.append(cond)
return result
def use_multi_slice(study):
condList = get_ms_conditions(study)
return len(condList) > 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 = []
prefix = dialog.GetValue(SET_PREFIX).decode('utf-8')
setList = targetModel.GetSetList()
if (setList.IsValid() == False):
return targetSetList
for i in range(setList.NumSet()):
set = setList.GetSet(i)
if set.IsValid():
setName = set.GetName()
if sys.version_info.major == 2:
setName = setName.decode('utf-8')
if setName.startswith(prefix):
targetSetList.append(set)
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_on_XYPlane(study):
condList = get_conditions(study, "SymmetryBoundary")
for symmetry in condList:
if 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 check_has_not_1cycle_step_cases(app, parameters):
result = False
useElectricCycle = parameters.GetValue(USE_COPY_CYCLE)
numPoles = parameters.GetValue(NUM_POLES)
targetStudy = app.GetCurrentStudy()
torqResultName = get_torq_result_name(app)
caseIndexList = get_case_index_list(parameters, targetStudy)
for caseIndex in caseIndexList:
if (targetStudy.CaseHasResult(caseIndex) == False):
continue
##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 get_removed_node_list_on_boundary(targetStudy, targetSetList):
removedList = []
for curset in targetSetList:
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
removedList.append(remove_nodes_on_boundary(targetStudy, nodeIds))
return removedList
def create_file_name(originalFilePath, numCases, caseNo, useMultiSlice, sliceNo):
if (useMultiSlice):
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, targetSetList):
progressLabel = "Exporting to CSV File..."
if (is_japanese(app)):
progressLabel = "CSVファイルへ出力中..."
app.SetupUserProgress(progressLabel)
app.SetUserProgressUseCancel(True)
maxSteps = dimension * len(caseIndexList) * numSlice * len(targetSetList)
app.SetUserProgressMaxSteps(maxSteps)
app.UserProgressStart()
def create_probe(title, targetStudy, useMultiSlice, sliceIndex, isJap, coordType, compIndex):
probe = targetStudy.CreateProbe(title)
probe.SetAutoRecalculate(False)
subTitle = ""
if (useMultiSlice):
if (isJap):
subTitle = " <断面 " + str(sliceIndex+1) + ">"
else:
subTitle = " "
probe.SetResultType("NodalForce", subTitle)
probe.SetResultCoordinate(get_coordName(coordType))
probe.SetComponent(get_component(coordType, compIndex))
probe.ClearPoints()
probe.SetProbeType(1)
probe.SetUseElementValue(True)
probe.SetMoveWithPart(True)
return probe
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 periodicIndex in range(len(fullModelF)):
if (periodicIndex == 0): # 0 is time column
file.write(str(fullModelF[periodicIndex][timeIndex]))
file.write(",")
else:
for eachSetIndex in range(len(fullModelF[periodicIndex])):
for eachCompIndex in range(len(fullModelF[periodicIndex][eachSetIndex])):
file.write(str(fullModelF[periodicIndex][eachSetIndex][eachCompIndex][timeIndex]))
if (periodicIndex == len(fullModelF)-1 and eachSetIndex == len(fullModelF[periodicIndex])-1 and eachCompIndex == len(fullModelF[periodicIndex][eachSetIndex])-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()
#---------------------------------------------------------------
# for express
#---------------------------------------------------------------
SCENARIO_TITLE_expr = "scnario_title"
CSV_VERSION_expr = "1.1.0"
def get_valid_motion(study):
motionList = get_conditions(study, "RotationMotion")
if (len(motionList)<1):
return False
for i in range(len(motionList)):
motion_type = motionList[i].GetValue("MotionGroupType")
if motion_type == 0:
return motionList[i]
return None
def has_zero_speed_expr(study, caseIndexList):
startCase = study.GetCurrentCase()
res = False
for i in range(len(caseIndexList)):
caseIndex = caseIndexList[i]
study.SetCurrentCase(caseIndex)
speed = get_speed(study)
if (speed==0.0):
res = True
break
study.SetCurrentCase(startCase)
return res
def getPoleParametricEquation_expr(designTable):
return designTable.GetEquation("POLES")
def has_invalid_pole_expr(designTable, caseIndexList):
if not designTable.HasEquation("POLES"):
return True
poleParametricEquation = getPoleParametricEquation_expr(designTable)
if (poleParametricEquation is None) or (not poleParametricEquation.IsValid()):
return True
for i in range(len(caseIndexList)):
if poleParametricEquation.GetValue(caseIndexList[i]) < 1:
return True
return False
def get_pole_expr(designTable, caseIndex):
poleParametricEquation = getPoleParametricEquation_expr(designTable)
return int(poleParametricEquation.GetValue(caseIndex))
def get_slot_expr(designTable, caseIndex):
if designTable.HasEquation("SLOTS"):
return int(designTable.GetEquation("SLOTS").GetValue(caseIndex))
else:
return 0
def findNodalForceCalculationDefinition_expr(study, component):
n = study.NumCalculationDefinitions()
for i in range(n):
calc_def = study.GetCalculationDefinition(i)
if (calc_def.GetResultType() != "NodalForce"):
continue
calc_def_compo = calc_def.GetComponent()
if (calc_def.GetComponent() == component):
return calc_def
return None
def getTargetTorqueResultName_expr(isMultiSlice, isJapanese):
if not isMultiSlice:
return "Torque"
elif isJapanese:
return "トルク <モデル全体>"
else:
return "Torque "
def checkTargetTorqueConditionTitle_expr(condName):
targetTorqueConditionTitleJp = "トルク"
targetTorqueConditionTitleEn = "Torque"
targetTorqueConditionTitleUtf8 = (b'\xe3\x83\x88\xe3\x83\xab\xe3\x82\xaf').decode('utf-8')
if condName == targetTorqueConditionTitleJp:
return True
elif condName == targetTorqueConditionTitleEn:
return True
elif condName ==targetTorqueConditionTitleUtf8:
return True
return False
def findTorqueCondition_expr(study):
torqConditions = get_conditions(study, "Torque")
for i in range(len(torqConditions)):
condName = torqConditions[i].GetName()
if checkTargetTorqueConditionTitle_expr(condName):
return torqConditions[i]
return None
def findTorqueDataSet_expr(study, caseIndex, isJapanese):
isMultiSlice = not (get_first_condition(study, "MultiSlice") is None)
torqResultName = getTargetTorqueResultName_expr(isMultiSlice, isJapanese)
dataSet = study.GetDataSet(torqResultName, caseIndex+1)
if (dataSet is None):
return [None, -1]
elif (not dataSet.IsValid()):
return [None, -1]
for i in range(dataSet.GetCols()):
column_name = dataSet.GetColumnName(i)
if checkTargetTorqueConditionTitle_expr(column_name):
return [dataSet, i]
return [None, -1]
def debugShowErrorMessage_expr(message):
#debug.Print(message)
#show_error_message(message, message)
return
def copy_cycles_expr(originalData, numExtendCycle):
result = []
for i in range(numExtendCycle):
if (i == 0):
result.extend(originalData)
else:
result.extend(originalData[1:])
return result
def extend_cycles_expr(timeData, numExtendCycle):
result = []
incremental = timeData[-1] - timeData[0]
for i in range(numExtendCycle):
if (i == 0):
result.extend(timeData)
else:
ext = timeData[1:]
ext = [t + incremental * i for t in ext]
result.extend(ext)
return result
def get_1_cycle_time_expr(speed, numPoles, useElectricCycle):
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 find_nearest_index(fullTime, startTime):
index = bisect_left(fullTime, startTime)
if index==0:
return 0
if index == len(fullTime):
return len(fullTime) - 1
prev = startTime - fullTime[index-1]
tmp = fullTime[index] - startTime
if prev <= tmp:
return index-1
else:
return index
def getUseElectricCycleCheckBoxLabel_expr(isJapanese):
if isJapanese:
return "電気角1周期分または1/2周期分をコピーして機械角1周期分にする"
else:
return "Copy 1 or 1/2 electrical cycle to mechanical cycle"
def get_last_cycle_start_index_expr(speed, numPoles, useElectricCycle, fullTime):
##Calculate 1 electric cycle time from rotation speed
full_time_range = fullTime[-1] - fullTime[0]
cycle_time = get_1_cycle_time_expr(speed, numPoles, useElectricCycle)
lastCycleStartTime = 0.0
numExtendCycle = 1
if useElectricCycle:
isFullCycle = (full_time_range > cycle_time - EPSILON)
isHalfCycle = ((not isFullCycle) and full_time_range > cycle_time/2 - EPSILON)
if isFullCycle:
lastCycleStartTime = fullTime[-1] - cycle_time
numExtendCycle = numPoles//2
elif isHalfCycle:
lastCycleStartTime = fullTime[-1] - cycle_time / 2.0
numExtendCycle = numPoles//2 * 2
else:
message = "Insufficient number of result time steps. The file output must have more than the half cycle electrical angle time step number. Please check the results of the specified cases."
message_jp = "結果の時間ステップ数が不十分です。ファイル出力には半周期電気角分の時間ステップ数以上の結果が必要です。指定ケースの結果を見直してください。"
show_error_message(message, message_jp)
return (-1, 0)
else:
if (full_time_range > cycle_time - EPSILON):
lastCycleStartTime = fullTime[-1] - cycle_time
numExtendCycle = 1
else:
message = "Insufficient number of result time steps. The file output must have more than one cycle mechanical angle time step number.\n"\
"If the target scenario is torque ripple or the custom scenario that calculates more than half a period of electrical angles,\n"\
"Please check the box ["+getUseElectricCycleCheckBoxLabel_expr(False) +"]."
message_jp = "結果の時間ステップ数が不十分です。ファイル出力には1周期機械角分の時間ステップ数以上の結果が必要です。\n"\
"対象シナリオがトルクリップルまたは電気角半周期分以上を計算しているカスタムシナリオの場合、\n"\
"["+getUseElectricCycleCheckBoxLabel_expr(True) + "]にチェックを入れてください。"
show_error_message(message, message_jp)
return (-1, 0)
index = find_nearest_index(fullTime, lastCycleStartTime)
return (index, numExtendCycle)
def create_torque_data_expr(study, designTable, useElectricCycle, caseIndexList, isJapanese):
##Initialize
speedList = []
avTorqList = []
startIndices = []
numExtendCycleList = []
insufficientResultCaseIndexList = []
outX = []
outYT = []
startCase = study.GetCurrentCase()
##Create each case data
for caseIndex in caseIndexList:
if check_progress_wascanceled_expr(app):
break
if (study.CaseHasResult(caseIndex) == False):
insufficientResultCaseIndexList.append(caseIndex)
continue
study.SetCurrentCase(caseIndex)
speed = get_speed(study)
numPoles = get_pole_expr(designTable, caseIndex)
##Calculate 1 electric or mechanical cycle time from rotation speed
T = get_1_cycle_time_expr(speed, numPoles, useElectricCycle)
##Get torque data for 1 last cycle
lastCycleTorq = []
[dataset, torqueColumn]= findTorqueDataSet_expr(study, caseIndex, isJapanese)
time = list(dataset.GetColumn(0))
torque = list(dataset.GetColumn(torqueColumn))
(start_index, numExtendCycle) = get_last_cycle_start_index_expr(speed, numPoles, useElectricCycle, time)
if start_index < 0:
insufficientResultCaseIndexList.append(caseIndex)
break
lastCycleTorq = torque[start_index:]
##Calculate average torque
aveTorq = calc_ave_torque(lastCycleTorq)
##Copy 1 electric cycle to 1 mechanical cycle
if numExtendCycle > 1:
lastCycleTorq = copy_cycles_expr(lastCycleTorq, numExtendCycle)
##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(start_index)
numExtendCycleList.append(numExtendCycle)
outX.append(angleData)
outYT.append(lastCycleTorq)
study.SetCurrentCase(startCase)
return (caseIndexList, insufficientResultCaseIndexList, speedList, avTorqList, startIndices, numExtendCycleList, outX, outYT)
def get_thickness_factor_expr(study, dimension, numSlice):
thickness_factor = 1.0
#if (dimension == 2):
# thickness_factor = study.GetStudyProperties().GetValueWithUnit("ModelThickness", "m")
#else:
# if (has_symmetry_boundary_on_XYPlane(study)):
# thickness_factor = 2.0
#if (numSlice > 1):
# thickness_factor /= numSlice
return thickness_factor
def create_partial_force_data_expr(study, componentKey, lastCycleStartIndex, numExtendCycle):
##Create data for selected component and selected case
dataTable =findNodalForceCalculationDefinition_expr(study, componentKey).GetDataSet()
rows = dataTable.GetRows()
nSet = dataTable.GetCols() - 1
partialModelF=[]
##Calculate TOOTH value
for setIndex in range(nSet):
lastCycleF = []
##Get last 1 cycle data
for i in range(lastCycleStartIndex, rows):
lastCycleF.append(dataTable.GetValue(i, setIndex+1))
##Copy 1 electric cycle to 1 mechanical cycle
if numExtendCycle > 1:
lastCycleF = copy_cycles_expr(lastCycleF, numExtendCycle)
##Add each set data
partialModelF.append(lastCycleF)
return partialModelF
def create_fft_force_data_expr(study, dataManager, componentKey, dimension, lastCycleStartIndex):
##Create data for selected component and selected case
dataTable =findNodalForceCalculationDefinition_expr(study, componentKey).GetDataSet()
rows = dataTable.GetRows()
lastCycleTF = []
for i in range(lastCycleStartIndex, rows):
lastCycleTF.append([dataTable.GetValue(i, 0)])
tmin = lastCycleTF[0][0]
tmax = lastCycleTF[-1][0]
nSet = dataTable.GetCols() - 1
freqList=[]
dataSetTitle = "fft_for_nvf_force_export"
##Calculate TOOTH value
partialModelRealF = []
partialModelImageF = []
for setIndex in range(nSet):
# update lastCycleTF
for i in range(lastCycleStartIndex, rows):
lastCycleTF[i-lastCycleStartIndex].append(dataTable.GetValue(i, setIndex+1))
dataSetTF = dataManager.CreateFromDataSet(dataSetTitle, "xtitle", "ytitle", lastCycleTF)
for i in range(1, dataSetTF.GetCols()):
fftDataSet = dataManager.CreateFFT(dataSetTF, i-1, "RealAndImaginary", 0, tmin, tmax)
if len(freqList)==0:
freqList = fftDataSet.GetColumn(0)
partialModelRealF.append(fftDataSet.GetColumn(1))
partialModelImageF.append(fftDataSet.GetColumn(2))
dataManager.DeleteDataSetObject(fftDataSet)
dataManager.DeleteDataSetObject(dataSetTF)
return (freqList, partialModelRealF, partialModelImageF)
def create_time_data_expr(speed, numPoles, useElectricCycle, dataSetForHeader):
fullTimeData = dataSetForHeader.GetColumn(0)
(lastCycleStartIndex, numExtendCycle) = get_last_cycle_start_index_expr(speed, numPoles, useElectricCycle, fullTimeData)
oneCycleTimeData = fullTimeData[lastCycleStartIndex:]
if numExtendCycle > 1:
oneCycleTimeData = extend_cycles_expr(oneCycleTimeData, numExtendCycle)
return (lastCycleStartIndex, numExtendCycle, oneCycleTimeData)
def write_format1_force_expr(file, study, designTable, dimension, useElectricCycle, caseIndexList, speedList, avTorqList, startIndices, numExtendCycleList, outX, is100Format):
##Get Study value
startCase = study.GetCurrentCase()
##Write data for each component
componentKeys = ["Radial", "Theta", "Z"]
componentLabels = ["Radius", "Theta", "Z"]
for compIndex in range(dimension):
if check_progress_wascanceled_expr(app):
break
if is100Format:
write_line2(file, "*Force", str(compIndex+1))
elif (not is100Format) and compIndex == 0:
write_line(file, "*Force")
componentKey = componentKeys[compIndex]
##Write data for each case
for outputIndex in range(len(caseIndexList)):
if check_progress_wascanceled_expr(app):
break
else:
app.UserProgressStep()
caseIndex = caseIndexList[outputIndex]
lastCycleStartIndex = startIndices[outputIndex]
numExtendCycle = numExtendCycleList[outputIndex]
study.SetCurrentCase(caseIndex)
slots = get_slot_expr(designTable, caseIndex)
partialModelF = create_partial_force_data_expr(study, componentKey, lastCycleStartIndex, numExtendCycle)
periodicity = slots // len(partialModelF)
fullModelF = partialModelFToFullModelFWithCopy_expr(partialModelF, periodicity)
if is100Format:
write_line2(file, "Speed(RPM)", str(speedList[outputIndex]))
write_line2(file, "Torque(Nm)", str(avTorqList[outputIndex]))
else:
write_line2(file, "Case", str(caseIndex + 1))
write_line2(file, "Component", str(componentLabels[compIndex]))
##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")
study.SetCurrentCase(startCase)
def get_active_case_indices_expr(study):
designTable = study.GetDesignTable()
numCase = designTable.NumCases()
caseIndexList = []
for i in range(numCase):
if designTable.IsActive(i) and study.CaseHasResult(i):
caseIndexList.append(i)
return caseIndexList
def get_param_from_input_dialog_expr(app):
dialog = app.CreateDialogBox()
scenario_titles = [s.GetName() for s in GetCanUseScriptStudies(app, True)]
setup_param_input_dialog_expr(dialog, scenario_titles)
dialogShowResponse = dialog.Show()
useElectricCycle = dialog.GetValue(USE_COPY_CYCLE)
outputPath = dialog.GetValue(OUTPUT_FILE_PATH)
outputFormatType = dialog.GetValue(OUTPUT_FORMAT_TYPE)
selectedStudyListIndex = dialog.GetValue(SCENARIO_TITLE_expr)
return (dialogShowResponse, selectedStudyListIndex, useElectricCycle, outputPath, outputFormatType)
def setup_param_input_dialog_expr(dialog, scenario_titles):
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_3 = "Target:"
label_3_jp = "対象:"
dialog.SetTranslation(label_3, label_3_jp)
label_8 = getUseElectricCycleCheckBoxLabel_expr(False)
label_8_jp = getUseElectricCycleCheckBoxLabel_expr(True)
dialog.SetTranslation(label_8, label_8_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_16 = "Single File Including Torque(Force Coordinates=Cylindrical)[v22.2 and earlier]"
#label_16_jp = "トルクデータ含む1ファイル出力(節点力の座標系=円筒座標系)[v22.2以前の形式]"
#dialog.SetTranslation(label_16, label_16_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, 1)
dialog.AddLabel(label_3, 0, 1)
dialog.AddComboBox(SCENARIO_TITLE_expr, "", scenario_titles, 0, 1)
dialog.AddCheckBox(USE_COPY_CYCLE, label_8, True, 1, 1)
dialog.AddLabel("", 0, 1)
dialog.AddLabel(label_12, 0, 1)
dialog.AddRadio(OUTPUT_FORMAT_TYPE, label_13, 0, 1)
#dialog.AddRadio(OUTPUT_FORMAT_TYPE, label_16, 1, 1)
dialog.AddRadio(OUTPUT_FORMAT_TYPE, label_14, 1, 1)
dialog.AddRadio(OUTPUT_FORMAT_TYPE, label_15, 2, 1)
def get_case_table_expr(study, designTable, is2D, caseIndexList):
numTeethList = []
modelThicknessList = []
numSliceList = []
startCase = study.GetCurrentCase()
for i in range(len(caseIndexList)):
caseIndex = caseIndexList[i]
study.SetCurrentCase(caseIndex)
slots = get_slot_expr(designTable, caseIndex)
numTeethList.append(slots)
if is2D:
modelThicknessList.append(study.GetStudyProperties().GetValueWithUnit("ModelThickness", "mm"))
else:
modelThicknessList.append(0.0)
if is2D and use_multi_slice(study):
numSliceList.append(get_slice_number(study))
else:
numSliceList.append(0)
study.SetCurrentCase(startCase)
return (numTeethList, modelThicknessList, numSliceList)
def getStudyAndDesignTable_expr(app, selectedStudyListIndex):
study = GetCanUseScriptStudies(app, True)[selectedStudyListIndex]
if app.NumAnalysisGroups() > 0:
return (study, app.GetCurrentAnalysisGroup().GetDesignTable())
else:
return (study, study.GetDesignTable())
def output_single_file_including_torque_expr(app, selectedStudyListIndex, useElectricCycle, outputPath, is100Format):
isJapanese = is_japanese(app)
dimension = app.GetCurrentModel().GetDimension()
is2D = (dimension == 2)
startStudy = app.GetCurrentStudy()
(study, designTable) = getStudyAndDesignTable_expr(app, selectedStudyListIndex)
app.SetCurrentStudy(study.GetName())
caseIndexList = get_active_case_indices_expr(study)
start_progress_expr(app, len(caseIndexList) * dimension)
(caseIndexList, insufficientResultCaseIndexList, speedList, avTorqList, startIndices, numExtendCycleList, outX, outYT) = create_torque_data_expr(study, designTable, useElectricCycle, caseIndexList, isJapanese)
if len(insufficientResultCaseIndexList) > 0:
return False
if check_progress_wascanceled_expr(app):
return False
(numTeethList, modelThicknessList, numSliceList) = get_case_table_expr(study, designTable, is2D, caseIndexList)
if check_progress_wascanceled_expr(app):
return False
result = True
try:
file = open(outputPath.decode('utf-8'), 'w')
if is100Format:
write_header_100(file, numTeethList[0], is2D, modelThicknessList[0], max(numSliceList) > 1 , numSliceList[0])
else:
write_header_110(file, is2D, caseIndexList, speedList, avTorqList, numTeethList, modelThicknessList, numSliceList)
if not check_progress_wascanceled_expr(app):
write_torque(file, caseIndexList, speedList, avTorqList, outX, outYT, is100Format)
if not check_progress_wascanceled_expr(app):
write_format1_force_expr(file, study, designTable, dimension, useElectricCycle, caseIndexList, speedList, avTorqList, startIndices, numExtendCycleList, outX, is100Format)
file.close()
except Exception as e:
app.UserProgressFinish()
show_error_message(str(e), str(e))
result = False
app.SetCurrentStudy(startStudy.GetName())
return result
def getColumnTitles(calcDefForHeader, periodicity):
dataSetForHeader =calcDefForHeader.GetDataSet()
n_set = dataSetForHeader.GetCols() - 1
titles = []
isAllDefault = True
isSequencial = True
setName0 = dataSetForHeader.GetColumnName(1)
tmpPrefix = ""
if len(setName0) > 1:
tmpPrefix = setName0[0:-1]
for setIndex in range(n_set):
setName = dataSetForHeader.GetColumnName(setIndex+1)
titles.append(setName)
if isAllDefault:
if setName!="合計" and setName!="Sum":
isAllDefault = False
if isSequencial:
sequencialName = tmpPrefix + str(setIndex+1)
if setName != sequencialName:
isSequencial = False
if isAllDefault:
titles = []
prefix = "SET"
if calcDefForHeader.NumSets() > 0:
prefix = calcDefForHeader.GetSet(0).GetName()
for i in range(n_set * periodicity):
titles.append(prefix + str(i+1))
elif isSequencial:
titles = []
for i in range(n_set * periodicity):
titles.append(tmpPrefix + str(i+1))
else:
for periodicityIndex in range(1, periodicity):
for setIndex in range(n_set):
titles.append(titles[setIndex] + "_" + str(periodicityIndex))
return titles
def partialModelFToFullModelFWithCopy_expr(partialModelF, periodicity):
fullModelF = []
for periodicIndex in range(periodicity):
fullModelF.extend(partialModelF)
return fullModelF
def partialModelFToFullModelFWithRotate_expr(partialModelF_X, partialModelF_Y, periodicity):
n_set = len(partialModelF_X)
fullModelF_X = partialModelF_X
fullModelF_Y = partialModelF_Y
for periodicIndex in range(1, periodicity):
rad = math.radians(360.0 * periodicIndex / periodicity)
cos = math.cos(rad)
sin = math.sin(rad)
for setIndex in range(n_set):
rotfx = [cos * x - sin * y for x,y in zip(partialModelF_X[setIndex], partialModelF_Y[setIndex])]
rotfy = [sin * x + cos * y for x,y in zip(partialModelF_X[setIndex], partialModelF_Y[setIndex])]
fullModelF_X.append(rotfx)
fullModelF_Y.append(rotfy)
return (fullModelF_X, fullModelF_Y)
def output_time_domain_tooth_forces_expr(app, selectedStudyListIndex, useElectricCycle, outputPath):
isJapanese = is_japanese(app)
dimension = app.GetCurrentModel().GetDimension()
startStudy = app.GetCurrentStudy()
(study, designTable) = getStudyAndDesignTable_expr(app, selectedStudyListIndex)
app.SetCurrentStudy(study.GetName())
caseIndexList = get_active_case_indices_expr(study)
coordType = 0 # Fixed to Global Rectangular
#targetSetList = get_target_set(targetModel, dialog)
#setPrefix = dialog.GetValue(SET_PREFIX).decode('utf-8')
## Setup parameters
useMultiSlice = False
numSlice = 1
if (dimension==2):
numSlice = get_slice_number(study)
useMultiSlice = numSlice > 1
## Case loop
result = True
startCase = study.GetCurrentCase()
numCases = len(caseIndexList)
start_progress_expr(app, numCases)
for caseLoopIndex in range(numCases):
if check_progress_wascanceled_expr(app):
break
else:
app.UserProgressStep()
caseIndex = caseIndexList[caseLoopIndex]
study.SetCurrentCase(caseIndex)
##Get last 1 cycle times
calcDefForHeader = findNodalForceCalculationDefinition_expr(study, "X")
dataSetForHeader = calcDefForHeader.GetDataSet()
n_set = dataSetForHeader.GetCols() - 1
speed = get_speed(study)
numPoles = get_pole_expr(designTable, caseIndex)
numSlots = get_slot_expr(designTable, caseIndex)
periodicity = numSlots//n_set
(lastCycleStartIndex, numExtendCycle, oneCycleTimeData) = create_time_data_expr(speed, numPoles, useElectricCycle, dataSetForHeader)
if lastCycleStartIndex < 0:
result = False
break
partialModelF_X = create_partial_force_data_expr(study, "X", lastCycleStartIndex, numExtendCycle)
partialModelF_Y = create_partial_force_data_expr(study, "Y", lastCycleStartIndex, numExtendCycle)
(fullModelF_X, fullModelF_Y) = partialModelFToFullModelFWithRotate_expr(partialModelF_X, partialModelF_Y, periodicity)
fullModelF_Z = []
if (dimension==3):
partialModelF_Z = create_partial_force_data_expr(study, "Z", lastCycleStartIndex, numExtendCycle)
fullModelF_Z = partialModelFToFullModelFWithCopy_expr(partialModelF_Z, periodicity)
##make the 1st line for set names
header_1st = ""
columnTitles = getColumnTitles(calcDefForHeader, periodicity)
for i in range(len(columnTitles)):
header_1st += "," + columnTitles[i] + ",,"
##make the 2nd line for time and each set components
header_2nd = "Time"
for periodicIndex in range(periodicity):
for setIndex in range(n_set):
setName = dataSetForHeader.GetColumnName(setIndex+1)
header_2nd += ",Fx,Fy,Fz"
## Slice loop
for sliceIndex in range(numSlice):
# Write file
dividedOutputPath = create_file_name(outputPath, numCases, caseIndex+1, useMultiSlice, sliceIndex+1)
try:
file = open(dividedOutputPath.decode('utf-8'), 'w')
## Write header
file.write(header_1st)
file.write("\n")
file.write(header_2nd)
file.write("\n")
##Write the all TOOTH value of the model
for i in range(len(oneCycleTimeData)):
line=str(oneCycleTimeData[i])
for j in range(n_set*periodicity):
line += ","
line += str(fullModelF_X[j][i])
line += ","
line += str(fullModelF_Y[j][i])
line += ","
if dimension==3:
line += str(fullModelF_Z[j][i])
else:
line += "0.0"
file.write(line)
file.write("\n")
file.close()
except Exception as e:
app.UserProgressFinish()
show_error_message(str(e), str(e))
result = False
if not result:
break
if not result:
break
study.SetCurrentCase(startCase)
app.SetCurrentStudy(startStudy.GetName())
return result
def output_frequency_domain_tooth_forces_expr(app, selectedStudyListIndex, useElectricCycle, outputPath):
isJapanese = is_japanese(app)
dimension = app.GetCurrentModel().GetDimension()
dataManager = app.GetDataManager()
startStudy = app.GetCurrentStudy()
(study, designTable) = getStudyAndDesignTable_expr(app, selectedStudyListIndex)
app.SetCurrentStudy(study.GetName())
caseIndexList = get_active_case_indices_expr(study)
coordType = 0 # Fixed to Global Rectangular
#targetSetList = get_target_set(targetModel, dialog)
#setPrefix = dialog.GetValue(SET_PREFIX).decode('utf-8')
## Setup parameters
useMultiSlice = False
numSlice = 1
if (dimension==2):
numSlice = get_slice_number(study)
useMultiSlice = numSlice > 1
## Case loop
startCase = study.GetCurrentCase()
numCases = len(caseIndexList)
start_progress_expr(app, numCases)
result = True
for caseLoopIndex in range(numCases):
if check_progress_wascanceled_expr(app):
break
else:
app.UserProgressStep()
caseIndex = caseIndexList[caseLoopIndex]
study.SetCurrentCase(caseIndex)
##Get last 1 cycle times
calcDefForHeader = findNodalForceCalculationDefinition_expr(study, "X")
dataSetForHeader = calcDefForHeader.GetDataSet()
n_set = dataSetForHeader.GetCols() - 1
numSlots = get_slot_expr(designTable, caseIndex)
periodicity = numSlots//n_set
(lastCycleStartIndex, numExtendCycle) = get_last_cycle_start_index_expr(get_speed(study), get_pole_expr(designTable, caseIndex), useElectricCycle, dataSetForHeader.GetColumn(0))
if lastCycleStartIndex < 0:
result = False
break
(freqList, partialModelF_Xr, partialModelF_Xi) = create_fft_force_data_expr(study, dataManager, "X", dimension, lastCycleStartIndex)
(freqList, partialModelF_Yr, partialModelF_Yi) = create_fft_force_data_expr(study, dataManager, "Y", dimension, lastCycleStartIndex)
(fullModelF_Xr, fullModelF_Yr) = partialModelFToFullModelFWithRotate_expr(partialModelF_Xr, partialModelF_Yr, periodicity)
(fullModelF_Xi, fullModelF_Yi) = partialModelFToFullModelFWithRotate_expr(partialModelF_Xi, partialModelF_Yi, periodicity)
fullModelF_Zr = []
fullModelF_Zi = []
if (dimension==3):
(freqList, partialModelF_Zr, partialModelF_Zi) = create_fft_force_data_expr(study, useElectricCycle, "Z", dimension, lastCycleStartIndex)
for periodicIndex in range(periodicity):
fullModelF_Zr.extend(partialModelF_Zr)
fullModelF_Zi.extend(partialModelF_Zi)
##make the 1st line for set names
header_1st = ""
columnTitles = getColumnTitles(calcDefForHeader, periodicity)
for i in range(len(columnTitles)):
header_1st += "," + columnTitles[i] + ",,,,,"
##make the 2nd line for time and each set components
header_2nd = "Frequency"
for periodicIndex in range(periodicity):
for setIndex in range(n_set):
header_2nd += ",Fx(real),Fx(imag),Fy(real),Fy(imag),Fz(real),Fz(imag)"
## Slice loop
slice_start = 0
for sliceIndex in range(numSlice):
# Write file
dividedOutputPath = create_file_name(outputPath, numCases, caseIndex+1, useMultiSlice, sliceIndex+1)
try:
file = open(dividedOutputPath.decode('utf-8'), 'w')
## Write header
file.write(header_1st)
file.write("\n")
file.write(header_2nd)
file.write("\n")
##Write the all TOOTH value of the model
slice_start = sliceIndex * n_set * periodicity * 2
slice_end = (sliceIndex+1) * n_set * periodicity * 2
for i in range(len(freqList)):
line=str(freqList[i])
for j in range(n_set*periodicity):
line += ","
line += str(fullModelF_Xr[j][i])
line += ","
line += str(fullModelF_Xi[j][i])
line += ","
line += str(fullModelF_Yr[j][i])
line += ","
line += str(fullModelF_Yi[j][i])
line += ","
if dimension==3:
line += str(fullModelF_Zr[j][i])
line += ","
line += str(fullModelF_Zi[j+1][i])
else:
line += "0.0,0.0"
file.write(line)
file.write("\n")
file.close()
except Exception as e:
app.UserProgressFinish()
show_error_message(str(e), str(e))
result = False
slice_start += n_set*2
if not result:
break
if not result:
break
study.SetCurrentCase(startCase)
app.SetCurrentStudy(startStudy.GetName())
return result
def hasActiveCase_expr(study):
caseIndexList = get_active_case_indices_expr(study)
return len(caseIndexList) > 0
def pre_scenario_mode_work():
if CanUseScript():
return True
else:
show_error_message("Unsuppoerted Synario", "未対応のシナリオです。")
return False
def check_post_state_expr(app):
for study in GetCanUseScriptStudies(app, True):
caseIndexList = get_active_case_indices_expr(study)
if len(caseIndexList) > 0:
return (True, "", "")
return (False, "No case is selected for which the result exists.", "結果が存在するケースが選択されていません。")
def setup_progress_expr(app):
progressLabel = "Exporting to CSV File..."
if (is_japanese(app)):
progressLabel = "CSVファイルへ出力中..."
app.SetupUserProgress(progressLabel)
app.SetUserProgressUseCancel(True)
def start_progress_expr(app, maxSteps):
#return
app.SetUserProgressMaxSteps(maxSteps)
app.UserProgressStart()
def end_progress_expr(app, resFlg):
#ShowFinishMessage(app, not resFlg)
wasCanceled = app.UserProgressWasCanceled()
app.UserProgressFinish()
ShowFinishMessage(app, wasCanceled or (not resFlg))
def check_progress_wascanceled_expr(app):
#return False
return app.UserProgressWasCanceled()
def post_scenario_mode_work():
app = designer.GetApplication()
(resCheck, error_msg_en, error_msg_jp) = check_post_state_expr(app)
if not resCheck:
show_error_message(error_msg_en, error_msg_jp)
return
(dialogShowResponse, selectedStudyListIndex, useElectricCycle, outputPath, outputFormatType) = get_param_from_input_dialog_expr(app)
if dialogShowResponse != 1:
return
elif len(outputPath)==0:
show_error_message("Output file path is invalid.","出力ファイルパスが不正です。")
return
setup_progress_expr(app)
resFlg = False
if outputFormatType==0:
resFlg = output_single_file_including_torque_expr(app, selectedStudyListIndex, useElectricCycle, outputPath, True)
elif outputFormatType==1:
resFlg = output_time_domain_tooth_forces_expr(app, selectedStudyListIndex, useElectricCycle, outputPath)
elif outputFormatType==2:
resFlg = output_frequency_domain_tooth_forces_expr(app, selectedStudyListIndex, useElectricCycle, outputPath)
end_progress_expr(app, resFlg)
def run_scenario_mode():
startStudy = designer.GetApplication().GetCurrentStudy()
if pre_scenario_mode_work():
post_scenario_mode_work()
designer.GetApplication().SetCurrentStudy(startStudy.GetName())
def run_prefix_tooth_set_mode():
main_designer()
# 0: prefix_tooth_set_mode (designer)
# 1: scenario_mode (express)
#-1: quit
def selectMode(app):
if app.IsExpressMode():
return 1
if CanUseScript():
return 1
if check_model(app):
return 0
return -1
mode = selectMode(app)
if mode==0:
run_prefix_tooth_set_mode()
elif mode==1:
run_scenario_mode()


