[D0032] 伝達関数作成用スタディのセットアップ

 

伝達関数を作成するための周波数応答解析をセットアップする。

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()

Download Python source code

ファイルご利用の注意点

JMAGスクリプトライブラリをご利用されるに際し、以下の利用規約をよくお読みいただき、ご同意の上ご利用下さるようお願い申し上げます。