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 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 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 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