diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/flow_kinds/lazy_func.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/flow_kinds/lazy_func.py index 52c0fb2..f5c6163 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/flow_kinds/lazy_func.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/flow_kinds/lazy_func.py @@ -369,15 +369,6 @@ class FuncFlow: return data | {info.output: self.realize(params, symbol_values=symbol_values)} - # return { - # dim: ( - # dim_idx - # if info.has_idx_cont(dim) or info.has_idx_labels(dim) - # else ?? - # ) - # for dim, dim_idx in self.dims - # } | {info.output: output_data} - #################### # - Composition Operations #################### diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/flow_kinds/params.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/flow_kinds/params.py index fdc0568..fb445a6 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/flow_kinds/params.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/flow_kinds/params.py @@ -251,7 +251,7 @@ class ParamsFlow: func_args=self.func_args + other.func_args, func_kwargs=self.func_kwargs | other.func_kwargs, symbols=self.symbols | other.symbols, - is_differentiable=self.is_differentiable & other.is_differentiable, + is_differentiable=self.is_differentiable and other.is_differentiable, ) def compose_within( diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py index b81504e..c660630 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/base.py @@ -453,10 +453,17 @@ class MaxwellSimNode(bpy.types.Node, bl_instance.BLInstance): created_sockets[socket_name] = socket_def # Initialize Just-Created BL Sockets - for socket_name, socket_def in created_sockets.items(): - socket_def.preinit(all_bl_sockets[socket_name]) - socket_def.init(all_bl_sockets[socket_name]) - socket_def.postinit(all_bl_sockets[socket_name]) + for bl_socket_name, socket_def in created_sockets.items(): + socket_def.preinit(all_bl_sockets[bl_socket_name]) + socket_def.init(all_bl_sockets[bl_socket_name]) + socket_def.postinit(all_bl_sockets[bl_socket_name]) + + # Invalidate Cached NoFlows + self._compute_input.invalidate( + input_socket_name=bl_socket_name, + kind=..., + unit_system=..., + ) def _sync_sockets(self) -> None: """Synchronize the node's sockets with the active sockets. diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/bounds/bound_cond_nodes/absorbing_bound_cond.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/bounds/bound_cond_nodes/absorbing_bound_cond.py index 2bf8b6b..35b9a7a 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/bounds/bound_cond_nodes/absorbing_bound_cond.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/bounds/bound_cond_nodes/absorbing_bound_cond.py @@ -110,10 +110,11 @@ class AdiabAbsorbBoundCondNode(base.MaxwellSimNode): col.label(text='2ε₀/Δt') #################### - # - Output + # - FlowKind.Value #################### @events.computes_output_socket( 'BC', + # Loaded props={'active_socket_set'}, input_sockets={ 'Layers', @@ -124,33 +125,154 @@ class AdiabAbsorbBoundCondNode(base.MaxwellSimNode): 'σ Order': True, 'σ Range': True, }, + output_sockets={'BC'}, + output_socket_kinds={'BC': ct.FlowKind.Params}, ) - def compute_adiab_absorber_bound_cond(self, props, input_sockets) -> td.Absorber: + def compute_bc_value(self, props, input_sockets, output_sockets) -> td.Absorber: r"""Computes the adiabatic absorber boundary condition based on the active socket set. - **Simple**: Use `tidy3d`'s default parameters for defining the absorber parameters (apart from number of layers). - **Full**: Use the user-defined $\sigma$ parameters, specifically polynomial order and sim-relative min/max conductivity values. """ - log.debug( - '%s: Computing "%s" Adiabatic Absorber Boundary Condition (Input Sockets = %s)', - self.sim_node_name, - props['active_socket_set'], - input_sockets, - ) + output_params = output_sockets['BC'] + layers = input_sockets['Layers'] - # Simple PML - if props['active_socket_set'] == 'Simple': - return td.Absorber(num_layers=input_sockets['Layers']) + has_output_params = not ct.FlowSignal.check(output_params) + has_layers = not ct.FlowSignal.check(layers) - # Full PML - return td.Absorber( - num_layers=input_sockets['Layers'], - parameters=td.AbsorberParams( - sigma_order=input_sockets['σ Order'], - sigma_min=input_sockets['σ Range'][0], - sigma_max=input_sockets['σ Range'][1], - ), - ) + active_socket_set = props['active_socket_set'] + if has_layers and has_output_params and not output_params.symbols: + # Simple PML + if active_socket_set == 'Simple': + return td.Absorber(num_layers=layers) + + # Full PML + sig_order = input_sockets['σ Order'] + sig_range = input_sockets['σ Range'] + + has_sig_order = not ct.FlowSignal.check(sig_order) + has_sig_range = not ct.FlowSignal.check(sig_range) + + if has_sig_order and has_sig_range: + return td.Absorber( + num_layers=layers, + parameters=td.AbsorberParams( + sigma_order=sig_order, + sigma_min=sig_range[0], + sigma_max=sig_range[1], + ), + ) + return ct.FlowSignal.FlowPending + + #################### + # - FlowKind.Func + #################### + @events.computes_output_socket( + 'BC', + kind=ct.FlowKind.Func, + # Loaded + props={'active_socket_set'}, + input_sockets={ + 'Layers', + 'σ Order', + 'σ Range', + }, + input_socket_kinds={ + 'Layers': ct.FlowKind.Func, + 'σ Order': ct.FlowKind.Func, + 'σ Range': ct.FlowKind.Func, + }, + input_sockets_optional={ + 'σ Order': True, + 'σ Range': True, + }, + output_sockets={'BC'}, + output_socket_kinds={'BC': ct.FlowKind.Params}, + ) + def compute_bc_func(self, props, input_sockets, output_sockets) -> td.Absorber: + r"""Computes the adiabatic absorber boundary condition based on the active socket set. + + - **Simple**: Use `tidy3d`'s default parameters for defining the absorber parameters (apart from number of layers). + - **Full**: Use the user-defined $\sigma$ parameters, specifically polynomial order and sim-relative min/max conductivity values. + """ + layers = input_sockets['Layers'] + + has_layers = not ct.FlowSignal.check(layers) + + active_socket_set = props['active_socket_set'] + if has_layers: + # Simple PML + if active_socket_set == 'Simple': + return layers.compose_within( + enclosing_func=lambda _layers: td.Absorber(num_layers=_layers), + supports_jax=False, + ) + + # Full PML + sig_order = input_sockets['σ Order'] + sig_range = input_sockets['σ Range'] + + has_sig_order = not ct.FlowSignal.check(sig_order) + has_sig_range = not ct.FlowSignal.check(sig_range) + + if has_sig_order and has_sig_range: + return (layers | sig_order | sig_range).compose_within( + enclosing_func=lambda els: td.Absorber( + num_layers=els[0][0], + parameters=td.AbsorberParams( + sigma_order=els[0][1], + sigma_min=els[1][0], + sigma_max=els[1][1], + ), + ), + supports_jax=False, + ) + return ct.FlowSignal.FlowPending + + #################### + # - FlowKind.Params + #################### + @events.computes_output_socket( + 'BC', + kind=ct.FlowKind.Params, + # Loaded + props={'active_socket_set'}, + input_sockets={ + 'Layers', + 'σ Order', + 'σ Range', + }, + input_socket_kinds={ + 'Layers': ct.FlowKind.Params, + 'σ Order': ct.FlowKind.Params, + 'σ Range': ct.FlowKind.Params, + }, + input_sockets_optional={ + 'σ Order': True, + 'σ Range': True, + }, + ) + def compute_params(self, props, input_sockets) -> td.Box: + layers = input_sockets['Layers'] + + has_layers = not ct.FlowSignal.check(layers) + + active_socket_set = props['active_socket_set'] + if has_layers: + # Simple PML + if active_socket_set == 'Simple': + return layers + + # Full PML + sig_order = input_sockets['σ Order'] + sig_range = input_sockets['σ Range'] + + has_sig_order = not ct.FlowSignal.check(sig_order) + has_sig_range = not ct.FlowSignal.check(sig_range) + + if has_sig_order and has_sig_range: + return layers | sig_order | sig_range + return ct.FlowSignal.FlowPending #################### diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/bounds/bound_conds.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/bounds/bound_conds.py index 622df33..c5906e9 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/bounds/bound_conds.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/bounds/bound_conds.py @@ -93,10 +93,11 @@ class BoundCondsNode(base.MaxwellSimNode): } #################### - # - Output Socket Computation + # - FlowKind.Value #################### @events.computes_output_socket( 'BCs', + kind=ct.FlowKind.Value, input_sockets={'X', 'Y', 'Z', '+X', '-X', '+Y', '-Y', '+Z', '-Z'}, input_sockets_optional={ 'X': True, diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py index d4d54b2..4c5cbfb 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/structures/primitives/box_structure.py @@ -205,8 +205,8 @@ class BoxStructureNode(base.MaxwellSimNode): if has_center and has_size and has_medium: if props['differentiable'] == ( center.is_differentiable - & size.is_differentiable - & medium.is_differentiable + and size.is_differentiable + and medium.is_differentiable ): return center | size | medium return ct.FlowSignal.FlowPending