openEMS/matlab/Tutorials/Dipole_SAR.m

220 lines
6.3 KiB
Matlab
Raw Normal View History

%
% Tutorials / Dipole SAR + Power budget
%
% Describtion at:
% http://openems.de/index.php/Tutorial:_Dipole_SAR
%
% Tested with
% - openEMS v0.0.31
%
% (C) 2013 Thorsten Liebig <thorsten.liebig@uni-due.de>
close all
clear
clc
%% switches & options...
postprocessing_only = 0;
%% prepare simulation folder
Sim_Path = 'Dipole_SAR';
Sim_CSX = 'Dipole_SAR.xml';
%% setup the simulation
physical_constants;
unit = 1e-3; % all lengths in mm
feed.R = 50; % feed resistance
%% define phantom
phantom{1}.name='skin';
phantom{1}.epsR = 50;
phantom{1}.kappa = 0.65; % S/m
phantom{1}.density = 1100; % kg/m^3
phantom{1}.radius = [80 100 100]; % ellipsoide
phantom{1}.center = [100 0 0];
phantom{2}.name='headbone';
phantom{2}.epsR = 13;
phantom{2}.kappa = 0.1; % S/m
phantom{2}.density = 2000; % kg/m^3
phantom{2}.radius = [75 95 95]; % ellipsoide
phantom{2}.center = [100 0 0];
phantom{3}.name='brain';
phantom{3}.epsR = 60;
phantom{3}.kappa = 0.7; % S/m
phantom{3}.density = 1040; % kg/m^3
phantom{3}.radius = [65 85 85]; % ellipsoide
phantom{3}.center = [100 0 0];
%% setup FDTD parameter & excitation function
f0 = 1e9; % center frequency
lambda0 = c0/f0;
f_stop = 1.5e9; % 20 dB corner frequency
lambda_min = c0/f_stop;
mesh_res_air = lambda_min/20/unit;
mesh_res_phantom = 2.5;
dipole_length = 0.46*lambda0/unit;
disp(['Lambda-half dipole length: ' num2str(dipole_length) 'mm'])
%%
FDTD = InitFDTD();
FDTD = SetGaussExcite( FDTD, 0, f_stop );
% apply PML-8 boundary conditions in all directions
BC = {'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8'};
FDTD = SetBoundaryCond( FDTD, BC );
%% setup CSXCAD geometry & mesh
CSX = InitCSX();
%% Dipole
CSX = AddMetal( CSX, 'Dipole' ); % create a perfect electric conductor (PEC)
CSX = AddBox(CSX, 'Dipole', 1, [0 0 -dipole_length/2], [0 0 dipole_length/2]);
% mesh lines for the dipole
mesh.x = 0;
mesh.y = 0;
mesh.z = [-dipole_length/2-[-1/3 2/3]*mesh_res_phantom dipole_length/2+[-1/3 2/3]*mesh_res_phantom];
%% add the dielectrics
for n=1:numel(phantom)
CSX = AddMaterial( CSX, phantom{n}.name );
CSX = SetMaterialProperty( CSX, phantom{n}.name, 'Epsilon', phantom{n}.epsR, 'Kappa', phantom{n}.kappa, 'Density', phantom{n}.density);
CSX = AddSphere( CSX, phantom{n}.name, 10+n, [0 0 0], 1,'Transform',{'Scale',phantom{n}.radius, 'Translate', phantom{n}.center} );
%% mesh lines for the dielectrics
mesh.x = [mesh.x phantom{n}.radius(1)*[-1 1]+phantom{n}.center(1) ];
mesh.y = [mesh.y phantom{n}.radius(2)*[-1 1]+phantom{n}.center(2) ];
mesh.z = [mesh.z phantom{n}.radius(3)*[-1 1]+phantom{n}.center(3) ];
end
%% apply the excitation & resist as a current source
[CSX port] = AddLumpedPort(CSX, 100, 1, feed.R, [-0.1 -0.1 -mesh_res_phantom/2], [0.1 0.1 +mesh_res_phantom/2], [0 0 1], true);
% mesh lines for the port
mesh.z = [mesh.z -mesh_res_phantom/2 +mesh_res_phantom/2];
%% smooth the mesh over the dipole and phantom
mesh = SmoothMesh(mesh, mesh_res_phantom);
%% add lines for the air-box
mesh.x = [mesh.x -200 250+100];
mesh.y = [mesh.y -250 250];
mesh.z = [mesh.z -250 250];
% smooth the final mesh (incl. air box)
mesh = SmoothMesh(mesh, mesh_res_air, 1.2);
%% dump SAR
start = [-10 -100 -100];
stop = [180 100 100];
CSX = AddDump( CSX, 'SAR', 'DumpType', 20, 'Frequency', f0,'FileType',1,'DumpMode',2);
CSX = AddBox( CSX, 'SAR', 0, start, stop);
%% nf2ff calc
start = [mesh.x(1) mesh.y(1) mesh.z(1)];
stop = [mesh.x(end) mesh.y(end) mesh.z(end)];
[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop, 'OptResolution', lambda_min/15/unit);
%%
% add 10 equidistant cells (air)
% around the structure to keep the pml away from the nf2ff box
mesh = AddPML( mesh, 10 );
% Define the mesh
CSX = DefineRectGrid(CSX, unit, mesh);
%%
if (postprocessing_only==0)
[status, message, messageid] = rmdir( Sim_Path, 's' ); % clear previous directory
[status, message, messageid] = mkdir( Sim_Path ); % create empty simulation folder
% write openEMS compatible xml-file
WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );
% show the structure
CSXGeomPlot( [Sim_Path '/' Sim_CSX] );
% run openEMS
RunOpenEMS( Sim_Path, Sim_CSX );
end
%% postprocessing & make the plots
freq = linspace(500e6, 1500e6, 501 );
port = calcPort(port, Sim_Path, freq);
s11 = port.uf.ref./port.uf.inc;
Zin = port.uf.tot./port.if.tot;
Pin = real(0.5*port.uf.tot.*conj(port.if.tot));
Pin_f0 = interp1(freq, Pin, f0);
%%
% plot feed point impedance
figure
plot( freq/1e6, real(Zin), 'k-', 'Linewidth', 2 );
hold on
grid on
plot( freq/1e6, imag(Zin), 'r--', 'Linewidth', 2 );
title( 'feed point impedance' );
xlabel( 'frequency f / MHz' );
ylabel( 'impedance Z_{in} / Ohm' );
legend( 'real', 'imag' );
% plot reflection coefficient S11
figure
plot( freq/1e9, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
grid on
xlabel( 'frequency f / MHz' );
ylabel( 'reflection coefficient |S_{11}|' );
%% read SAR and visualize
SAR_field = ReadHDF5Dump([Sim_Path '/SAR.h5']);
SAR = SAR_field.FD.values{1};
ptotal = ReadHDF5Attribute([Sim_Path '/SAR.h5'],'/FieldData/FD/f0','power');
%% calculate 3D pattern
phi = 0:3:360;
theta = 0:3:180;
disp( 'calculating 3D far field pattern...' );
nf2ff = CalcNF2FF(nf2ff, Sim_Path, f0, theta*pi/180, phi*pi/180, 'Outfile','3D_Pattern.h5');
%%
disp(['max SAR: ' num2str(max(SAR(:))/Pin_f0) ' W/kg normalized to 1 W accepted power']);
disp(['accepted power: ' num2str(Pin_f0) ' W']);
disp(['radiated power: ' num2str(nf2ff.Prad) ' W']);
disp(['absorbed power: ' num2str(ptotal) ' W']);
disp(['power budget: ' num2str(100*(nf2ff.Prad + ptotal) / Pin_f0) ' %']);
%% plot on a x/y-plane
[SAR_field SAR_mesh] = ReadHDF5Dump([Sim_Path '/SAR.h5'],'Range',{[],[],0});
figure
[X Y] = ndgrid(SAR_mesh.lines{1},SAR_mesh.lines{2});
h = pcolor(X,Y,log10(SAR_field.FD.values{1}/abs(Pin_f0)));
xlabel('x -->')
ylabel('y -->')
axis equal tight
set(h,'EdgeColor','none');
%% plot on a x/z-plane
[SAR_field SAR_mesh] = ReadHDF5Dump([Sim_Path '/SAR.h5'],'Range',{[],0,[]});
figure
[X Z] = ndgrid(SAR_mesh.lines{1},SAR_mesh.lines{3});
h = pcolor(X,Z,log10(squeeze(SAR_field.FD.values{1}))/abs(Pin_f0));
xlabel('x -->')
ylabel('z -->')
axis equal tight
set(h,'EdgeColor','none');
%% dump SAR to vtk file
disp(['Full local/normalized SAR has been dumped to vtk file! Use Paraview to visualize']);
ConvertHDF5_VTK([Sim_Path '/SAR.h5'],[Sim_Path '/SAR'],'weight',1/abs(Pin_f0),'FieldName','SAR_local' );