OpenBEM is an open-source framework for electromagnetic simulation with the boundary element method.
OpenBEM is not a solver. Rather, it is a framework of components that can be fit together in highly customizable ways, to allow users to implement their own application-specific solvers. It is intended as a research tool to facilitate the testing and prototyping of new ideas, formulations, and algorithms, without the researcher having to re-implement aspects of the boundary element method that are not pertinent to their specific research.
OpenBEM is written in C++, and its full documentation is available at https://shash-sharma.github.io/OpenBEM/.
As a starting point, it is highly recommended that users go through the provided examples in the documentation. To gain familiarity with the code and its organization, the Topics page in the documentation is the recommended way to navigate through the available functionality.
-
All RWG-based operators associated with the TEFIE, NEFIE, TMFIE, and NMFIE [Ylä-Oijala, Taskinen, Järvenpää, 2005].
-
Numerical quadrature over source and observation triangles for RWG-based meshes and single and double layer kernels [Ergül, Gürel, 2014].
-
Singularity extraction for single and double layer kernels [Ergül, Gürel, 2014].
-
Line integration for the case of highly oscillatory kernels, such as those associated with lossy conductors [Qian, Chew, Suaya, 2007] and [Xia et. al, 2017].
-
Plane wave, infinitesimal gap, and lumped circuit port excitations [Gibson 2021].
-
Near- and far-field projection for post-processing.
-
Input and output of Gmsh meshes and fields for post processing.
-
Sparse and dense matrix wrappers for the Eigen library for operator assembly.
-
The ability to partition meshes and specify subsets of triangle pairs for which to compute integrals, to enable compatibility with mesh distribution and acceleration algorithms.
-
A built-in standard acceleration algorithm (Q3-Q4 2026).
-
Support for dyadic kernels (Q4 2026).
-
Python bindings (Q1-Q2 2027).
OpenBEM is designed to be modular and extensible, so that researchers can focus on aspects of the boundary element method pertinent to their research, without needing to implement other aspects that are not of interest to them, but still must be implemented. Instead, researchers can prototype their ideas and plug them into the rest of OpenBEM's functionality, to quickly assemble full electromagnetic solvers that incorporate their ideas.
For example,
-
researchers focusing on high-level integral equation formulations need not worry about having to implement integration techniques over triangles for singular kernels;
-
researchers developing new integration techniques for singular kernels need not implement the surrounding code infrastructure needed to test their ideas in the context of a full solver;
-
researchers developing new acceleration algorithms that approximate far-zone electromagnetic interactions can wrap OpenBEM's functionality to compute the near-zone interactions.
This modularity is achieved with the following design pattern based on the well-known concept of runtime polymorphism.
Each module contains a base.hpp file containing an abstract base
class for that module, for example,
// module/base.hpp
class ModuleBase
{
// ...
};The base classes contain a blueprint for the basic functionality that any of its subclasses is expected to have. For example,
// module/base.hpp
class ModuleBase
{
virtual float compute_something(int input_1, float input_2) = 0;
// ...
};This means that any class that inherits from ModuleBase must have a
function called compute_something with exactly the same return and
input arguments. For example, we can define a custom class that
implements our own idea of compute_something,
// module/my_module.hpp
class MyModule: public ModuleBase
{
float compute_something(int input_1, float input_2)
{
// implementation of my amazing research idea
};
// ...
};Since MyModule follows all the rules of ModuleBase, we can now use
MyModule throughout the rest of OpenBEM! For example, suppose
there's another OpenBEM function func which accepts a ModuleBase
reference as an input,
// func.hpp
float func(ModuleBase& module)
{
float output = module.compute_something(4, 5.0);
return output;
}then we can pass in our custom MyModule to this OpenBEM function,
for example,
// test_mymodule.cpp
MyModule my_module;
float final_output = func(my_module);
// ...The idea is that func doesn't care what you pass in as long as it
inherits from and follows the rules of ModuleBase (i.e., provides an
implementation of all methods that are marked virtual and set to 0).
OpenBEM requires at least C++17.
To compile your project with OpenBEM, the following should be noted:
-
GCC version 10 or above, Clang version 8 or above, or an equivalent compiler is recommended.
-
OpenBEM uses a relatively recent version of the Eigen library. This is a header-only linear algebra toolkit which is included as part of the OpenBEM distribution, so you do not need to download or include it separately. However, if using an older compiler, you may need to disable certain compile options such as
march=native,mavx, etc., for compatibility with this version of Eigen. I've experienced this issue with GCC 8.5.
There are two ways to incorporate OpenBEM in your project.
The simplest and quickest way to use OpenBEM is to import it into your
project it in header-only mode, which involves no installation,
building or linking; you simply #include the appropriate header into
your C++ files, and you're all set.
For example, if you want to include OpenBEM in a C++ file called
main.cpp, your compilation command may look like
g++ -I/path/to/OpenBEM/source -std=c++17 main.cpp -o mainwhere the -I specifier adds the OpenBEM source directory to the
compiler's include search path.
If you're using CMake to build your project (recommended), you can include OpenBEM in header-only mode by doing the following:
add_executable(main main.cpp)
target_include_directories(main PRIVATE /path/to/OpenBEM/source)
target_compile_features(main PRIVATE cxx_std_17)In either case, OpenBEM's headers can then be included directly into your project, for example,
#include "openbem.hpp"and that's it.
The compile time of your project can be somewhat improved by using OpenBEM in linked mode, which involves building and dynamically linking OpenBEM to your project.
Doing this requires you to have at least version 3.16.0 of CMake installed on your machine. Then, just run
cmake -B /path/to/build/directory -S /path/to/OpenBEM
make -C /path/to/build/directoryThis will build OpenBEM in any /path/to/build/directory of your
choice.
The following options are available to use in the cmake command to
customize your build, by augmenting the cmake command as
cmake -DOPTION=VAL -B /path/to/build/directory -S /path/to/OpenBEMwhere OPTION is one of the following options, and VAL is one of
the possible corresponding values for that option:
PRECISION, which can besingle,double(default), orextended.DEBUG_LEVEL, which can berelease(default, optimized build) ordebug.BUILD_EXAMPLES, which can beyesorno(default).BUILD_TESTS, which can beyesorno(default).
Once built, you still need to follow the steps in Option 1 to add the
include path to your project's compilation. In addition, you'll need
to link your project to the OpenBEM dynamic library
/path/to/build/directory/libopenbem.[so/dylib/dll].
Then you can include OpenBEM's headers in your project as usual, for example,
#include "openbem.hpp"If OpenBEM benefits your research, please cite this GitHub repository via the following in your publications and presentations.