用python调用comsol

python for comsol

https://github.com/MPh-py/MPh

comsol有java和matlab的接口,参考手册不是太好看. MPh这个库是用python写了个java的接口去调用comsol. MPh有两种使用方式,一是直接使用提供的python接口,它比较简单,可以满足一般性的数据交互需要,但是功能不太完整;另外就是直接调用拿python封装好的"java"对象,这相当于是在使用comsol官方提供的java接口,功能比较齐全,文档也相对更全一些. 当然这两种方法是可以同时使用的,因为只是接口不同,本质上都是控制后面的comsol引擎.

2D multifinger chip

上面具有数量、宽度、间距均为变量的热源分布,热源平面上的非热源区域为绝热条件,左右两侧为绝热边界条件,下侧为热沉. 下面的code实现了建模、边界条件设置、参数化扫描、以及结果导出的实现.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# 创建一个引擎,用引擎生成一个模型.
client = mph.start(cores=1)
client.clear()
py_model = client.create("Model")
java_model = py_model.java

# 创建组件comp1,设置comp1的维度为2D
comp1 = java_model.modelNode().create("comp1")

# 创建参数
number_of_sources = 4

java_model.param().set("wg", 0.5e-6)
java_model.param().set("d", 50e-6)
java_model.param().set("w", 1000e-6)
java_model.param().set("t", 2e-6)

# 在comp1中建立一个几何geom1
java_model.geom().create("geom1", 2)

# 在geom1中画一个channel方块
java_model.geom("geom1").feature().create("r1", "Rectangle")
java_model.geom("geom1").feature("r1").set("size", ("w", "t"))
java_model.geom("geom1").feature("r1").set("pos", ["0", "0"])

# 用循环画上多热源边界
for i in range(number_of_sources):
java_model.geom("geom1").feature().create("ls{}".format(i), "LineSegment")
java_model.geom("geom1").feature("ls{}".format(i)).set("specify1", "coord")
java_model.geom("geom1").feature("ls{}".format(i)).set("specify2", "coord")
java_model.geom("geom1").feature("ls{}".format(i)).set(
"coord1", ("25e-6 + d * {} - wg/2".format(i), "t")
)
java_model.geom("geom1").feature("ls{}".format(i)).set(
"coord2", ("25e-6 + d * {} + wg/2".format(i), "t")
)
java_model.geom("geom1").run("fin")

# 自定义一个'GaN'材料
GaN = java_model.component("comp1").material().create("GaN")
GaN.materialmodel("def").set("density", 400)
GaN.materialmodel("def").set("heatcapacity", 2e3)
GaN.materialmodel("def").set("thermalconductivity", 150)

# 设置物理场和边界条件

## 设置区域1的材料为GaN
physics = java_model.physics().create("ht", "HeatTransfer", "geom1")
solid = physics.feature("solid1")
solid.set("k_mat", 1, "from_mat")
init = physics.feature("init1")
init.set("T", 1, "300[K]")

## 设置边界条件
temp = physics.feature().create("temp1", "TemperatureBoundary", 1)
source = physics.feature().create("hs1", "HeatFluxBoundary", 1)

temp.selection().set([2])
temp.set("T0", 1, "300[K]")

source.selection().set([4 + 2 * i for i in range(number_of_sources)])
source.set("q0", 1, "1e10")

# 画网格
comp1.mesh().create("mesh1")

# 添加tag为std1的研究
std_case = java_model.study().create("std1")

## 在std1中添加一个tag为stat的稳态研究
std_case.feature().create("stat", "Stationary")

## 在std1中添加一个tag为param的参数化研究
std_case.feature().create("param", "Parametric")
std_case.feature("param").setIndex('pname', 'wg', 0)
std_case.feature("param").setIndex('plistarr', [0.5e-6, 1e-6], 0)
std_case.feature("param").setIndex('pname', 'd', 1)
std_case.feature("param").setIndex('plistarr', [50e-6, 100e-6], 1)
std_case.feature("param").set('sweeptype', 'filled')

# 计算
std_case.run()

# 建立1维绘图组
pg1 = java_model.result().create("plot1", 1)
pg1.set("data", "dset1")
line1 = pg1.feature().create("line1", "LineGraph")
line1.selection().set(range(3, number_of_sources * 2 + 4 + 1))
line1.run()

# 导出一维绘图组数据
export1 = java_model.result().export().create('export1', 'Plot')
export1.set('plotgroup', 'plot1')
export1.set('filename', 'surface.txt')
export1.run()

# 导出温度场
data1 = java_model.result().export().create('data1', 'Data')
data1.set('data', 'dset1')
data1.setIndex('expr', 'T', 2)
data1.set('filename', 'temp.txt')
data1.run()

# 也可以画一个温度场
pg2 = java_model.result().create('plot2', 2)
pg2.set('data', 'dset1')
surface = pg2.create('surface', 'Surface')
pg2.run()

# 保存模型
java_model.save('model1')

当然,如果想直接获取温度场,或者模型已经建好了想简单地改一改参数,直接用mph提供的接口就可以了,

1
(x, y, T) = py_model.evaluate(['x', 'y', 'T'])

具体的操作可以参考 https://mph.readthedocs.io/en/stable/ ,当然,它的文档就更简略了.

一些说明

mph只是java的一个包装,而java或者matlab调用comsol的API都是类似的,基本使用操作可以参考 https://cn.comsol.com/blogs/automate-modeling-tasks-comsol-api-use-java/ . 这种调用实际上就相当于把GUI操作的流程代码化. 稍微简要整理一下整体的图像.

comsol是按照节点树的方式来整理一次模拟中的各个部分的,可以看一下上图的界面. 所打开的comsol的.mph文件相当于Linux系统中的根目录,这个组件包括了全度定义,组件,研究和结果四部分. 组件中包括了我们要模拟的对象的具体定义,其又可以划分为定义、几何、材料、物理场和网格五部分. 研究中可以包含不同的模拟设置,比如定义一个研究去研究baseline的稳态解,定义另一个研究去作某个变量的参数化扫描. 结果中包含Dataset、派升值、表格、绘图组和数据导出几部分. 这些层级不同的各个部分就像节点树一样,从根节点向下逐层展开,每一个子节点都是父节点的一个对象.

凡是在节点树中有显示的对象,其都叫作对应父节点的一个feature. 在调用中,可以用比如

1
java_model.geom("geom1").feature().create("r1", "Rectangle")

这样的方式在几何中生成一个矩形. 每一个对象都有它的唯一的tag,用来帮助comsol调用这个对象. 在上面这个语句中,我们用create方法在tag为geom1的几何中创建一个矩形,并把生成的这个矩形的tag赋值为r1. 有了tag后,我们就可以用set()方法来更改这个对象的属性,

1
java_model.geom("geom1").feature("r1").set("size", ("w", "t"))

上面这句话就是一个树形的调用逻辑. 其他各种部分的基本逻辑都是类似的,可以看到左边节点树中每一个对象都有它的唯一的一个tag.

注意set类的东西第一个参数是参数名(参数类别),第二个参数是参数值;create第一个参数是要create的这个对象的tag,第二个参数是这个参数的类别,有时候后面会跟第三个参数维度;setIndex这个方法是用来对长得像表格一类得东西赋值得,比如

selection方法是针对在GUI中用鼠标点击模型中每个边或者面的操作的,比如