伝達関数を作成するための周波数応答解析をセットアップする。
import designer
app = designer.GetApplication()
title_ja = u'伝達関数作成用スタディのセットアップ'
title_en = u'Set Up FQ Study to Create Transfer Function CSV File'
class ObservationPointConfig:
probe_name = "ObservationPoint"
def __init__(self):
self.node_ids = list()
self.result_type = ""
def get_probe_name(self, is_pole_coordinate):
if is_pole_coordinate:
return self.probe_name + "-rtz"
else:
return self.probe_name + "-xyz"
def add_probe_to_study(self, study, is_pole_coordinate):
probe: designer.ProbeDefinition = study.CreateProbe(self.get_probe_name(is_pole_coordinate))
probe.SetResultType(self.result_type, u"")
if is_pole_coordinate:
probe.SetResultCoordinate(1)
else:
probe.SetResultCoordinate(0)
probe.SetComponent(u"All")
probe.SetPhaseType(u"RealImag")
probe.SetLocationCoordinate(0)
probe.ClearPoints()
probe.SetProbeType(1)
probe.SetId(0, self.node_ids[0])
probe.RenamePoint(0, f"Node {self.node_ids[0]}")
for i in range(1, len(self.node_ids)):
probe.AddId(self.node_ids[i], f"Node {self.node_ids[i]}")
probe.SetUseElementValue(True)
probe.SetMoveWithPart(True)
return probe
class UserInput:
def __init__(self):
self.set_prefix = ""
self.output_dir = ""
self.num_steps = 100
self.frequency_interval = 1
self.start_frequency = 0
self.modal_damping = 0
self.obpt_config = ObservationPointConfig()
def check_study(study):
if study.GetDesignTable().NumCases() > 1:
return (False,
"Cannot use this script for a case that has multiple cases.",
"複数のケースを持つスタディにはこのスクリプトを利用することはできません。")
if study.GetScriptTypeName() != "StructuralEigenMode3D" and study.GetScriptTypeName() != "StructuralFrequency3D":
return (False,
"Select 3D Structural Eigenmode Analysis or 3D Structural Frequency Analysis.",
"3次元固有モード解析または3次元構造周波数応答解析のスタディを選択してください。")
if study.NumProbes() > 0:
return (False,
f"Do not include probes in the study referenced below.\n{study.GetName()}",
f"下記参照スタディにプローブが含まれないようにしてください。\n{study.GetName()}")
LoadTypes = ("ConcentratedLoad", "SurfaceLoad", "PressureLoad", "VolumeLoad", "ElectromagneticForce")
for i in range(study.NumConditions()):
cond_type = study.GetCondition(i).GetScriptTypeName()
if cond_type in LoadTypes:
return (False,
f"Do not include load conditions in the study referenced below.\n{study.GetName()}",
f"下記参照スタディに荷重条件が含まれないようにしてください。\n{study.GetName()}")
return (True, "", "")
def get_num_set(model, setPrefix):
idlist = list()
for i in range(model.GetSetList().NumSet()):
setName = model.GetSetList().GetSet(i).GetName()
if not setName.startswith(setPrefix):
continue
idstr = setName[len(setPrefix):]
try:
id = int(idstr)
except ValueError:
continue
idlist.append(id)
rawnum = len(idlist)
if rawnum == 0:
return 0
idlist = sorted(set(idlist))
if idlist[0] != 1:
return 0
resnum = len(idlist)
if resnum != rawnum or resnum != idlist[-1]:
return 0
return resnum
def setup_study(model, src_study, study, input):
properties = study.GetStudyProperties()
properties.SetValue("CsvOutputProbe", 1)
properties.SetValue("CsvOutputPath", input.output_dir)
properties.SetValue("CsvDivisionType", 1)
properties.SetValue("CsvDivisionCase", 1)
properties.SetValue("Damping", input.modal_damping)
step = study.GetStep()
step.SetValue("Step", input.num_steps)
step.SetValue("FrequencyStep", input.frequency_interval)
step.SetValue("Initialfrequency", input.start_frequency)
if src_study.GetScriptTypeName() == "StructuralEigenMode3D":
properties.SetValue("ReferEigenResult", 1)
properties.SetValue("EigenResultFile_DataSourceType", 2)
properties.SetValue("EigenResultFile_CurrentProject_StudyId", src_study.GetStudyId())
input.obpt_config.add_probe_to_study(study, False)
input.obpt_config.add_probe_to_study(study, True)
num_set = get_num_set(model, input.set_prefix)
if num_set < 1:
return (None,
f"Invalid set name.\n{input.set_prefix}",
f"セット名が不正です。\n{input.set_prefix}")
design_table = study.GetDesignTable()
dst_cases = list()
startingParameterIndexForNewEquations = 0
for i in range(num_set):
set_id = i + 1
set_name = f"{input.set_prefix}{set_id}"
var_name_force = f"F{set_id}"
var_name_direction_x = f"D{set_id}_X"
var_name_direction_y = f"D{set_id}_Y"
var_name_direction_z = f"D{set_id}_Z"
design_table.AddEquation(var_name_force)
design_table.AddEquation(var_name_direction_x)
design_table.AddEquation(var_name_direction_y)
design_table.AddEquation(var_name_direction_z)
if i == 0:
startingParameterIndexForNewEquations = design_table.GetParameterIndex(var_name_force)
design_table.GetEquation(var_name_force).SetType(0)
design_table.GetEquation(var_name_direction_x).SetType(0)
design_table.GetEquation(var_name_direction_y).SetType(0)
design_table.GetEquation(var_name_direction_z).SetType(0)
design_table.GetEquation(var_name_force).SetExpression(u"1")
design_table.GetEquation(var_name_direction_x).SetExpression(u"1")
design_table.GetEquation(var_name_direction_y).SetExpression(u"1")
design_table.GetEquation(var_name_direction_z).SetExpression(u"1")
design_table.GetEquation(var_name_force).SetModeling(False)
design_table.GetEquation(var_name_direction_x).SetModeling(False)
design_table.GetEquation(var_name_direction_y).SetModeling(False)
design_table.GetEquation(var_name_direction_z).SetModeling(False)
cond = study.CreateCondition(u"SurfaceLoad", f"load on {set_name}")
cond.SetValue(u"Load", var_name_force)
cond.AddSet(model.GetSetList().GetSet(set_name), 0)
cond.SetXYZPoint(u"Direction", var_name_direction_x, var_name_direction_y, var_name_direction_z)
if i < 1:
for dir_index in range(1, 3):
design_table.AddCase()
dst_cases.append(i*3+dir_index)
else:
for dir_index in range(3):
design_table.AddCase()
dst_cases.append(i*3+dir_index)
for i in range(num_set):
for j in range(3):
case_index = i*3 + j
for k in range(num_set):
startColumn = startingParameterIndexForNewEquations + k*4
design_table.SetValue(case_index, startColumn , 1 if i == k else 0)
design_table.SetValue(case_index, startColumn + 1, 1 if j == 0 else 0)
design_table.SetValue(case_index, startColumn + 2, 1 if j == 1 else 0)
design_table.SetValue(case_index, startColumn + 3, 1 if j == 2 else 0)
return dst_cases, "", ""
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()
def show_error_message(message_en, message_jp):
title_en = "Error"
title_jp = "エラー"
show_message(title_en, title_jp, message_en, message_jp)
def get_user_input():
input = UserInput()
dialog = app.CreateDialogBox()
label_num_steps_ja = u'周波数応答解析のステップ数:'
label_num_steps_en = u'Number of Steps of Frequency Analysis:'
label_frequency_interval_ja = u'周波数刻み:'
label_frequency_interval_en = u'Frequency Interval:'
label_start_frequency_ja = u'周波数初期値:'
label_start_frequency_en = u'Start Frequency:'
label_modal_damping_ja = u'モーダル減衰比:'
label_modal_damping_en = u'Modal Damping:'
label_study_csv_output_dir_ja = u'プローブのCSVファイル出力先フォルダ:'
label_study_csv_output_dir_en = u'CSV Output Folder for Probes:'
label_dir_explanation_ja = u'リモート実行の場合はリモートのパスを指定してください。'
label_dir_explanation_en = u'Specify remote path for remote execution.'
label_node_ids_for_observation_points_ja = u'観測点の節点ID:'
label_node_ids_for_observation_points_en = u'Node IDs for Observation Points:'
label_comma_separated_ja = u'コンマ区切りで入力してください。'
label_comma_separated_en = u'Separated by Commas.'
label_type_of_physical_quantity_ja = u'伝達関数で使用する物理量:'
label_type_of_physical_quantity_en = u'Physical Quantity in the Transfer Function:'
combobox_text_displacement_ja = u'変位'
combobox_text_displacement_en = u'Displacement'
combobox_text_velocity_ja = u'速度'
combobox_text_velocity_en = u'Velocity'
combobox_text_acceleration_ja = u'加速度'
combobox_text_acceleration_en = u'Acceleration'
label_quantity_explanation_ja = u'振動解析で評価する物理量は別途設定できます。'
label_quantity_explanation_en = u'The phyisical quantity in vibration analyses can be specified separately.'
label_tooth_set_prefix_ja = u'ティースのセット名の開始文字列:'
label_tooth_set_prefix_en = u'Names of Sets for Teeth Begin with:'
dialog.SetTranslation(title_en, title_ja)
dialog.SetTranslation(label_num_steps_en, label_num_steps_ja)
dialog.SetTranslation(label_frequency_interval_en, label_frequency_interval_ja)
dialog.SetTranslation(label_start_frequency_en, label_start_frequency_ja)
dialog.SetTranslation(label_modal_damping_en, label_modal_damping_ja)
dialog.SetTranslation(label_study_csv_output_dir_en, label_study_csv_output_dir_ja)
dialog.SetTranslation(label_dir_explanation_en, label_dir_explanation_ja)
dialog.SetTranslation(label_node_ids_for_observation_points_en, label_node_ids_for_observation_points_ja)
dialog.SetTranslation(combobox_text_displacement_en, combobox_text_displacement_ja)
dialog.SetTranslation(combobox_text_velocity_en, combobox_text_velocity_ja)
dialog.SetTranslation(combobox_text_acceleration_en, combobox_text_acceleration_ja)
dialog.SetTranslation(label_comma_separated_en, label_comma_separated_ja)
dialog.SetTranslation(label_type_of_physical_quantity_en, label_type_of_physical_quantity_ja)
dialog.SetTranslation(label_quantity_explanation_en, label_quantity_explanation_ja)
dialog.SetTranslation(label_tooth_set_prefix_en, label_tooth_set_prefix_ja)
types_of_physical_quantity = [combobox_text_displacement_en, combobox_text_velocity_en, combobox_text_acceleration_en]
dialog.SetTitle(title_en)
dialog.SetModal(True)
dialog.AddLabel(label_tooth_set_prefix_en, 0, 1)
dialog.AddString("tooth_set_prefix", "", "tooth", 1, 2)
dialog.AddLabel(label_node_ids_for_observation_points_en, 0, 1)
dialog.AddString("node_ids_for_observation_points", "", "", 1, 2)
dialog.AddLabel("", 0, 1)
dialog.AddLabel(label_comma_separated_en, 1, 2)
dialog.AddLabel(label_type_of_physical_quantity_en, 0, 1)
dialog.AddComboBox("type_of_physical_quantity", "", types_of_physical_quantity, 1, 1, 2)
dialog.AddLabel("", 0, 1)
dialog.AddLabel(label_quantity_explanation_en, 1, 2)
dialog.AddLabel(label_study_csv_output_dir_en, 0, 1)
dialog.AddDirectoryPath("study_csv_output_dir", "", "", 1, 2)
dialog.AddLabel("", 0, 1)
dialog.AddLabel(label_dir_explanation_en, 1, 2)
dialog.AddLabel(label_num_steps_en, 0, 1)
dialog.AddInteger("num_steps", "", 100, 1, 2)
dialog.AddLabel(label_frequency_interval_en, 0, 1)
dialog.AddInteger("frequency_interval", "", 10, 1, 2)
dialog.AddLabel(label_start_frequency_en, 0, 1)
dialog.AddInteger("start_frequency", "", 10, 1, 2)
dialog.AddLabel(label_modal_damping_en, 0, 1)
dialog.AddReal("modal_damping", "", 0.05, 1, 2)
ret = dialog.Show()
if ret==0:
return (False, input)
num_steps = dialog.GetValue("num_steps")
frequency_interval = dialog.GetValue("frequency_interval")
start_frequency = dialog.GetValue("start_frequency")
modal_damping = dialog.GetValue("modal_damping")
study_csv_output_dir = dialog.GetValue("study_csv_output_dir").decode(encoding='utf-8')
node_ids_for_observation_points = dialog.GetValue("node_ids_for_observation_points").decode(encoding='utf-8')
list_node_ids_org = node_ids_for_observation_points.replace(' ','').split(',')
index_physical_quantity = dialog.GetValue("type_of_physical_quantity")
tooth_set_prefix = dialog.GetValue("tooth_set_prefix").decode(encoding='utf-8')
if tooth_set_prefix == "":
show_error_message("\"Name of Sets for Teeth Begin with\" is not specified.", "ティースのセット名の開始文字列が指定されていません。")
return (False, input)
if study_csv_output_dir == "":
show_error_message("CSV Output Folder for Probes is not specified.", "プローブのCSVファイル出力先フォルダが指定されていません。")
return (False, input)
list_node_ids = list()
for s in list_node_ids_org:
try:
list_node_ids.append(int(s))
except ValueError as e:
(e)
if len(list_node_ids) == 0:
show_error_message(f"Node IDs not specified properly. ({node_ids_for_observation_points})", f"節点IDが正しく入力されていません。 ({node_ids_for_observation_points})")
return (False, input)
input.num_steps = num_steps
input.frequency_interval = frequency_interval
input.start_frequency = start_frequency
input.modal_damping = modal_damping
input.set_prefix = tooth_set_prefix
input.output_dir = study_csv_output_dir
input.obpt_config.node_ids = list_node_ids
input.obpt_config.result_type = types_of_physical_quantity[index_physical_quantity]
return (True, input)
def get_study_name():
num_studies = app.NumStudies()
study_name_list = []
for i in range(num_studies):
study = app.GetStudy(i)
if study.IsValid():
study_name_list.append(study.GetName())
count = 0
new_study_name = ""
while True:
new_study_name = "FQ_transfer_function" + ("" if count == 0 else f"_{count}")
count += 1;
match = new_study_name in study_name_list
if match == False:
break;
return new_study_name
def get_study_index(model, study):
num_studies = model.NumStudies()
uuid = study.GetUuid()
index = -1
for i in range(num_studies):
if model.GetStudy(i).GetUuid() == uuid:
index = i
break
return index
def main():
if app.NumModels() == 0:
show_error_message("No models.", "モデルがありません。")
return False
model: designer.Model = app.GetCurrentModel()
if model.NumStudies() == 0:
show_error_message("No studies.", "スタディがありません。")
return False
src_study = app.GetCurrentStudy()
(isok, err_en, err_jp) = check_study(src_study)
if not isok:
show_error_message(err_en, err_jp)
return False
(success, input) = get_user_input()
if not success:
return False
new_study_name = get_study_name()
src_study_index = get_study_index(model, src_study)
study = model.DuplicateStudyWithType(src_study_index, u"StructuralFrequency3D", new_study_name, True)
(dst_cases, err_en, err_jp) = setup_study(model, src_study, study, input)
if not dst_cases:
show_error_message(err_en, err_jp)
return False
message_finished_ja = f"スタディ \"{new_study_name}\" のセットアップが終了しました。"
message_finished_en = f"Setup of Study \"{new_study_name}\" has been completed,"
show_message(title_en, title_ja, message_finished_en, message_finished_ja)
return True
main()


