import numpy as np
from ...solutions import BaseSolution
from .base import Action
[docs]class DCFieldsSolutions(BaseSolution):
"""Contains the result of a :class:`DCFields` action.
Attributes
----------
homs : list
The Hermite-Gaussian higher order mode indices at each node, of each frequency.
nodes : tuple[str]
Name of nodes the fields were extracted at
frequencies : array_like[dtype=float]
Values of the optical frequencies at each node
fields : array_like
Field data array with shape [nodes, frequencies, HOMs.shape[0]]
Notes
-----
The `fields` attribute will contain all the required information with its ordering
defined by the `nodes`, `frequencies`, and `homs` array. For easier indexing you can
access the solution directly with node names.
Select all the frequencies and modes at l1.p1.i:
>>> sol['l1.p1.i']
Select all the first modes at all frequencies and modes at l1.p1.i:
>>> sol['l1.p1.i', :, 0]
Select all the frequencies and modes at two nodes:
>>> sol[('l1.p1.i', 'l1.p1.o')]
Select all the HG02 modes at every node and frequency
>>> sol[:, :, sol.homes.index([0,2]))]
The frequency and mode selection must be a slice or an array of integer or boolean
values.
"""
homs = None
nodes = None
frequencies = None
fields = None
def __getitem__(self, key):
key = list(key)
if not isinstance(key[0], slice):
nodes = np.atleast_1d(key[0])
for i in nodes:
if i not in self.nodes:
raise KeyError(f"`{i}` is not in the solution nodes")
key[0] = tuple(self.nodes.index(i) for i in nodes)
return self.fields[tuple(key)]
[docs]class DCFields(Action):
"""An action that saves the DC (carrier) fields at all nodes, frequencies, and
higher order modes for the current state of the simulation.
Parameters
----------
name : str, optional
Name of the solution generated by this action
"""
def __init__(self, *, name="dcfields"):
super().__init__(name)
def _requests(self, model, memo, first=True):
pass
def _do(self, state):
sol = DCFieldsSolutions(self.name)
sol.homs = state.model.homs.tolist()
sol.nodes = tuple(state.sim.carrier.nodes.keys())
sol.frequencies = np.array(
[f.f for f in state.sim.carrier.optical_frequencies.frequencies]
)
sol.fields = np.reshape(
state.sim.carrier.M().rhs_view[0, :].copy(),
(len(sol.nodes), len(sol.frequencies), len(sol.homs)),
order="C",
)
# rescale into sqrt(W) units
sol.fields /= np.sqrt(2)
return sol