diff --git a/.github/workflows/ci_cd_pr.yml b/.github/workflows/ci_cd_pr.yml index 4477a90..59e0fae 100644 --- a/.github/workflows/ci_cd_pr.yml +++ b/.github/workflows/ci_cd_pr.yml @@ -133,6 +133,7 @@ jobs: skip-install: true python-version: ${{ env.MAIN_PYTHON_VERSION }} use-python-cache: false + dependencies: "pandoc" needs-quarto: true doc-deploy-pr: diff --git a/doc/source/changelog/19.maintenance.md b/doc/source/changelog/19.maintenance.md new file mode 100644 index 0000000..261e849 --- /dev/null +++ b/doc/source/changelog/19.maintenance.md @@ -0,0 +1 @@ +Add pandoc to dependencies for doc build diff --git a/doc/source/conf.py b/doc/source/conf.py index f1f1508..c76a9c8 100755 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -2,6 +2,8 @@ from datetime import datetime import os +import pathlib +import shutil from ansys_sphinx_theme import get_version_match @@ -49,6 +51,7 @@ "sphinx_copybutton", "sphinx_design", # Needed for cards "sphinx.ext.extlinks", + "nbsphinx", ] # Intersphinx mapping @@ -90,6 +93,10 @@ copybutton_prompt_text = r">>> ?|\.\.\. ?" copybutton_prompt_is_regexp = True +# Ignore files for build + +exclude_patterns = ["conf.py", "examples/README.rst"] + # Skipping members def autodoc_skip_member_custom(app, what, name, obj, skip, options): @@ -97,7 +104,64 @@ def autodoc_skip_member_custom(app, what, name, obj, skip, options): return True if obj.__doc__ is None else None # need to return none if exclude is false otherwise it will interfere with other skip functions -# RST prolog for substitution of custom variables +# nbpsphinx configurations + +nbsphinx_execute = "never" + +nbsphinx_custom_formats = {".py": ["jupytext.reads", {"fmt": ""}]} + +nbsphinx_prolog = """ + + +.. grid:: 1 2 2 2 + + .. grid-item:: + + .. button-link:: {base_path}/{ipynb_file_path} + :color: secondary + :shadow: + :align: center + + :octicon:`download` Download Jupyter Notebook (.ipynb) + + + .. grid-item:: + + .. button-link:: {base_path}/{py_file_path} + :color: secondary + :shadow: + :align: center + + :octicon:`download` Download Python script (.py) + +---- +""".format( + base_path=f"https://{cname}/version/{get_version_match(version)}", py_file_path="{{ env.docname }}.py", ipynb_file_path="{{ env.docname }}.ipynb" +) + +# Define auxiliary functions needed for examples + + +def copy_examples_to_source_dir(app): + """Copy examples to source directory for nbsphinx.""" + source_dir = pathlib.Path(app.srcdir) + + shutil.copytree(source_dir.parent.parent / "examples", source_dir / "examples", dirs_exist_ok=True) + + +def remove_examples_from_source_dir(app, exception): + """Remove examples from source directory after build.""" + source_dir = pathlib.Path(app.srcdir) + shutil.rmtree(source_dir / "examples") + + +def copy_examples_to_output_dir(app, exception): + """Copy examples to output directory.""" + source_dir = pathlib.Path(app.srcdir) + build_dir = pathlib.Path(app.outdir) + + shutil.copytree(source_dir.parent.parent / "examples", build_dir / "examples", dirs_exist_ok=True) + rst_prolog = "" @@ -133,6 +197,12 @@ def autodoc_skip_member_custom(app, what, name, obj, skip, options): extlinks = {"examples_url": (f"{html_theme_options['github_url']}/blob/main/examples/%s", "%s")} +# Define setup function + + def setup(app): """Sphinx setup function.""" + app.connect("builder-inited", copy_examples_to_source_dir) app.connect("autodoc-skip-member", autodoc_skip_member_custom) + app.connect("build-finished", remove_examples_from_source_dir) + app.connect("build-finished", copy_examples_to_output_dir) diff --git a/doc/source/examples.rst b/doc/source/examples.rst index 9051469..5fc282e 100644 --- a/doc/source/examples.rst +++ b/doc/source/examples.rst @@ -5,24 +5,41 @@ You can use the examples below to get started with PyLumerical and learn its bas For in-depth discussion of PyLumerical concepts, see the :doc:`User guide `. -.. grid:: 2 2 3 3 +.. grid:: 2 2 4 4 .. grid-item-card:: Session management + :link: examples/Sessions_and_Objects/basic_session_management + :link-type: doc This example demonstrates how to initialize a local Lumerical session using PyLumerical. - Download the example :examples_url:`here `. - .. grid-item-card:: Basic FDTD simulation - Lumerical style commands + :link: examples/Sessions_and_Objects/fdtd_example1_lsf + :link-type: doc This example demonstrates how to set up a basic FDTD simulation with a Gaussian source and frequency-domain monitor. The example uses PyLumerical with workflows and syntax similar to the Lumerical Scripting Language. - Download the example :examples_url:`here `. .. grid-item-card:: Basic FDTD simulation - Python style commands + :link: examples/Sessions_and_Objects/fdtd_example1_pythonic + :link-type: doc This example demonstrates how to set up a basic FDTD simulation with a Gaussian source and frequency-domain monitor. This example uses PyLumerical with workflows and syntax that is more native to Python. - Download the example :examples_url:`here `. \ No newline at end of file + .. grid-item-card:: FDE MODE Simulation + :link: examples/Sessions_and_Objects/waveguide_FDE + :link-type: doc + + This example demonstrates how to set up a basic simulation with Ansys Lumerical MODEā„¢ using the FDE solver. + + + +.. toctree:: + :hidden: + + examples/Sessions_and_Objects/basic_session_management + examples/Sessions_and_Objects/fdtd_example1_lsf + examples/Sessions_and_Objects/fdtd_example1_pythonic + examples/Sessions_and_Objects/waveguide_FDE \ No newline at end of file diff --git a/doc/styles/config/vocabularies/ANSYS/accept.txt b/doc/styles/config/vocabularies/ANSYS/accept.txt index f591ced..9e947a2 100644 --- a/doc/styles/config/vocabularies/ANSYS/accept.txt +++ b/doc/styles/config/vocabularies/ANSYS/accept.txt @@ -29,4 +29,5 @@ photonic photonics lumopt lumslurm -[Aa]utodiscovery +[Jj]upytext +[Aa]utodiscovery \ No newline at end of file diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index df635b4..0000000 --- a/examples/README.md +++ /dev/null @@ -1 +0,0 @@ -# Examples diff --git a/examples/README.rst b/examples/README.rst new file mode 100644 index 0000000..b7ecf88 --- /dev/null +++ b/examples/README.rst @@ -0,0 +1,17 @@ +Examples +======== + +Examples source files for PyLumerical are .py files. The PyLumerical documentation infrastructure converts these .py source files into .rst files for display on the documentation site, by first converting them into Jupyter Notebooks using `Jupytext `_, and then converting the notebooks into .rst files using `nbsphinx `_. + +Formatting +---------- + +Example files must be compliant with `PEP8 `_ guidelines, as listed on the PyAnsys Developer's `guide `_. + +PyLumerical examples uses the "Light" format for jupytext conversion. To write comment cells into your source file, follow the formatting guidelines listed in the `Jupytext documentation `_. + +Always ensure that your example files run without errors, and are properly formatted prior to submitting a pull request. + +The documentation build process currently not automatically execute the examples, as such, no outputs are displayed in the resulting documentation pages. + +You can test your examples locally by running them as scripts, and you can test that the documentation formatting is correct by locally building the documentation. See the `contributing section <../doc/source/contributing.rst>`_ for more information. diff --git a/examples/Sessions_and_Objects/basic_session_management.py b/examples/Sessions_and_Objects/basic_session_management.py deleted file mode 100644 index 8384e9f..0000000 --- a/examples/Sessions_and_Objects/basic_session_management.py +++ /dev/null @@ -1,72 +0,0 @@ -""" - -Basic session management. - ------------------------- -This example demonstrates how to initialize a local Lumerical session. -PyLumerical interacts with Lumerical products through sessions. - -Prerequisites: Valid FDTD and MODE licenses are required. -""" - -############################################################################### -# -# Perform required imports -# ~~~~~~~~~~~~~~~~~~~~~~~~ - -import ansys.lumerical.core as lumapi - -############################################################################### -# -# Open an interactive session -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -fdtd = lumapi.FDTD() -# Wait for a second, then add FDTD region -fdtd.pause(1) -fdtd.addfdtd() -fdtd.print("Example complete. Press space bar to close.") -fdtd.pause(30) # Will close in 30 seconds if left idle -fdtd.close() - -mode = lumapi.MODE() -mode.print("Example complete. Press space bar to close.") -mode.pause(30) -mode.close() - -# Load a session but hide the application window -fdtd = lumapi.FDTD(hide=True) -fdtd.close() - -############################################################################### -# -# Use the "with" context manager -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -with lumapi.FDTD() as fdtd: - fdtd.addfdtd() - fdtd.print("Example complete. Press space bar to close.") - fdtd.pause(30) -# FDTD closes automatically - -############################################################################### -# -# Session wrapped in a function -# Get the number of grid cells in FDTD region for set span -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -def get_x_cells(fdtd_span): - """Return the number of grid cells in FDTD region for a set span.""" - with lumapi.FDTD() as fdtd: - # Adds FDTD region with span set by fdtd_span - fdtd.addfdtd(dimension="3D", x_span=fdtd_span, y_span=fdtd_span, z_span=fdtd_span) - # Get the x-coordinates of created FDTD region - x = fdtd.getresult("FDTD", "x") - x_cells = len(x) - return x_cells - - -# Test the function and print out the result -test = get_x_cells(1e-6) -print(test) diff --git a/examples/Sessions_and_Objects/example1_session_management.py b/examples/Sessions_and_Objects/example1_session_management.py new file mode 100644 index 0000000..ce2dcad --- /dev/null +++ b/examples/Sessions_and_Objects/example1_session_management.py @@ -0,0 +1,137 @@ +# %% [markdown] +# ## Basic FDTD Simulation - Lumerical style commands +# +# This simple example demonstrates using PyLumerical to start a session using Lumerical Script File (lsf) style commands. +# Sets up and runs a basic FDTD simulation. E field results are plotted in Lumerical. +# [Lumerical API](https://optics.ansys.com/hc/en-us/articles/360037824513-Python-API-overview) +# +# +# ## Prerequisites: +# +# Valid FDTD license is required. +# + +# %% +import ansys.lumerical.core as lumapi + + +# Set hide = True to hide the Lumerical GUI. +fdtd = lumapi.FDTD(hide=False) + +# - + +# +# ### Set up simulation region + +fdtd.addfdtd() +fdtd.set("x", 0) +fdtd.set("x span", 8e-6) +fdtd.set("y", 0) +fdtd.set("y span", 8e-6) +fdtd.set("z", 0.25e-6) +fdtd.set("z span", 0.5e-6) + +# ### Set up source + +fdtd.addgaussian() +fdtd.set("injection axis", "z") +fdtd.set("direction", "forward") +fdtd.set("x", 0) +fdtd.set("x span", 16e-6) +fdtd.set("y", 0) +fdtd.set("y span", 16e-6) +fdtd.set("z", 0.2e-6) +fdtd.set("use scalar approximation", 1) +fdtd.set("waist radius w0", 2e-6) +fdtd.set("distance from waist", 0) +fdtd.setglobalsource("wavelength start", 1e-6) +fdtd.setglobalsource("wavelength stop", 1e-6) + +# ### Set up monitor + +fdtd.adddftmonitor() +fdtd.set("monitor type", "2D Z-normal") +fdtd.set("x", 0) +fdtd.set("x span", 16e-6) +fdtd.set("y", 0) +fdtd.set("y span", 16e-6) +fdtd.set("z", 0.3e-6) + +# ### Run and save simulation + +fdtd.save("fdtd_tutorial.fsp") +fdtd.run() + +# ### Retrieve and plot results + +E = fdtd.getresult("monitor", "E") +fdtd.visualize(E) + +# ### Keep session open until user clicks space bar + +fdtd.print("Example complete. Hit space bar to close.") +fdtd.pause(60) + +# %% [markdown] +# ## Python style commands +# +# A simple example to demonstrate using PyLumerical. +# +# Sets up and runs a basic FDTD simulation. E field results are plotted using Matplotlib +# Demonstrates initializing objects using keyword arguments and OrderedDict. + +# %% +from collections import OrderedDict + +import matplotlib.pyplot as plt + +# - + +# ### Open interactive session with the "with" context manager, run session, retrieve and plots results, and close session + +# Set hide = True to hide the Lumerical GUI. +with lumapi.FDTD() as fdtd: + # Set up simulation region using keyword arguments + fdtd.addfdtd(x=0, x_span=8e-6, y=0, y_span=8e-6, z=0.25e-6, z_span=0.5e-6) + + # Set up source using Python OrderedDict + # OrderedDict is recommended when order is important + # Here, the scalar appproximation prop should be set before waist radius + props = OrderedDict( + [ + ("injection axis", "z"), + ("direction", "forward"), + ("x", 0), + ("x span", 16e-6), + ("y", 0), + ("y span", 16e-6), + ("z", 0.2e-6), + ("use scalar approximation", 1), + ("waist radius w0", 2e-6), + ("distance from waist", 0), + ("wavelength start", 1e-6), + ("wavelength stop", 1e-6), + ] + ) + fdtd.addgaussian(properties=props) + + # Set up monitor using regular dict + props = {"monitor type": "2D Z-normal", "x": 0, "x span": 16e-6, "y": 0, "y span": 16e-6, "z": 0.3e-6} + fdtd.adddftmonitor(properties=props) + + # Run and save simulation + fdtd.save("fdtd_tutorial.fsp") + fdtd.run() + + # Retrieve and plot results + E2 = fdtd.getelectric("monitor")[:, :, 0, 0] + + plt.figure() + plt.imshow(E2) + plt.show() + + print("Example complete. Press Enter to close.") + input() + + + diff --git a/examples/Sessions_and_Objects/fdtd_example1_lsf.py b/examples/Sessions_and_Objects/fdtd_example1_lsf.py deleted file mode 100644 index bbda79e..0000000 --- a/examples/Sessions_and_Objects/fdtd_example1_lsf.py +++ /dev/null @@ -1,65 +0,0 @@ -""" - -A simple example to demonstrate using PyLumerical using Lumerical Script File (lsf) style commands. - -------------------------------------------------- -Sets up and runs a basic FDTD simulation. E field results are plotted in Lumerical. - - -Prerequisites: Valid FDTD license is required. -""" - -############################################################################### -# -# Perform required imports -# ~~~~~~~~~~~~~~~~~~~~~~~~ - -import ansys.lumerical.core as lumapi - -# Set hide = True to hide the Lumerical GUI. -fdtd = lumapi.FDTD(hide=False) - -# Set up simulation region -fdtd.addfdtd() -fdtd.set("x", 0) -fdtd.set("x span", 8e-6) -fdtd.set("y", 0) -fdtd.set("y span", 8e-6) -fdtd.set("z", 0.25e-6) -fdtd.set("z span", 0.5e-6) - -# Set up source -fdtd.addgaussian() -fdtd.set("injection axis", "z") -fdtd.set("direction", "forward") -fdtd.set("x", 0) -fdtd.set("x span", 16e-6) -fdtd.set("y", 0) -fdtd.set("y span", 16e-6) -fdtd.set("z", 0.2e-6) -fdtd.set("use scalar approximation", 1) -fdtd.set("waist radius w0", 2e-6) -fdtd.set("distance from waist", 0) -fdtd.setglobalsource("wavelength start", 1e-6) -fdtd.setglobalsource("wavelength stop", 1e-6) - -# Set up monitor -fdtd.adddftmonitor() -fdtd.set("monitor type", "2D Z-normal") -fdtd.set("x", 0) -fdtd.set("x span", 16e-6) -fdtd.set("y", 0) -fdtd.set("y span", 16e-6) -fdtd.set("z", 0.3e-6) - -# Run and save simulation -fdtd.save("fdtd_tutorial.fsp") -fdtd.run() - -# Retrieve and plot results -E = fdtd.getresult("monitor", "E") -fdtd.visualize(E) - -# Keep session open until user clicks space bar -fdtd.print("Example complete. Hit space bar to close.") -fdtd.pause(60) diff --git a/examples/Sessions_and_Objects/fdtd_example1_pythonic.py b/examples/Sessions_and_Objects/fdtd_example1_pythonic.py deleted file mode 100644 index 720b0a1..0000000 --- a/examples/Sessions_and_Objects/fdtd_example1_pythonic.py +++ /dev/null @@ -1,66 +0,0 @@ -""" - -A simple example to demonstrate using PyLumerical. - -------------------------------------------------- -Sets up and runs a basic FDTD simulation. E field results are plotted using Matplotlib -Demonstrates initializing objects using keyword arguments and OrderedDict. - - -Prerequisites: Valid FDTD license is required. -""" - -############################################################################### -# -# Perform required imports -# ~~~~~~~~~~~~~~~~~~~~~~~~ - -from collections import OrderedDict - -import matplotlib.pyplot as plt - -import ansys.lumerical.core as lumapi - -# Set hide = True to hide the Lumerical GUI. -with lumapi.FDTD() as fdtd: - # Set up simulation region using keyword arguments - fdtd.addfdtd(x=0, x_span=8e-6, y=0, y_span=8e-6, z=0.25e-6, z_span=0.5e-6) - - # Set up source using Python OrderedDict - # OrderedDict is recommended when order is important - # Here, the scalar appproximation prop should be set before waist radius - props = OrderedDict( - [ - ("injection axis", "z"), - ("direction", "forward"), - ("x", 0), - ("x span", 16e-6), - ("y", 0), - ("y span", 16e-6), - ("z", 0.2e-6), - ("use scalar approximation", 1), - ("waist radius w0", 2e-6), - ("distance from waist", 0), - ("wavelength start", 1e-6), - ("wavelength stop", 1e-6), - ] - ) - fdtd.addgaussian(properties=props) - - # Set up monitor using regular dict - props = {"monitor type": "2D Z-normal", "x": 0, "x span": 16e-6, "y": 0, "y span": 16e-6, "z": 0.3e-6} - fdtd.adddftmonitor(properties=props) - - # Run and save simulation - fdtd.save("fdtd_tutorial.fsp") - fdtd.run() - - # Retrieve and plot results - E2 = fdtd.getelectric("monitor")[:, :, 0, 0] - - plt.figure() - plt.imshow(E2) - plt.show() - - print("Example complete. Press Enter to close.") - input() diff --git a/examples/Sessions_and_Objects/waveguide_FDE.py b/examples/Sessions_and_Objects/waveguide_FDE.py new file mode 100644 index 0000000..15c06ad --- /dev/null +++ b/examples/Sessions_and_Objects/waveguide_FDE.py @@ -0,0 +1,146 @@ +# --- +# jupyter: +# jupytext: +# formats: ipynb,py:light +# text_representation: +# extension: .py +# format_name: light +# format_version: '1.5' +# jupytext_version: 1.18.1 +# kernelspec: +# display_name: .venv +# language: python +# name: .venv +# --- + +# # A simple example using MODE. +# Waveguide (FDE): https://optics.ansys.com/hc/en-us/articles/360042800453-Waveguide-FDE +# +# The Finite Difference Eigenmode (FDE) solver in MODE is used to characterize a straight waveguide. +# +# In Part 1, we build the structure and set the FDE simulation region. +# In Part 2, we calculate the supported mode profiles of the waveguide. +# In Part 3, we perform a frequency sweep and obtain the effective index, group index, and dispersion. +# +# Prerequisites: +# Valid MODE license is required. + +# Perform required imports + +from collections import OrderedDict + +import ansys.lumerical.core as lumapi + +# Part 1: Set up structures and simulation objects + +# + +# Set hide = True to hide the Lumerical GUI. +mode = lumapi.MODE(hide=False) + +# Set key parameters +wavelength = 1.55e-6 # Center wavelength +# Set the waveguide cross-section and material +wg_width = 0.5e-6 +wg_height = 0.22e-6 +wg_material = "Si (Silicon) - Palik" +# Set substrate and cladding cross-section and material +sub_width = 10e-6 +sub_height = 5e-6 +sub_material = "SiO2 (Glass) - Palik" +clad_width = 10e-6 +clad_height = 5e-6 +clad_material = "SiO2 (Glass) - Palik" +# Set FDE region +fde_x_span = 3e-6 +fde_y_span = 3e-6 +fde_y_center = wg_height / 2 +fde_z = 0e-6 + +z_span = 1.0e-6 # Sets z span for all structures, but note FDE solver utilizes a cross section + +# Build substrate and cladding +mode.addrect(name="substrate", x=0, x_span=sub_width, y_min=-sub_height, y_max=0, z=0, z_span=z_span, material=sub_material) +mode.addrect(name="clad", x=0, x_span=clad_width, y_min=0, y_max=clad_height, z=0, z_span=z_span, material=clad_material) +# Build waveguide +# Use mesh order override to ensure waveguide object is prioritized over substrate and cladding +wg_props = OrderedDict( + [ + ("name", "waveguide"), + ("x", 0), + ("x span", wg_width), + ("y min", 0), + ("y max", wg_height), + ("z", 0), + ("z span", z_span), + ("material", wg_material), + ("override mesh order from material database", True), + ("mesh order", 1), + ] +) +mode.addrect(properties=wg_props) + +# Add FDE solver region +fde_props = OrderedDict([("x", 0), ("x span", fde_x_span), ("y", fde_y_center), ("y span", fde_y_span), ("z", fde_z)]) +mode.addfde(properties=fde_props) + +# Add mesh override region +mesh_props = OrderedDict( + [ + ("set maximum mesh step", True), + ("override x mesh", True), + ("override y mesh", True), + ("dx", 0.01e-6), + ("dy", 0.01e-6), + ("based on a structure", True), + ("structure", "waveguide"), + ] +) +mode.addmesh(properties=mesh_props) +# - + +# Part 2: Calculate the supported modes of the waveguide. The analysis_props are equivalent to the settings +# in the Eigensolver Analysis window in the GUI. + +# + +mode.setanalysis("wavelength", wavelength) +mode.setanalysis("number of trial modes", 10) +mode.setanalysis("search", "near n") +mode.setanalysis("use max index", True) +mode.findmodes() + +# Select and plot the fundamental mode +selected_mode_number = 1 +selected_mode = "mode" + str(selected_mode_number) +Efield = mode.getresult("FDE::data::" + selected_mode, "E") + +# Plot in Python - requires matplotlib +# Note that passing field data from Lumerical to Python may require additional effort. +# Lumerical uses an unstructured mesh, so the spacing between points may be non-constant. +# Ex = mode.getdata("FDE::data::"+selected_mode,"Ex")[:,:,0,0] +# Ey = mode.getdata("FDE::data::"+selected_mode,"Ey")[:,:,0,0] +# Ez = mode.getdata("FDE::data::"+selected_mode,"Ez")[:,:,0,0] +# absE = np.abs(Ex)**2+np.abs(Ey)**2+np.abs(Ez)**2 +# plt.figure() +# plt.imshow(np.transpose(absE)) +# plt.show() + +# Plot in Lumerical GUI +mode.visualize((Efield)) +# - +# Part 3: Perform a frequency sweep for the selected mode of the waveguide. + + +# + +mode.selectmode(selected_mode_number) +mode.setanalysis("track selected mode", 1) +mode.setanalysis("detailed dispersion calculation", 1) +mode.setanalysis("stop wavelength", 1.6e-6) +mode.setanalysis("number of points", 10) +mode.frequencysweep() + +# Save completed simulation file +mode.save("fde_wg_tutorial.lms") + +mode.print("Example complete. Hit space bar to continue.") +mode.pause(60) +# - diff --git a/examples/Single_Solver_Workflows/EME_edge_coupler.py b/examples/Single_Solver_Workflows/EME_edge_coupler.py new file mode 100644 index 0000000..7b79489 --- /dev/null +++ b/examples/Single_Solver_Workflows/EME_edge_coupler.py @@ -0,0 +1,61 @@ +# %% [markdown] +# ### Edge Coupler +# +# This example demonstrates how to use EME and run propogation length sweep + +# %% +import ansys.lumerical.core as lumapi +import matplotlib.pyplot as plt +import os + +fname = os.path.join(os.path.realpath(os.path.dirname(__file__)),'assets/spot_size_converter.lms') +print(fname) +##Open the session without GUI +with lumapi.MODE(filename=fname,hide=False) as mode: + ## Switch to layour before updating EME properties + mode.switchtolayout() + + ####################################### + ## Query geometry and can update + mode.select("taper") + taper_prop = mode.queryuserprop("taper") + print(taper_prop['name']) + + ## This shows how to update the values + mode.setnamed("taper","index",1.5) + + ###################################### + ## Update EME solver parameters + sc = mode.getnamed("EME","subcell method"); + + print(sc) + ## sub_cell is an array the length of the group span with 0 = none, and 1 = CVCS + sc[1] = 1 #Ensure you have CVCS enabled in cell group 2 + mode.setnamed("EME","subcell method",sc); #update EME solver + + ###################################### + ##Run EME solver + mode.run() + + ###################################### + ## Set propagation sweep settings + mode.setemeanalysis("propagation sweep",1) + mode.setemeanalysis("parameter","group span 2") + mode.setemeanalysis("start",20e-6) + mode.setemeanalysis("stop",200e-6) + mode.setemeanalysis("number of points",201) + + # run propagation sweep tool + mode.emesweep() + + # get propagation sweep result + S = mode.getemesweep('S') + + plt.plot(S['group_span_2']*1e6,abs(S['s21'])**2) + plt.title("Output Power") + plt.xlabel("Length [um]") + plt.ylabel("|S_21|^2") + plt.show() + input("Enter") + + diff --git a/examples/Single_Solver_Workflows/FDTD_nanowire.py b/examples/Single_Solver_Workflows/FDTD_nanowire.py new file mode 100644 index 0000000..f6437f2 --- /dev/null +++ b/examples/Single_Solver_Workflows/FDTD_nanowire.py @@ -0,0 +1,178 @@ +# %% [markdown] +# ### FDTD Nanowire Example +# +# This example demonstrates how to define an FDTD workflow as a python function. It will then load theory data from a csv file and it will then plot the results using matplot. +# [Nanowire Example](https://optics.ansys.com/hc/en-us/articles/360034416574-Using-the-Python-API-in-the-nanowire-application-example) + +# %% +#Import the required modules +import ansys.lumerical.core as lumapi +import numpy as np +import matplotlib.pyplot as plt + +#Define an FDTD function +def runNanowireSimulation(profile_monitor_wavelength=1e-6): + """ This function makes is convenient to reconstruct the simulation, + while changing a few key properties, a brand new FDTD will start + and close within this function + """ + fdtd = lumapi.FDTD() + fdtd.addcircle() + fdtd.addfdtd() + fdtd.addmesh() + fdtd.addtfsf() + + fdtd.addobject("cross_section") + fdtd.set("name", "scat") + fdtd.addobject("cross_section") + fdtd.set("name", "total") + + fdtd.addtime() + fdtd.set("name", "time") + + fdtd.adddftmonitor() + fdtd.set("name", "profile") + + configuration = ( + ("source", (("polarization angle", 0.), + ("injection axis", "y"), + ("x", 0.), + ("y", 0.), + ("x span", 100.0e-9), + ("y span", 100.0e-9), + ("wavelength start", 300.0e-9), + ("wavelength stop", 400.0e-9))), + + ("mesh", (("dx", 0.5e-9), + ("dy", 0.5e-9), + ("x", 0.), + ("y", 0.), + ("x span", 110.0e-9), + ("y span", 110.0e-9))), + + ("FDTD", (("simulation time", 200e-15), # in seconds + ("dimension", "2D"), + ("x",0.0e-9), + ("y",0.), + ("z",0.), + ("x span", 800.0e-9), + ("y span", 800.0e-9), + ("mesh refinement", "conformal variant 1"))), + + ("circle", (("x", 0.0e-9), + ("y", 0.0e-9), + ("z", 0.0e-9), + ("radius", 25.0e-9), # in meters + ("material", "Ag (Silver) - Palik (0-2um)"))), + + ("scat", (("x", 0.), + ("y", 0.), + ("z", 0.), + ("x span", 110.0e-9), + ("y span", 110.0e-9))), + + ("total", (("x", 0.), + ("y", 0.), + ("z", 0.), + ("x span", 90.0e-9), + ("y span", 90.0e-9))), + + ("time", (("x", 28.0e-9), + ("y", 26.0e-9))), + + ("profile", (("x", 0.), + ("y", 0.), + ("x span", 90e-9), + ("y span", 90e-9), + ("override global monitor settings", True), + ("use source limits", False), + ("frequency points", 1), + ("wavelength center", float(profile_monitor_wavelength)), + ("wavelength span", 0.))), + ) + + for obj, parameters in configuration: + for k, v in parameters: + fdtd.setnamed(obj, k, v) + + fdtd.setnamed("profile", "wavelength center", float(profile_monitor_wavelength)) + + fdtd.setglobalmonitor("frequency points", 100) # setting the global frequency resolution + + fdtd.save("nanowire_test") + fdtd.run("FDTD","CPU") + + return fdtd.getresult("scat", "sigma"), fdtd.getresult("total", "sigma"), fdtd.getresult("profile", "E") + + + +# %% [markdown] +# ## Plot results + +# %% +import os + +# run the simulation once, to determine resonance wavelength +## and get cross-sections from analysis objects +sigmascat, sigmaabs, _ = runNanowireSimulation() + +lam_sim = sigmascat['lambda'][:,0] +f_sim = sigmascat['f'][:,0] +sigmascat = sigmascat['sigma'] +sigmaabs = sigmaabs['sigma'] +sigmaext = -sigmaabs + sigmascat + +#load cross section theory from text file +nw_theory = np.genfromtxt(os.path.join(os.path.realpath(os.path.dirname(__file__)),"assets/nanowire_theory.csv"), delimiter=",") +nw_theory.shape + +lam_theory = nw_theory[:,0]*1.e-9 + +r23 = nw_theory[:,1:4]*2*23*1e-9 #flipping data +r24 = nw_theory[:,4:7]*2*24*1e-9 +r25 = nw_theory[:,7:10]*2*25*1e-9 +r26 = nw_theory[:,10:13]*2*26*1e-9 +r27 = nw_theory[:,13:16]*2*27*1e-9 + +for i in range(0, 3): + r23[:,i] = np.interp(lam_sim, lam_theory, r23[:,i]) + r24[:,i] = np.interp(lam_sim, lam_theory, r24[:,i]) + r25[:,i] = np.interp(lam_sim, lam_theory, r25[:,i]) + r26[:,i] = np.interp(lam_sim, lam_theory, r26[:,i]) + r27[:,i] = np.interp(lam_sim, lam_theory, r27[:,i]) + +# compare FDTD to theory +plt.plot(lam_sim, sigmaext*1e9, label='sigmaext') +plt.plot(lam_sim, -sigmaabs*1e9) +plt.plot(lam_sim, sigmascat*1e9) +plt.plot(lam_sim, r25*1e9) +plt.xlabel('wavelength (nm)') +plt.ylabel('cross section (nm)') + +plt.show() + +plt.plot(lam_sim, sigmaext*1e9, label='sigmaext') +plt.plot(lam_sim, -sigmaabs*1e9) +plt.plot(lam_sim, sigmascat*1e9) +plt.plot(lam_sim, r24*1e9) +plt.plot(lam_sim, r26*1e9) +plt.xlabel('wavelength (nm)') +plt.ylabel('cross section (nm)') + +plt.show() + +## run the simulation again using the resonance wavelength +_, _, E = runNanowireSimulation(profile_monitor_wavelength=lam_sim[np.argmax(sigmascat)]) + +## show the field intensity profile +Ey = E["E"][:,:,0,0,1] +plt.pcolor(np.transpose(abs(Ey)**2), vmax=5, vmin=0) +plt.xlabel("x (nm)") +plt.ylabel("y (nm)") +plt.xticks(range(Ey.shape[0])[::25], [int(v) for v in E["x"][:,0][::25]*1e9]) +plt.yticks(range(Ey.shape[1])[::25], [int(v) for v in E["y"][:,0][::25]*1e9]) +plt.colorbar() +plt.show() + + + diff --git a/examples/Single_Solver_Workflows/assets/nanowire_build_script.lsf b/examples/Single_Solver_Workflows/assets/nanowire_build_script.lsf new file mode 100644 index 0000000..beccb9c --- /dev/null +++ b/examples/Single_Solver_Workflows/assets/nanowire_build_script.lsf @@ -0,0 +1,100 @@ +# This script file builds the simulation for the nanowire example +# entirely using script commands. Objects are added to the simulation file +# using the specific add commands. The set commands sets the +# parameter you defined, any other parameters that are not set will remain as is (Default). + +switchtolayout; + +selectall; deleteall; # select and delete all objects to make sure we start with a clean project file +setprofile = 0; # not add the profile monitor for the first run; 1 to set this monitor + +############################################ +# add structures +addcircle; # add a circle object +set("x",0); # sets the x position +set("y",0); +set("z",0); +set("radius", 25e-9); # sets the radius of the circle, in meter +set("material", "Ag (Silver) - Palik (0-2um)"); # material name has to be exact + + +############################################# +# add simulation region and mesh override +addfdtd; +set("simulation time", 200e-15); # the unit is second +set("dimension", "2D"); +set("x",0); +set("y",0); +set("z",0); +set("x span", 800e-9); +set("y span", 800e-9); +# add finer mesh +addmesh; +set("dx", 1e-9); +set("dy", 1e-9); +set("x", 0); +set("y", 0); +set("x span", 110e-9); +set("y span", 110e-9); +# Mesh Reinement and Boundary conditions use the deault settings. + +############################################# +# add light source +addtfsf; +set("polarization angle", 0); +set("x", 0); +set("y", 0); +set("x span", 100e-9); +set("y span", 100e-9); +set("wavelength start", 300e-9); +set("wavelength stop", 400e-9); + + +############################################# +# add analysis group +addobject("cross_section"); +set("name", "scat"); +set("x", 0); +set("y", 0); +set("z", 0); +set("x span", 110e-9); +set("y span", 110e-9); + +addobject("cross_section"); +set("name", "total"); +set("x", 0); +set("y", 0); +set("z", 0); +set("x span", 90e-9); +set("y span", 90e-9); + +############################################# +# add monitos + + +addtime; +set("name", "time"); +set("x", 28e-9); +set("y", 26e-9); + +setglobalmonitor("frequency points", 100); # setting the global frequency resolution + +# +if(setprofile == 1){# once you know the wavelength to be monitored +addprofile; +set("name", "profile"); +set("x", 0); +set("y", 0); +set("x span", 90e-9); +set("y span", 90e-9); +set("override global monitor settings",1); +set("use source limits",0); +set("frequency points",1);# only record one frequnecy point +set("wavelength center",345e-9); +set("wavelength span",0); + +setnamed("mesh","dx",0.5e-9); +setnamed("mesh","dy",0.5e-9); + +setnamed("FDTD","mesh refinement","conformal variant 1"); +} \ No newline at end of file diff --git a/examples/Single_Solver_Workflows/assets/nanowire_plotcs.lsf b/examples/Single_Solver_Workflows/assets/nanowire_plotcs.lsf new file mode 100644 index 0000000..596cab7 --- /dev/null +++ b/examples/Single_Solver_Workflows/assets/nanowire_plotcs.lsf @@ -0,0 +1,40 @@ +# scriptfile: plotcs.lsf +# This script calculates the scattering, absorption +# and extinction cross-sections in 2D. + +# get cross-sections from analysis objects +sigmascat = getresult("scat","sigma"); +sigmaabs = getresult("total","sigma"); +sigmaext = -(sigmaabs.sigma) + (sigmascat.sigma); +lam = c/(sigmascat.f)*1e9;#in nanometer + +#load cross section theory from text file +tmp=readdata("nanowire_theory.csv"); +lam_theory=tmp(1:100,1)/1e9; +f_theory = c/lam_theory; +r23=tmp(1:100,2:4)*2*23*1e-9; +r24=tmp(1:100,5:7)*2*24*1e-9; +r25=tmp(1:100,8:10)*2*25*1e-9; +r26=tmp(1:100,11:13)*2*26*1e-9; +r27=tmp(1:100,14:16)*2*27*1e-9; + +for (i=1:3) { #interpolate onto FDTD's frequency points + r23(1:100,i)=interp(r23(1:100,i),f_theory,sigmascat.f); + r24(1:100,i)=interp(r24(1:100,i),f_theory,sigmascat.f); + r25(1:100,i)=interp(r25(1:100,i),f_theory,sigmascat.f); + r26(1:100,i)=interp(r26(1:100,i),f_theory,sigmascat.f); + r27(1:100,i)=interp(r27(1:100,i),f_theory,sigmascat.f); +} + +# Compare FDTD to theory +plot(lam, sigmaext*1e9, -(sigmaabs.sigma)*1e9, sigmascat.sigma*1e9, + r25(1:100,1)*1e9, r25(1:100,2)*1e9, r25(1:100,3)*1e9, + "wavelength (nm)","cross section (nm)","Cross sections"); +legend("Extinction", "Absorption", "Scattering", "r25 theory", "r25 theory", "r25 theory"); +# compare FDTD to theory of 24 and 26nm particle +plot(lam, sigmaext*1e9, -(sigmaabs.sigma)*1e9, sigmascat.sigma*1e9, + r24(1:100,1)*1e9, r24(1:100,2)*1e9, r24(1:100,3)*1e9, + r26(1:100,1)*1e9, r26(1:100,2)*1e9, r26(1:100,3)*1e9, + "wavelength (nm)", "cross section (nm)", "Cross sections"); +legend("Extinction", "Absorption", "Scattering", "r24 theory", "r24 theory", + "r24 theory", "r26 theory", "r26 theory", "r26 theory"); diff --git a/examples/Single_Solver_Workflows/assets/nanowire_theory.csv b/examples/Single_Solver_Workflows/assets/nanowire_theory.csv new file mode 100644 index 0000000..d5201c0 --- /dev/null +++ b/examples/Single_Solver_Workflows/assets/nanowire_theory.csv @@ -0,0 +1,100 @@ +3.00E+02,7.47E-01,5.81E-01,1.66E-01,7.94E-01,6.08E-01,1.86E-01,8.43E-01,6.36E-01,2.07E-01,8.92E-01,6.63E-01,2.28E-01,9.41E-01,6.90E-01,2.51E-01 +3.01E+02,7.29E-01,5.76E-01,1.53E-01,7.74E-01,6.03E-01,1.71E-01,8.20E-01,6.30E-01,1.90E-01,8.67E-01,6.57E-01,2.10E-01,9.13E-01,6.83E-01,2.30E-01 +3.02E+02,7.14E-01,5.74E-01,1.40E-01,7.57E-01,6.00E-01,1.57E-01,8.00E-01,6.26E-01,1.74E-01,8.44E-01,6.52E-01,1.92E-01,8.88E-01,6.77E-01,2.11E-01 +3.03E+02,7.01E-01,5.73E-01,1.28E-01,7.42E-01,5.98E-01,1.44E-01,7.83E-01,6.23E-01,1.60E-01,8.25E-01,6.48E-01,1.76E-01,8.66E-01,6.73E-01,1.93E-01 +3.04E+02,6.91E-01,5.74E-01,1.18E-01,7.30E-01,5.98E-01,1.31E-01,7.69E-01,6.23E-01,1.46E-01,8.08E-01,6.47E-01,1.61E-01,8.48E-01,6.71E-01,1.77E-01 +3.05E+02,6.84E-01,5.76E-01,1.08E-01,7.21E-01,6.00E-01,1.20E-01,7.58E-01,6.24E-01,1.34E-01,7.95E-01,6.48E-01,1.47E-01,8.33E-01,6.71E-01,1.62E-01 +3.06E+02,6.79E-01,5.80E-01,9.85E-02,7.14E-01,6.04E-01,1.10E-01,7.50E-01,6.27E-01,1.22E-01,7.85E-01,6.50E-01,1.35E-01,8.21E-01,6.73E-01,1.48E-01 +3.07E+02,6.77E-01,5.87E-01,9.03E-02,7.11E-01,6.10E-01,1.01E-01,7.45E-01,6.33E-01,1.12E-01,7.79E-01,6.55E-01,1.24E-01,8.13E-01,6.77E-01,1.36E-01 +3.08E+02,6.78E-01,5.95E-01,8.31E-02,7.10E-01,6.18E-01,9.28E-02,7.43E-01,6.40E-01,1.03E-01,7.76E-01,6.62E-01,1.14E-01,8.08E-01,6.83E-01,1.25E-01 +3.09E+02,6.81E-01,6.04E-01,7.69E-02,7.13E-01,6.27E-01,8.58E-02,7.44E-01,6.49E-01,9.51E-02,7.76E-01,6.71E-01,1.05E-01,8.07E-01,6.92E-01,1.15E-01 +3.10E+02,6.88E-01,6.16E-01,7.17E-02,7.19E-01,6.39E-01,7.99E-02,7.49E-01,6.61E-01,8.86E-02,7.80E-01,6.82E-01,9.77E-02,8.10E-01,7.03E-01,1.07E-01 +3.11E+02,6.98E-01,6.30E-01,6.76E-02,7.28E-01,6.52E-01,7.53E-02,7.57E-01,6.74E-01,8.35E-02,7.87E-01,6.95E-01,9.19E-02,8.16E-01,7.16E-01,1.01E-01 +3.12E+02,7.10E-01,6.46E-01,6.47E-02,7.40E-01,6.68E-01,7.20E-02,7.69E-01,6.90E-01,7.98E-02,7.98E-01,7.10E-01,8.78E-02,8.27E-01,7.31E-01,9.62E-02 +3.13E+02,7.27E-01,6.64E-01,6.30E-02,7.56E-01,6.86E-01,7.02E-02,7.85E-01,7.07E-01,7.76E-02,8.13E-01,7.28E-01,8.54E-02,8.42E-01,7.48E-01,9.35E-02 +3.14E+02,7.47E-01,6.84E-01,6.28E-02,7.76E-01,7.06E-01,6.98E-02,8.05E-01,7.27E-01,7.72E-02,8.33E-01,7.48E-01,8.49E-02,8.61E-01,7.68E-01,9.29E-02 +3.15E+02,7.71E-01,7.07E-01,6.40E-02,8.00E-01,7.29E-01,7.12E-02,8.29E-01,7.50E-01,7.86E-02,8.57E-01,7.70E-01,8.64E-02,8.85E-01,7.90E-01,9.44E-02 +3.16E+02,7.99E-01,7.32E-01,6.69E-02,8.28E-01,7.54E-01,7.43E-02,8.57E-01,7.75E-01,8.20E-02,8.86E-01,7.96E-01,9.01E-02,9.13E-01,8.15E-01,9.84E-02 +3.17E+02,8.32E-01,7.60E-01,7.16E-02,8.62E-01,7.82E-01,7.95E-02,8.91E-01,8.03E-01,8.77E-02,9.19E-01,8.23E-01,9.62E-02,9.47E-01,8.42E-01,1.05E-01 +3.18E+02,8.70E-01,7.91E-01,7.84E-02,9.00E-01,8.13E-01,8.69E-02,9.30E-01,8.34E-01,9.57E-02,9.59E-01,8.54E-01,1.05E-01,9.87E-01,8.73E-01,1.14E-01 +3.19E+02,9.13E-01,8.26E-01,8.74E-02,9.44E-01,8.48E-01,9.67E-02,9.75E-01,8.68E-01,1.06E-01,1.00E+00,8.88E-01,1.17E-01,1.03E+00,9.06E-01,1.27E-01 +3.20E+02,9.63E-01,8.64E-01,9.89E-02,9.95E-01,8.85E-01,1.09E-01,1.03E+00,9.06E-01,1.20E-01,1.06E+00,9.25E-01,1.31E-01,1.09E+00,9.43E-01,1.43E-01 +3.21E+02,1.02E+00,9.06E-01,1.13E-01,1.05E+00,9.27E-01,1.25E-01,1.08E+00,9.47E-01,1.37E-01,1.12E+00,9.65E-01,1.50E-01,1.15E+00,9.83E-01,1.63E-01 +3.22E+02,1.08E+00,9.51E-01,1.31E-01,1.12E+00,9.72E-01,1.44E-01,1.15E+00,9.92E-01,1.58E-01,1.18E+00,1.01E+00,1.72E-01,1.21E+00,1.03E+00,1.87E-01 +3.23E+02,1.15E+00,1.00E+00,1.51E-01,1.19E+00,1.02E+00,1.67E-01,1.22E+00,1.04E+00,1.82E-01,1.26E+00,1.06E+00,1.98E-01,1.29E+00,1.07E+00,2.15E-01 +3.24E+02,1.23E+00,1.06E+00,1.76E-01,1.27E+00,1.08E+00,1.93E-01,1.30E+00,1.09E+00,2.11E-01,1.34E+00,1.11E+00,2.30E-01,1.37E+00,1.12E+00,2.48E-01 +3.25E+02,1.32E+00,1.12E+00,2.05E-01,1.36E+00,1.13E+00,2.25E-01,1.40E+00,1.15E+00,2.45E-01,1.43E+00,1.17E+00,2.66E-01,1.47E+00,1.18E+00,2.87E-01 +3.26E+02,1.42E+00,1.18E+00,2.39E-01,1.46E+00,1.20E+00,2.61E-01,1.50E+00,1.21E+00,2.84E-01,1.53E+00,1.23E+00,3.08E-01,1.57E+00,1.24E+00,3.31E-01 +3.27E+02,1.53E+00,1.25E+00,2.78E-01,1.57E+00,1.27E+00,3.03E-01,1.61E+00,1.28E+00,3.29E-01,1.65E+00,1.29E+00,3.55E-01,1.68E+00,1.30E+00,3.82E-01 +3.28E+02,1.65E+00,1.33E+00,3.22E-01,1.69E+00,1.34E+00,3.51E-01,1.73E+00,1.35E+00,3.80E-01,1.77E+00,1.36E+00,4.10E-01,1.81E+00,1.37E+00,4.39E-01 +3.29E+02,1.78E+00,1.41E+00,3.72E-01,1.82E+00,1.42E+00,4.05E-01,1.86E+00,1.43E+00,4.37E-01,1.90E+00,1.43E+00,4.70E-01,1.94E+00,1.44E+00,5.03E-01 +3.30E+02,1.92E+00,1.49E+00,4.29E-01,1.97E+00,1.50E+00,4.65E-01,2.01E+00,1.51E+00,5.02E-01,2.05E+00,1.51E+00,5.38E-01,2.09E+00,1.51E+00,5.74E-01 +3.31E+02,2.07E+00,1.58E+00,4.93E-01,2.12E+00,1.59E+00,5.33E-01,2.16E+00,1.59E+00,5.73E-01,2.20E+00,1.59E+00,6.13E-01,2.24E+00,1.59E+00,6.52E-01 +3.32E+02,2.24E+00,1.68E+00,5.63E-01,2.28E+00,1.68E+00,6.07E-01,2.33E+00,1.68E+00,6.51E-01,2.37E+00,1.67E+00,6.94E-01,2.40E+00,1.67E+00,7.37E-01 +3.33E+02,2.41E+00,1.77E+00,6.39E-01,2.46E+00,1.77E+00,6.87E-01,2.50E+00,1.76E+00,7.35E-01,2.54E+00,1.76E+00,7.82E-01,2.57E+00,1.75E+00,8.28E-01 +3.34E+02,2.59E+00,1.87E+00,7.22E-01,2.63E+00,1.86E+00,7.74E-01,2.68E+00,1.85E+00,8.26E-01,2.71E+00,1.84E+00,8.76E-01,2.75E+00,1.82E+00,9.25E-01 +3.35E+02,2.77E+00,1.96E+00,8.09E-01,2.82E+00,1.95E+00,8.66E-01,2.86E+00,1.93E+00,9.21E-01,2.89E+00,1.92E+00,9.75E-01,2.93E+00,1.90E+00,1.03E+00 +3.36E+02,2.95E+00,2.05E+00,9.01E-01,3.00E+00,2.03E+00,9.61E-01,3.04E+00,2.02E+00,1.02E+00,3.07E+00,1.99E+00,1.08E+00,3.10E+00,1.97E+00,1.13E+00 +3.37E+02,3.13E+00,2.13E+00,9.94E-01,3.17E+00,2.11E+00,1.06E+00,3.21E+00,2.09E+00,1.12E+00,3.24E+00,2.06E+00,1.18E+00,3.28E+00,2.04E+00,1.24E+00 +3.38E+02,3.29E+00,2.21E+00,1.09E+00,3.34E+00,2.18E+00,1.16E+00,3.37E+00,2.15E+00,1.22E+00,3.41E+00,2.12E+00,1.29E+00,3.44E+00,2.09E+00,1.35E+00 +3.39E+02,3.44E+00,2.26E+00,1.18E+00,3.49E+00,2.23E+00,1.25E+00,3.52E+00,2.20E+00,1.32E+00,3.56E+00,2.17E+00,1.39E+00,3.59E+00,2.14E+00,1.45E+00 +3.40E+02,3.57E+00,2.31E+00,1.27E+00,3.62E+00,2.27E+00,1.34E+00,3.65E+00,2.24E+00,1.42E+00,3.69E+00,2.20E+00,1.48E+00,3.72E+00,2.17E+00,1.55E+00 +3.41E+02,3.67E+00,2.33E+00,1.34E+00,3.72E+00,2.29E+00,1.43E+00,3.76E+00,2.26E+00,1.50E+00,3.79E+00,2.22E+00,1.57E+00,3.82E+00,2.18E+00,1.64E+00 +3.42E+02,3.74E+00,2.33E+00,1.41E+00,3.80E+00,2.30E+00,1.50E+00,3.84E+00,2.26E+00,1.58E+00,3.88E+00,2.22E+00,1.66E+00,3.91E+00,2.18E+00,1.73E+00 +3.43E+02,3.79E+00,2.32E+00,1.47E+00,3.84E+00,2.28E+00,1.56E+00,3.89E+00,2.25E+00,1.65E+00,3.93E+00,2.21E+00,1.73E+00,3.97E+00,2.17E+00,1.80E+00 +3.44E+02,3.80E+00,2.28E+00,1.52E+00,3.86E+00,2.25E+00,1.61E+00,3.92E+00,2.22E+00,1.70E+00,3.96E+00,2.18E+00,1.78E+00,4.00E+00,2.14E+00,1.86E+00 +3.45E+02,3.78E+00,2.23E+00,1.55E+00,3.85E+00,2.21E+00,1.65E+00,3.91E+00,2.17E+00,1.74E+00,3.97E+00,2.14E+00,1.83E+00,4.01E+00,2.10E+00,1.91E+00 +3.46E+02,3.73E+00,2.17E+00,1.57E+00,3.82E+00,2.15E+00,1.67E+00,3.89E+00,2.12E+00,1.77E+00,3.95E+00,2.09E+00,1.86E+00,4.00E+00,2.05E+00,1.94E+00 +3.47E+02,3.66E+00,2.09E+00,1.57E+00,3.76E+00,2.08E+00,1.68E+00,3.84E+00,2.05E+00,1.78E+00,3.90E+00,2.03E+00,1.88E+00,3.96E+00,1.99E+00,1.97E+00 +3.48E+02,3.58E+00,2.01E+00,1.57E+00,3.68E+00,2.00E+00,1.68E+00,3.77E+00,1.98E+00,1.79E+00,3.84E+00,1.96E+00,1.89E+00,3.91E+00,1.93E+00,1.98E+00 +3.49E+02,3.47E+00,1.92E+00,1.55E+00,3.59E+00,1.92E+00,1.67E+00,3.68E+00,1.90E+00,1.78E+00,3.77E+00,1.88E+00,1.88E+00,3.84E+00,1.86E+00,1.98E+00 +3.51E+02,3.36E+00,1.83E+00,1.53E+00,3.48E+00,1.83E+00,1.65E+00,3.59E+00,1.82E+00,1.76E+00,3.68E+00,1.81E+00,1.87E+00,3.76E+00,1.79E+00,1.97E+00 +3.52E+02,3.24E+00,1.74E+00,1.50E+00,3.37E+00,1.75E+00,1.62E+00,3.48E+00,1.74E+00,1.74E+00,3.58E+00,1.73E+00,1.85E+00,3.67E+00,1.72E+00,1.95E+00 +3.53E+02,3.11E+00,1.65E+00,1.46E+00,3.25E+00,1.66E+00,1.59E+00,3.37E+00,1.66E+00,1.71E+00,3.47E+00,1.65E+00,1.82E+00,3.57E+00,1.64E+00,1.93E+00 +3.54E+02,2.99E+00,1.56E+00,1.42E+00,3.12E+00,1.58E+00,1.55E+00,3.25E+00,1.58E+00,1.67E+00,3.36E+00,1.58E+00,1.79E+00,3.47E+00,1.57E+00,1.90E+00 +3.55E+02,2.86E+00,1.48E+00,1.38E+00,3.00E+00,1.49E+00,1.51E+00,3.13E+00,1.50E+00,1.63E+00,3.25E+00,1.50E+00,1.75E+00,3.36E+00,1.50E+00,1.86E+00 +3.56E+02,2.73E+00,1.40E+00,1.34E+00,2.88E+00,1.41E+00,1.46E+00,3.01E+00,1.42E+00,1.59E+00,3.14E+00,1.43E+00,1.71E+00,3.25E+00,1.43E+00,1.82E+00 +3.57E+02,2.61E+00,1.32E+00,1.29E+00,2.76E+00,1.34E+00,1.42E+00,2.90E+00,1.35E+00,1.54E+00,3.02E+00,1.36E+00,1.66E+00,3.14E+00,1.36E+00,1.78E+00 +3.58E+02,2.50E+00,1.24E+00,1.25E+00,2.64E+00,1.27E+00,1.38E+00,2.78E+00,1.28E+00,1.50E+00,2.91E+00,1.29E+00,1.62E+00,3.03E+00,1.30E+00,1.74E+00 +3.59E+02,2.38E+00,1.18E+00,1.21E+00,2.53E+00,1.20E+00,1.33E+00,2.67E+00,1.22E+00,1.45E+00,2.80E+00,1.23E+00,1.57E+00,2.93E+00,1.23E+00,1.69E+00 +3.60E+02,2.28E+00,1.11E+00,1.16E+00,2.42E+00,1.14E+00,1.29E+00,2.56E+00,1.15E+00,1.41E+00,2.70E+00,1.17E+00,1.53E+00,2.82E+00,1.18E+00,1.65E+00 +3.61E+02,2.17E+00,1.05E+00,1.12E+00,2.32E+00,1.08E+00,1.24E+00,2.46E+00,1.10E+00,1.36E+00,2.59E+00,1.11E+00,1.48E+00,2.72E+00,1.12E+00,1.60E+00 +3.62E+02,2.08E+00,9.95E-01,1.08E+00,2.22E+00,1.02E+00,1.20E+00,2.36E+00,1.04E+00,1.32E+00,2.50E+00,1.06E+00,1.44E+00,2.62E+00,1.07E+00,1.56E+00 +3.63E+02,1.99E+00,9.43E-01,1.05E+00,2.13E+00,9.68E-01,1.16E+00,2.27E+00,9.89E-01,1.28E+00,2.40E+00,1.01E+00,1.40E+00,2.53E+00,1.02E+00,1.51E+00 +3.64E+02,1.90E+00,8.94E-01,1.01E+00,2.04E+00,9.20E-01,1.12E+00,2.18E+00,9.41E-01,1.24E+00,2.31E+00,9.59E-01,1.35E+00,2.44E+00,9.72E-01,1.47E+00 +3.65E+02,1.82E+00,8.49E-01,9.73E-01,1.96E+00,8.74E-01,1.08E+00,2.09E+00,8.96E-01,1.20E+00,2.23E+00,9.14E-01,1.31E+00,2.35E+00,9.28E-01,1.42E+00 +3.66E+02,1.75E+00,8.07E-01,9.39E-01,1.88E+00,8.32E-01,1.05E+00,2.01E+00,8.54E-01,1.16E+00,2.14E+00,8.72E-01,1.27E+00,2.27E+00,8.87E-01,1.38E+00 +3.67E+02,1.67E+00,7.67E-01,9.07E-01,1.81E+00,7.92E-01,1.01E+00,1.94E+00,8.14E-01,1.12E+00,2.07E+00,8.33E-01,1.23E+00,2.19E+00,8.48E-01,1.34E+00 +3.68E+02,1.61E+00,7.31E-01,8.76E-01,1.74E+00,7.56E-01,9.80E-01,1.86E+00,7.77E-01,1.09E+00,1.99E+00,7.96E-01,1.19E+00,2.12E+00,8.12E-01,1.30E+00 +3.69E+02,1.54E+00,6.97E-01,8.47E-01,1.67E+00,7.21E-01,9.48E-01,1.80E+00,7.43E-01,1.05E+00,1.92E+00,7.62E-01,1.16E+00,2.04E+00,7.78E-01,1.27E+00 +3.70E+02,1.48E+00,6.65E-01,8.19E-01,1.61E+00,6.89E-01,9.18E-01,1.73E+00,7.11E-01,1.02E+00,1.85E+00,7.29E-01,1.12E+00,1.98E+00,7.46E-01,1.23E+00 +3.71E+02,1.43E+00,6.36E-01,7.92E-01,1.55E+00,6.59E-01,8.89E-01,1.67E+00,6.80E-01,9.88E-01,1.79E+00,6.99E-01,1.09E+00,1.91E+00,7.15E-01,1.19E+00 +3.72E+02,1.38E+00,6.08E-01,7.67E-01,1.49E+00,6.31E-01,8.61E-01,1.61E+00,6.52E-01,9.59E-01,1.73E+00,6.71E-01,1.06E+00,1.85E+00,6.87E-01,1.16E+00 +3.73E+02,1.33E+00,5.83E-01,7.43E-01,1.44E+00,6.05E-01,8.34E-01,1.56E+00,6.25E-01,9.30E-01,1.67E+00,6.44E-01,1.03E+00,1.79E+00,6.60E-01,1.13E+00 +3.74E+02,1.28E+00,5.59E-01,7.20E-01,1.39E+00,5.80E-01,8.09E-01,1.50E+00,6.01E-01,9.03E-01,1.62E+00,6.19E-01,9.99E-01,1.73E+00,6.35E-01,1.10E+00 +3.75E+02,1.23E+00,5.36E-01,6.98E-01,1.34E+00,5.57E-01,7.85E-01,1.45E+00,5.77E-01,8.76E-01,1.57E+00,5.95E-01,9.71E-01,1.68E+00,6.11E-01,1.07E+00 +3.76E+02,1.19E+00,5.15E-01,6.77E-01,1.30E+00,5.36E-01,7.62E-01,1.41E+00,5.55E-01,8.51E-01,1.52E+00,5.73E-01,9.44E-01,1.63E+00,5.89E-01,1.04E+00 +3.77E+02,1.15E+00,4.95E-01,6.57E-01,1.26E+00,5.16E-01,7.40E-01,1.36E+00,5.35E-01,8.28E-01,1.47E+00,5.52E-01,9.18E-01,1.58E+00,5.68E-01,1.01E+00 +3.78E+02,1.11E+00,4.77E-01,6.38E-01,1.22E+00,4.96E-01,7.19E-01,1.32E+00,5.15E-01,8.05E-01,1.43E+00,5.32E-01,8.93E-01,1.53E+00,5.48E-01,9.84E-01 +3.79E+02,1.08E+00,4.59E-01,6.20E-01,1.18E+00,4.78E-01,6.99E-01,1.28E+00,4.97E-01,7.83E-01,1.38E+00,5.14E-01,8.69E-01,1.49E+00,5.29E-01,9.59E-01 +3.80E+02,1.05E+00,4.43E-01,6.03E-01,1.14E+00,4.62E-01,6.80E-01,1.24E+00,4.79E-01,7.62E-01,1.34E+00,4.96E-01,8.47E-01,1.45E+00,5.11E-01,9.34E-01 +3.81E+02,1.01E+00,4.27E-01,5.86E-01,1.11E+00,4.46E-01,6.62E-01,1.20E+00,4.63E-01,7.42E-01,1.30E+00,4.79E-01,8.25E-01,1.41E+00,4.95E-01,9.11E-01 +3.82E+02,9.83E-01,4.12E-01,5.70E-01,1.07E+00,4.31E-01,6.44E-01,1.17E+00,4.48E-01,7.22E-01,1.27E+00,4.64E-01,8.04E-01,1.37E+00,4.79E-01,8.88E-01 +3.83E+02,9.54E-01,3.99E-01,5.55E-01,1.04E+00,4.16E-01,6.27E-01,1.14E+00,4.33E-01,7.04E-01,1.23E+00,4.49E-01,7.84E-01,1.33E+00,4.64E-01,8.66E-01 +3.84E+02,9.26E-01,3.86E-01,5.41E-01,1.01E+00,4.03E-01,6.11E-01,1.11E+00,4.19E-01,6.86E-01,1.20E+00,4.35E-01,7.64E-01,1.29E+00,4.49E-01,8.45E-01 +3.85E+02,9.00E-01,3.73E-01,5.27E-01,9.86E-01,3.90E-01,5.96E-01,1.08E+00,4.06E-01,6.69E-01,1.17E+00,4.21E-01,7.46E-01,1.26E+00,4.36E-01,8.25E-01 +3.86E+02,8.75E-01,3.62E-01,5.14E-01,9.59E-01,3.78E-01,5.81E-01,1.05E+00,3.94E-01,6.53E-01,1.14E+00,4.09E-01,7.28E-01,1.23E+00,4.23E-01,8.06E-01 +3.87E+02,8.51E-01,3.50E-01,5.01E-01,9.33E-01,3.67E-01,5.67E-01,1.02E+00,3.82E-01,6.37E-01,1.11E+00,3.97E-01,7.10E-01,1.20E+00,4.10E-01,7.87E-01 +3.88E+02,8.29E-01,3.40E-01,4.89E-01,9.09E-01,3.56E-01,5.53E-01,9.92E-01,3.71E-01,6.22E-01,1.08E+00,3.85E-01,6.94E-01,1.17E+00,3.99E-01,7.69E-01 +3.89E+02,8.07E-01,3.30E-01,4.77E-01,8.85E-01,3.45E-01,5.40E-01,9.67E-01,3.60E-01,6.07E-01,1.05E+00,3.74E-01,6.78E-01,1.14E+00,3.87E-01,7.52E-01 +3.90E+02,7.86E-01,3.20E-01,4.66E-01,8.63E-01,3.35E-01,5.27E-01,9.43E-01,3.50E-01,5.93E-01,1.03E+00,3.64E-01,6.62E-01,1.11E+00,3.77E-01,7.35E-01 +3.91E+02,7.66E-01,3.11E-01,4.55E-01,8.41E-01,3.26E-01,5.15E-01,9.20E-01,3.40E-01,5.80E-01,1.00E+00,3.54E-01,6.48E-01,1.09E+00,3.67E-01,7.19E-01 +3.92E+02,7.47E-01,3.03E-01,4.44E-01,8.21E-01,3.17E-01,5.04E-01,8.98E-01,3.31E-01,5.67E-01,9.78E-01,3.44E-01,6.33E-01,1.06E+00,3.57E-01,7.03E-01 +3.93E+02,7.29E-01,2.95E-01,4.34E-01,8.01E-01,3.09E-01,4.92E-01,8.76E-01,3.22E-01,5.54E-01,9.55E-01,3.35E-01,6.20E-01,1.04E+00,3.48E-01,6.88E-01 +3.94E+02,7.11E-01,2.87E-01,4.25E-01,7.82E-01,3.01E-01,4.82E-01,8.56E-01,3.14E-01,5.42E-01,9.33E-01,3.27E-01,6.06E-01,1.01E+00,3.39E-01,6.74E-01 +3.95E+02,6.95E-01,2.79E-01,4.15E-01,7.64E-01,2.93E-01,4.71E-01,8.36E-01,3.06E-01,5.31E-01,9.12E-01,3.18E-01,5.93E-01,9.90E-01,3.30E-01,6.60E-01 +3.96E+02,6.79E-01,2.72E-01,4.06E-01,7.46E-01,2.85E-01,4.61E-01,8.17E-01,2.98E-01,5.19E-01,8.92E-01,3.11E-01,5.81E-01,9.68E-01,3.22E-01,6.46E-01 +3.97E+02,6.63E-01,2.65E-01,3.98E-01,7.30E-01,2.78E-01,4.51E-01,7.99E-01,2.91E-01,5.08E-01,8.72E-01,3.03E-01,5.69E-01,9.48E-01,3.15E-01,6.33E-01 +3.98E+02,6.48E-01,2.59E-01,3.89E-01,7.13E-01,2.71E-01,4.42E-01,7.82E-01,2.84E-01,4.98E-01,8.53E-01,2.96E-01,5.58E-01,9.27E-01,3.07E-01,6.20E-01 +3.99E+02,6.34E-01,2.53E-01,3.81E-01,6.98E-01,2.65E-01,4.33E-01,7.65E-01,2.77E-01,4.88E-01,8.35E-01,2.89E-01,5.46E-01,9.08E-01,3.00E-01,6.08E-01 +4.00E+02,6.20E-01,2.47E-01,3.74E-01,6.83E-01,2.59E-01,4.24E-01,7.49E-01,2.71E-01,4.78E-01,8.18E-01,2.82E-01,5.35E-01,8.89E-01,2.93E-01,5.96E-01 diff --git a/pyproject.toml b/pyproject.toml index 8b2f46c..96bbb19 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,9 +41,12 @@ tests = [ doc = [ "ansys-sphinx-theme[autoapi]==1.4.2", "numpydoc==1.8.0", - "sphinx==8.2.3", + "sphinx==8.1.3", "sphinx-copybutton==0.5.2", "sphinx_design==0.6.1", + "nbsphinx==0.9.7", + "jupytext==1.17.3", + "ipykernel==6.30.1" ] examples = [ "matplotlib==3.10.0",