XIAN-FEM-2026June/三维matlab代码/matlab 3D一阶基 + bele/resolve_comsol_e_field.m

119 lines
3.6 KiB
Matlab
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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