function export_ab_matrix(solver, outDir)
%EXPORT_AB_MATRIX  Export assembled A (COO) and b in OpticsFEM3D text format.

if nargin < 2 || isempty(outDir)
    outDir = fullfile(fileparts(mfilename('fullpath')), 'OutFile');
end
if ~exist(outDir, 'dir')
    mkdir(outDir);
end

if isfield(solver, 'A') && ~isempty(solver.A)
    [ii, jj, vv] = find(solver.A);
    Ai = ii(:) - 1;
    Aj = jj(:) - 1;
    Av = complex(vv(:));
    b = complex(solver.b(:));
elseif isfield(solver, 'Ai') && ~isempty(solver.Ai)
    Ai = solver.Ai(:) - 1;
    Aj = solver.Aj(:) - 1;
    Av = complex(solver.Av(:));
    b = complex(solver.b(:));
else
    error('export_ab_matrix:NeedA', 'solver must provide sparse A or Ai/Aj/Av.');
end

fidAi = fopen(fullfile(outDir, 'Ai.txt'), 'w');
fidAj = fopen(fullfile(outDir, 'Aj.txt'), 'w');
fidAv = fopen(fullfile(outDir, 'Av.txt'), 'w');
fidBr = fopen(fullfile(outDir, 'Bv_real.txt'), 'w');
fidBi = fopen(fullfile(outDir, 'Bv_imag.txt'), 'w');
cleanup = onCleanup(@() closeOpenFiles({fidAi, fidAj, fidAv, fidBr, fidBi}));

fprintf(fidAi, '%d\n', Ai);
fprintf(fidAj, '%d\n', Aj);
fprintf(fidAv, '(%g,%g)\n', [real(Av), imag(Av)].');
fprintf(fidBr, '%.12g\n', real(b));
fprintf(fidBi, '%.12g\n', imag(b));

nSys = numel(b);
if isfield(solver, 'A') && ~isempty(solver.A)
    nSys = size(solver.A, 1);
end
fprintf('Exported A/b to %s\n', outDir);
fprintf('  n=%d, nnz=%d, b length=%d\n', nSys, numel(Ai), numel(b));
end

function closeOpenFiles(fids)
for k = 1:numel(fids)
    if fids{k} > 0
        fclose(fids{k});
    end
end
end
