Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export raw NumPy array capacitance matrix for ElectrostaticResults #208

Merged
merged 2 commits into from
Oct 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 42 additions & 20 deletions gplugins/common/base_models/simulation.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,40 @@
from __future__ import annotations

from collections.abc import Sequence
from functools import cached_property
from pathlib import Path
from typing import Any

from pydantic import BaseModel, ConfigDict
import numpy as np
from numpy.typing import NDArray
from pydantic import BaseModel, ConfigDict, computed_field

from ..types import CapacitanceDict
from ..types import CapacitanceDict, ScatteringDict


def _raw_matrix_from_dict(dict_matrix: CapacitanceDict | ScatteringDict) -> NDArray:
"""Converts dictionary formatted matrix results to a NumPy array.

Args:
dict_matrix: Dictionary with matrix results in ``(port_i, port_j): result`` configuration.

Returns:
ndarray: A matrix representation of the connections.
"""
n = int(np.sqrt(len(dict_matrix)))
matrix = np.zeros((n, n))

port_to_index_map = {}
for iname, jname in dict_matrix.keys():
if iname not in port_to_index_map:
port_to_index_map[iname] = len(port_to_index_map)
if jname not in port_to_index_map:
port_to_index_map[jname] = len(port_to_index_map)

for (iname, jname), c in dict_matrix.items():
matrix[port_to_index_map[iname], port_to_index_map[jname]] = c

return matrix


class ElectrostaticResults(BaseModel):
Expand All @@ -18,28 +46,22 @@ class ElectrostaticResults(BaseModel):
mesh_location: Path | None = None
field_file_location: Path | None = None

# @computed_field
# @cached_property
# def raw_capacitance_matrix(self) -> NDArray:
# n = int(np.sqrt(len(self.capacitance_matrix)))
# matrix = np.zeros((n, n))

# port_to_index_map = {}
# for iname, jname in self.capacitance_matrix.keys():
# if iname not in port_to_index_map:
# port_to_index_map[iname] = len(port_to_index_map) + 1
# if jname not in port_to_index_map:
# port_to_index_map[jname] = len(port_to_index_map) + 1

# for (iname, jname), c in self.capacitance_matrix.items():
# matrix[port_to_index_map[iname], port_to_index_map[jname]] = c

# return matrix
@computed_field
@cached_property
def raw_capacitance_matrix(self) -> NDArray:
"""Capacitance matrix as a NumPy array."""
return _raw_matrix_from_dict(self.capacitance_matrix)


class DrivenFullWaveResults(BaseModel):
"""Results class for driven full-wave simulations."""

scattering_matrix: Any # TODO convert to SDict or similar
scattering_matrix: Any # TODO convert dataframe to ScatteringDict
mesh_location: Path | None = None
field_file_locations: Sequence[Path] | None = None

# @computed_field
# @cached_property
# def raw_scattering_matrix(self) -> NDArray:
# """Scattering matrix as a NumPy array."""
# return _raw_matrix_from_dict(self.scattering_matrix)
1 change: 1 addition & 0 deletions gplugins/common/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

RFMaterialSpec = dict[str, dict[str, float | int]]
CapacitanceDict = dict[tuple[str, str], float]
ScatteringDict = dict[tuple[str, str], float]
AnyShapelyPolygon = Annotated[
GeometryCollection | MultiPolygon | Polygon,
PlainSerializer(lambda x: x.wkb_hex, when_used="json"),
Expand Down
36 changes: 23 additions & 13 deletions gplugins/elmer/tests/test_elmer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from gdsfactory.technology import LayerStack
from gdsfactory.technology.layer_stack import LayerLevel

from gplugins.common.base_models.simulation import ElectrostaticResults
from gplugins.elmer import run_capacitive_simulation_elmer

layer_stack = LayerStack(
Expand Down Expand Up @@ -35,7 +36,7 @@
}


@pytest.fixture
@pytest.fixture(scope="session")
@gf.cell
def geometry():
simulation_box = [[-200, -200], [200, 200]]
Expand Down Expand Up @@ -67,7 +68,7 @@ def get_reasonable_mesh_parameters(c: Component):
"resolution": 40,
},
**{
f"bw{port}": {
f"bw__{port}": {
"resolution": 20,
"DistMax": 30,
"DistMin": 10,
Expand All @@ -80,16 +81,24 @@ def get_reasonable_mesh_parameters(c: Component):
)


def test_elmer_capacitance_simulation_runs(geometry) -> None:
@pytest.fixture(scope="session")
def elmer_capacitance_simulation_basic_results(geometry) -> ElectrostaticResults:
"""Run a Elmer capacitance simulation and cache the results"""
c = geometry
run_capacitive_simulation_elmer(
return run_capacitive_simulation_elmer(
c,
layer_stack=layer_stack,
material_spec=material_spec,
mesh_parameters=get_reasonable_mesh_parameters(c),
)


def test_elmer_capacitance_simulation_runs(
elmer_capacitance_simulation_basic_results,
) -> None:
assert elmer_capacitance_simulation_basic_results is not None


@pytest.mark.parametrize("n_processes", [(1), (2)])
def test_elmer_capacitance_simulation_n_processes(geometry, n_processes):
c = geometry
Expand All @@ -114,21 +123,22 @@ def test_elmer_capacitance_simulation_element_order(geometry, element_order) ->
)


@pytest.mark.skip(reason="TODO")
def test_elmer_capacitance_simulation_mesh_size_field(geometry) -> None:
pass


@pytest.mark.skip(reason="TODO")
def test_elmer_capacitance_simulation_flip_chip(geometry) -> None:
pass


@pytest.mark.skip(reason="TODO")
def test_elmer_capacitance_simulation_pyvist_plot(geometry) -> None:
def test_elmer_capacitance_simulation_pyvista_plot(geometry) -> None:
pass


@pytest.mark.skip(reason="TODO")
def test_elmer_capacitance_simulation_cdict_form(geometry) -> None:
pass
def test_elmer_capacitance_simulation_raw_cap_matrix(
elmer_capacitance_simulation_basic_results,
) -> None:
matrix = elmer_capacitance_simulation_basic_results.raw_capacitance_matrix
assert matrix is not None
assert (
len(elmer_capacitance_simulation_basic_results.capacitance_matrix)
== matrix.size
)
Loading