XIAN-FEM-2026June/三维matlab代码/matlab 3D一阶散射问题/export_comsol_normE_from_dat.m

137 lines
4.2 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 export_comsol_normE_from_dat(varargin)
%EXPORT_COMSOL_NORME_FROM_DAT 按 dat 中 Vertex 顺序从 COMSOL 插值 normE
%
% export_comsol_normE_from_dat
% export_comsol_normE_from_dat('normExpr', 'ewfd.Ex*conj(ewfd.Ex)+...')
% export_comsol_normE_from_dat('exExpr', 'ewfd.Ex', 'eyExpr', 'ewfd.Ey', 'ezExpr', 'ewfd.Ez')
%
% 若 normExpr 未指定或为空,将自动探测 Ex/Ey/Ez 并组合成 normE。
% 若模型没有预定义 normE 变量emw.normE 报错即属此类),请用自动探测或手动指定分量。
opts = parseOpts(varargin);
datPath = opts.datFile;
if ~isfile(datPath)
error('找不到网格文件: %s请先 getMesh + export 生成 SBCmesh.dat', datPath);
end
if ~isfile(opts.mphFile)
error('找不到 COMSOL 模型: %s', opts.mphFile);
end
[V, nbr] = load_dat_vertices(datPath);
fprintf('已从 %s 读取 %d 个顶点dat 顺序)\n', datPath, nbr);
model = mphload(opts.mphFile);
coord = V.'; % mphinterp: 3×N
probeCoord = mean(V, 1).';
if opts.autoDetect
info = resolve_comsol_e_field(model, probeCoord);
if isempty(opts.exExpr)
opts.exExpr = info.exExpr;
opts.eyExpr = info.eyExpr;
opts.ezExpr = info.ezExpr;
end
if isempty(opts.normExpr)
opts.normExpr = info.normExpr;
end
end
if isempty(opts.normExpr)
if isempty(opts.exExpr)
error(['未指定 normExpr且自动探测失败。\n', ...
'请先运行 probe_comsol_fields或手动传入 ex/ey/ez 表达式。']);
end
opts.normExpr = sprintf('sqrt(%s*conj(%s)+%s*conj(%s)+%s*conj(%s))', ...
opts.exExpr, opts.exExpr, opts.eyExpr, opts.eyExpr, opts.ezExpr, opts.ezExpr);
end
fprintf('正在插值 normE 表达式:\n %s\n', opts.normExpr);
normE = mphinterp(model, opts.normExpr, 'coord', coord);
normE = real(normE(:));
if numel(normE) ~= nbr
error('插值结果长度 %d 与顶点数 %d 不一致', numel(normE), nbr);
end
nanMask = isnan(normE) | isinf(normE);
if any(nanMask)
warning('export_comsol_normE:NaN', ...
'%d 个顶点插值为 NaN/Inf可能落在网格外或未求解', nnz(nanMask));
end
if opts.exportComponents
fprintf('正在插值 Ex/Ey/Ez ...\n');
Ex = mphinterp(model, opts.exExpr, 'coord', coord);
Ey = mphinterp(model, opts.eyExpr, 'coord', coord);
Ez = mphinterp(model, opts.ezExpr, 'coord', coord);
end
if ~exist(opts.outDir, 'dir')
mkdir(opts.outDir);
end
writeNormE(fullfile(opts.outDir, 'normE'), normE);
if opts.exportComponents
writeComplexField(fullfile(opts.outDir, 'Ex'), Ex);
writeComplexField(fullfile(opts.outDir, 'Ey'), Ey);
writeComplexField(fullfile(opts.outDir, 'Ez'), Ez);
end
if opts.exportTable
T = [(1:nbr).', V, normE];
writematrix(T, fullfile(opts.outDir, 'vertex_normE.dat'), 'Delimiter', 'tab');
end
metaFile = fullfile(opts.outDir, 'comsol_expr.txt');
fid = fopen(metaFile, 'w');
if fid > 0
fprintf(fid, 'normExpr=%s\n', opts.normExpr);
fprintf(fid, 'exExpr=%s\n', opts.exExpr);
fprintf(fid, 'eyExpr=%s\n', opts.eyExpr);
fprintf(fid, 'ezExpr=%s\n', opts.ezExpr);
fclose(fid);
end
fprintf('已写出 %s\n', fullfile(opts.outDir, 'normE'));
fprintf(' max(normE) = %.12g\n', max(normE(~nanMask)));
fprintf(' 行顺序与 %s 的 Vertex 第 1..%d 行一一对应\n', datPath, nbr);
end
function opts = parseOpts(args)
p = inputParser;
p.addParameter('mphFile', 'SBC.mph', @ischar);
p.addParameter('datFile', 'SBCmesh.dat', @ischar);
p.addParameter('normExpr', '', @ischar);
p.addParameter('exExpr', '', @ischar);
p.addParameter('eyExpr', '', @ischar);
p.addParameter('ezExpr', '', @ischar);
p.addParameter('outDir', 'OutFile_comsol', @ischar);
p.addParameter('exportComponents', false, @islogical);
p.addParameter('exportTable', true, @islogical);
p.addParameter('autoDetect', true, @islogical);
p.parse(args{:});
opts = p.Results;
end
function writeNormE(path, normE)
fid = fopen(path, 'w');
if fid < 0
error('无法写入: %s', path);
end
c = onCleanup(@() fclose(fid));
fprintf(fid, '//\n');
fprintf(fid, '%.12g\n', normE);
end
function writeComplexField(path, field)
fid = fopen(path, 'w');
if fid < 0
error('无法写入: %s', path);
end
c = onCleanup(@() fclose(fid));
fprintf(fid, '//\n');
fprintf(fid, '%.12g %.12g\n', [real(field(:)), imag(field(:))].');
end