COMSOL link with Matlab,批量创建几何并创建selection方便后续选定
写在开头
大大小小计算软件用了几款,COMSOL是给我感觉UI最简洁明了干净漂亮,功能相对来说最齐全的基于有限元的仿真软件,但是COMSOL也是接口做的最狗屎的仿真软件没有之一,matlab的接口环境做的让我感觉当时写这个的工程师是不是脑子被驴踢了,混乱的变量名,极其不方便的调用让我每次用都能恶心死(所以这软件真的很少用),最关键的是文档写的跟狗屎一样。
问题
1.问题背景
假设我们现在需要创建100个不同的柱子,并且有一百种材料,需要分别选择到对应的柱子上。
2.思路分析
对于其他软件,比如Lumerical FDTD,创建几何物体的时候可以直接在几何对象里面设置材料属性,这个是比较简洁舒适的;但是COMSOL里面材料和几何被分到了两个独立的模块,常规思路就是:创建几何(有个唯一标签)=》创建材料(也有个唯一标签)=》直接用标签把需要的两个东西关联起来,这样就大功告成了。
这就是很正常,很简洁的思路,但是COMSOL逆天的地方来了 ,COMSOL链接Matlab后,创建几何时需要在matlab里面创建一个matlab的唯一变量
v_matlab = geom.feature.create('tag_comsol', 'Block');
就像上面代码里写的,v_matlab是matlab里面的变量,tag_comsol是COMSOL里面的标签(创建完在COMSOL的UI界面里面就改不了了,唯一标识),两个都是唯一标识,但是在你后续想选择这个几何对象的时候,这个两个标识一个都不能用,得先创建一个selection,然而在创建这个selection的时候,你也不能调用这两个唯一标识,把物体放在你要创建的selection中,你得调用一个不知道是什么逻辑(我试过了,不是创建的先后顺序,是会一直变的)产生的域/面/线/点标签才能把你想要的对象包括进去。
确实这样一看逻辑很严密清晰,和COMSOL的底层逻辑很搭,但是接口写的跟狗屎一样,属于是眼高手低,也没个优化方案,代码臃肿的不成样,最主要是文档写的也不清不楚的。
3.解决方案
3.1 循环中可变的变量名
matlab里面使用eval函数:
eval(expression) %eval可以将括号里字符串当成指令运行,直观理解就是可以去掉一个“ ”
eval('1+3');
1+3; %上下两式等效
eval网上解释用法比较多,不多赘述,不懂的可以查其他贴
3.2 调用几何对象
这个是本帖的重点,主要是下面这个自动生成selection的设置打开,代码放在每次你创建的几何对象下面,blk是该几何对象在matlab中的变量名,这个设置的功能是会在你每次创建几何对象时,自动生成下面四个selection,注意,这四个selection在COMSOL或者Matlab中都找不到的,但是你可以调用,生成的格式是:geom是你一开始创建几何这个类的类名,blk是几何对象名,后面那个对应域,面,边,点。
blk.set('createselection', 'on');
model.selection.tags
ans =
java.lang.String[]:
'geom_blk_pnt'
'geom_blk_edg'
'geom_blk_bnd'
'geom_blk_dom'
3.3 整体代码
% 创建模型,组件,几何
model = ModelUtil.create('Model');
comp1 = model.component.create('comp1', true);
geom1 = comp1.geom.create('geom1', 3);
% 循环产生不同的几何对象,材料对象,并对应选择,
for i =1:length(index_array)
for j = 1:length(index_array)
%产生一个可以变化的变量名称
str_geo=strcat('geo',num2str(i),'l',num2str(j));
str_mat=strcat('mat',num2str(i),'l',num2str(j));
%创建几何,几何名字为str_geo(变化的)
eval([str_geo,'= geom1.feature.create(str_geo,''Block'')']);
eval([str_geo,'.set(''size'',[pixel_length pixel_length gh])']);
eval([str_geo,'.set(''base'',''center'')']);
eval([str_geo,'.set(''pos'',[-sx/2+pixel_length/2+(i-1)*pixel_length sy/2-pixel_length/2-(j-1)*pixel_length -sz/2+dpml+dsub+gh/2])']);
eval([str_geo,'.set(''createselection'', ''on'')'])
%创建材料,材料名字为str_mat(变化的)
eval([str_mat,'= comp1.material.create(','str_mat',')']);
eval(['def =',str_mat,'.materialModel(','"def"',')']);
def.set('relpermittivity',index_array(i,j)^2);
%把str_mat的材料选择到str_geo的几何上面
eval(['comp1.material(str_mat).selection.named("geom1_',str_geo,'_dom")']);
end
end