EM Solver API

View as Markdown

EM Solver API

The EM engine is developed directly by NVIDIA and embedded modularly in the Aerial Omniverse Digital Twin through a specific interface. This makes it possible to integrate different EM engines when needed. This section gives an overview of the key mechanics of that interface.

NVIDIA’s EM engine API provides functions to

  • manage the device memory,
  • perform EM calculations,
  • and copy results to host memory.

All classes, member functions, and variables are defined in the aerial_emsolver_api.h header and use the C++/CUDA primitive data types.

Data types

  • d_complex

    1typedef cuda::std::complex<float> d_complex

    Complex-valued data type used in both host code and device code.

  • d_complex4

    1typedef struct d_complex4 {
    2 d_complex m[4]{};
    3} d_complex4

    An array of four d_complex elements.

  • CIRResult

    1struct CIRResult {
    2 d_complex *cir_values{};
    3 float *cir_delays{};
    4 float2 *angles_of_departure{};
    5 float2 *angles_of_arrival{};
    6
    7 int num_rx{};
    8 int num_samples{};
    9 int num_tx_horz{};
    10 int num_tx_vert{};
    11 int num_tx_pol{};
    12 int num_rx_horz{};
    13 int num_rx_vert{};
    14 int num_rx_pol{};
    15 int num_taps{};
    16
    17 __host__ __device__ CIRResult(d_complex *cir_values, float *cir_delays,
    18 float2 *angles_of_departure,
    19 float2 *angles_of_arrival, int num_rx,
    20 int num_samples, int num_tx_horz,
    21 int num_tx_vert, int num_tx_pol,
    22 int num_rx_horz, int num_rx_vert,
    23 int num_rx_pol, int num_taps);
    24
    25 __host__ __device__ int cir_value_index(int rx, int sample, int rx_h,
    26 int rx_v, int rx_p, int tx_h,
    27 int tx_v, int tx_p, int tap) const;
    28 __host__ __device__ int cir_delay_index(int rx, int sample, int rx_h,
    29 int rx_v, int tx_h, int tx_v,
    30 int tap) const;
    31 __host__ __device__ int angle_of_departure_index(int rx, int sample,
    32 int rx_h, int rx_v,
    33 int tx_h, int tx_v,
    34 int tap) const;
    35 __host__ __device__ int angle_of_arrival_index(int rx, int sample,
    36 int rx_h, int rx_v,
    37 int tx_h, int tx_v,
    38 int tap) const;
    39
    40 size_t cir_value_size() const;
    41 size_t cir_delay_size() const;
    42 size_t angle_of_departure_size() const;
    43 size_t angle_of_arrival_size() const;
    44
    45 __host__ __device__ d_complex get_cir_value(int rx, int sample, int rx_h,
    46 int rx_v, int rx_p, int tx_h,
    47 int tx_v, int tx_p,
    48 int tap) const;
    49 __host__ __device__ void set_cir_value(int rx, int sample, int rx_h,
    50 int rx_v, int rx_p, int tx_h,
    51 int tx_v, int tx_p, int tap,
    52 d_complex value);
    53
    54 __host__ __device__ float get_cir_delay(int rx, int sample, int rx_h,
    55 int rx_v, int tx_h, int tx_v,
    56 int tap) const;
    57 __host__ __device__ void set_cir_delay(int rx, int sample, int rx_h,
    58 int rx_v, int tx_h, int tx_v,
    59 int tap, float value);
    60
    61 __host__ __device__ float2 get_angle_of_departure(int rx, int sample,
    62 int rx_h, int rx_v,
    63 int tx_h, int tx_v,
    64 int tap) const;
    65 __host__ __device__ void set_angle_of_departure(int rx, int sample,
    66 int rx_h, int rx_v,
    67 int tx_h, int tx_v,
    68 int tap, float2 value);
    69
    70 __host__ __device__ float2 get_angle_of_arrival(int rx, int sample,
    71 int rx_h, int rx_v,
    72 int tx_h, int tx_v,
    73 int tap) const;
    74 __host__ __device__ void set_angle_of_arrival(int rx, int sample,
    75 int rx_h, int rx_v,
    76 int tx_h, int tx_v,
    77 int tap, float2 value);
    78}

    Struct contains:

    • cir_values: the device buffer storing the CIR values; the size of the cir_values per TX is num_rx * num_samples * num_rx_horz * num_rx_vert * num_rx_pol * num_tx_horz * num_tx_vert * num_tx_pol * num_taps
    • cir_delays: the device buffer storing the CIR delay; the size of the cir_delays per TX is num_rx * num_samples * num_rx_horz * num_rx_vert * num_tx_horz * num_tx_vert * num_taps
    • angles_of_departure: the device buffer storing angle of departure values as float2 (azimuth, zenith) tuples, in radians, with the same indexing and element count as cir_delays; the angles are defined in the TX panel’s local coordinate system
    • angles_of_arrival: the device buffer storing angle of arrival values as float2 (azimuth, zenith) tuples, in radians, with the same indexing and element count as cir_delays; the angles are defined in the RX panel’s local coordinate system
    • num_samples is either 1 or 14, the number of realizations per slot
    • methods to get index, size, get, and set the CIR values, delays, angles of departure, and angles of arrival for a specific TX/RX antenna pair and tap
  • MultiTimeStepCIRResult

    1struct MultiTimeStepCIRResult {
    2 d_complex *d_cir_values_buffer{};
    3 float *d_cir_delays_buffer{};
    4 float2 *d_angles_of_departure_buffer{};
    5 float2 *d_angles_of_arrival_buffer{};
    6
    7 std::vector<std::vector<CIRResult>> cir_results;
    8
    9 std::vector<size_t> values_time_step_offsets;
    10 std::vector<size_t> delays_time_step_offsets;
    11 std::vector<size_t> angles_of_departure_time_step_offsets;
    12 std::vector<size_t> angles_of_arrival_time_step_offsets;
    13
    14 std::vector<std::vector<size_t>> values_ru_offsets;
    15 std::vector<std::vector<size_t>> delays_ru_offsets;
    16 std::vector<std::vector<size_t>> angles_of_departure_ru_offsets;
    17 std::vector<std::vector<size_t>> angles_of_arrival_ru_offsets;
    18
    19 size_t total_values_bytes{};
    20 size_t total_delays_bytes{};
    21 size_t total_angles_of_departure_bytes{};
    22 size_t total_angles_of_arrival_bytes{};
    23 size_t total_values_elements{};
    24 size_t total_delays_elements{};
    25 size_t total_angles_of_departure_elements{};
    26 size_t total_angles_of_arrival_elements{};
    27 int num_time_steps{};
    28 bool use_async_alloc{true};
    29
    30 std::vector<std::vector<uint32_t>> tx_indices_per_ts;
    31 std::vector<std::vector<std::vector<uint32_t>>> rx_indices_per_ts;
    32
    33 int get_num_rus(int time_step) const;
    34 std::vector<CIRResult>& get(int time_step);
    35 const std::vector<CIRResult>& get(int time_step) const;
    36 CIRResult& get(int time_step, int ru_pos);
    37 const CIRResult& get(int time_step, int ru_pos) const;
    38
    39 size_t get_values_offset(int time_step, int ru_pos) const;
    40 size_t get_delays_offset(int time_step, int ru_pos) const;
    41 size_t get_angles_of_departure_offset(int time_step, int ru_pos) const;
    42 size_t get_angles_of_arrival_offset(int time_step, int ru_pos) const;
    43}

    A struct storing batched CIR results for multiple time steps.

    MemberDescription
    d_cir_values_buffera single contiguous device buffer storing CIR values for all time steps and RUs
    d_cir_delays_buffera single contiguous device buffer storing CIR delays for all time steps and RUs
    d_angles_of_departure_buffera single contiguous device buffer storing angle of departure values for all time steps and RUs
    d_angles_of_arrival_buffera single contiguous device buffer storing angle of arrival values for all time steps and RUs
    cir_resultsper-time-step, per-RU CIRResult views into the contiguous buffers; indexed as cir_results[time_step][ru_pos]
    values_time_step_offsets, delays_time_step_offsets, angles_of_departure_time_step_offsets, angles_of_arrival_time_step_offsetscumulative element offsets for each time step from the corresponding buffer start
    values_ru_offsets, delays_ru_offsets, angles_of_departure_ru_offsets, angles_of_arrival_ru_offsetsper-RU element offsets within each time step, relative to that time step’s start
    total_values_bytes, total_delays_bytes, total_angles_of_departure_bytes, total_angles_of_arrival_bytestotal allocated byte counts for each contiguous buffer
    total_values_elements, total_delays_elements, total_angles_of_departure_elements, total_angles_of_arrival_elementstotal allocated element counts for each contiguous buffer
    num_time_stepsnumber of time steps in the batch
    use_async_alloctrue when buffers were allocated with cudaMallocAsync; false when allocated with cudaMalloc for CUDA IPC compatibility
    tx_indices_per_tsRU indices used for each time step, indexed as [num_time_steps][num_rus]
    rx_indices_per_tsUE indices used for each time step and RU, indexed as [num_time_steps][num_rus][num_ues]

    All offsets are element offsets, not byte offsets. The values offsets index d_complex elements, the delays offsets index float elements, and the angle offsets index float2 elements. The angle buffers have the same logical shape and element count as the delay buffer for the corresponding CIRResult.

    Each contiguous buffer is laid out by concatenating all time steps, then all RUs within each time step:

    pointer_for(time_step, ru_pos) =
    buffer_base
    + time_step_offsets[time_step]
    + ru_offsets[time_step][ru_pos]

    Use values_* offsets with d_cir_values_buffer, delays_* offsets with d_cir_delays_buffer, angles_of_departure_* offsets with d_angles_of_departure_buffer, and angles_of_arrival_* offsets with d_angles_of_arrival_buffer.

    Within each CIRResult view, use the CIRResult index helpers for the per-RU tensor layout: cir_value_index() for cir_values, cir_delay_index() for cir_delays, and angle_of_departure_index() / angle_of_arrival_index() for the angle buffers. The angle index helpers use the same layout as cir_delay_index(). Each angle element is a float2 tuple (azimuth, zenith) in radians. angles_of_departure is defined in the TX panel’s local coordinate system, and angles_of_arrival is defined in the RX panel’s local coordinate system.

  • Matrix4x4

    1typedef struct Matrix4x4 {
    2 float m[4][4]{};
    3
    4 [[nodiscard]] bool operator==(const Matrix4x4 &other) const;
    5} Matrix4x4

    A 4×44\times4 matrix of float elements.

  • EMMaterial

    1struct EMMaterial {
    2 float4 abcd{};
    3 float roughness_rms{};
    4 float k_xpol{};
    5 float scattering_coeff{};
    6 int exponent_alpha_R{};
    7 int exponent_alpha_I{};
    8 float lambda_R{};
    9 float thickness_m{};
    10
    11 [[nodiscard]] bool operator==(const EMMaterial &other) const;
    12}

    A struct storing EM material parameters.

    MemberDescription
    abcda float4 storing ITU-R P2040 a, b, c, and d parameters for calculating the relative permittivity [^2]
    roughness_rmsthe root mean square of the surface roughness (type float), in meters
    k_xpolscattering cross-polarization/col-polarization power ratio (type float)
    scattering_coeffscattering coefficient in the effective roughness (ER) model [^3], [^4] (type float)
    exponent_alpha_Rinteger exponent of the forward scattering lobe (in the specular reflection direction) in the Directional diffuse model (type int)
    exponent_alpha_Iinteger exponent of the backward scattering lobe (in the incidence direction) in the Directional diffuse model (type int)
    lambda_Rratio between the forward scattering power and the total scattering power in the Directional diffuse model (type float)
    thickness_mthickness of the single-layer material (type float), in meters

The diffuse model can be either Lambertian or Directional, and there are two ways to tune the diffuse scattering pattern:

  • using a fixed positive scattering_coeff (the ER model), which does not depend on the incidence angle of the impinging wave. This coefficient is used to calculate the reflection reduction factor and the fraction of power used for diffuse scattering. In this case, the roughness_rms parameter is ignored, as the sets of (abcd, scattering_coeff, k_xpol) and (abcd, scattering_coeff, k_xpol, exponent_alpha_R, exponent_alpha_I, lambda_R, thickness_m) are sufficient for Lambertian and Directional diffuse models, respectively.
  • using roughness_rms to characterize the Rayleigh reflection reduction factor [^5], [^6] and the fraction of power for diffuse scattering. In this case, the scattering_coeff parameter is ignored, as the sets of (abcd, roughness_rms, k_xpol) and (abcd, roughness_rms, k_xpol, exponent_alpha_R, exponent_alpha_I, lambda_R, thickness_m) are sufficient for Lambertian and Directional diffuse models, respectively.

By default, for a material with a positive scattering_coeff, the first method is used. Otherwise, if scattering_coeff = 0.0, then the second method is used. For the Directional diffuse model, the formulation [^4] is reciprocal. When lambda_R = 1.0, the Directional diffuse model becomes a single-lobe diffuse (SLD) model, and the forward lobe contains the total diffuse scattering power. Otherwise, the model uses two lobes.

For reflection and transmission coefficients, the single-layer slab model with a single thickness in ITU Recommendation P.2040-3 is used.

  • EMVegetationMaterial_ITUR

    1struct EMVegetationMaterial_ITUR {
    2 float A{};
    3 float B{};
    4 float C{};
    5 float E{};
    6 float G{};
    7 float scattering_power_factor{};
    8 float k_xpol{};
    9
    10 [[nodiscard]] bool operator==(const EMVegetationMaterial_ITUR &other) const;
    11}

    A struct storing EM material parameters for vegetation, where A, B, C, E, G are the empirical parameters (type float) used in modeling the attenuation loss in Equation (3) of ITU-R 388-10 Recommendation [^7]:

    L(dB)=AfBdC(θ+E)GL(\text{dB}) = Af^{B}d^{C}(θ + E)^{G}

    where ff is the carrier frequency (in MHz), dd is the vegetation depth (in meters), and θ\theta is the path’s elevation angle (in degrees).

    Additionally, the following parameters are used to model diffuse scattering power from vegetation and polarization effects.

    MemberDescription
    scattering_power_factorscattering power factor (type float), the fraction of the total power loss by vegetation that is diffused over all directions
    k_xpolscattering cross-polarization/co-polarization power ratio (type float)

The current diffuse scattering model assumes isotropic scattering pattern, i.e., same power in all directions over the unit sphere. The following figure illustrates the diffusion (a) and transmission (b) interactions modeling for vegetation.

  • EM_INTERACT_TYPE

    1enum EM_INTERACT_TYPE : unsigned int {
    2 Emission = 0,
    3 Reflection = 1,
    4 Diffraction = 2,
    5 Diffuse = 3,
    6 Reception = 4,
    7 Transmission = 5,
    8 Diffuse_Vegetation = 6,
    9 Transmission_Vegetation_In = 7,
    10 Transmission_Vegetation_Out = 8,
    11 Reserved,
    12}

    An enumeration of EM interaction types per ray.

  • EM_DIFFUSE_TYPE

    1enum EM_DIFFUSE_TYPE : unsigned int {
    2 Lambertian = 0,
    3 Directional = 1
    4}

    An enumeration of EM diffuse type.

  • RayPath

    1struct RayPath {
    2 int tx_id{};
    3 int rx_id{};
    4
    5 int tx_ij[2]{};
    6 int rx_ij[2]{};
    7
    8 int rx_index{};
    9
    10 EM_INTERACT_TYPE point_types[MAX_NUM_INTERACTIONS_WITH_TRANSMISSION+2]{};
    11 float3 points[MAX_NUM_INTERACTIONS_WITH_TRANSMISSION+2]{};
    12
    13 int object_ids[MAX_NUM_INTERACTIONS_WITH_TRANSMISSION + 2]{};
    14 int prim_ids[MAX_NUM_INTERACTIONS_WITH_TRANSMISSION+2]{};
    15
    16 float3 normals[MAX_NUM_INTERACTIONS_WITH_TRANSMISSION+2]{};
    17 float vegetation_depths[MAX_NUM_INTERACTIONS_WITH_TRANSMISSION + 2]{};
    18
    19 int num_points{};
    20
    21 d_complex cir_ampl[4]{};
    22 float cir_delay{};
    23
    24 __host__ __device__ RayPath() {}
    25 __host__ __device__ RayPath(int *tx_ij, int *rx_ij, float3 *points,
    26 EM_INTERACT_TYPE *point_types, int *object_ids,
    27 int *prim_ids, float3 *normals, int tx_id,
    28 int rx_id, int rx_index, int num_points);
    29
    30 [[nodiscard]] bool operator==(const RayPath &other) const;
    31}

    A struct storing geometry and EM data of a propagation path.

    MemberDescription
    tx_idID of the RU (type int)
    rx_idID of the UE (type int)
    tx_ijtwo-element array of indices (type int, i for horizontal index and j for vertical index) of the antenna element within the RU panel
    rx_ijtwo-element array of indices (type int, i for horizontal index and j for vertical index) of the antenna element within the UE panel
    rx_indexindex of the UE (type int)
    point_typesan array of EM_INTERACT_TYPE storing the EM interaction types for points along the path
    pointsan array of float3 storing the (x, y, z) coordinates of interaction points, in the same unit as USD map*
    object_idsan array of int storing the indices of the geometry object at the interaction points. The building object, if present, is indexed by 0, followed by the vehicular objects starting from 1. If the building is not present, the first vehicular object is indexed by 0 instead
    prim_idsan array of int storing the indices of the geometry primitive at the interaction points: the hit triangle index for reflection, diffusion, or transmission; the hit edge index for diffraction; and -1 otherwise. The triangle index is local to the building mesh or the base (pre-transform) scatterer mesh
    normalsan array of float3 storing the normals at the interaction points
    vegetation_depthsan array of float storing the vegetation depth at the interaction points**
    num_pointsnumber of interaction points from the RU to UE (type int)
    cir_amplan array of four complex-valued elements storing the path CIR amplitude for four UE-RU polarization combinations***
    cir_delaypropagation delay of the path (type float), in seconds

    *The map unit is determined by Meters Per Unit in the USD file. For example, a map is in meters if Meters Per Unit = 1 and in centimeters if Meters Per Unit = 0.01.

    **For the transmission paths that go through each vegetation object, the vegetation depth is zero at Transmission_Vegetation_In point, and is equal to propagation path length between Transmission_Vegetation_In and Transmission_Vegetation_Out points at the Transmission_Vegetation_Out point. For the diffuse scattering paths from each vegetation object, the vegetation depth is stored at the Diffuse_Vegetation point, the first contact point of the ray from the TX on the vegetation object.

    ***cir_ampl[i*2 + j] is for the UE’s ii-th polarization and RU’s jj-th polarization, for i[0,1]i \in \left[0, 1\right] and j[0,1]j \in \left[0, 1\right].

  • ANTENNA_TYPE

    1enum ANTENNA_TYPE : unsigned int {
    2 Isotropic = 0,
    3 Infinitesimal_dipole = 1,
    4 Halfwave_dipole = 2,
    5 Rec_microstrip_patch = 3,
    6 ThreeGPP_38901 = 4,
    7 Polarized_Isotropic = 5
    8}

    An enumeration for the built-in antenna types currently supported by the EM solver.

  • AntennaPattern

    1struct AntennaPattern {
    2 int pattern_type{};
    3 std::vector<std::vector<d_complex>> ampls_theta{};
    4 std::vector<std::vector<d_complex>> ampls_phi{};
    5
    6 [[nodiscard]] bool operator==(const AntennaPattern &other) const;
    7}

    A struct storing a radiation pattern for a given antenna element, for either a built-in or a custom antenna type. The current version only supports patterns at a single frequency.

    MemberDescription
    pattern_typean integer indicating the radiation pattern type as defined in the ANTENNA_TYPE enum (type int)
    ampls_thetaa two-dimensional vector storing complex-valued amplitudes (type d_complex) of the antenna radiated field along the theta direction, each inner vector stores the amplitudes for one frequency
    ampls_phia two-dimensional vector storing complex-valued amplitudes (type d_complex) of the antenna radiated field along the phi direction, each inner vector stores the amplitudes for one frequency

    For built-in antenna types, the radiation fields are analytically calculated by the EM engine, and the ampls_theta and ampls_phi member variables are ignored. For example, for an Infinitesimal_dipole pattern type, the AntennaPattern object is:

    1AntennaPattern pattern = {.pattern_type = 1, .ampls_theta = {}, .ampls_phi = {}};
  • AntennaPanel

    1struct AntennaPanel {
    2 std::string panel_name{};
    3 std::vector<std::string> antenna_names{};
    4 std::vector<int> antenna_pattern_indices{};
    5 std::vector<float> frequencies{};
    6 std::vector<float> thetas{};
    7 std::vector<float> phis{};
    8 double reference_freq{};
    9 bool dual_polarized{};
    10 int num_loc_antenna_horz{};
    11 int num_loc_antenna_vert{};
    12 double antenna_spacing_horz{};
    13 double antenna_spacing_vert{};
    14 double antenna_roll_angle_first_polz{};
    15 double antenna_roll_angle_second_polz{};
    16
    17 [[nodiscard]] bool operator==(const AntennaPanel &other) const;
    18}

    A struct storing information for a given antenna panel. The number of antenna elements in a panel is num_loc_antenna_horz*num_loc_antenna_vert*num_polarizations.

    MemberDescription
    panel_namename of the panel (type string)
    antenna_namesa vector of names (type string) of all antenna elements in the panel
    antenna_pattern_indicesa vector of indices (type int) to the patterns vector for the antenna elements in the panel
    frequenciesa vector of frequencies (type float) for the antenna radiation patterns of the antenna elements in the panel, in Hertz
    thetasa vector storing elevation angles (type float) of the radiation pattern for all antenna elements in the panel, in radians*
    phisa vector storing azimuth angles (type float) of the radiation pattern for all antenna elements in the panel, in radians*
    reference_freqcenter frequency (type double) of the panel, in Hertz
    dual_polarizeda bool variable to indicate if the panel antennas are dual- (true) or single- polarized (false)
    num_loc_antenna_horznumber of antenna element locations (type int) in the planar array along a row
    num_loc_antenna_vertnumber of antenna element locations (type int) in the planar array along a column
    antenna_spacing_horzhorizontal antenna element spacing (type double), in centimeters
    antenna_spacing_vertvertical antenna element spacing (type double), in centimeters
    antenna_roll_angle_first_polzangular displacement of the antenna element realizing the first polarization (type double), in radians
    antenna_roll_angle_second_polzangular displacement of the element realizing the second polarization (type double), in radians

    *For custom antenna patterns, the ranges of thetas and phis need to follow the standard conventions: [0,π][0, \pi] for thetas and [0,2π][0, 2\pi] for phis.

  • AntennaInfo

    1struct AntennaInfo {
    2 std::vector<AntennaPanel> panels{};
    3 std::vector<AntennaPattern> patterns{};
    4
    5 [[nodiscard]] bool operator==(const AntennaInfo &other) const;
    6}

    A struct encapsulating information of all antenna panels and antenna radiation patterns.

    MemberDescription
    panelsvector of panels (type AntennaPanel)
    patternsvector of patterns (type AntennaPattern)
  • TXInfo

    1struct TXInfo {
    2 int tx_ID{};
    3 float3 tx_center{};
    4 Matrix4x4 Ttx{};
    5
    6 std::vector<int> panel_id{};
    7 float height{};
    8 float mech_azimuth_deg{};
    9 float mech_tilt_deg{};
    10
    11 float carrier_freq{};
    12 float carrier_bandwidth{};
    13 float subcarrier_spacing{};
    14 int fft_size{};
    15 float radiated_power{};
    16 std::vector<std::string> antenna_names{};
    17 std::vector<int> antenna_pattern_indices{};
    18 bool dual_polarized_antenna{};
    19 std::vector<float3> antenna_rotation_angles{};
    20 int num_loc_antenna_horz{};
    21 int num_loc_antenna_vert{};
    22 std::vector<float3> loc_antenna{};
    23 std::vector<std::pair<int, int>> ij_antenna{};
    24
    25 float3 velocity_3d{};
    26
    27 [[nodiscard]] bool operator==(const TXInfo &other) const;
    28}

    A struct storing RU information.

    MemberDescription
    tx_IDID of the RU (type int)
    tx_center(x , y, z) coordinates of the RU center (type float3), in the same unit as USD map
    Ttxa Matrix4x4 transformation matrix for the RU combining translation and rotation, in the same unit as USD map
    panel_ida vector of indices (type int) identifying the panels used by the RU; currently only size 1 is supported
    heightheight (type float) calculated from RU base to the RU center, in centimeters
    mech_azimuth_degmechanical azimuth (type float) of the RU, in degrees
    mech_tilt_degmechanical tilt (type float) of the RU, in degrees
    carrier_freqcarrier frequency (type float) of the RU, in Hertz
    subcarrier_spacingsub-carrier spacing (type float), in Hertz
    fft_sizeFFT size (type int) used for wideband CFR calculation
    radiated_powerradiated power (type float) of the RU, in Watts
    antenna_namesa vector of names (type string) of all antenna elements in the RU panel
    antenna_pattern_indicesa vector of indices (type int) to the patterns vector for the antenna elements in the RU panel
    dual_polarized_antennaa bool variable to indicate if the RU antenna panel is composed by dual- (true) or single- polarized (false) elements
    antenna_rotation_anglesa vector of triplets storing rotation angles (type float3) of the antennas: the first triplet is for the first polarization, and in case of dual-polarized antennas, the second triplet is for the second polarization
    num_loc_antenna_horznumber of antenna element locations (type int) in the horizontal direction within the RU antenna panel
    num_loc_antenna_vertnumber of antenna element locations (type int) in the vertical direction within the RU antenna panel
    loc_antennavector of (x, y, z) of antenna positions within the RU antenna panel (type float3), in the same unit as USD map*
    ij_antennaa vector of pairs of indices (type int) storing horizontal and vertical indices of the antenna elements in the RU antenna panel
    velocity_3dthree-dimensional velocity (in meter per second) of the RU (type float3)

    Note: The antenna locations and the (i, j) antenna indices in the TXInfo are order-consistent: e.g. the element at location indexed by (i, j) with polarization p, is antenna_names[i*num_loc_antenna_vert*num_polarizations + j*num_polarizations + p - 1], where num_polarizations is 1 for single-polarized panels and 2 for dual-polarized panels. In addition, (i, j) = (0, 0) indicates the bottom-left antenna location in the antenna array. These conventions are also used for RXInfo struct below. It is worth noticing that, in the graphical interface, the top and the bottom of the array are inverted, i.e., what is at the top in the graphical interface is considered at the bottom in EM solver.

  • RXInfo

    1struct RXInfo {
    2 int rx_ID{};
    3 float3 rx_center{};
    4 Matrix4x4 Trx{};
    5
    6 std::vector<int> panel_id{};
    7 float radiated_power{};
    8 std::vector<std::string> antenna_names{};
    9 std::vector<int> antenna_pattern_indices{};
    10 bool dual_polarized_antenna{};
    11 std::vector<float3> antenna_rotation_angles{};
    12 int num_loc_antenna_horz{};
    13 int num_loc_antenna_vert{};
    14 std::vector<float3> loc_antenna{};
    15 std::vector<std::pair<int, int>> ij_antenna{};
    16
    17 float3 velocity_3d{};
    18
    19 [[nodiscard]] bool operator==(const RXInfo &other) const;
    20}

    A struct storing UE information.

    MemberDescription
    rx_IDID of the UE (type int)
    rx_center(x , y, z) coordinates of the UE center (type float3), in the same unit as USD map
    Trxa Matrix4x4 transformation matrix for the UE combining translation and rotation, in the same unit as USD map
    panel_ida vector of indices (type int) identifying the panels used by the UE; currently only size 1 is supported
    radiated_powerradiated power (type float) of the UE, in Watts
    antenna_namesa vector of names (type string) of all antenna elements in the UE panel
    antenna_pattern_indicesa vector of indices (type int) to the patterns vector for the antenna elements in the UE panel
    dual_polarized_antennaa bool variable to indicate if the UE antenna panel is composed by dual- (true) or single- polarized (false) elements
    antenna_rotation_anglesa vector of triplets storing rotation angles (type float3) of the antennas: the first triplet is for the first polarization, and in case of dual-polarized antennas, the second triplet is for the second polarization
    num_loc_antenna_horznumber of antenna element locations (type int) in the horizontal direction within the UE antenna panel
    num_loc_antenna_vertnumber of antenna element locations (type int) in the vertical direction within the UE antenna panel
    loc_antennavector of (x, y, z) of antenna positions within the RU antenna panel (type float3), in the same unit as USD map
    ij_antennaa vector of pairs of indices (type int) storing horizontal and vertical indices of the antenna elements in the UE antenna panel
    velocity_3dthree-dimensional velocity (in meter per second) of the UE (type float3)
  • Mesh

    1struct Mesh {
    2 std::vector<float3> mesh_vertices{};
    3 std::vector<int> triangle_material_ids{};
    4 bool is_diffusion{};
    5 bool is_diffraction{};
    6 bool is_transmission{};
    7 float diffuse_dS_sqm = 1.0;
    8
    9 [[nodiscard]] bool operator==(const Mesh &other) const;
    10};

    A struct storing information of a triangular mesh in the scene.

    MemberDescription
    mesh_verticesa vector of vertices (type float3) of the triangular mesh*, in the same unit as USD map
    triangle_material_idsa vector of material indices (type int) of the mesh’s triangles
    is_diffusionflag (type boolean) to indicate if the mesh is enabled for diffuse (True) or not (False)
    is_diffractionflag (type boolean) to indicate if the mesh is enabled for diffraction (True) or not (False)
    is_transmissionflag (type boolean) to indicate if the mesh is enabled for transmission (True) or not (False)
    diffuse_dS_sqm(type float) the area of the diffuse surface element in square meter

    Notes: The vertices are grouped in tuples of 3 elements for the building triangles, e.g., vertices {[0], [1], [2]} for the first triangle, vertices {[3], [4], [5]} for the second triangles and so on. For each triangle, the vertex winding order is counter-clockwise so that its front face normal points outward for the building meshes and upward for the ground meshes.

  • BuildingEdge

    1struct BuildingEdge {
    2 float3 p1{};
    3 float3 p2{};
    4 float3 e{};
    5 float3 e1{};
    6 float3 e2{};
    7 float3 n1{};
    8 float3 n2{};
    9 int triangle_id1{};
    10 int triangle_id2{};
    11 int material_id1{};
    12 int material_id2{};
    13 int diffuse_attr_1{};
    14 int diffuse_attr_2{};
    15};

    A struct storing information about a building edge formed by two connected building faces (triangles).

    MemberDescription
    p1first endpoint of the edge (type float3)
    p2second endpoint of the edge (type float3)
    eunit vector pointing from p1 to p2 (type float3)
    e1unit vector tangent to the first face (type float3)
    e2unit vector tangent to the second face (type float3)
    n1unit vector normal to the first face (type float3)
    n2unit vector normal to the second face (type float3)
    triangle_id1index of the first triangle (type int)
    triangle_id2index of the second triangle (type int)
    material_id1material index of the first triangle (type int)
    material_id2material index of the second triangle (type int)
    diffuse_attr_11 if the first face is enabled for diffuse scattering, 0 otherwise (type int)
    diffuse_attr_21 if the second face is enabled for diffuse scattering, 0 otherwise (type int)
  • SCATTERER_TYPE

    1enum SCATTERER_TYPE : int { Vehicle = 0 };

    An enumeration for the scatterer type.

  • ScattererInfo

    1struct ScattererInfo {
    2int id{};
    3SCATTERER_TYPE type{};
    4int mesh_ind{};
    5Matrix4x4 transform{};
    6float3 velocity_3d{};
    7
    8[[nodiscard]] bool operator==(const ScattererInfo &other) const;
    9};

    A struct storing information of a scatterer in the scene.

    MemberDescription
    idindex of the scatterer (type int)
    SCATTERER_TYPEtype of the scatterer (type SCATTERER_TYPE)
    mesh_indindex of the base (pre-transform) mesh in the array geometry_info.scatterer_mesh used for the scatterer (type int)
    transformtransformation matrix for the scatterer combining scaling, translation and rotation, in the same unit as USD map (type Matrix4x4)
    velocity_3dthree-dimensional velocity (in meter per second) of the scatterer (type float3)
  • VEGETATION_TYPE

    1enum VEGETATION_TYPE : int {
    2 Street_Tree = 0,
    3 // Add more here
    4};

    An enumeration for the vegetation type.

  • VegetationInfo

    1struct VegetationInfo {
    2 int id{};
    3 VEGETATION_TYPE type{};
    4 int vegetation_material_id{};
    5 int mesh_ind{}; // index to the array geometry_info.vegetation_mesh
    6 Matrix4x4 transform{};
    7
    8 [[nodiscard]] bool operator==(const VegetationInfo &other) const;
    9};

    A struct storing information of a vegetation in the scene.

    MemberDescription
    idindex of the vegetation (type int)
    VEGETATION_TYPEtype of the vegetation (type EM_VEGETATION_MODEL)
    vegetation_material_idmaterial index of the vegetation (type int)
    mesh_indindex of the base (pre-transform) mesh in the array geometry_info.vegetation_mesh used for the vegetation (type int)
    transformtransformation matrix for the scatterer combining scaling, translation and rotation, in the same unit as USD map (type Matrix4x4)
  • GeometryInfo

    1struct GeometryInfo {
    2 std::vector<Mesh> building_mesh{};
    3 std::vector<Mesh> terrain_mesh{};
    4 std::vector<Mesh> scatterer_mesh{};
    5 std::vector<ScattererInfo> scatterer_info{};
    6 std::vector<Mesh> vegetation_mesh{};
    7 std::vector<VegetationInfo> vegetation_info{};
    8 std::unordered_map<std::string, std::pair<int,EMMaterial>> material_dict{};
    9 std::unordered_map<std::string, std::pair<int, EMVegetationMaterial_ITUR>>
    10 vegetation_material_ITUR_dict{};
    11 float meters_per_unit = 0.01f;
    12
    13 [[nodiscard]] bool operator==(const GeometryInfo &other) const;
    14};

    A struct storing information for the geometries in the scene.

    MemberDescription
    building_mesha vector of building meshes (type Mesh) in the scene
    terrain_mesha vector of terrain meshes (type Mesh) in the scene
    scatterer_mesha vector of scatterer meshes (type Mesh), each holds the base (pre-transform) mesh and related metadata for each type of scatterer in the scene
    scatterer_infoa vector of ScattererInfo structs storing the information of the scatterers in the scene
    vegetation_mesha vector of vegetation meshes (type Mesh), each holds the base (pre-transform) mesh and related metadata for each type of vegetation in the scene
    vegetation_infoa vector of VegetationInfo structs storing the information of the vegetation in the scene
    material_dictan unordered map for the material dictionary storing all materials in the scene: key is the material name (type string) and value is a pair of <int, EMMaterial>
    vegetation_material_ITUR_dictan unordered map for the vegetation material dictionary storing all materials in the scene: key is the material name (type string) and value is a pair of <int, EMVegetationMaterial_ITUR>
    meters_per_unita constant value of the amount of meters in the spatial units of the meshes (type float), default value is 0.01 0.01
  • RTConfig

    1struct RTConfig {
    2 int num_rays_in_thousands{};
    3 int max_num_bounces{};
    4 float rx_sphere_radius_cm{};
    5 EM_DIFFUSE_TYPE em_diffuse_type{};
    6 bool use_only_first_antenna_pair{};
    7 bool write_cfr_results{};
    8 bool write_tau_mins{};
    9 bool simulate_ran{};
    10 int max_num_paths_per_ant_pair{};
    11 EM_VEGETATION_MODEL em_vegetation_model{};
    12 bool write_cir_results{};
    13 bool fast_mode{};
    14 bool copy_ray_paths_to_host{};
    15
    16 [[nodiscard]] bool operator==(const RTConfig &other) const;
    17}

    A struct storing the configuration of the raytracing parameters.

    MemberDescription
    num_rays_in_thousandsnumber of emitted rays in thousands (type int)
    max_num_bouncesmaximum number of scattering events for each emitted ray (type int)
    rx_sphere_radius_cmreception sphere radius (type float), in centimeters
    em_diffuse_typediffuse type to indicate the diffuse scattering model (type EM_DIFFUSE_TYPE): Lambertian = 0, Directional = 1
    use_only_first_antenna_paira bool variable, when set to true only the results for the first RU-UE antenna pair are returned from runEMSolver()
    write_cfr_resultsa bool variable, when set to true, runEMSolver() returns the channel frequency response results stored on device buffers d_all_cfr_results
    write_tau_minsa bool variable, when set to true, runEMSolver() returns the minimum propagation delays stored on device buffers d_all_tau_mins
    simulate_rana bool variable, when set to true the full RAN simulation is enabled
    max_num_paths_per_ant_pairthe maximum number of strongest paths retained per RU-UE antenna pair (type int)
    em_vegetation_modelenumeration for the vegetation attenuation model (type EM_VEGETATION_MODEL). Currently only ITU_R 388-10 model [^7] is supported
    write_cir_resultsa bool variable, when set to true, runEMSolver() returns the CIR values, delays, angles of departure, and angles of arrival stored on device buffers in CIRResult structs
    fast_modea bool variable, when set to true, the EM solver executes in fast mode with two approximations: plane-wave approximation for MIMO antenna panels, and Doppler phase-shift approximation for 14-symbol slot simulations
    copy_ray_paths_to_hosta bool variable, when set to true, all propagation results from all selected RUs to their associated UEs are stored in all_ray_path_results after the runEMSolver() call returns

Compute mutual coupling patterns (temporarily not supported)

  • compute_mutual_coupling_patterns()
    1std::vector<emsolver::AntennaPattern> compute_mutual_coupling_patterns(const emsolver::AntennaPanel &panel);
    Compute antenna patterns including the effect of mutual coupling.

Supported CUDA architectures

  • supported_cuda_architectures()
    1std::vector<uint32_t> supported_cuda_architectures();
    Returns list of supported cuda architectures based on emsolver library compilation, e.g. [80, 86, 89, 90].

Class AerialEMSolver

  • AerialEMSolver()

    1AerialEMSolver(const std::vector<TXInfo>& tx_info,
    2 const std::vector<RXInfo>& rx_info,
    3 const AntennaInfo& antenna_info,
    4 const GeometryInfo& geometry_info,
    5 const RTConfig& rt_cfg,
    6 cudaStream_t ext_stream);

    Constructor for the AerialEMSolver object.

    In/outParameterDescription
    [in]tx_infoa vector of TXInfo structs storing the information of the RUs
    [in]rx_infoa vector of RXInfo structs storing the information of the UEs
    [in]antenna_infoAntennaInfo struct storing the information of all antenna panels and antenna radiation patterns
    [in]geometry_infoGeometryInfo struct storing the information of the scene geometry and materials
    [in]rt_cfgRTConfig struct storing the ray tracing configurations
    [in]ext_streamCUDA stream index (type cudaStream_t)
  • ~AerialEMSolver()

    1~AerialEMSolver()

    Destructor for the AerialEMSolver object.

  • allocateDeviceMemForResults()

    1int32_t allocateDeviceMemForResults(const std::vector<TXInfo>& tx_info,
    2 const std::vector<RXInfo>& rx_info,
    3 const std::vector<uint32_t>& tx_indices,
    4 const std::vector<std::vector<uint32_t>>& rx_indices,
    5 const RTConfig& rt_cfg,
    6 const int symbols_per_slot,
    7 std::vector<d_complex*>& d_all_cfr_results,
    8 std::vector<float*>& d_all_tau_mins,
    9 std::vector<CIRResult> &d_all_cir_results);
    10
    11int32_t allocateDeviceMemForResults(const std::vector<TXInfo>& tx_info,
    12 const std::vector<RXInfo>& rx_info,
    13 const std::vector<std::vector<uint32_t>>& tx_indices_per_ts,
    14 const std::vector<std::vector<std::vector<uint32_t>>>& rx_indices_per_ts,
    15 const RTConfig& rt_cfg,
    16 const int symbols_per_slot,
    17 const int num_time_steps,
    18 std::vector<d_complex*>& d_all_cfr_results,
    19 std::vector<float*>& d_all_tau_mins,
    20 MultiTimeStepCIRResult& cir_result,
    21 bool use_async_alloc = true);
    22
    23int32_t allocateDeviceMemForResults(const std::vector<TXInfo>& tx_info,
    24 const std::vector<RXInfo>& rx_info,
    25 const std::vector<uint32_t>& tx_indices,
    26 const std::vector<std::vector<uint32_t>>& rx_indices,
    27 const RTConfig& rt_cfg,
    28 const int symbols_per_slot,
    29 const int num_time_steps,
    30 std::vector<d_complex*>& d_all_cfr_results,
    31 std::vector<float*>& d_all_tau_mins,
    32 MultiTimeStepCIRResult& cir_result,
    33 bool use_async_alloc = true);

    Allocation of device (GPU) memory to store the results of the EM engine.

    The first overload is the legacy single-time-step API and returns a vector of per-RU CIRResult views. The second overload accepts a per-time-step RU/UE configuration and allocates a MultiTimeStepCIRResult. The third overload broadcasts the same RU/UE configuration to num_time_steps time steps and delegates to the per-time-step overload.

    Multi-time-step allocation is supported for CIR results. CFR allocation is supported only for a single time step; when num_time_steps > 1, write_cfr_results must be false.

    In/outParameterDescription
    [in]tx_infoa vector of TXInfo structs storing the information of all the RUs
    [in]rx_infoa vector of RXInfo structs storing the information of all the UEs
    [in]tx_indices_per_tsa vector of vectors of RU indices (type uint32_t) for each time step, indexed as [num_time_steps][num_rus]
    [in]rx_indices_per_tsa vector of vectors of selected UE indices (type uint32_t) for each time step and RU, indexed as [num_time_steps][num_rus][num_ues]
    [in]tx_indicesa vector of indices (type uint32_t) for the RUs whose results need to be computed; used by the broadcast and legacy overloads
    [in]rx_indicesa vector of vectors of indices (type uint32_t) of selected UEs for each RU; used by the broadcast and legacy overloads
    [in]rt_cfgRTConfig struct storing the raytracing configuration
    [in]symbols_per_slotnumber of symbols (type int) in one slot (either 1 or 14)
    [in]num_time_stepsnumber of time steps to allocate for the multi-time-step overloads
    [out]d_all_cfr_resultsa vector of device pointers (type d_complex), each pointing to memory address holding the CFRs for the UEs associated to a given RU. The content of the vector follows the content of tx_indices. The allocation is realized when write_cfr_results in the rt_config is true
    [out]d_all_tau_minsa vector of device pointers (type float), each pointing to memory address holding the minimum propagation delay for the UEs associated to a given RU. The content of the vector follows the content of tx_indices. The allocation is realized when write_tau_mins in the rt_config is true
    [out]cir_resultMultiTimeStepCIRResult storing the contiguous CIR values, delays, angles of departure, angles of arrival, and per-time-step/per-RU views into those buffers. The allocation is realized only when write_cir_results in the rt_config is true
    [out]d_all_cir_resultsa vector of CIRResult structs storing the CIR results. The content of the vector follows the content of tx_indices. The allocation is realized only when write_cir_results in the rt_config is true
    [in]use_async_allocwhen true, allocate CIR buffers with cudaMallocAsync; when false, allocate them with cudaMalloc for CUDA IPC compatibility

    All CFR results for the ii-th RU, i.e., d_all_cfr_results_i = d_all_cfr_results[i], are stored in the device memory as a flattened representation of multidimensional array whose indices, in order, are <ue_idx>, <symbol_idx>, <freq_idx>, <ue_ant_idx>, <ue_ant_pol_idx>, <ru_ant_idx>, <ru_ant_pol_idx>.

    For example, the first 6 elements of d_all_cfr_results_i, with the ii-the RU being equipped with dual-polarized antennas and all associated UEs also having dual-polarized antennas, are:

    CFRs_mem_arrangement

    For the minimum delay results, there is one minimum delay for all RU-UE antenna pairs (i.e., one value for one RU-UE pair, and d_all_tau_mins[i] holds the minimum delays from ii-th RU to its associated UEs).

    Similar device memory arrangements are done for cir_values, cir_delays, angles_of_departure, and angles_of_arrival in each CIRResult. In the multi-time-step API, these CIRResult objects are stored in cir_result.cir_results[time_step][ru_pos] and point into the contiguous buffers owned by MultiTimeStepCIRResult.

  • runEMSolver()

    1int32_t runEMSolver(const unsigned int time_idx,
    2 const std::vector<TXInfo>& tx_info,
    3 const std::vector<RXInfo>& rx_info,
    4 const AntennaInfo& antenna_info,
    5 const GeometryInfo &geometry_info,
    6 const std::vector<uint32_t>& tx_indices,
    7 std::vector<std::vector<uint32_t>>& rx_indices,
    8 const RTConfig& rt_cfg,
    9 const int symbol_idx,
    10 const int symbols_per_slot,
    11 std::vector<RayPath>& all_ray_path_results,
    12 std::vector<d_complex*>& d_all_cfr_results,
    13 std::vector<float*>& d_all_tau_mins,
    14 std::vector<CIRResult> &d_all_cir_results);

    Launch the EM engine.

    In/outParameterDescription
    [in]time_idxtime index (type unsigned int) in the simulation
    [in]tx_infoa vector of TXInfo structs storing the information of all the RUs
    [in]rx_infoa vector of RXInfo structs storing the information of all the UEs
    [in]antenna_infoAntennaInfo struct storing the information of all antenna panels and antenna radiation patterns
    [in]geometry_infoGeometryInfo struct storing the information of the scene geometry and materials
    [in]tx_indicesa vector of indices (type uint32_t) for the RUs whose results need to be computed
    [in]rx_indicesa vector of vectors of indices (type uint32_t) of selected UEs for each RUs whose results need to be computed
    [in]rt_cfgRTConfig struct storing the ray tracing configurations
    [in]symbol_idxsymbol index (type int) within a slot
    [in]symbols_per_slotnumber of symbols (type int) in one slot (either 1 or 14)
    [in]all_ray_path_resultsa vector of RayPath structs storing all propagation results from all selected RUs to their associated UEs
    [out]d_all_cfr_resultsa vector of device pointers (type d_complex), each pointing to memory address holding the CFRs for the UEs associated to a given RU. The content of the vector follows the content of tx_indices. The storing is realized when write_cfr_results in the rt_config is true
    [out]d_all_tau_minsa vector of device pointers (type float), each pointing to memory address holding the minimum propagation delay for the UEs associated to a given RU. The content of the vector follows the content of tx_indices. The storing is realized when write_tau_mins in the rt_config is true
    [out]d_all_cir_resultsa vector of CIRResult structs storing the CIR results. The content of the vector follows the content of tx_indices. The storing is realized only when write_cir_results in the rt_config is true
  • copyResultsFromDeviceToHost()

    1int32_t copyResultsFromDeviceToHost(const std::vector<uint32_t>& tx_indices,
    2 const std::vector<std::vector<uint32_t>>& rx_indices,
    3 const RTConfig& rt_cfg,
    4 const int symbols_per_slot,
    5 const std::vector<d_complex*>& d_all_cfr_results,
    6 std::vector<std::vector<d_complex>>* all_cfr_results);

    Copy the results of the EM engine from device to host.

    In/outParameterDescription
    [in]tx_indicesa vector of indices (type uint32_t) for the RUs whose results need to be computed
    [in]rx_indicesa vector of vectors of indices (type uint32_t) of selected UEs for each RUs whose results need to be computed
    [in]rt_cfgRTConfig struct storing the ray tracing configurations
    [in]symbols_per_slotnumber of symbols (type int) in one slot (either 1 or 14)
    [in]d_all_cfr_resultsa vector of device pointers (type d_complex), each pointing to memory address holding the CFRs for the UEs associated to a given RU. The content of the vector follows the content of tx_indices
    [out]all_cfr_resultsa pointer to a host-side vector of vectors for the CFR results, with the inner vector holding the CFRs from one RU to its associated UEs and the outer vector following tx_indices
  • deAllocateDeviceMemForResults()

    1int32_t deAllocateDeviceMemForResults(const RTConfig& rt_cfg,
    2 std::vector<d_complex*>& d_all_cfr_results,
    3 std::vector<float*>& d_all_tau_mins,
    4 std::vector<CIRResult>& d_all_cir_results);
    5
    6int32_t deAllocateDeviceMemForResults(const RTConfig& rt_cfg,
    7 std::vector<d_complex*>& d_all_cfr_results,
    8 std::vector<float*>& d_all_tau_mins,
    9 MultiTimeStepCIRResult& cir_result);

    Deallocate device memory previously used for the EM engine results.

    The first overload is the legacy single-time-step API. The second overload deallocates the contiguous CIR buffers owned by MultiTimeStepCIRResult.

    In/outParameterDescription
    [in]rt_cfgRTConfig struct storing the ray tracing configurations
    [in]d_all_cfr_resultsa vector of device pointers (type d_complex): each of them pointing to a device memory that holds complex-valued amplitude of the CFRs from one RU to its associated UEs. The size of the vector is equal to size of the tx_indices
    [in]d_all_tau_minsa vector of device pointers (type float), each pointing to memory address holding the minimum propagation delay for the UEs associated to a given RU. The content of the vector follows the content of tx_indices
    [in]cir_resultMultiTimeStepCIRResult whose contiguous CIR values, delays, angles of departure, and angles of arrival buffers are deallocated
    [in]d_all_cir_resultsa vector of CIRResult structs storing the CIR results. The content of the vector follows the content of tx_indices.
  • getBuildingEdges()

    1const std::vector<BuildingEdge>& getBuildingEdges() const noexcept;

    Return all building edges of the scene.

Error handling

The EM engine has built-in error handling. The function where the error or invalid condition occurs is recorded and error messages are propagated to both the local console and the Console tab in the graphical interface.

  • EMLogLevel

    1enum class EMLogLevel {ERROR=0, NOTIFY=1, WARNING=2, INFO=3, DEBUG=4, VERBOSE=5}

    An enumeration for the level of logging.

  • EMLogCallback

    1EMLogCallback = std::function<void(EMLogLevel, const std::string&)>;

    Callback function prototype.

  • registerLogCallback()

    1int32_t registerLogCallback(EMLogCallback func);

    Function to register a callback function (type EMLogCallback) for error handling.

  • deregisterLogCallback()

    1int32_t deregisterLogCallback();

    Function to deregister the currently registered callback function.