Incorporation of Fabrication Constraints¶
When using inverse design with FDTDX, fabrication constraints have to be specified. The basic building block for an object optimizable by inverse design is a Device:
from fdtdx.objects.multi_material.device import Device
from fdtdx.core.physics import constants
permittivity_config = {
"Air": constants.relative_permittivity_air,
"Polymer": constants.relative_permittivity_ma_N_1400_series,
}
device_scatter = Device(
name="Device",
partial_real_shape=(1e-6, 1e-6, 1e-6),
permittivity_config=permittivity_config,
constraint_mapping=..., # <- This needs to be filled
partial_voxel_real_shape=(0.2e-6, 0.2e-6, 0.2e-6),
)
The constraint mapping, which is left empty above, specifies the mapping from continuous latent parameters to inverse permittivities used in the simulation. Note that currently only optimization of permittivitiy is implemented, but we plan to extend the inverse design capabilities to metallic materials in the very near future.
Simple example¶
At the beginning of optimization, the latent parameters of a device are always initialized randomly in the interval [0, 1]. Depending on the constraint mapping, these parameteters are mapped to inverse permittivities. Let's look at an example of a simple constraint mapping:
from fdtdx.constraints.mapping import ConstraintMapping
from fdtdx.constraints.module import (
ClosestIndex,
IndicesToInversePermittivities,
StandardToInversePermittivityRange,
)
mapping = ConstraintMapping(
modules=[
StandardToInversePermittivityRange(),
ClosestIndex(),
IndicesToInversePermittivities(),
],
)
This mapping constraints each voxel independently of the other voxels to the inverse permittivity of either air or polymer. However, often more elaborate fabrication constraints are needed in practice, which we introduce in the following sections.
Silicon Device with minimum feature constraint¶
Now let's develop a constraint mapping for silicon photonics, which restricts the minimum feature size of a device. In the example above,
from fdtdx.constraints.mapping import ConstraintMapping
from fdtdx.constraints.discrete import BrushConstraint2D, circular_brush
from fdtdx.constraints.module import (
ClosestIndex,
IndicesToInversePermittivities,
StandardToPlusOneMinusOneRange,
)
brush_diameter_in_voxels = round(100e-9 / config.resolution)
mapping = ConstraintMapping(
modules=[
StandardToPlusOneMinusOneRange(),
BrushConstraint2D(
brush=circular_brush(diameter=brush_diameter_in_voxels),
axis=2,
),
IndicesToInversePermittivities(),
]
)
This mapping does not just quantize the inverse permittivities, but also makes sure that the device adheres to a minimum feature size with regard to a specific brush. In this example, we used a circular brush of 100nm. In other words, one could "paint" the design with a brush of this size. In more detail: - StandardToPlusOneMinusOneRange(): maps the standard [0, 1] range to [-1, 1]. This is necessary, because the BrushConstraint2D expects the input to be in this range. - BrushConstraint2D(): maps the output of the previous module to permittivity indices similar to ClosestIndex() described above. However, it also makes sure that the design adheres to a minimum feature size regarding a specific brush shape. The axis argument defines the axis perpendicular to the 2D-design plane used. In our example, the perpendicular axis is 2 (in other words z/upwards). Therefore, the minimum feature constraint is enforced in the XY-plane. - IndicesToInversePermittivities(): See above.
3D Fabrication Constraints for Two-Photon-Polymerization¶
Lastly, let's look at a more involved constraint mapping used to Two-Photon Polymerization (2PP). In 2PP, a laser is focused on liquid monomer to harden the material. This allows the creation of fully three-dimensional designs.
Resulting from this fabrication technique multiple constraints arise. Firstly, basic physical knowledge tells us that no material can float in the air without a connection to the ground. In 3D-design, we have to explicitly incorporate this constraint, which was not necessary in 2D (in 2D, all voxels are always connected to the ground). Secondly, there cannot be enclosed air cavities in a design for 2PP. An enclosed cavity would trap unpolmerized monomer and destroy the structural integrity of the design. However, in practice it is often not necessary to explicitly encode this constraint in the simulation. Enclosed cavities seldomly increase a figure of merit and therefore only rarely appear in an optimized design. But, it is important to check after the simulation is finished if any enclosed cavitities exist in the design.
from fdtdx.constraints.mapping import ConstraintMapping
from fdtdx.constraints.discrete import (
BOTTOM_Z_PADDING_CONFIG_REPEAT,
BinaryMedianFilterModule,
RemoveFloatingMaterial
)
from fdtdx.constraints.module import (
ClosestIndex,
IndicesToInversePermittivities,
)
brush_diameter_in_voxels = round(100e-9 / config.resolution)
mapping = ConstraintMapping(
modules=[
StandardToInversePermittivityRange(),
ClosestIndex(),
BinaryMedianFilterModule(
kernel_sizes=(5, 5, 5),
padding_cfg=BOTTOM_Z_PADDING_CONFIG_REPEAT,
num_repeats=2,
),
RemoveFloatingMaterial(),
IndicesToInversePermittivities(),
],
)