Skip to content

Commit

Permalink
improving connectivity models
Browse files Browse the repository at this point in the history
  • Loading branch information
daquintero committed Sep 6, 2024
1 parent ef982eb commit 86eecee
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 11 deletions.
28 changes: 24 additions & 4 deletions docs/examples/10_electronic_photonic_timing_networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

# One of the main complexities of creating concurrent photonic-electronics systems is matching the timing between the optical signals and the electronic signals in relation to a datum reference. These concucrrent systems can hard enough to conceptualize, and hence `piel` provides some functionality to enable easier network analysis.

# ## Setting up a Basic Network
# ## The Basics

# ### `Connection` with `time`

# Part of the desired functionality in `piel` is to be able to understand these timing networks in relation to existing component definitions. Each `Connection` has a `time` definition which is defined as `TimeMetrics`.

# Let's start by creating a network of two paths.

import piel
import piel.experimental as pe

# Let's create a basic network between two paths.

Expand All @@ -23,7 +26,24 @@

# You will note that this `Connection` has some timing information attached to it. We can compose relevant timing information accordingly in the `Connection` definition:

timing = piel.types.TimeMetrics(value=0)
timing
basic_timing = piel.types.TimeMetrics(value=1)
timed_connection = piel.types.Connection(ports=[port_1, port_2], time=basic_timing)
timed_connection

# Using this functionality, now we can compute the total timing path of a given directional path. Now this is useful if we can define a `Component` and create connectivity accordingly.

# ### Modelling RF & Photonics Propagation
#
# A few important terms to understand are group velocity and group delay in a RF or photonic network. Basically, an RF or optical pulse is a collection of frequencies each which propagate slightly differently through a dispersive material such as many dielectrics which are used in coaxial cables or waveguides. This has a strong relationship to path-length matching in concurrent electronic-photonic systems.
#
# Let's create a cable and assign a corresponding group delay to it based on a given function:

dir(piel.models.physical.electrical)

piel.models

# +
pe.models

dir(piel.models.frequency)
piel.create_sequential_component_path()
# -
97 changes: 97 additions & 0 deletions piel/connectivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,16 @@
PhysicalConnection,
ConnectionTypes,
ComponentTypes,
TimeMetrics,
)
from piel.types.connectivity.abstract import Component


__all__ = [
"create_all_connections",
"create_component_connections",
"create_sequential_component_path",
]


def create_all_connections(
Expand Down Expand Up @@ -166,3 +175,91 @@ def create_component_connections(
connection_list.append(connection)

return connection_list


def create_sequential_component_path(
components: list[ComponentTypes], name: str = "", **kwargs
) -> ComponentTypes:
"""
This function takes in a list of components and creates a sequential path connectivity of components with all the ports defined in each component.
By default, the connectivity will be implemented with the first two ports of the components. There is a clear input and output on each component.
The timing metric calculations is provided by the timing model of each connection of the component, if there is none defined it will assume a default zero
time connectivity between the relevant ports. For the output component collection, it will output the timing of the network as a whole based on the
defined subcomponents.
This will create an output component with all the subcomponents, TODO more than two ports, and the list of ports
Creates a sequential path connectivity of components with all the ports defined in each component.
Parameters:
-----------
components : List[ComponentTypes]
A list of components to be connected sequentially.
Returns:
--------
ComponentTypes
A new component that encapsulates the sequential path of input components.
"""
if len(components) < 2:
raise ValueError(
"At least two components are required to create a sequential path."
)

connections = []
total_time_value = 0 # = TimeMetrics(name=name, attrs={}, value=0, mean=0, min=0, max=0, standard_deviation=0)

for i in range(len(components) - 1):
current_component = components[i]
next_component = components[i + 1]

# Assume the first port is output and the second is input
if len(current_component.ports) < 1 or len(next_component.ports) < 1:
raise ValueError(
f"Component {current_component.name} or {next_component.name} doesn't have enough ports."
)

output_port = current_component.ports[0]
input_port = next_component.ports[0]

# Create connection with timing information
connection_time = (
output_port.time if hasattr(output_port, "time") else TimeMetrics(value=0)
)
connection = Connection(
ports=[output_port, input_port],
time=connection_time,
name=f"{current_component.name}_to_{next_component.name}",
)
connections.append(connection)

# Update total time
total_time_value += connection_time.value
# TODO total_time.mean += connection_time.mean
# TODO total_time.min += connection_time.min
# TODO total_time.max += connection_time.max
# Assuming standard deviation is not simply additive

total_time = TimeMetrics(value=total_time_value)
# TODO implement full network timing analysis

top_level_ports = [components[0].ports[0], components[-1].ports[-1]]
# TODO best define top level ports

top_level_connection = Connection(ports=top_level_ports, time=total_time)
# Define abstract path. Note that this is not a physical connection, just that there is a connection path between the ports.
# TODO this may have to be redefined

connections += top_level_connection

# Create a new component that encapsulates this path
path_component = Component(
ports=[
components[0].ports[0],
components[-1].ports[-1],
], # Input of first, output of last
components=components,
connections=connections,
**kwargs,
)

return path_component
103 changes: 100 additions & 3 deletions piel/models/physical/electrical/cable.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
from typing import Optional, Literal

from typing import Optional, Literal, Callable
from piel.types.connectivity.physical import PhysicalConnection
from piel.types.connectivity.timing import TimeMetricsTypes
from ..geometry import calculate_cross_sectional_area_m2, awg_to_cross_sectional_area_m2
from ..thermal import heat_transfer_1d_W
from piel.types.materials import MaterialReferenceType
from piel.materials.thermal_conductivity.utils import get_thermal_conductivity_fit
from piel.types.electrical.cables import (
CoaxialCable,
CoaxialCableGeometryType,
CoaxialCableHeatTransferType,
CoaxialCableMaterialSpecificationType,
DCCableGeometryType,
DCCableHeatTransferType,
DCCableMaterialSpecificationType,
)
from piel.types.materials import MaterialReferenceType
from piel.types.physical import TemperatureRangeTypes
from piel.types import PhysicalPort
from piel.types import Connection


def calculate_coaxial_cable_geometry(
Expand Down Expand Up @@ -244,3 +248,96 @@ def calculate_dc_cable_heat_transfer(
return DCCableHeatTransferType(
**heat_transfer_parameters,
)


def create_coaxial_cable(
material_specification_function: Callable[
..., CoaxialCableMaterialSpecificationType
],
timing_function: Callable[..., TimeMetricsTypes],
geometry_function: Callable[
..., CoaxialCableGeometryType
] = calculate_coaxial_cable_geometry,
heat_transfer_function: Callable[
..., CoaxialCableHeatTransferType
] = calculate_coaxial_cable_heat_transfer,
parameters: dict = {},
**kwargs,
) -> CoaxialCable:
"""
Creates a complete model of a CoaxialCable with relevant geometrical, frequency, timing, and heat transfer descriptions.
This function operates on a collection of functions to create a comprehensive model of a `CoaxialCable`.
Each function is parametrized through a `parameters` dictionary common to all defined internal functions,
in order to compose each relevant model accordingly. This is decomposed internally within this method.
Parameters:
-----------
material_specification_function : Callable[..., CoaxialCableMaterialSpecificationType]
A function that returns the material specification for the coaxial cable.
This function should not take any arguments as it will be called without parameters.
timing_function : Callable[..., TimeMetricsTypes]
A function that calculates and returns the timing metrics for the coaxial cable.
This function will be called with the parameters from the `parameters` dict.
geometry_function : Callable[..., CoaxialCableGeometryType], optional
A function that calculates and returns the geometry specification for the coaxial cable.
Defaults to `calculate_coaxial_cable_geometry`.
This function will be called with the parameters from the `parameters` dict.
heat_transfer_function : Callable[..., CoaxialCableHeatTransferType], optional
A function that calculates and returns the heat transfer characteristics of the coaxial cable.
Defaults to `calculate_coaxial_cable_heat_transfer`.
This function will be called with the parameters from the `parameters` dict.
parameters : dict, optional
A dictionary of parameters to be passed to the geometry, timing, and heat transfer functions.
These parameters are used to customize the calculations for each aspect of the coaxial cable.
Defaults to an empty dictionary.
**kwargs :
Additional keyword arguments to be passed to the CoaxialCable constructor.
Returns:
--------
CoaxialCable
A fully specified CoaxialCable object with all relevant properties set.
Notes:
------
- The function creates a Connection object with "in" and "out" PhysicalPorts, using the calculated time metrics.
- A PhysicalConnection is created using the Connection object.
- The CoaxialCable is constructed using the results from all calculation functions and the created PhysicalConnection.
Example:
--------
>>> def material_spec():
... return CoaxialCableMaterialSpecification(...)
>>> def timing_calc(**params):
... return TimeMetrics(...)
>>> cable = create_coaxial_cable(
... material_specification_function=material_spec,
... timing_function=timing_calc,
... parameters={'length': 10, 'diameter': 0.5},
... name='My Coaxial Cable'
... )
"""
heat_transfer = heat_transfer_function(**parameters)
geometry = geometry_function(**parameters)
time_metrics = timing_function(**parameters)

connection = Connection(
ports=[PhysicalPort(name="in"), PhysicalPort(name="out")],
time=time_metrics,
)

physical_connection = PhysicalConnection(connections=[connection])

return CoaxialCable(
material_specification=material_specification_function(),
geometry=geometry,
heat_transfer=heat_transfer,
connections=[physical_connection],
**kwargs,
)
11 changes: 7 additions & 4 deletions piel/types/connectivity/timing.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Optional
from typing import Optional, Union
from piel.types.core import NumericalTypes
from piel.types.connectivity.core import Instance
from piel.types.units import Unit, s


class ScalarMetrics(Instance):
Expand All @@ -13,6 +14,7 @@ class ScalarMetrics(Instance):
min: Optional[NumericalTypes]
max: Optional[NumericalTypes]
standard_deviation: Optional[NumericalTypes]
unit: Unit


class TimeMetrics(ScalarMetrics):
Expand Down Expand Up @@ -47,6 +49,7 @@ class TimeMetrics(ScalarMetrics):
min: Optional[NumericalTypes] = 0
max: Optional[NumericalTypes] = 0
standard_deviation: Optional[NumericalTypes] = 0
unit: Unit = s


class DispersiveTimeMetrics(Instance):
Expand All @@ -57,11 +60,11 @@ class DispersiveTimeMetrics(Instance):

frequency_group: dict[float, TimeMetrics] = {}
"""
Definition of a mutli-frequency component.
"""
Definition of a mutli-frequency component.
"""


TimeMetricsTypes = TimeMetrics | DispersiveTimeMetrics
TimeMetricsTypes = Union[TimeMetrics, DispersiveTimeMetrics]
"""
Corresponds to all the implemented timing metrics accordingly.
"""
Expand Down
1 change: 1 addition & 0 deletions piel/types/electrical/cables.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,4 @@ class CoaxialCable(Cable):
CableMaterialSpecificationTypes = Union[
CoaxialCableMaterialSpecificationType, DCCableMaterialSpecificationType
]
CableTypes = Union[DCCable, CoaxialCable]

0 comments on commit 86eecee

Please sign in to comment.