Skip to content
View in the app

A better way to browse. Learn more.

Ham Radio Base -Powered By Ham CQ DX

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
Solar
SFI 147
SN 89
A 8
K 1 Quiet
X-Ray C3.2
Wind 382.1 km/s
Aurora 3
Updated 00:00 UTC HamQSL · N0NBH
Day 80/40m Fair 30/20m Good 17/15m Good 12/10m Fair
Night 80/40m Good 30/20m Good 17/15m Good 12/10m Poor

Callsign Lookup
_
Vanity Call Signs Available
Enter filters above and click Search.
ⓘ Callsign lookups are in real time via the FCC database. Vanity callsign availability is refreshed daily at 6:00 AM CST. The vanity search may be unavailable for a few minutes during this update.
Live DX spots
Live DX Spots — 70cm via PSKReporter · scroll or pinch to zoom
Band
Mode
Time
Loading map data…
MHz DX Spotter Info
Recent spots
Select a band above to load spots
Ready — select a band to fetch live spots

Antenna HubAntenna Software › OpenEMS Guide

OpenEMS Antenna Simulation: Open-Source FDTD EM Solver

OpenEMS is a free, open-source electromagnetic field solver that uses the Finite-Difference Time-Domain (FDTD) method — a fundamentally different and more powerful approach to antenna modelling than NEC2's Method of Moments. Where NEC2 models only thin-wire structures, OpenEMS can simulate antennas with complex 3D geometries: patch antennas, helices on dielectric substrates, antenna arrays over imperfect ground planes, and coaxial connectors with full 3D geometry. For the technically inclined amateur, OpenEMS opens modelling possibilities that NEC2 cannot approach.

Cost: Free / Open source
Platform: Linux, Windows, macOS
Method: FDTD (3D full-wave)
Interface: MATLAB / Octave / Python
FDTD vs. Method of Moments — Key Differences

To understand when OpenEMS adds value over NEC2, you need to understand the fundamental difference between FDTD and Method of Moments (MoM). NEC2 (MoM) solves Maxwell's equations in the frequency domain by decomposing the antenna into wire segments and computing the current distribution directly. This makes it extremely efficient for thin-wire antennas — a 20-element Yagi runs in seconds. But MoM breaks down for structures that are not thin wires: dielectric materials, thick solid conductors, complex 3D surfaces, and structures where the interior fields matter.

FDTD (Finite-Difference Time-Domain), the method used by OpenEMS, divides the entire simulation volume into a 3D grid of small cells and advances Maxwell's equations through time at each cell. This solves for fields everywhere in space simultaneously and handles arbitrary 3D geometries, dielectric materials, and lossy conductors naturally. The trade-off is computational cost — an FDTD simulation of a simple dipole requires vastly more memory and time than the same dipole in NEC2. For thin-wire HF antennas, NEC2 is the correct tool. For anything involving planar structures, dielectrics, or complex 3D geometry at VHF and above, FDTD is necessary.

When OpenEMS adds value over NEC2

Patch antennas on PCB substrates. Helical antennas with dielectric formers. Antennas near lossy dielectric structures (walls, ground with varying layers). Coaxial connector analysis. Feed network design on PCBs. Antenna arrays with complex ground planes. Any antenna where dielectric materials are part of the structure.

When NEC2 is still better

All thin-wire HF antenna designs: dipoles, Yagis, verticals, phased arrays, loops. Fast iterative design exploration where NEC2's speed allows hundreds of evaluations. Simple VHF wire Yagis where element diameter is small relative to wavelength. Any application where FDTD's computational overhead is not justified by the added physical accuracy.

The learning investment

OpenEMS has a significantly steeper learning curve than NEC2 tools. Models are scripted in MATLAB/Octave or Python — there is no GUI for model entry. Understanding FDTD stability criteria, mesh resolution, absorbing boundary conditions, and post-processing is required before meaningful results can be obtained. Expect 10–20 hours of learning before first useful results.

Installing OpenEMS
1
Choose your platform — Linux is easiest

OpenEMS runs on Linux, Windows, and macOS. Linux (Ubuntu 20.04 or 22.04 LTS) provides the smoothest installation experience through the package manager. Windows requires either a pre-compiled binary package from the OpenEMS website or compilation from source using Visual Studio. macOS requires Homebrew and compilation from source. For most amateur users, a Linux installation is strongly recommended — either native or in WSL2 (Windows Subsystem for Linux 2) on Windows 10/11.

2
Install on Ubuntu/Debian via package manager

Open a terminal and run: sudo apt-get install openems python3-openems. This installs the OpenEMS engine and the Python interface. Also install GNU Octave (free MATLAB-compatible environment) if you prefer the MATLAB interface: sudo apt-get install octave octave-openems. The paraview visualisation tool (for 3D field viewing) is available as: sudo apt-get install paraview.

3
Install AppCSXCAD for 3D geometry viewing

AppCSXCAD is the OpenEMS geometry visualiser — it shows the 3D structure of your antenna model before running the simulation. Install with: sudo apt-get install appcsxcad. Launch with appcsxcad from the command line. This tool is invaluable for verifying that your model geometry is correct before committing to a potentially long FDTD simulation run.

4
Run the example scripts to verify installation

OpenEMS includes a set of example simulation scripts. Navigate to /usr/share/openems/examples/ (Linux) and run a simple example: cd Dipole_Antenna && octave dipole.m (for Octave) or python3 dipole.py (for Python). A successful run produces S11 (reflection coefficient) data and a radiation pattern — verify these match the expected results for a half-wave dipole before proceeding to your own models.

FDTD Fundamentals — What You Must Understand

Running OpenEMS productively requires understanding three fundamental FDTD concepts that have no equivalent in NEC2. Getting these wrong produces silently incorrect results — simulations that run without error but give physically wrong answers.

1. Mesh resolution and the CFL stability criterion

The FDTD method requires the simulation volume to be divided into a 3D rectangular mesh. The mesh cell size must be small enough to resolve the smallest geometrical feature and the shortest wavelength in the simulation. The general rule is a minimum of 10–20 cells per wavelength at the highest frequency of interest — at 1296 MHz (λ = 231 mm), this means cells no larger than 12–23 mm. Near wires and surfaces the mesh must be finer — typically cells of λ/30 to λ/50 at conductor surfaces.

CFL stability criterion (time step limit) Δt ≤ 1 / (c × √(1/Δx² + 1/Δy² + 1/Δz²))   where Δx, Δy, Δz = cell dimensions, c = speed of light

OpenEMS calculates the time step automatically from the mesh dimensions using the CFL criterion — you set the mesh and OpenEMS determines the time step. Finer mesh = smaller time step = more iterations needed for the simulation to reach steady state = longer run time. The simulation runtime scales as approximately N³ where N is the number of cells per dimension, making mesh selection the primary runtime trade-off in FDTD.

2. Absorbing boundary conditions (PML)

The simulation domain is a finite volume, but electromagnetic waves radiate to infinity. OpenEMS uses Perfectly Matched Layer (PML) absorbing boundaries at the edges of the simulation domain to absorb outgoing waves without reflection — simulating free space or open space beyond the domain. The PML must be placed far enough from the antenna structure (at least λ/4 of the lowest frequency in the simulation) to avoid corrupting the near-field results. Setting the domain too small causes reflected waves from the boundary to contaminate the simulation results.

3. Simulation duration and convergence

The FDTD simulation advances time step by time step. The simulation must run long enough for all excited waves to leave the domain through the PML boundaries and for the steady-state response to develop. OpenEMS monitors the energy remaining in the simulation domain and stops when it falls below a specified threshold (typically −40 to −60 dB of the peak excitation energy). If the simulation stops too early (poor convergence), the frequency-domain results computed by Fourier transform of the time-domain data will be inaccurate at frequencies where the response has long time constants (high-Q resonances).

A First OpenEMS Model — Half-Wave Dipole at 1296 MHz

The following Python script models a half-wave dipole at 1296 MHz (23 cm band) in free space. This is the OpenEMS equivalent of the "Hello World" program — a reference case where the expected result (feed point impedance ~73 + j0 Ω, gain 2.15 dBi) is well known, allowing you to verify the simulation setup before moving to more complex geometries.

# OpenEMS half-wave dipole at 1296 MHz — Python script # Requires: openems, CSXCAD, numpy, matplotlib import openems from CSXCAD import ContinuousStructure import numpy as np # ── Simulation parameters ──────────────────────────────────────────── f0 = 1296e6 # Centre frequency (Hz) fc = 300e6 # Frequency bandwidth of Gaussian excitation lam0 = 3e8 / f0 # Wavelength at f0 (m): 0.2315 m dipLen = lam0 * 0.47 # Total dipole length (slightly shorter than λ/2) dipRad = 0.0015 # Wire radius 1.5 mm feedGap = lam0 * 0.01 # Feed gap (1% of λ) # ── Create CSXCAD structure ────────────────────────────────────────── CSX = ContinuousStructure() FDTD = openems.openEMS(NrTS=30000) FDTD.SetGaussExcite(f0, fc) FDTD.SetBoundaryCond(['PML_8']*6) # PML absorbing boundaries all sides # ── Create mesh ────────────────────────────────────────────────────── # Fine mesh near the wire, coarser mesh in free space mesh_res = lam0 / 20 # λ/20 general mesh resolution fine_res = dipRad / 3 # Fine mesh near wire # (mesh definition code abbreviated for clarity) # ── Define the dipole as two wire cylinders ────────────────────────── CSX.AddMetal('dipole') # Perfect electric conductor # Upper arm: from feedGap/2 to dipLen/2 along Z-axis CSX.GetMaterial('dipole').AddCylinder( start=[0,0,feedGap/2], stop=[0,0,dipLen/2], radius=dipRad) # Lower arm: from -feedGap/2 to -dipLen/2 CSX.GetMaterial('dipole').AddCylinder( start=[0,0,-feedGap/2], stop=[0,0,-dipLen/2], radius=dipRad) # ── Add lumped port as feed point ──────────────────────────────────── port = FDTD.AddLumpedPort( port_nr=1, R=50, start=[0,0,-feedGap/2], stop=[0,0,feedGap/2], p_dir='z', excite=True) # ── Run simulation ─────────────────────────────────────────────────── FDTD.Run(sim_path='/tmp/dipole_sim', cleanup=True) # ── Post-process: compute S11 and impedance ────────────────────────── freq = np.linspace(f0-fc, f0+fc, 401) port.CalcPort(sim_path, freq) s11 = port.uf_ref / port.uf_inc # Reflection coefficient Zin = port.uf_tot / port.if_tot # Input impedance # Plot S11 and Zin (real, imag) vs frequency
This is a conceptual script. Real OpenEMS scripts require full mesh definition, domain size calculation, boundary placement verification, and post-processing. The script above shows the structure and key concepts; consult the OpenEMS documentation and examples for a complete, runnable dipole simulation. The openems.github.io/openEMS-Project documentation includes a fully working dipole example that serves as the best starting point.
Interactive Calculator: FDTD Mesh and Runtime Estimator

OpenEMS FDTD Simulation Parameters Estimator

Estimates mesh parameters, time steps, and approximate simulation time for an OpenEMS FDTD run.

OpenEMS vs. NEC2 — When to Use Each
Antenna/ProblemBest toolReason
HF wire dipole, vertical, loopNEC2 (MMANA, 4NEC2)Thin wire — MoM is ideal, fast, accurate
HF Yagi, phased arrayNEC2 (YO, MMANA)Thin wire elements — NEC2 handles perfectly
Patch antenna on PCBOpenEMS (FDTD)Dielectric substrate essential — NEC2 cannot model
Helix on fibre formerOpenEMS (FDTD)Dielectric core affects impedance and pattern
VHF/UHF Yagi (thin elements)NEC2Still thin wire — NEC2 works; OpenEMS adds nothing
VHF/UHF Yagi (thick elements near λ)OpenEMS or NEC4Thick element corrections matter at higher frequency
Coaxial cable feed analysisOpenEMS (FDTD)Full 3D coax geometry; dielectric
Antenna in/near building structureOpenEMS (FDTD)Dielectric walls, complex near field
Dish/reflector with feedOpenEMS or ray tracingCurved surface, dielectric support structures
Ground wave propagationNEC2/NEC4 with S-N groundSurface wave analysis optimised in NEC codes
Practical OpenEMS Workflow for a Patch Antenna at 1296 MHz

A patch antenna (microstrip patch) is the canonical OpenEMS application — it requires modelling the dielectric substrate, the copper patch, the ground plane, and the coaxial feed connector, none of which NEC2 can represent accurately. This example outlines the workflow without the full script, which would be many pages long.

1
Define substrate and patch dimensions

Calculate the approximate patch length and width from transmission line theory for the chosen substrate (FR4: εr = 4.4, thickness 1.6 mm is most common). At 1296 MHz on FR4: patch length ≈ c/(2f₀√εr_eff) ≈ 54 mm, width ≈ 60 mm. These are starting dimensions — OpenEMS will reveal the true resonant frequency and you trim the patch from there.

2
Create the geometry in CSXCAD

Define the substrate as a dielectric box (AddDielectric with εr = 4.4, loss tangent = 0.02 for FR4). Add the copper ground plane as a metal box on the bottom face of the substrate. Add the patch as a metal box on the top face, offset to leave feed clearance. Add the coaxial feed as a lumped port or as a physical coaxial geometry (SMA connector model). Visualise with AppCSXCAD before running.

3
Set mesh with fine resolution at the substrate

The substrate dielectric requires fine mesh — cells of 1–2 mm inside the substrate to capture the field concentration. Use OpenEMS's SmoothMeshLines function to create a mesh that is fine near the patch and substrate and gradually coarsens toward the PML boundaries. The total domain might be 300 × 300 × 150 mm with the patch at the centre.

4
Run simulation and extract S11, radiation pattern

Run OpenEMS with the Gaussian excitation spanning 900–1700 MHz — this covers the entire 23 cm band and provides wideband results from a single simulation. Post-process the port time-domain data to compute S11 across frequency. Extract the near-field data and use the near-to-far-field transformation to compute the radiation pattern and gain at 1296 MHz.

5
Optimise patch dimensions for 1296 MHz resonance

If S11 minimum is not at 1296 MHz, adjust the patch length: shorter patch raises the resonant frequency, longer patch lowers it. In OpenEMS, this requires re-running the simulation with the adjusted geometry — each run may take minutes to hours depending on mesh resolution. Consider using a coarser mesh (λ/10) for optimisation iterations and a finer mesh (λ/20) for the final verified design.

GPU Acceleration — Making OpenEMS Practical

The primary practical barrier to using OpenEMS for antenna design is simulation time. A high-resolution 3D patch antenna simulation at 1296 MHz on a single CPU core can take 30–120 minutes. OpenEMS supports GPU acceleration via OpenCL, which can reduce simulation time by 10–50× on a suitable GPU — bringing 120-minute simulations down to 3–12 minutes.

To use GPU acceleration, OpenEMS must be compiled with OpenCL support (the Ubuntu package version typically includes this). Run with the --engine=fastest flag: openEMS --engine=fastest my_simulation.xml. OpenEMS automatically selects the fastest available engine (CPU, single-GPU, or multi-GPU). A mid-range consumer GPU (NVIDIA RTX 3060 or AMD RX 6700) provides 20–40× speedup over a single CPU core for typical antenna simulation sizes.

For first-time users: Start with the example scripts in the OpenEMS documentation before building your own models. The dipole example, Yagi example, and patch antenna example each demonstrate a different aspect of the workflow. Run each example, verify the results match published data, then modify them incrementally to build confidence before tackling your own antenna geometry from scratch.
OpenEMS Resources and Community

OpenEMS has an active developer and user community. The primary resources are:

  • openems.de — main project website with downloads, documentation, and news
  • openems.github.io/openEMS-Project — GitHub repository with examples, issue tracker, and release notes
  • openems.de/forum — community forum for questions and design discussion
  • YouTube: "openems antenna" — several tutorial series by university researchers and engineers showing complete workflows from geometry creation to radiation pattern output
  • QUCS-S + OpenEMS integration — QUCS-S is a circuit simulator that integrates with OpenEMS, allowing co-simulation of antenna structures with matching networks in the same environment
Frequently Asked Questions

Is OpenEMS suitable for HF antenna design?

For typical HF wire antenna design (dipoles, Yagis, loops, verticals), OpenEMS provides no advantage over NEC2 and requires vastly more computational resources for the same result. Use NEC2 tools (MMANA-GAL, 4NEC2, EZNEC) for HF wire antennas. OpenEMS becomes valuable for HF antennas involving dielectric materials, complex ground structures, or indoor near-field problems where the dielectric environment matters.

How much RAM does OpenEMS need?

RAM requirements depend on the number of mesh cells. A 200×200×100 cell simulation requires approximately 6 × 8 bytes × 4 million = 200 MB RAM — very manageable. A 500×500×250 cell simulation at higher resolution requires approximately 6 × 8 × 62.5 million ≈ 3 GB RAM. High-resolution 3D simulations of complex antennas can require 8–32 GB. The FDTD estimator calculator above helps plan RAM requirements before committing to a mesh design.

Can I model an antenna with a real coaxial connector in OpenEMS?

Yes — this is one of OpenEMS's genuine advantages over NEC2. You can model the complete 3D geometry of an SMA connector, including the PTFE dielectric and outer conductor, and simulate how it couples to an antenna structure. This is especially valuable for patch antennas, helices, and microwave antennas where the connector geometry influences the match and radiation pattern at higher frequencies.

What is the CSXCAD geometry format?

CSXCAD (Conformal Structure eXtensible Cad) is the geometry description format used by OpenEMS. Structures are defined in Python or MATLAB/Octave using CSXCAD API calls (AddBox, AddCylinder, AddSphere, etc.) or imported from CAD files (step/iges via FreeCAD). The geometry is saved as an XML file that OpenEMS reads at simulation time. AppCSXCAD provides a 3D viewer for verifying geometry before running.

Is there a GUI for OpenEMS?

OpenEMS itself uses scripted input — there is no point-and-click GUI for model creation comparable to MMANA-GAL or EZNEC. However, several GUI front-ends exist: FreeCAD has an OpenEMS workbench that allows importing mechanical CAD models and setting up FDTD simulations graphically. QUCS-S provides a circuit-like interface for antenna and matching network co-simulation. For pure FDTD modelling, the scripting approach is still most commonly used.

What is the difference between OpenEMS and CST Microwave Studio?

Both use FDTD (and other methods) for electromagnetic simulation. CST is a commercial product costing tens of thousands of dollars per licence, with a polished GUI, extensive material libraries, optimisation suites, and commercial support. OpenEMS is free and open-source with a scripting interface and community support. For professionally demanding work, CST's additional features are worth the cost. For learning, research, and technically capable amateur radio users, OpenEMS provides comparable physical accuracy at zero cost.

Related Guides

Affiliate Disclosure: As an Amazon Associate, Ham Radio Base earns from qualifying purchases. Some links throughout this website may be affiliate links. If you purchase a product through one of these links, we may earn a commission at no additional cost to you. Your support helps us continue creating free articles, tutorials, reviews, and resources for the amateur radio community. N0TLB © Ham Radio Base - Powered by the Ham CQ DX Community. All rights reserved.

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.