function exportPortModesFem2(outFile)
%EXPORTPORTMODESFEM2  导出 MainFem2 / MeshData2 数值端口模态 (port_modes.json)

if nargin < 1
    outFile = fullfile(fileparts(mfilename('fullpath')), '..', '..', ...
        '3D opticsfem-master', 'port', 'Release', 'port_modes.json');
end

rootDir = fileparts(mfilename('fullpath'));
load(fullfile(rootDir, 'MeshData2.mat'), 'Mesh');
[Physic, Material, Port1Solver, Port2Solver] = configPhysicMaterialFem4();

Port1Mesh = GetBMesh(Mesh.Nodes, Mesh.Faces, Mesh.FacesIndex, Physic.Port1);
[Port1Solver, Port1Mesh] = BoundaryEigenMode(Port1Mesh, Physic, Material, Port1Solver);
Port1Solver = GetPowerCoef(Port1Solver, Port1Mesh, Material.murF, 1);
Port1Mesh.normal = [0; 0; -1];

Port2Mesh = GetBMesh(Mesh.Nodes, Mesh.Faces, Mesh.FacesIndex, Physic.Port2);
[Port2Solver, Port2Mesh] = BoundaryEigenMode(Port2Mesh, Physic, Material, Port2Solver);
Port2Mesh.normal = [0; 0; 1];

el2no = Mesh.Elements';
f1 = el2no([1 1 1 2], :);
f2 = el2no([2 2 3 3], :);
f3 = el2no([3 4 4 4], :);
f_array = [f1(:) f2(:) f3(:)];
[Faces, ~, FacesOfElements] = unique(f_array, 'rows');
Port1Mesh.FacesConn = GetBFacesConn(Port1Mesh.OldFaces, Faces, FacesOfElements);
Port2Mesh.FacesConn = GetBFacesConn(Port2Mesh.OldFaces, Faces, FacesOfElements);

js.input = packPort(Port1Mesh, Port1Solver, 1);
js.output = packPort(Port2Mesh, Port2Solver, 2);

fid = fopen(outFile, 'w');
fprintf(fid, '%s', jsonencode(js));
fclose(fid);
fprintf('Exported port modes (MeshData2) -> %s\n', outFile);
fprintf('powerCoef=%g  gamma1=(%g,%g)\n', Port1Solver.powerCoef, ...
    real(Port1Solver.gamma(1)), imag(Port1Solver.gamma(1)));

end

function p = packPort(PortMesh, PortSolver, ptype)
nf = size(PortMesh.NewFaces, 1);
edgeOfFace = zeros(nf, 3);
for n = 1:nf
    for i = 1:3
        edgeOfFace(n, i) = PortMesh.EdgesOfElements((n - 1) * 3 + i) - 1;
    end
end
ez = PortSolver.Ez(:, 1);
et = PortSolver.Et(:, 1);
p = struct( ...
    'type', ptype, ...
    'gamma', [real(PortSolver.gamma(1)), imag(PortSolver.gamma(1))], ...
    'powerCoef', getPowerCoef(PortSolver), ...
    'normal', PortMesh.normal(:)', ...
    'facesConn', PortMesh.FacesConn, ...
    'portNewFaces', PortMesh.NewFaces - 1, ...
    'portEdgeOfFace', edgeOfFace, ...
    'portNodes', PortMesh.Nodes, ...
    'Ez_re', real(ez(:)), 'Ez_im', imag(ez(:)), ...
    'Et_re', real(et(:)), 'Et_im', imag(et(:)));
end

function c = getPowerCoef(PortSolver)
if isfield(PortSolver, 'powerCoef')
    c = PortSolver.powerCoef;
else
    c = 1.0;
end
end
