Skip to content

Mediums

This page describes how to define mediums (material models) in Flexcompute RF (also Flex RF). The medium describes the electromagnetic properties of the material. In conjunction with Maxwell’s equations and the constitutive equations, these properties determine how EM waves propagate through and interact with the medium. Every physical structure in Flex RF is comprised of a medium and a geometry.

For lossless media, use PECMedium, Medium, or PMCMedium.

# Define lossless metal (PEC) or PMC
pec = PECMedium()
pmc = PMCMedium()
# Define lossless dielectric
my_dielectric = Medium(permittivity=4.3)

For lossy dielectrics, either use Medium with non-zero conductivity, or FastDispersionFitter.constant_loss_tangent_model() for constant loss tangent.

# Define lossy dielectric with constant conductivity (units: S/um)
my_lossy_medium = Medium(permittivity=11.9, conductivity=5e-6)
# Define lossy dielectric with constant loss tangent
my_lossy_medium2 = FastDispersionFitter.constant_loss_tangent_model(
eps_real=4.3, # Permittivity
loss_tangent=0.009, # Loss tangent (constant)
frequency_range=(f_min, f_max) # Frequency range of simulation
)

For lossy metals, typically use LossyMetalMedium.

copper = LossyMetalMedium(
conductivity=58, # Conductivity, S/um
frequency_range=(f_min, f_max) # Frequency range of simulation
)

The LossyMetalMedium implements a surface impedance boundary condition (SIBC). This means that the EM fields are only solved at the surface of the metal and not in its interior.

The RF material library is accessible from rf_material_library.

# Load the RF material library
mat_lib = rf_material_library
# Print names of all available materials
print(mat_lib.keys())
# Print a summary of a material
mat_lib['Annealed_Copper']

A material can contain one or more variants, which are listed in the material summary. To access a particular variant, use the variant name as a dictionary key. You can also use the medium attribute to access the default variant.

# Print all variant names
print(mat_lib['RO3003'].variants.keys())
# Use a particular variant of a material
ro3003_design = mat_lib['RO3003']['design']
# Use the default variant of a material
copper = mat_lib['Annealed_Copper'].medium

For certain lossy materials you can also specify a custom fitting frequency range.

# Use a specific frequency range for fitting
rt5880 = mat_lib['RT_duroid5880'].medium_in_range(frequency_range=(f_min, f_max))

Use the roughness parameter of LossyMetalMedium to specify a surface roughness model.

# Specify metal surface roughness
roughness_model = HammerstadSurfaceRoughness(rq=1.2)
my_rough_metal = LossyMetalMedium(
conductivity=58,
frequency_range=(f_min, f_max),
roughness=roughness_model
)

The available surface roughness models include the HammerstadSurfaceRoughness and HuraySurfaceRoughness models. Please refer to their respective API reference page for details.

An anisotropic medium has different EM properties depending on the direction of field propagation. Its relative permittivity is thus specified in the form of a 3x3 tensor.

For diagonally anisotropic mediums, use AnisotropicMedium.

# Specify mediums for each diagonal component
medium_xx = Medium(permittivity=4.0)
medium_yy = Medium(permittivity=4.1)
medium_zz = Medium(permittivity=3.9)
# Construct the diagonally anisotropic medium
my_anisotropic_medium = AnisotropicMedium(xx=medium_xx, yy=medium_yy, zz=medium_zz)

The AnisotropicMedium supports dispersive media along the diagonal components. Subpixel averaging is also natively supported.

To specify all 9 components of the tensor independently, use the FullyAnisotropicMedium:

# Specify the full 3x3 tensors
perm = [[2, 0, 0], [0, 1, 0], [0, 0, 3]]
cond = [[0.1, 0, 0], [0, 0, 0], [0, 0, 0]]
# Construct the anisotropic medium from the tensors
my_anisotropic_medium = FullyAnisotropicMedium(permittivity=perm, conductivity=cond)

Currently, FullyAnisotropicMedium only supports non-dispersive media and does not support subpixel averaging.

The CustomMedium class is used to define a spatially-varying non-dispersive medium. The spatial distribution of the EM property is defined using the SpatialDataArray class. Below, we define an example spherical profile n(r)=2(r/R)2n(r) = \sqrt{2-(r/R)^2} as in a Luneburg lens.

# Define spatial grid
R = 20
Nx, Ny, Nz = 100, 100, 100
X = np.linspace(-R, R, Nx)
Y = np.linspace(-R, R, Ny)
Z = np.linspace(-R, R, Nz)
Xg, Yg, Zg = np.meshgrid(X, Y, Z, indexing='ij')
rg = np.sqrt(Xg**2 + Yg**2 + Zg**2)
# Refractive index n profile
n_profile = np.ones((Nx, Ny, Nz))
n_profile[rg <= R] = np.sqrt(2-(rg[rg<=R]/R)**2)
# Define SpatialDataArray object
n_data = SpatialDataArray(n_profile, coords=dict(x=X, y=Y, z=Z))
# Define CustomMedium
my_custom_medium = CustomMedium.from_nk(n_data)

CustomAnisotropicMedium and CustomPoleResidue implement similar spatially varying behavior but for anisotropic and dispersive media, respectively.