XIAN-FEM-2026June/三维matlab代码/common/export_phy_to_json.m

513 lines
8.4 KiB
Matlab
Raw 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_phy_to_json(phy, jsonFile, cfg)
%EXPORT_PHY_TO_JSON 由 phy + case_config 生成 OpticsFEM 散射 JSON通用
% BoundaryFlag(i) = 网格面域 DomainOfTri 编号 i 的边界类型0 PMC, 2 SBC, 4 PBC
if nargin < 1 || isempty(phy)
if ~exist('case_config', 'file')
error('未传入 phy且当前目录无 case_config.m');
end
[phy, cfg] = case_config();
if nargin < 2 || isempty(jsonFile)
jsonFile = fullfile(pwd, cfg.jsonFile);
end
elseif nargin < 3 || isempty(cfg)
if exist('case_config', 'file')
[~, cfg] = case_config();
else
cfg = struct();
end
cfg = fill_cfg_defaults(cfg, phy);
if nargin < 2 || isempty(jsonFile)
if isfield(cfg, 'jsonFile')
jsonFile = fullfile(pwd, cfg.jsonFile);
else
jsonFile = fullfile(pwd, 'sbc3d.json');
end
end
else
cfg = fill_cfg_defaults(cfg, phy);
end
outFaces = phy.out(:)';
incFaces = phy.inc(:)';
sbcIndex = unique([outFaces, incFaces], 'stable');
nSbc = numel(sbcIndex);
sbcType = zeros(1, nSbc);
for k = 1:nSbc
if ismember(sbcIndex(k), incFaces)
sbcType(k) = 1;
else
sbcType(k) = 0;
end
end
[nbrBoundary, boundaryFlag] = infer_boundary_flag(phy, cfg);
nDom = numel(phy.eps);
doc = struct();
doc.FemType = cfg.FemType;
doc.EletricType = cfg.EletricType;
doc.lambda = phy.lda0;
doc.NbrBoundary = nbrBoundary;
doc.BoundaryFlag = boundaryFlag;
if isfield(phy, 'src') && isfield(phy, 'dst') && ~isempty(phy.src)
if isfield(cfg, 'pbcPhi')
pbcPhi = cfg.pbcPhi;
else
pbcPhi = exp(1i * 2 * pi / 6);
end
if isfield(cfg, 'pbcAngle')
pbcAngle = cfg.pbcAngle;
else
pbcAngle = pi / 3;
end
doc.pbc = struct( ...
'srcIndex', phy.src(:)', ...
'dstIndex', phy.dst(:)', ...
'phiR', real(pbcPhi(:)'), ...
'phiI', imag(pbcPhi(:)'), ...
'pbcAngle', pbcAngle);
end
doc.sbc = struct( ...
'Index', sbcIndex, ...
'SBCType', sbcType, ...
'E0x', {repmat({num2str(phy.Einc(1))}, 1, nSbc)}, ...
'E0y', {repmat({num2str(phy.Einc(2))}, 1, nSbc)}, ...
'E0z', {repmat({num2str(phy.Einc(3))}, 1, nSbc)}, ...
'kx', zeros(1, nSbc), ...
'ky', zeros(1, nSbc), ...
'kz', zeros(1, nSbc));
doc.NbrDomain = nDom;
doc.domainType = repmat(2, 1, nDom);
doc.domainIndex = 0:(nDom - 1);
doc.matType = zeros(1, nDom);
doc.epsilonrR = phy.eps(:)';
doc.epsilonrI = zeros(1, nDom);
doc.murR = phy.mur(:)';
doc.murI = zeros(1, nDom);
doc.chiheR = zeros(1, nDom);
doc.chiehR = zeros(1, nDom);
doc.chiheI = zeros(1, nDom);
doc.chiehI = zeros(1, nDom);
doc.sigma = zeros(1, nDom);
doc.n = ones(1, nDom);
doc.k = zeros(1, nDom);
doc.MeshFile = cfg.MeshFile;
doc.OutFile = cfg.OutFile;
txt = pretty_json(doc);
fid = fopen(jsonFile, 'w');
if fid < 0
error('无法写入: %s', jsonFile);
end
cleanup = onCleanup(@() fclose(fid));
fprintf(fid, '%s', txt);
fprintf('已写出 %s (%d 字节, lambda=%.4g, NbrBoundary=%d)\n', ...
jsonFile, length(txt), phy.lda0, doc.NbrBoundary);
end
function cfg = fill_cfg_defaults(cfg, phy)
if nargin < 2, phy = struct(); end
if ~isfield(cfg, 'FemType'), cfg.FemType = 4; end
if ~isfield(cfg, 'EletricType'), cfg.EletricType = 2; end
if ~isfield(cfg, 'MeshFile'), cfg.MeshFile = 'SBCmesh.dat'; end
if ~isfield(cfg, 'OutFile'), cfg.OutFile = './OutFile'; end
if ~isfield(cfg, 'NbrBoundary') || ~isfield(cfg, 'BoundaryFlag')
[cfg.NbrBoundary, cfg.BoundaryFlag] = infer_boundary_flag(phy, cfg);
end
end
function [nbrBoundary, boundaryFlag] = infer_boundary_flag(phy, cfg)
% Prefer explicit cfg; else build from phy face domains (PBC case 1..9).
if isfield(cfg, 'NbrBoundary') && isfield(cfg, 'BoundaryFlag') ...
&& numel(cfg.BoundaryFlag) == cfg.NbrBoundary
nbrBoundary = cfg.NbrBoundary;
boundaryFlag = cfg.BoundaryFlag;
return;
end
if isfield(phy, 'src') && isfield(phy, 'dst') && ~isempty(phy.src)
allDom = [phy.src(:); phy.dst(:); phy.out(:); phy.inc(:)];
nbrBoundary = max(allDom);
boundaryFlag = zeros(1, nbrBoundary);
for d = 1:nbrBoundary
if ismember(d, [phy.src(:); phy.dst(:)])
boundaryFlag(d) = 4;
elseif ismember(d, [phy.out(:); phy.inc(:)])
boundaryFlag(d) = 2;
else
boundaryFlag(d) = 0;
end
end
return;
end
% Legacy SBC full model (14 COMSOL boundaries)
nbrBoundary = 14;
boundaryFlag = [0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2];
end
function txt = pretty_json(doc)
lines = cell(1, 50);
n = 0;
n = n + 1; lines{n} = '{';
n = n + 1; lines{n} = sprintf(' "FemType": %d,', doc.FemType);
n = n + 1; lines{n} = sprintf(' "EletricType": %d,', doc.EletricType);
n = n + 1; lines{n} = sprintf(' "lambda": %s,', json_num(doc.lambda));
n = n + 1; lines{n} = sprintf(' "NbrBoundary": %d,', doc.NbrBoundary);
n = n + 1; lines{n} = sprintf(' "BoundaryFlag": %s,', json_int_array(doc.BoundaryFlag));
if isfield(doc, 'pbc')
n = n + 1; lines{n} = ' "pbc": {';
n = n + 1; lines{n} = sprintf(' "srcIndex": %s,', json_int_array(doc.pbc.srcIndex));
n = n + 1; lines{n} = sprintf(' "dstIndex": %s,', json_int_array(doc.pbc.dstIndex));
n = n + 1; lines{n} = sprintf(' "phiR": %s,', json_float_array(doc.pbc.phiR));
n = n + 1; lines{n} = sprintf(' "phiI": %s,', json_float_array(doc.pbc.phiI));
n = n + 1; lines{n} = sprintf(' "pbcAngle": %s', json_num(doc.pbc.pbcAngle));
n = n + 1; lines{n} = ' },';
end
n = n + 1; lines{n} = ' "sbc": {';
n = n + 1; lines{n} = sprintf(' "Index": %s,', json_int_array(doc.sbc.Index));
n = n + 1; lines{n} = sprintf(' "SBCType": %s,', json_int_array(doc.sbc.SBCType));
n = n + 1; lines{n} = sprintf(' "E0x": %s,', json_str_array(doc.sbc.E0x));
n = n + 1; lines{n} = sprintf(' "E0y": %s,', json_str_array(doc.sbc.E0y));
n = n + 1; lines{n} = sprintf(' "E0z": %s,', json_str_array(doc.sbc.E0z));
n = n + 1; lines{n} = sprintf(' "kx": %s,', json_int_array(doc.sbc.kx));
n = n + 1; lines{n} = sprintf(' "ky": %s,', json_int_array(doc.sbc.ky));
n = n + 1; lines{n} = sprintf(' "kz": %s', json_int_array(doc.sbc.kz));
n = n + 1; lines{n} = ' },';
n = n + 1; lines{n} = sprintf(' "NbrDomain": %d,', doc.NbrDomain);
n = n + 1; lines{n} = sprintf(' "domainType": %s,', json_int_array(doc.domainType));
n = n + 1; lines{n} = sprintf(' "domainIndex": %s,', json_int_array(doc.domainIndex));
n = n + 1; lines{n} = sprintf(' "matType": %s,', json_int_array(doc.matType));
n = n + 1; lines{n} = sprintf(' "epsilonrR": %s,', json_float_array(doc.epsilonrR));
n = n + 1; lines{n} = sprintf(' "epsilonrI": %s,', json_float_array(doc.epsilonrI));
n = n + 1; lines{n} = sprintf(' "murR": %s,', json_float_array(doc.murR));
n = n + 1; lines{n} = sprintf(' "murI": %s,', json_float_array(doc.murI));
n = n + 1; lines{n} = sprintf(' "chiheR": %s,', json_float_array(doc.chiheR));
n = n + 1; lines{n} = sprintf(' "chiehR": %s,', json_float_array(doc.chiehR));
n = n + 1; lines{n} = sprintf(' "chiheI": %s,', json_float_array(doc.chiheI));
n = n + 1; lines{n} = sprintf(' "chiehI": %s,', json_float_array(doc.chiehI));
n = n + 1; lines{n} = sprintf(' "sigma": %s,', json_float_array(doc.sigma));
n = n + 1; lines{n} = sprintf(' "n": %s,', json_float_array(doc.n));
n = n + 1; lines{n} = sprintf(' "k": %s,', json_float_array(doc.k));
n = n + 1; lines{n} = sprintf(' "MeshFile": "%s",', doc.MeshFile);
n = n + 1; lines{n} = sprintf(' "OutFile": "%s"', doc.OutFile);
n = n + 1; lines{n} = '}';
lines = lines(1:n);
txt = join_lines(lines);
end
function s = join_lines(lines)
if isempty(lines)
s = '';
return;
end
s = lines{1};
for i = 2:numel(lines)
s = [s, sprintf('\n'), lines{i}]; %#ok<AGROW>
end
end
function s = json_num(x)
s = num2str(x, '%.16g');
end
function s = json_int_array(v)
v = v(:)';
parts = cell(1, numel(v));
for i = 1:numel(v)
parts{i} = sprintf('%d', round(v(i)));
end
s = sprintf('[%s]', join_csv(parts));
end
function s = json_float_array(v)
v = v(:)';
parts = cell(1, numel(v));
for i = 1:numel(v)
parts{i} = num2str(v(i), '%.16g');
end
s = sprintf('[%s]', join_csv(parts));
end
function s = json_str_array(c)
parts = cell(1, numel(c));
for i = 1:numel(c)
parts{i} = sprintf('"%s"', char(c{i}));
end
s = sprintf('[%s]', join_csv(parts));
end
function s = join_csv(parts)
if isempty(parts)
s = '';
elseif numel(parts) == 1
s = parts{1};
else
s = parts{1};
for i = 2:numel(parts)
s = [s, ', ', parts{i}]; %#ok<AGROW>
end
end
end