feat: Continue to add features.
See README.md.
parent
e7979f0f06
commit
9a148d7d97
10
README.md
10
README.md
|
@ -38,6 +38,10 @@
|
||||||
- [ ] Pop-up multiline string print as alternative to console print.
|
- [ ] Pop-up multiline string print as alternative to console print.
|
||||||
- [x] Toggleable auto-plot, auto-3D-preview, auto-value-view, (?)auto-text-view.
|
- [x] Toggleable auto-plot, auto-3D-preview, auto-value-view, (?)auto-text-view.
|
||||||
|
|
||||||
|
[x] Web Export / Tidy3D Web Exporter
|
||||||
|
- [ ] We need better ways of doing checks before uploading, like for monitor data size. Maybe a SimInfo node?
|
||||||
|
- [ ] We need to be able to "delete and re-upload" (or maybe just delete from the interface).
|
||||||
|
|
||||||
[x] File Export / JSON File Export
|
[x] File Export / JSON File Export
|
||||||
[ ] File Import / Tidy3D File Export
|
[ ] File Import / Tidy3D File Export
|
||||||
- [ ] Implement HDF-based export of Tidy3D-exported object (which includes ex. mesh data and such)
|
- [ ] Implement HDF-based export of Tidy3D-exported object (which includes ex. mesh data and such)
|
||||||
|
@ -47,6 +51,9 @@
|
||||||
- [ ] Standardize 1D and 2D array loading/saving on numpy's savetxt with gzip enabled.
|
- [ ] Standardize 1D and 2D array loading/saving on numpy's savetxt with gzip enabled.
|
||||||
|
|
||||||
## Viz
|
## Viz
|
||||||
|
[ ] Sim Info
|
||||||
|
- [ ] Implement estimation of monitor storage
|
||||||
|
- [ ] Implement cost estimation
|
||||||
[ ] Monitor Data Viz
|
[ ] Monitor Data Viz
|
||||||
- [ ] Implement dropdown to choose which monitor in the SimulationData should be visualized (based on which are available in the SimulationData), and implement visualization based on every kind of monitor-adjascent output data type (<https://docs.flexcompute.com/projects/tidy3d/en/latest/api/output_data.html>)
|
- [ ] Implement dropdown to choose which monitor in the SimulationData should be visualized (based on which are available in the SimulationData), and implement visualization based on every kind of monitor-adjascent output data type (<https://docs.flexcompute.com/projects/tidy3d/en/latest/api/output_data.html>)
|
||||||
- [ ] Project field values onto a plane object (managed)
|
- [ ] Project field values onto a plane object (managed)
|
||||||
|
@ -61,7 +68,8 @@
|
||||||
[x] Point Dipole Source
|
[x] Point Dipole Source
|
||||||
- [ ] Consider a "real" mesh - the empty kind of gets stuck inside of the sim domain.
|
- [ ] Consider a "real" mesh - the empty kind of gets stuck inside of the sim domain.
|
||||||
[-] Plane Wave Source
|
[-] Plane Wave Source
|
||||||
- [ ] Implement an oriented vector input with 3D preview.
|
- [ ] **IMPORTANT**: Fix the math so that an actually valid construction emerges!!
|
||||||
|
- [x] Implement an oriented vector input with 3D preview.
|
||||||
[ ] Uniform Current Source
|
[ ] Uniform Current Source
|
||||||
[ ] TFSF Source
|
[ ] TFSF Source
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,10 @@ SOCKET_COLORS = {
|
||||||
ST.ComplexNumber: (0.2, 0.2, 0.7, 1.0), # Dark Blue
|
ST.ComplexNumber: (0.2, 0.2, 0.7, 1.0), # Dark Blue
|
||||||
|
|
||||||
# Vector
|
# Vector
|
||||||
|
ST.Integer2DVector: (0.5, 1.0, 0.5, 1.0), # Light Green
|
||||||
ST.Real2DVector: (0.5, 1.0, 0.5, 1.0), # Light Green
|
ST.Real2DVector: (0.5, 1.0, 0.5, 1.0), # Light Green
|
||||||
ST.Complex2DVector: (0.4, 0.9, 0.4, 1.0), # Medium Light Green
|
ST.Complex2DVector: (0.4, 0.9, 0.4, 1.0), # Medium Light Green
|
||||||
|
ST.Integer3DVector: (0.3, 0.8, 0.3, 1.0), # Medium Green
|
||||||
ST.Real3DVector: (0.3, 0.8, 0.3, 1.0), # Medium Green
|
ST.Real3DVector: (0.3, 0.8, 0.3, 1.0), # Medium Green
|
||||||
ST.Complex3DVector: (0.2, 0.7, 0.2, 1.0), # Dark Green
|
ST.Complex3DVector: (0.2, 0.7, 0.2, 1.0), # Dark Green
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,10 @@ SOCKET_SHAPES = {
|
||||||
ST.ComplexNumber: "CIRCLE_DOT",
|
ST.ComplexNumber: "CIRCLE_DOT",
|
||||||
|
|
||||||
# Vector
|
# Vector
|
||||||
|
ST.Integer2DVector: "SQUARE_DOT",
|
||||||
ST.Real2DVector: "SQUARE_DOT",
|
ST.Real2DVector: "SQUARE_DOT",
|
||||||
ST.Complex2DVector: "DIAMOND_DOT",
|
ST.Complex2DVector: "DIAMOND_DOT",
|
||||||
|
ST.Integer3DVector: "SQUARE_DOT",
|
||||||
ST.Real3DVector: "SQUARE_DOT",
|
ST.Real3DVector: "SQUARE_DOT",
|
||||||
ST.Complex3DVector: "DIAMOND_DOT",
|
ST.Complex3DVector: "DIAMOND_DOT",
|
||||||
|
|
||||||
|
|
|
@ -20,10 +20,12 @@ class SocketType(BlenderTypeEnum):
|
||||||
ComplexNumber = enum.auto()
|
ComplexNumber = enum.auto()
|
||||||
|
|
||||||
# Vector
|
# Vector
|
||||||
|
Integer2DVector = enum.auto()
|
||||||
Real2DVector = enum.auto()
|
Real2DVector = enum.auto()
|
||||||
Real2DVectorDir = enum.auto()
|
Real2DVectorDir = enum.auto()
|
||||||
Complex2DVector = enum.auto()
|
Complex2DVector = enum.auto()
|
||||||
|
|
||||||
|
Integer3DVector = enum.auto()
|
||||||
Real3DVector = enum.auto()
|
Real3DVector = enum.auto()
|
||||||
Real3DVectorDir = enum.auto()
|
Real3DVectorDir = enum.auto()
|
||||||
Complex3DVector = enum.auto()
|
Complex3DVector = enum.auto()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import sympy.physics.units as spu
|
import sympy.physics.units as spu
|
||||||
from ....utils import extra_sympy_units as spuex
|
from ....utils import extra_sympy_units as spux
|
||||||
|
|
||||||
from .socket_types import SocketType as ST
|
from .socket_types import SocketType as ST
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ SOCKET_UNITS = {
|
||||||
ST.PhysicalTime: {
|
ST.PhysicalTime: {
|
||||||
"default": "PS",
|
"default": "PS",
|
||||||
"values": {
|
"values": {
|
||||||
|
"FS": spux.femtosecond,
|
||||||
"PS": spu.picosecond,
|
"PS": spu.picosecond,
|
||||||
"NS": spu.nanosecond,
|
"NS": spu.nanosecond,
|
||||||
"MS": spu.microsecond,
|
"MS": spu.microsecond,
|
||||||
|
@ -188,9 +189,9 @@ SOCKET_UNITS = {
|
||||||
"default": "UNEWT",
|
"default": "UNEWT",
|
||||||
"values": {
|
"values": {
|
||||||
"KG_M_S_SQ": spu.kg * spu.m/spu.second**2,
|
"KG_M_S_SQ": spu.kg * spu.m/spu.second**2,
|
||||||
"NNEWT": spuex.nanonewton,
|
"NNEWT": spux.nanonewton,
|
||||||
"UNEWT": spuex.micronewton,
|
"UNEWT": spux.micronewton,
|
||||||
"MNEWT": spuex.millinewton,
|
"MNEWT": spux.millinewton,
|
||||||
"NEWT": spu.newton,
|
"NEWT": spu.newton,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -210,9 +211,9 @@ SOCKET_UNITS = {
|
||||||
"default": "UNEWT",
|
"default": "UNEWT",
|
||||||
"values": {
|
"values": {
|
||||||
"KG_M_S_SQ": spu.kg * spu.m/spu.second**2,
|
"KG_M_S_SQ": spu.kg * spu.m/spu.second**2,
|
||||||
"NNEWT": spuex.nanonewton,
|
"NNEWT": spux.nanonewton,
|
||||||
"UNEWT": spuex.micronewton,
|
"UNEWT": spux.micronewton,
|
||||||
"MNEWT": spuex.millinewton,
|
"MNEWT": spux.millinewton,
|
||||||
"NEWT": spu.newton,
|
"NEWT": spu.newton,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -221,12 +222,12 @@ SOCKET_UNITS = {
|
||||||
"default": "THZ",
|
"default": "THZ",
|
||||||
"values": {
|
"values": {
|
||||||
"HZ": spu.hertz,
|
"HZ": spu.hertz,
|
||||||
"KHZ": spuex.kilohertz,
|
"KHZ": spux.kilohertz,
|
||||||
"MHZ": spuex.megahertz,
|
"MHZ": spux.megahertz,
|
||||||
"GHZ": spuex.gigahertz,
|
"GHZ": spux.gigahertz,
|
||||||
"THZ": spuex.terahertz,
|
"THZ": spux.terahertz,
|
||||||
"PHZ": spuex.petahertz,
|
"PHZ": spux.petahertz,
|
||||||
"EHZ": spuex.exahertz,
|
"EHZ": spux.exahertz,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ST.PhysicalPol: {
|
ST.PhysicalPol: {
|
||||||
|
|
|
@ -6,7 +6,7 @@ from . import sources
|
||||||
from . import mediums
|
from . import mediums
|
||||||
from . import structures
|
from . import structures
|
||||||
#from . import bounds
|
#from . import bounds
|
||||||
#from . import monitors
|
from . import monitors
|
||||||
from . import simulations
|
from . import simulations
|
||||||
#from . import utilities
|
#from . import utilities
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ 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 = {
|
||||||
**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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -456,7 +456,9 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
# Draw Name
|
# Draw Name
|
||||||
col = layout.column(align=False)
|
col = layout.column(align=False)
|
||||||
if self.use_sim_node_name:
|
if self.use_sim_node_name:
|
||||||
col.prop(self, "sim_node_name", text="")
|
row = col.row(align=True)
|
||||||
|
row.label(text="", icon="EVENT_N")
|
||||||
|
row.prop(self, "sim_node_name", text="")
|
||||||
|
|
||||||
# Draw Name
|
# Draw Name
|
||||||
self.draw_props(context, col)
|
self.draw_props(context, col)
|
||||||
|
@ -555,13 +557,13 @@ class MaxwellSimNode(bpy.types.Node):
|
||||||
for method in self._on_value_changed_methods:
|
for method in self._on_value_changed_methods:
|
||||||
if (
|
if (
|
||||||
socket_name
|
socket_name
|
||||||
and socket_name == method._extra_data.get("changed_socket")
|
and socket_name in method._extra_data.get("changed_sockets")
|
||||||
) or (
|
) or (
|
||||||
prop_name
|
prop_name
|
||||||
and prop_name == method._extra_data.get("changed_prop")
|
and prop_name in method._extra_data.get("changed_props")
|
||||||
) or (
|
) or (
|
||||||
socket_name
|
socket_name
|
||||||
and method._extra_data.get("changed_loose_input")
|
and method._extra_data["changed_loose_input"]
|
||||||
and socket_name in self.loose_input_sockets
|
and socket_name in self.loose_input_sockets
|
||||||
):
|
):
|
||||||
method(self)
|
method(self)
|
||||||
|
@ -833,8 +835,8 @@ def computes_output_socket(
|
||||||
# - Decorator: On Show Preview
|
# - Decorator: On Show Preview
|
||||||
####################
|
####################
|
||||||
def on_value_changed(
|
def on_value_changed(
|
||||||
socket_name: ct.SocketName | None = None,
|
socket_name: set[ct.SocketName] | ct.SocketName | None = None,
|
||||||
prop_name: str | None = None,
|
prop_name: set[str] | str | None = None,
|
||||||
any_loose_input_socket: bool = False,
|
any_loose_input_socket: bool = False,
|
||||||
|
|
||||||
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
kind: ct.DataFlowKind = ct.DataFlowKind.Value,
|
||||||
|
@ -863,8 +865,12 @@ def on_value_changed(
|
||||||
return chain_event_decorator(
|
return chain_event_decorator(
|
||||||
callback_type="on_value_changed",
|
callback_type="on_value_changed",
|
||||||
extra_data={
|
extra_data={
|
||||||
"changed_socket": socket_name,
|
"changed_sockets": (
|
||||||
"changed_prop": prop_name,
|
socket_name if isinstance(socket_name, set) else {socket_name}
|
||||||
|
),
|
||||||
|
"changed_props": (
|
||||||
|
prop_name if isinstance(prop_name, set) else {prop_name}
|
||||||
|
),
|
||||||
"changed_loose_input": any_loose_input_socket,
|
"changed_loose_input": any_loose_input_socket,
|
||||||
},
|
},
|
||||||
kind=kind,
|
kind=kind,
|
||||||
|
|
|
@ -38,10 +38,10 @@ class WaveConstantNode(base.MaxwellSimNode):
|
||||||
kind=ct.DataFlowKind.Value,
|
kind=ct.DataFlowKind.Value,
|
||||||
input_sockets={"WL", "Freq"},
|
input_sockets={"WL", "Freq"},
|
||||||
)
|
)
|
||||||
def compute_vac_wl(self, input_socket_values: dict) -> sp.Expr:
|
def compute_vac_wl(self, input_sockets: dict) -> sp.Expr:
|
||||||
if (vac_wl := input_socket_values["WL"]):
|
if (vac_wl := input_sockets["WL"]):
|
||||||
return vac_wl
|
return vac_wl
|
||||||
elif (freq := input_socket_values["Freq"]):
|
elif (freq := input_sockets["Freq"]):
|
||||||
return spu.convert_to(
|
return spu.convert_to(
|
||||||
VAC_SPEED_OF_LIGHT / freq,
|
VAC_SPEED_OF_LIGHT / freq,
|
||||||
spu.meter,
|
spu.meter,
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
from . import eh_field_monitor
|
from . import eh_field_monitor
|
||||||
from . import field_power_flux_monitor
|
#from . import field_power_flux_monitor
|
||||||
from . import epsilon_tensor_monitor
|
#from . import epsilon_tensor_monitor
|
||||||
from . import diffraction_monitor
|
#from . import diffraction_monitor
|
||||||
|
|
||||||
BL_REGISTER = [
|
BL_REGISTER = [
|
||||||
*eh_field_monitor.BL_REGISTER,
|
*eh_field_monitor.BL_REGISTER,
|
||||||
*field_power_flux_monitor.BL_REGISTER,
|
# *field_power_flux_monitor.BL_REGISTER,
|
||||||
*epsilon_tensor_monitor.BL_REGISTER,
|
# *epsilon_tensor_monitor.BL_REGISTER,
|
||||||
*diffraction_monitor.BL_REGISTER,
|
# *diffraction_monitor.BL_REGISTER,
|
||||||
]
|
]
|
||||||
BL_NODES = {
|
BL_NODES = {
|
||||||
**eh_field_monitor.BL_NODES,
|
**eh_field_monitor.BL_NODES,
|
||||||
**field_power_flux_monitor.BL_NODES,
|
# **field_power_flux_monitor.BL_NODES,
|
||||||
**epsilon_tensor_monitor.BL_NODES,
|
# **epsilon_tensor_monitor.BL_NODES,
|
||||||
**diffraction_monitor.BL_NODES,
|
# **diffraction_monitor.BL_NODES,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,171 @@
|
||||||
|
import typing as typ
|
||||||
|
import functools
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import tidy3d as td
|
||||||
|
import sympy as sp
|
||||||
|
import sympy.physics.units as spu
|
||||||
|
import numpy as np
|
||||||
|
import scipy as sc
|
||||||
|
|
||||||
|
from .....utils import analyze_geonodes
|
||||||
|
from .....utils import extra_sympy_units as spux
|
||||||
|
from ... import contracts as ct
|
||||||
|
from ... import sockets
|
||||||
|
from ... import managed_objs
|
||||||
|
from .. import base
|
||||||
|
|
||||||
|
GEONODES_MONITOR_BOX = "monitor_box"
|
||||||
|
|
||||||
|
class EHFieldMonitorNode(base.MaxwellSimNode):
|
||||||
|
node_type = ct.NodeType.EHFieldMonitor
|
||||||
|
bl_label = "E/H Field Monitor"
|
||||||
|
use_sim_node_name = True
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Sockets
|
||||||
|
####################
|
||||||
|
input_sockets = {
|
||||||
|
"Rec Start": sockets.PhysicalTimeSocketDef(),
|
||||||
|
"Rec Stop": sockets.PhysicalTimeSocketDef(
|
||||||
|
default_value=200*spux.fs
|
||||||
|
),
|
||||||
|
"Center": sockets.PhysicalPoint3DSocketDef(),
|
||||||
|
"Size": sockets.PhysicalSize3DSocketDef(),
|
||||||
|
"Samples/Space": sockets.Integer3DVectorSocketDef(
|
||||||
|
default_value=sp.Matrix([10, 10, 10])
|
||||||
|
),
|
||||||
|
"Samples/Time": sockets.IntegerNumberSocketDef(
|
||||||
|
default_value=100,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
output_sockets = {
|
||||||
|
"Monitor": sockets.MaxwellMonitorSocketDef(),
|
||||||
|
}
|
||||||
|
|
||||||
|
managed_obj_defs = {
|
||||||
|
"monitor_box": ct.schemas.ManagedObjDef(
|
||||||
|
mk=lambda name: managed_objs.ManagedBLObject(name),
|
||||||
|
name_prefix="",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Properties
|
||||||
|
####################
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - UI
|
||||||
|
####################
|
||||||
|
def draw_props(self, context, layout):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def draw_info(self, context, col):
|
||||||
|
pass
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Output Sockets
|
||||||
|
####################
|
||||||
|
@base.computes_output_socket(
|
||||||
|
"Monitor",
|
||||||
|
input_sockets={
|
||||||
|
"Rec Start", "Rec Stop", "Center", "Size", "Samples/Space",
|
||||||
|
"Samples/Time",
|
||||||
|
},
|
||||||
|
props={"sim_node_name"}
|
||||||
|
)
|
||||||
|
def compute_monitor(self, input_sockets: dict, props: dict) -> td.FieldTimeMonitor:
|
||||||
|
_rec_start = input_sockets["Rec Start"]
|
||||||
|
_rec_stop = input_sockets["Rec Stop"]
|
||||||
|
_center = input_sockets["Center"]
|
||||||
|
_size = input_sockets["Size"]
|
||||||
|
_samples_space = input_sockets["Samples/Space"]
|
||||||
|
samples_time = input_sockets["Samples/Time"]
|
||||||
|
|
||||||
|
rec_start = spu.convert_to(_rec_start, spu.second) / spu.second
|
||||||
|
rec_stop = spu.convert_to(_rec_stop, spu.second) / spu.second
|
||||||
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
|
size = tuple(spu.convert_to(_size, spu.um) / spu.um)
|
||||||
|
samples_space = tuple(_samples_space)
|
||||||
|
|
||||||
|
return td.FieldTimeMonitor(
|
||||||
|
center=center,
|
||||||
|
size=size,
|
||||||
|
name=props["sim_node_name"],
|
||||||
|
start=rec_start,
|
||||||
|
stop=rec_stop,
|
||||||
|
interval=samples_time,
|
||||||
|
interval_space=samples_space,
|
||||||
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Preview - Changes to Input Sockets
|
||||||
|
####################
|
||||||
|
@base.on_value_changed(
|
||||||
|
socket_name={"Center", "Size"},
|
||||||
|
input_sockets={"Center", "Size"},
|
||||||
|
managed_objs={"monitor_box"},
|
||||||
|
)
|
||||||
|
def on_value_changed__center_size(
|
||||||
|
self,
|
||||||
|
input_sockets: dict,
|
||||||
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
|
):
|
||||||
|
_center = input_sockets["Center"]
|
||||||
|
center = tuple([
|
||||||
|
float(el)
|
||||||
|
for el in spu.convert_to(_center, spu.um) / spu.um
|
||||||
|
])
|
||||||
|
|
||||||
|
_size = input_sockets["Size"]
|
||||||
|
size = tuple([
|
||||||
|
float(el)
|
||||||
|
for el in spu.convert_to(_size, spu.um) / spu.um
|
||||||
|
])
|
||||||
|
## TODO: Preview unit system?? Presume um for now
|
||||||
|
|
||||||
|
# Retrieve Hard-Coded GeoNodes and Analyze Input
|
||||||
|
geo_nodes = bpy.data.node_groups[GEONODES_MONITOR_BOX]
|
||||||
|
geonodes_interface = analyze_geonodes.interface(
|
||||||
|
geo_nodes, direc="INPUT"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Sync Modifier Inputs
|
||||||
|
managed_objs["monitor_box"].sync_geonodes_modifier(
|
||||||
|
geonodes_node_group=geo_nodes,
|
||||||
|
geonodes_identifier_to_value={
|
||||||
|
geonodes_interface["Size"].identifier: size,
|
||||||
|
## TODO: Use 'bl_socket_map.value_to_bl`!
|
||||||
|
## - This accounts for auto-conversion, unit systems, etc. .
|
||||||
|
## - We could keep it in the node base class...
|
||||||
|
## - ...But it needs aligning with Blender, too. Hmm.
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Sync Object Position
|
||||||
|
managed_objs["monitor_box"].bl_object("MESH").location = center
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Preview - Show Preview
|
||||||
|
####################
|
||||||
|
@base.on_show_preview(
|
||||||
|
managed_objs={"monitor_box"},
|
||||||
|
)
|
||||||
|
def on_show_preview(
|
||||||
|
self,
|
||||||
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
|
):
|
||||||
|
managed_objs["monitor_box"].show_preview("MESH")
|
||||||
|
self.on_value_changed__center_size()
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
####################
|
####################
|
||||||
BL_REGISTER = []
|
BL_REGISTER = [
|
||||||
BL_NODES = {}
|
EHFieldMonitorNode,
|
||||||
|
]
|
||||||
|
BL_NODES = {
|
||||||
|
ct.NodeType.EHFieldMonitor: (
|
||||||
|
ct.NodeCategory.MAXWELLSIM_MONITORS
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ class Tidy3DTaskStatusModalOperator(bpy.types.Operator):
|
||||||
node = context.node
|
node = context.node
|
||||||
wm = context.window_manager
|
wm = context.window_manager
|
||||||
|
|
||||||
self._timer = wm.event_timer_add(0.25, window=context.window)
|
self._timer = wm.event_timer_add(2.0, window=context.window)
|
||||||
self._task_id = node.uploaded_task_id
|
self._task_id = node.uploaded_task_id
|
||||||
self._node = node
|
self._node = node
|
||||||
self._status = task_status(self._task_id)
|
self._status = task_status(self._task_id)
|
||||||
|
@ -335,7 +335,7 @@ class Tidy3DWebExporterNode(base.MaxwellSimNode):
|
||||||
"queued": (0.0, "Queued..."),
|
"queued": (0.0, "Queued..."),
|
||||||
"preprocessing": (0.05, "Pre-processing..."),
|
"preprocessing": (0.05, "Pre-processing..."),
|
||||||
"running": (0.2, "Running..."),
|
"running": (0.2, "Running..."),
|
||||||
"postprocessing": (0.85, "Post-processing..."),
|
"postprocess": (0.85, "Post-processing..."),
|
||||||
"success": (1.0, f"Success (={billed_task_cost(self.uploaded_task_id)} credits)"),
|
"success": (1.0, f"Success (={billed_task_cost(self.uploaded_task_id)} credits)"),
|
||||||
"error": (1.0, f"Error (={billed_task_cost(self.uploaded_task_id)} credits)"),
|
"error": (1.0, f"Error (={billed_task_cost(self.uploaded_task_id)} credits)"),
|
||||||
}[task_status(self.uploaded_task_id)]
|
}[task_status(self.uploaded_task_id)]
|
||||||
|
|
|
@ -45,11 +45,14 @@ class FDTDSimNode(base.MaxwellSimNode):
|
||||||
sources = [sources]
|
sources = [sources]
|
||||||
if not isinstance(structures, list):
|
if not isinstance(structures, list):
|
||||||
structures = [structures]
|
structures = [structures]
|
||||||
|
if not isinstance(monitors, list):
|
||||||
|
monitors = [monitors]
|
||||||
|
|
||||||
return td.Simulation(
|
return td.Simulation(
|
||||||
**sim_domain, ## run_time=, size=, grid=, medium=
|
**sim_domain, ## run_time=, size=, grid=, medium=
|
||||||
structures=structures,
|
structures=structures,
|
||||||
sources=sources,
|
sources=sources,
|
||||||
|
monitors=monitors,
|
||||||
boundary_spec=bounds,
|
boundary_spec=bounds,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ from ... import sockets
|
||||||
from .. import base
|
from .. import base
|
||||||
from ... import managed_objs
|
from ... import managed_objs
|
||||||
|
|
||||||
GEONODES_DOMAIN_BOX = "domain_box"
|
GEONODES_DOMAIN_BOX = "simdomain_box"
|
||||||
|
|
||||||
class SimDomainNode(base.MaxwellSimNode):
|
class SimDomainNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.SimDomain
|
node_type = ct.NodeType.SimDomain
|
||||||
|
@ -20,6 +20,7 @@ class SimDomainNode(base.MaxwellSimNode):
|
||||||
default_value = 5 * spu.ps,
|
default_value = 5 * spu.ps,
|
||||||
default_unit = spu.ps,
|
default_unit = spu.ps,
|
||||||
),
|
),
|
||||||
|
"Center": sockets.PhysicalSize3DSocketDef(),
|
||||||
"Size": sockets.PhysicalSize3DSocketDef(),
|
"Size": sockets.PhysicalSize3DSocketDef(),
|
||||||
"Grid": sockets.MaxwellSimGridSocketDef(),
|
"Grid": sockets.MaxwellSimGridSocketDef(),
|
||||||
"Ambient Medium": sockets.MaxwellMediumSocketDef(),
|
"Ambient Medium": sockets.MaxwellMediumSocketDef(),
|
||||||
|
@ -40,19 +41,22 @@ class SimDomainNode(base.MaxwellSimNode):
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Domain",
|
"Domain",
|
||||||
input_sockets={"Duration", "Size", "Grid", "Ambient Medium"},
|
input_sockets={"Duration", "Center", "Size", "Grid", "Ambient Medium"},
|
||||||
)
|
)
|
||||||
def compute_sim_domain(self, input_sockets: dict) -> sp.Expr:
|
def compute_sim_domain(self, input_sockets: dict) -> sp.Expr:
|
||||||
if all([
|
if all([
|
||||||
(_duration := input_sockets["Duration"]),
|
(_duration := input_sockets["Duration"]),
|
||||||
|
(_center := input_sockets["Center"]),
|
||||||
(_size := input_sockets["Size"]),
|
(_size := input_sockets["Size"]),
|
||||||
(grid := input_sockets["Grid"]),
|
(grid := input_sockets["Grid"]),
|
||||||
(medium := input_sockets["Ambient Medium"]),
|
(medium := input_sockets["Ambient Medium"]),
|
||||||
]):
|
]):
|
||||||
duration = spu.convert_to(_duration, spu.second) / spu.second
|
duration = spu.convert_to(_duration, spu.second) / spu.second
|
||||||
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
size = tuple(spu.convert_to(_size, spu.um) / spu.um)
|
size = tuple(spu.convert_to(_size, spu.um) / spu.um)
|
||||||
return dict(
|
return dict(
|
||||||
run_time=duration,
|
run_time=duration,
|
||||||
|
center=center,
|
||||||
size=size,
|
size=size,
|
||||||
grid_spec=grid,
|
grid_spec=grid,
|
||||||
medium=medium,
|
medium=medium,
|
||||||
|
@ -62,15 +66,21 @@ class SimDomainNode(base.MaxwellSimNode):
|
||||||
# - Preview
|
# - Preview
|
||||||
####################
|
####################
|
||||||
@base.on_value_changed(
|
@base.on_value_changed(
|
||||||
socket_name="Size",
|
socket_name={"Center", "Size"},
|
||||||
input_sockets={"Size"},
|
input_sockets={"Center", "Size"},
|
||||||
managed_objs={"domain_box"},
|
managed_objs={"domain_box"},
|
||||||
)
|
)
|
||||||
def on_value_changed__center(
|
def on_value_changed__center_size(
|
||||||
self,
|
self,
|
||||||
input_sockets: dict,
|
input_sockets: dict,
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
|
_center = input_sockets["Center"]
|
||||||
|
center = tuple([
|
||||||
|
float(el)
|
||||||
|
for el in spu.convert_to(_center, spu.um) / spu.um
|
||||||
|
])
|
||||||
|
|
||||||
_size = input_sockets["Size"]
|
_size = input_sockets["Size"]
|
||||||
size = tuple([
|
size = tuple([
|
||||||
float(el)
|
float(el)
|
||||||
|
@ -88,7 +98,7 @@ class SimDomainNode(base.MaxwellSimNode):
|
||||||
managed_objs["domain_box"].sync_geonodes_modifier(
|
managed_objs["domain_box"].sync_geonodes_modifier(
|
||||||
geonodes_node_group=geo_nodes,
|
geonodes_node_group=geo_nodes,
|
||||||
geonodes_identifier_to_value={
|
geonodes_identifier_to_value={
|
||||||
geonodes_interface["Size"].identifier: size
|
geonodes_interface["Size"].identifier: size,
|
||||||
## TODO: Use 'bl_socket_map.value_to_bl`!
|
## TODO: Use 'bl_socket_map.value_to_bl`!
|
||||||
## - This accounts for auto-conversion, unit systems, etc. .
|
## - This accounts for auto-conversion, unit systems, etc. .
|
||||||
## - We could keep it in the node base class...
|
## - We could keep it in the node base class...
|
||||||
|
@ -96,6 +106,9 @@ class SimDomainNode(base.MaxwellSimNode):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Sync Object Position
|
||||||
|
managed_objs["domain_box"].bl_object("MESH").location = center
|
||||||
|
|
||||||
@base.on_show_preview(
|
@base.on_show_preview(
|
||||||
managed_objs={"domain_box"},
|
managed_objs={"domain_box"},
|
||||||
)
|
)
|
||||||
|
@ -104,7 +117,7 @@ class SimDomainNode(base.MaxwellSimNode):
|
||||||
managed_objs: dict[str, ct.schemas.ManagedObj],
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
):
|
):
|
||||||
managed_objs["domain_box"].show_preview("MESH")
|
managed_objs["domain_box"].show_preview("MESH")
|
||||||
self.on_value_changed__center()
|
self.on_value_changed__center_size()
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Blender Registration
|
# - Blender Registration
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import typing_extensions as typx
|
||||||
import math
|
import math
|
||||||
|
|
||||||
import tidy3d as td
|
import tidy3d as td
|
||||||
|
@ -6,10 +7,46 @@ import sympy.physics.units as spu
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
|
from .....utils import analyze_geonodes
|
||||||
|
from ... import managed_objs
|
||||||
from ... import contracts as ct
|
from ... import contracts as ct
|
||||||
from ... import sockets
|
from ... import sockets
|
||||||
from .. import base
|
from .. import base
|
||||||
|
|
||||||
|
GEONODES_PLANE_WAVE = "source_plane_wave"
|
||||||
|
|
||||||
|
def convert_vector_to_spherical(
|
||||||
|
v: sp.MatrixBase,
|
||||||
|
) -> tuple[str, str, sp.Expr, sp.Expr]:
|
||||||
|
"""Converts a vector (maybe normalized) to spherical coordinates from an arbitrary choice of injection axis.
|
||||||
|
|
||||||
|
Injection axis is chosen to minimize `theta`
|
||||||
|
"""
|
||||||
|
x, y, z = v
|
||||||
|
|
||||||
|
injection_axis = max(
|
||||||
|
('x', abs(x)),
|
||||||
|
('y', abs(y)),
|
||||||
|
('z', abs(z)),
|
||||||
|
key=lambda item: item[1]
|
||||||
|
)[0]
|
||||||
|
## Select injection axis that minimizes 'theta'
|
||||||
|
|
||||||
|
if injection_axis == "x":
|
||||||
|
direction = "+" if x >= 0 else "-"
|
||||||
|
theta = sp.acos(x / sp.sqrt(x**2 + y**2 + z**2))
|
||||||
|
phi = sp.atan2(z, y)
|
||||||
|
elif injection_axis == "y":
|
||||||
|
direction = "+" if y >= 0 else "-"
|
||||||
|
theta = sp.acos(y / sp.sqrt(x**2 + y**2 + z**2))
|
||||||
|
phi = sp.atan2(x, z)
|
||||||
|
else:
|
||||||
|
direction = "+" if z >= 0 else "-"
|
||||||
|
theta = sp.acos(z / sp.sqrt(x**2 + y**2 + z**2))
|
||||||
|
phi = sp.atan2(y, x)
|
||||||
|
|
||||||
|
return injection_axis, direction, theta, phi
|
||||||
|
|
||||||
class PlaneWaveSourceNode(base.MaxwellSimNode):
|
class PlaneWaveSourceNode(base.MaxwellSimNode):
|
||||||
node_type = ct.NodeType.PlaneWaveSource
|
node_type = ct.NodeType.PlaneWaveSource
|
||||||
bl_label = "Plane Wave Source"
|
bl_label = "Plane Wave Source"
|
||||||
|
@ -20,79 +57,112 @@ class PlaneWaveSourceNode(base.MaxwellSimNode):
|
||||||
input_sockets = {
|
input_sockets = {
|
||||||
"Temporal Shape": sockets.MaxwellTemporalShapeSocketDef(),
|
"Temporal Shape": sockets.MaxwellTemporalShapeSocketDef(),
|
||||||
"Center": sockets.PhysicalPoint3DSocketDef(),
|
"Center": sockets.PhysicalPoint3DSocketDef(),
|
||||||
"Direction": sockets.BoolSocketDef(
|
"Direction": sockets.Real3DVectorSocketDef(
|
||||||
default_value=True,
|
default_value=sp.Matrix([0, 0, -1])
|
||||||
),
|
),
|
||||||
"Pol": sockets.PhysicalPolSocketDef(),
|
"Pol Angle": sockets.PhysicalAngleSocketDef(),
|
||||||
}
|
}
|
||||||
output_sockets = {
|
output_sockets = {
|
||||||
"Source": sockets.MaxwellSourceSocketDef(),
|
"Source": sockets.MaxwellSourceSocketDef(),
|
||||||
}
|
}
|
||||||
|
|
||||||
####################
|
managed_obj_defs = {
|
||||||
# - Properties
|
"plane_wave_source": ct.schemas.ManagedObjDef(
|
||||||
####################
|
mk=lambda name: managed_objs.ManagedBLObject(name),
|
||||||
inj_axis: bpy.props.EnumProperty(
|
name_prefix="",
|
||||||
name="Injection Axis",
|
)
|
||||||
description="Axis to inject plane wave along",
|
}
|
||||||
items=[
|
|
||||||
("X", "X", "X-Axis"),
|
|
||||||
("Y", "Y", "Y-Axis"),
|
|
||||||
("Z", "Z", "Z-Axis"),
|
|
||||||
],
|
|
||||||
default="Y",
|
|
||||||
update=(lambda self, context: self.sync_prop("inj_axis")),
|
|
||||||
)
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Output Socket Computation
|
# - Output Socket Computation
|
||||||
####################
|
####################
|
||||||
@base.computes_output_socket(
|
@base.computes_output_socket(
|
||||||
"Source",
|
"Source",
|
||||||
input_sockets={"Temporal Shape", "Center", "Direction", "Pol"},
|
input_sockets={"Temporal Shape", "Center", "Direction", "Pol Angle"},
|
||||||
props={"inj_axis"},
|
|
||||||
)
|
)
|
||||||
def compute_source(self, input_sockets: dict, props: dict):
|
def compute_source(self, input_sockets: dict):
|
||||||
temporal_shape = input_sockets["Temporal Shape"]
|
temporal_shape = input_sockets["Temporal Shape"]
|
||||||
_center = input_sockets["Center"]
|
_center = input_sockets["Center"]
|
||||||
_direction = input_sockets["Direction"]
|
direction = input_sockets["Direction"]
|
||||||
_inj_axis = props["inj_axis"]
|
pol_angle = input_sockets["Pol Angle"]
|
||||||
pol = input_sockets["Pol"]
|
|
||||||
|
injection_axis, dir_sgn, theta, phi = convert_vector_to_spherical(direction)
|
||||||
|
|
||||||
direction = {
|
|
||||||
False: "-",
|
|
||||||
True: "+",
|
|
||||||
}[_direction]
|
|
||||||
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
|
||||||
size = {
|
size = {
|
||||||
"X": (0, math.inf, math.inf),
|
"x": (0, math.inf, math.inf),
|
||||||
"Y": (math.inf, 0, math.inf),
|
"y": (math.inf, 0, math.inf),
|
||||||
"Z": (math.inf, math.inf, 0),
|
"z": (math.inf, math.inf, 0),
|
||||||
}[_inj_axis]
|
}[injection_axis]
|
||||||
|
center = tuple(spu.convert_to(_center, spu.um) / spu.um)
|
||||||
S0, S1, S2, S3 = tuple(pol)
|
|
||||||
|
|
||||||
chi = 0.5 * sp.atan2(S2, S1)
|
|
||||||
psi = 0.5 * sp.asin(S3/S0)
|
|
||||||
## chi: Pol angle
|
|
||||||
## psi: Ellipticity
|
|
||||||
|
|
||||||
## TODO: Something's wonky.
|
|
||||||
#angle_theta = chi
|
|
||||||
#angle_phi = psi
|
|
||||||
pol_angle = sp.pi/2 - chi
|
|
||||||
|
|
||||||
# Display the results
|
# Display the results
|
||||||
return td.PlaneWave(
|
return td.PlaneWave(
|
||||||
center=tuple(_center),
|
center=center,
|
||||||
size=size,
|
|
||||||
source_time=temporal_shape,
|
source_time=temporal_shape,
|
||||||
direction="+" if _direction else "-",
|
size=size,
|
||||||
#angle_theta=angle_theta,
|
direction=dir_sgn,
|
||||||
#angle_phi=angle_phi,
|
angle_theta=theta,
|
||||||
#pol_angle=pol_angle,
|
angle_phi=phi,
|
||||||
|
pol_angle=pol_angle,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Preview
|
||||||
|
####################
|
||||||
|
@base.on_value_changed(
|
||||||
|
socket_name={"Center", "Direction"},
|
||||||
|
input_sockets={"Center", "Direction"},
|
||||||
|
managed_objs={"plane_wave_source"},
|
||||||
|
)
|
||||||
|
def on_value_changed__center_direction(
|
||||||
|
self,
|
||||||
|
input_sockets: dict,
|
||||||
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
|
):
|
||||||
|
_center = input_sockets["Center"]
|
||||||
|
center = tuple([
|
||||||
|
float(el)
|
||||||
|
for el in spu.convert_to(_center, spu.um) / spu.um
|
||||||
|
])
|
||||||
|
|
||||||
|
_direction = input_sockets["Direction"]
|
||||||
|
direction = tuple([
|
||||||
|
float(el)
|
||||||
|
for el in _direction
|
||||||
|
])
|
||||||
|
## TODO: Preview unit system?? Presume um for now
|
||||||
|
|
||||||
|
# Retrieve Hard-Coded GeoNodes and Analyze Input
|
||||||
|
geo_nodes = bpy.data.node_groups[GEONODES_PLANE_WAVE]
|
||||||
|
geonodes_interface = analyze_geonodes.interface(
|
||||||
|
geo_nodes, direc="INPUT"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Sync Modifier Inputs
|
||||||
|
managed_objs["plane_wave_source"].sync_geonodes_modifier(
|
||||||
|
geonodes_node_group=geo_nodes,
|
||||||
|
geonodes_identifier_to_value={
|
||||||
|
geonodes_interface["Direction"].identifier: direction,
|
||||||
|
## TODO: Use 'bl_socket_map.value_to_bl`!
|
||||||
|
## - This accounts for auto-conversion, unit systems, etc. .
|
||||||
|
## - We could keep it in the node base class...
|
||||||
|
## - ...But it needs aligning with Blender, too. Hmm.
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Sync Object Position
|
||||||
|
managed_objs["plane_wave_source"].bl_object("MESH").location = center
|
||||||
|
|
||||||
|
@base.on_show_preview(
|
||||||
|
managed_objs={"plane_wave_source"},
|
||||||
|
)
|
||||||
|
def on_show_preview(
|
||||||
|
self,
|
||||||
|
managed_objs: dict[str, ct.schemas.ManagedObj],
|
||||||
|
):
|
||||||
|
managed_objs["plane_wave_source"].show_preview("MESH")
|
||||||
|
self.on_value_changed__center_direction()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
|
|
@ -15,6 +15,7 @@ ComplexNumberSocketDef = number.ComplexNumberSocketDef
|
||||||
from . import vector
|
from . import vector
|
||||||
Real2DVectorSocketDef = vector.Real2DVectorSocketDef
|
Real2DVectorSocketDef = vector.Real2DVectorSocketDef
|
||||||
Complex2DVectorSocketDef = vector.Complex2DVectorSocketDef
|
Complex2DVectorSocketDef = vector.Complex2DVectorSocketDef
|
||||||
|
Integer3DVectorSocketDef = vector.Integer3DVectorSocketDef
|
||||||
Real3DVectorSocketDef = vector.Real3DVectorSocketDef
|
Real3DVectorSocketDef = vector.Real3DVectorSocketDef
|
||||||
Complex3DVectorSocketDef = vector.Complex3DVectorSocketDef
|
Complex3DVectorSocketDef = vector.Complex3DVectorSocketDef
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ class MaxwellSimSocket(bpy.types.NodeSocket):
|
||||||
# Options
|
# Options
|
||||||
#link_limit: int = 0
|
#link_limit: int = 0
|
||||||
use_units: bool = False
|
use_units: bool = False
|
||||||
|
#list_like: bool = False
|
||||||
|
|
||||||
# Computed
|
# Computed
|
||||||
bl_idname: str
|
bl_idname: str
|
||||||
|
|
|
@ -17,32 +17,6 @@ VAC_SPEED_OF_LIGHT = (
|
||||||
class MaxwellMonitorBLSocket(base.MaxwellSimSocket):
|
class MaxwellMonitorBLSocket(base.MaxwellSimSocket):
|
||||||
socket_type = ct.SocketType.MaxwellMonitor
|
socket_type = ct.SocketType.MaxwellMonitor
|
||||||
bl_label = "Maxwell Monitor"
|
bl_label = "Maxwell Monitor"
|
||||||
use_units = True
|
|
||||||
|
|
||||||
####################
|
|
||||||
# - Properties
|
|
||||||
####################
|
|
||||||
wl: bpy.props.FloatProperty(
|
|
||||||
name="WL",
|
|
||||||
description="WL to store in monitor",
|
|
||||||
default=500.0,
|
|
||||||
precision=4,
|
|
||||||
step=50,
|
|
||||||
update=(lambda self, context: self.sync_prop("wl", context)),
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def value(self) -> td.Monitor:
|
|
||||||
freq = spu.convert_to(
|
|
||||||
VAC_SPEED_OF_LIGHT / (self.wl*self.unit),
|
|
||||||
spu.hertz,
|
|
||||||
) / spu.hertz
|
|
||||||
return td.FieldMonitor(
|
|
||||||
size=(td.inf, td.inf, 0),
|
|
||||||
freqs=[freq],
|
|
||||||
name="fields",
|
|
||||||
colocate=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Socket Configuration
|
# - Socket Configuration
|
||||||
|
|
|
@ -162,7 +162,7 @@ class Tidy3DCloudTaskBLSocket(base.MaxwellSimSocket):
|
||||||
"queued": "Task is queued for simulation",
|
"queued": "Task is queued for simulation",
|
||||||
"preprocessing": "Task is pre-processing",
|
"preprocessing": "Task is pre-processing",
|
||||||
"running": "Task is currently running",
|
"running": "Task is currently running",
|
||||||
"postprocessing": "Task is post-processing",
|
"postprocess": "Task is post-processing",
|
||||||
"success": "Task ran successfully, costing {task.real_flex_unit} credits",
|
"success": "Task ran successfully, costing {task.real_flex_unit} credits",
|
||||||
"error": "Task ran, but an error occurred",
|
"error": "Task ran, but an error occurred",
|
||||||
}[task.status],
|
}[task.status],
|
||||||
|
@ -174,7 +174,7 @@ class Tidy3DCloudTaskBLSocket(base.MaxwellSimSocket):
|
||||||
"queued": "SEQUENCE_COLOR_03",
|
"queued": "SEQUENCE_COLOR_03",
|
||||||
"preprocessing": "SEQUENCE_COLOR_02",
|
"preprocessing": "SEQUENCE_COLOR_02",
|
||||||
"running": "SEQUENCE_COLOR_05",
|
"running": "SEQUENCE_COLOR_05",
|
||||||
"postprocessing": "SEQUENCE_COLOR_06",
|
"postprocess": "SEQUENCE_COLOR_06",
|
||||||
"success": "SEQUENCE_COLOR_04",
|
"success": "SEQUENCE_COLOR_04",
|
||||||
"error": "SEQUENCE_COLOR_01",
|
"error": "SEQUENCE_COLOR_01",
|
||||||
}[task.status],
|
}[task.status],
|
||||||
|
|
|
@ -3,8 +3,10 @@ from . import complex_2d_vector
|
||||||
Real2DVectorSocketDef = real_2d_vector.Real2DVectorSocketDef
|
Real2DVectorSocketDef = real_2d_vector.Real2DVectorSocketDef
|
||||||
Complex2DVectorSocketDef = complex_2d_vector.Complex2DVectorSocketDef
|
Complex2DVectorSocketDef = complex_2d_vector.Complex2DVectorSocketDef
|
||||||
|
|
||||||
|
from . import integer_3d_vector
|
||||||
from . import real_3d_vector
|
from . import real_3d_vector
|
||||||
from . import complex_3d_vector
|
from . import complex_3d_vector
|
||||||
|
Integer3DVectorSocketDef = integer_3d_vector.Integer3DVectorSocketDef
|
||||||
Real3DVectorSocketDef = real_3d_vector.Real3DVectorSocketDef
|
Real3DVectorSocketDef = real_3d_vector.Real3DVectorSocketDef
|
||||||
Complex3DVectorSocketDef = complex_3d_vector.Complex3DVectorSocketDef
|
Complex3DVectorSocketDef = complex_3d_vector.Complex3DVectorSocketDef
|
||||||
|
|
||||||
|
@ -13,6 +15,7 @@ BL_REGISTER = [
|
||||||
*real_2d_vector.BL_REGISTER,
|
*real_2d_vector.BL_REGISTER,
|
||||||
*complex_2d_vector.BL_REGISTER,
|
*complex_2d_vector.BL_REGISTER,
|
||||||
|
|
||||||
|
*integer_3d_vector.BL_REGISTER,
|
||||||
*real_3d_vector.BL_REGISTER,
|
*real_3d_vector.BL_REGISTER,
|
||||||
*complex_3d_vector.BL_REGISTER,
|
*complex_3d_vector.BL_REGISTER,
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
import typing as typ
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
import sympy as sp
|
||||||
|
import pydantic as pyd
|
||||||
|
|
||||||
|
from .....utils.pydantic_sympy import ConstrSympyExpr
|
||||||
|
from .. import base
|
||||||
|
from ... import contracts as ct
|
||||||
|
|
||||||
|
Integer3DVector = ConstrSympyExpr(
|
||||||
|
allow_variables=False,
|
||||||
|
allow_units=False,
|
||||||
|
allowed_sets={"integer"},
|
||||||
|
allowed_structures={"matrix"},
|
||||||
|
allowed_matrix_shapes={(3, 1)},
|
||||||
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Socket
|
||||||
|
####################
|
||||||
|
class Integer3DVectorBLSocket(base.MaxwellSimSocket):
|
||||||
|
socket_type = ct.SocketType.Integer3DVector
|
||||||
|
bl_label = "Integer 3D Vector"
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Properties
|
||||||
|
####################
|
||||||
|
raw_value: bpy.props.IntVectorProperty(
|
||||||
|
name="Int 3D Vector",
|
||||||
|
description="Represents an integer 3D (coordinate) vector",
|
||||||
|
size=3,
|
||||||
|
default=(0, 0, 0),
|
||||||
|
update=(lambda self, context: self.sync_prop("raw_value", context)),
|
||||||
|
)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Socket UI
|
||||||
|
####################
|
||||||
|
def draw_value(self, col: bpy.types.UILayout) -> None:
|
||||||
|
col.prop(self, "raw_value", text="")
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Computation of Default Value
|
||||||
|
####################
|
||||||
|
@property
|
||||||
|
def value(self) -> Integer3DVector:
|
||||||
|
return sp.Matrix(tuple(self.raw_value))
|
||||||
|
|
||||||
|
@value.setter
|
||||||
|
def value(self, value: Integer3DVector) -> None:
|
||||||
|
self.raw_value = tuple(int(el) for el in value)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Socket Configuration
|
||||||
|
####################
|
||||||
|
class Integer3DVectorSocketDef(pyd.BaseModel):
|
||||||
|
socket_type: ct.SocketType = ct.SocketType.Integer3DVector
|
||||||
|
|
||||||
|
default_value: Integer3DVector = sp.Matrix([0, 0, 0])
|
||||||
|
|
||||||
|
def init(self, bl_socket: Integer3DVectorBLSocket) -> None:
|
||||||
|
bl_socket.value = self.default_value
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Blender Registration
|
||||||
|
####################
|
||||||
|
BL_REGISTER = [
|
||||||
|
Integer3DVectorBLSocket,
|
||||||
|
]
|
|
@ -22,6 +22,13 @@ def get_units(expression: sp.Expr):
|
||||||
if isinstance(arg, spu.Quantity)
|
if isinstance(arg, spu.Quantity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# - Time
|
||||||
|
####################
|
||||||
|
femtosecond = fs = spu.Quantity("femtosecond", abbrev="fs")
|
||||||
|
femtosecond.set_global_relative_scale_factor(spu.femto, spu.second)
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# - Force
|
# - Force
|
||||||
####################
|
####################
|
||||||
|
|
Loading…
Reference in New Issue