CAEのためのPython3(keywordファイルの入出力)

2023/08/22に公開

動機

前回の記事でNastranファイルを読み込めたので同じ要領でkeywordファイルの入出力をやってみます。
Ls-Dynaのkeywordファイルは、個人的に慣れ親しんだ形式なので節点、要素以外にPART,Section,材料,セット(パート、節点)も扱えるようしようと思います。

今回やること

keywordファイルの入出力を行います。

プログラムの説明

  • keywordファイルは、キーワード(*NODEなど)とキーワードの間に中身が記述されています。
*NODE
     100        331.7869       -215.0759        -1091.19       0       0
     101       -271.5705       -29.70801          -946.8       0       0
     102        97.48036       -161.6168          -954.0       0       0
     103        94.36771        -164.815          -954.0       0       0
     104        91.20172       -167.7399          -954.0       0       0
     105        87.96567       -170.4286          -954.0       0       0
     106        84.57141       -172.9781          -954.0       0       0
     107         81.0126       -175.3664          -954.0       0       0
     108        77.28926       -177.5935          -954.0       0       0
     109        73.41306       -179.6517          -954.0       0       0
     110        69.43188       -181.4983          -954.0       0       0
  • そのため、ファイルの全文をリストにした後にキーワードごとで小分けにするしました。
def Separate_Ranges(self,Liens,Keyword,num,LimitWordLen=1000):
        temp=[]
        jug=False
        for i in Liens:
            if i[:1]=="*":
                jug=False
            if i[:num]==Keyword and len(i)<=LimitWordLen+1:
                jug=True
            if jug:
                temp.append(i)
        return temp

*読み込みのコード
*keywordファイルはInculedファイル(複数のファイルをまとめる親ファイル)

+KEYWORD
*INCLUDE
1-test_dat.k
*INCLUDE
2-test_Control.k
*INCLUDE
3-test_PartMat.k
*INCLUDE
4-test_Others.k
*END

があるため以下のコードで判別しています。

def Read_File(self,filename,DATA):
        sp=super()
        temp=[i.replace("\n","") for i in sp.Separate_Ranges(sp.First_Read_File(filename),'*INCLUDE',8) if i.find('*')==-1]
        INput_File=[filename] if len(temp)==0 else temp
        [self.Read_File_Sub(i,DATA) for i in INput_File]

*ここが読み込みのメインでキーワードごとにリストを作成し、後で加工しやすいように保存します。

    def Read_File_Sub(self,filename,DATA): 
        sp=super()
        temp=sp.First_Read_File(filename)
        N=sp.Separate_Str_Count_Liens(sp.Separate_Ranges(temp,'*NODE',5))
        EL=sp.Separate_Str_Count_Liens(sp.Separate_Ranges(temp,'*ELEMENT_SHELL',14))
        PR=[sp.Separate_Str_Count_Liens(i,10) for i in self.List_Joins(sp.Separate_Ranges(temp,'*PART',5,5))]
        SE=[sp.Separate_Str_Count_Liens(i,10) for i in self.List_Joins(sp.Separate_Ranges(temp,'*SECTION_SHELL',14))]
        PR_COMP=[sp.Separate_Str_Count_Liens(i,10) for i in self.List_Joins(sp.Separate_Ranges(temp,'*PART_COMPOSITE',15))]
        SET_NODE=[sp.Separate_Str_Count_Liens(i,10) for i in self.List_Joins(sp.Separate_Ranges(temp,'*SET_NODE_LIST',14))]
        SET_PART=[sp.Separate_Str_Count_Liens(i,10) for i in self.List_Joins(sp.Separate_Ranges(temp,'*SET_PART_LIST',14))]
        RIGHT=[sp.Separate_Str_Count_Liens(i,10) for i in self.List_Joins(sp.Separate_Ranges(temp,'*MAT_RIGID',10))]
        ELASTIC=[sp.Separate_Str_Count_Liens(i,10) for i in self.List_Joins(sp.Separate_Ranges(temp,'*MAT_ELASTIC',12))]
        PIECEWISE_LINEAR_PLASTICITY=[sp.Separate_Str_Count_Liens(i,10) for i in self.List_Joins(sp.Separate_Ranges(temp,'*MAT_PIECEWISE_LINEAR_PLASTICITY',32))]
        Input_DATAList=[(N[1:],self.NODE_R_Func),(EL[1:],self.ELEMENT_R_Func),(PR,self.PART_R_Func),
                        (SE,self.SECTION_R_Func),(SET_NODE,self.SET_NODE_R_Func),(SET_PART,self.SET_PART_R_Func),
                        (PR_COMP,self.PARTCOMP_R_Func),(RIGHT,self.MAT_RIGIT_R_Func),(ELASTIC,self.MAT_ELASTIC_R_Func),
                        (PIECEWISE_LINEAR_PLASTICITY,self.MAT_PIECEWISE_LINEAR_PLASTICITY_R_Func)]
        
        [self.SET_R(i[0],DATA,i[1]) for i in Input_DATAList]

*メインで使用している関数

    def List_Joins(self,temp):
        if len(temp)==0:
            return []
        temp2=[i for i in temp if i.find("*")==-1]
        num= temp[1:].index(next((i for i in temp[1:] if i.find("*")!=-1),temp[-1]))
        return [temp2[i*num:(i+1)*num] for i in range(int(len(temp2)/num))]
    def tryint(self,s):  # 正規表現を使ってintか判断する
        return True if re.fullmatch('[-+]?\d+', s.replace(" ","")) else False
    def SET_R(self,temp1,DATA,Func):
        if temp1!=0:
            if Func==self.SET_PART_R_Func:
                A=0
            for i,value in enumerate(temp1):
                temp= "".join(value[0]).replace("\n","")
                NAME="" if self.tryint(value[0][0]) else temp
                num= 0 if self.tryint(value[0][0]) else 1
                Func(value,DATA,NAME,num)
    
    def NODE_R_Func(self,value,DATA,NAME,num):
        DATA.N.setdefault(int(value[0]),NODE(np.array([value[1]+value[2],value[3]+value[4],value[5]+value[6]])))
    def ELEMENT_R_Func(self,value,DATA,NAME,num):
        DATA.EL.setdefault(int(value[0]),ELEMENT([value[1],value[2:]]))
    def PART_R_Func(self,value,DATA,NAME,num):    
        DATA.PR.setdefault(int(value[num][0]),PART([value[num][2],value[num][1],NAME]))
    def SECTION_R_Func(self,value,DATA,NAME,num):
        DATA.SE.setdefault(int(value[num][0]),SEC([value[num][1],value[num+1][0],NAME]))
    def PARTCOMP_R_Func(self,value,DATA,NAME,num):
        DATA.PC.setdefault(int(value[num][0]),PART_COPM([value[num+1][0],value[num+1][1],value[num][1],NAME]))
        self.PARTCOPM_SET_R_SUB(value,DATA.PC[int(value[num][0])])
    def PARTCOPM_SET_R_SUB(self,value,PC):
        for i in range(len(value)):
            if i>1:
                for j in range(int(len(value)/4)):
                    PC.MID.append(value[i][j*4])
                    PC.T.append(value[i][j*4+1])
    def MAT_ELASTIC_R_Func(self,value,DATA,NAME,num):
        ID=int(value[num][0])
        DATA.MA.setdefault(ID,MAT(value[num][0:2] + [NAME]))
        return ID
    def MAT_RIGIT_R_Func(self,value,DATA,NAME,num):
        ID=self.MAT_ELASTIC_R_Func(value,DATA,NAME,num)
        DATA.MA[ID].CM=tuple(int(float(i)) for i in value[num+1][:3])
    def MAT_PIECEWISE_LINEAR_PLASTICITY_R_Func(self,value,DATA,NAME,num):
        ID=self.MAT_ELASTIC_R_Func(value,DATA,NAME,num)
        DATA.MA[ID].LCSS=value[num+1][2]
    def SET_NODE_R_Func(self,value,DATA,NAME,num):
        VALUE =self.SET_SET_R_SUB(value,num)
        DATA.SET_NODE.setdefault(int(value[num][0]) ,SET_NODE([VALUE,NAME]))
    def SET_PART_R_Func(self,value,DATA,NAME,num):
        VALUE =self.SET_SET_R_SUB(value,num)
        DATA.SET_PART.setdefault(int(value[num][0]) ,SET_PART([VALUE,NAME]))
    def SET_SET_R_SUB(self,value,num): 
        tempList=value[2:] if num==1 else value[1:]
        VALUE=[]
        [[VALUE.append(i) for i in j if i.find("\n")==-1] for j in tempList]
        return VALUE
  • 読み込みと同様にメインで保存してあるデータをファイル形式に合うように加工して
    出力しています。
    *出力メイン
def Write_File(self, filename, DATA):
        with open(filename, 'w') as f:
            f.write("*KEYWORD\n")
            f.writelines(self.NODE_W(DATA))
            f.writelines(self.ELEMENT_W(DATA))
            f.writelines(self.PART_W(DATA))
            f.writelines(self.PARTCOMP_W(DATA))
            f.writelines(self.SECTION_W(DATA))
            f.writelines(self.MAT_W(DATA))
            f.writelines(self.SET_W(DATA.SET_NODE,"*SET_NODE_LIST_TITLE\n"))
            f.writelines(self.SET_W(DATA.SET_PART,"*SET_PART_LIST_TITLE\n"))
            f.write("*END")

*メインで使用する関数

def NODE_W(self,DATA):
       sp=super()
       return["*NODE\n"] + [str(key).rjust(8) + sp.Str_Join(value.CRD,0,16,False) 
                                  + sp.Str_Join([0,0],0,8) for key,value in DATA.N.items()]
   def ELEMENT_W(self,DATA):
       sp=super()
       return ["*ELEMENT_SHELL\n"] +[sp.Str_Join([key,value.PID] + value.NID,0,8) for key,value in DATA.EL.items()]
   def PART_W(self,DATA):
       sp=super()
       return ["*PART\n$# TITLE\n"  + value.Name +"\n" + sp.Str_Join([key,value.SEID,value.MID] + [0]*5,0,10)  for key,value in DATA.PR.items()]
   def SECTION_W(self,DATA):
       sp=super()
       return ["*SECTION_SHELL\n$# TITLE\n" + value.Name +"\n" + sp.Str_Join([key,value.ELform] +[0,2,1,0,0,1],0,10) +
               sp.Str_Join([value.T]*4 +[0]*4,0,10) for key,value in DATA.SE.items()]
   def PARTCOMP_W(self,DATA):
       sp=super()
       return ["*PART_COMPOSITE\n$# TITLE\n"  + value.Name +"\n" + sp.Str_Join([key,value.ELform] + [0]*6,0,10) +
               "".join([sp.Str_Join([value.MID[i],value.T[i],0,0,value.MID[i+1],value.T[i+1],0,0],0,10) for i in range(int(len(value.MID)/2))]) for key,value in DATA.PC.items()]
   def MAT_W(self,DATA):
       temp=self.MAT_PIECEWISE_LINEAR_PLASTICITY_SUB(DATA)
       temp.extend(self.MAT_RIGID_SUB(DATA))
       temp.extend(self.MAT_ELASTIC_SUB(DATA))
       return temp
   def MAT_RIGID_SUB(self,DATA):
       sp=super()      
       return ["*MAT_RIGID_TITLE\n$# TITLE\n"  + value.Name +"\n" + sp.Str_Join([key,f"{value.RO:.1E}",f"{value.E:.1E}",0.3,0,0,0],0,10)
               + sp.Str_Join(list(value.CM),0,10) + sp.Str_Join([0]*6,0,10) for key,value in DATA.MA.items() if value.CM!=None] 
   def MAT_PIECEWISE_LINEAR_PLASTICITY_SUB(self,DATA):
       sp=super()      
       return ["*MAT_PIECEWISE_LINEAR_PLASTICITY_TITLE\n$# TITLE\n"  + value.Name +"\n" + sp.Str_Join([key,f"{value.RO:.1E}",f"{value.E:.1E}",0.4,24,0,0,0],0,10)
               + sp.Str_Join([0,0,value.LCSS,0,1],0,10) + sp.Str_Join([0]*8,0,10) + sp.Str_Join([0]*8,0,10) for key,value in DATA.MA.items() if value.LCSS!=None] 
   def MAT_ELASTIC_SUB(self,DATA):
       sp=super()      
       return ["*MAT_ELASTIC_TITLE\n$# TITLE\n"  + value.Name +"\n" + sp.Str_Join([key,f"{value.RO:.1E}",f"{value.E:.1E}",0.4,24,0,0,0],0,10)
                for key,value in DATA.MA.items() if value.CM==None and value.LCSS==None]  
   def List_devide_into_small_portions(self,temp,num):
          return [temp[i*num:(i+1)*num] for i in range(int(len(temp)/num) + 1)]
   def SET_W(self,SET,SET_TYPE):
           sp=super()
       return [ SET_TYPE + value.Name +"\n" +sp.Str_Join([key] +[0.0]*4+["MECH"],0,10) + "".join([sp.Str_Join(i,0,10) for i in self.List_devide_into_small_portions(value.value,8)]) for key,value in SET.items()]

*今回、材料やSctionなどパラメータが多いものは、よく使用するものだけ読み込めるようにし
、その他は適当に値を割り振っています。

使い方

*ファイルの読み込み

File_key().Read_File(入力ファイル名,DATA_BASE())

*ファイルの書き出し

File_key().Read_File(出力ファイル名,DATA_BASE())

今後

*扱えるデータの種類が増えたので拘束やセットの自動作成などに取り組んでいけたらと思います。

Discussion