Meshing issues for PCB trace antenna simulation

How to use openEMS. Discussion on examples, tutorials etc

Moderator: thorsten

bonkoung2
Posts: 10
Joined: Mon 11 Jul 2022, 14:26
Contact:

Meshing issues for PCB trace antenna simulation

Post by bonkoung2 » Tue 19 Jul 2022, 12:03

Hello,
I am a beginner in the use of OpenEMS. I am using it for my internship to simulate a PCB antenna of 2.45GHz for bluetooth low energy. I used the inverted F antenna and modified the code to have the shape of my antenna on an FR4 substrate. And I have a mesh problem.

-When I run the simulation, I get an error that tells me that the time step is small and that I need to check my mesh and also I get an error with the excitation length I tried to increase the length of my simulation box but it doesn't correct anything.
If I make a coarse mesh, the result is not good. I understand that the mesh in the metal part of the structure is where we have the simulation, so the mesh must be coarse.
I have tried automatic meshing with edge detection but it does not work for me, so I do the meshing by hand.

-At the end of the simulation, I get this error: "RunFDTD: Warning: Max. number of timesteps was reached before the end-criteria of -50dB was". I know that this is because the energy does not decay to zero before the simulation is stopped. I want to know if I could have good result if I have this problem?

Attached is the images of CSX image of my antenna and the results I get.Image
Image

Could anyone help me to correct these errors?
How do I know that my meshing is good and I get good results?
Thanks,


This is the error I've got. I put the code just after this.


##########################################################
Create FDTD operator (compressed SSE + multi-threading)
FDTD simulation size: 78x58x37 --> 167388 FDTD cells
FDTD timestep is: 2.74965e-14 s; Nyquist rate: 5270 timesteps @3.4505e+09 Hz
openEMS::SetupFDTD: Warning, the timestep seems to be very small --> long simulation. Check your mesh!?
Excitation signal length is: 104188 timesteps (2.8648e-09s)
Max. number of timesteps: 300000 ( --> 2.87941 * Excitation signal length)
openEMS::SetupFDTD: Warning, max. number of timesteps is smaller than three times the excitation.
You may want to choose a higher number of max. timesteps...

Create FDTD engine (compressed SSE + multi-threading)
Running FDTD engine... this may take a while... grab a cup of coffee?!?

####################################################################


Code: Select all

% EXAMPLE / antennas / ) 2.4GHz

%

% This example demonstrates how to:

% - calculate the reflection coefficient of an antenna

% - calculate farfield of an antenna

%

close all

clear

clc

%% setup the simulation

physical_constants;

unit = 1e-3; % all length in mm

substrate.width = 10; % width of substrate

substrate.length = 10; % length of substrate

substrate.thickness = 0.8; % thickness of substrate

substrate.cells = 4; % use 4 cells for meshing substrate

ifa.h = 2.1; % height of short circuit stub

ifa.l = 7.625; % length of radiating element1

ifa.w1 = 0.9; % width of short circuit stub

ifa.w2 = 0.3; % width of radiating element

ifa.wf = 0.3; % width of feed element

ifa.fp = 4; % position of feed element relative to short


% circuit stub

ifa.e = 2.4; % distance to edge

ifa.b = 5.525; %Radiating element3_5_7 length

ifa.a = 0.9; %Radiating element 2_4_6 length

ifa.c = 0.3; % distance between feeding elementand circuit stub

ifa.d = 0.3; %distance between feeding element and radiating element 2...

ifa.gnd = 0.3; %distance antenna to the ground plane

ifa.Ledge = 1; % distance to the left edge
ifa.cut = 0 ;  %Cutting element


% substrate setup

substrate.epsR = 4.29;

substrate.kappa = 1e-3 * 2*pi*2.45e9 * EPS0*substrate.epsR;

%setup feeding

feed.R = 50; %feed resistance

%open AppCSXCAD and show ifa

show = 1;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% size of the simulation box

SimBox = [substrate.width*6 substrate.length*6 200];

%% setup FDTD parameter & excitation function

f0 = 2.45e9; % center frequency

fc = 1e9; % 20 dB corner frequency

c0 = 3e8; %Speed of light

%FDTD = InitFDTD(80000, 1e-3, 'TimeStep', 5e-13);
%FDTD = InitFDTD('OverSampling', 100) %highly discourage you to change the timestep.
%we either make the simulation slower or unstable.
%openEMS chooses the fastest possible and stable timestep. So change the oversampling


%FDTD = InitFDTD('NrTS', 80000, 'EndCriteria', 1e-3);


FDTD = InitFDTD('NrTS', 300000 );

FDTD = SetGaussExcite( FDTD, f0, fc );

BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'MUR'}; % boundary conditions

FDTD = SetBoundaryCond( FDTD, BC );

%% setup CSXCAD geometry & mesh

CSX = InitCSX();

%initialize the mesh with the "air-box" dimensions

mesh.x = [-SimBox(1)/2 SimBox(1)/2];

mesh.y = [-SimBox(2)/2 SimBox(2)/2];

mesh.z = [-SimBox(3)/2 SimBox(3)/2];

%% create substrate

CSX = AddMaterial( CSX, 'substrate');

CSX = SetMaterialProperty( CSX, 'substrate', 'Epsilon',substrate.epsR, 'Kappa', substrate.kappa);

start = [-substrate.width/2 -substrate.length/2 0];

stop = [ substrate.width/2 substrate.length/2 substrate.thickness];

CSX = AddBox( CSX, 'substrate', 1, start, stop );

% add extra cells to discretize the substrate thickness

mesh.z = [linspace(0,substrate.thickness,substrate.cells+1) mesh.z];


%% create ground plane

CSX = AddMetal( CSX, 'groundplane' ); % create a perfect electric conductor (PEC)

start = [-substrate.width/2 -substrate.length/2 substrate.thickness];

stop = [ substrate.width/2 substrate.length/2-ifa.e-0.1 substrate.thickness];

CSX = AddBox(CSX, 'groundplane', 10, start,stop);


%% create ifa
CSX = AddMetal( CSX, 'ifa' ); % create a perfect electric conductor (PEC)
tl = [ifa.Ledge,substrate.length/2-ifa.e,substrate.thickness];   % translate

start = [(-substrate.width/2)+ifa.w1+ifa.c 0.5-0.1 0] + tl;
stop = start + [ifa.wf ifa.h-0.5 0];
CSX = AddBox( CSX, 'ifa', 10,  start, stop);  % feed element

start = [-substrate.width/2  -0.1 0] + tl;
stop =  start + [ifa.w1 ifa.h 0];
CSX = AddBox( CSX, 'ifa', 10,  start, stop);  % short circuit stub

start = [(-substrate.width/2) ifa.h 0] + tl;
stop = start + [ifa.l -ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element1

start = [(-substrate.width/2+ifa.l) ifa.h 0] + tl;
stop = start + [-ifa.w2 -ifa.a 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element2

start = [(-substrate.width/2+ifa.l) ifa.h-ifa.a 0] + tl;
stop = start + [-ifa.b ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element3

start = [(-substrate.width/2+ifa.l-ifa.b+ifa.w2) ifa.h-ifa.a+ifa.w2 0] + tl;
stop = start + [-ifa.w2 -ifa.a 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element4


start = [(-substrate.width/2+ifa.l) (ifa.h-2*ifa.a+ifa.w2) 0] + tl;
stop = start + [-ifa.b ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element5

start = [(-substrate.width/2+ifa.l) ifa.h-2*ifa.a+2*ifa.w2 0] + tl;
stop = start + [-ifa.w2 -ifa.a 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element6

start = [(-substrate.width/2+ifa.l) (ifa.h-3*ifa.a+2*ifa.w2) 0] + tl;
stop = start + [-ifa.b+ifa.cut ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element7

%% apply the excitation & resist as a current source
start = [ (-substrate.width/2)+ifa.w1+ifa.c -0.1 0] + tl;
stop  = start + [ifa.wf 0.5 0];
[CSX port] = AddLumpedPort(CSX, 5 ,1 ,feed.R, start, stop, [0 1 0], true); %


% MESH left
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace(-substrate.width,(-substrate.width/2)+ifa.Ledge-0.2,8.0)]; %tab 15 elements step of 0.4
mesh.y = [mesh.y linspace(-substrate.length,(substrate.length/2)-ifa.e-0.1,18.0)];%mesh.z = [mesh.z linspace(-10.0,5,40.0) + 0];
CSX = DefineRectGrid(CSX, 0.001, mesh);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MESH right
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace((-substrate.width/2)+ifa.l+ifa.Ledge+0.5,substrate.width,8.0)];
mesh.y = [mesh.y linspace(substrate.length/2+0.1,substrate.length,8.0) ];

CSX = DefineRectGrid(CSX, 0.001, mesh);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%MESH

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%mesh.x = [mesh.x linspace(-4,4,1.0)];
mesh.x = [mesh.x linspace(-substrate.width/2+ifa.Ledge,-substrate.width/2+ifa.Ledge+ifa.l,60.0) ];

mesh.y = [mesh.y linspace((substrate.length/2)-ifa.e,substrate.width/2-ifa.e+ifa.h,30.0) ];

mesh.z = [mesh.z linspace(-substrate.width,substrate.width,30.0) ];

CSX = DefineRectGrid(CSX, 0.001, mesh);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%






%% finalize the mesh DOESN'T WORK Hand meshing is better.

%ifa_mesh = DetectEdges(CSX, [], 'SetProperty','ifa');

%mesh.x = [mesh.x SmoothMeshLines(ifa_mesh.x, 0.5)];

%mesh.y = [mesh.y SmoothMeshLines(ifa_mesh.y, 10)];



% generate a smooth mesh with max. cell size: lambda_min / 20

%mesh = DetectEdges(CSX, mesh);

%mesh = SmoothMesh(mesh, c0 / (f0+fc) / unit / 20);

% Always problem to put smoothmeshing problem error: max_recursion_depth exceeded

%CSX = DefineRectGrid(CSX, unit , mesh); % define the mesh with a drawing unit of 1mm (1e-3)

%% add a nf2ff calc box; size is 3 cells away from MUR boundary condition

%%%%%%%It's implements a near field to far field transformation for near field antenna measurement setups
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);


%For H-fields
CSX = AddDump(CSX,'Et');
start = [mesh.x(1) mesh.y(1) mesh.z(1)];
stop = [mesh.x(end) mesh.y(end) mesh.z(end)];
CSX = AddBox(CSX, 'Et',0, start, stop);

%For E-fields
CSX= AddDump(CSX,'Ht', 'DumpType',1);
start = [mesh.x(1) mesh.y(1) mesh.z(1)];
stop = [mesh.x(end) mesh.y(end) mesh.z(end)];
CSX = AddBox(CSX, 'Ht',0, start, stop);

%For current
CSX = AddDump(CSX,'Jt', 'Dumptype', 3);
start = [mesh.x(1) mesh.y(1) mesh.z(1)];
stop = [mesh.x(end) mesh.y(end) mesh.z(end)];
CSX = AddBox(CSX, 'Jt',0, start, stop);

%% prepare simulation folder

Sim_Path = 'tmp_LIGHT';

Sim_CSX = 'IFA.xml';

try confirm_recursive_rmdir(false,'local'); end

[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

if (show == 1)

CSXGeomPlot( [Sim_Path '/' Sim_CSX] );

end



%% run openEMS
RunOpenEMS( Sim_Path, Sim_CSX);  %RunOpenEMS( Sim_Path, Sim_CSX, '--debug-PEC -v');

%% postprocessing & do the plots
freq = linspace( max([1e9,f0-fc]), f0+fc, 501 );
port = calcPort(port, Sim_Path, freq);

Zin = port.uf.tot ./ port.if.tot;
s11 = port.uf.ref ./ port.uf.inc;
P_in = real(0.5 * port.uf.tot .* conj( port.if.tot )); % antenna feed power

% 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/1e6, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
grid on
title( 'reflection coefficient S_{11}' );
xlabel( 'frequency f / MHz' );
ylabel( 'reflection coefficient |S_{11}|' );

drawnow

%% NFFF contour plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%
%find resonance frequncy from s11
f_res_ind = find(s11==min(s11));
f_res = freq(f_res_ind);

%%
disp( 'calculating 3D far field pattern and dumping to vtk (use Paraview to visualize)...' );
thetaRange = (0:2:180);
phiRange = (0:2:360) - 180;
nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, thetaRange*pi/180, phiRange*pi/180,'Verbose',1,'Outfile','3D_Pattern.h5');

figure
plotFF3D(nf2ff)

% display power and directivity
disp( ['radiated power: Prad = ' num2str(nf2ff.Prad) ' Watt']);
disp( ['directivity: Dmax = ' num2str(nf2ff.Dmax) ' (' num2str(10*log10(nf2ff.Dmax)) ' dBi)'] );
disp( ['efficiency: nu_rad = ' num2str(100*nf2ff.Prad./real(P_in(f_res_ind))) ' %']);

E_far_normalized = nf2ff.E_norm{1} / max(nf2ff.E_norm{1}(:)) * nf2ff.Dmax;
DumpFF2VTK([Sim_Path '/3D_Pattern.vtk'],E_far_normalized,thetaRange,phiRange,1e-3);


asdf
Posts: 15
Joined: Sat 11 Aug 2018, 08:19

Re: Meshing issues for PCB trace antenna simulation

Post by asdf » Thu 28 Jul 2022, 16:21

Your nf2ff dump box seems to be in a bad place, antenna is not in the center.
The big mesh cells in the corners are probably unnecessary, you can decrease the simulation box to be just a little bigger than dump boxes (with proper margin if PML_8 is used as boundary condition, but here it's MUR).
Your mesh may be too coarse in some places, e.g. only one cell distance between ground plane and part of the antenna structure.
Also place mesh lines on the edges of lumped port - https://openems.de/forum/viewtopic.php? ... l+material
You can probably remove the 'NrTS', 300000 so that simulation can end when it reaches energy criterion 50dB.

bonkoung2
Posts: 10
Joined: Mon 11 Jul 2022, 14:26
Contact:

Re: Meshing issues for PCB trace antenna simulation

Post by bonkoung2 » Mon 01 Aug 2022, 15:09

Thanks for your response.

I don't understand why you said that my nf2ff dump is not well placed and my antenna isn't well centred. Since the nf2ff dump box is not visible on the CSX screen, it is difficult for me to correct this.
Sorry, could you explain to me how to do this? I am a beginner at using this software and I don't understand all the commands.

Best regards

asdf
Posts: 15
Joined: Sat 11 Aug 2018, 08:19

Re: Meshing issues for PCB trace antenna simulation

Post by asdf » Mon 01 Aug 2022, 16:13

You can show the box by turning on some light bulbs in CSXCAD (list on top left panel), then it's visible and it looks like it's something wrong with it.

bonkoung2
Posts: 10
Joined: Mon 11 Jul 2022, 14:26
Contact:

Re: Meshing issues for PCB trace antenna simulation

Post by bonkoung2 » Mon 01 Aug 2022, 16:40

Thank you very much.
I now see that my dump box is completely outside my antenna. I will change the parameter to center it and run the simulation to see the result.
Best regards

bonkoung2
Posts: 10
Joined: Mon 11 Jul 2022, 14:26
Contact:

Re: Meshing issues for PCB trace antenna simulation

Post by bonkoung2 » Mon 01 Aug 2022, 20:48

Thank you, I have corrected the switch on the nf2ff box and it is now centred with the PCB (antenna). I have also reduced the size of the simulation box. I no longer have gain and efficiency values that are negative.
I have removed the 'NrTS', 300000 and I no longer have a problem with energy criteria.
I don't understand your advice for the lumped port: do you mean that I have to remove all my fine manipulations on that side and only mesh the lumped part?
Also, what does it mean by "only a cell distance between the ground plane and a part of the antenna structure"? I'm trying to make a picture to understand



[@ 12m51s] Timestep: 94600 || Speed: 17.6 MC/s (7.049e-03 s/TS) || Energy: ~1.41e-21 (-49.46dB)
[@ 12m55s] Timestep: 95202 || Speed: 18.3 MC/s (6.805e-03 s/TS) || Energy: ~1.12e-21 (-50.47dB)
Time for 95202 iterations with 124215.00 cells : 775.27 sec
Speed: 15.25 MCells/s
-> Zin @ 2.292GHz = 20.3086-82.728i
-> |Zin| @ 2.292GHz = 85.1843 Ohm
-> S11 @ 2.292GHz = -1.8349 dB

calculating 3D far field pattern and dumping to vtk (use Paraview to visualize)...
----------------------------------------------------------------------
| nf2ff, near-field to far-field transformation for openEMS
| (C) 2012-2014 Thorsten Liebig <thorsten.liebig@gmx.de> GPL license
----------------------------------------------------------------------
nf2ff: Set verbose level to 1
nf2ff: Reading planes: nf2ff_E_xn.h5 & nf2ff_H_xn.h5
nf2ff: Data-Size: 1x39x30
nf2ff: Analysing far-field for 1 frequencies.
nf2ff: Reading planes: nf2ff_E_xp.h5 & nf2ff_H_xp.h5
nf2ff: Data-Size: 1x39x30
nf2ff: Analysing far-field for 1 frequencies.
nf2ff: Reading planes: nf2ff_E_yn.h5 & nf2ff_H_yn.h5
nf2ff: Data-Size: 50x1x30
nf2ff: Analysing far-field for 1 frequencies.
nf2ff: Reading planes: nf2ff_E_yp.h5 & nf2ff_H_yp.h5
nf2ff: Data-Size: 50x1x30
nf2ff: Analysing far-field for 1 frequencies.
nf2ff: Reading planes: nf2ff_E_zn.h5 & nf2ff_H_zn.h5
nf2ff: Data-Size: 50x39x1
nf2ff: Analysing far-field for 1 frequencies.
nf2ff: Reading planes: nf2ff_E_zp.h5 & nf2ff_H_zp.h5
nf2ff: Data-Size: 50x39x1
nf2ff: Analysing far-field for 1 frequencies.
radiated power: Prad = 1.9321e-29 Watt
directivity: Dmax = 0.70005 (-1.5487 dBi)
efficiency: nu_rad = 77.6802 %
>>


Here is my code, I changed the boundary condition to PML_8, I also added a dumb box, I tested the code without and with it and I don't see any difference. I change it to FDTD = InitFDTD('NrTS',100000,'EndCriteria', 1e-5); to smooth each end of the S11 curve as it is zigzagged:
The simulation last 10min.

Code: Select all

% EXAMPLE / antennas / ) 2.4GHz

%

% This example demonstrates how to:

% - calculate the reflection coefficient of an antenna
% - Give the antenna impedance
% - calculate farfield of an antenna

%

close all

clear

clc

%% setup the simulation

physical_constants;

unit = 1e-3; % all length in mm

substrate.width = 10; % width of substrate

substrate.length = 10; % length of substrate

substrate.thickness = 0.8; % thickness of substrate

substrate.cells = 4; % use 4 cells for meshing substrate

ifa.h = 2.1; % height of short circuit stub

ifa.l = 8.875; % length of radiating element1

ifa.w1 = 0.9; % width of short circuit stub

ifa.w2 = 0.3; % width of radiating element

ifa.wf = 0.3; % width of feed element

ifa.fp = 4; % position of feed element relative to short


% circuit stub

ifa.e = 2.7; % distance to edge

ifa.b = 6.075; %Radiating element 3_5_7 length

ifa.a = 0.9; %Radiating element 2_4_6 length

ifa.c = 0.3; % distance between feeding elementand circuit stub

ifa.d = 0.3; %distance between feeding element and radiating element 2...

ifa.gnd = 0.3; %distance antenna to the ground plane

ifa.Ledge = 0.5; % distance to the left edge 1.1 Previously
ifa.cut = 0 ;  %Cutting element

ifa.sbt= 0.4; %reduce substrate length

length = 125 ;
% substrate setup

substrate.epsR = 4.3;

substrate.kappa = 1e-3 * 2*pi*2.45e9 * EPS0*substrate.epsR;

%setup feeding

feed.R = 50; %feed resistance

%open AppCSXCAD and show ifa

show = 1;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% size of the simulation box

SimBox = [substrate.width*2 substrate.length*2 20];

%% setup FDTD parameter & excitation function

f0 = 2.4e9; % center frequency

fc = 1e9; % 20 dB corner frequency

c0 = 3e8; %Speed of light

%FDTD = InitFDTD(90000, 1e-3, 'TimeStep', 5e-13);
%FDTD = InitFDTD('OverSampling', 400) %highly discourage you to change the timestep.
%we either make the simulation slower or unstable.
%openEMS chooses the fastest possible and stable timestep. So change the oversampling

%FDTD = InitFDTD('NrTS', 100000 );

%FDTD = InitFDTD('NrTS', 200000, 'EndCriteria', 1e-3); %1e-3
FDTD = InitFDTD('NrTS',100000,'EndCriteria', 1e-5);




FDTD = SetGaussExcite( FDTD, f0, fc );

%BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'MUR'}; % simple absorbing boundary conditions because our antenna being destined to be in open space
BC = {'PML_8','PML_8','PML_8','PML_8','PML_8','PML_8'}; %Perfectly Matched Layer absorbing boundary condition, using x number of cells

FDTD = SetBoundaryCond( FDTD, BC );

%% setup CSXCAD geometry & mesh

CSX = InitCSX();

%initialize the mesh with the "air-box" dimensions

mesh.x = [-SimBox(1)/2 SimBox(1)/2];

mesh.y = [-SimBox(2)/2 SimBox(2)/2];

mesh.z = [-SimBox(3)/2 SimBox(3)/2];

%% create substrate

CSX = AddMaterial( CSX, 'substrate');

CSX = SetMaterialProperty( CSX, 'substrate', 'Epsilon',substrate.epsR, 'Kappa', substrate.kappa);

start = [-substrate.width/2 -substrate.length/2 0];

stop = [ substrate.width/2 substrate.length/2 substrate.thickness];

CSX = AddBox( CSX, 'substrate', 1, start, stop );

% add extra cells to discretize the substrate thickness

mesh.z = [linspace(0,substrate.thickness,substrate.cells+1) mesh.z];


%% create ground plane

CSX = AddMetal( CSX, 'groundplane' ); % create a perfect electric conductor (PEC)

start = [-substrate.width/2 -substrate.length/2 substrate.thickness];

stop = [ substrate.width/2 substrate.length/2-ifa.e-ifa.sbt substrate.thickness];

CSX = AddBox(CSX, 'groundplane', 10, start,stop);


%% create ifa
CSX = AddMetal( CSX, 'ifa' ); % create a perfect electric conductor (PEC)
tl = [ifa.Ledge,substrate.length/2-ifa.e,substrate.thickness];   % translate

start = [(-substrate.width/2)+ifa.w1+ifa.c (ifa.h-3*ifa.a+2*ifa.w2-0.3) 0] + tl;
stop = start + [ifa.wf ifa.h 0];
CSX = AddBox( CSX, 'ifa', 10,  start, stop);  % feed element

start = [-substrate.width/2  (ifa.h-3*ifa.a+2*ifa.w2)-ifa.sbt 0] + tl;
stop =  start + [ifa.w1 ifa.h+ifa.sbt 0];
CSX = AddBox( CSX, 'ifa', 10,  start, stop);  % short circuit stub

start = [(-substrate.width/2) ifa.h 0] + tl;
stop = start + [ifa.l -ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element1

start = [(-substrate.width/2+ifa.l) ifa.h 0] + tl;
stop = start + [-ifa.w2 -ifa.a 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element2

start = [(-substrate.width/2+ifa.l) ifa.h-ifa.a 0] + tl;
stop = start + [-ifa.b ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element3

start = [(-substrate.width/2+ifa.l-ifa.b+ifa.w2) ifa.h-ifa.a+ifa.w2 0] + tl;
stop = start + [-ifa.w2 -ifa.a 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element4


start = [(-substrate.width/2+ifa.l) (ifa.h-2*ifa.a+ifa.w2) 0] + tl;
stop = start + [-ifa.b ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element5

start = [(-substrate.width/2+ifa.l) ifa.h-2*ifa.a+2*ifa.w2 0] + tl;
stop = start + [-ifa.w2 -ifa.a 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element6

start = [(-substrate.width/2+ifa.l) (ifa.h-3*ifa.a+2*ifa.w2) 0] + tl;
stop = start + [-ifa.b+ifa.cut ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element7

%% apply the excitation & resist as a current source
start = [ (-substrate.width/2)+ifa.w1+ifa.c (ifa.h-3*ifa.a+2*ifa.w2-0.3) 0] + tl;
stop  = start + [ifa.wf -ifa.sbt+0.3 0];
[CSX port] = AddLumpedPort(CSX, 5 ,1 ,feed.R, start, stop, [0 1 0], true); %


% MESH left
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace(-substrate.width,(-substrate.width/2)+ifa.Ledge-1,14.0)]; %tab 15 elements step of 0.4

mesh.y = [mesh.y linspace(-substrate.length,(substrate.length/2)-ifa.e-ifa.sbt-1,20.0)];%mesh.z = [mesh.z linspace(-10.0,5,40.0) + 0];
CSX = DefineRectGrid(CSX, 0.001, mesh);  %define the mesh with a drawing unit of 1mm (1e-3)


% MESH left2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace((-substrate.width/2)+ifa.Ledge-1,(-substrate.width/2)+ifa.Ledge,4.0)]; %tab 15 elements step of 0.4

mesh.y = [mesh.y linspace((substrate.length/2)-ifa.e-ifa.sbt-1,(substrate.length/2)-ifa.e-ifa.sbt,5.0)];%mesh.z = [mesh.z linspace(-10.0,5,40.0) + 0];
CSX = DefineRectGrid(CSX, 0.001, mesh);




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MESH right
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace((-substrate.width/2)+ifa.l+ifa.Ledge+1,substrate.width,12.0)]; % a=4.97
mesh.y = [mesh.y linspace(substrate.width/2-ifa.e+ifa.h+1,substrate.length,10.0) ]; % a=5.4

CSX = DefineRectGrid(CSX, 0.001, mesh);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MESH right2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace((-substrate.width/2)+ifa.l+ifa.Ledge,(-substrate.width/2)+ifa.l+ifa.Ledge+1,4.0)];
mesh.y = [mesh.y linspace(substrate.width/2-ifa.e+ifa.h,substrate.width/2-ifa.e+ifa.h+1,4.0) ];

CSX = DefineRectGrid(CSX, 0.001, mesh);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%MESH

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%mesh.x = [mesh.x linspace(-4,4,1.0)];
mesh.x = [mesh.x linspace(-substrate.width/2+ifa.Ledge,-substrate.width/2+ifa.Ledge+ifa.l,35.0) ];  % a-b=4.4; Step=

mesh.y = [mesh.y linspace((substrate.length/2)-ifa.e-ifa.sbt,substrate.width/2-ifa.e+ifa.h,14.0) ]; % a-b=2.5; Step=



mesh.z = [mesh.z linspace(-substrate.width,-1,15.0) ];
mesh.z = [mesh.z linspace(-1,0,4) ];
mesh.z = [mesh.z linspace(substrate.thickness,substrate.thickness+1,4.0) ];
mesh.z = [mesh.z linspace(substrate.thickness+1,substrate.width,15.0) ];

CSX = DefineRectGrid(CSX, 0.001, mesh);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% When third rule does't work, use high resolution meshing


%% finalize the mesh with detec edge DOESN'T WORK Hand meshing is better.

%ifa_mesh = DetectEdges(CSX, [], 'SetProperty','ifa');

%mesh.x = [mesh.x SmoothMeshLines(ifa_mesh.x, 0.5)];

%mesh.y = [mesh.y SmoothMeshLines(ifa_mesh.y, 10)];

% generate a smooth mesh with max. cell size: lambda_min / 20

%mesh = DetectEdges(CSX, mesh);

%mesh = SmoothMesh(mesh, c0 / (f0+fc) / unit / 20);

% Always problem to put smoothmeshing problem error: max_recursion_depth exceeded

%CSX = DefineRectGrid(CSX, unit , mesh); % define the mesh with a drawing unit of 1mm (1e-3)

[color=#FF0000]% Dumb box
CSX = AddDump(CSX,'Et','FileType',1,'SubSampling','4,4,4');
start = [10 10 10];
stop = [-10 -10 -10];
CSX = AddBox(CSX,'Et',0 , start,stop);[/color]

%% add a nf2ff calc box; size is 3 cells away from MUR boundary condition
%%%%%%%It's implements a near field to far field transformation for near field antenna measurement setups
%start = [mesh.x(4)     mesh.y(1)     mesh.z(4)];
%stop  = [mesh.x(end-3) mesh.y(end-3) mesh.z(end-3)];
%[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop);

start = [7     7    7];
stop  = [-7 -7 -7];
[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop);


%% prepare simulation folder

Sim_Path = 'tmp_LIGHT';

Sim_CSX = 'IFA.xml';

try confirm_recursive_rmdir(false,'local'); end

[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

if (show == 1)

CSXGeomPlot( [Sim_Path '/' Sim_CSX] );

end

%%%TO START SIMULATION AND FIND S11, IMPEDANCE, GAIN

%% run openEMS
RunOpenEMS( Sim_Path, Sim_CSX);  %RunOpenEMS( Sim_Path, Sim_CSX, '--debug-PEC -v');

%% postprocessing & do the plots
freq = linspace( max([1e9,f0-fc]), f0+fc, 501 );
port = calcPort(port, Sim_Path, freq);

Zin = port.uf.tot ./ port.if.tot;
s11 = port.uf.ref ./ port.uf.inc;
P_in = real(0.5 * port.uf.tot .* conj( port.if.tot )); % antenna feed power

%% NFFF contour plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%find resonance frequncy from s11
f_res_ind = find(s11==min(s11));
f_res = freq(f_res_ind);

% plot feed point impedance

figure
plot( freq/1e6, abs(Zin), 'k-', 'Linewidth', 2 );
hold on
plot( freq/1e6, real(Zin), 'g--', 'Linewidth', 2 );
hold on
grid on
plot( freq/1e6, imag(Zin), 'm--', 'Linewidth', 2 );
title( 'feed point impedance' );
xlabel( 'frequency f / MHz' );
ylabel( 'impedance Z_{in} / Ohm' );
legend( 'real', 'imag' );
disp( ['-> Zin @ ', num2str(f_res/1e9), 'GHz = ', num2str(Zin(f_res_ind)), ]);
disp( ['-> |Zin| @ ', num2str(f_res/1e9), 'GHz = ', num2str(abs(Zin(f_res_ind))), ' Ohm' ]);

% plot reflection coefficient S11
figure
plot( freq/1e6, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
grid on
title( 'reflection coefficient S_{11}' );
xlabel( 'frequency f / MHz' );
ylabel( 'reflection coefficient |S_{11}|' );
disp( ['-> S11 @ ', num2str(f_res/1e9), 'GHz = ', num2str(20*log10(abs(min(s11)))), ' dB']);

drawnow

%% %%%% 3B dB
disp( 'calculating 3D far field pattern and dumping to vtk (use Paraview to visualize)...' );
thetaRange = (0:2:180);
phiRange = (0:2:360) - 180;
nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, thetaRange*pi/180, phiRange*pi/180,'Verbose',1,'Outfile','3D_Pattern.h5');
%nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, [-180:2:180]*pi/180, [0 90]*pi/180, 'Mode', 1, 'Center', [0 0 length])
%nf2ff = CalcNF2FF(nf2ff, Sim_Path, f0, [-180:2:180]*pi/180, [0 90]*pi/180, 'Mode', 1, [0 0 0], [0 0 length*unit]);

figure
plotFF3D(nf2ff)

%%%%%% display power and directivity
disp( ['radiated power: Prad = ' num2str(nf2ff.Prad) ' Watt']);
disp( ['directivity: Dmax = ' num2str(nf2ff.Dmax) ' (' num2str(10*log10(nf2ff.Dmax)) ' dBi)'] );
disp( ['efficiency: nu_rad = ' num2str(100*nf2ff.Prad./real(P_in(f_res_ind))) ' %']);

E_far_normalized = nf2ff.E_norm{1} / max(nf2ff.E_norm{1}(:)) * nf2ff.Dmax;
DumpFF2VTK([Sim_Path '/3D_Pattern.vtk'],E_far_normalized,thetaRange,phiRange,1e-3);


bonkoung2
Posts: 10
Joined: Mon 11 Jul 2022, 14:26
Contact:

Re: Meshing issues for PCB trace antenna simulation

Post by bonkoung2 » Mon 01 Aug 2022, 21:58

I don't understand your advice for the lumped port: do you mean that I have to remove all my fine manipulations on that side and only mesh the lumped part? Is it like that you want me to do the meshing?
Here you can see a code I have modified the meshing but the result isn't quite good.




Code: Select all

% EXAMPLE / antennas / ) 2.4GHz

%

% This example demonstrates how to:

% - calculate the reflection coefficient of an antenna
% - Give the antenna impedance
% - calculate farfield of an antenna

%

close all

clear

clc

%% setup the simulation

physical_constants;

unit = 1e-3; % all length in mm

substrate.width = 10; % width of substrate

substrate.length = 10; % length of substrate

substrate.thickness = 0.8; % thickness of substrate

substrate.cells = 4; % use 4 cells for meshing substrate

ifa.h = 2.1; % height of short circuit stub

ifa.l = 8.875; % length of radiating element1

ifa.w1 = 0.9; % width of short circuit stub

ifa.w2 = 0.3; % width of radiating element

ifa.wf = 0.3; % width of feed element

ifa.fp = 4; % position of feed element relative to short


% circuit stub

ifa.e = 2.7; % distance to edge

ifa.b = 6.075; %Radiating element 3_5_7 length

ifa.a = 0.9; %Radiating element 2_4_6 length

ifa.c = 0.3; % distance between feeding elementand circuit stub

ifa.d = 0.3; %distance between feeding element and radiating element 2...

ifa.gnd = 0.3; %distance antenna to the ground plane

ifa.Ledge = 0.5; % distance to the left edge 1.1 Previously
ifa.cut = 0 ;  %Cutting element

ifa.sbt= 0.4; %reduce substrate length

length = 125 ;
% substrate setup

substrate.epsR = 4.3;

substrate.kappa = 1e-3 * 2*pi*2.45e9 * EPS0*substrate.epsR;

%setup feeding

feed.R = 50; %feed resistance

%open AppCSXCAD and show ifa

show = 1;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% size of the simulation box

SimBox = [substrate.width*2 substrate.length*2 20];

%% setup FDTD parameter & excitation function

f0 = 2.4e9; % center frequency

fc = 1e9; % 20 dB corner frequency

c0 = 3e8; %Speed of light

%FDTD = InitFDTD(90000, 1e-3, 'TimeStep', 5e-13);
%FDTD = InitFDTD('OverSampling', 400) %highly discourage you to change the timestep.
%we either make the simulation slower or unstable.
%openEMS chooses the fastest possible and stable timestep. So change the oversampling

%FDTD = InitFDTD('NrTS', 100000 );

%FDTD = InitFDTD('NrTS', 200000, 'EndCriteria', 1e-3); %1e-3
FDTD = InitFDTD('NrTS',200000,'EndCriteria', 1e-5);




FDTD = SetGaussExcite( FDTD, f0, fc );

%BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'MUR'}; % simple absorbing boundary conditions because our antenna being destined to be in open space
BC = {'PML_8','PML_8','PML_8','PML_8','PML_8','PML_8'}; %Perfectly Matched Layer absorbing boundary condition, using x number of cells

FDTD = SetBoundaryCond( FDTD, BC );

%% setup CSXCAD geometry & mesh

CSX = InitCSX();

%initialize the mesh with the "air-box" dimensions

mesh.x = [-SimBox(1)/2 SimBox(1)/2];

mesh.y = [-SimBox(2)/2 SimBox(2)/2];

mesh.z = [-SimBox(3)/2 SimBox(3)/2];

%% create substrate

CSX = AddMaterial( CSX, 'substrate');

CSX = SetMaterialProperty( CSX, 'substrate', 'Epsilon',substrate.epsR, 'Kappa', substrate.kappa);

start = [-substrate.width/2 -substrate.length/2 0];

stop = [ substrate.width/2 substrate.length/2 substrate.thickness];

CSX = AddBox( CSX, 'substrate', 1, start, stop );

% add extra cells to discretize the substrate thickness

mesh.z = [linspace(0,substrate.thickness,substrate.cells+1) mesh.z];


%% create ground plane

CSX = AddMetal( CSX, 'groundplane' ); % create a perfect electric conductor (PEC)

start = [-substrate.width/2 -substrate.length/2 substrate.thickness];

stop = [ substrate.width/2 substrate.length/2-ifa.e-ifa.sbt substrate.thickness];

CSX = AddBox(CSX, 'groundplane', 10, start,stop);


%% create ifa
CSX = AddMetal( CSX, 'ifa' ); % create a perfect electric conductor (PEC)
tl = [ifa.Ledge,substrate.length/2-ifa.e,substrate.thickness];   % translate

start = [(-substrate.width/2)+ifa.w1+ifa.c (ifa.h-3*ifa.a+2*ifa.w2-0.3) 0] + tl;
stop = start + [ifa.wf ifa.h 0];
CSX = AddBox( CSX, 'ifa', 10,  start, stop);  % feed element

start = [-substrate.width/2  (ifa.h-3*ifa.a+2*ifa.w2)-ifa.sbt 0] + tl;
stop =  start + [ifa.w1 ifa.h+ifa.sbt 0];
CSX = AddBox( CSX, 'ifa', 10,  start, stop);  % short circuit stub

start = [(-substrate.width/2) ifa.h 0] + tl;
stop = start + [ifa.l -ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element1

start = [(-substrate.width/2+ifa.l) ifa.h 0] + tl;
stop = start + [-ifa.w2 -ifa.a 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element2

start = [(-substrate.width/2+ifa.l) ifa.h-ifa.a 0] + tl;
stop = start + [-ifa.b ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element3

start = [(-substrate.width/2+ifa.l-ifa.b+ifa.w2) ifa.h-ifa.a+ifa.w2 0] + tl;
stop = start + [-ifa.w2 -ifa.a 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element4


start = [(-substrate.width/2+ifa.l) (ifa.h-2*ifa.a+ifa.w2) 0] + tl;
stop = start + [-ifa.b ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element5

start = [(-substrate.width/2+ifa.l) ifa.h-2*ifa.a+2*ifa.w2 0] + tl;
stop = start + [-ifa.w2 -ifa.a 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element6

start = [(-substrate.width/2+ifa.l) (ifa.h-3*ifa.a+2*ifa.w2) 0] + tl;
stop = start + [-ifa.b+ifa.cut ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element7

%% apply the excitation & resist as a current source
start = [ (-substrate.width/2)+ifa.w1+ifa.c (ifa.h-3*ifa.a+2*ifa.w2-0.3) 0] + tl;
stop  = start + [ifa.wf -ifa.sbt+0.3 0];
[CSX port] = AddLumpedPort(CSX, 5 ,1 ,feed.R, start, stop, [0 1 0], true); %


% MESH left
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace(-substrate.width,(-substrate.width/2)+ifa.Ledge+ifa.w1+ifa.c-1,14.0)]; %tab 15 elements step of 0.4

mesh.y = [mesh.y linspace(-substrate.length,(substrate.length/2)-ifa.e-ifa.sbt-1,20.0)];%mesh.z = [mesh.z linspace(-10.0,5,40.0) + 0];
CSX = DefineRectGrid(CSX, 0.001, mesh);  %define the mesh with a drawing unit of 1mm (1e-3)


% MESH left2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace((-substrate.width/2)+ifa.Ledge+ifa.w1+ifa.c-1,(-substrate.width/2)+ifa.Ledge+ifa.w1+ifa.c,7.0)]; %tab 15 elements step of 0.4

mesh.y = [mesh.y linspace((substrate.length/2)-ifa.e-ifa.sbt-1,(substrate.length/2)-ifa.e-ifa.sbt,5.0)];%mesh.z = [mesh.z linspace(-10.0,5,40.0) + 0];
CSX = DefineRectGrid(CSX, 0.001, mesh);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MESH right
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace(-substrate.width/2+ifa.Ledge+ifa.wf+ifa.w1+ifa.c+1,substrate.width,25.0)]; % a=4.97
mesh.y = [mesh.y linspace(substrate.width/2-ifa.e+ifa.h+1,substrate.length,10.0) ]; % a=5.4

CSX = DefineRectGrid(CSX, 0.001, mesh);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MESH right2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace(-substrate.width/2+ifa.Ledge+ifa.wf+ifa.w1+ifa.c,-substrate.width/2+ifa.Ledge+ifa.wf+ifa.w1+ifa.c+1,7.0)];
mesh.y = [mesh.y linspace(substrate.width/2-ifa.e+ifa.h,substrate.width/2-ifa.e+ifa.h+1,4.0) ];
CSX = DefineRectGrid(CSX, 0.001, mesh);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%MESH
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace(-substrate.width/2+ifa.Ledge+ifa.w1+ifa.c,-substrate.width/2+ifa.Ledge+ifa.wf+ifa.w1+ifa.c,5.0) ];  % a-b=4.4; Step=
mesh.y = [mesh.y linspace((substrate.length/2)-ifa.e-ifa.sbt,substrate.width/2-ifa.e+ifa.h,14.0) ]; % a-b=2.5; Step=


mesh.z = [mesh.z linspace(-substrate.width,-1,15.0) ];
mesh.z = [mesh.z linspace(-1,0,4) ];
mesh.z = [mesh.z linspace(substrate.thickness,substrate.thickness+1,4.0) ];
mesh.z = [mesh.z linspace(substrate.thickness+1,substrate.width,15.0) ];

CSX = DefineRectGrid(CSX, 0.001, mesh);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%





% Dumb box
CSX = AddDump(CSX,'Et','FileType',1,'SubSampling','4,4,4');
start = [10 10 10];
stop = [-10 -10 -10];
CSX = AddBox(CSX,'Et',0 , start,stop);

%% add a nf2ff calc box; size is 3 cells away from MUR boundary condition
%%%%%%%It's implements a near field to far field transformation for near field antenna measurement setups

start = [7     7    7];
stop  = [-7 -7 -7];
[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop);


%% prepare simulation folder

Sim_Path = 'tmp_LIGHT';

Sim_CSX = 'IFA.xml';

try confirm_recursive_rmdir(false,'local'); end

[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

if (show == 1)

CSXGeomPlot( [Sim_Path '/' Sim_CSX] );

end





%%%TO START SIMULATION AND FIND S11, IMPEDANCE, GAIN

%% run openEMS
RunOpenEMS( Sim_Path, Sim_CSX);  %RunOpenEMS( Sim_Path, Sim_CSX, '--debug-PEC -v');

%% postprocessing & do the plots
freq = linspace( max([1e9,f0-fc]), f0+fc, 501 );
port = calcPort(port, Sim_Path, freq);

Zin = port.uf.tot ./ port.if.tot;
s11 = port.uf.ref ./ port.uf.inc;
P_in = real(0.5 * port.uf.tot .* conj( port.if.tot )); % antenna feed power

%% NFFF contour plots %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%find resonance frequncy from s11
f_res_ind = find(s11==min(s11));
f_res = freq(f_res_ind);


% plot feed point impedance

figure
plot( freq/1e6, abs(Zin), 'k-', 'Linewidth', 2 );
hold on
plot( freq/1e6, real(Zin), 'g--', 'Linewidth', 2 );
hold on
grid on
plot( freq/1e6, imag(Zin), 'm--', 'Linewidth', 2 );
title( 'feed point impedance' );
xlabel( 'frequency f / MHz' );
ylabel( 'impedance Z_{in} / Ohm' );
legend( 'real', 'imag' );
disp( ['-> Zin @ ', num2str(f_res/1e9), 'GHz = ', num2str(Zin(f_res_ind)), ]);
disp( ['-> |Zin| @ ', num2str(f_res/1e9), 'GHz = ', num2str(abs(Zin(f_res_ind))), ' Ohm' ]);

% plot reflection coefficient S11
figure
plot( freq/1e6, 20*log10(abs(s11)), 'k-', 'Linewidth', 2 );
grid on
title( 'reflection coefficient S_{11}' );
xlabel( 'frequency f / MHz' );
ylabel( 'reflection coefficient |S_{11}|' );
disp( ['-> S11 @ ', num2str(f_res/1e9), 'GHz = ', num2str(20*log10(abs(min(s11)))), ' dB']);


drawnow

%% %%%% 3B dB
disp( 'calculating 3D far field pattern and dumping to vtk (use Paraview to visualize)...' );
thetaRange = (0:2:180);
phiRange = (0:2:360) - 180;
nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, thetaRange*pi/180, phiRange*pi/180,'Verbose',1,'Outfile','3D_Pattern.h5');
%nf2ff = CalcNF2FF(nf2ff, Sim_Path, f_res, [-180:2:180]*pi/180, [0 90]*pi/180, 'Mode', 1, 'Center', [0 0 length])
%nf2ff = CalcNF2FF(nf2ff, Sim_Path, f0, [-180:2:180]*pi/180, [0 90]*pi/180, 'Mode', 1, [0 0 0], [0 0 length*unit]);


figure
plotFF3D(nf2ff)

%%%%%% display power and directivity
disp( ['radiated power: Prad = ' num2str(nf2ff.Prad) ' Watt']);
disp( ['directivity: Dmax = ' num2str(nf2ff.Dmax) ' (' num2str(10*log10(nf2ff.Dmax)) ' dBi)'] );
disp( ['efficiency: nu_rad = ' num2str(100*nf2ff.Prad./real(P_in(f_res_ind))) ' %']);

E_far_normalized = nf2ff.E_norm{1} / max(nf2ff.E_norm{1}(:)) * nf2ff.Dmax;
DumpFF2VTK([Sim_Path '/3D_Pattern.vtk'],E_far_normalized,thetaRange,phiRange,1e-3);

asdf
Posts: 15
Joined: Sat 11 Aug 2018, 08:19

Re: Meshing issues for PCB trace antenna simulation

Post by asdf » Wed 03 Aug 2022, 08:49

Regarding the lumped port, probably you need to add one horizontal of mesh so that lumped port would touch the mesh on both sides. Currently it starts on a mesh line that touches ground plane and ends in the middle of mesh cell (so simulator may remove it or do some unexpected approximation).
About mesh, If I display the geometry in AppCSXCAD, click "PP" and "xy" in top toolbar I can see the mesh is quite coarse. If the antenna would be approximated by the mesh cells it may be totally different shape.
I usually place some important mesh lines (for example to make sure lumped parts are touching mesh or thin metal sheets are not skipped), then I use smoothmeshlines to fill gaps.

bonkoung2
Posts: 10
Joined: Mon 11 Jul 2022, 14:26
Contact:

Re: Meshing issues for PCB trace antenna simulation

Post by bonkoung2 » Wed 03 Aug 2022, 21:20

Hello thanks again for your response,
When I do fine meshing I get an error for the timestep and the simulation last a long time 1h :
Here what I got and the code when I add those 2lines in my code:

mesh = SmoothMesh(mesh, c0 / (f0+fc) / unit / 20);
CSX = DefineRectGrid(CSX, unit, mesh);



Create FDTD operator (compressed SSE + multi-threading)
FDTD simulation size: 162x97x70 --> 1.09998e+06 FDTD cells
FDTD timestep is: 1.38364e-13 s; Nyquist rate: 1062 timesteps @3.4027e+09 Hz
openEMS::SetupFDTD: Warning, the timestep seems to be very small --> long simulation. Check your mesh!?
Excitation signal length is: 20705 timesteps (2.86482e-09s)
Max. number of timesteps: 100000 ( --> 4.82975 * Excitation signal length)
Create FDTD engine (compressed SSE + multi-threading)
.................................................................................................................
..................................................................................................................................................

[@ 1h11m44s] Timestep: 99640 || Speed: 36.4 MC/s (3.022e-02 s/TS) || Energy: ~3.47e-18 (-25.30dB)
[@ 1h11m52s] Timestep: 99905 || Speed: 36.6 MC/s (3.008e-02 s/TS) || Energy: ~2.32e-18 (-27.06dB)
RunFDTD: Warning: Max. number of timesteps was reached before the end-criteria of -70dB was reached...

You may want to choose a higher number of max. timesteps...
Time for 100000 iterations with 1099980.00 cells : 4315.15 sec
Speed: 25.49 MCells/s
-> Zin @ 2.704GHz = 25.0423-85.0167i
-> |Zin| @ 2.704GHz = 88.6282 Ohm
-> S11 @ 2.704GHz = -2.143 dB
calculating 3D far field pattern and dumping to vtk (use Paraview to visualize)...
----------------------------------------------------------------------
| nf2ff, near-field to far-field transformation for openEMS
| (C) 2012-2014 Thorsten Liebig <thorsten.liebig@gmx.de> GPL license
----------------------------------------------------------------------
nf2ff: Set verbose level to 1
nf2ff: Reading planes: nf2ff_E_xn.h5 & nf2ff_H_xn.h5
nf2ff: Data-Size: 1x85x58
nf2ff: Analysing far-field for 1 frequencies.
nf2ff: Reading planes: nf2ff_E_xp.h5 & nf2ff_H_xp.h5
nf2ff: Data-Size: 1x85x58
nf2ff: Analysing far-field for 1 frequencies.
nf2ff: Reading planes: nf2ff_E_yn.h5 & nf2ff_H_yn.h5
nf2ff: Data-Size: 147x1x58
nf2ff: Analysing far-field for 1 frequencies.
nf2ff: Reading planes: nf2ff_E_yp.h5 & nf2ff_H_yp.h5
nf2ff: Data-Size: 147x1x58
nf2ff: Analysing far-field for 1 frequencies.
nf2ff: Reading planes: nf2ff_E_zn.h5 & nf2ff_H_zn.h5
nf2ff: Data-Size: 147x85x1
nf2ff: Analysing far-field for 1 frequencies.
nf2ff: Reading planes: nf2ff_E_zp.h5 & nf2ff_H_zp.h5
nf2ff: Data-Size: 147x85x1
nf2ff: Analysing far-field for 1 frequencies.
radiated power: Prad = 1.3412e-29 Watt
directivity: Dmax = 1.3891 (1.4272 dBi)
efficiency: nu_rad = 39.5107 %
>>









I just put a part of the code this permit just to see the CSX geometric representation and the meshing:

Code: Select all

% EXAMPLE / antennas / ) 2.4GHz

%

% This example demonstrates how to:

% - calculate the reflection coefficient of an antenna
% - Give the antenna impedance
% - calculate farfield of an antenna

%

close all


clear

clc

%% setup the simulation

physical_constants;

unit = 1e-3; % all length in mm

substrate.width = 10; % width of substrate

substrate.length = 10; % length of substrate

substrate.thickness = 0.8; % thickness of substrate

substrate.cells = 4; % use 4 cells for meshing substrate

%Antenna parameters

ifa.l = 7.875; % length of radiating element1
ifa.b = 6.075; %Radiating element 3_5_7 length
ifa.h = 2.1; % height of short circuit stub



ifa.w1 = 0.9; % width of short circuit stub

ifa.w2 = 0.3; % width of radiating element

ifa.wf = 0.3; % width of feed element

ifa.fp = 4; % position of feed element relative to short


ifa.e = 2.7; % distance antenna to top edge


ifa.a = 0.9; %Radiating element 2_4_6 length

ifa.c = 0.3; % distance between feeding elementand circuit stub

ifa.d = 0.3; %distance between feeding element and radiating element 2...

ifa.gnd = 0.3; %distance antenna to the ground plane

ifa.Ledge = 0.5; % distance to the left edge 1.1 Previously
ifa.cut = 0 ;  %Cutting element

ifa.sbt= 0.4; %reduce substrate length



% substrate setup

substrate.epsR = 4.3;

substrate.kappa = 1e-3 * 2*pi*2.45e9 * EPS0*substrate.epsR;

%setup feeding

feed.R = 50; %feed resistance

%open AppCSXCAD and show ifa

show = 1;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% size of the simulation box

SimBox = [substrate.width*2 substrate.length*2 20];

%% setup FDTD parameter & excitation function

f0 = 2.4e9; % center frequency

fc = 1e9; % 20 dB corner frequency

c0 = 3e8; %Speed of light

%FDTD = InitFDTD(90000, 1e-3, 'TimeStep', 5e-13);
%FDTD = InitFDTD('OverSampling', 400) %highly discourage you to change the timestep.
%we either make the simulation slower or unstable.
%openEMS chooses the fastest possible and stable timestep. So change the oversampling

%FDTD = InitFDTD('NrTS', 100000 );

%FDTD = InitFDTD('NrTS', 200000, 'EndCriteria', 1e-3); %1e-3
FDTD = InitFDTD('NrTS',100000,'EndCriteria', 1e-7);




FDTD = SetGaussExcite( FDTD, f0, fc );

%BC = {'MUR' 'MUR' 'MUR' 'MUR' 'MUR' 'MUR'}; % simple absorbing boundary conditions because our antenna being destined to be in open space
BC = {'PML_8','PML_8','PML_8','PML_8','PML_8','PML_8'}; %Perfectly Matched Layer absorbing boundary condition, using x number of cells

FDTD = SetBoundaryCond( FDTD, BC );

%% setup CSXCAD geometry & mesh

CSX = InitCSX();

%initialize the mesh with the "air-box" dimensions

mesh.x = [-SimBox(1)/2 SimBox(1)/2];

mesh.y = [-SimBox(2)/2 SimBox(2)/2];

mesh.z = [-SimBox(3)/2 SimBox(3)/2];

%% create substrate

CSX = AddMaterial( CSX, 'substrate');

CSX = SetMaterialProperty( CSX, 'substrate', 'Epsilon',substrate.epsR, 'Kappa', substrate.kappa);

start = [-substrate.width/2 -substrate.length/2 0];

stop = [ substrate.width/2 substrate.length/2 substrate.thickness];

CSX = AddBox( CSX, 'substrate', 1, start, stop );

% add extra cells to discretize the substrate thickness

mesh.z = [linspace(0,substrate.thickness,substrate.cells+1) mesh.z];


%% create ground plane

CSX = AddMetal( CSX, 'groundplane' ); % create a perfect electric conductor (PEC)

start = [-substrate.width/2 -substrate.length/2 substrate.thickness];

stop = [ substrate.width/2 substrate.length/2-ifa.e-ifa.sbt substrate.thickness];

CSX = AddBox(CSX, 'groundplane', 10, start,stop);


%% create ifa
CSX = AddMetal( CSX, 'ifa' ); % create a perfect electric conductor (PEC)
tl = [ifa.Ledge,substrate.length/2-ifa.e,substrate.thickness];   % translate

start = [(-substrate.width/2)+ifa.w1+ifa.c (ifa.h-3*ifa.a+2*ifa.w2-0.3) 0] + tl;
stop = start + [ifa.wf ifa.h 0];
CSX = AddBox( CSX, 'ifa', 10,  start, stop);  % feed element

start = [-substrate.width/2  (ifa.h-3*ifa.a+2*ifa.w2)-ifa.sbt 0] + tl;
stop =  start + [ifa.w1 ifa.h+ifa.sbt 0];
CSX = AddBox( CSX, 'ifa', 10,  start, stop);  % short circuit stub

start = [(-substrate.width/2) ifa.h 0] + tl;
stop = start + [ifa.l -ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element1

start = [(-substrate.width/2+ifa.l) ifa.h 0] + tl;
stop = start + [-ifa.w2 -ifa.a 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element2

start = [(-substrate.width/2+ifa.l) ifa.h-ifa.a 0] + tl;
stop = start + [-ifa.b ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element3

start = [(-substrate.width/2+ifa.l-ifa.b+ifa.w2) ifa.h-ifa.a+ifa.w2 0] + tl;
stop = start + [-ifa.w2 -ifa.a 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element4


start = [(-substrate.width/2+ifa.l) (ifa.h-2*ifa.a+ifa.w2) 0] + tl;
stop = start + [-ifa.b ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element5

start = [(-substrate.width/2+ifa.l) ifa.h-2*ifa.a+2*ifa.w2 0] + tl;
stop = start + [-ifa.w2 -ifa.a 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element6

start = [(-substrate.width/2+ifa.l) (ifa.h-3*ifa.a+2*ifa.w2) 0] + tl;
stop = start + [-ifa.b+ifa.cut ifa.w2 0];
CSX = AddBox( CSX, 'ifa', 10, start, stop);   % radiating element7

%% apply the excitation & resist as a current source
start = [ (-substrate.width/2)+ifa.w1+ifa.c (ifa.h-3*ifa.a+2*ifa.w2-0.3) 0] + tl;
stop  = start + [ifa.wf -ifa.sbt+0.3 0];
[CSX port] = AddLumpedPort(CSX, 5 ,1 ,feed.R, start, stop, [0 1 0], true); %


% MESH left
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace(-substrate.width,(-substrate.width/2)+ifa.Ledge-1,5.0)]; %tab 15 elements step of 0.4

mesh.y = [mesh.y linspace(-substrate.length,(substrate.length/2)-ifa.e-ifa.sbt-1,10.0)];%mesh.z = [mesh.z linspace(-10.0,5,40.0) + 0];
CSX = DefineRectGrid(CSX, 0.001, mesh);  %define the mesh with a drawing unit of 1mm (1e-3)


% MESH left2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace((-substrate.width/2)+ifa.Ledge-1,(-substrate.width/2)+ifa.Ledge,4.0)]; %tab 15 elements step of 0.4

mesh.y = [mesh.y linspace((substrate.length/2)-ifa.e-ifa.sbt-1,(substrate.length/2)-ifa.e-ifa.sbt,5.0)];%mesh.z = [mesh.z linspace(-10.0,5,40.0) + 0];
CSX = DefineRectGrid(CSX, 0.001, mesh);




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MESH right
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace((-substrate.width/2)+ifa.l+ifa.Ledge+1,substrate.width,7.0)]; % a=4.97
mesh.y = [mesh.y linspace(substrate.width/2-ifa.e+ifa.h+1,substrate.length,5.0) ]; % a=5.4

CSX = DefineRectGrid(CSX, 0.001, mesh);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MESH right2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mesh.x = [mesh.x linspace((-substrate.width/2)+ifa.l+ifa.Ledge,(-substrate.width/2)+ifa.l+ifa.Ledge+1,4.0)];
mesh.y = [mesh.y linspace(substrate.width/2-ifa.e+ifa.h,substrate.width/2-ifa.e+ifa.h+1,4.0) ];

CSX = DefineRectGrid(CSX, 0.001, mesh);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%MESH

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%mesh.x = [mesh.x linspace(-4,4,1.0)];
mesh.x = [mesh.x linspace(-substrate.width/2+ifa.Ledge,-substrate.width/2+ifa.Ledge+ifa.l,40.0) ];  % a-b=4.4; Step=

mesh.y = [mesh.y linspace((substrate.length/2)-ifa.e-ifa.sbt,substrate.width/2-ifa.e+ifa.h,14.0) ]; % a-b=2.5; Step=



mesh.z = [mesh.z linspace(-substrate.width,-1,8.0) ];
mesh.z = [mesh.z linspace(-1,0,4) ];
mesh.z = [mesh.z linspace(substrate.thickness,substrate.thickness+1,4.0) ];
mesh.z = [mesh.z linspace(substrate.thickness+1,substrate.width,8.0) ];

CSX = DefineRectGrid(CSX, 0.001, mesh);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% When third rule does't work, use high resolution meshing


%% finalize the mesh with detec edge DOESN'T WORK Hand meshing is better.

%ifa_mesh = DetectEdges(CSX, [], 'SetProperty','ifa');

%mesh.x = [mesh.x SmoothMeshLines(ifa_mesh.x, 0.5)];

%mesh.y = [mesh.y SmoothMeshLines(ifa_mesh.y, 10)];

% generate a smooth mesh with max. cell size: lambda_min / 20

%mesh = DetectEdges(CSX, mesh);

%mesh = SmoothMesh(mesh, c0 / (f0+fc) / unit / 20);

% Always problem to put smoothmeshing problem error: max_recursion_depth exceeded

%CSX = DefineRectGrid(CSX, unit , mesh); % define the mesh with a drawing unit of 1mm (1e-3)

%% finalize the mesh
% generate a smooth mesh with max. cell size: lambda_min / 20


mesh = SmoothMesh(mesh, c0 / (f0+fc) / unit / 20);

CSX = DefineRectGrid(CSX, unit, mesh);


% Dumb box or storage box We can visualize after the E- field or H- depends
CSX = AddDump(CSX,'Et','FileType',1,'SubSampling','4,4,4'); %'4,4,4', which means, dump only every forth line in x- and y- and only every forth line in z-direction.
start = [10 10 10];
stop = [-10 -10 -10];
CSX = AddBox(CSX,'Et',0 , start,stop);

%% add a nf2ff calc box; size is 3 cells away from MUR boundary condition
%%%%%%%It's implements a near field to far field transformation for near field antenna measurement setups
%start = [mesh.x(4)     mesh.y(1)     mesh.z(4)];
%stop  = [mesh.x(end-3) mesh.y(end-3) mesh.z(end-3)];
%[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop);

start = [7     7    7];
stop  = [-7 -7 -7];
[CSX nf2ff] = CreateNF2FFBox(CSX, 'nf2ff', start, stop);


%% prepare simulation folder

Sim_Path = 'tmp_LIGHT';

Sim_CSX = 'IFA.xml';

try confirm_recursive_rmdir(false,'local'); end

[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

if (show == 1)

CSXGeomPlot( [Sim_Path '/' Sim_CSX] );

end


%%%TO START SIMULATION AND FIND S11, IMPEDANCE, GAIN





asdf
Posts: 15
Joined: Sat 11 Aug 2018, 08:19

Re: Meshing issues for PCB trace antenna simulation

Post by asdf » Tue 09 Aug 2022, 13:55

I'd remove the
'NrTS',100000,'EndCriteria', 1e-7
then leave that simulation for a few hours and assume that it's ok if energy drop to the default 50dB. I'm not sure if it's ok but probably some simulations may require fine mesh and long time. Using 1/3 2/3 mesh may help to get better results in shorter time.

Post Reply