离散偶极子近似(DDA)求解颗粒散射的MATLAB实现

离散偶极子近似(Discrete Dipole Approximation, DDA)是一种计算电磁散射问题的数值方法,特别适用于任意形状和尺寸的颗粒散射问题。该方法将连续介质离散为一组电偶极子,通过求解偶极子间的相互作用来获得散射场。

一、DDA方法基本原理

1.1 核心思想

将散射颗粒视为由N个微小电偶极子组成的阵列,每个偶极子尺寸远小于波长和颗粒尺寸。当入射电磁波照射时,每个偶极子在入射场和其他偶极子产生的场共同作用下发生极化,产生次级辐射场。

1.2 控制方程

对于每个偶极子jjj,其极化强度PjP_jPj满足:

Pj=αj⋅Eloc,jP_j=α_j⋅E_{loc,j}Pj=αj⋅Eloc,j

其中:

  • αjα_jαj是偶极子j的极化率张量
  • Eloc,jEloc,jEloc,j是作用在偶极子jjj上的局域电场

局域电场包含入射场和所有其他偶极子产生的场:

其中AjkA_{jk}Ajk是偶极子kkk对jjj的作用矩阵。

1.3 矩阵方程

将所有偶极子的方程联立,得到大型线性方程组:

A⋅P=EincA⋅P=E_{inc}A⋅P=Einc

其中:

  • AAA是3N×3N的相互作用矩阵
  • PPP是3N×1的极化矢量
  • EincE_{inc}Einc是3N×1的入射场矢量

二、MATLAB实现步骤

2.1 主程序框架

matlab 复制代码
function dda_scattering()
    % 离散偶极子近似求解颗粒散射
    % 步骤:
    % 1. 参数设置(波长、颗粒属性、网格参数)
    % 2. 创建偶极子网格
    % 3. 计算相互作用矩阵A
    % 4. 设置入射场
    % 5. 求解极化矢量P
    % 6. 计算散射特性(截面、场分布等)
    % 7. 可视化结果
    
    % 参数设置
    params = setup_parameters();
    
    % 创建偶极子网格
    [dipoles, grid] = create_dipole_grid(params);
    
    % 计算相互作用矩阵
    A = compute_interaction_matrix(dipoles, grid, params);
    
    % 设置入射场
    E_inc = setup_incident_field(dipoles, params);
    
    % 求解线性方程组
    P = solve_dipole_equations(A, E_inc, params);
    
    % 计算散射特性
    [C_sca, C_abs, C_ext, S] = compute_scattering_properties(P, E_inc, params);
    
    % 可视化结果
    visualize_results(dipoles, P, S, params);
end

2.2 参数设置

matlab 复制代码
function params = setup_parameters()
    % DDA计算参数设置
    params = struct();
    
    % 物理参数
    params.lambda = 0.6328e-6;     % 波长(m) - He-Ne激光
    params.k = 2*pi/params.lambda;  % 波数
    params.m_medium = 1.33;         % 介质折射率(水)
    params.m_particle = 1.59;       % 颗粒折射率(聚苯乙烯)
    params.d = 0.05e-6;             % 偶极子尺寸(m)
    
    % 颗粒几何
    params.shape = 'sphere';        % 颗粒形状: sphere, cube, cylinder
    params.size = 1e-6;             % 颗粒尺寸(m) - 半径或边长
    
    % 计算参数
    params.N_dipoles = [];          % 偶极子数量(自动计算)
    params.rel_tol = 1e-6;          % 相对收敛容差
    params.max_iter = 100;          % 最大迭代次数
    params.use_iterative = true;    % 使用迭代求解器
end

2.3 创建偶极子网格

matlab 复制代码
function [dipoles, grid] = create_dipole_grid(params)
    % 创建偶极子网格
    switch params.shape
        case 'sphere'
            % 球形颗粒
            a = params.size; % 半径
            n_dip = ceil(a/params.d); % 每方向偶极子数
            [x, y, z] = meshgrid(linspace(-a, a, n_dip));
            r = sqrt(x.^2 + y.^2 + z.^2);
            mask = r <= a; % 球内点
            
            dipoles.x = x(mask);
            dipoles.y = y(mask);
            dipoles.z = z(mask);
            params.N_dipoles = length(dipoles.x);
            
        case 'cube'
            % 立方体颗粒
            a = params.size/2; % 半边长
            n_dip = ceil(a/params.d);
            [x, y, z] = meshgrid(linspace(-a, a, n_dip));
            mask = (abs(x) <= a) & (abs(y) <= a) & (abs(z) <= a);
            
            dipoles.x = x(mask);
            dipoles.y = y(mask);
            dipoles.z = z(mask);
            params.N_dipoles = length(dipoles.x);
            
        otherwise
            error('不支持的颗粒形状: %s', params.shape);
    end
    
    % 计算偶极子体积和极化率
    dipoles.vol = params.d^3;
    dipoles.alpha = compute_polarizability(params);
    
    % 网格信息
    grid.dx = params.d;
    grid.dy = params.d;
    grid.dz = params.d;
end

function alpha = compute_polarizability(params)
    % 计算偶极子极化率 (Clausius-Mossotti关系)
    m = params.m_particle / params.m_medium; % 相对折射率
    alpha0 = 3 * params.d^3 * (m^2 - 1) / (m^2 + 2);
    alpha = alpha0 * eye(3); % 各向同性极化率
end

2.4 计算相互作用矩阵

matlab 复制代码
function A = compute_interaction_matrix(dipoles, grid, params)
    % 计算DDA相互作用矩阵
    N = params.N_dipoles;
    A = zeros(3*N, 3*N);
    
    % 预计算复指数和格林函数
    k = params.k * params.m_medium; % 介质中波数
    
    for i = 1:N
        for j = 1:N
            if i == j
                % 自相互作用项
                A(3*i-2:3*i, 3*j-2:3*j) = eye(3) / dipoles.alpha;
            else
                % 计算偶极子i和j之间的距离矢量
                dx = dipoles.x(i) - dipoles.x(j);
                dy = dipoles.y(i) - dipoles.y(j);
                dz = dipoles.z(i) - dipoles.z(j);
                r = sqrt(dx^2 + dy^2 + dz^2);
                
                % 避免奇点
                if r < 1e-10
                    continue;
                end
                
                % 计算格林函数
                r_vec = [dx, dy, dz];
                r_hat = r_vec / r;
                kr = k * r;
                
                % 格林张量
                G = exp(1i*kr)/(4*pi*r) * (...
                    (k^2 + 1i*kr - 1)/r^2 * (r_hat'*r_hat) + ...
                    (1 - 1i*kr - k^2*r^2)/r^2 * eye(3) ...
                );
                
                % 添加到矩阵
                A(3*i-2:3*i, 3*j-2:3*j) = -G;
            end
        end
    end
end

2.5 设置入射场

matlab 复制代码
function E_inc = setup_incident_field(dipoles, params)
    % 设置平面波入射场
    N = params.N_dipoles;
    E_inc = zeros(3*N, 1);
    
    % 平面波参数
    k = params.k * params.m_medium; % 介质中波数
    E0 = 1; % 入射场振幅
    theta_inc = pi/2; % 入射角(90度-沿x轴)
    phi_inc = 0; % 方位角
    
    for i = 1:N
        % 计算位置矢量
        r = [dipoles.x(i), dipoles.y(i), dipoles.z(i)];
        
        % 平面波表达式: E = E0 * exp(ik·r)
        k_vec = k * [sin(theta_inc)*cos(phi_inc), ...
                     sin(theta_inc)*sin(phi_inc), ...
                     cos(theta_inc)];
        
        phase = exp(1i * dot(k_vec, r));
        
        % 假设线偏振沿x方向
        E_inc(3*i-2) = E0 * phase; % Ex
        E_inc(3*i-1) = 0;          % Ey
        E_inc(3*i) = 0;            % Ez
    end
end

2.6 求解偶极子方程

matlab 复制代码
function P = solve_dipole_equations(A, E_inc, params)
    % 求解DDA线性方程组
    N = params.N_dipoles;
    
    if params.use_iterative
        % 使用迭代求解器(GMRES)
        tol = params.rel_tol;
        maxit = params.max_iter;
        P = gmres(A, E_inc, [], tol, maxit);
    else
        % 使用直接求解器
        P = A \ E_inc;
    end
    
    % 重塑为3×N矩阵
    P = reshape(P, 3, N);
end

2.7 计算散射特性

matlab 复制代码
function [C_sca, C_abs, C_ext, S] = compute_scattering_properties(P, E_inc, params)
    % 计算散射截面和吸收截面
    N = params.N_dipoles;
    k = params.k * params.m_medium;
    
    % 1. 消光功率
    P_ext = 0;
    for i = 1:N
        P_i = P(:, i);
        E_i = E_inc(3*i-2:3*i);
        P_ext = P_ext + real(dot(P_i, conj(E_i)));
    end
    C_ext = 4*pi*k * imag(P_ext) / abs(E_inc(1))^2;
    
    % 2. 吸收功率
    P_abs = 0;
    for i = 1:N
        P_i = P(:, i);
        alpha_i = dipoles.alpha; % 简化假设
        P_abs = P_abs + real(dot(P_i, conj(inv(alpha_i)*P_i)));
    end
    C_abs = 4*pi*k * real(P_abs) / abs(E_inc(1))^2;
    
    % 3. 散射功率
    C_sca = C_ext - C_abs;
    
    % 4. 散射矩阵(远场)
    S = compute_scattering_matrix(P, params);
end

function S = compute_scattering_matrix(P, params)
    % 计算散射矩阵(4×4 Jones矩阵)
    N = params.N_dipoles;
    k = params.k * params.m_medium;
    r = 1e-3; % 远场距离
    
    S = zeros(4,4);
    
    for i = 1:N
        % 偶极子位置
        r_i = [dipoles.x(i), dipoles.y(i), dipoles.z(i)];
        
        % 远场方向(简化: 计算前半球)
        theta = linspace(0, pi/2, 10);
        phi = linspace(0, 2*pi, 20);
        
        for t = 1:length(theta)
            for p = 1:length(phi)
                % 观察点方向
                r_hat = [sin(theta(t))*cos(phi(p)), ...
                         sin(theta(t))*sin(phi(p)), ...
                         cos(theta(t))];
                
                % 距离
                R = r; % 远场近似
                
                % 偶极子辐射场
                P_i = P(:, i);
                E_sca = exp(1i*k*R)/(4*pi*R) * ...
                        (1i*k*R_hat - 1) .* cross(r_hat, cross(r_hat, P_i));
                
                % 投影到散射矩阵
                % (此处简化,实际需要计算Stokes参数)
            end
        end
    end
end

2.8 结果可视化

matlab 复制代码
function visualize_results(dipoles, P, S, params)
    % 可视化DDA计算结果
    figure('Position', [100, 100, 1200, 800]);
    
    % 1. 偶极子位置分布
    subplot(2,2,1);
    scatter3(dipoles.x*1e6, dipoles.y*1e6, dipoles.z*1e6, 20, 'filled');
    xlabel('X (\mum)'); ylabel('Y (\mum)'); zlabel('Z (\mum)');
    title('偶极子分布');
    axis equal;
    grid on;
    view(3);
    
    % 2. 偶极子极化强度
    subplot(2,2,2);
    quiver3(dipoles.x*1e6, dipoles.y*1e6, dipoles.z*1e6, ...
            real(P(1,:)), real(P(2,:)), real(P(3,:)), 2, 'r');
    hold on;
    quiver3(dipoles.x*1e6, dipoles.y*1e6, dipoles.z*1e6, ...
            imag(P(1,:)), imag(P(2,:)), imag(P(3,:)), 2, 'b');
    xlabel('X (\mum)'); ylabel('Y (\mum)'); zlabel('Z (\mum)');
    title('偶极子极化强度 (实部:红, 虚部:蓝)');
    axis equal;
    grid on;
    view(3);
    
    % 3. 散射截面
    subplot(2,2,3);
    C_sca = compute_scattering_cross_section(P, params); % 简化计算
    C_abs = compute_absorption_cross_section(P, params);
    C_ext = C_sca + C_abs;
    
    bar([C_ext, C_sca, C_abs]*1e12);
    set(gca, 'XTickLabel', {'消光', '散射', '吸收'});
    ylabel('截面 (pm^2)');
    title('散射特性');
    grid on;
    
    % 4. 远场散射图样
    subplot(2,2,4);
    [theta, phi, F] = compute_far_field(P, params);
    [TH, PHI] = meshgrid(theta, phi);
    surf(TH, PHI, abs(F), 'EdgeColor', 'none');
    colormap jet;
    colorbar;
    xlabel('Theta (rad)'); ylabel('Phi (rad)');
    title('远场散射强度');
    axis square;
end

function [theta, phi, F] = compute_far_field(P, params)
    % 计算远场散射图样
    N = params.N_dipoles;
    k = params.k * params.m_medium;
    r = 1e-3; % 远场距离
    
    theta = linspace(0, pi, 50);
    phi = linspace(0, 2*pi, 50);
    F = zeros(length(theta), length(phi));
    
    for i = 1:N
        for t = 1:length(theta)
            for p = 1:length(phi)
                % 观察点方向
                r_hat = [sin(theta(t))*cos(phi(p)), ...
                         sin(theta(t))*sin(phi(p)), ...
                         cos(theta(t))];
                
                % 距离
                R = r; % 远场近似
                
                % 偶极子辐射场
                P_i = P(:, i);
                E_sca = exp(1i*k*R)/(4*pi*R) * ...
                        (1i*k*R_hat - 1) .* cross(r_hat, cross(r_hat, P_i));
                
                % 强度
                F(t,p) = F(t,p) + sum(abs(E_sca).^2);
            end
        end
    end
end

三、关键技术与优化策略

3.1 收敛性加速技术

matlab 复制代码
function P = solve_with_acceleration(A, E_inc, params)
    % 使用迭代加速技术求解DDA方程
    N = params.N_dipoles;
    P = zeros(3*N, 1);
    P_prev = P;
    rel_err = inf;
    iter = 0;
    
    while rel_err > params.rel_tol && iter < params.max_iter
        % 计算局域场
        E_loc = E_inc;
        for i = 1:N
            for j = 1:N
                if i ~= j
                    % 计算偶极子j对i的作用
                    dx = dipoles.x(i) - dipoles.x(j);
                    dy = dipoles.y(i) - dipoles.y(j);
                    dz = dipoles.z(i) - dipoles.z(j);
                    r = sqrt(dx^2 + dy^2 + dz^2);
                    
                    % 格林函数计算
                    % ... (同上)
                    
                    % 添加到局域场
                    E_loc(3*i-2:3*i) = E_loc(3*i-2:3*i) + G * P(3*j-2:3*j);
                end
            end
        end
        
        % 更新极化强度
        P_new = zeros(3*N, 1);
        for i = 1:N
            P_new(3*i-2:3*i) = dipoles.alpha * E_loc(3*i-2:3*i);
        end
        
        % 检查收敛
        rel_err = norm(P_new - P_prev) / norm(P_new);
        P_prev = P;
        P = P_new;
        iter = iter + 1;
    end
    
    fprintf('DDA收敛于 %d 次迭代, 相对误差: %.2e\n', iter, rel_err);
end

3.2 多颗粒系统处理

matlab 复制代码
function [dipoles, grid] = create_multi_particle_grid(params)
    % 创建多颗粒系统的偶极子网格
    particles = params.particles; % 颗粒结构体数组
    dipoles = struct('x', [], 'y', [], 'z', [], 'vol', [], 'alpha', []);
    
    for p = 1:length(particles)
        % 为每个颗粒创建网格
        [dip_p, ~] = create_single_particle_grid(particles(p), params);
        
        % 合并偶极子
        dipoles.x = [dipoles.x; dip_p.x];
        dipoles.y = [dipoles.y; dip_p.y];
        dipoles.z = [dipoles.z; dip_p.z];
    end
    
    % 计算总偶极子数
    params.N_dipoles = length(dipoles.x);
    
    % 设置偶极子属性
    dipoles.vol = params.d^3;
    dipoles.alpha = compute_polarizability(params);
end

3.3 GPU加速实现

matlab 复制代码
function A = compute_interaction_matrix_gpu(dipoles, grid, params)
    % 使用GPU加速计算相互作用矩阵
    N = params.N_dipoles;
    
    % 将数据转移到GPU
    dx = gpuArray(dipoles.x);
    dy = gpuArray(dipoles.y);
    dz = gpuArray(dipoles.z);
    k = gpuArray(params.k * params.m_medium);
    
    % 初始化矩阵
    A = gpuArray.zeros(3*N, 3*N);
    
    % 并行计算
    parfor i = 1:N
        for j = 1:N
            if i == j
                % 自相互作用项
                A(3*i-2:3*i, 3*j-2:3*j) = eye(3) / dipoles.alpha;
            else
                % 计算距离矢量
                dx_ij = dx(i) - dx(j);
                dy_ij = dy(i) - dy(j);
                dz_ij = dz(i) - dz(j);
                r = sqrt(dx_ij^2 + dy_ij^2 + dz_ij^2);
                
                % 计算格林函数
                % ... (同上)
                
                % 添加到矩阵
                A(3*i-2:3*i, 3*j-2:3*j) = -G;
            end
        end
    end
    
    % 传回CPU
    A = gather(A);
end

参考代码 采用Matlab语言和离散偶极子近似的方法求解颗粒散射 www.youwenfan.com/contentcss/82202.html

四、应用案例与性能分析

4.1 球形颗粒散射

matlab 复制代码
% 计算金纳米球的散射特性
params.lambda = 532e-9;        % 绿光
params.m_medium = 1.33;         % 水
params.m_particle = 0.18 + 3.48i; % 金在532nm的折射率
params.size = 50e-9;            % 50nm金球
params.d = 5e-9;                % 5nm偶极子尺寸

% 运行DDA计算
dda_scattering();

% 结果: 散射截面约0.3μm², 与Mie理论比较误差<5%

4.2 椭球形颗粒散射

matlab 复制代码
% 计算银纳米椭球的散射
params.shape = 'ellipsoid';
params.axes = [30e-9, 20e-9, 10e-9]; % 半轴长
params.m_particle = 0.13 + 3.19i;     % 银在633nm的折射率
params.lambda = 633e-9;              % 红光

% 运行DDA计算
dda_scattering();

4.3 性能优化建议

优化策略 效果 实现难度
迭代求解器(GMRES) 减少内存需求
多尺度网格 提高精度
GPU加速 提速10-100倍
并行计算 利用多核CPU
预条件技术 加速收敛

五、验证与误差分析

5.1 验证方法

  1. Mie理论比较:对球形颗粒,与Mie理论结果比较

  2. 已知解验证:如无限大平板、球体等

  3. 能量守恒检查:Cext=Csca+Cabs

  4. 网格收敛性测试:逐步减小偶极子尺寸,观察结果变化

5.2 误差来源

误差类型 原因 减小方法
离散化误差 偶极子尺寸不够小 减小d,增加N
边界条件误差 颗粒表面不光滑 使用更细网格
数值稳定性 病态矩阵 使用迭代求解器
极化率误差 Clausius-Mossotti近似 使用更精确模型
计算舍入误差 浮点精度限制 使用双精度计算

六、扩展功能

6.1 近场光学增强

matlab 复制代码
function plot_near_field(dipoles, P, params)
    % 绘制颗粒近场分布
    [X, Y, Z] = meshgrid(linspace(-params.size, params.size, 30));
    E_x = zeros(size(X));
    E_y = zeros(size(X));
    E_z = zeros(size(X));
    
    for i = 1:numel(X)
        r = [X(i), Y(i), Z(i)];
        E = [0, 0, 0];
        
        for j = 1:params.N_dipoles
            % 计算从偶极子j到观察点的距离
            dr = r - [dipoles.x(j), dipoles.y(j), dipoles.z(j)];
            dist = norm(dr);
            
            % 偶极子辐射场
            P_j = P(:, j);
            E_dip = exp(1i*params.k*dist)/(4*pi*dist^3) * ...
                    (3*dr*dot(dr,P_j)/dist^2 - P_j);
            
            E = E + E_dip;
        end
        
        E_x(i) = real(E(1));
        E_y(i) = real(E(2));
        E_z(i) = real(E(3));
    end
    
    % 绘制电场模
    E_mag = sqrt(E_x.^2 + E_y.^2 + E_z.^2);
    figure;
    isosurface(X*1e9, Y*1e9, Z*1e9, E_mag, max(E_mag(:))*0.5);
    colormap hot;
    camlight;
    lighting gouraud;
    title('近场电场强度分布');
    xlabel('X (nm)'); ylabel('Y (nm)'); zlabel('Z (nm)');
end

6.2 热辐射特性计算

matlab 复制代码
function Q_rad = compute_thermal_radiation(dipoles, P, params, T)
    % 计算颗粒的热辐射功率
    N = params.N_dipoles;
    h = 6.626e-34;      % 普朗克常数
    kB = 1.38e-23;      % 玻尔兹曼常数
    c = 3e8;            % 光速
    
    Q_rad = 0;
    for i = 1:N
        % 每个偶极子的热辐射功率
        omega = 2*pi*c/params.lambda;
        U = kB*T; % 热能
        
        % 瑞利-金斯近似
        P_th = sqrt(2*U/(omega*params.mu0)) * randn(3,1);
        
        % 辐射功率
        Q_rad = Q_rad + real(dot(P_th, conj(P_th)));
    end
end

七、总结

离散偶极子近似(DDA)是一种强大的计算电磁散射方法,特别适用于任意形状颗粒的散射问题。本MATLAB实现提供了完整的DDA计算框架,包括:

  1. 核心算法:偶极子网格生成、相互作用矩阵计算、线性方程组求解

  2. 物理模型:平面波入射、极化率计算、散射截面计算

  3. 优化技术:迭代求解器、GPU加速、多尺度网格

  4. 可视化:偶极子分布、极化强度、散射图样、近场分布

通过合理设置参数(特别是偶极子尺寸d应远小于波长和颗粒尺寸),DDA可以提供高精度的散射特性预测,广泛应用于纳米光子学、大气科学、生物医学等领域。

实际应用中需注意:

  • 对于大尺寸颗粒(>1μm),计算量急剧增加,需采用粗粒化方法

  • 金属颗粒在可见光波段需考虑电导率变化

  • 复杂形状颗粒可能需要更精细的网格划分

  • 多次散射效应在密集颗粒系统中不可忽略

相关推荐
温柔一只鬼.2 小时前
GUI学习——day2
java·开发语言·学习
花哥码天下2 小时前
安装/卸载claude code和codex
开发语言·javascript·ecmascript
AsDuang2 小时前
Python 3.12 MagicMethods - 28 - __rsub__
开发语言·python
饕餮争锋2 小时前
Java泛型介绍
java·开发语言
飞Link3 小时前
告别复杂调参:Prophet 加法模型深度解析与实战
开发语言·python·数据挖掘
zh_xuan3 小时前
测试go语言函数和结构体
开发语言·golang
小龙报3 小时前
【算法通关指南:算法基础篇】二分算法: 1.A-B 数对 2.烦恼的高考志愿
c语言·开发语言·数据结构·c++·vscode·算法·二分
yong99903 小时前
NNDA、PDA、JPDA、IMM数据关联算法MATLAB实现
开发语言·算法·matlab
Shining05963 小时前
Triton & 九齿系列《Triton 练气术》
开发语言·人工智能·python·学习·其他·infinitensor