-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
1,001 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Book settings | ||
# Learn more at https://jupyterbook.org/customize/config.html | ||
|
||
title: My sample book | ||
author: The Jupyter Book Community | ||
logo: logo.png | ||
|
||
# Force re-execution of notebooks on each build. | ||
# See https://jupyterbook.org/content/execute.html | ||
execute: | ||
execute_notebooks: force | ||
exclude_patterns: | ||
- 'gdsfactory_interface' | ||
|
||
# Define the name of the latex output file for PDF builds | ||
latex: | ||
latex_documents: | ||
targetname: book.tex | ||
|
||
# Add a bibtex file so that we can create citations | ||
bibtex_bibfiles: | ||
- references.bib | ||
|
||
# Information about where the book exists on the web | ||
repository: | ||
url: https://github.com/executablebooks/jupyter-book # Online location of your book | ||
path_to_book: docs # Optional path to your book, relative to the repository root | ||
branch: master # Which branch of the repository should be used when creating links (optional) | ||
|
||
# Add GitHub buttons to your book | ||
# See https://jupyterbook.org/customize/config.html#add-a-link-to-your-repository | ||
html: | ||
use_issues_button: true | ||
use_repository_button: true | ||
|
||
sphinx: | ||
config: | ||
html_js_files: | ||
- https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js | ||
mime_types: | ||
application/vnd.plotly.v1+json: plotly |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Table of contents | ||
# Learn more at https://jupyterbook.org/customize/toc.html | ||
|
||
format: jb-book | ||
root: intro | ||
chapters: | ||
- file: intro_gmsh | ||
- file: polysurfaces | ||
- file: prisms | ||
- file: models | ||
- file: resolution | ||
- file: gdsfactory_interface |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# %% [markdown] | ||
# # GDSFactory integration | ||
# GDSFactory has an interface to meshwell (v1.0.7) | ||
|
||
# %% [markdown] | ||
# > **Warning** | ||
# > The GDSFactory plugin for meshwell/gmsh has not been updated since meshwell version 1.0.7! Some features may be missing, and some more bugs might be present. | ||
# | ||
# %%[markdown] | ||
# GDSFactory has the concept of a "LayerStack", which contains the information about the final fabricated layers: | ||
|
||
# %% | ||
import gmsh | ||
import gdsfactory as gf | ||
from gplugins.gmsh.get_mesh import get_mesh | ||
from gdsfactory.generic_tech.layer_stack import get_layer_stack | ||
|
||
PDK = gf.generic_tech.get_generic_pdk() | ||
PDK.bend_points_distance = 0.5 | ||
|
||
LAYER_STACK = get_layer_stack() | ||
LAYER_STACK.pprint() | ||
|
||
|
||
# %% | ||
|
||
c = gf.components.spiral_heater.spiral_racetrack_heater_metal(num=3) | ||
c.plot() | ||
|
||
# %% [markdown] | ||
# In meshwell 1.0.7, only a ThresholdField as a distance from the surfaces/volumes was supported. From the GDSFactory plugin, this is entered as a dict for the LayerLevels: | ||
# %% | ||
resolutions = {} | ||
resolutions["core"] = {"resolution": 0.1, "distance": 5} | ||
resolutions["heater"] = {"resolution": 0.2, "distance": 10} | ||
# %% [markdown] | ||
# the "type" argument in get_mesh can be "xy", "uz", or "3D", depending on if a 2D in-plane, 2D out-of-plane cross-section, or 3D mesh si desired: | ||
|
||
# %% | ||
xbound = (c.dxmin + c.dxmax) / 2 | ||
ymax = c.dymin | ||
ymin = (c.dymin + c.dymax) / 2 | ||
|
||
mesh = get_mesh( | ||
c, | ||
type="uz", | ||
xsection_bounds=[[xbound, ymin], [xbound, ymax]], | ||
layer_stack=LAYER_STACK, | ||
filename="heater_uz.msh", | ||
resolutions=resolutions, | ||
default_characteristic_length=10, | ||
wafer_padding=50, | ||
interface_delimiter="___", | ||
) | ||
|
||
# %% | ||
try: | ||
gmsh.initialize() | ||
gmsh.open("heater_uz.msh") | ||
gmsh.fltk.run() | ||
except: # noqa: E722 | ||
print("Skipping CAD GUI visualization - only available when running locally") | ||
|
||
# %% | ||
resolutions = {} | ||
resolutions["core"] = {"resolution": 0.5, "distance": 10} | ||
resolutions["heater"] = {"resolution": 5, "distance": 10} | ||
|
||
mesh = get_mesh( | ||
c, | ||
type="3D", | ||
layer_stack=LAYER_STACK, | ||
filename="heater_3D.msh", | ||
resolutions=resolutions, | ||
default_characteristic_length=20, | ||
wafer_padding=50, | ||
interface_delimiter="___", | ||
) | ||
|
||
# %% | ||
try: | ||
gmsh.initialize() | ||
gmsh.open("heater_3D.msh") | ||
gmsh.fltk.run() | ||
except: # noqa: E722 | ||
print("Skipping CAD GUI visualization - only available when running locally") | ||
# %% |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
# %% [markdown] | ||
# # GMSH | ||
# Since meshwell is a wrapper around GMSH, we will first review GMSH Python API. For a more thorough explanation of the below, see the GMSH documentation (https://gmsh.info/doc/texinfo/gmsh.html), tutorials (https://gitlab.onelab.info/gmsh/gmsh/-/tree/master/tutorials/python) and API (https://gitlab.onelab.info/gmsh/gmsh/-/blob/master/api/gmsh.py?ref_type=heads). | ||
|
||
# %% | ||
import gmsh | ||
import meshio | ||
from meshwell.visualization import plot2D | ||
|
||
# %% [markdown] | ||
# ## Bottom-up construction of CAD entities | ||
# The most general way to create CAD entities in GMSH is "bottom-up", going from points --> lines --> closed loops --> surfaces --> closed shells --> volumes | ||
|
||
# %% | ||
# Initialize GMSH | ||
gmsh.initialize() | ||
model = gmsh.model | ||
model.add("bottom_up") | ||
|
||
# Create points | ||
p1 = model.occ.addPoint(0, 0, 0) | ||
p2 = model.occ.addPoint(2, 0, 0) | ||
p3 = model.occ.addPoint(2, 1, 0) | ||
p4 = model.occ.addPoint(1, 1, 0) | ||
p5 = model.occ.addPoint(1, 2, 0) | ||
p6 = model.occ.addPoint(0, 2, 0) | ||
|
||
# Create lines | ||
l1 = model.occ.addLine(p1, p2) | ||
l2 = model.occ.addLine(p2, p3) | ||
l3 = model.occ.addLine(p3, p4) | ||
l4 = model.occ.addLine(p4, p5) | ||
l5 = model.occ.addLine(p5, p6) | ||
l6 = model.occ.addLine(p6, p1) | ||
|
||
# Create curve loop | ||
cl = model.occ.addCurveLoop([l1, l2, l3, l4, l5, l6]) | ||
|
||
# Create surface | ||
s1 = model.occ.addPlaneSurface([cl]) | ||
|
||
# Create the mesh | ||
model.occ.synchronize() | ||
model.mesh.generate(2) | ||
|
||
gmsh.write("bottom_up.xao") | ||
gmsh.write("bottom_up.msh") | ||
gmsh.finalize() | ||
|
||
# Read the mesh | ||
mesh = meshio.read("bottom_up.msh") | ||
|
||
# %% | ||
try: | ||
gmsh.initialize() | ||
gmsh.open("bottom_up.xao") | ||
gmsh.fltk.run() | ||
except: # noqa: E722 | ||
print("Skipping CAD GUI visualization - only available when running locally") | ||
|
||
# %% | ||
try: | ||
gmsh.initialize() | ||
gmsh.open("bottom_up.msh") | ||
gmsh.fltk.run() | ||
except: # noqa: E722 | ||
print("Skipping mesh GUI visualization - only available when running locally") | ||
|
||
# %% | ||
plot2D(mesh, wireframe=True) | ||
|
||
# %% [markdown] | ||
# ## Construction of CAD entities from primitives | ||
# A limited set of primitives (rectangles, circles, arcs, spheres, boxes, etc.) are also already implemented in GMSH: | ||
# %% | ||
gmsh.initialize() | ||
model = gmsh.model | ||
model.add("bottom_up") | ||
|
||
# Create rectangle | ||
box = model.occ.addRectangle(0, 0, 0, 1, 1) | ||
|
||
# Create circle | ||
circle = model.occ.addDisk(3, 0, 0, 0.5, 0.5) | ||
|
||
# Create the mesh | ||
model.occ.synchronize() | ||
model.mesh.generate(2) | ||
gmsh.write("primitives.msh") | ||
gmsh.finalize() | ||
|
||
# %% | ||
mesh = meshio.read("primitives.msh") | ||
plot2D(mesh, wireframe=True) | ||
|
||
# %% [markdown] | ||
# ## Constructive geometry operations | ||
# More complex elementary entities can also be created from constructive geometry operations (cut, fuse, intersect): | ||
|
||
# %% | ||
gmsh.initialize() | ||
model = gmsh.model | ||
model.add("bottom_up") | ||
|
||
# Create rectangle | ||
box = model.occ.addRectangle(-1, -1, 0, 2, 2) | ||
|
||
# Create circle | ||
circle = model.occ.addDisk(0, 0, 0, 0.5, 0.5) | ||
|
||
# Keep difference, delete originals | ||
difference = model.occ.cut( | ||
[(2, box)], [(2, circle)], removeObject=True, removeTool=True | ||
) | ||
|
||
# Create the mesh | ||
model.occ.synchronize() | ||
model.mesh.generate(2) | ||
gmsh.write("booleans.msh") | ||
gmsh.finalize() | ||
|
||
# %% | ||
mesh = meshio.read("booleans.msh") | ||
plot2D(mesh, wireframe=True) | ||
|
||
# %% [markdown] | ||
# ## Physical entities | ||
# It is almost always extremely useful to be able to refer to all of the mesh nodes within a set of elementary entities. In GMSH, this is achieved by assigning a "physical" group to a set of elementary entities: | ||
|
||
# %% | ||
gmsh.initialize() | ||
model = gmsh.model | ||
model.add("physicals") | ||
|
||
# Create rectangle | ||
box1 = model.occ.addRectangle(0, 0, 0, 1, 1) | ||
box2 = model.occ.addRectangle(-2, -2, 0, 1, 1) | ||
|
||
# Create circle | ||
circle1 = model.occ.addDisk(3, 0, 0, 0.5, 0.5) | ||
circle2 = model.occ.addDisk(2, -2, 0, 0.5, 0.5) | ||
|
||
model.occ.synchronize() | ||
|
||
# Create physical groups | ||
model.addPhysicalGroup(2, [box1, box2], tag=1, name="boxes") | ||
model.addPhysicalGroup(2, [circle1, circle2], tag=2, name="circles") | ||
|
||
# Create the mesh | ||
model.occ.synchronize() | ||
model.mesh.generate(2) | ||
gmsh.write("physicals.msh") | ||
gmsh.finalize() | ||
|
||
# %% | ||
mesh = meshio.read("physicals.msh") | ||
plot2D(mesh) | ||
|
||
# %% [markdown] | ||
# ## The sharp bits | ||
# | ||
# ### Conflicting entities | ||
# When adding elementary entities, overlaps and interfaces are not "merged" by default: the entities will overlap and will be meshed separately. The resulting sub-meshes will not be connected. | ||
# | ||
# | ||
|
||
# %% [markdown] | ||
# ### Keeping track of integers | ||
# Whenever entities are created / transformed (e.g. when healing interfaces), there can be reassignment of the integer tags used to label them. In the official tutorials, entity tags are re-identified based on some characteristic like bounding extent to later assign to physical groups. |
Oops, something went wrong.