做了這麼多準備工夫,今天終於可以開始來寫creators.py的幾個function。一旦有了各種creator後,我們的code就會精簡許多,減少很多boilerplate的typing。
creator function最終都需透過base.CreateEntity來建立Entity,所以pattern都很相似,目標是找出各function的deck,element_type及fields。
deck使用我們一貫的short circuit技巧,如果沒指定則設為constants.LSDYNA。element_type則引用schemas.py中的LSDYNAType.NODE。
最後將給定的fields與上述的deck及element_type一併置入base.CreateEntity,並return。
# creators.py
def create_node(fields, deck=None):
deck = deck or constants.LSDYNA
type_ = LSDYNAType.NODE
return base.CreateEntity(deck, type_, fields)
此處element_type我們使用LSDYNAType.SHELL,ANSA會自動認為我們想建立一個QUAD4 element,在我們當前的使用情況不會有問題。我們會在之後使用base.ImportV1時,試著修正這個問題。
# creators.py
def create_shell(fields, deck=None):
deck = deck or constants.LSDYNA
type_ = LSDYNAType.SHELL
return base.CreateEntity(deck, type_, fields)
create_mat的步驟稍微多一點,我們慢慢來看。
element_type,我們使用short circuit的技巧,將其預設為常用的MAT1材料卡。fields,我們這邊取名叫vals,如果沒有給定的話,則設為一個空的dict。name的話,使用我們先前建立的get_one_material_name來自動建立材料名。force_val的dict, 將DEFINED設為YES,這樣我們就不用在輸出的時候,再調整每個材料的visibility。name,vals,force_vals組合成fields。此處需留意組合的順序,由於name其實是可以放在vals內由使用者給定,所以我們將vals放在第二位。如果有給定的話,則會使用給定的名字蓋過第一位的name。另外,由於我們想強迫所有材料都是預設會輸出的,所以要擺在最後一位,這樣即使使用者在vals中指定DEFINE為NO,也會被第三位的force_vals蓋過去。deck、element_type及fields一併置入base.CreateEntity,並return。# creators.py
def create_mat(mat_type=None, name=None, vals=None, deck=None):
deck = deck or constants.LSDYNA
type_ = mat_type or MatType.MAT1_MAT_ELASTIC
name = name or get_one_material_name()
vals = vals or {}
force_vals = {'DEFINED': 'YES'}
fields = {**{'Name': name},
**vals,
**force_vals}
return base.CreateEntity(deck, type_, fields)
create_sec的邏輯與create_mat類似,只是使用create_sec可以同時建立material及property。
值得一提的是,這邊我們使用get_mat_prop_id來取得一個id,可以同時給material及property使用。
# creators.py
def create_sec(sec_type=None,
mat_type=None,
name=None,
vals=None,
matvals=None,
deck=None):
deck = deck or constants.LSDYNA
type_ = sec_type or SecType.SECTION_SHELL
name = name or get_one_section_name()
vals = vals or {}
matvals = matvals or {}
used_mat_prop_id = get_mat_prop_id()
matvals = {**{'MID': used_mat_prop_id}, **matvals}
mat = create_mat(mat_type=mat_type, vals=matvals)
force_vals = {'DEFINED': 'YES'}
fields = {**{
'Name': name,
'PID': used_mat_prop_id,
'MID': used_mat_prop_id},
**vals,
**force_vals}
return base.CreateEntity(deck, type_, fields)
create_set的前半部建立了一個空的set Entity,如果有指定想放入set內的entities的話,我們使用base.AddToSet將其加入,最後回傳這個set Entity。
# creators.py
def create_set(entities=None, name=None, deck=None):
deck = deck or constants.LSDYNA
type_ = LSDYNAType.SET
name = name or get_one_set_name()
fields = {'Name': name}
set_entity = base.CreateEntity(deck, type_, fields)
if entities is not None:
base.AddToSet(set_entity, entities)
return set_entity
create_contact的contact_type預設為常用的AUTOMATIC_SURFACE_TO_SURFACE。至於sstyp及mstyp則可透過schemas中的ContactType來調整。
# creators.py
def create_contact(ssid: int,
msid: int,
sstyp: str,
mstyp: str,
contact_type=None,
name=None,
vals=None,
deck=None):
deck = deck or constants.LSDYNA
type_ = LSDYNAType.CONTACT
contact_type = contact_type or ContactTypeName.AUTOMATIC_SURFACE_TO_SURFACE.value
name = name or get_one_contact_name()
vals = vals or {}
fields = {**{'Name': name,
'TYPE': contact_type,
'SSID': ssid,
'MSID': msid,
'SSTYP': sstyp,
'MSTYP': mstyp},
**vals}
return base.CreateEntity(deck, type_, fields)
相關creator function代換後的結果,請參考本日的box_drop.py。