REMI Lab
OPEN KNOWLEDGE / TOOLS

Automation

이 페이지의 내용

These helpers propose a mesh, domain, absorber and run length from your geometry and frequency range, and build graded cell profiles. Use them for a first setup, then read what they chose and check it with preflight. For when to grade a mesh at all, see Non-Uniform Mesh.

Planning from geometry

HelperSignatureReturns
plan_meshplan_mesh(geometry, freq_range, materials=None, accuracy="standard", *, boundary="cpml", dx_override=None, margin_override=None, n_steps_override=None, max_memory_mb=None, artifact_root=None)MeshPlan
auto_configureauto_configure(geometry, freq_range, materials=None, accuracy="standard", *, boundary="cpml", dx_override=None, margin_override=None, n_steps_override=None, max_memory_mb=None, waveform=None, thin_conductors=())SimConfig
  • geometry: a list of (shape, material_name) pairs.
  • freq_range: (f_min, f_max) in Hz. f_max sets the cell size, f_min the margin around the geometry.
  • materials: {name: {"eps_r": ..., "sigma": ...}} for every material in geometry. Pass it even for library names such as "fr4": a material the planner cannot find is treated as vacuum, and the cell comes out too coarse.
  • accuracy: "draft" (10 cells per wavelength), "standard" (20) or "high" (40). The thinnest feature can force a finer cell than that.
  • max_memory_mb: coarsen dx until the estimated memory fits.
  • thin_conductors: declared sheets. Each sheet’s plane becomes a z mesh line, so the sheet lands where you drew it.
  • A thin z feature makes the plan grade z and return a dz_profile.

plan_mesh wraps auto_configure and adds a serializable record of what it chose. Prefer it.

import numpy as np
from rfx import Box, Simulation, plan_mesh
geometry = [(Box((0.0, 0.0, 0.0), (0.02, 0.01, 0.0016)), "fr4")]
materials = {"fr4": {"eps_r": 4.4, "sigma": 0.025}}
plan = plan_mesh(geometry, freq_range=(1.5e9, 3.5e9), materials=materials,
accuracy="standard")
print(plan.to_markdown())
kwargs = plan.to_sim_kwargs() # freq_max, domain, boundary, cpml_layers, dx (+ dz_profile)
sim = Simulation(**kwargs)
print(sorted(kwargs))

MeshPlan holds the derived domain, cell_sizes, cfl, absorber, memory, grid_shape, support_checks and warnings. Export it with to_dict(), to_json() or to_markdown(). Values rfx could not determine are None, not missing. artifact_root only records intended output paths; it writes nothing.

to_sim_kwargs() gives the constructor arguments only. It does not add your geometry or move it into the new domain. Add the shapes yourself, a few cells in from the domain edges (where the absorber begins) and with thin layers aligned to the final profile’s cell edges, then run sim.preflight() and resolve what it reports. SimConfig.summary() prints the same choices as text.

sim.plan_mesh(...) is the equivalent for a simulation you have already built. It also runs preflight and can check an S-parameter calculator; see Simulation. Simulation.auto(freq_range, ...) builds a simulation from the frequency range alone, with no geometry; see Simulation.

Building graded profiles by hand

HelperSignatureWhat it does
make_band_profilemake_band_profile(edges, cell_sizes, *, max_ratio=1.4, protected=None, boundary_cell=None, min_cells=1)Builds a profile from a declared stack. Every interface in edges lands exactly on a node plane, and every adjacent ratio stays at or below max_ratio.
smooth_gradingsmooth_grading(cells, max_ratio=1.3, *, preserve_regions=None)Inserts transition cells so no adjacent ratio exceeds max_ratio.
apply_thirds_ruleapply_thirds_rule(cells, boundary_indices)Splits the cells at the given material interfaces into 1/3 + 2/3 pairs.
from rfx import apply_thirds_rule, make_band_profile, smooth_grading
# 10 mm of 1 mm air, a 1.5 mm substrate at 0.25 mm, 13.5 mm of 1 mm air.
dz = make_band_profile([0.0, 0.010, 0.0115, 0.025], [1e-3, 0.25e-3, 1e-3],
max_ratio=1.4, protected=[False, True, False])
print(len(dz), f"{dz.sum() * 1e3:.3f} mm", f"max ratio {np.max(dz[1:] / dz[:-1]):.2f}")
graded = smooth_grading([1e-3] * 4 + [0.25e-3] * 6 + [1e-3] * 4, max_ratio=1.3)
print(len(graded), f"{graded.sum() * 1e3:.3f} mm") # longer: cells were inserted

make_band_profile is the one to use when layer faces must sit on grid planes: the total length and every interface are exact. smooth_grading adds cells, so the total length and the positions after the inserted cells change. Recompute your layer coordinates from the final profile’s cumulative sum. Use max_ratio=1.4 along z and 1.3 in-plane; those are the ratios rfx has evidence for, and preflight flags larger ones.

Limits

  • The plan is a starting point, not a validation. It has not run Simulation.preflight() for geometry you add later, nor a convergence study.
  • The cell count per wavelength in accuracy is a free-space figure. Check that dielectrics still get enough cells: preflight warns below 15 per wavelength in the material.
  • On a graded mesh, a Box whose faces fall between grid planes snaps to the nearest one. Preflight reports this as graded_box_rasterization. Align layers to the profile’s cell edges.
  • Keep the grading out of the absorber: the first and last cpml_layers cells of a profile on a CPML axis should be uniform. Preflight warns with nu_grading_reaches_absorber.
Back to top ↑