119 lines
3.6 KiB
Matlab
119 lines
3.6 KiB
Matlab
function info = resolve_comsol_e_field(model, coordProbe)
|
||
%RESOLVE_COMSOL_E_FIELD 自动探测 COMSOL 模型中可用的 Ex/Ey/Ez 表达式
|
||
%
|
||
% info = resolve_comsol_e_field(model)
|
||
% info = resolve_comsol_e_field(model, coordProbe) % 3×1 或 1×3
|
||
%
|
||
% 返回 info.tag, info.exExpr, info.eyExpr, info.ezExpr, info.normExpr
|
||
|
||
if nargin < 2 || isempty(coordProbe)
|
||
coordProbe = [0; 0; 0];
|
||
end
|
||
coordProbe = coordProbe(:);
|
||
if numel(coordProbe) ~= 3
|
||
error('coordProbe 必须是 3 元坐标');
|
||
end
|
||
|
||
physicsTags = listPhysicsTags(model);
|
||
if isempty(physicsTags)
|
||
physicsTags = {'emw', 'ewfd', 'emw2', 'ewfd2', 'wfd'};
|
||
end
|
||
|
||
componentNames = {'Ex', 'Ey', 'Ez'; ...
|
||
'Efieldx', 'Efieldy', 'Efieldz'; ...
|
||
'Ex_i', 'Ey_i', 'Ez_i'};
|
||
|
||
failMsgs = strings(0, 1);
|
||
|
||
for t = 1:numel(physicsTags)
|
||
tag = physicsTags{t};
|
||
for r = 1:size(componentNames, 1)
|
||
ex = sprintf('%s.%s', tag, componentNames{r, 1});
|
||
ey = sprintf('%s.%s', tag, componentNames{r, 2});
|
||
ez = sprintf('%s.%s', tag, componentNames{r, 3});
|
||
[ok, msg] = tryFieldTriplet(model, coordProbe, ex, ey, ez);
|
||
if ok
|
||
info.tag = tag;
|
||
info.exExpr = ex;
|
||
info.eyExpr = ey;
|
||
info.ezExpr = ez;
|
||
info.normExpr = buildNormExpr(ex, ey, ez);
|
||
info.probeCoord = coordProbe;
|
||
fprintf('已识别电场变量: %s / %s / %s\n', ex, ey, ez);
|
||
return;
|
||
end
|
||
failMsgs(end + 1, 1) = string(msg); %#ok<AGROW>
|
||
end
|
||
end
|
||
|
||
% 尝试不依赖 physics tag 的全局变量
|
||
globalCandidates = {
|
||
'Ex', 'Ey', 'Ez'
|
||
'E_x', 'E_y', 'E_z'
|
||
};
|
||
for r = 1:size(globalCandidates, 1)
|
||
ex = globalCandidates{r, 1};
|
||
ey = globalCandidates{r, 2};
|
||
ez = globalCandidates{r, 3};
|
||
[ok, msg] = tryFieldTriplet(model, coordProbe, ex, ey, ez);
|
||
if ok
|
||
info.tag = '';
|
||
info.exExpr = ex;
|
||
info.eyExpr = ey;
|
||
info.ezExpr = ez;
|
||
info.normExpr = buildNormExpr(ex, ey, ez);
|
||
info.probeCoord = coordProbe;
|
||
fprintf('已识别电场变量: %s / %s / %s\n', ex, ey, ez);
|
||
return;
|
||
end
|
||
failMsgs(end + 1, 1) = string(msg); %#ok<AGROW>
|
||
end
|
||
|
||
fprintf('\n未能自动识别 Ex/Ey/Ez。已尝试的 physics 标签:\n');
|
||
disp(physicsTags');
|
||
fprintf('\n请在 COMSOL 结果浏览器中查看变量名,然后手动指定,例如:\n');
|
||
fprintf(' export_comsol_normE_from_dat(''normExpr'', ''ewfd.Ex*conj(ewfd.Ex)+...'')\n');
|
||
fprintf(' export_comsol_normE_from_dat(''exExpr'', ''ewfd.Ex'', ''eyExpr'', ''ewfd.Ey'', ''ezExpr'', ''ewfd.Ez'')\n\n');
|
||
|
||
error('resolve_comsol_e_field:NotFound', ...
|
||
'无法自动识别电场表达式。请用 probe_comsol_fields 查看可用变量。');
|
||
end
|
||
|
||
function tags = listPhysicsTags(model)
|
||
tags = {};
|
||
compTags = {'comp1', 'comp2', 'comp3'};
|
||
for c = 1:numel(compTags)
|
||
try
|
||
comp = model.java.component(compTags{c});
|
||
pt = comp.physics.tags;
|
||
for i = 1:pt.length
|
||
tags{end + 1} = char(pt(i)); %#ok<AGROW>
|
||
end
|
||
catch
|
||
end
|
||
end
|
||
tags = unique(tags, 'stable');
|
||
end
|
||
|
||
function [ok, msg] = tryFieldTriplet(model, coordProbe, ex, ey, ez)
|
||
ok = false;
|
||
msg = '';
|
||
try
|
||
vx = mphinterp(model, ex, 'coord', coordProbe);
|
||
vy = mphinterp(model, ey, 'coord', coordProbe);
|
||
vz = mphinterp(model, ez, 'coord', coordProbe);
|
||
if isempty(vx) || isnan(vx) || isnan(vy) || isnan(vz)
|
||
msg = sprintf('%s/%s/%s -> NaN', ex, ey, ez);
|
||
return;
|
||
end
|
||
ok = true;
|
||
catch ME
|
||
msg = sprintf('%s/%s/%s -> %s', ex, ey, ez, ME.message);
|
||
end
|
||
end
|
||
|
||
function expr = buildNormExpr(ex, ey, ez)
|
||
expr = sprintf('sqrt(%s*conj(%s)+%s*conj(%s)+%s*conj(%s))', ...
|
||
ex, ex, ey, ey, ez, ez);
|
||
end
|