#--------------------------------------------------------------------- #Name: d0028_search_optimization_size_range.py #Menu-en: Search Size Range in Optimization Table #Menu-ja: 最適化の寸法範囲の探索 #Type: Python #Create: December, 2017 JSOL Corporation #Comment-en: Search for the maximum value and the minimum value of the parametric variable range of optimization. #Comment-ja: 最適化のパラメータ変数範囲の最大値と最小値を探索する。 #Copyright: (c) JSOL Corporation. All Rights Reserved. #--------------------------------------------------------------------- import designer import csv import subprocess app = designer.GetApplication() class DialogData: def __init__(self): self.num_trials = 20 self.csv_file_name = "" self.is_open_csv = False self.is_update_range = False self.is_add_cases = False self.is_valid = False class RangeData: def __init__(self): self.name = "" self.optimization_range= 0 self.param_index = 0 self.init_value = 0 def main(): data = get_data_from_input_dialog() if data.is_valid == False: return if search_size_range_in_optimization_table(data)==False: return show_normal_exit_message() def get_data_from_input_dialog(): dialog = create_input_dialog() return show_input_dialog(dialog) def create_input_dialog(): dialog = app.CreateDialogBox() title_jp = "最適化の寸法範囲の探索" title_en = "Search Size Range in Optimization Table" inputlbl_jp = "入力:" inputlbl_en = "Input:" outputlbl_jp = "出力:" outputlbl_en = "Output:" optionlbl_jp = "オプション:" optionlbl_en = "Option:" numtrialslbl_jp = "探索回数:" numtrialslbl_en = "Number of Search:" noteslbl_jp = "1寸法あたりの探索回数は上限側/下限側合わせて、探索回数*2になります" noteslbl_en = "Number of searches per dimension is equal to number of search times * 2 with upper limit side / lower limit side combined" csvfile_jp = "結果ファイル:" csvfile_en = "Result File:" updatevallbl_jp = "最適化ダイアログの寸法値の最大値/最小値を更新する" updatevallbl_en = "Update Max/Min of The Dimensions in Optimization Dialog" leavecaseslbl_jp = "探索で形状を生成したケースを追加する" leavecaseslbl_en = "Add Cases that Generated Shapes in Search" dialog.SetTranslation(title_en, title_jp) dialog.SetTranslation(inputlbl_en, inputlbl_jp) dialog.SetTranslation(outputlbl_en, outputlbl_jp) dialog.SetTranslation(optionlbl_en, optionlbl_jp) dialog.SetTranslation(numtrialslbl_en, numtrialslbl_jp) dialog.SetTranslation(noteslbl_en, noteslbl_jp) dialog.SetTranslation(csvfile_en, csvfile_jp) dialog.SetTranslation(updatevallbl_en, updatevallbl_jp) dialog.SetTranslation(leavecaseslbl_en, leavecaseslbl_jp) dialog.SetTitle(title_en) dialog.AddLabel(inputlbl_en) dialog.AddInteger("num_trials", numtrialslbl_en, 20) dialog.SetTooltip("num_trials", noteslbl_en) dialog.AddLine() dialog.AddLabel(outputlbl_en) dialog.AddSaveFilename("csv_file_name", csvfile_en, "", "CSV file (*.csv)") dialog.AddLine() dialog.AddLabel(optionlbl_en) dialog.AddCheckBox("is_update_range", updatevallbl_en, False) dialog.AddCheckBox("is_add_cases", leavecaseslbl_en, False) return dialog def show_input_dialog(dialog): dialog.Show() if dialog.WasCancelled() == False: data = get_values_from_input_dialog(dialog) if data.is_valid == False: return show_input_dialog(dialog) return data return DialogData() def get_values_from_input_dialog(dialog): data = DialogData() if dialog.GetValue("num_trials") <= 0: message_en = "The number of trials must be greater than 0." message_jp = "探索回数は0より大きな値を入力してください。" show_error_exit_message(message_en, message_jp) return data if dialog.GetValue("csv_file_name") == "": message_en = "Please specify result file name." message_jp = "結果ファイル名を指定してください。" show_error_exit_message(message_en, message_jp) return data data.num_trials = dialog.GetValue("num_trials") data.is_update_range = dialog.GetValue("is_update_range") data.is_add_cases = dialog.GetValue("is_add_cases") data.csv_file_name = dialog.GetValue("csv_file_name") data.is_valid = True return data def search_size_range_in_optimization_table(data): range_list = [] if check_optimization_range(range_list) == False: return False if app.GetCurrentModel().IsCadLinkOpen() == False: app.GetCurrentModel().RestoreCadLink() app.GetCurrentStudy().SetCurrentCase(0) geomApp = app.CreateGeometryEditor() geomDoc = geomApp.GetDocument() if geomDoc.NumBuildMessages() > 0: show_error_exit_message("Initial case has error.", "初期ケースにエラーがあります。") return False initialTopologyKey = geomDoc.GetTopologyHashKey() designTable = app.GetCurrentStudy().GetDesignTable() num_case = designTable.NumCases() result_list = [] for range_data in range_list: optimizationRange = range_data.optimization_range result = [] result.append(range_data.name) result.append(search_size_range(range_data, optimizationRange.GetMin(), geomDoc, initialTopologyKey, data.num_trials)) result.append(search_size_range(range_data, optimizationRange.GetMax(), geomDoc, initialTopologyKey, data.num_trials)) result_list.append(result) if data.is_update_range == True: set_range_to_optimization_table(optimizationRange, result[1], result[2]) if data.is_add_cases == False: remove_temp_cases(num_case) output_csv_file(result_list, data.csv_file_name) return True def check_optimization_range(range_list): designTable = app.GetCurrentStudy().GetDesignTable() optimizationTable = app.GetCurrentStudy().GetOptimizationTable() numParam = designTable.NumParameters() for i in range(numParam): if is_optimization_item(i) == False: continue name = designTable.ParameterName(i) optimizationRange = optimizationTable.GetParametricItemByParameterName(name) ini = designTable.GetValue(0, i) if app.HasError(): app.ClearError() optimizationTable.AddParametricItem(name) optimizationRange = optimizationTable.GetParametricItemByParameterName(name) optimizationRange.SetMin(ini) optimizationRange.SetMax(ini) min = optimizationRange.GetMin() max = optimizationRange.GetMax() if max < min: message_en = "Maximum value of {0} in optimization dialog must be greater than or equal to minimum value.".format(name) message_jp = "最適化ダイアログの {0} の最大値は最小値以上の値を入力してください。".format(name) show_error_exit_message(message_en, message_jp) return False if min > ini: message_en = "Minimum value of {0} in optimization dialog must be less than or equal to that of initial case.".format(name) message_jp = "最適化ダイアログの {0} の最小値は初期ケースの値以下の値を入力してください。".format(name) show_error_exit_message(message_en, message_jp) return False if max < ini: message_en = "Maximum value of {0} in optimization dialog must be greater than or equal to that of initial case.".format(name) message_jp = "最適化ダイアログの {0} の最大値は初期ケースの値以上の値を入力してください。".format(name) show_error_exit_message(message_en, message_jp) return False data = RangeData() data.name = name data.optimization_range = optimizationRange data.param_index = i data.init_value = ini range_list.append(data) return True def is_optimization_item(index): designTable = app.GetCurrentStudy().GetDesignTable() if designTable.IsCadParameter(index): if designTable.ParameterTypeName(index) == "Real": return True return False def search_size_range(range_data, limit, geomDoc, initialTopologyKey, num_trials): designTable = app.GetCurrentStudy().GetDesignTable() ini = range_data.init_value paramIndex = range_data.param_index shift = 0.0 shift = abs(limit - ini) / 2 if shift == 0: return limit elif limit > ini: sign = 1 else: sign = -1 binary = 0.0 binary = limit for i in range(num_trials): designTable.AddCase() lastIndex = designTable.NumCases() - 1 for j in range(designTable.NumParameters()): designTable.SetValue(lastIndex, j, designTable.GetValue(0, j)) designTable.SetValue(lastIndex, paramIndex, binary) app.GetCurrentStudy().SetCurrentCase(lastIndex) if geomDoc.NumBuildMessages() > 0 or geomDoc.GetTopologyHashKey() != initialTopologyKey: binary = designTable.GetValue(lastIndex, paramIndex) - sign * shift else: if designTable.GetValue(lastIndex, paramIndex) == limit: return limit binary = designTable.GetValue(lastIndex, paramIndex) + sign * shift shift /= 2 return designTable.GetValue(lastIndex, paramIndex) def set_range_to_optimization_table(optimizationRange, min, max): if optimizationRange.GetMin() != min: optimizationRange.SetMin(min) if optimizationRange.GetMax() != max: optimizationRange.SetMax(max) def remove_temp_cases(num_case): designTable = app.GetCurrentStudy().GetDesignTable() while num_case < designTable.NumCases(): index = designTable.NumCases() - 1 designTable.RemoveCase(index) def output_csv_file(range_list, csv_file_name): f = open(csv_file_name.decode('utf-8'), 'w') writer = csv.writer(f, lineterminator='\n') writer.writerow(["ParameterName", "Min", "Max"]) for line in range_list: writer.writerow(line) f.close() def show_normal_exit_message(): title_en = "Search Finished" title_jp = "探索終了" message_en = "Search of Dimension Range is Finished." message_jp = "寸法範囲の探索が終了しました。" show_message(title_en, title_jp, message_en, message_jp) def show_error_exit_message(message_en, message_jp): title_en = "Error" title_jp = "エラー" show_message(title_en, title_jp, message_en, message_jp) def show_message(title_en, title_jp, message_en, message_jp): msgdlg = app.CreateDialogBox() msgdlg.SetTranslation(title_en, title_jp) msgdlg.SetTranslation(message_en, message_jp) msgdlg.SetCancelButtonVisible(False) msgdlg.SetTitle(title_en) msgdlg.AddLabel(message_en) msgdlg.Show() main()