feat: Added BoundConds Node & Fancy PML Node
We now have a solid category (w/accompanying sockets) for defining boundary conditions. We also have a single-boundary-condition node for fully configuring the all-important PML condition. Some insights: - PEC/PMC are so dead-simple that giving them their own nodes doesn't even make sense. - StablePML and PML are the same, just with differing layers. Chose to require the user add layers to the PML node for the same effect. - "Periodic" is a special case of "Bloch", so we only need "Bloch". - "Absorber" vs "PML" is an important choice for the user, which we must ensure shines through.main
parent
7263d585e5
commit
f60b736584
18
TODO.md
18
TODO.md
|
@ -1,10 +1,10 @@
|
||||||
# Working TODO
|
# Working TODO
|
||||||
- [x] Wave Constant
|
- [x] Wave Constant
|
||||||
- Bounds
|
- Bounds
|
||||||
- [ ] Boundary Conds
|
- [x] Boundary Conds
|
||||||
- [ ] PML
|
- [x] PML
|
||||||
- [ ] PEC
|
- [x] PEC
|
||||||
- [ ] PMC
|
- [x] PMC
|
||||||
- [ ] Bloch
|
- [ ] Bloch
|
||||||
- [ ] Absorbing
|
- [ ] Absorbing
|
||||||
- Sources
|
- Sources
|
||||||
|
@ -198,13 +198,11 @@
|
||||||
|
|
||||||
## Bounds
|
## Bounds
|
||||||
- [x] Boundary Conds
|
- [x] Boundary Conds
|
||||||
- [ ] Boundary Cond / PML Bound Face
|
- [x] Boundary Cond / PML Bound Cond
|
||||||
- [ ] Dropdown for "Normal" and "Stable"
|
- [ ] 1D plot visualizing the effect of parameters on a 1D wave function
|
||||||
- [ ] Boundary Cond / PEC Bound Face
|
- [ ] Boundary Cond / Bloch Bound Cond
|
||||||
- [ ] Boundary Cond / PMC Bound Face
|
|
||||||
- [ ] Boundary Cond / Bloch Bound Face
|
|
||||||
- [ ] Implement "simple" mode aka "periodic" mode in Tidy3D
|
- [ ] Implement "simple" mode aka "periodic" mode in Tidy3D
|
||||||
- [ ] Boundary Cond / Absorbing Bound Face
|
- [ ] Boundary Cond / Absorbing Bound Cond
|
||||||
|
|
||||||
## Monitors
|
## Monitors
|
||||||
- [x] EH Field Monitor
|
- [x] EH Field Monitor
|
||||||
|
|
|
@ -40,6 +40,7 @@ from .flow_signals import FlowSignal
|
||||||
from .icons import Icon
|
from .icons import Icon
|
||||||
from .mobj_types import ManagedObjType
|
from .mobj_types import ManagedObjType
|
||||||
from .node_types import NodeType
|
from .node_types import NodeType
|
||||||
|
from .sim_types import BoundCondType
|
||||||
from .socket_colors import SOCKET_COLORS
|
from .socket_colors import SOCKET_COLORS
|
||||||
from .socket_types import SocketType
|
from .socket_types import SocketType
|
||||||
from .tree_types import TreeType
|
from .tree_types import TreeType
|
||||||
|
@ -77,6 +78,7 @@ __all__ = [
|
||||||
'BLSocketInfo',
|
'BLSocketInfo',
|
||||||
'BLSocketType',
|
'BLSocketType',
|
||||||
'NodeType',
|
'NodeType',
|
||||||
|
'BoundCondType',
|
||||||
'NodeCategory',
|
'NodeCategory',
|
||||||
'NODE_CAT_LABELS',
|
'NODE_CAT_LABELS',
|
||||||
'ManagedObjType',
|
'ManagedObjType',
|
||||||
|
|
|
@ -90,8 +90,6 @@ class NodeType(blender_type_enum.BlenderTypeEnum):
|
||||||
BoundConds = enum.auto()
|
BoundConds = enum.auto()
|
||||||
## Bounds / Bound Conds
|
## Bounds / Bound Conds
|
||||||
PMLBoundCond = enum.auto()
|
PMLBoundCond = enum.auto()
|
||||||
PECBoundCond = enum.auto()
|
|
||||||
PMCBoundCond = enum.auto()
|
|
||||||
BlochBoundCond = enum.auto()
|
BlochBoundCond = enum.auto()
|
||||||
AbsorbingBoundCond = enum.auto()
|
AbsorbingBoundCond = enum.auto()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
"""Declares various simulation types for use by nodes and sockets."""
|
||||||
|
|
||||||
|
import enum
|
||||||
|
import typing as typ
|
||||||
|
|
||||||
|
import tidy3d as td
|
||||||
|
|
||||||
|
|
||||||
|
class BoundCondType(enum.StrEnum):
|
||||||
|
r"""A type of boundary condition, applied to a half-axis of a simulation domain.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
Pml: "Perfectly Matched Layer" models infinite free space.
|
||||||
|
**Should be placed sufficiently far** (ex. $\frac{\lambda}{2}) from any active structures to mitigate divergence.
|
||||||
|
Periodic: Denotes Bloch-basedrepetition
|
||||||
|
Pec: "Perfect Electrical Conductor" models a surface that perfectly reflects electric fields.
|
||||||
|
Pmc: "Perfect Magnetic Conductor" models a surface that perfectly reflects the magnetic fields.
|
||||||
|
"""
|
||||||
|
|
||||||
|
Pml = enum.auto()
|
||||||
|
Periodic = enum.auto()
|
||||||
|
Pec = enum.auto()
|
||||||
|
Pmc = enum.auto()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def to_name(v: typ.Self) -> str:
|
||||||
|
"""Convert the enum value to a human-friendly name.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
Used to print names in `EnumProperty`s based on this enum.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A human-friendly name corresponding to the enum value.
|
||||||
|
"""
|
||||||
|
BCT = BoundCondType
|
||||||
|
return {
|
||||||
|
BCT.Pml: 'PML',
|
||||||
|
BCT.Pec: 'PEC',
|
||||||
|
BCT.Pmc: 'PMC',
|
||||||
|
BCT.Periodic: 'Periodic',
|
||||||
|
}[v]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def to_icon(_: typ.Self) -> str:
|
||||||
|
"""Convert the enum value to a Blender icon.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
Used to print icons in `EnumProperty`s based on this enum.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A human-friendly name corresponding to the enum value.
|
||||||
|
"""
|
||||||
|
return ''
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tidy3d_boundary_edge(self) -> td.BoundaryEdge:
|
||||||
|
"""Convert the boundary condition specifier to a corresponding, sensible `tidy3d` boundary edge.
|
||||||
|
|
||||||
|
`td.BoundaryEdge` can be used to declare a half-axis in a `td.BoundarySpec`, which attaches directly to a simulation object.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A sensible choice of `tidy3d` object representing the boundary condition.
|
||||||
|
"""
|
||||||
|
BCT = BoundCondType
|
||||||
|
return {
|
||||||
|
BCT.Pml: td.PML(),
|
||||||
|
BCT.Pec: td.PECBoundary(),
|
||||||
|
BCT.Pmc: td.PMCBoundary(),
|
||||||
|
BCT.Periodic: td.Periodic(),
|
||||||
|
}[self]
|
|
@ -1,6 +1,6 @@
|
||||||
from . import (
|
from . import (
|
||||||
analysis,
|
analysis,
|
||||||
# bounds,
|
bounds,
|
||||||
inputs,
|
inputs,
|
||||||
# mediums,
|
# mediums,
|
||||||
monitors,
|
monitors,
|
||||||
|
@ -18,7 +18,7 @@ BL_REGISTER = [
|
||||||
# *sources.BL_REGISTER,
|
# *sources.BL_REGISTER,
|
||||||
# *mediums.BL_REGISTER,
|
# *mediums.BL_REGISTER,
|
||||||
# *structures.BL_REGISTER,
|
# *structures.BL_REGISTER,
|
||||||
# *bounds.BL_REGISTER,
|
*bounds.BL_REGISTER,
|
||||||
*monitors.BL_REGISTER,
|
*monitors.BL_REGISTER,
|
||||||
# *simulations.BL_REGISTER,
|
# *simulations.BL_REGISTER,
|
||||||
# *utilities.BL_REGISTER,
|
# *utilities.BL_REGISTER,
|
||||||
|
@ -30,7 +30,7 @@ BL_NODES = {
|
||||||
# **sources.BL_NODES,
|
# **sources.BL_NODES,
|
||||||
# **mediums.BL_NODES,
|
# **mediums.BL_NODES,
|
||||||
# **structures.BL_NODES,
|
# **structures.BL_NODES,
|
||||||
# **bounds.BL_NODES,
|
**bounds.BL_NODES,
|
||||||
**monitors.BL_NODES,
|
**monitors.BL_NODES,
|
||||||
# **simulations.BL_NODES,
|
# **simulations.BL_NODES,
|
||||||
# **utilities.BL_NODES,
|
# **utilities.BL_NODES,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
from . import bound_box, bound_faces
|
from . import bound_cond_nodes, bound_conds
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
*bound_box.BL_REGISTER,
|
*bound_conds.BL_REGISTER,
|
||||||
*bound_faces.BL_REGISTER,
|
*bound_cond_nodes.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
**bound_box.BL_NODES,
|
**bound_conds.BL_NODES,
|
||||||
**bound_faces.BL_NODES,
|
**bound_cond_nodes.BL_NODES,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
import tidy3d as td
|
|
||||||
|
|
||||||
from ... import contracts as ct
|
|
||||||
from ... import sockets
|
|
||||||
from .. import base, events
|
|
||||||
|
|
||||||
|
|
||||||
class BoundCondsNode(base.MaxwellSimNode):
|
|
||||||
node_type = ct.NodeType.BoundConds
|
|
||||||
bl_label = 'Bound Box'
|
|
||||||
# bl_icon = ...
|
|
||||||
|
|
||||||
####################
|
|
||||||
# - Sockets
|
|
||||||
####################
|
|
||||||
input_sockets = {
|
|
||||||
'+X': sockets.MaxwellBoundCondSocketDef(),
|
|
||||||
'-X': sockets.MaxwellBoundCondSocketDef(),
|
|
||||||
'+Y': sockets.MaxwellBoundCondSocketDef(),
|
|
||||||
'-Y': sockets.MaxwellBoundCondSocketDef(),
|
|
||||||
'+Z': sockets.MaxwellBoundCondSocketDef(),
|
|
||||||
'-Z': sockets.MaxwellBoundCondSocketDef(),
|
|
||||||
}
|
|
||||||
output_sockets = {
|
|
||||||
'BCs': sockets.MaxwellBoundCondsSocketDef(),
|
|
||||||
}
|
|
||||||
|
|
||||||
####################
|
|
||||||
# - Output Socket Computation
|
|
||||||
####################
|
|
||||||
@events.computes_output_socket(
|
|
||||||
'BCs', input_sockets={'+X', '-X', '+Y', '-Y', '+Z', '-Z'}
|
|
||||||
)
|
|
||||||
def compute_simulation(self, input_sockets) -> td.BoundarySpec:
|
|
||||||
x_pos = input_sockets['+X']
|
|
||||||
x_neg = input_sockets['-X']
|
|
||||||
y_pos = input_sockets['+Y']
|
|
||||||
y_neg = input_sockets['-Y']
|
|
||||||
z_pos = input_sockets['+Z']
|
|
||||||
z_neg = input_sockets['-Z']
|
|
||||||
|
|
||||||
return td.BoundarySpec(
|
|
||||||
x=td.Boundary(
|
|
||||||
plus=x_pos,
|
|
||||||
minus=x_neg,
|
|
||||||
),
|
|
||||||
y=td.Boundary(
|
|
||||||
plus=y_pos,
|
|
||||||
minus=y_neg,
|
|
||||||
),
|
|
||||||
z=td.Boundary(
|
|
||||||
plus=z_pos,
|
|
||||||
minus=z_neg,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
|
||||||
# - Blender Registration
|
|
||||||
####################
|
|
||||||
BL_REGISTER = [
|
|
||||||
BoundCondsNode,
|
|
||||||
]
|
|
||||||
BL_NODES = {ct.NodeType.BoundConds: (ct.NodeCategory.MAXWELLSIM_BOUNDS)}
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
from . import (
|
||||||
|
#absorbing_bound_cond,
|
||||||
|
#bloch_bound_cond,
|
||||||
|
pml_bound_cond,
|
||||||
|
)
|
||||||
|
|
||||||
|
BL_REGISTER = [
|
||||||
|
*pml_bound_cond.BL_REGISTER,
|
||||||
|
#*bloch_bound_cond.BL_REGISTER,
|
||||||
|
#*absorbing_bound_cond.BL_REGISTER,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
**pml_bound_cond.BL_NODES,
|
||||||
|
#**bloch_bound_cond.BL_NODES,
|
||||||
|
#**absorbing_bound_cond.BL_NODES,
|
||||||
|
}
|
|
@ -0,0 +1,190 @@
|
||||||
|
"""Implements `PMLBoundCondNode`."""
|
||||||
|
|
||||||
|
import typing as typ
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import sympy as sp
|
||||||
|
import tidy3d as td
|
||||||
|
|
||||||
|
from blender_maxwell.utils import extra_sympy_units as spux
|
||||||
|
from blender_maxwell.utils import logger
|
||||||
|
|
||||||
|
from .... import contracts as ct
|
||||||
|
from .... import sockets
|
||||||
|
from ... import base, events
|
||||||
|
|
||||||
|
log = logger.get(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class PMLBoundCondNode(base.MaxwellSimNode):
|
||||||
|
r"""A "Perfectly Matched Layer" boundary condition, which is a theoretical medium that attempts to _perfectly_ absorb all outgoing waves, so as to represent "infinite space" in FDTD simulations.
|
||||||
|
|
||||||
|
PML boundary conditions do so by inducing a **frequency-dependent attenuation** on all waves that are outside of the boundary, over the course of several layers.
|
||||||
|
|
||||||
|
It is critical to note that a PML boundary can only absorb **propagating** waves.
|
||||||
|
_Evanescent_ waves oscillating w/o any power flux, ex. close to structures, may actually be **amplified** by a PML boundary.
|
||||||
|
This is the reasoning behind the $\frac{\lambda}{2}$-distance rule of thumb.
|
||||||
|
|
||||||
|
For more theoretical details, please refer to the `tidy3d` resource: <https://docs.flexcompute.com/projects/tidy3d/en/latest/api/_autosummary/tidy3d.PML.html>
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
**Ensure** that all simulation structures are $\approx \frac{\lambda}{2}$ from any PML boundary.
|
||||||
|
|
||||||
|
This helps avoid the amplification of stray evanescent waves.
|
||||||
|
|
||||||
|
Socket Sets:
|
||||||
|
Simple: Only specify the number of PML layers.
|
||||||
|
$12$ should cover the most common cases; $40$ should be extremely stable.
|
||||||
|
Full: Specify the conductivity min/max that make up the PML, as well as the order of approximating polynomials.
|
||||||
|
The meaning of the parameters are rooted in the mathematics that underlie the PML function - if that doesn't mean anything to you, then you should probably leave it alone!
|
||||||
|
Since the value units are sim-relative, we've opted to show the scaling information in the node's UI, instead of coercing the values into any particular unit.
|
||||||
|
"""
|
||||||
|
|
||||||
|
node_type = ct.NodeType.PMLBoundCond
|
||||||
|
bl_label = 'PML Bound Cond'
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Sockets
|
||||||
|
####################
|
||||||
|
input_sockets: typ.ClassVar = {
|
||||||
|
'Layers': sockets.ExprSocketDef(
|
||||||
|
shape=None,
|
||||||
|
mathtype=spux.MathType.Integer,
|
||||||
|
abs_min=1,
|
||||||
|
default_value=12,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
input_socket_sets: typ.ClassVar = {
|
||||||
|
'Simple': {},
|
||||||
|
'Full': {
|
||||||
|
'σ Order': sockets.ExprSocketDef(
|
||||||
|
shape=None,
|
||||||
|
mathtype=spux.MathType.Integer,
|
||||||
|
abs_min=1,
|
||||||
|
default_value=3,
|
||||||
|
),
|
||||||
|
'σ Range': sockets.ExprSocketDef(
|
||||||
|
shape=(2,),
|
||||||
|
mathtype=spux.MathType.Real,
|
||||||
|
default_value=sp.Matrix([0, 1.5]),
|
||||||
|
abs_min=0,
|
||||||
|
),
|
||||||
|
'κ Order': sockets.ExprSocketDef(
|
||||||
|
shape=None,
|
||||||
|
mathtype=spux.MathType.Integer,
|
||||||
|
abs_min=1,
|
||||||
|
default_value=3,
|
||||||
|
),
|
||||||
|
'κ Range': sockets.ExprSocketDef(
|
||||||
|
shape=(2,),
|
||||||
|
mathtype=spux.MathType.Real,
|
||||||
|
default_value=sp.Matrix([0, 1.5]),
|
||||||
|
abs_min=0,
|
||||||
|
),
|
||||||
|
'α Order': sockets.ExprSocketDef(
|
||||||
|
shape=None,
|
||||||
|
mathtype=spux.MathType.Integer,
|
||||||
|
abs_min=1,
|
||||||
|
default_value=3,
|
||||||
|
),
|
||||||
|
'α Range': sockets.ExprSocketDef(
|
||||||
|
shape=(2,),
|
||||||
|
mathtype=spux.MathType.Real,
|
||||||
|
default_value=sp.Matrix([0, 1.5]),
|
||||||
|
abs_min=0,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output_sockets: typ.ClassVar = {
|
||||||
|
'BC': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - UI
|
||||||
|
####################
|
||||||
|
def draw_info(self, _: bpy.types.Context, layout: bpy.types.UILayout) -> None:
|
||||||
|
if self.active_socket_set == 'Full':
|
||||||
|
box = layout.box()
|
||||||
|
row = box.row()
|
||||||
|
row.alignment = 'CENTER'
|
||||||
|
row.label(text='Parameter Scale')
|
||||||
|
|
||||||
|
# Split
|
||||||
|
split = box.split(factor=0.4, align=False)
|
||||||
|
|
||||||
|
## LHS: Parameter Names
|
||||||
|
col = split.column()
|
||||||
|
col.alignment = 'RIGHT'
|
||||||
|
for param in ['σ', 'κ', 'α']:
|
||||||
|
col.label(text=param + ':')
|
||||||
|
|
||||||
|
## RHS: Parameter Units
|
||||||
|
col = split.column()
|
||||||
|
for _ in range(3):
|
||||||
|
col.label(text='2ε₀/Δt')
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Output
|
||||||
|
####################
|
||||||
|
@events.computes_output_socket(
|
||||||
|
'BC',
|
||||||
|
props={'active_socket_set'},
|
||||||
|
input_sockets={
|
||||||
|
'Layers',
|
||||||
|
'σ Order',
|
||||||
|
'σ Range',
|
||||||
|
'κ Order',
|
||||||
|
'κ Range',
|
||||||
|
'α Order',
|
||||||
|
'α Range',
|
||||||
|
},
|
||||||
|
input_sockets_optional={
|
||||||
|
'σ Order': True,
|
||||||
|
'σ Range': True,
|
||||||
|
'κ Order': True,
|
||||||
|
'κ Range': True,
|
||||||
|
'α Order': True,
|
||||||
|
'α Range': True,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
def compute_pml_boundary_cond(self, props, input_sockets) -> td.BoundarySpec:
|
||||||
|
r"""Computes the PML boundary condition based on the active socket set.
|
||||||
|
|
||||||
|
- **Simple**: Use `tidy3d`'s default parameters for defining the PML conductor.
|
||||||
|
- **Full**: Use the user-defined $\sigma$, $\kappa$, and $\alpha$ parameters, specifically polynomial order, and sim-relative min/max conductivity values.
|
||||||
|
"""
|
||||||
|
log.debug(
|
||||||
|
'%s: Computing "%s" PML Boundary Condition (Input Sockets = %s)',
|
||||||
|
self.sim_node_name,
|
||||||
|
props['active_socket_set'],
|
||||||
|
input_sockets,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Simple PML
|
||||||
|
if props['active_socket_set'] == 'Simple':
|
||||||
|
return td.PML(num_layers=input_sockets['Layers'])
|
||||||
|
|
||||||
|
# Full PML
|
||||||
|
return td.PML(
|
||||||
|
num_layers=input_sockets['Layers'],
|
||||||
|
parameters=td.PMLParams(
|
||||||
|
sigma_order=input_sockets['σ Order'],
|
||||||
|
sigma_min=input_sockets['σ Range'][0],
|
||||||
|
sigma_max=input_sockets['σ Range'][1],
|
||||||
|
kappa_order=input_sockets['κ Order'],
|
||||||
|
kappa_min=input_sockets['κ Range'][0],
|
||||||
|
kappa_max=input_sockets['κ Range'][1],
|
||||||
|
alpha_order=input_sockets['α Order'],
|
||||||
|
alpha_min=input_sockets['α Range'][0],
|
||||||
|
alpha_max=input_sockets['α Range'][1],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Registration
|
||||||
|
####################
|
||||||
|
BL_REGISTER = [
|
||||||
|
PMLBoundCondNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {ct.NodeType.PMLBoundCond: (ct.NodeCategory.MAXWELLSIM_BOUNDS_BOUNDCONDS)}
|
|
@ -0,0 +1,155 @@
|
||||||
|
"""Implements `BoundCondsNode`."""
|
||||||
|
|
||||||
|
import typing as typ
|
||||||
|
|
||||||
|
import tidy3d as td
|
||||||
|
|
||||||
|
from blender_maxwell.utils import logger
|
||||||
|
|
||||||
|
from ... import contracts as ct
|
||||||
|
from ... import sockets
|
||||||
|
from .. import base, events
|
||||||
|
|
||||||
|
log = logger.get(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class BoundCondsNode(base.MaxwellSimNode):
|
||||||
|
"""Provides a hub for joining custom simulation domain boundary conditions by-axis."""
|
||||||
|
|
||||||
|
node_type = ct.NodeType.BoundConds
|
||||||
|
bl_label = 'Bound Conds'
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Sockets
|
||||||
|
####################
|
||||||
|
input_socket_sets: typ.ClassVar = {
|
||||||
|
'XYZ': {
|
||||||
|
'X': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'Y': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'Z': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
},
|
||||||
|
'±X | YZ': {
|
||||||
|
'+X': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'-X': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'Y': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'Z': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
},
|
||||||
|
'X | ±Y | Z': {
|
||||||
|
'X': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'+Y': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'-Y': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'Z': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
},
|
||||||
|
'XY | ±Z': {
|
||||||
|
'X': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'Y': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'+Z': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'-Z': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
},
|
||||||
|
'±XY | Z': {
|
||||||
|
'+X': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'-X': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'+Y': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'-Y': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'Z': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
},
|
||||||
|
'X | ±YZ': {
|
||||||
|
'X': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'+Y': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'-Y': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'+Z': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'-Z': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
},
|
||||||
|
'±XYZ': {
|
||||||
|
'+X': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'-X': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'+Y': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'-Y': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'+Z': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
'-Z': sockets.MaxwellBoundCondSocketDef(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
output_sockets: typ.ClassVar = {
|
||||||
|
'BCs': sockets.MaxwellBoundCondsSocketDef(),
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Output Socket Computation
|
||||||
|
####################
|
||||||
|
@events.computes_output_socket(
|
||||||
|
'BCs',
|
||||||
|
input_sockets={'X', 'Y', 'Z', '+X', '-X', '+Y', '-Y', '+Z', '-Z'},
|
||||||
|
input_sockets_optional={
|
||||||
|
'X': True,
|
||||||
|
'Y': True,
|
||||||
|
'Z': True,
|
||||||
|
'+X': True,
|
||||||
|
'-X': True,
|
||||||
|
'+Y': True,
|
||||||
|
'-Y': True,
|
||||||
|
'+Z': True,
|
||||||
|
'-Z': True,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
def compute_boundary_conds(self, input_sockets) -> td.BoundarySpec:
|
||||||
|
"""Compute the simulation boundary conditions, by combining the individual input by specified half axis."""
|
||||||
|
log.debug(
|
||||||
|
'%s: Computing Boundary Conditions (Input Sockets = %s)',
|
||||||
|
self.sim_node_name,
|
||||||
|
str(input_sockets),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Deduce "Doubledness"
|
||||||
|
## -> A "doubled" axis defines the same bound cond both ways
|
||||||
|
has_doubled_x = not ct.FlowSignal.check(input_sockets['X'])
|
||||||
|
has_doubled_y = not ct.FlowSignal.check(input_sockets['Y'])
|
||||||
|
has_doubled_z = not ct.FlowSignal.check(input_sockets['Z'])
|
||||||
|
|
||||||
|
# Deduce +/- of Each Axis
|
||||||
|
## +/- X
|
||||||
|
if has_doubled_x:
|
||||||
|
x_pos = input_sockets['X']
|
||||||
|
x_neg = input_sockets['X']
|
||||||
|
else:
|
||||||
|
x_pos = input_sockets['+X']
|
||||||
|
x_neg = input_sockets['-X']
|
||||||
|
|
||||||
|
## +/- Y
|
||||||
|
if has_doubled_y:
|
||||||
|
y_pos = input_sockets['Y']
|
||||||
|
y_neg = input_sockets['Y']
|
||||||
|
else:
|
||||||
|
y_pos = input_sockets['+Y']
|
||||||
|
y_neg = input_sockets['-Y']
|
||||||
|
|
||||||
|
## +/- Z
|
||||||
|
if has_doubled_z:
|
||||||
|
z_pos = input_sockets['Z']
|
||||||
|
z_neg = input_sockets['Z']
|
||||||
|
else:
|
||||||
|
z_pos = input_sockets['+Z']
|
||||||
|
z_neg = input_sockets['-Z']
|
||||||
|
|
||||||
|
return td.BoundarySpec(
|
||||||
|
x=td.Boundary(
|
||||||
|
plus=x_pos,
|
||||||
|
minus=x_neg,
|
||||||
|
),
|
||||||
|
y=td.Boundary(
|
||||||
|
plus=y_pos,
|
||||||
|
minus=y_neg,
|
||||||
|
),
|
||||||
|
z=td.Boundary(
|
||||||
|
plus=z_pos,
|
||||||
|
minus=z_neg,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Registration
|
||||||
|
####################
|
||||||
|
BL_REGISTER = [
|
||||||
|
BoundCondsNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {ct.NodeType.BoundConds: (ct.NodeCategory.MAXWELLSIM_BOUNDS)}
|
|
@ -1,25 +0,0 @@
|
||||||
from . import (
|
|
||||||
absorbing_bound_face,
|
|
||||||
bloch_bound_face,
|
|
||||||
pec_bound_face,
|
|
||||||
periodic_bound_face,
|
|
||||||
pmc_bound_face,
|
|
||||||
pml_bound_face,
|
|
||||||
)
|
|
||||||
|
|
||||||
BL_REGISTER = [
|
|
||||||
*pml_bound_face.BL_REGISTER,
|
|
||||||
*pec_bound_face.BL_REGISTER,
|
|
||||||
*pmc_bound_face.BL_REGISTER,
|
|
||||||
*bloch_bound_face.BL_REGISTER,
|
|
||||||
*periodic_bound_face.BL_REGISTER,
|
|
||||||
*absorbing_bound_face.BL_REGISTER,
|
|
||||||
]
|
|
||||||
BL_NODES = {
|
|
||||||
**pml_bound_face.BL_NODES,
|
|
||||||
**pec_bound_face.BL_NODES,
|
|
||||||
**pmc_bound_face.BL_NODES,
|
|
||||||
**bloch_bound_face.BL_NODES,
|
|
||||||
**periodic_bound_face.BL_NODES,
|
|
||||||
**absorbing_bound_face.BL_NODES,
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
####################
|
|
||||||
# - Blender Registration
|
|
||||||
####################
|
|
||||||
BL_REGISTER = []
|
|
||||||
BL_NODES = {}
|
|
|
@ -1,5 +0,0 @@
|
||||||
####################
|
|
||||||
# - Blender Registration
|
|
||||||
####################
|
|
||||||
BL_REGISTER = []
|
|
||||||
BL_NODES = {}
|
|
|
@ -1,5 +0,0 @@
|
||||||
####################
|
|
||||||
# - Blender Registration
|
|
||||||
####################
|
|
||||||
BL_REGISTER = []
|
|
||||||
BL_NODES = {}
|
|
|
@ -1,5 +0,0 @@
|
||||||
####################
|
|
||||||
# - Blender Registration
|
|
||||||
####################
|
|
||||||
BL_REGISTER = []
|
|
||||||
BL_NODES = {}
|
|
|
@ -741,6 +741,10 @@ class ExprSocketDef(base.SocketDef):
|
||||||
|
|
||||||
# FlowKind: Value
|
# FlowKind: Value
|
||||||
default_value: spux.SympyExpr = sp.RealNumber(0)
|
default_value: spux.SympyExpr = sp.RealNumber(0)
|
||||||
|
abs_min: spux.SympyExpr | None = None ## TODO: Not used (yet)
|
||||||
|
abs_max: spux.SympyExpr | None = None ## TODO: Not used (yet)
|
||||||
|
## TODO: Idea is to use this scalar uniformly for all shape elements
|
||||||
|
## TODO: -> But we may want to **allow** using same-shape for diff. bounds.
|
||||||
|
|
||||||
# FlowKind: LazyArrayRange
|
# FlowKind: LazyArrayRange
|
||||||
default_min: spux.SympyExpr = sp.RealNumber(0)
|
default_min: spux.SympyExpr = sp.RealNumber(0)
|
||||||
|
@ -831,7 +835,6 @@ class ExprSocketDef(base.SocketDef):
|
||||||
bl_socket.symbols = self.symbols
|
bl_socket.symbols = self.symbols
|
||||||
|
|
||||||
# Socket Units & FlowKind.Value
|
# Socket Units & FlowKind.Value
|
||||||
log.critical(self)
|
|
||||||
if self.physical_type is not None:
|
if self.physical_type is not None:
|
||||||
bl_socket.unit = self.default_unit
|
bl_socket.unit = self.default_unit
|
||||||
bl_socket.value = self.default_value * self.default_unit
|
bl_socket.value = self.default_value * self.default_unit
|
||||||
|
|
|
@ -3,51 +3,45 @@ import typing as typ
|
||||||
import bpy
|
import bpy
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
|
|
||||||
|
from blender_maxwell.utils import bl_cache, logger
|
||||||
|
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
from .. import base
|
from .. import base
|
||||||
|
|
||||||
|
log = logger.get(__name__)
|
||||||
|
|
||||||
|
|
||||||
class MaxwellBoundCondBLSocket(base.MaxwellSimSocket):
|
class MaxwellBoundCondBLSocket(base.MaxwellSimSocket):
|
||||||
|
"""Describes a single of boundary condition to apply to the half-axis of a simulation domain.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
default: The default boundary condition type.
|
||||||
|
"""
|
||||||
|
|
||||||
socket_type = ct.SocketType.MaxwellBoundCond
|
socket_type = ct.SocketType.MaxwellBoundCond
|
||||||
bl_label = 'Maxwell Bound Face'
|
bl_label = 'Maxwell Bound Cond'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
default_choice: bpy.props.EnumProperty(
|
default: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml, prop_ui=True)
|
||||||
name='Bound Face',
|
|
||||||
description='A choice of default boundary face',
|
|
||||||
items=[
|
|
||||||
('PML', 'PML', 'Perfectly matched layer'),
|
|
||||||
('PEC', 'PEC', 'Perfect electrical conductor'),
|
|
||||||
('PMC', 'PMC', 'Perfect magnetic conductor'),
|
|
||||||
('PERIODIC', 'Periodic', 'Infinitely periodic layer'),
|
|
||||||
],
|
|
||||||
default='PML',
|
|
||||||
update=(lambda self, context: self.on_prop_changed('default_choice', context)),
|
|
||||||
)
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI
|
# - UI
|
||||||
####################
|
####################
|
||||||
def draw_value(self, col: bpy.types.UILayout) -> None:
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
col.prop(self, 'default_choice', text='')
|
col.prop(self, self.blfields['default'], text='')
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Computation of Default Value
|
# - Computation of Default Value
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def value(self) -> td.BoundarySpec:
|
def value(self) -> td.BoundaryEdge:
|
||||||
return {
|
return self.default.tidy3d_boundary_edge
|
||||||
'PML': td.PML(num_layers=12),
|
|
||||||
'PEC': td.PECBoundary(),
|
|
||||||
'PMC': td.PMCBoundary(),
|
|
||||||
'PERIODIC': td.Periodic(),
|
|
||||||
}[self.default_choice]
|
|
||||||
|
|
||||||
@value.setter
|
@value.setter
|
||||||
def value(self, value: typ.Literal['PML', 'PEC', 'PMC', 'PERIODIC']) -> None:
|
def value(self, value: ct.BoundCondType) -> None:
|
||||||
self.default_choice = value
|
self.default = value
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
@ -56,10 +50,10 @@ class MaxwellBoundCondBLSocket(base.MaxwellSimSocket):
|
||||||
class MaxwellBoundCondSocketDef(base.SocketDef):
|
class MaxwellBoundCondSocketDef(base.SocketDef):
|
||||||
socket_type: ct.SocketType = ct.SocketType.MaxwellBoundCond
|
socket_type: ct.SocketType = ct.SocketType.MaxwellBoundCond
|
||||||
|
|
||||||
default_choice: typ.Literal['PML', 'PEC', 'PMC', 'PERIODIC'] = 'PML'
|
default: ct.BoundCondType = ct.BoundCondType.Pml
|
||||||
|
|
||||||
def init(self, bl_socket: MaxwellBoundCondBLSocket) -> None:
|
def init(self, bl_socket: MaxwellBoundCondBLSocket) -> None:
|
||||||
bl_socket.value = self.default_choice
|
bl_socket.default = self.default
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -1,123 +1,101 @@
|
||||||
|
"""Implements the `MaxwellBoundCondsBLSocket` socket."""
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
|
|
||||||
|
from blender_maxwell.utils import bl_cache, logger
|
||||||
|
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
from .. import base
|
from .. import base
|
||||||
|
|
||||||
BOUND_FACE_ITEMS = [
|
log = logger.get(__name__)
|
||||||
('PML', 'PML', 'Perfectly matched layer'),
|
|
||||||
('PEC', 'PEC', 'Perfect electrical conductor'),
|
|
||||||
('PMC', 'PMC', 'Perfect magnetic conductor'),
|
|
||||||
('PERIODIC', 'Periodic', 'Infinitely periodic layer'),
|
|
||||||
]
|
|
||||||
BOUND_MAP = {
|
|
||||||
'PML': td.PML(),
|
|
||||||
'PEC': td.PECBoundary(),
|
|
||||||
'PMC': td.PMCBoundary(),
|
|
||||||
'PERIODIC': td.Periodic(),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class MaxwellBoundCondsBLSocket(base.MaxwellSimSocket):
|
class MaxwellBoundCondsBLSocket(base.MaxwellSimSocket):
|
||||||
|
"""Describes a set of boundary conditions to apply to a simulation domain.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
show_definition: Toggle to show/hide default per-axis boundary conditions.
|
||||||
|
x_pos: Default boundary condition to apply at the boundary of the sim domain's positive x-axis.
|
||||||
|
x_neg: Default boundary condition to apply at the boundary of the sim domain's negative x-axis.
|
||||||
|
y_pos: Default boundary condition to apply at the boundary of the sim domain's positive y-axis.
|
||||||
|
y_neg: Default boundary condition to apply at the boundary of the sim domain's negative y-axis.
|
||||||
|
z_pos: Default boundary condition to apply at the boundary of the sim domain's positive z-axis.
|
||||||
|
z_neg: Default boundary condition to apply at the boundary of the sim domain's negative z-axis.
|
||||||
|
"""
|
||||||
|
|
||||||
socket_type = ct.SocketType.MaxwellBoundConds
|
socket_type = ct.SocketType.MaxwellBoundConds
|
||||||
bl_label = 'Maxwell Bound Box'
|
bl_label = 'Maxwell Bound Box'
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Properties
|
# - Properties
|
||||||
####################
|
####################
|
||||||
show_definition: bpy.props.BoolProperty(
|
show_definition: bool = bl_cache.BLField(False, prop_ui=True)
|
||||||
name='Show Bounds Definition',
|
|
||||||
description='Toggle to show bound faces',
|
|
||||||
default=False,
|
|
||||||
update=(lambda self, context: self.on_prop_changed('show_definition', context)),
|
|
||||||
)
|
|
||||||
|
|
||||||
x_pos: bpy.props.EnumProperty(
|
x_pos: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml, prop_ui=True)
|
||||||
name='+x Bound Face',
|
x_neg: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml, prop_ui=True)
|
||||||
description='+x choice of default boundary face',
|
y_pos: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml, prop_ui=True)
|
||||||
items=BOUND_FACE_ITEMS,
|
y_neg: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml, prop_ui=True)
|
||||||
default='PML',
|
z_pos: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml, prop_ui=True)
|
||||||
update=(lambda self, context: self.on_prop_changed('x_pos', context)),
|
z_neg: ct.BoundCondType = bl_cache.BLField(ct.BoundCondType.Pml, prop_ui=True)
|
||||||
)
|
|
||||||
x_neg: bpy.props.EnumProperty(
|
|
||||||
name='-x Bound Face',
|
|
||||||
description='-x choice of default boundary face',
|
|
||||||
items=BOUND_FACE_ITEMS,
|
|
||||||
default='PML',
|
|
||||||
update=(lambda self, context: self.on_prop_changed('x_neg', context)),
|
|
||||||
)
|
|
||||||
y_pos: bpy.props.EnumProperty(
|
|
||||||
name='+y Bound Face',
|
|
||||||
description='+y choice of default boundary face',
|
|
||||||
items=BOUND_FACE_ITEMS,
|
|
||||||
default='PML',
|
|
||||||
update=(lambda self, context: self.on_prop_changed('y_pos', context)),
|
|
||||||
)
|
|
||||||
y_neg: bpy.props.EnumProperty(
|
|
||||||
name='-y Bound Face',
|
|
||||||
description='-y choice of default boundary face',
|
|
||||||
items=BOUND_FACE_ITEMS,
|
|
||||||
default='PML',
|
|
||||||
update=(lambda self, context: self.on_prop_changed('y_neg', context)),
|
|
||||||
)
|
|
||||||
z_pos: bpy.props.EnumProperty(
|
|
||||||
name='+z Bound Face',
|
|
||||||
description='+z choice of default boundary face',
|
|
||||||
items=BOUND_FACE_ITEMS,
|
|
||||||
default='PML',
|
|
||||||
update=(lambda self, context: self.on_prop_changed('z_pos', context)),
|
|
||||||
)
|
|
||||||
z_neg: bpy.props.EnumProperty(
|
|
||||||
name='-z Bound Face',
|
|
||||||
description='-z choice of default boundary face',
|
|
||||||
items=BOUND_FACE_ITEMS,
|
|
||||||
default='PML',
|
|
||||||
update=(lambda self, context: self.on_prop_changed('z_neg', context)),
|
|
||||||
)
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - UI
|
# - UI
|
||||||
####################
|
####################
|
||||||
def draw_label_row(self, row: bpy.types.UILayout, text) -> None:
|
def draw_label_row(self, row: bpy.types.UILayout, text) -> None:
|
||||||
row.label(text=text)
|
row.label(text=text)
|
||||||
row.prop(self, 'show_definition', toggle=True, text='', icon='MOD_LENGTH')
|
row.prop(
|
||||||
|
self,
|
||||||
|
self.blfields['show_definition'],
|
||||||
|
toggle=True,
|
||||||
|
text='',
|
||||||
|
icon=ct.Icon.ToggleSocketInfo,
|
||||||
|
)
|
||||||
|
|
||||||
def draw_value(self, col: bpy.types.UILayout) -> None:
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
if not self.show_definition:
|
if self.show_definition:
|
||||||
return
|
for axis in ['x', 'y', 'z']:
|
||||||
|
row = col.row(align=False)
|
||||||
|
split = row.split(factor=0.2, align=False)
|
||||||
|
|
||||||
for axis in ['x', 'y', 'z']:
|
_col = split.column(align=True)
|
||||||
row = col.row(align=False)
|
_col.alignment = 'RIGHT'
|
||||||
split = row.split(factor=0.2, align=False)
|
_col.label(text=axis + ' -')
|
||||||
|
_col.label(text=' +')
|
||||||
|
|
||||||
_col = split.column(align=True)
|
_col = split.column(align=True)
|
||||||
_col.alignment = 'RIGHT'
|
_col.prop(self, self.blfields[axis + '_neg'], text='')
|
||||||
_col.label(text=axis + ' -')
|
_col.prop(self, self.blfields[axis + '_pos'], text='')
|
||||||
_col.label(text=' +')
|
|
||||||
|
|
||||||
_col = split.column(align=True)
|
|
||||||
_col.prop(self, axis + '_neg', text='')
|
|
||||||
_col.prop(self, axis + '_pos', text='')
|
|
||||||
|
|
||||||
draw_value_array = draw_value
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Computation of Default Value
|
# - Computation of Default Value
|
||||||
####################
|
####################
|
||||||
@property
|
@property
|
||||||
def value(self) -> td.BoundarySpec:
|
def value(self) -> td.BoundarySpec:
|
||||||
|
"""Compute a user-defined default value for simulation boundary conditions, from certain common/sensible options.
|
||||||
|
|
||||||
|
Each half-axis has a selection pulled from `ct.BoundCondType`.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A usable `tidy3d` boundary specification.
|
||||||
|
"""
|
||||||
|
log.debug(
|
||||||
|
'%s|%s: Computing default value for Boundary Conditions',
|
||||||
|
self.node.sim_node_name,
|
||||||
|
self.bl_label,
|
||||||
|
)
|
||||||
return td.BoundarySpec(
|
return td.BoundarySpec(
|
||||||
x=td.Boundary(
|
x=td.Boundary(
|
||||||
plus=BOUND_MAP[self.x_pos],
|
plus=self.x_pos.tidy3d_boundary_edge,
|
||||||
minus=BOUND_MAP[self.x_neg],
|
minus=self.x_neg.tidy3d_boundary_edge,
|
||||||
),
|
),
|
||||||
y=td.Boundary(
|
y=td.Boundary(
|
||||||
plus=BOUND_MAP[self.y_pos],
|
plus=self.y_pos.tidy3d_boundary_edge,
|
||||||
minus=BOUND_MAP[self.y_neg],
|
minus=self.y_neg.tidy3d_boundary_edge,
|
||||||
),
|
),
|
||||||
z=td.Boundary(
|
z=td.Boundary(
|
||||||
plus=BOUND_MAP[self.z_pos],
|
plus=self.z_pos.tidy3d_boundary_edge,
|
||||||
minus=BOUND_MAP[self.z_neg],
|
minus=self.z_neg.tidy3d_boundary_edge,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -128,8 +106,20 @@ class MaxwellBoundCondsBLSocket(base.MaxwellSimSocket):
|
||||||
class MaxwellBoundCondsSocketDef(base.SocketDef):
|
class MaxwellBoundCondsSocketDef(base.SocketDef):
|
||||||
socket_type: ct.SocketType = ct.SocketType.MaxwellBoundConds
|
socket_type: ct.SocketType = ct.SocketType.MaxwellBoundConds
|
||||||
|
|
||||||
|
default_x_pos: ct.BoundCondType = ct.BoundCondType.Pml
|
||||||
|
default_x_neg: ct.BoundCondType = ct.BoundCondType.Pml
|
||||||
|
default_y_pos: ct.BoundCondType = ct.BoundCondType.Pml
|
||||||
|
default_y_neg: ct.BoundCondType = ct.BoundCondType.Pml
|
||||||
|
default_z_pos: ct.BoundCondType = ct.BoundCondType.Pml
|
||||||
|
default_z_neg: ct.BoundCondType = ct.BoundCondType.Pml
|
||||||
|
|
||||||
def init(self, bl_socket: MaxwellBoundCondsBLSocket) -> None:
|
def init(self, bl_socket: MaxwellBoundCondsBLSocket) -> None:
|
||||||
pass
|
bl_socket.x_pos = self.default_x_pos
|
||||||
|
bl_socket.x_neg = self.default_x_neg
|
||||||
|
bl_socket.y_pos = self.default_y_pos
|
||||||
|
bl_socket.y_neg = self.default_y_neg
|
||||||
|
bl_socket.z_pos = self.default_z_pos
|
||||||
|
bl_socket.z_neg = self.default_z_neg
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
Loading…
Reference in New Issue