Geometry-Level Layout API Reference

Units

DeviceLayout.set_unit_preference!Function
set_unit_preference!(pref::String; local_only=true)

Set the unit preference. pref must be one of "NoUnits", "PreferMicrons", or "PreferNanometers".

If local_only is true, add the preference to LocalPreferences.toml. Otherwise, add it to Project.toml.

Because this preference is used at compile time, Julia must be restarted for a change to take effect.

source
DeviceLayout.PreferNanometers.UPREFERREDConstant
const PreferNanometers.UPREFERRED = nm

Constant for DeviceLayout.jl compiled with units = "PreferNanometers" in LocalPreferences.toml.

Default value if no preference specified. Other options are PreferMicrons and NoUnits.

source
DeviceLayout.PreferMicrons.UPREFERREDConstant
const PreferMicrons.UPREFERRED = μm

Constant for DeviceLayout.jl compiled with units = "PreferMicrons" in LocalPreferences.toml.

Other options are PreferNanometers (the default) and NoUnits.

source
DeviceLayout.PreferNoUnits.UPREFERREDConstant
const UPREFERRED = Unitful.NoUnits

Constant for DeviceLayout.jl compiled with units = "NoUnits" in LocalPreferences.toml.

Other options are PreferNanometers (the default) and PreferMicrons.

source

Points

DeviceLayout.PointTypesType
PointTypes = Union{Real, DimensionlessQuantity, Length, InverseLength}

Allowed type variables for Point{T} types.

source
DeviceLayout.Points.lowerleftMethod
lowerleft{T}(A::AbstractArray{Point{T}})

Return the lower-left Point of the smallest bounding rectangle (with sides parallel to the x- and y-axes) that contains all points in A.

Example:

julia> lowerleft([Point(2, 0), Point(1, 1), Point(0, 2), Point(-1, 3)])
2-element Point{Int64} with indices SOneTo(2):
 -1
  0
source
DeviceLayout.Points.upperrightMethod
upperright{T}(A::AbstractArray{Point{T}})

Return the upper-right Point of the smallest bounding rectangle (with sides parallel to the x- and y-axes) that contains all points in A.

Example:

julia> upperright([Point(2, 0), Point(1, 1), Point(0, 2), Point(-1, 3)])
2-element Point{Int64} with indices SOneTo(2):
 2
 3
source

AbstractGeometry

DeviceLayout.AbstractGeometryType
AbstractGeometry{S <: Coordinate}

Abstract supertype for things that have a geometric representation.

Abstract subtypes include GeometryStructure, GeometryEntity, and GeometryReference. Provides an interface for coordinate transformations and bounding boxes.

source
DeviceLayout.coordinatetypeFunction
coordinatetype(::Type{S}) where {T, S <: AbstractGeometry{T}}
coordinatetype(S) where {T, S <: AbstractGeometry{T}}

Return the coordinate type of the geometry.

source
DeviceLayout.boundsMethod
bounds(geo::AbstractGeometry)
bounds(geo0::AbstractGeometry, geo1::AbstractGeometry, geo::AbstractGeometry...)
bounds(geos)

Return the minimum bounding Rectangle for geo or a collection/iterator geos.

If geo is empty or has no extent, a rectangle with zero width and height is returned.

For a collection or a structure that may contain multiple entities and references to other structures, geometries with bounds having zero width and height are excluded from the calculation.

source
DeviceLayout.centerMethod
center(geo::AbstractGeometry)
center(geos)

Return the center of the bounding rectangle bounds(geo) or bounds(geos). Note that this point doesn't have to be in ent.

Will not throw an InexactError even if geo has integer coordinates, but instead return floating point coordinates.

See also: lowerleft, upperright.

source
DeviceLayout.footprintFunction
footprint(geo::AbstractGeometry)
footprint(geos)

Return the footprint of geo.

By default, this falls back to bounds(geo), but it may be any single GeometryEntity fully containing geo.

The footprint of a collection or iterator geos is bounds(geos).

source
DeviceLayout.Points.lowerleftMethod
lowerleft(ent::AbstractGeometry)
lowerleft(ents)

Return the lower-left-most corner of a rectangle bounding ent or ents. Note that this point doesn't have to be in ent.

For iterable ents, entities with bounding rectangles of zero width and height will be excluded.

source
DeviceLayout.Points.upperrightMethod
upperright(ent::AbstractGeometry)
upperright(ents)

Return the upper-right-most corner of a rectangle bounding ent or ents. Note that this point doesn't have to be in ent.

For iterable ents, entities with bounding rectangles of zero width and height will be excluded.

source
DeviceLayout.transformFunction
transform(geom::AbstractGeometry, f::Transformation)
transform(
    geom::AbstractGeometry{S};
    origin=zero(Point{S}),
    rot=0°,
    xrefl=false,
    mag=1
)

Return a new AbstractGeometry obtained by applying f to geom.

For generic geom and transformation, attempts to decompose f into a scaled isometry: translate ∘ magnify ∘ rotate ∘ reflect_across_xaxis. In that case, if f does not preserve angles, a DomainError will be thrown.

A concrete subtype of AbstractGeometry must implement

transform(ent::MyEntity, f::Transformation)

It is not, however, required that an arbitrary Transformation be valid on MyEntity. For example, one might write

transform(ent::MyEntity, f::Transformation) = transform(ent, ScaledIsometry(f))
function transform(ent::MyEntity, f::ScaledIsometry)
    # ... create and return transformed entity
end

which will throw a DomainError if !preserves_angles(f) (f is not a scaled isometry).

source

GeometryEntity

DeviceLayout.GeometryEntityType
GeometryEntity{T <: Coordinate}

A geometric entity that can be placed in a coordinate system.

New concrete GeometryEntity subtypes must implement the following:

to_polygons(::MyEntity)
transform(ent::MyEntity, f)

A subtype may also implement specialized transformations like transform(::MyEntity, ::ScaledIsometry), for example if special handling is possible for angle-preserving transformations, as well as specializations for

magnify
rotate
rotate90
reflect_across_xaxis
translate

which otherwise construct the corresponding ScaledIsometry and call transform.

New subtypes may also implement

footprint
halo
lowerleft
upperright

if there are better ways to calculate these than with to_polygons (the default), which may be slow and expensive. The bounding rectangle returned by bounds is derived from lowerleft and upperright. By default, halo is derived from footprint and offset.

New subtypes may also implement any application functions required for valid styles. Not all styles need be valid for any given entity type.

source
DeviceLayout.to_polygonsFunction
to_polygons(ent::GeometryEntity; kwargs...)

Return a single polygon, an iterator, or Vector of Polygons equivalent to ent.

If ent is a StyledEntity, all styles will be applied before conversion to polygons.

source
DeviceLayout.haloMethod
halo(ent::GeometryEntity{T}, outer_delta, inner_delta=nothing)

Return the "halo" of ent using an offset of outer_delta.

By default, the halo is a vector containing offset(footprint(ent), outer_delta), but it may contain any number of GeometryEntitys that together fully cover ent with a margin of outer_delta. It is not guaranteed to cover footprint(ent).

If inner_delta is provided, then the offset at inner_delta is subtracted from the result.

A GeometryEntity should implement a specialized halo if there is an efficient non-Polygon representation of the halo. If it does not, then by default offset will be used, which first resolves the entity into Polygons using to_polygons.

source

Entity Styles

DeviceLayout.GeometryEntityStyleType
abstract type GeometryEntityStyle

A style that can be used with a GeometryEntity to create a modified entity.

May use (sty::MyStyle)(ent), styled(ent, sty), or MyStyle(ent, style_args...; style_kwargs...) to create a StyledEntity.

A GeometryEntityStyle should implement to_polygons(::MyEntity, ::MyStyle; kwargs...) for any entity type it can be applied to. As a fallback, it can implement to_polygons(::Polygon, ::MyStyle; kwargs...), in which case entities will be converted to polygons before applying the style.

Unless implemented by the style, lowerleft and upperright (and hence bounds) of a styled entity will use the underlying entity's bounds. Similarly, footprint and halo will fall back to using the underlying entity. Exceptions include the NoRender style, in which case the entity is treated as a zero-area Rectangle (ignored in collective bounds calculations), as well as OptionalStyle, in which case the default style is used (in case it has special behavior).

source
DeviceLayout.StyledEntityType
StyledEntity{T, U <: GeometryEntity{T}, S <: GeometryEntityStyle} <: GeometryEntity

GeometryEntity composing another GeometryEntity with a GeometryEntityStyle.

The use of a StyledEntity allows the composition of operations like rounding on geometric entities without committing to a particular representation of those entities.

source
DeviceLayout.unstyledFunction
unstyled(styled_ent::StyledEntity)

Return the unstyled entity referenced by styled_ent.

If styled_ent.ent is itself a StyledEntity, apply unstyled recursively until the original plain GeometyEntity is found.

source
DeviceLayout.unstyled_typeFunction
unstyled_type(::GeometryEntity)
unstyled_type(::Type{GeometryEntity})

Return the type of the unstyled entity beneath all styles.

source
DeviceLayout.PlainType
Plain <: GeometryEntityStyle

Plain style. Does not affect rendering of the styled entity.

source
DeviceLayout.MeshSizedType
struct MeshSized{T, S} <: GeometryEntityStyle where {T, S <: Real}
    h::T
    α::S
end

Style that annotates a GeometryEntity with a mesh size to use in SolidModel rendering. The generated mesh will include a size field defined as:

$s = h * max(s_g, (d/h)^α)$

where $s$ is the mesh size, $d$ is the distance away from the styled entity, $s_g$ is the global mesh scale parameter specified in DeviceLayout.SolidModels.mesh_scale, and h and α are the parameters provided. A smaller value of h will give a finer mesh attached to the styled entity, and a larger value of α will give a more rapid increase in size away from the styled entity.

If α < 0, the resulting size field will use DeviceLayout.SolidModels.mesh_grading_default. It is generally recommended to use this global value in most scenarios, as it provides a helpful mechanism for global mesh modification.

Each MeshSized entity generates a corresponding set of DeviceLayout.SolidModels.mesh_control_points during the call to DeviceLayout.SolidModels.render! along the perimeter of the styled entity. Controlling the mesh only at the edges of entities, rather than within the interior, ensures that geometric entities are resolved whilst avoiding overrefinement in surface regions which can be reasonably achieved through adaptive mesh refinement. Increasing resolution of edges of entities can be achieved through reducing the value of h on the particular entity or $s_g$ to affect all entities globally.

For the set of all DeviceLayout.SolidModels.mesh_control_points computed, a corresponding mesh size will be computed, and the resulting mesh size is then the minimum over all of these values

$s(x) = \min_{x_p ∈ X_p} h_p \max(s_g, \frac{\| x - x_p \|_2}{h_p}^{α_p})$

where $s(x)$ explicitly expresses that the size is a function of position $x$, the $p$ subscript denotes parameters associated to a single control $x_p$ from the $X_p$ of all control points. Reducing $h_p$ will result in a finer mesh next to an entity which will then grow as a function of distance from the control point $x_p$. In the implementation a KDTree ordering per (h,α) pair is used to ensure the reduction over $X_p$ is highly efficient.

See also meshsized_entity.

Associated methods:

source
DeviceLayout.meshsized_entityFunction
meshsized_entity(ent::GeometryEntity, h::T, α::S=-1.0) where {T, S <: Real}

Create a MeshSized entity, specifying a mesh size use in SolidModel rendering. The generated mesh will include a size field defined as:

mesh size = h * max(s_g, (d/h)^α)

where d is the distance away from the styled entity, and s_g is the global mesh scale parameter specified in DeviceLayout.SolidModels.mesh_scale. A smaller value of h will give a finer mesh attached to the styled entity, and a larger value of α will give a more rapid increase in size away from the styled entity.

If α < 0, the size field will use DeviceLayout.SolidModels.mesh_grading_default used in rendering.

source
DeviceLayout.NoRenderType
NoRender <: GeometryEntityStyle

Style that marks an entity to be skipped when rendering.

NoRender-styled entities have zero-area bounds and footprint and empty halo.

source
DeviceLayout.OptionalStyleType
struct OptionalStyle <: GeometryEntityStyle
    true_style::GeometryEntityStyle
    false_style::GeometryEntityStyle
    flag::Symbol
    default::Bool
end
OptionalStyle(true_style::GeometryEntityStyle, flag::Symbol;
    false_style::GeometryEntityStyle=Plain(), default::Bool=true)

Style that depends on a Boolean rendering option flag with default default.

lowerleft, upperright, bounds, footprint, and halo are forwarded to the underlying entity styled with the default style.

Examples

sty = OptionalStyle(Rounded(1μm), :rounding)
p = Rectangle(4μm, 4μm)
rounded_rect = to_polygons(sty(p))
plain_rect = to_polygons(sty(p), rounding=false)
source
DeviceLayout.optional_entityFunction
optional_entity(ent::GeometryEntity, flag::Symbol;
    true_style::GeometryEntityStyle=Plain(), default=true)

Return an entity to be rendered or not based on the rendering option flag.

Example

julia> c = Cell();

julia> ent = optional_entity(Rectangle(2, 2), :optional_entities; default=false);

julia> render!(c, ent);

julia> length(elements(c))
0

julia> render!(c, ent; optional_entities=true);

julia> length(elements(c))
1
source
DeviceLayout.ToToleranceType
struct ToTolerance{T<:Coordinate} <: GeometryEntityStyle
    atol::T
end

Style for rendering an entity to absolute tolerance atol.

Equivalent to passing or overriding the keyword atol when rendering this entity.

source

GeometryStructure

DeviceLayout.elementsMethod
elements(s::GeometryStructure)

Return a vector of GeometryEntity in the structure.

For a Cell, these are Polygons. For a CoordinateSystem, these can be any GeometryEntity.

source
DeviceLayout.flattenMethod
flatten(c::GeometryStructure; depth::Integer=-1, name=uniquename("flatten_"*name(c)))

Return a new coordinate system with name name with recursively flattened references and arrays up to a hierarchical depth.

Flattening a CoordinateSystem or Cell produces a coordinate system of the same type (meaning these can also be flattened in-place with flatten!), while flattening other structures generally produces a CoordinateSystem with the same coordinate type.

Flattening adds the elements of references to the top-level structure with appropriate transformations, then discards those references. Deeper references and arrays are brought upwards and are not discarded.

This function has no effect on references for depth == 0, and unlimited depth by default.

source
Base.getindexMethod
getindex(c::GeometryStructure, nom::AbstractString, index::Integer=1)

If c references a structure with name nom, this method will return the corresponding GeometryReference. If there are several references to that coordinate system, then index specifies which one is returned (in the order they are found in refs(c)). e.g. to specify an index of 2: myCS["myreferencedCS",2].

source
DeviceLayout.map_metadataFunction
function map_metadata(geom::GeometryStructure, map_meta)

Create a copy of geom and change original metadata m to map_meta(m) for all elements.

Recursive on the copies of referenced structures.

source
DeviceLayout.map_metadata!Function
function map_metadata!(geom::GeometryStructure, map_meta, [visited])

For every element in geom with original meta m, set its metadata to map_meta(m).

Operates on all unique structures in the reference hierarchy exactly once, so that multiply-referenced structures are not mapped multiple times.

The visited argument is used internally to track structures already processed.

source
function map_metadata(comp::AbstractComponent, map_meta)

For every element in geometry(comp) with original meta m, set its metadata to map_meta(m).

Recursive on referenced structures.

source
DeviceLayout.reset_uniquename!Function
reset_uniquename!(counter=GLOBAL_NAME_COUNTER)

Reset uniquename counters for all strings.

counter is the Dict{String,Int} that counts how many times each name has been seen. The default is the same default global counter used by uniquename.

source
reset_uniquename!(str::String, counter=GLOBAL_NAME_COUNTER)

Reset uniquename counter for str.

counter is the Dict{String,Int} that counts how many times each name has been seen. The default is the same default global counter used by uniquename.

source
DeviceLayout.uniquenameFunction
uniquename(str, dlm="\$"; modify_first=false, counter=GLOBAL_NAME_COUNTER, case_sensitive=true)

Given string input str for the nth time, return str * dlm * string(n).

If str is already formatted as str0 * dlm * n, where n is an integer, then str0 will be used with the larger of n and the number of times str0 has been counted plus one.

If modify_first is false, then str will be returned the first time uniquename(str, dlm; modify_first=false) is called.

Useful if programmatically making Cells and all of them will eventually be saved into a GDSII file.

The uniqueness is expected on a per-Julia session basis or until reset_uniquename! is called, so if you load an existing GDSII file and try to save unique cells on top of that you may get an unlucky clash. Calling uniquename on all loaded Cell names will effectively "register" them, making subsequent uniquename calls aware of them.

If case_sensitive is false, counter keys are lowercased so that e.g. "Main" and "main" are treated as duplicates. The original case of str is preserved in the output.

Example

julia> reset_uniquename!();

julia> uniquename("name"; modify_first=true)
"name\$1"

julia> uniquename("name\$4")
"name\$4"

julia> uniquename("name\$3")
"name\$5"

julia> uniquename("name")
"name\$6"

counter is the Dict{String,Int} that counts how many times each name has been seen. The default is a global counter that persists until the end of the Julia session or until reset_uniquename! is called.

source

GeometryReference

DeviceLayout.GeometryReferenceType
GeometryReference{S<:Coordinate, T<:GeometryStructure} <: AbstractGeometry{S}

Abstract supertype for references to geometry structures.

Subtypes are StructureReference and ArrayReference.

source
DeviceLayout.StructureReferenceType
mutable struct StructureReference{S, T} <: GeometryReference{S, T}
    structure::T
    origin::Point{S}
    xrefl::Bool
    mag::Float64
    rot::Float64
end

Reference to a structure positioned at origin, with optional x-reflection xrefl, magnification factor mag, and rotation angle rot. If an angle is given without units it is assumed to be in radians.

That is, the transformation applied by the reference is the composition of the following transformations, ordered with reflection applied first:

  1. If xrefl(f) is true, a reflection across the x-axis
  2. Rotation by rotation(f)
  3. Magnification by mag(f)
  4. Translation by origin(f)

The type variable T is to avoid circular definitions.

source
DeviceLayout.ArrayReferenceType
mutable struct ArrayReference{S,T} <: GeometryReference{S,T}
    structure::T
    origin::Point{S}
    deltacol::Point{S}
    deltarow::Point{S}
    col::Int
    row::Int
    xrefl::Bool
    mag::Float64
    rot::Float64
end

Array of structure starting at origin with row rows and col columns, spanned by vectors deltacol and deltarow. Optional x-reflection xrefl, magnification factor mag, and rotation angle rot for the array as a whole. If an angle is given without units it is assumed to be in radians.

The type variable T is to avoid circular definitions.

source
Base.copyMethod
copy(x::GeometryReference)

Creates a shallow copy of x (does not copy the referenced structure).

source
Base.getindexMethod
getindex(c::GeometryReference, nom::AbstractString, index::Integer=1)

If the structure referenced by c references a structure with name nom, this method will return the corresponding GeometryReference. If there are several references to that structure, then index specifies which one is returned (in the order they are found in refs(structure(c))).

This method is typically used so that we can type the first line instead of the second line in the following:

myCS["myreferencedCS"]["onedeeper"]
myCS["myreferencedCS"].structure["onedeeper"]
source
DeviceLayout.arefFunction
aref(x::GeometryStructure{S}, origin::Point{T}=zero(Point{S}); kwargs...) where
    {S <: Coordinate, T <: Coordinate}

Construct a ArrayReference{float(T),typeof(x)} object.

Keyword arguments specify the column vector, row vector, number of columns, number of rows, x-reflection, magnification factor, and rotation.

Synonyms are accepted for these keywords:

  • Column vector dc::Point{T}: :deltacol, :dcol, :dc, :vcol, :colv, :colvec, :colvector, :columnv, :columnvec, :columnvector
  • Row vector: :deltarow, :drow, :dr, :vrow, :rv, :rowvec, :rowvector
  • Number of columns: :nc, :numcols, :numcol, :ncols, :ncol
  • Number of rows: :nr, :numrows, :numrow, :nrows, :nrow
  • X-reflection: :xrefl, :xreflection, :refl, :reflect, :xreflect, :xmirror, :mirror
  • Magnification: :mag, :magnification, :magnify, :zoom, :scale
  • Rotation: :rot, :rotation, :rotate, :angle
source
aref(x, c::AbstractRange, r::AbstractRange; kwargs...)

Construct an ArrayReference based on ranges (probably LinSpace or FloatRange). c specifies column coordinates and r for the rows. Pairs from c and r specify the origins of the repeated cells. The extrema of the ranges therefore do not specify the extrema of the resulting ArrayReference's bounding box; some care is required.

Keyword arguments specify x-reflection, magnification factor, and rotation, with synonyms allowed:

  • X-reflection: :xrefl, :xreflection, :refl, :reflect, :xreflect, :xmirror, :mirror
  • Magnification: :mag, :magnification, :magnify, :zoom, :scale
  • Rotation: :rot, :rotation, :rotate, :angle
source
DeviceLayout.flattenMethod
flatten(c::GeometryReference; depth::Integer=-1, name=uniquename("flatten_"*name(structure(c))), metadata_filter=nothing)

Return a new structure with name name with recursively flattened references and arrays up to a hierarchical depth.

Flattening adds the elements of references to the top-level coordinate system with appropriate transformations, then discards those references. Deeper references and arrays are brought upwards and are not discarded. If depth=0, a new coordinate system is returned containing only the reference.

metadata_filter can be a function that takes a DeviceLayout.Meta and returns a Bool, like a function returned by layer_inclusion. In that case, only elements whose metadata m have metadata_filter(m) == true will be retained while flattening. Elements of deeper references and arrays are not filtered.

The reference c remains unmodified.

source
DeviceLayout.flat_elementsFunction
flat_elements(geom::Union{GeometryStructure,GeometryReference}, only_layers=[], ignore_layers=[])
flat_elements(geom_layer::Pair{<:Union{GeometryStructure,GeometryReference}})

Return a list of GeometryEntity elements in flatten(cs), optionally filtering metadata.

only_layers and ignore_layers can be layer name Symbols, DeviceLayout.Meta, or collections of either. The metadata filtering function is produced using layer_inclusion(only_layers, ignore_layers). This means that the default empty only_layers is the same as listing all layers.

Using an argument pair geom => layer is equivalent to flat_elements(geom, layer).

source
DeviceLayout.layer_inclusionFunction
layer_inclusion(only_layers, ignore_layers)

Return a function f(m::Meta) that returns a Bool based on inclusion/exclusion rules.

Both only_layers and ignore_layers are DeviceLayout.Meta, layer name Symbols, and/or collections of either.

If only_layers is empty, then only ignore_layers is used, and f(m) checks that neither m nor layer(m) is in ignore_layers. Otherwise, f(m) also checks that m or layer(m) is in only_layers.

source
DeviceLayout.srefFunction
sref(x::GeometryStructure{T}, origin=zero(Point{T}); kwargs...)

Convenience constructor for StructureReference{float(T), typeof(x)}.

Synonyms are accepted for these keywords:

- X-reflection: `:xrefl`, `:xreflection`, `:refl`, `:reflect`, `:xreflect`,
`:xmirror`, `:mirror`
- Magnification: `:mag`, `:magnification`, `:magnify`, `:zoom`, `:scale`
- Rotation: `:rot`, `:rotation`, `:rotate`, `:angle`
source
DeviceLayout.transformationMethod
transformation(c::GeometryReference)

Return the angle-preserving transformation to be applied to the referenced structure.

source
DeviceLayout.transformationMethod
transformation(c::GeometryStructure, d::GeometryReference)

Given a GeometryStructure c containing GeometryReference d in its tree of references, this function returns a Transformations.ScaledIsometry object that lets you translate from the coordinate system of d to the coordinate system of c.

If the same exact GeometryReference (as in ===, same address in memory) is included multiple times in the tree of references, then the resulting transform will be based on the first time it is encountered. The tree is traversed using a depth-first search (but checking all references of a structure before looking inside each reference).

Example: You want to translate (2.0,3.0) in the coordinate system of the referenced coordinate system d to the coordinate system of c:

julia> trans = transformation(c,d)

julia> trans(Point(2.0,3.0))
source
DeviceLayout.transformationMethod
transformation(c::GeometryStructure, d::GeometryReference, e::GeometryReference, f::GeometryReference...)

Given a geometry structure c containing GeometryReference last(f) in its tree of references, this function returns a Transformations.ScaledIsometry object that lets you translate from the coordinate system of last(f) to the coordinate system of c. This method is needed when you want to specify intermediate GeometryReferences explicitly.

For example, suppose for instance you have a hierarchy of coordinate systems, where coordinate system A references B1 and B2, which both reference C. Schematically, it might look like this:

a -- b1 -- c
  \      /
   \ b2 /

Coordinate system C appears in two places inside coordinate system A, owing to the fact that it is referenced by both B1 and B2. If you need to get the coordinate system of C via B2, then you need to do transformation(coordinatesystemA, coordsysrefB2, coordsysrefC), rather than simply transform(coordinatesystemA, coordsysrefC), because the latter will just take the first path to C available, via B1.

source
DeviceLayout.Transformations.originMethod
origin(ref::GeometryReference)

The origin of the structure that ref points to, in ref's parent coordinate system.

Equivalently, the translation part of transformation(ref) (the transformation that ref would apply to structure(ref)).

source
DeviceLayout.Transformations.rotationMethod
rotation(ref::GeometryReference; α0=0)

The change in angle when applying transformation(ref) to a line originally at α0 CCW from the x-axis.

Equivalent to rotation(transformation(ref); α0=α0).

source

Transformations

CoordinateTransformations.composeFunction
compose(trans1, trans2)
trans1 ∘ trans2

Take two transformations and create a new transformation that is equivalent to successively applying trans2 to the coordinate, and then trans1. By default will create a ComposedTransformation, however this method can be overloaded for efficiency (e.g. two affine transformations naturally compose to a single affine transformation).

source
CoordinateTransformations.TranslationType
Translation(v) <: AbstractAffineMap
Translation(dx, dy)         # 2D
Translation(dx, dy, dz)     # 3D

Construct the Translation transformation for translating Cartesian points by an offset v = (dx, dy, ...)

source
DeviceLayout.Transformations.ReflectionFunction
Reflection(α; through_pt=nothing)
Reflection(vec::Point; through_pt=nothing)
Reflection(p1::Point, p2::Point)

Construct a reflection across a line.

The line can be specified by two points p1, p2 or by a direction and point through_pt the line passes through. The direction can be a vector or an angle made with the positive x axis (units accepted; no units => radians), and the through_pt is the origin by default.

source
DeviceLayout.Transformations.XReflectionFunction
XReflection()

Construct a reflection about the x-axis (y-coordinate changes sign).

Example:

julia> trans = XReflection()
LinearMap([1 0; 0 -1])

julia> trans(Point(1, 1))
2-element Point{Int64} with indices SOneTo(2):
  1
 -1
source
DeviceLayout.Transformations.YReflectionFunction
YReflection()

Construct a reflection about the y-axis (x-coordinate changes sign).

Example:

julia> trans = YReflection()
LinearMap([-1 0; 0 1])

julia> trans(Point(1, 1))
2-element Point{Int64} with indices SOneTo(2):
 -1
  1
source
DeviceLayout.Transformations.RotationPiFunction
RotationPi(Θ_over_pi=1; around_pt=nothing)

Construct a rotation about the origin or around_pt, with rotation in units of pi (180°).

This may be useful if you know your rotation will be a multiple of 90° but not necessarily which one, since it can be slightly more precise than Rotation (as sincospi is to sincos).

source
DeviceLayout.Transformations.ScaledIsometryType
struct ScaledIsometry{T<:Union{Point, Nothing}} <: AbstractAffineMap
ScaledIsometry(origin=nothing, rotation=0°, xrefl=false, mag=1.0)

A coordinate transformation that preserves angles.

The equivalent transformation of f::ScaledIsometry is the composition of the following transformations, ordered with reflection applied first:

  1. If xrefl(f) is true, a reflection across the x-axis
  2. Rotation by rotation(f)
  3. Magnification by mag(f)
  4. Translation by origin(f)

May be also be constructed as

ScaledIsometry(f::Transformation) = ScaledIsometry(origin(f), rotation(f), xrefl(f), mag(f))

but a DomainError will be thrown if f is not a scaled isometry (does not preserve angles).

Transformation compositions (with compose or ) involving a ScaledIsometry will return a ScaledIsometry if the other transformation also preserves angles.

source
DeviceLayout.centeredFunction
centered(ent::AbstractGeometry; on_pt=zero(Point{T}))

Centers a copy of ent on on_pt, with promoted coordinates if necessary. This function will not throw an InexactError(), even if ent had integer coordinates.

source
DeviceLayout.magnifyFunction
magnify(geom, mag)

Returns a copy of geom magnified by a factor of mag.

The origin is the center of magnification.

source
DeviceLayout.reflect_across_lineFunction
reflect_across_line(geom, dir; through_pt=nothing)
reflect_across_line(geom, p0, p1)

Return a copy of geom reflected across a line.

The line is specified through two points p0 and p1 that it passes through, or by a direction dir (vector or angle made with the x-axis) and a point through_pt that it passes through.

source
DeviceLayout.rotateFunction
rotate(ent, rot)

Return a copy of geom rotated counterclockwise by rot around the origin.

Units are accepted (no units => radians).

source
Base.:+Method
+(ent::AbstractGeometry, p::Point)
+(p::Point, ent::AbstractGeometry)

Translate an entity by p.

source
Base.:-Method
-(ent::AbstractGeometry, p::Point)

Translate an entity by -p.

source
Base.:*Method
*(ent::AbstractGeometry, a::Real)
*(a::Real, ent::AbstractGeometry)

Magnify an entity by a.

source
Base.:/Method
/(ent::AbstractGeometry, a::Real)

Magnify an entity by inv(a).

source
DeviceLayout.Transformations.magFunction
mag(f::Translation)

Return the magnification (uniform scaling factor) for f, if it is well defined.

Throws a DomainError if f does not preserve angles ("scaling" depends on direction).

source
mag(ref::GeometryReference)

The magnification (uniform scaling factor) applied by transformation(ref).

source
DeviceLayout.Transformations.originFunction
origin(f::Transformation)

Return the transformed origin if it is translated, or nothing otherwise.

It's necessary to return nothing rather than a zero(Point{T}) if there's no translation, because such transformations (e.g., LinearMaps) may not supply a coordinate type T.

source
origin(ref::GeometryReference)

The origin of the structure that ref points to, in ref's parent coordinate system.

Equivalently, the translation part of transformation(ref) (the transformation that ref would apply to structure(ref)).

source
origin(sch::Schematic, node::ComponentNode)
origin(sch::Schematic, node_idx::Int)

The origin of node in the global coordinate system of sch.

source
DeviceLayout.Transformations.preserves_anglesFunction
preserves_angles(f::Transformation)

Return true if f is angle-preserving (has equal-magnitude eigenvalues) and false otherwise.

Uses approximate equality to allow for floating point imprecision.

source
DeviceLayout.Transformations.rotationFunction
rotation(f::Transformation; α0=0)

Return the change in angle when applying f to a line originally at α0 CCW from the x-axis.

By default, α0 is taken to be 0, and the result is equivalent to the rotation when decomposing the linear part of f into reflection across the x-axis followed by rotation.

Units are accepted for α0 (no units => radians).

If f does not preserve angles, a DomainError is thrown.

source
rotation(ref::GeometryReference; α0=0)

The change in angle when applying transformation(ref) to a line originally at α0 CCW from the x-axis.

Equivalent to rotation(transformation(ref); α0=α0).

source
DeviceLayout.Transformations.rounding_safeFunction
rounding_safe(precision, f::Transformation)

true when applying f gives the same results before or after rounding to precision.

Specifically, if f preserves angles, translates by integer precision, scales by an integer multiplier, and rotates by a multiple of 90°, it is "rounding safe".

precision should either be an integer type like Int32 or unitful type like typeof(1nm).

source
DeviceLayout.Transformations.xreflFunction
xrefl(f::Transformation)

Return true if f applies a reflection (has negative determinant) and false otherwise.

source
xrefl(ref::GeometryReference)

A Bool indicating whether transformation(ref) includes a reflection.

source

Alignment

DeviceLayout.Align.aboveFunction
above(source, target; offset=0, centered=false)

Align a copy of source with its bounding box bottom aligned with the top of target's.

source
DeviceLayout.Align.belowFunction
below(source, target; offset=0, centered=false)

Align a copy of source with its bounding box top aligned with the bottom of target's.

source
DeviceLayout.Align.leftofFunction
leftof(source, target; offset=0, centered=false)

Align a copy of source with its bounding box right side aligned on the left of target's.

source
DeviceLayout.Align.rightofFunction
rightof(source, target; offset=0, centered=false)

Align a copy of source with its bounding box left side aligned on the right of target's.

source
DeviceLayout.Align.flushbottomFunction
flushbottom(source, target; offset=0, centered=false)

Align a copy of source with its bounding box bottom flush with that of target.

source
DeviceLayout.Align.flushtopFunction
flushtop(source, target; offset=0, centered=false)

Align a copy of source with its bounding box top flush with that of target.

source
DeviceLayout.Align.flushleftFunction
flushleft(source, target; offset=0, centered=false)

Align a copy of source with its bounding box left side flush with that of target.

source
DeviceLayout.Align.flushrightFunction
flushright(source, target; offset=0, centered=false)

Align a copy of source with its bounding box right side flush with that of target.

source
DeviceLayout.Align.centered_onFunction
centered_on(source::AbstractGeometry, target::AbstractGeometry)

Centers a copy of source centered on the center of target, promoting coordinates if necessary.

source
DeviceLayout.Align.aligned_toFunction
aligned_to(source::AbstractGeometry{T}, target::AbstractGeometry{S},
           align_source::RectAlignRule, align_target::RectAlignRule;
           offset=convert(S, zero(T))) where {T,S}

Aligns a copy of source with its align_source aligned to align_target of target.

For alignment in only one coordinate, the other coordinate is left unchanged. An optional offset will further displace the result in the aligned coordinate. Coordinates will be promoted if necessary when centering.

align_source and align_target must match coordinates; that is, both must refer to the x coordinate (Align.LeftEdge, Align.RightEdge, or Align.XCenter) or both to the y coordinate (Align.TopEdge, Align.BottomEdge, or Align.YCenter).

Convenience functions (leftof, rightof, above, below, flushleft, flushright, flushtop, flushbottom) are also defined as wrappers around aligned_to with pre-specified AlignRules.

Examples

julia> Align.aligned_to(Rectangle(2, 2), Rectangle(4, 4), Align.LeftEdge(), Align.XCenter())
Rectangle{Float64}((2.0,0.0), (4.0,2.0))
source
aligned_to(source::AbstractGeometry{T}, target::AbstractGeometry{S},
    align_source::Tuple{XAlignRule, YAlignRule},
    align_target::Tuple{XAlignRule, YAlignRule};
    offset::Point = zero(Point{promote_type(S, T)})) where {T,S}

Align a copy of source to target in x and y coordinates simultaneously.

source

Polygons

DeviceLayout.AbstractPolygonType
abstract type AbstractPolygon{T} <: GeometryEntity{T} end

Anything you could call a polygon regardless of the underlying representation. Currently only Rectangle, Polygon, and ClippedPolygon are concrete subtypes, but one could imagine further subtypes to represent specific shapes that appear in highly optimized pattern formats. Examples include the OASIS format (which has 25 implementations of trapezoids) or e-beam lithography pattern files like the Raith GPF format.

source
DeviceLayout.Polygons.PolygonType
struct Polygon{T} <: AbstractPolygon{T}
    p::Vector{Point{T}}
    Polygon(x) = new(x)
    Polygon(x::AbstractPolygon) = convert(Polygon{T}, x)
end

Polygon defined by list of coordinates. The first point should not be repeated at the end (although this is true for the GDS format).

source
DeviceLayout.Rectangles.RectangleType
struct Rectangle{T} <: AbstractPolygon{T}
    ll::Point{T}
    ur::Point{T}
    function Rectangle(a,b)
        # Ensure ll is lower-left, ur is upper-right.
        ll = Point(a.<=b) .* a + Point(b.<=a) .* b
        ur = Point(a.<=b) .* b + Point(b.<=a) .* a
        new(ll,ur)
    end
end

A rectangle, defined by opposing lower-left and upper-right corner coordinates. Lower-left and upper-right are guaranteed to be such by the inner constructor.

source
DeviceLayout.boundsFunction
bounds(r::Rectangle)

No-op (just returns r).

source
bounds(geo::AbstractGeometry)
bounds(geo0::AbstractGeometry, geo1::AbstractGeometry, geo::AbstractGeometry...)
bounds(geos)

Return the minimum bounding Rectangle for geo or a collection/iterator geos.

If geo is empty or has no extent, a rectangle with zero width and height is returned.

For a collection or a structure that may contain multiple entities and references to other structures, geometries with bounds having zero width and height are excluded from the calculation.

source
bounds(s::GeometryStructure{T}) where {T <: Coordinate}

Return a Rectangle{T} bounding box around all objects in a structure or structures. Return a rectangle with zero width and height if the structures are empty.

source
bounds(ref::GeometryReference)

Return a Rectangle bounding box around all objects in ref. The bounding box respects reflection, rotation, and magnification specified by ref.

source
bounds(sch::Schematic, node::ComponentNode)
bounds(sch::Schematic, node_idx::Int)

The Rectangle bounding the component in node in the global coordinate system of sch.

source
DeviceLayout.Polygons.gridpoints_in_polygonFunction
gridpoints_in_polygon(poly::AbstractArray{<:AbstractPolygon},
    dx::Coordinate, dy::Coordinate; b=nothing)

Return a BitArray for the gridpoints in b with true for gridpoints in poly.

Only grid points in the bounding box b will be considered; if b is nothing, then bounds(poly) is used. dx and dy are the distances between adjacent points on the rectangular grid. The grid points represented by the BitArray start from the lower left point p0 = (m*dx, n*dy) with m and n integers and p0 lying in b.

All polygons should have the same orientation (clockwise or counterclockwise). A mix (for example to represent "holes") may not give the desired behavior on polygon or hole edges.

source
gridpoints_in_polygon(poly::AbstractArray{<:AbstractPolygon},
    grid_x::AbstractArray, grid_y::AbstractArray)

Return a BitArray with true for points lying in some polygon in poly.

The BitArray values correspond to points (x, y) with x ∈ grid_x, y ∈ grid_y, starting from the lower left.

All polygons should have the same orientation (clockwise or counterclockwise). A mix (for example to represent "holes") may not give the desired behavior on polygon or hole edges.

source
DeviceLayout.offsetFunction
offset{S<:Coordinate}(s::AbstractPolygon{S}, delta::Coordinate;
    j::Clipper.JoinType=Clipper.JoinTypeMiter,
    e::Clipper.EndType=Clipper.EndTypeClosedPolygon)
offset{S<:AbstractPolygon}(subject::AbstractVector{S}, delta::Coordinate;
    j::Clipper.JoinType=Clipper.JoinTypeMiter,
    e::Clipper.EndType=Clipper.EndTypeClosedPolygon)
offset{S<:Polygon}(s::AbstractVector{S}, delta::Coordinate;
    j::Clipper.JoinType=Clipper.JoinTypeMiter,
    e::Clipper.EndType=Clipper.EndTypeClosedPolygon)

Using the Clipper library and the Clipper.jl wrapper, perform polygon offsetting.

The orientations of polygons must be consistent, such that outer polygons share the same orientation, and any holes have the opposite orientation. Additionally, any holes should be contained within outer polygons; offsetting hole edges may create positive artifacts at corners.

The first argument should be an AbstractPolygon. The second argument is how much to offset the polygon. Keyword arguments include a join type:

  • Clipper.JoinTypeMiter
  • Clipper.JoinTypeRound
  • Clipper.JoinTypeSquare

and also an end type:

  • Clipper.EndTypeClosedPolygon
  • Clipper.EndTypeClosedLine
  • Clipper.EndTypeOpenSquare
  • Clipper.EndTypeOpenRound
  • Clipper.EndTypeOpenButt
source
DeviceLayout.Polygons.perimeterFunction
perimeter(poly::AbstractPolygon)

The (Euclidean) perimeter of an AbstractPolygon.

source
perimeter(poly::ClippedPolygon)

The (Euclidean) perimeter of the outermost contour of a ClippedPolygon

source
perimeter(poly::Ellipse)

Approximate (Euclidean) perimeter of an Ellipse using Ramanujan's approximation formula https://arxiv.org/pdf/math/0506384.pdf

source
DeviceLayout.Polygons.pointsFunction
points(x::Polygon)

Return the array of Point objects defining the polygon.

source
points{T}(x::Rectangle{T})

Return the array of Point objects defining the rectangle.

source
points(x::ClippedPolygon)

Return the array of Point objects that define the keyhole polygon.

source
points(x::Clipper.PolyNode)

Return the array of Point objects that make up the contour of the PolyNode

source
DeviceLayout.Polygons.sweep_polyFunction
sweep_poly(poly::Polygon, displacement::Point)

Return a Polygon corresponding to the boundary formed by poly swept by displacement.

This is the result you would get by painting with a brush shaped like poly and moving it along a line by displacement.

source
DeviceLayout.Polygons.unfoldFunction
unfold(v::Vector{Point{T}}, direction; through_pt=nothing) where {T}
unfold(v::Vector{Point{T}}, p0, p1) where {T}

Return a vector of twice the length of v, where the first half is v and the second half is v in reverse order and reflected about an axis.

This can be used to construct polygons that have a mirror symmetry. The symmetry axis can be defined in either of two ways: as a line with a given direction passing through point through_pt (defaults to origin), or by two points p0, p1. direction can be passed either as an angle or as a Point representing a vector.

As a trivial example, to draw a centered square:

uy = Point(0μm, 1μm) # could also be passed as 90°
pts = [Point(-1μm, -1μm), Point(-1μm, 1μm)]
square = Polygon(unfold(pts, uy))
source
DeviceLayout.Polygons.RoundedType
struct Rounded{T <: Coordinate} <: GeometryEntityStyle
    abs_r::T = zero(T)
    rel_r::Float64 = 0.0
    min_side_len::T = r
    min_angle::Float64 = 1e-3
    p0::Vector{Point{T}} = []
    inverse_selection::Bool = false
end

Rounded polygon style defined by either radius absolute radius abs_r or relative radius rel_r. Only one of abs_r or rel_r can be non-zero at once. Can't handle shapes with interior cuts, or shapes with too sharp of angles relative to segment length. If rel_r is non-zero the radius of curvature at each vertex is calculated with rel_r * min(l₁, l₂) where l₁ and l₂ denote the length of the two attached line segments.

Example usage:

r = Rectangle(10μm, 10μm)
rsty = Rounded(1μm)
# Create a rounded rectangle StyledEntity with different options for syntax
rounded_rect = rsty(r)
rounded_rect = styled(r, rsty)
rounded_rect = Rounded(r, 1μm)
# Turn the result into a plain Polygon
rounded_rect_discretized_poly = to_polygons(rounded_rect)

Keyword arguments

  • min_side_len: The minimum side length that will get rounded (e.g. for 90-degree angles, it makes sense to have min_side_len = 2 * rounding_radius). This currently uses exact comparison, so it may result in very short straight edges or failure to round a corner due to floating point imprecision.
  • min_angle: If adjacent sides are collinear within the tolerance set by min_angle, rounding will not be performed.
  • p0: set of target points used to select vertices to attempt to round when applied to a polygon. Selected vertices where min_side_len and min_angle are satisfied will be rounded. If empty, all vertices will be selected. Otherwise, for each point in p0, the nearest point that satisfies selection_tolerance in the styled polygon will be selected. Note that for a ClippedPolygon, the same p0 will be used for every contour; for different rounding styles on different contours, use StyleDict.
  • inverse_selection: If true, the selection from p0 is inverted; that is, all corners will be rounded except those selected by p0.
  • selection_tolerance: Selections using p0 will only be chosen if they are within selection_tolerance distance of p0. The current default of infinite reflects the legacy behaviour of always finding the closest point, and will be replaced with a small non-zero tolerance to capture floating point precision in future (approximately 1.0nm).
source

Polygon clipping

DeviceLayout.Polygons.difference2dFunction
difference2d(p1, p2)

Return the geometric union of p1 minus the geometric union of p2 as a ClippedPolygon.

Each of p1 and p2 may be a GeometryEntity or array of GeometryEntity. All entities are first converted to polygons using to_polygons.

Each of p1 and p2 can also be a GeometryStructure or GeometryReference, in which case elements(flatten(p)) will be converted to polygons.

Each can also be a pair geom => layer, where geom is a GeometryStructure or GeometryReference, while layer is a DeviceLayout.Meta, a layer name Symbol, and/or a collection of either, in which case only the elements in those layers will be used.

source
DeviceLayout.Polygons.intersect2dFunction
intersect2d(p1, p2)

Return the geometric union of p1 intersected with the geometric union of p2 as a ClippedPolygon.

Each of p1 and p2 may be a GeometryEntity or array of GeometryEntity. All entities are first converted to polygons using to_polygons.

Each of p1 and p2 can also be a GeometryStructure or GeometryReference, in which case elements(flatten(p)) will be converted to polygons.

Each can also be a pair geom => layer, where geom is a GeometryStructure or GeometryReference, while layer is a DeviceLayout.Meta, a layer name Symbol, and/or a collection of either, in which case only the elements in those layers will be used.

source
DeviceLayout.Polygons.union2dFunction
union2d(p1, p2)

Return the geometric union of p1 and p2 as a ClippedPolygon.

Each of p1 and p2 may be a GeometryEntity or array of GeometryEntity. All entities are first converted to polygons using to_polygons.

Each of p1 and p2 can also be a GeometryStructure or GeometryReference, in which case elements(flatten(p)) will be converted to polygons.

Each can also be a pair geom => layer, where geom is a GeometryStructure or GeometryReference, while layer is a DeviceLayout.Meta, a layer name Symbol, and/or a collection of either, in which case only the elements in those layers will used.

This is not implemented as a method of union because you can have a set union of arrays of polygons, which is a distinct operation.

The Clipper polyfill rule is PolyFillTypePositive, meaning as long as a region lies within more non-hole (by orientation) than hole polygons, it lies in the union.

source
union2d(p)

Return the geometric union of p or all entities in p.

source
DeviceLayout.Polygons.xor2dFunction
xor2d(p1, p2)

Return the symmetric difference (XOR) of p1 and p2 as a ClippedPolygon.

The XOR operation returns regions that are in either p1 or p2, but not in both. This is useful for finding non-overlapping regions between two sets of polygons.

Each of p1 and p2 may be a GeometryEntity or array of GeometryEntity. All entities are first converted to polygons using to_polygons.

Each of p1 and p2 can also be a GeometryStructure or GeometryReference, in which case elements(flatten(p)) will be converted to polygons.

Each can also be a pair geom => layer, where geom is a GeometryStructure or GeometryReference, while layer is a DeviceLayout.Meta, a layer name Symbol, and/or a collection of either, in which case only the elements in those layers will be used.

source
DeviceLayout.Polygons.clipFunction
clip(op::Clipper.ClipType, s, c; kwargs...) where {S<:Coordinate, T<:Coordinate}
clip(op::Clipper.ClipType, s::AbstractVector{A}, c::AbstractVector{B};
    kwargs...) where {S, T, A<:Polygon{S}, B<:Polygon{T}}
clip(op::Clipper.ClipType,
    s::AbstractVector{Polygon{T}}, c::AbstractVector{Polygon{T}};
    pfs::Clipper.PolyFillType=Clipper.PolyFillTypeEvenOdd,
    pfc::Clipper.PolyFillType=Clipper.PolyFillTypeEvenOdd) where {T}

Return the ClippedPolygon resulting from a polygon clipping operation.

Uses the Clipper library and the Clipper.jl wrapper to perform polygon clipping.

Positional arguments

The first argument must be one of the following types to specify a clipping operation:

  • Clipper.ClipTypeDifference
  • Clipper.ClipTypeIntersection
  • Clipper.ClipTypeUnion
  • Clipper.ClipTypeXor

Note that these are types; you should not follow them with ().

The second and third argument may be a GeometryEntity or array of GeometryEntity. All entities are first converted to polygons using to_polygons. Each can also be a GeometryStructure or GeometryReference, in which case elements(flatten(p)) will be converted to polygons. Each can also be a pair geom => layer, where geom is a GeometryStructure or GeometryReference, while layer is a DeviceLayout.Meta, a layer name Symbol, and/or a collection of either, in which case only the elements in those layers will be taken from the flattened structure.

Keyword arguments

pfs and pfc specify polygon fill rules for the s and c arguments, respectively. These arguments may include:

  • Clipper.PolyFillTypeNegative
  • Clipper.PolyFillTypePositive
  • Clipper.PolyFillTypeEvenOdd
  • Clipper.PolyFillTypeNonZero

See the Clipper docs for further information.

See also union2d, difference2d, and intersect2d.

source
DeviceLayout.Polygons.StyleDictType
struct StyleDict{S} <: GeometryEntityStyle where {S}
    styles::Dict{Vector{Int}, GeometryEntityStyle},
    default::S
end

Style used for applying differing styles to different Polygons at different levels within a ClippedPolygon or CurvilinearRegion. Styles are stored by the sequence of child indices required to find the corresponding Clipper.PolyNode within the ClippedPolygon. For a CurvilinearRegion only dictionaries of depth 2 (a single parent and one set of holes) are valid.

source

Shapes

DeviceLayout.Polygons.EllipseType
struct Ellipse{T} <: GeometryEntity{T}
    center::Point{T}
    radii::NTuple{2, T}
    angle::typeof(1.0°)
    Ellipse{T}(c, r, a) where {T} = new{T}(c, r[1] < r[2] ? (r[2], r[1]) : r, a)
end
Ellipse(center::Point{T}, radii, angle) where {T} = Ellipse{T}(center, radii, angle)
Ellipse(center::Point{T}; r::T) where {T} = Ellipse{T}(center, (r, r), 0.0°)

Represent an ellipse with a centroid, radii and major axis angle. The major axis radius is stored first within radii, and the axis angle is defined from the x-axis.

source

See Shapes.

Coordinate Systems

DeviceLayout.AbstractCoordinateSystemType
AbstractCoordinateSystem{S<:Coordinate} <: GeometryStructure{S}

Abstract supertype for coordinate systems, including CoordinateSystem and Cell.

Also exists to avoid circular definitions involving the concrete AbstractCoordinateSystem types and subtypes of GeometryReference.

source
DeviceLayout.CoordinateSystems.CoordinateSystemType
mutable struct CoordinateSystem{S<:Coordinate} <: AbstractCoordinateSystem{S}
    name::String
    elements::Vector{GeometryEntity{S}}
    meta::Vector{Meta}
    refs::Vector{GeometryReference}
    create::DateTime

    CoordinateSystem{S}(x, y, ym, z, t) where {S} = new{S}(x, y, ym, z, t)
    CoordinateSystem{S}(x, y, ym, z) where {S} = new{S}(x, y, ym, z, now())
    CoordinateSystem{S}(x, y, ym) where {S} = new{S}(x, y, ym, GeometryReference[], now())
    CoordinateSystem{S}(x) where {S} =
        new{S}(x, GeometryEntity{S}[], Meta[], GeometryReference[], now())
    CoordinateSystem{S}() where {S} = begin
        c = new{S}()
        c.elements = GeometryEntity{S}[]
        c.meta = Meta[]
        c.refs = GeometryReference[]
        c.create = now()
        c
    end
end

A CoordinateSystem has a name and contains geometry entities (Polygons, Rectangles) and references to GeometryStructure objects. It also records the time of its own creation.

To add elements, use place!, or use render! to be agnostic between CoordinateSystem and Cell. To add references, use addref! or addarr!.

source
DeviceLayout.SemanticMetaType
struct SemanticMeta <: DeviceLayout.Meta
    layer::Symbol
    index::Int = 1
    level::Int = 1
end
SemanticMeta(layer::String; kwargs...)
SemanticMeta(meta::Meta; kwargs...)

DeviceLayout-native representation of an object's layer information and attributes.

Semantic metadata refers to the meaning of an element without reference to a fixed encoding. For example, "this polygon is in the negative of the ground plane" is semantic, while "this polygon is in GDS layer 1, datatype 2" is not. The semantic metadata is used in the final render step, where a layout is converted from a CoordinateSystem to a representation corresponding to a particular output format (e.g., a Cell for GDSII). A call to render!(cell::Cell{S}, cs::CoordinateSystem; map_meta = default_meta_map, kwargs...) will use the map_meta function to map each GeometryEntity's metadata to GDSMeta.

By default, DeviceLayout.default_meta_map is used, which:

  • Passes GDSMeta through unchanged
  • Converts other metadata types to GDSMeta using a hash-based layer assignment (0-255)

The level and index fields do not have a strict interpretation imposed by DeviceLayout. (In this sense they are similar to GDS datatype.) The suggested use is as follows:

  • index distinguishes numbered instances within a layer, for example in greyscale lithography or port numbering
  • level distinguishes instances of a layer occurring in different contexts, such as in a 3D stack where equivalent layers may be present in multiple levels
source
DeviceLayout.CoordinateSystems.addref!Function
addref!(c1::AbstractCoordinateSystem, cr::GeometryReference)

Add the reference cr to the list of references in c1.

source
addref!(c1::AbstractCoordinateSystem{T},
    c2::GeometryStructure,
    origin=zero(Point{T});
    kwargs...)

Add a reference to c2 to the list of references in c1.

The reference to c2 has origin origin; x-reflection, magnification factor, and rotation are set by keywords arguments.

Synonyms are accepted for these keywords:

  • X-reflection: :xrefl, :xreflection, :refl, :reflect, :xreflect, :xmirror, :mirror
  • Magnification: :mag, :magnification, :magnify, :zoom, :scale
  • Rotation: :rot, :rotation, :rotate, :angle
source
DeviceLayout.CoordinateSystems.addarr!Function
addarr!(
    c1::AbstractCoordinateSystem{T},
    c2::GeometryStructure,
    origin::Point=zero(Point{T});
    kwargs...
)

Add an ArrayReference to c2 to the list of references in c1.

The reference to c2 has origin origin. Keyword arguments specify the column vector, row vector, number of columns, number of rows, x-reflection, magnification factor, and rotation.

Synonyms are accepted for these keywords:

  • Column vector dc::Point{T}: :deltacol, :dcol, :dc, :vcol, :colv, :colvec, :colvector, :columnv, :columnvec, :columnvector
  • Row vector: :deltarow, :drow, :dr, :vrow, :rv, :rowvec, :rowvector
  • Number of columns: :nc, :numcols, :numcol, :ncols, :ncol
  • Number of rows: :nr, :numrows, :numrow, :nrows, :nrow
  • X-reflection: :xrefl, :xreflection, :refl, :reflect, :xreflect, :xmirror, :mirror
  • Magnification: :mag, :magnification, :magnify, :zoom, :scale
  • Rotation: :rot, :rotation, :rotate, :angle
source
addarr!(
    c1::AbstractCoordinateSystem,
    c2::GeometryStructure,
    c::AbstractRange,
    r::AbstractRange;
    kwargs...
)

Add an ArrayReference to c2 to the list of references in c1, based on ranges.

c specifies column coordinates and r for the rows. Pairs from c and r specify the origins of the repeated cells. The extrema of the ranges therefore do not specify the extrema of the resulting ArrayReference's bounding box; some care is required.

Keyword arguments specify x-reflection, magnification factor, and rotation, with synonyms allowed:

  • X-reflection: :xrefl, :xreflection, :refl, :reflect, :xreflect, :xmirror, :mirror
  • Magnification: :mag, :magnification, :magnify, :zoom, :scale
  • Rotation: :rot, :rotation, :rotate, :angle
source
DeviceLayout.default_meta_mapFunction
default_meta_map(meta::Meta) -> GDSMeta

Default metadata mapping function for rendering to Cell.

This map is for convenient graphical display and should not be relied on in production workflows.

GDSMeta passes through unchanged.

Other Meta types are converted to GDSMeta using a layer in (0-255) based on the hash of (layer(m), level(m)) and datatype layerindex(m)-1 (clamped to 0-255). This means that other metadata types are not guaranteed to be mapped to unique GDSMeta.

Examples

julia> default_meta_map(GDSMeta(10, 2))
GDSMeta(10, 2)

julia> default_meta_map(SemanticMeta(:metal))
GDSMeta(63, 0)  # Hash-based layer, datatype from index

julia> default_meta_map(SemanticMeta(:metal, index=5))
GDSMeta(63, 4)  # Same layer, different datatype
source
DeviceLayout.CoordinateSystems.flatten!Method
flatten!(c::AbstractCoordinateSystem, depth::Integer=-1, metadata_filter=nothing, max_copy=Inf)

Recursively flatten references and arrays up to a hierarchical depth, adding their elements to c with appropriate transformations.

The references and arrays that were flattened are then discarded. Deeper references and arrays are brought upwards and are not discarded.

This function has no effect for depth == 0, and unlimited depth by default.

source
DeviceLayout.layerFunction
layer(m::Meta)

The layer specified by m, as a Symbol.

For example, layer(GDSMeta(1, 2)) is :GDS1_2, and layername(SemanticMeta(:base)) is :base.

source
DeviceLayout.layerindexFunction
layerindex(m::Meta)

The index specified by metadata m. Defaults to 1 for metadata types without an index.

source
DeviceLayout.layernameFunction
layername(m::Meta)

The layer specified by m, as a String.

For example, layer(GDSMeta(1, 2)) is "GDS1_2", and layername(SemanticMeta(:base)) is "base".

source
DeviceLayout.levelFunction
level(m::Meta)

The level specified by metadata s. Defaults to 1 for metadata types without a level.

source
DeviceLayout.CoordinateSystems.place!Function
place!(cs::CoordinateSystem, ent::GeometryEntity, metadata)

Place ent in cs with metadata metadata.

source
place!(cs::CoordinateSystem, s::GeometryStructure)

Place a reference to s in cs.

source
place!(cs::CoordinateSystem, p::Path, metadata=p.metadata)

Place a reference to p in cs and set metadata to metadata.

source

Cells

DeviceLayout.Cells.CellType
mutable struct Cell{S<:Coordinate}

A cell has a name and contains polygons and references to CellArray or CellReference objects. It also records the time of its own creation. As currently implemented it mirrors the notion of cells in GDSII files.

To add elements, use render!. To add references, use addref! or addarr!. To add text, use text!.

source
DeviceLayout.Cells.CellMethod
Cell(name::AbstractString)

Convenience constructor for Cell{typeof(1.0UPREFERRED)}.

DeviceLayout.UPREFERRED is a constant set according to the unit preference in Project.toml or LocalPreferences.toml. The default ("PreferNanometers") gives const UPREFERRED = DeviceLayout.nm, with mixed-unit operations preferring conversion to nm.

Unit preference does not affect the database scale for GDS export.

source
DeviceLayout.Cells.CellMethod
Cell(cs::CoordinateSystem{S}) = Cell{S}(cs)
Cell(cs::CoordinateSystem, unit::CoordinateUnits) = Cell{typeof(1.0unit)}(cs)
Cell{S}(cs::CoordinateSystem) where {S}

Construct a Cell from a CoordinateSystem by rendering its contents, reproducing the reference hierarchy.

source
DeviceLayout.Cells.dbscaleMethod
dbscale(c::Cell)

Give the database scale for a cell. The database scale is the smallest increment of length that will be represented in the output CAD file. This is different from the working coordinate type T of the Cell.

The database scale defaults to 1nm (1.0nm if T <: FloatCoordinate), but can be changed by updating c.dbscale to a new Unitful.Length quantity.

source
DeviceLayout.Cells.dbscaleMethod
dbscale(cell::Cell...)

Choose an appropriate database scale for a GDSII file given Cells of different types. The smallest database scale of all cells considered is returned.

source
DeviceLayout.GDSMetaType
struct GDSMeta <: DeviceLayout.Meta
    layer::Int
    datatype::Int
    GDSMeta() = new(DEFAULT_LAYER, DEFAULT_DATATYPE)
    GDSMeta(l) = new(l, DEFAULT_DATATYPE)
    GDSMeta(l, d) = new(l, d)
end

Metadata associated with GDSII format. Default layer and datatype are 0.

source
DeviceLayout.GDS.GDSWriterOptionsType
@kwdef struct GDSWriterOptions

Options controlling warnings and validation during GDS file writing.

Fields

  • max_layer::Int = 32767: Maximum layer number that will not throw a warning.
  • max_datatype::Int = 32767: Maximum datatype number that will not throw a warning.
  • warn_invalid_names::Bool = true: Whether to warn about cell/text names that violate the GDSII spec (must be ≤32 chars, only A-Z, a-z, 0-9, '_', '?', '$').
  • rename_duplicates::Bool = false: If true, automatically rename duplicate cell names during GDS save using uniquename with a save-scoped counter. Renaming is case-insensitive (GDS readers like KLayout treat cell names case-insensitively). The original Cell objects are not mutated; renamed names are only written to the file. New names may exceed the GDSII spec's 32 character limit.

Warnings for layer number and datatype are configurable because different tools may have different limits. In the GDSII specification, layer and datatype must be in the range 0 to 63, but modern tools are rarely so strict. The hard limit is that the layer and datatype records are each two bytes. In the specification, they are two-byte signed integers, and for tools that conform in that regard, the maximum value is 32767. For that reason, larger values will cause a warning to be shown by default. However, a common extension of the format interprets these records as unsigned integers, allowing values up to 65535.

Examples

# Default: modern limits, name warnings enabled
opts = GDSWriterOptions()

# Strict GDSII spec compliance
opts = GDSWriterOptions(max_layer=63, max_datatype=63)

# No warnings at all
opts = GDSWriterOptions(
    max_layer=typemax(UInt16),
    max_datatype=typemax(UInt16),
    warn_invalid_names=false
)

# Auto-rename duplicate cell names on save
opts = GDSWriterOptions(rename_duplicates=true)
source
DeviceLayout.Cells.gdslayersMethod
gdslayers(x::Cell)

Returns the unique GDS layers of elements in cell x. Does not return the layers in referenced or arrayed cells.

source
DeviceLayout.render!Method
render!(c::Cell, p::Polygon, meta::GDSMeta=GDSMeta())

Render a polygon p to cell c, defaulting to plain styling. If p has more than 8190 (set by DeviceLayout's GDS_POLYGON_MAX constant), then it is partitioned into smaller polygons which are then rendered. Environment variable ENV["GDS_POLYGON_MAX"] will override this constant. The partitioning algorithm implements guillotine cutting, that goes through at least one existing vertex and in manhattan directions. Cuts are selected by ad hoc optimization for "nice" partitions.

source
DeviceLayout.render!Method
render!(cell::Cell{S}, cs::GeometryStructure;
    memoized_cells=Dict{GeometryStructure, Cell}(),
    map_meta = default_meta_map,
    kwargs...) where {S}

Render a geometry structure (e.g., CoordinateSystem) to a cell.

Passes each element and its metadata (mapped by map_meta if a method is supplied) to render!(::Cell, element, ::Meta), traversing the references such that if a structure is referred to in multiple places, it will become a single cell referred to in multiple places.

Rendering a GeometryStructure to a Cell uses the optional keyword arguments

  • map_meta, a function that takes a Meta object and returns a GDSMeta object (or nothing, in which case rendering is skipped). Defaults to DeviceLayout.default_meta_map, which passes GDSMeta through unchanged. Other metadata types will be converted using hash-based layer assignment, but this conversion is provided for quick GDS viewing and should not be relied on in production workflows.
  • memoized_cells, a dictionary used internally to make sure that if a structure is referred to in multiple places, it will become a single cell referred to in multiple places. Calling this function with non-empty dictionary memoized_cells = Dict{GeometryStructure, Cell}(geom => prerendered_cell) is effectively a manual override that forces geom (which may be cs or any structure in its reference hierarchy) to render as prerendered_cell.

Additional keyword arguments are passed to to_polygons for each entity and may be used for certain entity types to control how they are converted to polygons.

source
DeviceLayout.saveMethod
save(::Union{AbstractString,IO}, cell0::Cell{T}, cell::Cell...)
save(f::File{format"GDS"}, cell0::Cell, cell::Cell...;
    name="GDSIILIB", userunit=1μm, modify=now(), acc=now(),
    options=GDSWriterOptions(), spec_warnings=nothing, verbose=false)

This bottom method is implicitly called when you use the convenient syntax of the top method: save("/path/to/my.gds", cells_i_want_to_save...)

Keyword arguments include:

  • name: used for the internal library name of the GDSII file and probably inconsequential for modern workflows.
  • userunit: sets what 1.0 corresponds to when viewing this file in graphical GDS editors with inferior unit support.
  • modify: date of last modification.
  • acc: date of last accession. It would be unusual to have this differ from now().
  • options: a GDSWriterOptions controlling validation of Cell names and warnings for maximum layer/datatype numbers.
  • spec_warnings: if false, disables all warnings for max layer/datatype and invalid names
  • verbose: monitor the output of traverse! and order! to see if something funny is happening while saving.
source
DeviceLayout.loadMethod
load(f::File{format"GDS"}; verbose::Bool=false, nounits::Bool=false)

A dictionary of top-level cells (Cell objects) found in the GDSII file is returned. The dictionary keys are the cell names. The other cells in the GDSII file are retained by CellReference or CellArray objects held by the top-level cells. Currently, cell references and arrays are not implemented.

The FileIO package recognizes files based on "magic bytes" at the start of the file. To permit any version of GDSII file to be read, we consider the magic bytes to be the GDS HEADER tag (0x0002), preceded by the number of bytes in total (0x0006) for the entire HEADER record. The last well-documented version of GDSII is v6.0.0, encoded as 0x0258 == 600. LayoutEditor appears to save a version 7 as 0x0007, which as far as I can tell is unofficial, and probably just permits more layers than 64, or extra characters in cell names, etc.

If the database scale is 1μm, 1nm, or 1pm, then the corresponding unit is used for the resulting imported cells. Otherwise, an "anonymous unit" is used that will display as u"2.4μm" if the database scale is 2.4μm, say.

Warnings are thrown if the GDSII file does not begin with a BGNLIB record following the HEADER record, but loading will proceed.

Property values and attributes (PROPVALUE and PROPATTR records) will be ignored.

Encountering an ENDLIB record will discard the remainder of the GDSII file without warning. If no ENDLIB record is present, a warning will be thrown.

The content of some records are currently discarded (mainly the more obscure GDSII record types, but also BGNLIB and LIBNAME).

If nounits is true, Cell{Float64} objects will be returned, where 1.0 corresponds to one micron.

source
DeviceLayout.CoordinateSystems.traverse!Function
traverse!(a::AbstractArray, c::GeometryStructure, level=1)

Given a coordinate system, recursively traverse its references for other coordinate systems and add to array a some tuples: (level, c). level corresponds to how deep the coordinate system was found, and c is the found coordinate system.

source
DeviceLayout.CoordinateSystems.order!Function
order!(a::AbstractArray)

Given an array of tuples like that coming out of traverse!, we sort by the level, strip the level out, and then retain unique entries. The aim of this function is to determine an optimal writing order when saving pattern data (although the GDSII spec does not require cells to be in a particular order, there may be performance ramifications).

For performance reasons, this function modifies a but what you want is the returned result array.

source

Texts

DeviceLayout.Texts.TextType
Text{S} <: GeometryEntity{S}

Text element in a layout. Distinct from rendering text as polygons (PolyText).

Text rendering may be viewer or system dependent. Use PolyText for text with well-defined geometry.

Arguments:

  • text: the text string.
  • origin: location of the text in parent coordinate system.
  • width: character size
  • can_scale: defaults to false, set to true if the text size should not be affected by scaling of parent coordinate system.
  • xalign: horizontal alignment of text with respect to origin. Can be any instance of abstract type Align.XAlignRule and defaults to LeftEdge().
  • yalign: vertical alignment of text with respect to origin. Can be any instance of abstract type Align.YAlignRule and defaults to TopEdge().
  • xrefl: Reflect across x-axis. Defaults to false.
  • mag: Magnification factor.
  • rot: Rotation in radians.
source
DeviceLayout.Cells.text!Function
text!(c::Cell{S}, str::String, origin::Point=zero(Point{S}), meta::Meta=GDSMeta(); kwargs...) where {S}

Annotate cell c with string str as a text element. See also polytext! for rendering strings as polygons.

source
text!(c::Cell, text::Texts.Text, meta)

Annotate cell c with Texts.Text object.

source

PolyText

DeviceLayout.PolyText.DotMatrixType
DotMatrix(; pixelsize, pixelspacing=pixelsize,
            rounding=zero(pixelsize), meta::Meta=GDSMeta(0,0))

Keyword args

  • pixelsize: dimension for the width/height of each pixel.
  • pixelspacing: dimension for the spacing between adjacent pixels. Should be ≥ pixelsize. Defaults to pixelsize.
  • rounding: rounding radius for sharp corners of pixels. If pixelsize == pixelspacing, individual pixels are not rounded, but rather the pixels are unioned and the entire letter will be rounded.
  • meta: layer/datatype or similar info.
source
DeviceLayout.PolyText.polytextFunction
polytext(str::String, sty::PolyText.Style;
    scripting=false, linelimit=typemax(Int), verbose=false) where {T}

Renders the string str to a new coordinate system in a given style.

Keyword args

  • scripting: boolean parameter for allocating special characters ^, _, {, and } for superscripting and subscripting. Follows the same usage as LaTeX.
  • linelimit: sets the maximum number of characters per line and continues on a new line if str is longer than linelimit.
  • verbose: prints out information about the character dictionary.
source
DeviceLayout.PolyText.polytext!Function
polytext!(c::AbstractCoordinateSystem, str::String, sty::PolyText.Style;
    scripting=false, linelimit=typemax(Int), verbose=false)

Renders the string str to cell or coordinate system c in a given style.

Keyword args

  • scripting: boolean parameter for allocating special characters ^, _, {, and } for superscripting and subscripting. Follows the same usage as LaTeX.
  • linelimit: sets the maximum number of characters per line and continues on a new line if str is longer than linelimit.
  • verbose: prints out information about the character dictionary.
source
DeviceLayout.PolyText.characters_demoFunction
characters_demo(save_path = joinpath(homedir(),"Desktop","characters.gds"), flatten = false)

Demo script for demonstrating the available characters in polytext! and the linelimit parameter in use. flatten can flatten the cells before saving (for SVG output).

source
DeviceLayout.PolyText.scripted_demoFunction
scripted_demo(save_path = joinpath(homedir(),"Desktop","scripted.gds"), flatten = false)

Demo script for demonstrating the use of the scripting parameter in polytext!. flatten can flatten the cells before saving (for SVG output).

source
DeviceLayout.PolyText.referenced_characters_demoFunction
referenced_characters_demo(save_path = joinpath(homedir(),"Desktop","referenced_characters.gds");
    verbose_override = false)

Demo script for demonstrating the memory saving ability of keeping CellReferences for previously used characters in polytext!. Nothing is printed if verbose_override is true.

source

Rendering

DeviceLayout.render!Function
render!(c::Cell, p::Polygon, meta::GDSMeta=GDSMeta())

Render a polygon p to cell c, defaulting to plain styling. If p has more than 8190 (set by DeviceLayout's GDS_POLYGON_MAX constant), then it is partitioned into smaller polygons which are then rendered. Environment variable ENV["GDS_POLYGON_MAX"] will override this constant. The partitioning algorithm implements guillotine cutting, that goes through at least one existing vertex and in manhattan directions. Cuts are selected by ad hoc optimization for "nice" partitions.

source
render!(c::CoordinateSystem, ent, meta)

Synonym for place!.

source
render!(cell::Cell{S}, cs::GeometryStructure;
    memoized_cells=Dict{GeometryStructure, Cell}(),
    map_meta = default_meta_map,
    kwargs...) where {S}

Render a geometry structure (e.g., CoordinateSystem) to a cell.

Passes each element and its metadata (mapped by map_meta if a method is supplied) to render!(::Cell, element, ::Meta), traversing the references such that if a structure is referred to in multiple places, it will become a single cell referred to in multiple places.

Rendering a GeometryStructure to a Cell uses the optional keyword arguments

  • map_meta, a function that takes a Meta object and returns a GDSMeta object (or nothing, in which case rendering is skipped). Defaults to DeviceLayout.default_meta_map, which passes GDSMeta through unchanged. Other metadata types will be converted using hash-based layer assignment, but this conversion is provided for quick GDS viewing and should not be relied on in production workflows.
  • memoized_cells, a dictionary used internally to make sure that if a structure is referred to in multiple places, it will become a single cell referred to in multiple places. Calling this function with non-empty dictionary memoized_cells = Dict{GeometryStructure, Cell}(geom => prerendered_cell) is effectively a manual override that forces geom (which may be cs or any structure in its reference hierarchy) to render as prerendered_cell.

Additional keyword arguments are passed to to_polygons for each entity and may be used for certain entity types to control how they are converted to polygons.

source
render!(sm::SolidModel, cs::AbstractCoordinateSystem{T}; map_meta=layer,
postrender_ops=[], zmap=(_) -> zero(T), gmsh_options = Dict(), skip_postrender = false, kwargs...) where {T}

Render cs to sm.

Keywords

  • map_meta: Function (m::SemanticMeta) -> name of PhysicalGroup (as String or Symbol; may also return nothing to skip rendering m)
  • postrender_ops: Vector of Tuples (destination, op, args, op_kwargs...) specifying "postrendering" of PhysicalGroups executed after entities have been rendered to to sm. Each operation op creates a new PhysicalGroup defined as sm[destination] = op(sm, args...; op_kwargs...). That is, args are the arguments to op (following the first argument, which is always the model sm being rendered to). For most operations, these arguments include the names and dimensions of groups being operated on, and op_kwargs are the keyword arguments passed to op. For example, ("base", difference_geom!, ("writeable_area", "base_negative"), :remove_object => true, :remove_tool => true) defines a postrendering step that subtracts the PhysicalGroup named "base_negative" from "writeable_area" (by default using dimension 2 for each group) to define a new group called "base". The keyword pairs :remove_object=>true and :remove_tool=>true mean that the "object" (first argument) group "writeable_area" and the "tool" (second argument) group "base_negative" are both removed when "base" is created.
  • retained_physical_groups: Vector of (name, dimension) tuples specifying which physical groups to keep after rendering. All other groups are removed.
  • zmap: Function (m::SemanticMeta) -> z coordinate of corresponding elements. Default: Map all metadata to zero.
  • gmsh_options: Dictionary of gmsh option name-value pairs to set before meshing.
  • meshing_parameters: Deprecated. Use individual mesh control functions DeviceLayout.SolidModels.mesh_scale, DeviceLayout.SolidModels.mesh_order and DeviceLayout.SolidModels.mesh_grading_default, along with gmsh_options instead.
  • skip_postrender: Whether or not to return early without performing any postrendering operations. This can be particularly helpful during debugging, as all two dimensional entities will be placed appropriately but will not have been combined.

Available postrendering operations include translate!, extrude_z!, revolve!, union_geom!, intersect_geom!, difference_geom!, fragment_geom!, and box_selection. (The geometric Boolean operations are only available for models using the OpenCASCADE kernel.)

Additional keyword arguments are passed to DeviceLayout.SolidModels.to_primitives (which falls back to to_polygons) and may be used for certain entity types to control how entities of cs are converted to primitives and added to sm.

source
render!(cs::AbstractCoordinateSystem, obj::GeometryEntity, meta::DeviceLayout.Meta,
    target::LayoutTarget; kwargs...)

Render obj to cs, with metadata mapped to layers and rendering options by target.

source
render!(cs::AbstractCoordinateSystem, cs2::GeometryStructure, target::LayoutTarget; kwargs...)

Render cs2 to cs, with metadata mapped to layers and rendering options by target.

See LayoutTarget documentation for details.

source
render!(
    cs::AbstractCoordinateSystem,
    sch::Schematic,
    target::LayoutTarget;
    strict=:error,
    kwargs...
)

Render the schematic sch to cs using target's rendering options, without modifying sch.

Users must run check!(sch) before calling this method; otherwise, it will throw an error.

The strict keyword should be :error, :warn, or :no.

The strict=:error keyword option causes render! to throw an error if any errors were logged while building component geometries or while rendering geometries to cs. This is enabled by default, but can be disabled with strict=:no, in which case any component which was not successfully built will have an empty geometry, and any non-fatal rendering errors will be ignored as usual. Using strict=:no is recommended only for debugging purposes.

The strict=:warn keyword option causes render! to throw an error if any warnings were logged. This is disabled by default. Using strict=:warn is suggested for use in automated pipelines, where warnings may require human review.

source
render!(sm::SolidModel, sch::Schematic, target::Target; strict=:error, kwargs...)

Render sch to sm, using rendering settings from target.

The strict keyword should be :error, :warn, or :no.

The strict=:error keyword option causes render! to throw an error if any errors were logged while building component geometries or while rendering geometries to cs. This is enabled by default, but can be disabled with strict=:no, in which case any component which was not successfully built will have an empty geometry, and any non-fatal rendering errors will be ignored as usual. Using strict=:no is recommended only for debugging purposes.

The strict=:warn keyword option causes render! to throw an error if any warnings were logged. This is disabled by default. Using strict=:warn is suggested for use in automated pipelines, where warnings may require human review.

Additional keyword arguments may be used for certain entity types for controlling how geometry entities are converted to primitives and added to sm.

source
DeviceLayout.adapted_gridFunction
adapted_grid(f, anchors;
    max_recursions::Real = 7, max_change = 5°, rand_factor::Real = 0.05,
    grid_step = 1.0μm)

Computes a resampled grid given anchor points so that f.(grid) is sufficiently smooth. The method used is to create an initial grid around the anchor points and refine intervals. When an interval becomes "straight enough" it is no longer divided. Adapted from a contribution to PlotUtils.jl from Kristoffer Carlsson.

  • max_recursions: how many times each interval is allowed to be refined.
  • max_change: specifies acceptable change between evaluations of f on subsequent grid points, as estimated by the derivative times the distance between grid points. Typically, f is the angle of a path in the plane, so this is often an angle threshold. This condition is approximately valid in the end result, but may be weakly violated. This condition may be grossly violated if max_recursions is too low.
  • rand_factor: between anchor points, adapted_grid will wiggle initial grid points a bit to prevent aliasing. The wiggling is sampled uniformly from the interval: [-rand_factor, rand_factor], times the distance between three grid points (e.g. i+1 and i-1). A random number generator is given a fixed seed every time adapted_grid is called, so the rendered results are deterministic.
  • grid_step: Step size for initial grid points. If you set this to be larger than the maximum anchor point, then the lowest resolution consistent with max_change is used (unless f has some fast variations that the algorithm might miss).
source
DeviceLayout.discretize_curveFunction
discretize_curve(f, ddf, tolerance)

Given a curve f and its second derivative ddf, discretize a curve into piecewise linear segments with an approximate absolute tolerance.

source

SolidModels

DeviceLayout.SolidModels.SolidModelType
struct SolidModel{T} where {T <: SolidModelKernel}
    name::String
    groups::NTuple{4,Dict{String,AbstractPhysicalGroup}}
end
SolidModel(name::String, kernel=OpenCascade; overwrite=false)

A 3D geometry model.

Geometry rendering, boolean operations, and export are provided by the specified kernel.

Physical groups can be accessed by name using indexing with a String or Symbol and a dimension: mymodel["mygroup", 3] will return the PhysicalGroup with dimension 3 called mygroup.

Physical groups can also be assigned as mymodel["mygroup"] = dimtags, where dimtags is a list of NTuple{2, Int32} of entities identified by (dim, tag) in mymodel. If dimtags includes entities of multiple dimensions, then a group is created for each dimension.

If the constructor is called with overwrite=false (the default), then an error will be thrown if a model with the same name already exists. If overwrite=true, then any existing model with the same name will be deleted and a new model will be created.

A SolidModel can be saved to a file with FileIO.save(filename, sm). Supported filetypes for OpenCASCADE geometries are .brep and .stp. Meshes can be exported as .msh2 (compatible with Palace) or .msh (most recent Gmsh format) files. Other filetypes supported by gmsh.write() like .xao can be used with DeviceLayout.save.

source
DeviceLayout.SolidModels.attributesFunction
attributes(sm::SolidModel)

Given a SolidModel construct a dictionary from physical group name to attribute number for use in specification of a configuration file for use with Palace.

source
DeviceLayout.SolidModels.to_primitivesFunction
to_primitives(::SolidModel, ent::GeometryEntity; kwargs...)

Return a GeometryEntity or a vector of entities equivalent to ent.

Called inside render! before adding entities to the SolidModel. Each resulting entity corresponds to a single entity in that SolidModel's geometry kernel.

If there is no special handling for ent in the kernel, then the result will be to_polygons(ent; kwargs...).

source
DeviceLayout.render!Method
render!(sm::SolidModel, cs::AbstractCoordinateSystem{T}; map_meta=layer,
postrender_ops=[], zmap=(_) -> zero(T), gmsh_options = Dict(), skip_postrender = false, kwargs...) where {T}

Render cs to sm.

Keywords

  • map_meta: Function (m::SemanticMeta) -> name of PhysicalGroup (as String or Symbol; may also return nothing to skip rendering m)
  • postrender_ops: Vector of Tuples (destination, op, args, op_kwargs...) specifying "postrendering" of PhysicalGroups executed after entities have been rendered to to sm. Each operation op creates a new PhysicalGroup defined as sm[destination] = op(sm, args...; op_kwargs...). That is, args are the arguments to op (following the first argument, which is always the model sm being rendered to). For most operations, these arguments include the names and dimensions of groups being operated on, and op_kwargs are the keyword arguments passed to op. For example, ("base", difference_geom!, ("writeable_area", "base_negative"), :remove_object => true, :remove_tool => true) defines a postrendering step that subtracts the PhysicalGroup named "base_negative" from "writeable_area" (by default using dimension 2 for each group) to define a new group called "base". The keyword pairs :remove_object=>true and :remove_tool=>true mean that the "object" (first argument) group "writeable_area" and the "tool" (second argument) group "base_negative" are both removed when "base" is created.
  • retained_physical_groups: Vector of (name, dimension) tuples specifying which physical groups to keep after rendering. All other groups are removed.
  • zmap: Function (m::SemanticMeta) -> z coordinate of corresponding elements. Default: Map all metadata to zero.
  • gmsh_options: Dictionary of gmsh option name-value pairs to set before meshing.
  • meshing_parameters: Deprecated. Use individual mesh control functions DeviceLayout.SolidModels.mesh_scale, DeviceLayout.SolidModels.mesh_order and DeviceLayout.SolidModels.mesh_grading_default, along with gmsh_options instead.
  • skip_postrender: Whether or not to return early without performing any postrendering operations. This can be particularly helpful during debugging, as all two dimensional entities will be placed appropriately but will not have been combined.

Available postrendering operations include translate!, extrude_z!, revolve!, union_geom!, intersect_geom!, difference_geom!, fragment_geom!, and box_selection. (The geometric Boolean operations are only available for models using the OpenCASCADE kernel.)

Additional keyword arguments are passed to DeviceLayout.SolidModels.to_primitives (which falls back to to_polygons) and may be used for certain entity types to control how entities of cs are converted to primitives and added to sm.

source
DeviceLayout.saveMethod
save(file::File, sm::SolidModel)
save(filename::String, sm::SolidModel)

Save a SolidModel instance to a file or filename.

Using FileIO.save, supported filetypes using for OpenCASCADE geometries are .brep and .stp. Meshes can be exported as .msh2 (compatible with Palace) or .msh (most recent Gmsh format) files.

Using DeviceLayout.save, you can also choose any other extension supported by gmsh.write() like .xao.

source

Physical Groups

DeviceLayout.SolidModels.bounds3dFunction
bounds3d(group::AbstractPhysicalGroup; delta=0)
bounds3d(dimtags; delta=0)

Return the rectangular prism defined bounding group or dimtags with an offset of delta.

Note that OpenCASCADE bounding boxes are not tight, and will typically extend beyond the exact bounding box by 1e-7μm at each face.

The result is returned as the tuple (xmin, ymin, zmin, xmax, ymax, zmax).

source

Postrendering

DeviceLayout.SolidModels.box_selectionFunction
box_selection(x1, y1, z1, x2, y2, z2; dim=-1, delta=zero(x1))
box_selection(::SolidModel, x1, y1, z1, x2, y2, z2; dim=-1, delta=zero(x1))

Get the model entities in the bounding box defined by the two points (xmin, ymin, zmin) and (xmax, ymax, zmax). If dim is >= 0, return only the entities of the specified dimension (e.g. points if dim == 0).

Return the selected entities as a vector of (dimension, entity_tag) Tuples.

source
DeviceLayout.SolidModels.difference_geom!Function
difference_geom!(
    object::Union{PhysicalGroup, AbstractArray{PhysicalGroup}},
    tool::Union{PhysicalGroup, AbstractArray{PhysicalGroup}};
    tag=-1,
    remove_object=false,
    remove_tool=false
)

Create the geometric difference of the groups object and tool.

Return the resulting entities as a vector of (dimension, entity_tag) Tuples.

If tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.

The operator - can be used as a synonymous infix operator.

source
difference_geom!(sm::SolidModel, object::Union{String, Symbol}, tool::Union{String, Symbol}, d1=2, d2=2;
    tag=-1,
    remove_object=false,
    remove_tool=false)

Create the geometric difference of groups with Symbol or String names object, tool in sm.

Return the resulting entities as a vector of (dimension, entity_tag) Tuples.

The dimensions of the object and tool groups can be specified as d1 and d2, respectively. The dimension defaults to 2 (surfaces).

If the tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.

If object is not a physical group in sm, will error and return an empty dimtag array. If tool is not a physical group in sm, will return dimtags of object.

source
difference_geom!(sm::SolidModel, object, tool, d1=2, d2=2; remove_tool=false,
remove_object=false, kwargs...)

Create the geometric difference of groups object and tool which can be collections of Union{String, Symbol}.

source
DeviceLayout.SolidModels.extrude_z!Function
extrude_z!(g::PhysicalGroup, dz; num_elements=[], heights=[], recombine=false)
extrude_z!(sm::SolidModel, groupname, dz, groupdim=2; num_elements=[], heights=[], recombine=false)

Extrude the entities in g in the z direction by dz.

If the numElements vector is not empty, also extrude the mesh: the entries in numElements give the number of elements in each layer. If the height vector is not empty, it provides the (cumulative) height of the different layers, normalized to 1. If recombine is set, recombine the mesh in the layers.

Return the resulting entities as a vector of (dimension, entity_tag) Tuples.

source
DeviceLayout.SolidModels.fragment_geom!Function
fragment_geom!(
    object::Union{PhysicalGroup, AbstractArray{PhysicalGroup}},
    tool::Union{PhysicalGroup, AbstractArray{PhysicalGroup}};
    tag=-1,
    remove_object=false,
    remove_tool=false
)

Create the Boolean fragments (general fuse) of the groups object and tool, making all interfaces conformal.

When applied to entities of different dimensions, the lower dimensional entities will be automatically embedded in the higher dimensional entities if they are not on their boundary.

Return the resulting entities as a vector of (dimension, entity_tag) Tuples.

If tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.

source
fragment_geom!(sm::SolidModel, object::Union{String, Symbol}, tool::Union{String, Symbol}, d1=2, d2=2;
    tag=-1,
    remove_object=false,
    remove_tool=false)

Create the Boolean fragments (general fuse) of groups with Symbol or String names object, tool in sm, making all interfaces conformal.

When applied to entities of different dimensions, the lower dimensional entities will be automatically embedded in the higher dimensional entities if they are not on their boundary.

Return the resulting entities as a vector of (dimension, entity_tag) Tuples.

The dimensions of the object and tool groups can be specified as d1 and d2, respectively. The dimension defaults to 2 (surfaces).

If the tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.

If only one of object or tool is a physical group in sm, will perform union of physical group with itself, if neither are present will return an empty array.

source
DeviceLayout.SolidModels.get_boundaryFunction
get_boundary(group::AbstractPhysicalGroup; combined=true, oriented=true, recursive=false, direction="all", position="all")
get_boundary(sm::SolidModel, groupname, dim=2; combined=true, oriented=true, recursive=false, direction="all", position="all")

Get the boundary of the model entities in group, given as a vector of (dim, tag) tuples.

Return the boundary of the individual entities (if combined is false) or the boundary of the combined geometrical shape formed by all input entities (if combined is true).

Return tags multiplied by the sign of the boundary entity if oriented is true.

Apply the boundary operator recursively down to dimension 0 (i.e. to points) if recursive is true.

If direction is specified, return only the boundaries perperdicular to the x, y, or z axis. If position is also specified, return only the boundaries at the min or max position along the specified direction.

source
DeviceLayout.SolidModels.intersect_geom!Function
intersect_geom!(
    object::Union{PhysicalGroup, AbstractArray{PhysicalGroup}},
    tool::Union{PhysicalGroup, AbstractArray{PhysicalGroup}};
    tag=-1,
    remove_object=false,
    remove_tool=false
)

Create the geometric intersection (the common parts) of the groups object and tool.

Return the resulting entities as a vector of (dimension, entity_tag) Tuples.

If tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.

The operators * and can be used as synonymous infix operators.

source
intersect_geom!(sm::SolidModel, object::Union{String, Symbol}, tool::Union{String, Symbol}, d1=2, d2=2;
    tag=-1,
    remove_object=false,
    remove_tool=false)

Create the geometric intersection (the common parts) of groups with Symbol or String names object, tool in sm.

Return the resulting entities as a vector of (dimension, entity_tag) Tuples.

The dimensions of the object and tool groups can be specified as d1 and d2, respectively. The dimension defaults to 2 (surfaces).

If the tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.

If tool or object are not physical groups in sm, will error and return an empty dimtag array.

source
DeviceLayout.SolidModels.remove_group!Function
remove_group!(sm::SolidModel, group::Union{String, Symbol}, dim; recursive=true, remove_entities=true)
remove_group!(group::AbstractPhysicalGroup; recursive=true, remove_entities=true)

Remove entities in group from the model, unless they are boundaries of higher-dimensional entities or part of another physical group.

If recursive is true, remove all entities on their boundaries, down to dimension zero (points).

Also removes the record of the (now-empty) physical group.

If remove_entities is false, only removes the record of the group from the model.

source
DeviceLayout.SolidModels.restrict_to_volume!Function
restrict_to_volume(sm::SolidModel, volume)

Checks if all surfaces and volumes are contained within sm[volume, 3], and if not performs an intersection operation replacing all entities and groups with their intersection with sm[volume, 3].

Embeds entities if they are on the boundary of higher-dimensional entities and removes duplicate entities.

Preserves the meaning of existing groups by assigning to them the (possibly new) entities corresponding to that group's intersection with the volume.

source
DeviceLayout.SolidModels.revolve!Function
revolve!(g::PhysicalGroup, x, y, z, ax, ay, az, θ; num_elements=[], heights=[], recombine=false)
revolve!(sm::SolidModel, groupname, groupdim, x, y, z, ax, ay, az, θ; num_elements=[], heights=[], recombine=false)

Extrude the entities in g using a rotation of θ radians around the axis of revolution through (x, y, z) in the direction (ax, ay, az).

If the numElements vector is not empty, also extrude the mesh: the entries in numElements give the number of elements in each layer. If the height vector is not empty, it provides the (cumulative) height of the different layers, normalized to 1. If recombine is set, recombine the mesh in the layers. When the mesh is extruded the angle should be strictly smaller than 2π.

Return the resulting entities as a vector of (dimension, entity_tag) Tuples.

source
DeviceLayout.SolidModels.set_periodic!Function
set_periodic!(group1::AbstractPhysicalGroup, group2::AbstractPhysicalGroup; dim=2)
set_periodic!(sm, group1, group2, d1=2, d2=2)

Set the model entities in group1 and group2 to be periodic. Only supports d1 = d2 = 2 and surfaces in both groups need to be parallel and axis-aligned.

source
DeviceLayout.SolidModels.translate!Function
translate!(group, dx, dy, dz; copy=true)
translate!(sm::SolidModel, groupname, dx, dy, dz, groupdim=2; copy=true)

Translate the entities in physical group group by (dx, dy, dz).

If copy=true, then a copy of the entities in group are translated instead.

Return the resulting entities as a vector of (dimension, entity_tag) Tuples.

source
DeviceLayout.SolidModels.union_geom!Function
union_geom!(
    object::Union{PhysicalGroup, AbstractArray{PhysicalGroup}},
    tool::Union{PhysicalGroup, AbstractArray{PhysicalGroup}};
    tag=-1,
    remove_object=false,
    remove_tool=false
)

Create the geometric union (the fusion) of the groups object and tool.

Return the resulting entities as a vector of (dimension, entity_tag) Tuples.

If tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.

The operators + and can be used as synonymous infix operators.

source
union_geom!(sm::SolidModel, object::Union{String, Symbol}, tool::Union{String, Symbol}, d1=2, d2=2;
    tag=-1,
    remove_object=false,
    remove_tool=false)

Create the geometric union of groups with Symbol or String names object, tool in sm.

Return the resulting entities as a vector of (dimension, entity_tag) Tuples.

The dimensions of the object and tool groups can be specified as d1 and d2, respectively. The dimension defaults to 2 (surfaces).

If tag is positive, try to set the tag explicitly (only valid if the boolean operation results in a single entity). Remove the object if remove_object is set. Remove the tool if remove_tool is set.

If only one of object or tool is a physical group in sm, will perform union of physical group with itself, if neither are present will return an empty array.

source
DeviceLayout.SolidModels.staple_bridge_postrenderingFunction
staple_bridge_postrendering(; levels=[], base, bridge, bridge_height=1μm, output="bridge_metal")

Returns a vector of postrendering operations for creating air bridges from a base and bridge group. levels specifies the indices of levelwise layers to build bridges upon, for examples levels = [1,2] will attempt to form airbridges on the L1 and L2 layers. Representing air bridges as a metallic staple is a basic modeling simplification made for purposes of simulation. The support and bridge shapes are intersected to form a bridge platform which is then connected to the underlying surface with legs which run parallel to the path.

           ______
         >|      |< support
     _____|      |_____
  > |                  |< bridge
  > |_____        _____|
        > |      |
        > |______|
           > /> ||
           > ||< path

Outputs a 2D physical group named output ("bridge_metal" by default) containing the rectangular bridge "legs" and "platform".

source

Meshing

DeviceLayout.SolidModels.MeshingParametersType
Base.@kwdef struct MeshingParameters
    mesh_scale::Float64 = 1.0
    mesh_order::Int = 1
    α_default::Float64 = 0.75
    apply_size_to_surfaces::Bool = false
    high_order_optimize::Int = 1
    surface_mesh_algorithm::Int = 6
    volume_mesh_algorithm::Int = 1
    options::Dict{String, Float64} = Dict{String, Float64}()
end

α

Deprecated

This struct is deprecated. See render!

MeshingParameters contains high level parameters to specify mesh sizing fields throughout the domain.

  • mesh_scale applies multiplicatively to the smallest size specified by any size field function, comparing to the formula in the MeshSized style, this results in all mesh size fields being rescaled where hmesh_scale * h.
  • mesh_order specifies the order of polynomials to use in representing the geometry, this is important if curved geometric features are present, mesh_order == 1 will represent the geometry with linear polynomials, whilst mesh_order == 2 will represent it with quadratic polynomials, and mesh_order == 3 with cubic polynomials. Increasing the value of mesh_order results in greater geometric fidelity, whilst making meshing more difficult (and prone to errors).
  • α_default specifies the default value of α to use for MeshSized entities where α is set to less than 0, α_default ∈ (0, 1] is particularly used for the default grading of Path entities. A value closer to 1 can result in an unstable meshing algorithm in gmsh, particularly for complex geometries.
  • apply_size_to_surfaces=true will cause the mesh sizing field to specify the size within any sized entities, as opposed to only along the perimeter of the entity if apply_size_to_surfaces=false. Setting apply_size_to_surfaces=true will result in a larger number of elements.
  • high_order_optimize=0 flag to pass to gmsh if optimization of a higher order mesh is to be performed. (0: none, 1: optimization, 2: elastic+optimization, 3: elastic, 4: fast curving). Refer to the gmsh documentation for more details.
  • surface_mesh_algorithm specifies the algorithm gmsh should use when performing the surface mesh generation. Refer to the gmsh documentation for more details.
  • volume_mesh_algorithm specifies the algorithm gmsh should use when performing the volume mesh generation. Refer to the gmsh documentation for more details.
  • options used to specify any additional options provided to gmsh, which will be set with gmsh.options.set_number(key, value) for each key => value pair. Refer to the gmsh documentation for a list of available options. Will override any other options as is called last.
source
DeviceLayout.SolidModels.mesh_orderFunction
mesh_order()
mesh_order(order, higher_order_optimize=1)

Get or set the mesh element order and optimization level.

Higher order elements provide better geometric fidelity for curved boundaries but increase meshing complexity.

source
DeviceLayout.SolidModels.mesh_scaleFunction
mesh_scale()
mesh_scale(s)

Get or set the global mesh scaling factor.

The mesh scale adjusts the minimum for all size fields, from h adjacent to a sized entity, to mesh_scale * h. It does not reduce the size in the far field, and is most appropriate for refining geometric features such as curves, which might require additional local refinement to capture the geometry, but do not require refinement non-locally.

See DeviceLayout.MeshSized for more details and the explicit mesh sizing formula.

source
DeviceLayout.SolidModels.set_gmsh_optionFunction
set_gmsh_option(s, o::Number)
set_gmsh_option(s, o::AbstractString)
set_gmsh_option(s, d::Dict, default)
set_gmsh_option(d::Dict)

Set gmsh configuration options.

Methods

  • set_gmsh_option(option_name, value): Set a single option to a numeric or string value
  • set_gmsh_option(option_name, dict, default): Set option from dict with fallback to default
  • set_gmsh_option(option_name, dict): Set option from dict if option_name is present
  • set_gmsh_option(dict): Set multiple options from a dictionary

Arguments

  • s: Option name as string (e.g., "Mesh.Algorithm", "General.NumThreads")
  • o: Option value (Number or String)
  • d: Dictionary containing option name-value pairs
  • default: Default value if option not found in dictionary

Examples

set_gmsh_option("Mesh.Algorithm", 6)
set_gmsh_option("General.FileName", "output.msh")
set_gmsh_option("General.FileName", Dict("Mesh.Algorithm" => 6)) # does nothing
set_gmsh_option(Dict("Mesh.Algorithm" => 6, "General.NumThreads" => 4))
source
DeviceLayout.SolidModels.get_gmsh_numberFunction
get_gmsh_number(s)

Get a numeric option value from gmsh.

Arguments

  • s: Option name as string (e.g., "Mesh.ElementOrder")

Returns the current numeric value of the specified gmsh option.

source
DeviceLayout.SolidModels.get_gmsh_stringFunction
get_gmsh_string(s)

Get a string option value from gmsh.

Arguments

  • s: Option name as string (e.g., "General.FileName")

Returns the current string value of the specified gmsh option.

source
DeviceLayout.SolidModels.mesh_control_pointsFunction
mesh_control_points()

Get the dictionary of mesh size control points grouped by (h, α) parameters.

Returns a Dict{Tuple{Float64, Float64}, Vector{SVector{3, Float64}}} where keys are (mesh_size, grading_parameter) tuples and values are vectors of 3D points.

If this dictionary is modified, by erasing points or adding points using add_mesh_size_point, then it is necessary to call finalize_size_fields! to rebuild the KDTree from the data, else any resulting mesh will not reflect the change in data.

See DeviceLayout.MeshSized for details and the explicit mesh sizing formula utilizing the control points.

source
DeviceLayout.SolidModels.mesh_control_treesFunction
mesh_control_trees()

Get the dictionary of KDTrees for efficient spatial queries of mesh size control points.

Returns a Dict{Tuple{Float64, Float64}, KDTree} where keys are (mesh_size, grading_parameter) tuples and values are KDTrees for fast nearest-neighbor lookups.

See DeviceLayout.MeshSized for details and the explicit mesh sizing formula computed using the control trees.

source
DeviceLayout.SolidModels.add_mesh_size_pointFunction
add_mesh_size_point(; h, α=-1, p)

Add a mesh size control point to the global mesh sizing parameters.

Arguments

  • p: 3D point coordinates where mesh size is controlled. Can be a single point, or array of concatenated points [x1,y1,z1,x2,y2,z2,...].
  • h: Target mesh size at the point
  • α: Mesh grading parameter (α ≤ 1). If negative the default global value will be used when the size trees are regenerated. All negative values are mapped together for efficient KDTree calculations.

The point is added to a collection grouped by (h, α) values for efficient mesh size field computation. This is a manual override that occurs in addition to those control points generated by a geometry, in general mesh size points should be encoded directly within component definitions but manual additional points can be helpful in prototyping.

See DeviceLayout.MeshSized for details and the explicit mesh sizing formula.

source