diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/contracts.py b/blender_maxwell/node_trees/maxwell_sim_nodes/contracts.py index 6a55df7..a417a04 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/contracts.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/contracts.py @@ -79,6 +79,7 @@ class TreeType(BlenderTypeEnum): class SocketType(BlenderTypeEnum): # Base Any = enum.auto() + Bool = enum.auto() Text = enum.auto() FilePath = enum.auto() @@ -104,11 +105,19 @@ class SocketType(BlenderTypeEnum): PhysicalArea = enum.auto() PhysicalVolume = enum.auto() + PhysicalPoint2D = enum.auto() + PhysicalPoint3D = enum.auto() + + PhysicalSize2D = enum.auto() + PhysicalSize3D = enum.auto() + PhysicalMass = enum.auto() PhysicalSpeed = enum.auto() - PhysicalAccel = enum.auto() - PhysicalForce = enum.auto() + PhysicalAccelScalar = enum.auto() + PhysicalForceScalar = enum.auto() + PhysicalAccel3DVector = enum.auto() + PhysicalForce3DVector = enum.auto() PhysicalPol = enum.auto() @@ -220,6 +229,72 @@ SocketType_to_units = { }, }, + SocketType.PhysicalPoint2D: { + "default": "UM", + "values": { + "PM": spu.picometer, + "A": spu.angstrom, + "NM": spu.nanometer, + "UM": spu.micrometer, + "MM": spu.millimeter, + "CM": spu.centimeter, + "M": spu.meter, + "INCH": spu.inch, + "FOOT": spu.foot, + "YARD": spu.yard, + "MILE": spu.mile, + }, + }, + SocketType.PhysicalPoint3D: { + "default": "UM", + "values": { + "PM": spu.picometer, + "A": spu.angstrom, + "NM": spu.nanometer, + "UM": spu.micrometer, + "MM": spu.millimeter, + "CM": spu.centimeter, + "M": spu.meter, + "INCH": spu.inch, + "FOOT": spu.foot, + "YARD": spu.yard, + "MILE": spu.mile, + }, + }, + + SocketType.PhysicalSize2D: { + "default": "UM", + "values": { + "PM": spu.picometer, + "A": spu.angstrom, + "NM": spu.nanometer, + "UM": spu.micrometer, + "MM": spu.millimeter, + "CM": spu.centimeter, + "M": spu.meter, + "INCH": spu.inch, + "FOOT": spu.foot, + "YARD": spu.yard, + "MILE": spu.mile, + }, + }, + SocketType.PhysicalSize3D: { + "default": "UM", + "values": { + "PM": spu.picometer, + "A": spu.angstrom, + "NM": spu.nanometer, + "UM": spu.micrometer, + "MM": spu.millimeter, + "CM": spu.centimeter, + "M": spu.meter, + "INCH": spu.inch, + "FOOT": spu.foot, + "YARD": spu.yard, + "MILE": spu.mile, + }, + }, + SocketType.PhysicalMass: { "default": "UG", "values": { @@ -247,7 +322,7 @@ SocketType_to_units = { "MI_H": spu.mile / spu.hour, }, }, - SocketType.PhysicalAccel: { + SocketType.PhysicalAccelScalar: { "default": "UM_S_SQ", "values": { "PM_S_SQ": spu.picometer / spu.second**2, @@ -259,7 +334,29 @@ SocketType_to_units = { "FT_S_SQ": spu.feet / spu.second**2, }, }, - SocketType.PhysicalForce: { + SocketType.PhysicalForceScalar: { + "default": "UNEWT", + "values": { + "KG_M_S_SQ": spu.kg * spu.m/spu.second**2, + "NNEWT": spuex.nanonewton, + "UNEWT": spuex.micronewton, + "MNEWT": spuex.millinewton, + "NEWT": spu.newton, + }, + }, + SocketType.PhysicalAccel3DVector: { + "default": "UM_S_SQ", + "values": { + "PM_S_SQ": spu.picometer / spu.second**2, + "NM_S_SQ": spu.nanometer / spu.second**2, + "UM_S_SQ": spu.micrometer / spu.second**2, + "MM_S_SQ": spu.millimeter / spu.second**2, + "M_S_SQ": spu.meter / spu.second**2, + "KM_S_SQ": spu.kilometer / spu.second**2, + "FT_S_SQ": spu.feet / spu.second**2, + }, + }, + SocketType.PhysicalForce3DVector: { "default": "UNEWT", "values": { "KG_M_S_SQ": spu.kg * spu.m/spu.second**2, @@ -294,6 +391,7 @@ SocketType_to_units = { SocketType_to_color = { # Basic SocketType.Any: (0.8, 0.8, 0.8, 1.0), # Light Grey + SocketType.Bool: (0.7, 0.7, 0.7, 1.0), # Medium Light Grey SocketType.Text: (0.7, 0.7, 0.7, 1.0), # Medium Light Grey SocketType.FilePath: (0.6, 0.6, 0.6, 1.0), # Medium Grey @@ -315,10 +413,16 @@ SocketType_to_color = { SocketType.PhysicalLength: (0.8, 0.4, 0.4, 1.0), # Medium Red SocketType.PhysicalArea: (0.7, 0.35, 0.35, 1.0), # Medium Dark Red SocketType.PhysicalVolume: (0.6, 0.3, 0.3, 1.0), # Dark Red + SocketType.PhysicalPoint2D: (0.7, 0.35, 0.35, 1.0), # Medium Dark Red + SocketType.PhysicalPoint3D: (0.6, 0.3, 0.3, 1.0), # Dark Red + SocketType.PhysicalSize2D: (0.7, 0.35, 0.35, 1.0), # Medium Dark Red + SocketType.PhysicalSize3D: (0.6, 0.3, 0.3, 1.0), # Dark Red SocketType.PhysicalMass: (0.9, 0.6, 0.4, 1.0), # Light Orange SocketType.PhysicalSpeed: (0.8, 0.55, 0.35, 1.0), # Medium Light Orange - SocketType.PhysicalAccel: (0.7, 0.5, 0.3, 1.0), # Medium Orange - SocketType.PhysicalForce: (0.6, 0.45, 0.25, 1.0), # Medium Dark Orange + SocketType.PhysicalAccelScalar: (0.7, 0.5, 0.3, 1.0), # Medium Orange + SocketType.PhysicalForceScalar: (0.6, 0.45, 0.25, 1.0), # Medium Dark Orange + SocketType.PhysicalAccel3DVector: (0.7, 0.5, 0.3, 1.0), # Medium Orange + SocketType.PhysicalForce3DVector: (0.6, 0.45, 0.25, 1.0), # Medium Dark Orange SocketType.PhysicalPol: (0.5, 0.4, 0.2, 1.0), # Dark Orange SocketType.PhysicalFreq: (1.0, 0.7, 0.5, 1.0), # Light Peach SocketType.PhysicalSpecPowerDist: (0.9, 0.65, 0.45, 1.0), # Medium Light Peach diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py index ea1565a..6f131f2 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py @@ -371,12 +371,23 @@ class MaxwellSimTreeNode(bpy.types.Node): Blender's own node socket object. """ - # (Guard) Socket Exists - if input_socket_name not in self.input_sockets: - msg = f"Input socket with name {input_socket_name} does not exist" - raise ValueError(msg) + if input_socket_name in self.input_sockets: + # Check Nicely that it Exists + if input_socket_name not in self.input_sockets: + msg = f"Input socket with name {input_socket_name} does not exist" + raise ValueError(msg) + + return self.inputs[self.input_sockets[input_socket_name].label] - return self.inputs[self.input_sockets[input_socket_name].label] + elif hasattr(self, "input_socket_sets"): + # You're on your own, chump + + return self.inputs[next( + socket_def.label + for socket_set, socket_dict in self.input_socket_sets.items() + for socket_name, socket_def in socket_dict.items() + if socket_name == input_socket_name + )] def g_output_bl_socket( self, @@ -392,17 +403,35 @@ class MaxwellSimTreeNode(bpy.types.Node): Blender's own node socket object. """ - # (Guard) Socket Exists - if output_socket_name not in self.output_sockets: - msg = f"Input socket with name {output_socket_name} does not exist" - raise ValueError(msg) - return self.outputs[self.output_sockets[output_socket_name].label] + if output_socket_name in self.output_sockets: + # (Guard) Socket Exists + if output_socket_name not in self.output_sockets: + msg = f"Input socket with name {output_socket_name} does not exist" + raise ValueError(msg) + + return self.outputs[self.output_sockets[output_socket_name].label] + + elif hasattr(self, "input_socket_sets"): + return self.outputs[next( + socket_def.label + for socket_set, socket_dict in self.input_socket_sets.items() + for socket_name, socket_def in socket_dict.items() + if socket_name == output_socket_name + )] def g_output_socket_name( self, output_bl_socket_name: contracts.BLSocketName, ) -> contracts.SocketName: + if hasattr(self, "output_socket_sets"): + return next( + socket_name + for socket_set, socket_dict in self.output_socket_sets.items() + for socket_name, socket_def in socket_dict.items() + if socket_def.label == output_bl_socket_name + ) + else: return next( output_socket_name for output_socket_name in self.output_sockets.keys() diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/constants/number_constant.py b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/constants/number_constant.py index 216ff2f..16d0e36 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/constants/number_constant.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/constants/number_constant.py @@ -11,16 +11,21 @@ class NumberConstantNode(base.MaxwellSimTreeNode): bl_label = "Numerical Constant" #bl_icon = constants.ICON_SIM_INPUT - input_sockets = { - "value": sockets.ComplexNumberSocketDef( - label="Complex", - ), ## TODO: Dynamic number socket! - } - output_sockets = { - "value": sockets.ComplexNumberSocketDef( - label="Complex", - ), ## TODO: Dynamic number socket! + input_sockets = {} + input_socket_sets = { + "real": { + "value": sockets.RealNumberSocketDef( + label="Real", + ), + }, + "complex": { + "value": sockets.ComplexNumberSocketDef( + label="Complex", + ), + }, } + output_sockets = {} + output_socket_sets = input_socket_sets #################### # - Callbacks diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/constants/physical_constant.py b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/constants/physical_constant.py index 41fac16..1503b45 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/constants/physical_constant.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/constants/physical_constant.py @@ -1,5 +1,75 @@ +import bpy +import sympy as sp + +from .... import contracts +from .... import sockets +from ... import base + +class PhysicalConstantNode(base.MaxwellSimTreeNode): + node_type = contracts.NodeType.PhysicalConstant + + bl_label = "Physical Constant" + #bl_icon = constants.ICON_SIM_INPUT + + input_sockets = {} + input_socket_sets = { + "time": { + "value": sockets.PhysicalTimeSocketDef( + label="Time", + ), + }, + "angle": { + "value": sockets.PhysicalAngleSocketDef( + label="Angle", + ), + }, + "length": { + "value": sockets.PhysicalLengthSocketDef( + label="Length", + ), + }, + "area": { + "value": sockets.PhysicalAreaSocketDef( + label="Area", + ), + }, + "volume": { + "value": sockets.PhysicalVolumeSocketDef( + label="Volume", + ), + }, + "point_3d": { + "value": sockets.PhysicalPoint3DSocketDef( + label="3D Point", + ), + }, + "size_3d": { + "value": sockets.PhysicalSize3DSocketDef( + label="3D Size", + ), + }, + ## I got bored so maybe the rest later + } + output_sockets = {} + output_socket_sets = input_socket_sets + + #################### + # - Callbacks + #################### + @base.computes_output_socket("value") + def compute_value(self: contracts.NodeTypeProtocol) -> sp.Expr: + return self.compute_input("value") + + + #################### # - Blender Registration #################### -BL_REGISTER = [] -BL_NODES = {} +BL_REGISTER = [ + PhysicalConstantNode, +] +BL_NODES = { + contracts.NodeType.PhysicalConstant: ( + contracts.NodeCategory.MAXWELLSIM_INPUTS_CONSTANTS + ) +} diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/kitchen_sink.py b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/kitchen_sink.py index ea41c38..fac1788 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/kitchen_sink.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/kitchen_sink.py @@ -19,6 +19,7 @@ class KitchenSinkNode(base.MaxwellSimTreeNode): input_socket_sets = { "basic": { "basic_any": sockets.AnySocketDef(label="Any"), + "basic_bool": sockets.BoolSocketDef(label="Bool"), "basic_filepath": sockets.FilePathSocketDef(label="FilePath"), "basic_text": sockets.TextSocketDef(label="Text"), }, @@ -36,14 +37,20 @@ class KitchenSinkNode(base.MaxwellSimTreeNode): }, "physical": { "physical_time": sockets.PhysicalTimeSocketDef(label="PhysicalTime"), + #"physical_point_2d": sockets.PhysicalPoint2DSocketDef(label="PhysicalPoint2D"), "physical_angle": sockets.PhysicalAngleSocketDef(label="PhysicalAngle"), "physical_length": sockets.PhysicalLengthSocketDef(label="PhysicalLength"), "physical_area": sockets.PhysicalAreaSocketDef(label="PhysicalArea"), "physical_volume": sockets.PhysicalVolumeSocketDef(label="PhysicalVolume"), + "physical_point_3d": sockets.PhysicalPoint3DSocketDef(label="PhysicalPoint3D"), + #"physical_size_2d": sockets.PhysicalSize2DSocketDef(label="PhysicalSize2D"), + "physical_size_3d": sockets.PhysicalSize3DSocketDef(label="PhysicalSize3D"), "physical_mass": sockets.PhysicalMassSocketDef(label="PhysicalMass"), "physical_speed": sockets.PhysicalSpeedSocketDef(label="PhysicalSpeed"), - "physical_accel": sockets.PhysicalAccelSocketDef(label="PhysicalAccel"), - "physical_force": sockets.PhysicalForceSocketDef(label="PhysicalForce"), + "physical_accel_scalar": sockets.PhysicalAccelScalarSocketDef(label="PhysicalAccelScalar"), + "physical_force_scalar": sockets.PhysicalForceScalarSocketDef(label="PhysicalForceScalar"), + #"physical_accel_3dvector": sockets.PhysicalAccel3DVectorSocketDef(label="PhysicalAccel3DVector"), + #"physical_force_3dvector": sockets.PhysicalForce3DVectorSocketDef(label="PhysicalForce3DVector"), "physical_pol": sockets.PhysicalPolSocketDef(label="PhysicalPol"), "physical_freq": sockets.PhysicalFreqSocketDef(label="PhysicalFreq"), "physical_spec_power_dist": sockets.PhysicalSpecPowerDistSocketDef(label="PhysicalSpecPowerDist"), @@ -62,18 +69,21 @@ class KitchenSinkNode(base.MaxwellSimTreeNode): "maxwell_temporal_shape": sockets.MaxwellTemporalShapeSocketDef(label="MaxwellTemporalShape"), "maxwell_medium": sockets.MaxwellMediumSocketDef(label="MaxwellMedium"), #"maxwell_medium_nonlinearity": sockets.MaxwellMediumNonLinearitySocketDef(label="MaxwellMediumNonLinearity"), - "maxwell_structure": sockets.MaxwellMediumSocketDef(label="MaxwellMedium"), + "maxwell_structure": sockets.MaxwellStructureSocketDef(label="MaxwellMedium"), "maxwell_bound_box": sockets.MaxwellBoundBoxSocketDef(label="MaxwellBoundBox"), "maxwell_bound_face": sockets.MaxwellBoundFaceSocketDef(label="MaxwellBoundFace"), "maxwell_monitor": sockets.MaxwellMonitorSocketDef(label="MaxwellMonitor"), - "maxwell_monitor": sockets.MaxwellFDTDSimSocketDef(label="MaxwellFDTDSim"), - "maxwell_monitor": sockets.MaxwellSimGridSocketDef(label="MaxwellSimGrid"), - "maxwell_monitor": sockets.MaxwellSimGridAxisSocketDef(label="MaxwellSimGridAxis"), + "maxwell_fdtd_sim": sockets.MaxwellFDTDSimSocketDef(label="MaxwellFDTDSim"), + "maxwell_sim_grid": sockets.MaxwellSimGridSocketDef(label="MaxwellSimGrid"), + "maxwell_sim_grid_axis": sockets.MaxwellSimGridAxisSocketDef(label="MaxwellSimGridAxis"), }, } output_sockets = {} - output_socket_sets = input_socket_sets + output_socket_sets = { + k + " Output": v + for k, v in input_socket_sets.items() + } diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/simulations/fdtd_sim.py b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/simulations/fdtd_sim.py index e681efb..f08cbfc 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/simulations/fdtd_sim.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/simulations/fdtd_sim.py @@ -16,21 +16,11 @@ class FDTDSimNode(base.MaxwellSimTreeNode): # - Sockets #################### input_sockets = { - "run_time": sockets.RealNumberSocketDef( + "run_time": sockets.PhysicalTimeSocketDef( label="Run Time", - default_value=1.0, ), - "size_x": sockets.RealNumberSocketDef( - label="Size X", - default_value=1.0, - ), - "size_y": sockets.RealNumberSocketDef( - label="Size Y", - default_value=1.0, - ), - "size_z": sockets.RealNumberSocketDef( - label="Size Z", - default_value=1.0, + "size": sockets.PhysicalSize3DSocketDef( + label="Size", ), "ambient_medium": sockets.MaxwellMediumSocketDef( label="Ambient Medium", @@ -56,17 +46,15 @@ class FDTDSimNode(base.MaxwellSimTreeNode): #################### @base.computes_output_socket("fdtd_sim") def compute_simulation(self: contracts.NodeTypeProtocol) -> td.Simulation: - run_time = self.compute_input("run_time") + _run_time = self.compute_input("run_time") + _size = self.compute_input("size") ambient_medium = self.compute_input("ambient_medium") structures = [self.compute_input("structure")] sources = [self.compute_input("source")] bound = self.compute_input("bound") - size = ( - self.compute_input("size_x"), - self.compute_input("size_y"), - self.compute_input("size_z"), - ) + run_time = spu.convert_to(_run_time, spu.second) / spu.second + size = tuple(spu.convert_to(_size, spu.um) / spu.um) return td.Simulation( size=size, diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/point_dipole_source.py b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/point_dipole_source.py index 655d286..608dcb3 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/point_dipole_source.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/point_dipole_source.py @@ -16,17 +16,14 @@ class PointDipoleSourceNode(base.MaxwellSimTreeNode): # - Sockets #################### input_sockets = { - "center_x": sockets.RealNumberSocketDef( - label="Center X", - default_value=0.0, + #"polarization": sockets.PhysicalPolSocketDef( + # label="Polarization", + #), ## TODO: Exactly how to go about this... + "temporal_shape": sockets.MaxwellTemporalShapeSocketDef( + label="Temporal Shape", ), - "center_y": sockets.RealNumberSocketDef( - label="Center Y", - default_value=0.0, - ), - "center_z": sockets.RealNumberSocketDef( - label="Center Z", - default_value=0.0, + "center": sockets.PhysicalPoint3DSocketDef( + label="Center", ), } output_sockets = { @@ -40,19 +37,19 @@ class PointDipoleSourceNode(base.MaxwellSimTreeNode): #################### @base.computes_output_socket("source") def compute_source(self: contracts.NodeTypeProtocol) -> td.PointDipole: - center = ( - self.compute_input("center_x"), - self.compute_input("center_y"), - self.compute_input("center_z"), - ) + temporal_shape = self.compute_input("temporal_shape") - cheating_pulse = td.GaussianPulse(freq0=200e12, fwidth=20e12) + _center = self.compute_input("center") + center = tuple(spu.convert_to(_center, spu.um) / spu.um) + + cheating_pol = "Ex" + ## TODO: Fix return td.PointDipole( center=center, - source_time=cheating_pulse, + source_time=temporal_shape, interpolate=True, - polarization="Ex", + polarization=cheating_pol, ) diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/temporal_shapes/gaussian_pulse_temporal_shape.py b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/temporal_shapes/gaussian_pulse_temporal_shape.py index 8f4a665..5d29bda 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/temporal_shapes/gaussian_pulse_temporal_shape.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/temporal_shapes/gaussian_pulse_temporal_shape.py @@ -1,6 +1,82 @@ +import tidy3d as td +import sympy as sp +import sympy.physics.units as spu + +from .... import contracts +from .... import sockets +from ... import base + +class GaussianPulseTemporalShapeNode(base.MaxwellSimTreeNode): + node_type = contracts.NodeType.GaussianPulseTemporalShape + + bl_label = "Gaussian Pulse Temporal Shape" + #bl_icon = ... + + #################### + # - Sockets + #################### + input_sockets = { + #"amplitude": sockets.RealNumberSocketDef( + # label="Temporal Shape", + #), ## Should have a unit of some kind... + "phase": sockets.PhysicalAngleSocketDef( + label="Phase", + ), + "freq_center": sockets.PhysicalFreqSocketDef( + label="Freq Center", + ), + "freq_std": sockets.PhysicalFreqSocketDef( + label="Freq STD", + ), + "time_delay_rel_ang_freq": sockets.RealNumberSocketDef( + label="Time Delay rel. Ang. Freq", + ), + "remove_dc_component": sockets.BoolSocketDef( + label="Remove DC", + default_value=True, + ), + } + output_sockets = { + "temporal_shape": sockets.MaxwellTemporalShapeSocketDef( + label="Temporal Shape", + ), + } + + #################### + # - Output Socket Computation + #################### + @base.computes_output_socket("temporal_shape") + def compute_source(self: contracts.NodeTypeProtocol) -> td.PointDipole: + _phase = self.compute_input("phase") + _freq_center = self.compute_input("freq_center") + _freq_std = self.compute_input("freq_std") + time_delay_rel_ang_freq = self.compute_input("time_delay_rel_ang_freq") + remove_dc_component = self.compute_input("remove_dc_component") + + cheating_amplitude = 1.0 + phase = spu.convert_to(_phase, spu.radian) / spu.radian + freq_center = spu.convert_to(_freq_center, spu.hertz) / spu.hertz + freq_std = spu.convert_to(_freq_std, spu.hertz) / spu.hertz + + return td.GaussianPulse( + amplitude=cheating_amplitude, + phase=phase, + freq0=freq_center, + fwidth=freq_std, + offset=time_delay_rel_ang_freq, + remove_dc_component=remove_dc_component, + ) + + + #################### # - Blender Registration #################### -BL_REGISTER = [] -BL_NODES = {} - +BL_REGISTER = [ + GaussianPulseTemporalShapeNode, +] +BL_NODES = { + contracts.NodeType.GaussianPulseTemporalShape: ( + contracts.NodeCategory.MAXWELLSIM_SOURCES_TEMPORALSHAPES + ) +} diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py index d550c69..56c0961 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py @@ -18,29 +18,11 @@ class BoxStructureNode(base.MaxwellSimTreeNode): "medium": sockets.MaxwellMediumSocketDef( label="Medium", ), - "center_x": sockets.RealNumberSocketDef( - label="Center X", - default_value=0.0, + "center": sockets.PhysicalPoint3DSocketDef( + label="Center", ), - "center_y": sockets.RealNumberSocketDef( - label="Center Y", - default_value=0.0, - ), - "center_z": sockets.RealNumberSocketDef( - label="Center Z", - default_value=0.0, - ), - "size_x": sockets.RealNumberSocketDef( - label="Size X", - default_value=1.0, - ), - "size_y": sockets.RealNumberSocketDef( - label="Size Y", - default_value=1.0, - ), - "size_z": sockets.RealNumberSocketDef( - label="Size Z", - default_value=1.0, + "size": sockets.PhysicalSize3DSocketDef( + label="Size", ), } output_sockets = { @@ -55,16 +37,11 @@ class BoxStructureNode(base.MaxwellSimTreeNode): @base.computes_output_socket("structure") def compute_simulation(self: contracts.NodeTypeProtocol) -> td.Box: medium = self.compute_input("medium") - center = ( - self.compute_input("center_x"), - self.compute_input("center_y"), - self.compute_input("center_z"), - ) - size = ( - self.compute_input("size_x"), - self.compute_input("size_y"), - self.compute_input("size_z"), - ) + _center = self.compute_input("center") + _size = self.compute_input("size") + + center = tuple(spu.convert_to(_center, spu.um) / spu.um) + size = tuple(spu.convert_to(_size, spu.um) / spu.um) return td.Structure( geometry=td.Box( diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/__init__.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/__init__.py index d61eb79..c0a2853 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/__init__.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/__init__.py @@ -1,5 +1,6 @@ from . import basic AnySocketDef = basic.AnySocketDef +BoolSocketDef = basic.BoolSocketDef TextSocketDef = basic.TextSocketDef FilePathSocketDef = basic.FilePathSocketDef @@ -21,10 +22,12 @@ PhysicalAngleSocketDef = physical.PhysicalAngleSocketDef PhysicalLengthSocketDef = physical.PhysicalLengthSocketDef PhysicalAreaSocketDef = physical.PhysicalAreaSocketDef PhysicalVolumeSocketDef = physical.PhysicalVolumeSocketDef +PhysicalPoint3DSocketDef = physical.PhysicalPoint3DSocketDef +PhysicalSize3DSocketDef = physical.PhysicalSize3DSocketDef PhysicalMassSocketDef = physical.PhysicalMassSocketDef PhysicalSpeedSocketDef = physical.PhysicalSpeedSocketDef -PhysicalAccelSocketDef = physical.PhysicalAccelSocketDef -PhysicalForceSocketDef = physical.PhysicalForceSocketDef +PhysicalAccelScalarSocketDef = physical.PhysicalAccelScalarSocketDef +PhysicalForceScalarSocketDef = physical.PhysicalForceScalarSocketDef PhysicalPolSocketDef = physical.PhysicalPolSocketDef PhysicalFreqSocketDef = physical.PhysicalFreqSocketDef PhysicalSpecRelPermDistSocketDef = physical.PhysicalSpecRelPermDistSocketDef diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/base.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/base.py index 9655cf1..bfd451a 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/base.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/base.py @@ -127,10 +127,16 @@ class BLSocket(bpy.types.NodeSocket): the value with the new unit. """ if hasattr(self, "raw_value") and hasattr(self, "unit"): - self.raw_value = spu.convert_to( - self.raw_value * self._unit_previous, - self.unit, - ) / self.unit + if hasattr(self.raw_value, "__getitem__"): + self.raw_value = tuple(spu.convert_to( + sp.Matrix(tuple(self.raw_value)) * self._unit_previous, + self.unit, + ) / self.unit) + else: + self.raw_value = spu.convert_to( + self.raw_value * self._unit_previous, + self.unit, + ) / self.unit self._unit_previous = self.unit @@ -187,6 +193,9 @@ class BLSocket(bpy.types.NodeSocket): label_col_row = col.row(align=True) if hasattr(self, "draw_label_row"): self.draw_label_row(label_col_row, text) + elif hasattr(self, "raw_unit"): + label_col_row.label(text=text) + label_col_row.prop(self, "raw_unit", text="") else: label_col_row.label(text=text) @@ -208,6 +217,9 @@ class BLSocket(bpy.types.NodeSocket): # Row(s): Value if hasattr(self, "draw_value"): self.draw_value(col) + elif hasattr(self, "raw_value"): + #col_row = col.row(align=True) + col.prop(self, "raw_value", text="") def draw_output( self, diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/__init__.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/__init__.py index 0f5cc2a..db03d73 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/__init__.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/__init__.py @@ -1,6 +1,9 @@ from . import any_socket AnySocketDef = any_socket.AnySocketDef +from . import bool_socket +BoolSocketDef = bool_socket.BoolSocketDef + from . import text_socket TextSocketDef = text_socket.TextSocketDef @@ -10,6 +13,7 @@ FilePathSocketDef = file_path_socket.FilePathSocketDef BL_REGISTER = [ *any_socket.BL_REGISTER, + *bool_socket.BL_REGISTER, *text_socket.BL_REGISTER, *file_path_socket.BL_REGISTER, ] diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/bool_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/bool_socket.py new file mode 100644 index 0000000..a417304 --- /dev/null +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/bool_socket.py @@ -0,0 +1,73 @@ +import typing as typ + +import bpy +import sympy as sp +import pydantic as pyd + +from .. import base +from ... import contracts + +#################### +# - Blender Socket +#################### +class BoolBLSocket(base.BLSocket): + socket_type = contracts.SocketType.Bool + bl_label = "Bool" + + compatible_types = { + bool: {}, + } + + #################### + # - Properties + #################### + raw_value: bpy.props.BoolProperty( + name="Boolean", + description="Represents a boolean", + default=False, + ) + + #################### + # - Socket UI + #################### + def draw_label_row(self, label_col_row: bpy.types.UILayout, text: str) -> None: + label_col_row.label(text=text) + label_col_row.prop(self, "raw_value", text="") + + def draw_value(self, label_col_row: bpy.types.UILayout) -> None: + pass + + #################### + # - Computation of Default Value + #################### + @property + def default_value(self) -> str: + return self.raw_value + + @default_value.setter + def default_value(self, value: typ.Any) -> None: + # (Guard) Value Compatibility + if not self.is_compatible(value): + msg = f"Tried setting socket ({self}) to incompatible value ({value}) of type {type(value)}" + raise ValueError(msg) + + self.raw_value = bool(value) + +#################### +# - Socket Configuration +#################### +class BoolSocketDef(pyd.BaseModel): + socket_type: contracts.SocketType = contracts.SocketType.Bool + label: str + + default_value: bool = False + + def init(self, bl_socket: BoolBLSocket) -> None: + bl_socket.raw_value = self.default_value + +#################### +# - Blender Registration +#################### +BL_REGISTER = [ + BoolBLSocket, +] diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/text_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/text_socket.py index dfdbff7..c6b2fd0 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/text_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/basic/text_socket.py @@ -37,6 +37,9 @@ class TextBLSocket(base.BLSocket): """ label_col_row.prop(self, "raw_value", text=text) + def draw_value(self, label_col_row: bpy.types.UILayout) -> None: + pass + #################### # - Computation of Default Value #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/__init__.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/__init__.py index c09a292..6088df8 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/__init__.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/__init__.py @@ -32,6 +32,7 @@ BL_REGISTER = [ *source_socket.BL_REGISTER, *temporal_shape_socket.BL_REGISTER, *structure_socket.BL_REGISTER, + *monitor_socket.BL_REGISTER, *fdtd_sim_socket.BL_REGISTER, *sim_grid_socket.BL_REGISTER, *sim_grid_axis_socket.BL_REGISTER, diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/medium_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/medium_socket.py index 4929229..cd9312f 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/medium_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/maxwell/medium_socket.py @@ -22,7 +22,7 @@ class MaxwellMediumBLSocket(base.BLSocket): name="Permittivity", description="Represents a simple, real permittivity.", default=0.0, - precision=6, + precision=4, ) #################### @@ -33,7 +33,7 @@ class MaxwellMediumBLSocket(base.BLSocket): specifying the active unit. """ col_row = col.row(align=True) - col_row.prop(self, "rel_permittivity", text="Re(eps_r)") + col_row.prop(self, "rel_permittivity", text="ϵr") #################### # - Computation of Default Value diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/number/real_number_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/number/real_number_socket.py index d7427fe..7a3da98 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/number/real_number_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/number/real_number_socket.py @@ -32,14 +32,6 @@ class RealNumberBLSocket(base.BLSocket): precision=6, ) - #################### - # - Socket UI - #################### - def draw_label_row(self, label_col_row: bpy.types.UILayout, text: str) -> None: - """Draw the value of the real number. - """ - label_col_row.prop(self, "raw_value", text=text) - #################### # - Computation of Default Value #################### diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/__init__.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/__init__.py index 943e06e..182e2fc 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/__init__.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/__init__.py @@ -11,15 +11,21 @@ PhysicalLengthSocketDef = length_socket.PhysicalLengthSocketDef PhysicalAreaSocketDef = area_socket.PhysicalAreaSocketDef PhysicalVolumeSocketDef = volume_socket.PhysicalVolumeSocketDef +from . import point_3d_socket +PhysicalPoint3DSocketDef = point_3d_socket.PhysicalPoint3DSocketDef + +from . import size_3d_socket +PhysicalSize3DSocketDef = size_3d_socket.PhysicalSize3DSocketDef + from . import mass_socket PhysicalMassSocketDef = mass_socket.PhysicalMassSocketDef from . import speed_socket -from . import accel_socket -from . import force_socket +from . import accel_scalar_socket +from . import force_scalar_socket PhysicalSpeedSocketDef = speed_socket.PhysicalSpeedSocketDef -PhysicalAccelSocketDef = accel_socket.PhysicalAccelSocketDef -PhysicalForceSocketDef = force_socket.PhysicalForceSocketDef +PhysicalAccelScalarSocketDef = accel_scalar_socket.PhysicalAccelScalarSocketDef +PhysicalForceScalarSocketDef = force_scalar_socket.PhysicalForceScalarSocketDef from . import pol_socket PhysicalPolSocketDef = pol_socket.PhysicalPolSocketDef @@ -42,11 +48,15 @@ BL_REGISTER = [ *area_socket.BL_REGISTER, *volume_socket.BL_REGISTER, + *point_3d_socket.BL_REGISTER, + + *size_3d_socket.BL_REGISTER, + *mass_socket.BL_REGISTER, *speed_socket.BL_REGISTER, - *accel_socket.BL_REGISTER, - *force_socket.BL_REGISTER, + *accel_scalar_socket.BL_REGISTER, + *force_scalar_socket.BL_REGISTER, *pol_socket.BL_REGISTER, diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/accel_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/accel_scalar_socket.py similarity index 61% rename from blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/accel_socket.py rename to blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/accel_scalar_socket.py index deba94e..02d9b5a 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/accel_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/accel_scalar_socket.py @@ -9,8 +9,8 @@ from ... import contracts #################### # - Blender Socket #################### -class PhysicalAccelBLSocket(base.BLSocket): - socket_type = contracts.SocketType.PhysicalAccel +class PhysicalAccelScalarBLSocket(base.BLSocket): + socket_type = contracts.SocketType.PhysicalAccelScalar bl_label = "PhysicalAccel" use_units = True @@ -24,17 +24,6 @@ class PhysicalAccelBLSocket(base.BLSocket): precision=6, ) - #################### - # - Socket UI - #################### - def draw_label_row(self, label_col_row: bpy.types.UILayout, text: str) -> None: - label_col_row.label(text=text) - label_col_row.prop(self, "raw_unit", text="") - - def draw_value(self, col: bpy.types.UILayout) -> None: - col_row = col.row(align=True) - col_row.prop(self, "raw_value", text="") - #################### # - Default Value #################### @@ -49,16 +38,19 @@ class PhysicalAccelBLSocket(base.BLSocket): #################### # - Socket Configuration #################### -class PhysicalAccelSocketDef(pyd.BaseModel): - socket_type: contracts.SocketType = contracts.SocketType.PhysicalAccel +class PhysicalAccelScalarSocketDef(pyd.BaseModel): + socket_type: contracts.SocketType = contracts.SocketType.PhysicalAccelScalar label: str - def init(self, bl_socket: PhysicalAccelBLSocket) -> None: - pass + default_unit: typ.Any | None = None + + def init(self, bl_socket: PhysicalAccelScalarBLSocket) -> None: + if self.default_unit: + bl_socket.unit = self.default_unit #################### # - Blender Registration #################### BL_REGISTER = [ - PhysicalAccelBLSocket, + PhysicalAccelScalarBLSocket, ] diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/angle_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/angle_socket.py index 3a2b62d..ac4bfc5 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/angle_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/angle_socket.py @@ -1,5 +1,6 @@ import typing as typ +import bpy import pydantic as pyd from .. import base @@ -11,17 +12,28 @@ from ... import contracts class PhysicalAngleBLSocket(base.BLSocket): socket_type = contracts.SocketType.PhysicalAngle bl_label = "PhysicalAngle" + use_units = True + + #################### + # - Properties + #################### + raw_value: bpy.props.FloatProperty( + name="Unitless Acceleration", + description="Represents the unitless part of the acceleration", + default=0.0, + precision=4, + ) #################### # - Default Value #################### @property def default_value(self) -> None: - pass + return self.raw_value * self.unit @default_value.setter def default_value(self, value: typ.Any) -> None: - pass + self.raw_value = self.value_as_unit(value) #################### # - Socket Configuration @@ -30,8 +42,11 @@ class PhysicalAngleSocketDef(pyd.BaseModel): socket_type: contracts.SocketType = contracts.SocketType.PhysicalAngle label: str + default_unit: typ.Any | None = None + def init(self, bl_socket: PhysicalAngleBLSocket) -> None: - pass + if self.default_unit: + bl_socket.unit = self.default_unit #################### # - Blender Registration diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/area_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/area_socket.py index 5adf794..5ad6dea 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/area_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/area_socket.py @@ -38,9 +38,6 @@ class PhysicalAreaBLSocket(base.BLSocket): # - Socket UI #################### def draw_label_row(self, label_col_row: bpy.types.UILayout, text: str) -> None: - """Draw the value of the area, including a toggle for - specifying the active unit. - """ label_col_row.label(text=text) label_col_row.prop(self, "raw_unit", text="") diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/force_scalar_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/force_scalar_socket.py new file mode 100644 index 0000000..1e84256 --- /dev/null +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/force_scalar_socket.py @@ -0,0 +1,56 @@ +import typing as typ + +import bpy +import pydantic as pyd + +from .. import base +from ... import contracts + +#################### +# - Blender Socket +#################### +class PhysicalForceScalarBLSocket(base.BLSocket): + socket_type = contracts.SocketType.PhysicalForceScalar + bl_label = "PhysicalForceScalar" + use_units = True + + #################### + # - Properties + #################### + raw_value: bpy.props.FloatProperty( + name="Unitless Force", + description="Represents the unitless part of the force", + default=0.0, + precision=6, + ) + + #################### + # - Default Value + #################### + @property + def default_value(self) -> None: + return self.raw_value * self.unit + + @default_value.setter + def default_value(self, value: typ.Any) -> None: + self.raw_value = self.value_as_unit(value) + +#################### +# - Socket Configuration +#################### +class PhysicalForceScalarSocketDef(pyd.BaseModel): + socket_type: contracts.SocketType = contracts.SocketType.PhysicalForceScalar + label: str + + default_unit: typ.Any | None = None + + def init(self, bl_socket: PhysicalForceScalarBLSocket) -> None: + if self.default_unit: + bl_socket.unit = self.default_unit + +#################### +# - Blender Registration +#################### +BL_REGISTER = [ + PhysicalForceScalarBLSocket, +] diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/force_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/force_socket.py deleted file mode 100644 index e558597..0000000 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/force_socket.py +++ /dev/null @@ -1,41 +0,0 @@ -import typing as typ - -import pydantic as pyd - -from .. import base -from ... import contracts - -#################### -# - Blender Socket -#################### -class PhysicalForceBLSocket(base.BLSocket): - socket_type = contracts.SocketType.PhysicalForce - bl_label = "PhysicalForce" - - #################### - # - Default Value - #################### - @property - def default_value(self) -> None: - pass - - @default_value.setter - def default_value(self, value: typ.Any) -> None: - pass - -#################### -# - Socket Configuration -#################### -class PhysicalForceSocketDef(pyd.BaseModel): - socket_type: contracts.SocketType = contracts.SocketType.PhysicalForce - label: str - - def init(self, bl_socket: PhysicalForceBLSocket) -> None: - pass - -#################### -# - Blender Registration -#################### -BL_REGISTER = [ - PhysicalForceBLSocket, -] diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/freq_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/freq_socket.py index 66a1cb3..0ef7376 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/freq_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/freq_socket.py @@ -1,5 +1,6 @@ import typing as typ +import bpy import pydantic as pyd from .. import base @@ -11,17 +12,28 @@ from ... import contracts class PhysicalFreqBLSocket(base.BLSocket): socket_type = contracts.SocketType.PhysicalFreq bl_label = "PhysicalFreq" + use_units = True + + #################### + # - Properties + #################### + raw_value: bpy.props.FloatProperty( + name="Unitless Frequency", + description="Represents the unitless part of the frequency", + default=0.0, + precision=6, + ) #################### # - Default Value #################### @property def default_value(self) -> None: - pass + return self.raw_value * self.unit @default_value.setter def default_value(self, value: typ.Any) -> None: - pass + self.raw_value = self.value_as_unit(value) #################### # - Socket Configuration diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/length_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/length_socket.py index d153d89..109f29b 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/length_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/length_socket.py @@ -1,5 +1,6 @@ import typing as typ +import bpy import pydantic as pyd from .. import base @@ -11,17 +12,28 @@ from ... import contracts class PhysicalLengthBLSocket(base.BLSocket): socket_type = contracts.SocketType.PhysicalLength bl_label = "PhysicalLength" + use_units = True + + #################### + # - Properties + #################### + raw_value: bpy.props.FloatProperty( + name="Unitless Force", + description="Represents the unitless part of the force", + default=0.0, + precision=6, + ) #################### # - Default Value #################### @property def default_value(self) -> None: - pass + return self.raw_value * self.unit @default_value.setter def default_value(self, value: typ.Any) -> None: - pass + self.raw_value = self.value_as_unit(value) #################### # - Socket Configuration @@ -30,8 +42,11 @@ class PhysicalLengthSocketDef(pyd.BaseModel): socket_type: contracts.SocketType = contracts.SocketType.PhysicalLength label: str + default_unit: typ.Any | None = None + def init(self, bl_socket: PhysicalLengthBLSocket) -> None: - pass + if self.default_unit: + bl_socket.unit = self.default_unit #################### # - Blender Registration diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/point_3d_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/point_3d_socket.py new file mode 100644 index 0000000..812f84b --- /dev/null +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/point_3d_socket.py @@ -0,0 +1,67 @@ +import typing as typ + +import bpy +import sympy as sp +import sympy.physics.units as spu +import pydantic as pyd + +from .. import base +from ... import contracts + +class PhysicalPoint3DBLSocket(base.BLSocket): + socket_type = contracts.SocketType.PhysicalPoint3D + bl_label = "Physical Volume" + use_units = True + + compatible_types = { + sp.Expr: { + lambda self, v: v.is_real, + lambda self, v: len(v.free_symbols) == 0, + lambda self, v: any( + contracts.is_exactly_expressed_as_unit(v, unit) + for unit in self.units.values() + ) + }, + } + + #################### + # - Properties + #################### + raw_value: bpy.props.FloatVectorProperty( + name="Unitless 3D Point (global coordinate system)", + description="Represents the unitless part of the 3D point", + size=3, + default=(0.0, 0.0, 0.0), + precision=4, + ) + + #################### + # - Computation of Default Value + #################### + @property + def default_value(self) -> sp.Expr: + return sp.Matrix(tuple(self.raw_value)) * self.unit + + @default_value.setter + def default_value(self, value: typ.Any) -> None: + self.raw_value = self.value_as_unit(value) + +#################### +# - Socket Configuration +#################### +class PhysicalPoint3DSocketDef(pyd.BaseModel): + socket_type: contracts.SocketType = contracts.SocketType.PhysicalPoint3D + label: str + + default_unit: typ.Any | None = None + + def init(self, bl_socket: PhysicalPoint3DBLSocket) -> None: + if self.default_unit: + bl_socket.unit = self.default_unit + +#################### +# - Blender Registration +#################### +BL_REGISTER = [ + PhysicalPoint3DBLSocket, +] diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/size_3d_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/size_3d_socket.py new file mode 100644 index 0000000..aabd749 --- /dev/null +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/size_3d_socket.py @@ -0,0 +1,67 @@ +import typing as typ + +import bpy +import sympy as sp +import sympy.physics.units as spu +import pydantic as pyd + +from .. import base +from ... import contracts + +class PhysicalSize3DBLSocket(base.BLSocket): + socket_type = contracts.SocketType.PhysicalSize3D + bl_label = "Physical Volume" + use_units = True + + compatible_types = { + sp.Expr: { + lambda self, v: v.is_real, + lambda self, v: len(v.free_symbols) == 0, + lambda self, v: any( + contracts.is_exactly_expressed_as_unit(v, unit) + for unit in self.units.values() + ) + }, + } + + #################### + # - Properties + #################### + raw_value: bpy.props.FloatVectorProperty( + name="Unitless 3D Size", + description="Represents the unitless part of the 3D size", + size=3, + default=(1.0, 1.0, 1.0), + precision=4, + ) + + #################### + # - Computation of Default Value + #################### + @property + def default_value(self) -> sp.Expr: + return sp.Matrix(tuple(self.raw_value)) * self.unit + + @default_value.setter + def default_value(self, value: typ.Any) -> None: + self.raw_value = self.value_as_unit(value) + +#################### +# - Socket Configuration +#################### +class PhysicalSize3DSocketDef(pyd.BaseModel): + socket_type: contracts.SocketType = contracts.SocketType.PhysicalSize3D + label: str + + default_unit: typ.Any | None = None + + def init(self, bl_socket: PhysicalSize3DBLSocket) -> None: + if self.default_unit: + bl_socket.unit = self.default_unit + +#################### +# - Blender Registration +#################### +BL_REGISTER = [ + PhysicalSize3DBLSocket, +] diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/time_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/time_socket.py index 093ddbe..a35759b 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/time_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/time_socket.py @@ -1,5 +1,6 @@ import typing as typ +import bpy import pydantic as pyd from .. import base @@ -11,17 +12,28 @@ from ... import contracts class PhysicalTimeBLSocket(base.BLSocket): socket_type = contracts.SocketType.PhysicalTime bl_label = "PhysicalTime" + use_units = True + + #################### + # - Properties + #################### + raw_value: bpy.props.FloatProperty( + name="Unitless Force", + description="Represents the unitless part of the force", + default=0.0, + precision=6, + ) #################### # - Default Value #################### @property def default_value(self) -> None: - pass + return self.raw_value * self.unit @default_value.setter def default_value(self, value: typ.Any) -> None: - pass + self.raw_value = self.value_as_unit(value) #################### # - Socket Configuration @@ -30,8 +42,11 @@ class PhysicalTimeSocketDef(pyd.BaseModel): socket_type: contracts.SocketType = contracts.SocketType.PhysicalTime label: str + default_unit: typ.Any | None = None + def init(self, bl_socket: PhysicalTimeBLSocket) -> None: - pass + if self.default_unit: + bl_socket.unit = self.default_unit #################### # - Blender Registration diff --git a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/volume_socket.py b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/volume_socket.py index 4fa88fc..cd465c6 100644 --- a/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/volume_socket.py +++ b/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/physical/volume_socket.py @@ -5,9 +5,6 @@ import sympy as sp import sympy.physics.units as spu import pydantic as pyd -sp.printing.str.StrPrinter._default_settings['abbrev'] = True -## When we str() a unit expression, use abbrevied units. - from .. import base from ... import contracts diff --git a/blender_maxwell/requirements.txt b/blender_maxwell/requirements.txt index 2d1034c..4bcb244 100644 --- a/blender_maxwell/requirements.txt +++ b/blender_maxwell/requirements.txt @@ -1,3 +1,4 @@ tidy3d==2.5.2 pydantic==2.6.0 sympy==1.12 +scipy==1.12.0