Skip to content

(WIP) doc-src: add preliminary openEMS documentation#417

Draft
biergaizi wants to merge 31 commits into
thliebig:masterfrom
fasterEMS:doc-concepts
Draft

(WIP) doc-src: add preliminary openEMS documentation#417
biergaizi wants to merge 31 commits into
thliebig:masterfrom
fasterEMS:doc-concepts

Conversation

@biergaizi

@biergaizi biergaizi commented Dec 1, 2025

Copy link
Copy Markdown
Contributor

WIP, do not merge, but comments welcomed

The following draft documentation adds a new section to the openEMS documentation website called "concepts". It explains several important concepts of CSXCAD, openEMS and FDTD. This represents a small part of my month-long work made in 2025 on documenting openEMS.

Currently this documentation is still incomplete, some parts contain known mistakes. To my best knowledge, I am aware of two mistakes and several limitations:

  1. "primitives.rst" contains many broken Python syntax in the example code - All fixed!

  2. "ports.rst" does not correctly explain the use of transmission line ports, the given information is only correct for lumped port.

  3. Post-processing is unexplained. This part needs to be "ported" from my parallel-plate waveguide tutorial.

  4. No tutorial is given, my parallel-plate waveguide tutorial needs some rework.

I plan to fix (1) and (2) in the upcoming days, and get these documents merged. The rest can be added in the future. "Some documents" is always better than "no document".

Although it's still a work in progress, I believe this documentation draft already contains information not documented anywhere about the openEMS project. In particular, "signals.rst" explains the usage of all excitation waveforms, and "dispersive.rst" explains the mathematical formulation of Debye, Drude, Lorentz models, including comparison to other textbook formulations. Both are original work.

Comments (other than repeating the known problems) are welcomed since I may have still missed something.

The following draft documentation adds a new section to the openEMS
documentation website called "concepts". It explains several important
concepts of CSXCAD, openEMS and FDTD. This represents a small part
of my month-long work made in 2025 on documenting openEMS.

Currently this documentation is still incomplete, some parts
contain known mistakes. To my best knowledge, I am aware of
two mistakes and several limitations:

1. "primitives.rst" contains many broken Python syntax in the
example code.

2. "ports.rst" does not correctly explain the use of transmission
line ports, the given information is only correct for lumped port.

3. Post-processing is unexplained. This part needs to be "ported"
from my parallel-plate waveguide tutorial.

4. No tutorial is given, my parallel-plate waveguide tutorial needs
some rework.

I plan to fix (1) and (2) in the upcoming days, and get these
documents merged. The rest can be added in the future. "Some
documents" is always better than "no document".

Although it's still a work in progress, I believe this documentation
draft already contains information not documented anywhere about the
openEMS project. In particular, "signals.rst" explains the usage of
all excitation waveforms, and "dispersive.rst" explains the mathematical
formulation of Debye, Drude, Lorentz models, including comparison to
other textbook formulations. Both are original work.

Comments (other than repeating the known problems) are welcomed since
I may have still missed something.

Signed-off-by: Yifeng Li <tomli@tomli.me>
@biergaizi biergaizi marked this pull request as draft December 1, 2025 00:03
@biergaizi biergaizi force-pushed the doc-concepts branch 2 times, most recently from f7a62c7 to 4776a4c Compare December 1, 2025 18:20

@thliebig thliebig left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments for the first few files. This is going to take a while...

Comment thread doc-src/concepts/bc.rst

PML is a more effective absorber and is easy to use, but it has the
highest computational overhead (especially in openEMS, due to suboptimal
implementation). Avoid it if efficiency is critical (e.g. only use

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well "optimal" is a matter of perspective. The goal for openEMS was to implement an FDTD algorithm that is easy to maintain and easy to extend with new experimental features. It was never designed to be as fast as possible as that almost by definition negates the first two goals.
But in any case, the PML is the relative "slowest" BC even in the most advanced implementations, thus this comment is not helpful in any case?

@biergaizi biergaizi Dec 1, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well "optimal" is a matter of perspective.

Yes, it's a matter of perspective. But the old project wiki also agreed that the PML implementation in its current form is suboptimal, I only repeated the old statement in the new documentation. I thought you wrote that page?

This ABC is not optimally implemented regarding the simulation speed. Use the Mur-ABC for faster simulations.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if I wrote that or not. But in any case, it is as sub-optimal as any other extension. Since it tries to make use of the main engine operator maybe even less than others.
In any case, it is not interesting for the reader of the docu? Because if you need to use the PML you simply need to 😏

Comment thread doc-src/concepts/bc.rst Outdated
Comment thread doc-src/concepts/bc.rst Outdated
Comment thread doc-src/concepts/bc.rst Outdated
Comment thread doc-src/concepts/bc.rst Outdated

On the other hand, although openEMS is also available as a shared library,
but its C++ APIs are presently intended only for use by the Python binding,
not public use. Breaking changes may occur at any time. Invoke openEMS as

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No actually the API is intended to be usable by other tools and I do intend to be very careful about breaking changes...


* :func:`export_empire`:

* For comparing simulation results with proprietary, commercial

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I completely forgot about this exporter, I think I have to check if it still works. and maybe implement a python version too 😏

Comment thread doc-src/concepts/csxcad.rst Outdated
Python
"""""""

Unfortunately, none of the functions above have been implemented in Python.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

STL is available, everything else should be put on the list of missing python features

@thliebig thliebig left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still not done, but only three *.rst to do...

@biergaizi please not that some comments may be hidden under the "Load diff"

Comment thread doc-src/concepts/dump.rst

Several kinds of dump boxes exist.

#. Time-domain dumps of electric field :math:`\mathbf{E}`, auxiliary magnetic

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why "auxiliary" magnetic field? It is as primary as the electric field, after all that is what "EM" stands for 😏

@biergaizi biergaizi Dec 1, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why "auxiliary" magnetic field? It is as primary as the electric field

It's "auxiliary" in the sense that it's not as "fundamental" as the B field. It would be pretty confusing if H and B are both called the "magnetic field", but "H" doesn't really have its own name in English at all. Griffiths for example recommends people to just call it the "H field" without a name. The only name ever used in the literature is "auxiliary magnetic field", which was what I used.

It's the old engineering vs. physics debate on whether H or B should be the "real" magnetic field, and physics textbooks (such as Griffiths's E&M and Max Born's Optics) generally say "B" is real while "H" is a calculation tool to analyze macroscopic materials. But, I guess for our purpose of FDTD and openEMS, calling "H" as the magnetic field has a point here because it's what actually stored in computer's memory.

I think I'll just change them to "magnetic field B" and "magnetic field H", using words and letters at the same time sidesteps the whole argument.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting point, I'm not sure if this "debate" actually exists in Germany.
For me the magnetic field is H, and the magnetic flux density is B.
I think this wording should be the clearest?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also compare the first and second paragraph in this section of the MEEP documentation:

Meep simulates Maxwell's equations, which describe the interactions of electric (E) and magnetic (H) fields

where D is the displacement field, ε is the dielectric constant, J is the current density (of electric charge), and JB is the magnetic-charge current density. Magnetic currents are a convenient computational fiction in some situations. B is the magnetic flux density (often called the magnetic field), μ is the magnetic permeability, and H is the magnetic field.

Comment thread doc-src/concepts/dump.rst
#. Near-Field to Far-Field Transformation (NF2FF) for antenna analysis
(special setup required, via :meth:`openEMS.openEMS.CreateNF2FFBox` and a
separate post-processing tool).

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I think a reference to the different file types are missing? But at the same time the methods have an good documentation themself?
  • Additionally for frequency dumps the recording frequencies must be specified.
  • There could be made a point here that time-domain dumps are much more storage and file access effort and thus can not only produce very large files, but also slow down the simulation a lot. If you now the desired frequencies at the start, you should always use the FD dump instead (unless many frequencies are of interest)

Comment thread doc-src/concepts/excitations.rst Outdated
Comment thread doc-src/concepts/mesh.rst
Comment on lines +194 to +195
cells with different sizes around the edge, creating a non-uniform
rectilinear mesh with variable spacing. Around the metal edge, the metal

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thats not correct, the mesh can be uniform as long as the "edge cells" obay the 1/3-2/3 rule...
This just requires a very special cell width to make this happen...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant to write

openEMS supports a rectilinear mesh with variable spacing, not use.

Comment thread doc-src/concepts/mesh.rst Outdated

2. Only the electric field is known at an exact timestep, the magnetic field
is known with a half-timestep offset (``t + 0.5``). This error is always
neglected.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error is always neglected.

Why is this an error? And it is never neglected. Wherever e.g. voltages and currents are analyzed the correct times are used, Otherwise phase errors would always be a major issue.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean that if you create an E-field dump box and an H-field dump box, both E and H fields are also interpolated to the "correct" time?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no correct time? Both fields are recorded with their respective time and always has to be taken care of properly. Putting E- and H-fields in a direct relationship in time-domain is difficult and should be avoided I guess.

@biergaizi biergaizi Dec 2, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is consistent with my own understanding, the field dump of E and H are off by a half-timestep, the openEMS engine does not auto-interpolate two H fields at H(t - 0.5), H(t + 0.5) to approximate H(t) - it's impossible even if someone wants to, because the engine only saves one copy of the field at the latest timestep, there's no double buffering.

This is why I said: "this error is always neglected", I meant it's neglected in openEMS engine's probes and field dumps.

I propose the following wording to clarify the issues.

Only the electric field is known at an exact timestep, the magnetic field is known with a half-timestep offset (t + 0.5). When probing both voltages and currents, or dumping both electric and magnetic fields, users must explicitly take this simulation artifact into account. Since temporal interpolation is unsupported, analyzing both physical quantities at the same timestep is difficult, and best be avoided without a strong FDTD background.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add that this only affects the fields in time-domain? None of this issue arise if you are looking (at the more common?) frequency domain.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point.

Comment thread doc-src/concepts/ports.rst Outdated
into the simulation, helping establish initial conditions for the system.
Simultaneously, a lumped resistor and a probe are also created at the
same location as the port, allowing it to provide a matched load for the
signal, or to measure the voltage or current at this region.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

voltage and current. I think I know no port that only wants one of them

These waveguides only have one conductor, unlike the usual two-conductor
transmission lines. An ordinary port can't excite them correctly,
as the waveguide is essentially a DC short circuit. Special waveguide
ports must be used to excite the unique TE-mode waves. These include

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TE- or TM-Modes

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I'm not sure TM is really implemented at all?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the earliest draft I wrote "TE or TM", and I later deleted "TM" after I noticed that only the E-field excitation was implemented in AddWaveGuidePort.m.

CSX = AddExcitation( CSX, exc_name, 0, e_vec, varargin{:});
CSX = SetExcitationWeight(CSX, exc_name, E_WG_func );
CSX = AddBox( CSX, exc_name, prio, e_start, e_stop);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that's what I though...

Comment on lines +104 to +108
:func:`CalcLorentzMaterial`, no workaround is available. These
Octave functions are helper functions that calculate the model's
output curves for the purpose of fitting parameters and preparing
a simulation. No C++ APIs exist because they're not actually used
in the simulation.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be really good test case for modern LLM's ? Feed them the Octave code and ask to transfer to python? I think this would be worth a shot?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I believe this problem is easy for LLMs to solve, it's just a plain language translation and it's hard to get it wrong. Copyright issue is also non-existent, it's derived from our own code (and code itself is from physics formulas, not copyrightable anyway). Perhaps I will try translating a function myself, and later comparing it with different LLMs. the LLMs are possibly more readable than my code. LLMs memorized all Python idioms, helper functions and syntactic sugars. I wrote Python for 10 years but I can't memorize all.

However, using LLMs to generate code opens up the question of determining the project's LLM usage policy, which is tricky and controversial. For example, at the OCaml project, recently there was a prominent incident, a first-time contributor opened a Pull Request with 13k lines of LLM-generated code, delegating the review to the project maintainer. Although it was the most extreme incident, it was not the only one. So if we say "auto-generating contributions with LLMs will be accepted", there's a non-zero risk that you'll soon receive a flood of mixed-quality code to review...

For full disclosure, this documentation patch itself is also 10000 line-long, and I did use LLM in this tutorial, but only to flag writing problems, not for authoring it, I wrote everything on a Model M in a plain Vim window. Otherwise it won't take months - and none of my previous patches or forum posts were auto-generated (and I doubt LLMs can debug arcane build issues such as "Homebrew shipped a broken Python standard library on macOS", but perhaps I underestimate them).

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well this is a valid point about the policy. I think my current personal policy is, if an LLM is used e.g. to translate some function, but the author of that code than does a good review and testing of that code and is open about the whole process in the PR, this should be okay?? But I guess we should have a look at what LLM usage policy we want to adopt at some point (soon)...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but the author of that code than does a good review and testing of that code and is open about the whole process in the PR, this should be okay?

I think it's a reasonable policy.

@biergaizi

Copy link
Copy Markdown
Contributor Author

Missing Python features are now documented in the Development section in doc-src/development/python_todo.rst, as it's a TODO list related to project development.

Also, some documents can be difficult to check in the source form, you can use the preview provided by ReadTheDocs, such as the formula-heavy note on dispersive materials: https://openems--417.org.readthedocs.build/en/417/concepts/dispersive.html

@biergaizi

Copy link
Copy Markdown
Contributor Author

Update: Changed all silly mentions of "first-order model" in dispersive.rst to "single-term model". 🤦 The Lorentz model is a mass-spring-damper or RLC-like oscillator, you still have a second-order system even with a single pole.

@biergaizi

biergaizi commented Dec 2, 2025

Copy link
Copy Markdown
Contributor Author

Update: Added 5 new sections on post-processing simulation S-parameter results:

  • Manually
  • via scikit-rf for frequency-domain plotting and TDR
  • via SignalIntegrity for eye diagram and signal path interconnect analysis.
  • via ParaView for visualization
  • via Qucs-S simulation.

Again, these sections are copied and pasted from my Parallel Plate Waveguide tutorial, some paragraphs need serious rewrites, otherwise it doesn't make sense due to lack of context. For example, currently the tutorial doesn't say anything about where the S-parameters come from. Still, early comments unrelated to these issues are appreciated.

@thliebig thliebig left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments on your comments

Comment thread doc-src/concepts/bc.rst

PML is a more effective absorber and is easy to use, but it has the
highest computational overhead (especially in openEMS, due to suboptimal
implementation). Avoid it if efficiency is critical (e.g. only use

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if I wrote that or not. But in any case, it is as sub-optimal as any other extension. Since it tries to make use of the main engine operator maybe even less than others.
In any case, it is not interesting for the reader of the docu? Because if you need to use the PML you simply need to 😏

Comment thread doc-src/concepts/dump.rst

Several kinds of dump boxes exist.

#. Time-domain dumps of electric field :math:`\mathbf{E}`, auxiliary magnetic

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting point, I'm not sure if this "debate" actually exists in Germany.
For me the magnetic field is H, and the magnetic flux density is B.
I think this wording should be the clearest?

Comment thread doc-src/concepts/mesh.rst Outdated

2. Only the electric field is known at an exact timestep, the magnetic field
is known with a half-timestep offset (``t + 0.5``). This error is always
neglected.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no correct time? Both fields are recorded with their respective time and always has to be taken care of properly. Putting E- and H-fields in a direct relationship in time-domain is difficult and should be avoided I guess.

These waveguides only have one conductor, unlike the usual two-conductor
transmission lines. An ordinary port can't excite them correctly,
as the waveguide is essentially a DC short circuit. Special waveguide
ports must be used to excite the unique TE-mode waves. These include

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that's what I though...

Comment on lines +104 to +108
:func:`CalcLorentzMaterial`, no workaround is available. These
Octave functions are helper functions that calculate the model's
output curves for the purpose of fitting parameters and preparing
a simulation. No C++ APIs exist because they're not actually used
in the simulation.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well this is a valid point about the policy. I think my current personal policy is, if an LLM is used e.g. to translate some function, but the author of that code than does a good review and testing of that code and is open about the whole process in the PR, this should be okay?? But I guess we should have a look at what LLM usage policy we want to adopt at some point (soon)...

@VolkerMuehlhaus

Copy link
Copy Markdown

I don't know know how to create a link here, but the image for extruded polygons is wrong. This shows the image for rotated polygons.

https://openems--417.org.readthedocs.build/en/417/concepts/primitives.html

Signed-off-by: Yifeng Li <tomli@tomli.me>
@biergaizi

Copy link
Copy Markdown
Contributor Author

@VolkerMuehlhaus Fixed.

Signed-off-by: Yifeng Li <tomli@tomli.me>
Signed-off-by: Yifeng Li <tomli@tomli.me>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants