function mesh = load_SBCmesh_dat(datFile) %LOAD_SBCMESH_DAT 读取 OpticsFEM/COMSOL 导出的 SBCmesh.dat(1-based 索引)。 % 与 3D opticsfem-master Mesh_3D 读入格式一致,供 main.m 与 C++ 共用同一网格。 fid = fopen(datFile, 'r'); if fid < 0 error('无法打开网格文件: %s', datFile); end cleanup = onCleanup(@() fclose(fid)); tag = read_tag(fid); assert(strcmp(tag, 'NbrVertex'), 'Expected NbrVertex'); mesh.NbrVertex = read_int(fid); tag = read_tag(fid); assert(strcmp(tag, 'Vertex'), 'Expected Vertex'); mesh.Vertex = reshape(fscanf(fid, '%f', mesh.NbrVertex * 3), 3, []).'; tag = read_tag(fid); assert(strcmp(tag, 'NbrTet'), 'Expected NbrTet'); mesh.NbrTet = read_int(fid); tag = read_tag(fid); assert(strcmp(tag, 'Tet'), 'Expected Tet'); mesh.Tet = reshape(fscanf(fid, '%d', mesh.NbrTet * 4), 4, []).'; tag = read_tag(fid); assert(strcmp(tag, 'DomainOfTet'), 'Expected DomainOfTet'); mesh.DomainOfTet = fscanf(fid, '%d', mesh.NbrTet); tag = read_tag(fid); assert(strcmp(tag, 'NbrEdge'), 'Expected NbrEdge'); mesh.NbrEdge = read_int(fid); tag = read_tag(fid); assert(strcmp(tag, 'Edge'), 'Expected Edge'); mesh.Edge = reshape(fscanf(fid, '%d', mesh.NbrEdge * 2), 2, []).'; tag = read_tag(fid); assert(strcmp(tag, 'EdgeOfTet'), 'Expected EdgeOfTet'); mesh.EdgeOfTet = reshape(fscanf(fid, '%d', mesh.NbrTet * 6), 6, []).'; tag = read_tag(fid); assert(strcmp(tag, 'NbrTri'), 'Expected NbrTri'); mesh.NbrTri = read_int(fid); tag = read_tag(fid); assert(strcmp(tag, 'Tri'), 'Expected Tri'); mesh.Tri = reshape(fscanf(fid, '%d', mesh.NbrTri * 3), 3, []).'; tag = read_tag(fid); assert(strcmp(tag, 'DomainOfTri'), 'Expected DomainOfTri'); mesh.DomainOfTri = fscanf(fid, '%d', mesh.NbrTri); tag = read_tag(fid); assert(strcmp(tag, 'ConnOfTri'), 'Expected ConnOfTri'); mesh.ConnOfTri = reshape(fscanf(fid, '%d', mesh.NbrTri * 2), 2, []).'; tag = read_tag(fid); assert(strcmp(tag, 'NormOfFace'), 'Expected NormOfFace'); nbrNorm = read_int(fid); maxDom = 14; mesh.NormOfFace = zeros(maxDom, 3); for k = 1:nbrNorm row = fscanf(fid, '%f', 4); if numel(row) < 4 error('NormOfFace 第 %d 条记录不完整(文件可能被截断)', k); end domainId = round(row(1)); if domainId > maxDom extra = zeros(domainId, 3); extra(1:maxDom, :) = mesh.NormOfFace; mesh.NormOfFace = extra; maxDom = domainId; end mesh.NormOfFace(domainId, :) = row(2:4); end % 仅对仍为 0 的 SBC 模板域补默认(PBC 网格 1..9 已在 dat 中给出) defaults = { 1, [-1, 0, 0]; 2, [0, -1, 0]; 3, [0, 0, -1]; 4, [0, 0, 1]; 5, [0, 1, 0]; 8, [0, 0, 1]; 14, [1, 0, 0]; }; for k = 1:size(defaults, 1) d = defaults{k, 1}; if norm(mesh.NormOfFace(d, :)) < 1e-30 mesh.NormOfFace(d, :) = defaults{k, 2}; end end if min(mesh.EdgeOfTet(:)) < 1 error(['SBCmesh.dat 中 EdgeOfTet 必须为 1-based(最小值=%d)。' ... '请使用 export_SBCmesh_to_dat 或修正后再读。'], min(mesh.EdgeOfTet(:))); end fprintf('已加载 %s: NbrTet=%d, NbrEdge=%d, NbrTri=%d\n', ... datFile, mesh.NbrTet, mesh.NbrEdge, mesh.NbrTri); end function tag = read_tag(fid) tag = ''; while true line = fgetl(fid); if ~ischar(line) error('Unexpected end of mesh file.'); end line = strtrim(line); if ~isempty(line) tag = line; return; end end end function value = read_int(fid) value = fscanf(fid, '%d', 1); end