thliebig / openEMS

openEMS is a free and open-source electromagnetic field solver using the EC-FDTD method.
http://openEMS.de
GNU General Public License v3.0
413 stars 146 forks source link

Weird Behavior of Lumped Components #136

Closed 2nOrderEDO closed 6 months ago

2nOrderEDO commented 6 months ago

Hello fellow OpenEMS users,

I have been working on a simulation for the last couple of days. I was able to get it up and running by learning from the Wiki, examples and tutorials in GitHub, but I have problems with lumped components.

To give some context, I'm simulating a simple three resistor splitter/combiner in a 2-layer PCB, for a range frequency from "DC" to 10 GHz. All the resistors are 50 Ohm. My geometry looks like this:

image

Which is a simplified version of the original design:

image

I decided to remove the vias and top copper fills to simplify the geometry in order to get a first working approximation. My plan is to add this details back once I have everything figured out. The original design comes from KiCad, where I made the simplifications and the exported an Hyper-lynx file. Many parts of my script are based on the original PCB import tutorial from the wiki: Tutorial: Importing with hyp2mat

In my Octave script, I declare three lumped components R1, R2 and R3 and I assign box primitives to them on the appropriate positions over the PCB. The main problem I'm facing is that adding or removing the resistors seems to have no effect on the simulation results.

For reference, this is are my simulation outputs with AND without the resistors. Pay special attention to the voltage at the output ports in Figure 3 (blue and green signals):

image

if I replace R1 and R3 by "Metal" through the command AddMetal, then I get the following results, which I think they are closer to a valid result, since at least I can see some voltages on the output ports in figure 3:

[Hyp_File_Plus_Code_Splitter.zip](https://github.com/thliebig/openEMS/files/14223112/Hyp_File_Plus_Code_Splitter.zip)

# CSX = AddLumpedElement( CSX, 'R1', 1, 'Caps', 1, 'R', 50.0);
CSX = AddLumpedElement( CSX, 'R2', 1, 'Caps', 1, 'R', 50.0);
# CSX = AddLumpedElement( CSX, 'R3', 1, 'Caps', 1, 'R', 50.0);
CSX = AddMetal(CSX,'metal');

## Resistor bodies
CSX = AddBox(CSX,'metal',999,[-R_Width/2, -R_Length/2, pad1_stop(3)],
                       [R_Width/2, R_Length/2,(pad1_stop(3) + R_Height)],
                        'Transform',{'Rotate_Z',-pi/4, 'Translate', '0.0145,0.0182,0.00'});

CSX = AddBox(CSX,'R2',999,[-R_Width/2, -R_Length/2, pad1_stop(3)],
                        [R_Width/2, R_Length/2,(pad1_stop(3) + R_Height)],
                        'Transform',{'Rotate_Z', 0, 'Translate', '0.0172,0.0160,0.00'});                        

CSX = AddBox(CSX,'metal',999,[-R_Width/2, -R_Length/2, pad1_stop(3)],
                        [R_Width/2, R_Length/2,(pad1_stop(3) + R_Height)],
                        'Transform',{'Rotate_Z',pi/4, 'Translate', '0.0145,0.0138,0.00'});

image

Original script, with R1, R2 and R3 is as follows:

close all
clear
clc

f_max = 10e9; # 10 Ghz
physical_constants;
unit = 1000; 

# Load PCB
CSX = InitCSX();
CSX = ImportHyperLynx(CSX, 'Power_Divider_50R_V02_Simplified_1.5mm.hyp');

# Components
[pad1_material, pad1_start, pad1_stop] = GetHyperLynxPort(CSX, 'R1.1'); # Just to get the height

CSX = AddLumpedElement( CSX, 'R1', 1, 'Caps', 1, 'R', 50.0);
CSX = AddLumpedElement( CSX, 'R2', 1, 'Caps', 1, 'R', 50.0);
CSX = AddLumpedElement( CSX, 'R3', 1, 'Caps', 1, 'R', 50.0);
#CSX = AddMetal(CSX,'metal');

## Resistor size
R_Height = 0.5/unit;
R_Width = 1.6/unit;
R_Length = 3.2/unit;

## Resistor bodies
CSX = AddBox(CSX,'R1',999,[-R_Width/2, -R_Length/2, pad1_stop(3)],
                       [R_Width/2, R_Length/2,(pad1_stop(3) + R_Height)],
                        'Transform',{'Rotate_Z',-pi/4, 'Translate', '0.0145,0.0182,0.00'});

CSX = AddBox(CSX,'R2',999,[-R_Width/2, -R_Length/2, pad1_stop(3)],
                        [R_Width/2, R_Length/2,(pad1_stop(3) + R_Height)],
                        'Transform',{'Rotate_Z',pi/4, 'Translate', '0.0145,0.0138,0.00'});

CSX = AddBox(CSX,'R3',999,[-R_Width/2, -R_Length/2, pad1_stop(3)],
                        [R_Width/2, R_Length/2,(pad1_stop(3) + R_Height)],
                        'Transform',{'Rotate_Z', 0, 'Translate', '0.0172,0.0160,0.00'});

# Add excitation and load
# TP1.1 is right bottom port

port_wide = 0.2; # mm
port_length = 0.2; # mm

in_port_start = [1.5-port_wide/2 16-port_length/2 1.5]/unit;
in_port_stop  = [1.5+port_wide/2 16+port_length/2 0]/unit;

out_top_port_start = [30.5-port_wide/2 26-port_length/2 1.5]/unit;
out_top_port_stop  = [30.5+port_wide/2 26+port_length/2 0]/unit;

out_bot_port_start = [30.5-port_wide/2 6-port_length/2 1.5]/unit;
out_bot_port_stop  = [30.5+port_wide/2 6+port_length/2 0]/unit;

[CSX, port{1}] = AddLumpedPort( CSX, 999, 1, 50, in_port_start, in_port_stop, [0 0 1], true); # Excitation
[CSX, port{2}] = AddLumpedPort( CSX, 999, 2, 50, out_top_port_start, out_top_port_stop, [0 0 1]); # Load
[CSX, port{3}] = AddLumpedPort( CSX, 999, 3, 50, out_bot_port_start, out_bot_port_stop, [0 0 1]); # Load

# My Mesh

mesh.x = SmoothMeshLines([0 32]/unit, .2/unit);
mesh.y = SmoothMeshLines([0 32]/unit, .2/unit);
mesh.z = SmoothMeshLines([-0.5 2.5]/unit, .5/unit);

AirBox = c0 / f_max / 25;

mesh.x = [min(mesh.x)-AirBox max(mesh.x)+AirBox mesh.x];
mesh.y = [min(mesh.y)-AirBox max(mesh.y)+AirBox mesh.y];
mesh.z = [min(mesh.z)-2*AirBox max(mesh.z)+2*AirBox mesh.z];

CSX = DefineRectGrid(CSX, 1/unit ,mesh);

# Boundary Conditions

FDTD = InitFDTD();
FDTD = SetGaussExcite(FDTD, f_max/2, f_max/2);
#FDTD = SetSinusExcite(FDTD,1e9)

BC   = {'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8' 'PML_8'};
FDTD = SetBoundaryCond(FDTD, BC );

mesh = AddPML(mesh, 8);
CSX = DefineRectGrid(CSX, 1, mesh);
mesh = SmoothMesh(mesh, 1, 'algorithm', [ 1 ]);

# Write to disk

Sim_Path = 'tmp';
Sim_CSX = 'msl.xml';

[status, message, messageid] = rmdir(Sim_Path, 's'); % clear previous directory
[status, message, messageid] = mkdir(Sim_Path ); % create empty simulation folder

WriteOpenEMS([Sim_Path '/' Sim_CSX], FDTD, CSX);
CSXGeomPlot([Sim_Path '/' Sim_CSX]);

# Simulation
# #{
RunOpenEMS(Sim_Path, Sim_CSX);

# Calculations
f = linspace( 1e6, f_max, 1601 );
port = calcPort(port, Sim_Path, f, 'RefImpedance', 50);
s11 = port{1}.uf.ref./ port{1}.uf.inc;
s21 = port{2}.uf.ref./ port{1}.uf.inc;
s12 = port{1}.uf.ref./ port{2}.uf.inc;

# Plot: S-Parameters

figure(1);
semilogx(f/1e9,20*log10(abs(s11)),'k-','LineWidth',2);
hold on;
grid on;
semilogx(f/1e9,20*log10(abs(s21)),'r--','LineWidth',2);
hold on;
grid on;
semilogx(f/1e9,20*log10(abs(s12)),'g--','LineWidth',2);
legend('S_{11}','S_{21}','S_{12}');
ylabel('S-Parameter (dB)','FontSize',12);
xlabel('Frequency (GHz) \rightarrow','FontSize',12);
#title('Test');
ylim([-80 10]);
print('sparam.png', '-dpng');

# Plot: Complex Impedance from feed point
Zin = port{1}.uf.tot ./ port{1}.if.tot;

figure(2);
semilogx(f/1e9,real(Zin),'k-','LineWidth',2);
hold on
grid on
semilogx(f/1e9,imag(Zin),'r--','LineWidth',2);
hold on
grid on
semilogx(f/1e9,sqrt(imag(Zin).^2+real(Zin).^2),'b','LineWidth',2);
title( 'Feed Point Impedance');
xlabel('Frequency (GHz) \rightarrow','FontSize',12);
ylabel('Impedance Z_{in} [Ohm]', 'FontSize', 12);
legend( 'Real', 'Imag', 'Abs');

# Plot: Voltage in the input and output ports
figure(3);
plot( port{1}.ut.time, port{1}.ut.tot, 'r', 'Linewidth', 2 );
hold on
grid on
plot( port{2}.ut.time, port{2}.ut.tot, 'g', 'Linewidth', 2 );
hold on
grid on
plot( port{3}.ut.time, port{3}.ut.tot, 'b', 'Linewidth', 2 );
title( 'Time Domain Voltage');
xlabel('Time [s]','FontSize',12);
ylabel('Voltage [V]', 'FontSize', 12);
legend( 'Input', 'Top Out', 'Bot Out');

Summary:

I would like to know if I'm correctly using the lumped elements. I have also tried to do the following, without success:

Other info:

The simulation takes around 3 min to run in my old i7-7700K. I uploaded a .zip file with the Octave script file and the hyperlynx file for simulation, just in case someone want's to try to test my simulation.

I added below an example output from running the above script, just for reference. It also includes my version of OpenEMS and related libraries.

remove entire contents of tmp? (yes or no) yes
invoking AppCSXCAD, exit to continue script...
QCSXCAD - disabling editing
args = "msl.xml"
 ----------------------------------------------------------------------
 | openEMS 64bit -- version v0.0.36-14-g6a13d81
 | (C) 2010-2023 Thorsten Liebig <thorsten.liebig@gmx.de>  GPL license
 ----------------------------------------------------------------------
        Used external libraries:
                CSXCAD -- Version: v0.6.3-2-gc6a1587
                hdf5   -- Version: 1.10.7
                          compiled against: HDF5 library version: 1.10.7
                tinyxml -- compiled against: 2.6.2
                fparser
                boost  -- compiled against: 1_74
                vtk -- Version: 7.1.1
                       compiled against: 7.1.1

Create FDTD operator (compressed SSE + multi-threading)
FDTD simulation size: 179x179x25 --> 801025 FDTD cells
FDTD timestep is: 2.77129e-13 s; Nyquist rate: 180 timesteps @1.00234e+10 Hz
Excitation signal length is: 2068 timesteps (5.73102e-10s)
Max. number of timesteps: 1000000000 ( --> 483559 * Excitation signal length)
Create FDTD engine (compressed SSE + multi-threading)
Running FDTD engine... this may take a while... grab a cup of coffee?!?
[@        4s] Timestep:          180 || Speed:   29.7 MC/s (2.700e-02 s/TS) || Energy: ~1.28e-22 (- 0.00dB)
[@        9s] Timestep:          405 || Speed:   39.2 MC/s (2.045e-02 s/TS) || Energy: ~3.80e-19 (- 0.00dB)
[@       13s] Timestep:          630 || Speed:   40.0 MC/s (2.002e-02 s/TS) || Energy: ~1.78e-17 (- 0.00dB)
[@       18s] Timestep:          855 || Speed:   38.3 MC/s (2.093e-02 s/TS) || Energy: ~3.04e-16 (- 0.00dB)
Multithreaded Engine: Best performance found using 3 threads.
[@       23s] Timestep:         1080 || Speed:   39.9 MC/s (2.009e-02 s/TS) || Energy: ~1.46e-15 (- 0.00dB)
[@       27s] Timestep:         1305 || Speed:   40.8 MC/s (1.963e-02 s/TS) || Energy: ~2.43e-15 (- 0.00dB)
[@       31s] Timestep:         1530 || Speed:   41.4 MC/s (1.936e-02 s/TS) || Energy: ~2.69e-15 (- 0.00dB)
[@       36s] Timestep:         1755 || Speed:   41.8 MC/s (1.917e-02 s/TS) || Energy: ~1.02e-15 (- 4.22dB)
[@       40s] Timestep:         1980 || Speed:   40.9 MC/s (1.960e-02 s/TS) || Energy: ~2.85e-16 (- 9.75dB)
[@       45s] Timestep:         2205 || Speed:   40.1 MC/s (1.999e-02 s/TS) || Energy: ~3.26e-17 (-19.17dB)
[@       49s] Timestep:         2430 || Speed:   40.0 MC/s (2.001e-02 s/TS) || Energy: ~1.34e-17 (-23.03dB)
[@       54s] Timestep:         2655 || Speed:   39.6 MC/s (2.023e-02 s/TS) || Energy: ~4.49e-18 (-27.78dB)
[@       58s] Timestep:         2880 || Speed:   40.5 MC/s (1.978e-02 s/TS) || Energy: ~2.03e-18 (-31.24dB)
[@     1m03s] Timestep:         3105 || Speed:   40.8 MC/s (1.962e-02 s/TS) || Energy: ~6.94e-19 (-35.89dB)
[@     1m07s] Timestep:         3330 || Speed:   39.9 MC/s (2.005e-02 s/TS) || Energy: ~3.44e-19 (-38.93dB)
[@     1m12s] Timestep:         3555 || Speed:   41.0 MC/s (1.952e-02 s/TS) || Energy: ~2.23e-19 (-40.81dB)
[@     1m16s] Timestep:         3780 || Speed:   40.8 MC/s (1.965e-02 s/TS) || Energy: ~1.56e-19 (-42.37dB)
[@     1m20s] Timestep:         4005 || Speed:   41.9 MC/s (1.914e-02 s/TS) || Energy: ~1.25e-19 (-43.35dB)
[@     1m25s] Timestep:         4230 || Speed:   41.5 MC/s (1.928e-02 s/TS) || Energy: ~1.03e-19 (-44.17dB)
[@     1m29s] Timestep:         4455 || Speed:   41.6 MC/s (1.924e-02 s/TS) || Energy: ~9.16e-20 (-44.68dB)
[@     1m33s] Timestep:         4680 || Speed:   41.2 MC/s (1.943e-02 s/TS) || Energy: ~8.24e-20 (-45.14dB)
[@     1m38s] Timestep:         4905 || Speed:   41.1 MC/s (1.950e-02 s/TS) || Energy: ~7.60e-20 (-45.49dB)
[@     1m42s] Timestep:         5130 || Speed:   40.9 MC/s (1.958e-02 s/TS) || Energy: ~7.06e-20 (-45.81dB)
[@     1m46s] Timestep:         5355 || Speed:   40.9 MC/s (1.957e-02 s/TS) || Energy: ~6.56e-20 (-46.13dB)
[@     1m51s] Timestep:         5580 || Speed:   40.3 MC/s (1.986e-02 s/TS) || Energy: ~6.13e-20 (-46.43dB)
[@     1m55s] Timestep:         5805 || Speed:   41.9 MC/s (1.912e-02 s/TS) || Energy: ~5.75e-20 (-46.71dB)
[@     2m00s] Timestep:         6030 || Speed:   37.9 MC/s (2.112e-02 s/TS) || Energy: ~5.41e-20 (-46.97dB)
[@     2m05s] Timestep:         6255 || Speed:   40.0 MC/s (2.003e-02 s/TS) || Energy: ~5.10e-20 (-47.22dB)
[@     2m09s] Timestep:         6480 || Speed:   41.6 MC/s (1.926e-02 s/TS) || Energy: ~4.82e-20 (-47.47dB)
[@     2m13s] Timestep:         6705 || Speed:   40.2 MC/s (1.994e-02 s/TS) || Energy: ~4.57e-20 (-47.70dB)
[@     2m18s] Timestep:         6930 || Speed:   40.7 MC/s (1.970e-02 s/TS) || Energy: ~4.35e-20 (-47.92dB)
[@     2m22s] Timestep:         7155 || Speed:   40.8 MC/s (1.963e-02 s/TS) || Energy: ~4.14e-20 (-48.13dB)
[@     2m27s] Timestep:         7380 || Speed:   40.6 MC/s (1.974e-02 s/TS) || Energy: ~3.95e-20 (-48.33dB)
[@     2m31s] Timestep:         7605 || Speed:   41.8 MC/s (1.914e-02 s/TS) || Energy: ~3.78e-20 (-48.52dB)
[@     2m35s] Timestep:         7830 || Speed:   42.3 MC/s (1.894e-02 s/TS) || Energy: ~3.63e-20 (-48.71dB)
[@     2m40s] Timestep:         8055 || Speed:   41.6 MC/s (1.925e-02 s/TS) || Energy: ~3.48e-20 (-48.88dB)
[@     2m44s] Timestep:         8280 || Speed:   40.8 MC/s (1.963e-02 s/TS) || Energy: ~3.35e-20 (-49.05dB)
[@     2m48s] Timestep:         8505 || Speed:   41.7 MC/s (1.919e-02 s/TS) || Energy: ~3.23e-20 (-49.21dB)
[@     2m53s] Timestep:         8730 || Speed:   41.2 MC/s (1.944e-02 s/TS) || Energy: ~3.11e-20 (-49.37dB)
[@     2m57s] Timestep:         8955 || Speed:   41.1 MC/s (1.949e-02 s/TS) || Energy: ~3.01e-20 (-49.52dB)
[@     3m01s] Timestep:         9180 || Speed:   42.0 MC/s (1.909e-02 s/TS) || Energy: ~2.91e-20 (-49.67dB)
[@     3m06s] Timestep:         9405 || Speed:   42.1 MC/s (1.904e-02 s/TS) || Energy: ~2.81e-20 (-49.81dB)
[@     3m10s] Timestep:         9630 || Speed:   42.0 MC/s (1.905e-02 s/TS) || Energy: ~2.73e-20 (-49.94dB)
[@     3m14s] Timestep:         9855 || Speed:   41.5 MC/s (1.931e-02 s/TS) || Energy: ~2.64e-20 (-50.08dB)
Time for 9855 iterations with 801025.00 cells : 194.73 sec
Speed: 40.54 MCells/s

Thanks a lot for your time reading my post.

I would gladly contribute this simulation as an example, and also write a tutorial once I have it running.

Greetings, 2nOrderEDO

thliebig commented 6 months ago

--> openEMS-Project Discussion