Msc.Marc的python开发#1

Msc.Marc的python开发#1

Msc.Marc 是一款较为实用的有限元计算软件,但是本身自带的Mentat 前处理可谓十分不好用。当然我们可以选择Msc 公司推出的Patran 前处理程序,不过毕竟还是有一定学习曲线要求的,我暂时不太想换。那么怎么提高现有的蹩脚Mentat的建模效率呢?

其实Mentat 自带的procedure文件可以用来记录一些基本的大量重复的工作。但是在procedure 文件中不能有复杂的选择或循环等结构出现,这限制了procedure文件的功力。

Marc的开发人员早就考虑了这一点,同其他大型软件一样,Marc 早就留出了python 接口,方便我们用python进行批处理工作。

前期配置

我用的是Marc2015 + Visual studio 2012 + Intel visual fortran 2013 的配置
之所以用IVF,是因为我所用的一个子程序需要用Fortran开发,接入到Marc 提供的Ubeam 接口中。

PC上的python本来是3.8的,紧跟时代,各种包装备齐全,然而Marc的python接口自带python.exe,还是2.X版本的(具体什么版本我也没细看)导致装在PC上的python 没法用,各种包也没用。急得我在Marc 的核心python接口模块 py_mentat 所在位置安装了包,然而因为版本兼容问题,bug 不断。我只好暂时舍弃习惯的包,轻装上阵,只用python本体。好在目前接触的问题还比较简单,python本体就能解决了。

核心思想

Marc的python接口的核心思想其实很简单,那就是 一个换了python皮的procedure 文件 。或者说,把需要人工输入的命令汇集到python源文件中,并通过命令行和Marc进行交互,向Marc下各种命令,并获得Marc 的数据库中的各种数据。

核心交互函数及数据库函数

核心交互函数:

  • py_send() #向Marc 发送命令的函数,参数一般是以 * 开头的字符串,代表不同的操作。例如:
    • py_send("*new_mater standard *mater_option general:state:solid *mater_option general:skip_structural:off")
    • py_send("*mater_name %s" % name)
    • py_send("*mater_param general:mass_density 2.5e-9")
    • py_send("*mater_option structural:type:elast_plast_ortho")
    • py_send("*mater_option structural:type:hypo_elast")
    • py_send("*mater_option structural:hypoelastic_method:ubeam")
    • py_send("*mater_option structural:damping:on")
    • py_send("*mater_param structural:rayleigh_damping_stiff_mult 0.0136764")
      上面的代码是建立一种材料的必要操作指令,包括建立新材料,设置类型是standard,输入材料名字,设置密度,设置对称性,弹性行为,接入ubeam子程序接口,打开阻尼开关,设置阻尼系数。你可能会问,Marc 指令千千万万条,我怎么记住每个指令对应的代码呢?很简单,要想这些指令,可在先Marc 上用鼠标操作一遍,然后到procedure 文件里找到对应的指令即可。
  • py_get_int() 和py_get_float() #这两个函数用来从Marc的数据库中抽取数据。括号中为提取参数,例如
    • n = py_get_int(“nelements()”) #获取模型中的单元总数
    • node1.x=py_get_float(“node_x(%d)”%node1.ID) #获取指定节点的整体x坐标

数据库函数:

  • nnodes( ) #Number of nodes in database
  • node_id(ARG1) #ID of ARG1-th node in database
  • max_node_id( ) #Largest node ID in database
  • node_x(arg1) #Global X-coordinate of node arg1
  • node_y(arg1) #Global Y-coordinate of node arg1
  • node_z(arg1) #Global Z-coordinate of node arg1
  • nelements( ) Number of elements in database
  • element_id(ARG1) ID of ARG1-th element in database
  • max_element_id( ) Largest element id in database
  • element_node_id(arg1,ARG2) ID of ARG2-th node of element arg1

更多的函数可以参考 Marc®Python 2015:Tutorial and Reference Manual

应用实例

下面的代码实现的功能是:从一个csv文件中读入截面的属性,并为每个材料起名字,在Mentat 中按顺序建立这些材料,并赋予相应的属性。然后根据一定的规则把材料和单元对应起来

from py_mentat import *
# import the py_mentat module, which is foundamental 
class beam(object):
    def __init__(self, string):
        data = string.split(',')
        self.Nfloor = int(data[0])
        self.Nbeam = int(data[1])
        self.name = 'F'+data[0]+'L'+data[1]
class column(object):
    def __init__(self, string):
        data = string.split(',')
        self.Nfloor = int(data[0])
        self.Ncolu = int(data[1])
        self.name = 'F'+data[0]+'C'+data[1]

class node(object):
    ID=0
    x=0.0
    y=0.0
    z=0.0

def add_matl(name):

    py_send("*new_mater standard *mater_option general:state:solid *mater_option general:skip_structural:off")
    py_send("*mater_name %s" % name)
    py_send("*mater_param general:mass_density 2.5e-9")
    py_send("*mater_option structural:type:elast_plast_ortho")
    py_send("*mater_option structural:type:hypo_elast")
    py_send("*mater_option structural:hypoelastic_method:ubeam")
    py_send("*mater_option structural:damping:on")
    py_send("*mater_param structural:rayleigh_damping_stiff_mult 0.0136764")
    return
def beam_add(beams):
    # add elements for all materials
    # take-in parameter:beams, a list containing all the beam elements in order
    node_beams = {} # beam dictionary takes 'FXLX' as key
    for i in range(len(beams)):
        node_beams[beams[i].name]=[]
    py_send("*renumber_all")
    n = py_get_int("nelements()")
    for i in range(1,n+1):
    # acquire the ID of the nodes linked by one element, and do this procedure for each element
        node1=node()
        node1.ID=py_get_int("element_node_id(%d,%d)"%(i,1))
        node2=node()
        node2.ID=py_get_int("element_node_id(%d,%d)"%(i,2))

        node1.x=py_get_float("node_x(%d)"%node1.ID)
        node1.y=py_get_float("node_y(%d)"%node1.ID)
        node1.z=py_get_float("node_z (%d)"%node1.ID)

        node2.x=py_get_float("node_x(%d)"%node2.ID)
        node2.y=py_get_float("node_y(%d)"%node2.ID)
        node2.z=py_get_float("node_z (%d)"%node2.ID)

        if (node1.z ==node2.z):# it's a beam
            Nfloor = int(node1.z/4000)
            if(node1.x==node2.x):
                Nbeam = 4 + int(node1.x/5000) + int((node1.y+node2.y)/10000)*7
            else:
                Nbeam = 1 + int(node1.y/5000)*7 + int((node1.x+node2.x)/10000)
            name="F%dL%d"%(Nfloor,Nbeam)
            node_beams[name].append(i)
    
    for key in node_beams:
        py_send("*edit_mater %s"%key)
        py_send("*add_mater_elements")
        for j in range(len(node_beams[key])):
            str = "%d " % node_beams[key][j]
            py_send(str)
        py_send(" # ")
    return
def colu_add(columns):
    # add elements for all materials
    # take-in parameter:columns, a list containing all the column elements in order
    node_columns = {} # beam dictionary takes 'FXCX' as key
    for i in range(len(columns)):
        node_columns[columns[i].name]=[]
    py_send("*renumber_all")
    n = py_get_int("nelements()")
    for i in range(1,n+1):
        node1=node()
        node1.ID=py_get_int("element_node_id(%d,%d)"%(i,1))
        node2=node()
        node2.ID=py_get_int("element_node_id(%d,%d)"%(i,2))

        node1.x=py_get_float("node_x(%d)"%node1.ID)
        node1.y=py_get_float("node_y(%d)"%node1.ID)
        node1.z=py_get_float("node_z (%d)"%node1.ID)

        node2.x=py_get_float("node_x(%d)"%node2.ID)
        node2.y=py_get_float("node_y(%d)"%node2.ID)
        node2.z=py_get_float("node_z (%d)"%node2.ID)

        if ((node1.x==node2.x)and(node1.y == node2.y)):# it's a column
            Nfloor = int((node1.z+node2.z)/8000)+1
            Ncolu = int(node1.x/5000)+4*int(node1.y/5000)+1
            name="F%dC%d"%(Nfloor,Ncolu)
            node_columns[name].append(i)
    
    for key in node_columns:
        py_send("*edit_mater %s"%key)
        py_send("*add_mater_elements")
        for j in range(len(node_columns[key])):
            str = "%d " % node_columns[key][j]
            py_send(str)
        py_send(" # ")
    return
def main():
    beams = []
    with open('E:\\02_research\\06_firstblood\\01_model_PKPM\\ExportExcel\\section_beam.csv') as file:
        for content in file:
            list = content.split(',')
            if list[0] == 'Nfloor':
                continue
            new_beam = beam(content)
            beams.append(new_beam)
        file.close()
    for i in range(len(beams)):
        add_matl(beams[i].name)
    beam_add(beams)
    columns = []
    with open('E:\\02_research\\06_firstblood\\01_model_PKPM\\ExportExcel\\section_colu.csv') as file:
        for content in file:
            list = content.split(',')
            if list[0] == 'Nfloor':
                continue
            new_column = column(content)
            columns.append(new_column)
    for i in range(len(columns)):
        add_matl(columns[i].name)
    colu_add(columns)


    return


if __name__ == '__main__':
    py_connect("", 40007)
    main()
    py_disconnect()

发布了1 篇原创文章 · 获赞 0 · 访问量 24

猜你喜欢

转载自blog.csdn.net/LokeHome/article/details/104057607