Solid Models

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

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

Rendering to a SolidModel

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.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

Postrendering operations

After adding the elements of a CoordinateSystem to a SolidModel ("rendering"), we can perform additional "postrendering" operations including boolean operations, extrusions, and selections, to create new PhysicalGroups.

The recommended pattern is to provide all postrendering operations to the postrender_ops keyword argument in render!, because render! performs important cleanup at the very end. Specifically, it removes duplicate elements using the fragment operation; because this can also change the labeling of elements, it then reassigns the resulting elements to their corresponding groups.

Boolean operations and infix equivalents:

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.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.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.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
Base.:+Method
+(object::AbstractPhysicalGroup, tool::AbstractPhysicalGroup)

Equivalent to union_geom!(object, tool). Can be used as an infix (object + tool).

source
Base.:∪Method
∪(object::AbstractPhysicalGroup, tool::AbstractPhysicalGroup)

Equivalent to union_geom!(object, tool). Can be used as an infix (object ∪ tool).

source
Base.:-Method
-(object::AbstractPhysicalGroup, tool::AbstractPhysicalGroup)

Equivalent to difference_geom!(object, tool). Can be used as an infix (object - tool).

source
Base.:*Method
*(object::AbstractPhysicalGroup, tool::AbstractPhysicalGroup)

Equivalent to intersect_geom!(object, tool). Can be used as an infix (object * tool).

source
Base.:∩Method
∩(object::AbstractPhysicalGroup, tool::AbstractPhysicalGroup)

Equivalent to intersect_geom!(object, tool). Can be used as an infix (object ∩ tool).

source

Selections:

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.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

Other operations:

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.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

Meshing

Entities can carry mesh sizing information with them when rendered to a SolidModel. Many entities will default to a maximal size to reasonably resolve the geometry. This is particularly useful together with adaptive mesh refinement to efficiently refine your mesh to minimize estimated error with as few elements as possible. You can also style entities with MeshSized to manually control mesh sizing, the SolidModels.mesh_scale, SolidModels.mesh_order and SolidModels.mesh_grading_default methods are used to modify the global default parameters used in each sizing field (see MeshSized).

Size fields within a SolidModel are specified in terms of control points, which are spatial locations combined with an (h, α) as in MeshSized. When a model is rendered, a set of control points are computed from the geometry, and these are then used to create KDTree structures to allow for rapid evaluation. Additional points can be manually inserted after render! is called using DeviceLayout.SolidModels.add_mesh_size_point, and the global size parameters SolidModels.mesh_scale, SolidModels.mesh_order and SolidModels.mesh_grading_default modified without requiring render! to be called again. This allows for iteration on the mesh for a given fixed geometry. Manual modification of the control points is in general not necessary but can be achieved through DeviceLayout.SolidModels.add_mesh_size_point, DeviceLayout.SolidModels.finalize_size_fields!, DeviceLayout.SolidModels.clear_mesh_control_points! and DeviceLayout.SolidModels.reset_mesh_control!. Once an improved mesh has been achieved through addition of custom size fields like this, it is generally suggested to incorporate this information back into the MeshSized style used on the original entities.

Info

If SolidModels.mesh_control_points is modified, then it is important to call SolidModels.finalize_size_fields! in order to ensure that the KDTree are rebuilt. Additionally, to generate a new mesh SolidModels.gmsh.model.mesh.clear() must be called otherwise gmsh will return only any previously generated mesh.

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

Example

Below, we create a 3D model of a meandered CPW on a chip, restricting the model to a small volume (for example, for the purposes of simulation).

using DeviceLayout
using FileIO

cs = CoordinateSystem("test", nm)

# Create a CPW meander
pa = Path(-0.5mm, 0nm)
straight!(pa, 900μm, Paths.SimpleCPW(10μm, 6μm))
turn!(pa, 180°, 50μm)
straight!(pa, 900μm)
turn!(pa, -180°, 50μm)
straight!(pa, 900μm)
turn!(pa, 180°, 50μm)
straight!(pa, 900μm)
terminate!(pa)
render!(cs, pa, SemanticMeta(:base_negative))

render!(cs, centered(Rectangle(10mm, 10mm)), SemanticMeta(:chip_area))
render!(cs, centered(Rectangle(9mm, 9mm)), SemanticMeta(:writeable_area))
render!(cs, centered(Rectangle(2mm, 2mm)), SemanticMeta(:simulated_area))

# Define z heights and thickness (where nonzero)
layer_z = Dict(:chip_area => -525μm, :simulated_area => -1mm)
layer_thickness = Dict(:chip_area => 525μm, :simulated_area => 2mm)

# Define postrendering operations:
# Extrusions, geometric Boolean operations, and other transformations
postrender_ops = vcat(
    [   # Extrude layers with nonzero thickness
        (string(layer) * "_extrusion", SolidModels.extrude_z!, (layer, thickness)) for
        (layer, thickness) in pairs(layer_thickness)
    ],
    [   # sm["chip_sim"] = intersect_geom!(sm, "simulated_area_extrusion", ...)
        (   # Intersect chip volume with simulation volume
            "chip_sim", # New physical group name
            SolidModels.intersect_geom!, # Operation
            # Arguments: Object, tool, object dimension, tool dimension
            ("simulated_area_extrusion", "chip_area_extrusion", 3, 3), # Vol ∩ Vol
            # Keyword arguments
            :remove_tool => true # Remove the "chip_area_extrusion" group
        ),
        (   # Intersect writeable area with simulation volume
            "writeable_sim",
            SolidModels.intersect_geom!,
            ("simulated_area_extrusion", "writeable_area", 3, 2), # Volume ∩ Area
            :remove_tool => true # Remove "writeable_area" group
        ),
        (   # Create group for non-chip volumes (vacuum)
            "vac_sim",
            SolidModels.difference_geom!, # Subtract "tool" from "object"
            ("simulated_area_extrusion", "chip_sim", 3, 3),
            :remove_object => true # Remove "simulated_area_extrusion" group
        ),
        (   # Subtract negative from writeable area to get metal area
            "base_metal",
            SolidModels.difference_geom!,
            ("writeable_sim", "base_negative"), # Uses default dimension 2
            :remove_object => true # Remove "writeable_sim" group
        )
    ]
)

sm = SolidModel("model"; overwrite=true)
SolidModels.render!(
    sm,
    cs,
    zmap=(m) -> get(layer_z, layer(m), 0μm),
    postrender_ops=postrender_ops
)
SolidModels.gmsh.model.mesh.generate() # Generate default mesh (low quality)
save("model.msh2", sm) # Use older MSH v2 format (Gmsh format compatible with Palace)
# save("model.stp", sm) # Use standard STEP format
SolidModels.gmsh.finalize() # Finalize the Gmsh API when done using Gmsh