# rfx

Channel: development; package: 2.0.0rc1; source: 2c32b7cf79b796fae825bfa08fc73d9914e61723

Page: https://remilab.ai/rfx/
Source: https://github.com/bk-squared/rfx/blob/2c32b7cf79b796fae825bfa08fc73d9914e61723/docs/public/index.mdx

Open source · JAX · 3-D FDTD for RF and microwave
  The RF simulator that returns gradients.
  Write a loss on S-parameters, a radiation pattern or a field. rfx gives its derivative with respect to the permittivity of every cell in your design region from one forward and one reverse pass. On the patch antenna below, the value and gradient over 43,008 design cells take 1.4 times as long as the simulation alone.
  pip install rfx-fdtd [See the showcase →](https://remilab.ai/rfx/showcase/) [GitHub](https://github.com/bk-squared/rfx)

  ![Video poster](https://remilab.cnu.ac.kr/share/7c02ad43c580/patch-sensitivity/patch_sensitivity_poster.png)

    [source](https://remilab.cnu.ac.kr/share/7c02ad43c580/patch-sensitivity/patch_sensitivity.mp4)

    [Download the loop (MP4)](https://remilab.cnu.ac.kr/share/7c02ad43c580/patch-sensitivity/patch_sensitivity.mp4).
  
  One reverse pass through a 2.3 GHz patch antenna on RT/Duroid 5880: how much each of 20,592 substrate cells moves |S11| at 2.356 GHz. The map is strongest under the two radiating edges and nearly zero along the centre line, the field pattern of the TM010 mode. [Read the case →](https://remilab.ai/rfx/showcase/sensitivity-map/)

  
    1.4×
    Value and gradient over 12,400 to 43,008 design cells, compared with one forward run on the same RTX A6000. Central differences would take 4.9 to 16.8 days.
    [What a gradient costs →](https://remilab.ai/rfx/showcase/gradient-cost/)
  
  
    2×10⁻⁵
    Largest relative difference between the reverse-mode gradient and central finite differences on the patch (float64).
    [How the gradient was checked →](https://remilab.ai/rfx/showcase/sensitivity-map/)
  

## See the gradient at work

  
    [![Map of the derivative of |S11|² with respect to the permittivity of each substrate cell under a patch antenna, beside its |S11| curve and its |E_z|² map](https://remilab.cnu.ac.kr/share/7c02ad43c580/patch-sensitivity/patch_sensitivity_site.png)](https://remilab.ai/rfx/showcase/sensitivity-map/)
    Which cells move the match?
    One reverse pass maps the sensitivity of a patch antenna's |S11| to every substrate cell.
    20,592 cells, one pass
    [Read the case →](https://remilab.ai/rfx/showcase/sensitivity-map/)
  
  
    [![Bar chart of wall time on an RTX A6000 for a forward run, the value and gradient, and central differences, for three design regions](https://remilab.cnu.ac.kr/share/7c02ad43c580/patch-sensitivity/gradient_cost_site.png)](https://remilab.ai/rfx/showcase/gradient-cost/)
    What a gradient costs
    Time and memory for the value and gradient against a forward run, as the design region grows.
    24 s vs 4.9–16.8 days
    [Read the case →](https://remilab.ai/rfx/showcase/gradient-cost/)
  
  
    [![Reflection of a three-layer anti-reflection coating, its layer permittivities over the Adam iterations, and the band-mean reflection against the transfer-matrix optimum](https://remilab.cnu.ac.kr/share/7c02ad43c580/ar-coating/ar_coating_site.png)](https://remilab.ai/rfx/showcase/descent-to-optimum/)
    Descend to the closed-form optimum
    Adam through the FDTD solve finds the three layer permittivities of a broadband anti-reflection coating.
    within 1.1 % of the transfer-matrix optimum
    [Read the case →](https://remilab.ai/rfx/showcase/descent-to-optimum/)
  
  
    [![Input impedance of the RT/Duroid 5880 probe-fed patch from rfx and from openEMS](https://remilab.cnu.ac.kr/share/7c02ad43c580/forward-patch/forward_curves_rt5880_patch_site.png)](https://remilab.ai/rfx/showcase/forward-checks/)
    The forward model next to openEMS
    Input impedance of the patch and |S21| of a microstrip notch filter, on the same boards as openEMS.
    being re-measured under the current settling check
    [Read the case →](https://remilab.ai/rfx/showcase/forward-checks/)
  

## What the code looks like

The objective is an ordinary Python function of the permittivity in a design
box. JAX differentiates the whole time-stepping loop.

```python
def J(eps_box):
    res = board.sim.forward(
        design_box=corners, design_eps_override=eps_box,
        design_box_holds_ports=True, n_steps=n_steps, checkpoint=False,
        checkpoint_segments=checkpoint_segments,
        port_s11_freqs=freqs, skip_preflight=True)
    s = res.s_params
    s = s if s.ndim == 1 else s[0]
    return jnp.real(s[0]) ** 2 + jnp.imag(s[0]) ** 2

v, g = jax.jit(jax.value_and_grad(J))(eps_bg)
```

The full script builds the board, runs preflight once on it, and checks the
gradient against finite differences before anything is plotted.
[Full script →](https://github.com/bk-squared/rfx/blob/2c32b7cf79b796fae825bfa08fc73d9914e61723/scripts/showcase/patch_sensitivity.py)

## Start here

- Install and run a first model: [Installation](https://remilab.ai/rfx/start/install/) · [Your first run](https://remilab.ai/rfx/guide/first-run/)
- Watch fields move before measuring them: [The visual manual](https://remilab.ai/rfx/gallery/visual-manual/) (the teaching films)
- Design with gradients: [Autodiff and adjoint](https://remilab.ai/rfx/design/gradients/) · [Inverse design](https://remilab.ai/rfx/design/optimization/) · [Gradient behavior](https://remilab.ai/rfx/guide/gradient-behavior/)
- Look up a call: [API reference](https://remilab.ai/rfx/api/)

## Before you trust a number

A result holds for the structure, mesh and observable it was checked on. Read
[Support Boundaries](https://remilab.ai/rfx/support/) before combining features and
[Evidence](https://remilab.ai/rfx/validation/) before reporting an RF result.

  Working with a coding assistant? Point it at [/rfx/llms.txt](https://remilab.ai/rfx/llms.txt). Every page has a Markdown version, and every showcase case has a result.json with its numbers, units, conditions and limits.
