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

to_gmsh --> get_mesh #150

Merged
merged 2 commits into from
Sep 19, 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
5 changes: 3 additions & 2 deletions docs/notebooks/femwell_02_heater.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from gdsfactory.technology import LayerStack
from skfem.io import from_meshio

from gplugins.gmsh.mesh import create_physical_mesh
from gplugins.gmsh.mesh import create_physical_mesh, get_mesh

gf.config.rich_output()
PDK = get_generic_pdk()
Expand Down Expand Up @@ -46,7 +46,8 @@ def mesh_with_physicals(mesh, filename):

# -

mesh = heater.to_gmsh(
mesh = get_mesh(
component=heater,
type="uz",
xsection_bounds=[(4, -4), (4, 4)],
layer_stack=filtered_layerstack,
Expand Down
9 changes: 7 additions & 2 deletions docs/notebooks/meshing_01_intro.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
from gdsfactory.technology import LayerStack
from skfem.io import from_meshio

from gplugins.gmsh.get_mesh import get_mesh
from gplugins.gmsh.mesh import create_physical_mesh

gf.config.rich_output()
Expand Down Expand Up @@ -95,8 +96,12 @@ def mesh_with_physicals(mesh, filename):

# The various processing and meshing functions are located under `gplugins.gmsh` and can be called from there, but a shortcut is implemented to mesh directly from a component:

mesh = waveguide.to_gmsh(
type="xy", z=0.09, layer_stack=filtered_layerstack, filename="mesh.msh"
mesh = get_mesh(
component=waveguide,
type="xy",
z=0.09,
layer_stack=filtered_layerstack,
filename="mesh.msh",
)

# This returns a gmsh `.msh` mesh, also saved in `filename` if provided, which can be processed:
Expand Down
33 changes: 25 additions & 8 deletions docs/notebooks/meshing_02_2D_xy_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from gdsfactory.technology import LayerStack
from skfem.io import from_meshio

from gplugins.gmsh.get_mesh import get_mesh
from gplugins.gmsh.mesh import create_physical_mesh

gf.config.rich_output()
Expand Down Expand Up @@ -45,26 +46,38 @@ def mesh_with_physicals(mesh, filename):
# At `z=0.09` um, according to the layer stack above we should see polygons from all three layers:

filename = "mesh"
mesh = waveguide.to_gmsh(
type="xy", z=0.09, layer_stack=filtered_layerstack, filename=f"{filename}.msh"
mesh = get_mesh(
component=waveguide,
type="xy",
z=0.09,
layer_stack=filtered_layerstack,
filename=f"{filename}.msh",
)
mesh = mesh_with_physicals(mesh, filename)
mesh = from_meshio(mesh)
mesh.draw().plot()

# At `z=0`, you can see only the core and slab:

mesh = waveguide.to_gmsh(
type="xy", z=0.0, layer_stack=filtered_layerstack, filename=f"{filename}.msh"
mesh = get_mesh(
component=waveguide,
type="xy",
z=0.0,
layer_stack=filtered_layerstack,
filename=f"{filename}.msh",
)
mesh = mesh_with_physicals(mesh, filename)
mesh = from_meshio(mesh)
mesh.draw().plot()

# At `z=1.0`, you can only see the vias appear:

mesh = waveguide.to_gmsh(
type="xy", z=1.0, layer_stack=filtered_layerstack, filename=f"{filename}.msh"
mesh = get_mesh(
component=waveguide,
type="xy",
z=1.0,
layer_stack=filtered_layerstack,
filename=f"{filename}.msh",
)
mesh = mesh_with_physicals(mesh, filename)
mesh = from_meshio(mesh)
Expand All @@ -86,8 +99,12 @@ def mesh_with_physicals(mesh, filename):
waveguide_trimmed
# -

mesh = waveguide_trimmed.to_gmsh(
type="xy", z=0.09, layer_stack=filtered_layerstack, filename=f"{filename}.msh"
mesh = get_mesh(
component=waveguide_trimmed,
type="xy",
z=0.09,
layer_stack=filtered_layerstack,
filename=f"{filename}.msh",
)
mesh = mesh_with_physicals(mesh, filename)
mesh = from_meshio(mesh)
Expand Down
7 changes: 5 additions & 2 deletions docs/notebooks/meshing_03_2D_uz_mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from gdsfactory.technology import LayerStack
from skfem.io import from_meshio

from gplugins.gmsh.get_mesh import get_mesh
from gplugins.gmsh.mesh import create_physical_mesh

gf.config.rich_output()
Expand Down Expand Up @@ -52,7 +53,8 @@ def mesh_with_physicals(mesh, filename):

# Choosing the line going from `y=-4` to `y=4` at `x=4`, which crosses slab, via, and core:

mesh = waveguide_trimmed.to_gmsh(
mesh = get_mesh(
component=waveguide_trimmed,
type="uz",
xsection_bounds=[(4, -4), (4, 4)],
layer_stack=filtered_layerstack,
Expand All @@ -68,7 +70,8 @@ def mesh_with_physicals(mesh, filename):
#
# You can add a convenience argument to add a background mesh around the geometry (instead of defining a dummy polygon and layer in the layerstack with low mesh_order):

mesh = waveguide_trimmed.to_gmsh(
mesh = get_mesh(
component=waveguide_trimmed,
type="uz",
xsection_bounds=[(4, -4), (4, 4)],
layer_stack=filtered_layerstack,
Expand Down
19 changes: 13 additions & 6 deletions docs/notebooks/meshing_04_refinement.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from gdsfactory.technology import LayerStack
from skfem.io import from_meshio

from gplugins.gmsh.get_mesh import get_mesh
from gplugins.gmsh.mesh import create_physical_mesh

PDK = get_generic_pdk()
Expand Down Expand Up @@ -60,7 +61,8 @@ def mesh_with_physicals(mesh, filename):
# With `default_resolution_max` set to 1 um and `default_resolution_min` set to 100 nm:

# +
mesh = waveguide_trimmed.to_gmsh(
mesh = get_mesh(
component=waveguide_trimmed,
type="uz",
xsection_bounds=[(4, -4), (4, 4)],
layer_stack=filtered_layerstack,
Expand All @@ -78,7 +80,8 @@ def mesh_with_physicals(mesh, filename):

# With `default_resolution_max` set to 300 nm and `default_resolution_max` set to 50 nm:

mesh = waveguide_trimmed.to_gmsh(
mesh = get_mesh(
component=waveguide_trimmed,
type="uz",
xsection_bounds=[(4, -4), (4, 4)],
layer_stack=filtered_layerstack,
Expand All @@ -101,7 +104,8 @@ def mesh_with_physicals(mesh, filename):
# For example, to refine within the core only, one could use:

resolutions = {"core": {"resolution": 0.05, "distance": 0}}
mesh = waveguide_trimmed.to_gmsh(
mesh = get_mesh(
component=waveguide_trimmed,
type="uz",
xsection_bounds=[(4, -4), (4, 4)],
layer_stack=filtered_layerstack,
Expand All @@ -117,7 +121,8 @@ def mesh_with_physicals(mesh, filename):
# Adding a dropoff at the interface:

resolutions = {"core": {"resolution": 0.05, "distance": 5}}
mesh = waveguide_trimmed.to_gmsh(
mesh = get_mesh(
component=waveguide_trimmed,
type="uz",
xsection_bounds=[(4, -4), (4, 4)],
layer_stack=filtered_layerstack,
Expand All @@ -138,7 +143,8 @@ def mesh_with_physicals(mesh, filename):
"via_contact": {"resolution": 0.2, "distance": 0},
"oxide": {"resolution": 1, "distance": 0},
}
mesh = waveguide_trimmed.to_gmsh(
mesh = get_mesh(
component=waveguide_trimmed,
type="uz",
xsection_bounds=[(4, -4), (4, 4)],
layer_stack=filtered_layerstack,
Expand Down Expand Up @@ -178,7 +184,8 @@ def mesh_with_physicals(mesh, filename):

global_meshsize_array = np.array(global_meshsize_array)

mesh = waveguide_trimmed.to_gmsh(
mesh = get_mesh(
component=waveguide_trimmed,
type="uz",
xsection_bounds=[(4, -4), (4, 4)],
layer_stack=filtered_layerstack,
Expand Down
7 changes: 5 additions & 2 deletions docs/notebooks/meshing_05_3D.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from gdsfactory.technology import LayerStack
from skfem.io import from_meshio

from gplugins.gmsh.get_mesh import get_mesh
from gplugins.gmsh.mesh import create_physical_mesh

PDK = get_generic_pdk()
Expand Down Expand Up @@ -49,7 +50,8 @@ def mesh_with_physicals(mesh, filename):

# -

mesh = waveguide.to_gmsh(
mesh = get_mesh(
component=waveguide,
type="3D",
layer_stack=filtered_layerstack,
filename=f"{filename}.msh",
Expand Down Expand Up @@ -80,7 +82,8 @@ def mesh_with_physicals(mesh, filename):
print(waveguide.ports["top_e1"])
print(waveguide.ports["bot_e1"])

mesh = waveguide.to_gmsh(
mesh = get_mesh(
component=waveguide,
type="3D",
layer_stack=filtered_layerstack,
filename=f"{filename}.msh",
Expand Down
6 changes: 4 additions & 2 deletions gplugins/elmer/get_capacitance.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from numpy import isfinite
from pandas import read_csv


from gplugins.common.base_models.simulation import ElectrostaticResults
from gplugins.common.types import RFMaterialSpec
from gplugins.common.utils.async_helpers import (
Expand Down Expand Up @@ -190,7 +191,7 @@ def run_capacitive_simulation_elmer(
Default is a temporary directory.
simulator_params: Elmer-specific parameters. See template file for more details.
mesh_parameters:
Keyword arguments to provide to :func:`~Component.to_gmsh`.
Keyword arguments to provide to :func:`get_mesh`.
mesh_file: Path to a ready mesh to use. Useful for reusing one mesh file.
By default a mesh is generated according to ``mesh_parameters``.

Expand Down Expand Up @@ -223,7 +224,8 @@ def run_capacitive_simulation_elmer(
if mesh_file:
shutil.copyfile(str(mesh_file), str(simulation_folder / filename))
else:
component.to_gmsh(
get_mesh(
component=component,
type="3D",
filename=simulation_folder / filename,
layer_stack=layer_stack,
Expand Down
5 changes: 4 additions & 1 deletion gplugins/femwell/mode_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
Mesh,
)

from gplugins.gmsh.get_mesh import get_mesh

mesh_filename = "mesh.msh"


Expand Down Expand Up @@ -127,7 +129,8 @@ def compute_component_slice_modes(
"""

# Mesh
mesh = component.to_gmsh(
mesh = get_mesh(
component=component,
type="uz",
xsection_bounds=xsection_bounds,
layer_stack=layerstack,
Expand Down
6 changes: 5 additions & 1 deletion gplugins/femwell/solve_thermal.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ def get_thermal_conductivities(basis):
from gdsfactory.generic_tech import LAYER_STACK
from skfem import Mesh

from gplugins.gmsh.get_mesh import get_mesh

LAYER_STACK.layers["heater"].thickness = 0.13
LAYER_STACK.layers["heater"].zmin = 2.2
heater_len = 1 # 1 um, so normalized
Expand All @@ -83,7 +85,9 @@ def get_thermal_conductivities(basis):

# ====== MESH =====
filtered_layerstack = LAYER_STACK
filtered_layerstack.get_component_with_derived_layers(heater).to_gmsh(
heater_derived = filtered_layerstack.get_component_with_derived_layers(heater)
get_mesh(
component=heater_derived,
type="uz",
xsection_bounds=[(3, c.bbox[0, 1]), (3, c.bbox[1, 1])],
# xsection_bounds=[(3, -4), (3, 4)],
Expand Down
78 changes: 78 additions & 0 deletions gplugins/gmsh/get_mesh.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import importlib.util

from gdsfactory import Component
from gdsfactory.typings import ComponentSpec, Layer, LayerStack

from gplugins.gmsh.uz_xsection_mesh import uz_xsection_mesh
from gplugins.gmsh.xy_xsection_mesh import xy_xsection_mesh
from gplugins.gmsh.xyz_mesh import xyz_mesh


def get_mesh(
component: ComponentSpec,
type: str,
layer_stack: LayerStack,
z: float | None = None,
xsection_bounds=None,
wafer_padding: float = 0.0,
wafer_layer: Layer = (99999, 0),
**kwargs,
):
"""Returns a gmsh mesh of the component for finite element simulation.

Arguments:
component: component
type: one of "xy", "uz", or "3D". Determines the type of mesh to return.
layer_stack: LayerStack object containing layer information.
z: used to define z-slice for xy meshing.
xsection_bounds: used to define in-plane line for uz meshing.
wafer_padding: padding beyond bbox to add to WAFER layers.
wafer_layer: layer to use for WAFER padding.

Keyword Args:
Arguments for the target meshing function in gplugins.gmsh


TODO! make compatible with new unified plugins interface
"""

# Add WAFER layer:
padded_component = Component()
padded_component << component
(xmin, ymin), (xmax, ymax) = component.bbox
points = [
[xmin - wafer_padding, ymin - wafer_padding],
[xmax + wafer_padding, ymin - wafer_padding],
[xmax + wafer_padding, ymax + wafer_padding],
[xmin - wafer_padding, ymax + wafer_padding],
]
padded_component.add_polygon(points, layer=wafer_layer)
padded_component.add_ports(component.get_ports_list())

if type == "xy":
if z is None:
raise ValueError(
'For xy-meshing, a z-value must be provided via the float argument "z".'
)

return xy_xsection_mesh(padded_component, z, layer_stack, **kwargs)
elif type == "uz":
if xsection_bounds is None:
raise ValueError(
"For uz-meshing, you must provide a line in the xy-plane "
"via the Tuple argument [[x1,y1], [x2,y2]] xsection_bounds."
)

return uz_xsection_mesh(
padded_component, xsection_bounds, layer_stack, **kwargs
)
elif type == "3D":
spec = importlib.util.find_spec("meshwell")
if spec is None:
print(
"3D meshing requires meshwell, see https://github.com/simbilod/meshwell or run pip install meshwell."
)

return xyz_mesh(padded_component, layer_stack, **kwargs)
else:
raise ValueError('Required argument "type" must be one of "xy", "uz", or "3D".')
6 changes: 4 additions & 2 deletions gplugins/gmsh/parse_gds.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ def tile_shapes(shapes_dict):
if __name__ == "__main__":
from gdsfactory.generic_tech import LAYER_STACK

from gplugins.gmsh.get_mesh import get_mesh

c = gf.components.straight_heater_doped_rib()
c.to_gmsh(type="xy", layer_stack=LAYER_STACK, z=0)
c.to_gmsh(type="xy", layer_stack=LAYER_STACK, z=0)
get_mesh(component=c, type="xy", layer_stack=LAYER_STACK, z=0)
get_mesh(component=c, type="xy", layer_stack=LAYER_STACK, z=0)
Loading