### Install femwell using pip Source: https://github.com/helgegehring/femwell/blob/main/docs/install.md Use this command to install the femwell package via pip. Ensure pip is up-to-date. ```bash pip install femwell ``` -------------------------------- ### Coulomb/Electrostatic Solver Setup Source: https://context7.com/helgegehring/femwell/llms.txt Set up geometry for solving electrostatic potential distributions in capacitor and electrode analysis. This snippet focuses on defining the geometry and mesh. ```python from femwell.coulomb import solve_coulomb from shapely.geometry import box # Define parallel plate capacitor geometry electrode_left = box(-6, 0.5, -3, 2.3) electrode_right = box(3, 0.5, 6, 2.3) slab = box(-10, 0, 10, 0.5) env = slab.buffer(20, resolution=8) polygons_cap = OrderedDict( electrode_left=electrode_left, electrode_right=electrode_right, slab=slab, env=env, ) resolutions_cap = dict( slab={"resolution": 0.1, "distance": 0.1}, ) mesh_cap = from_meshio( mesh_from_OrderedDict(polygons_cap, resolutions_cap, default_resolution_max=5) ) ``` -------------------------------- ### Install slepc4py for slepc eigensolver Source: https://github.com/helgegehring/femwell/blob/main/docs/install.md Install slepc4py with complex support using conda, required for the slepc eigensolver. This command ensures the correct version for complex number support. ```bash conda install slepc4py=*=complex* ``` -------------------------------- ### Static Thermal Simulation Source: https://context7.com/helgegehring/femwell/llms.txt Solve steady-state heat distribution with Joule heating sources. Requires defining geometry, mesh, material properties, and current densities. ```python from femwell.thermal import solve_thermal from shapely.geometry import LineString # Define geometry with heater element polygons_thermal = OrderedDict( bottom=LineString([(-8, -1), (8, -1)]), # Fixed temperature boundary core=Polygon([(-0.25, 0), (-0.25, 0.22), (0.25, 0.22), (0.25, 0)]), heater=Polygon([(-1, 2), (-1, 2.14), (1, 2.14), (1, 2)]), clad=box(-8, 0, 8, 3), box=box(-8, -1, 8, 0), ) resolutions_thermal = dict( core={"resolution": 0.04, "distance": 1}, heater={"resolution": 0.1, "distance": 1}, ) mesh_thermal = from_meshio( mesh_from_OrderedDict(polygons_thermal, resolutions_thermal, default_resolution_max=0.6) ) # Define thermal conductivity (W/m·K, scaled for um units) basis0_thermal = Basis(mesh_thermal, ElementTriP0(), intorder=4) thermal_conductivity = basis0_thermal.zeros() for domain, value in { "core": 148, # Silicon "box": 1.38, # SiO2 "clad": 1.38, # SiO2 "heater": 28, # TiN }.items(): thermal_conductivity[basis0_thermal.get_dofs(elements=domain)] = value thermal_conductivity *= 1e-12 # Convert to um^-2 units # Solve thermal distribution with current density current_density = 0.007 / polygons_thermal["heater"].area # A/um^2 basis_T, temperature = solve_thermal( basis0_thermal, thermal_conductivity, specific_conductivity={"heater": 2.3e6}, # S/m current_densities={"heater": current_density}, fixed_boundaries={"bottom": 0}, # Reference temperature ) # Plot temperature distribution basis_T.plot(temperature, shading="gouraud", colorbar=True) plt.title("Temperature Distribution (K above ambient)") plt.show() ``` -------------------------------- ### Calculate Mode Properties and Metrics Source: https://context7.com/helgegehring/femwell/llms.txt Extract physical properties from computed modes such as confined power, confinement factor, effective area, and propagation loss. ```python import numpy as np mode = modes[0] # First (fundamental) mode # Calculate power confined in a specific region power_in_core = mode.calculate_power(elements="core") print(f"Power in core: {np.real(power_in_core):.4f}") # Calculate confinement factor confinement = mode.calculate_confinement_factor(elements="core") print(f"Confinement factor: {np.real(confinement):.4f}") # Calculate effective area (for nonlinear optics) A_eff = mode.calculate_effective_area(field="xy") print(f"Effective area: {A_eff:.4f} um^2") # Calculate propagation loss over a distance (for lossy materials) # Requires complex epsilon with imaginary part distance = 1000 # micrometers loss_dB = mode.calculate_propagation_loss(distance) print(f"Propagation loss over {distance}um: {loss_dB:.2f} dB") # Access wavelength and frequency print(f"Wavelength: {mode.wavelength:.4f} um") print(f"Frequency: {mode.frequency:.4e} Hz") ``` -------------------------------- ### Define Permittivity and Solve Coulomb Equation Source: https://context7.com/helgegehring/femwell/llms.txt Sets up permittivity for a layered dielectric and solves the Coulomb equation to find the electric potential. Requires mesh and basis definitions. ```python from skfem import Basis, ElementTriP0 import matplotlib.pyplot as plt # Define permittivity basis_cap = Basis(mesh_cap, ElementTriP0()) epsilon = basis_cap.zeros() + 3.9 # Air/oxide epsilon[basis_cap.get_dofs(elements="slab")] = 28.4 # High-k dielectric # Solve Coulomb equation with boundary conditions basis_u, potential = solve_coulomb( basis_cap, epsilon, { "electrode_left___slab": 1.0, # 1V on left electrode "electrode_right___slab": 0.0, # 0V on right electrode }, ) # Plot electric potential basis_u.plot(potential, shading="gouraud", colorbar=True) plt.title("Electric Potential (V)") plt.show() ``` -------------------------------- ### Transient Thermal Simulation Source: https://context7.com/helgegehring/femwell/llms.txt Simulate time-dependent thermal behavior for phase shifter response analysis. Requires defining thermal diffusivity and time-varying current. ```python from femwell.thermal_transient import solve_thermal_transient # Define thermal diffusivity (m^2/s, scaled for um units) thermal_diffusivity = basis0_thermal.zeros() for domain, value in { "heater": 28 / 598 / 5240, # TiN: k/(c*rho) "box": 1.38 / 709 / 2203, # SiO2 "clad": 1.38 / 709 / 2203, "core": 148 / 711 / 2330, # Silicon }.items(): thermal_diffusivity[basis0_thermal.get_dofs(elements=domain)] = value thermal_diffusivity *= 1e12 # Convert to um^2 units # Define time-varying current dt = 0.1e-5 # Time step in seconds steps = 100 heater_area = polygons_thermal["heater"].area current = lambda t: 0.007 / heater_area * ((t < dt * steps / 10) + (t > dt * steps / 2)) # Run transient simulation basis_T, temperatures = solve_thermal_transient( basis0_thermal, thermal_conductivity, thermal_diffusivity, specific_conductivity={"heater": 2.3e6}, current_densities_0={"heater": current(0)}, current_densities={"heater": current}, fixed_boundaries={"bottom": 0}, dt=dt, steps=steps, ) # Plot temperature evolution times = np.array([dt * i for i in range(steps + 1)]) avg_temps = [np.mean(T) for T in temperatures] plt.plot(times * 1e6, avg_temps) plt.xlabel("Time (us)") plt.ylabel("Average Temperature (K)") plt.show() ``` -------------------------------- ### Compute Modes for Bent Waveguide Analysis Source: https://context7.com/helgegehring/femwell/llms.txt Calculates the modes of a waveguide with a finite bend radius. Requires basis, permittivity, wavelength, and bend radius. ```python from skfem import Basis, ElementTriP0 # Compute modes with finite bend radius radius = 10 # Bend radius in um modes_bent = compute_modes( basis0, epsilon, wavelength=1.55, num_modes=1, radius=radius # Enable bent waveguide analysis ) # Compare effective index with straight waveguide mode_straight = modes[0] mode_bent = modes_bent[0] print(f"Straight waveguide n_eff: {mode_straight.n_eff:.6f}") print(f"Bent waveguide n_eff (R={radius}um): {mode_bent.n_eff:.6f}") # Calculate bending loss loss_per_um = mode_bent.calculate_propagation_loss(1) circumference = 2 * np.pi * radius loss_per_turn = loss_per_um * circumference print(f"Loss per 90-degree bend: {loss_per_turn/4:.4f} dB") ``` -------------------------------- ### Calculate Coupling Coefficients Source: https://context7.com/helgegehring/femwell/llms.txt Use this to calculate coupling coefficients between waveguide modes for directional coupler design. Requires defining waveguide geometries and calculating modes. ```python from scipy.constants import epsilon_0, speed_of_light # Define two waveguides in a coupled system gap = 0.4 w_core_1, w_core_2 = 0.45, 0.46 polygons_coupled = OrderedDict( core_1=Polygon([ (-w_core_1 - gap/2, 0), (-w_core_1 - gap/2, 0.22), (-gap/2, 0.22), (-gap/2, 0), ]), core_2=Polygon([ (gap/2, 0), (gap/2, 0.22), (w_core_2 + gap/2, 0.22), (w_core_2 + gap/2, 0), ]), clad=box(-2, -1, 2, 1), box=box(-2, -1, 2, 0), ) # Calculate modes with both waveguides present epsilon_both = basis0.zeros() + 1.444**2 epsilon_both[basis0.get_dofs(elements=("core_1", "core_2"))] = 3.4777**2 modes_coupled = compute_modes(basis0, epsilon_both, wavelength=1.55, num_modes=2) # Calculate coupling length for power transfer n_eff_1, n_eff_2 = modes_coupled[0].n_eff, modes_coupled[1].n_eff coupling_length = wavelength / (2 * np.abs(n_eff_1 - n_eff_2)) print(f"Coupling length for full power transfer: {coupling_length:.2f} um") ``` -------------------------------- ### Visualize Schrödinger Equation Bound States Source: https://github.com/helgegehring/femwell/blob/main/docs/math/schroedinger.md Plots the conditions for symmetric and asymmetric bound states of the Schrödinger equation in a potential well. Requires numpy and matplotlib. The plot visualizes the relationship between energy levels and well parameters. ```python import numpy as np import matplotlib.pyplot as plt u0 = np.sqrt(20) v = np.linspace(0,5,10000) yc = np.sqrt(u0**2-v**2) plt.ylim(0,u0+1) plt.plot(v, yc) y = v*np.tan(v) y = np.where(y>-10,y,np.nan) plt.plot(v, y, label='symmetric') idx_s = np.argwhere(np.nan_to_num(np.diff(np.sign(y - yc)),-1))[:,0] plt.plot(v[idx_s], y[idx_s], 'ro') print(v[idx_s]) y = -v*1/np.tan(v) plt.plot(v, np.where(y>-10,y,np.nan), label='asymmetric') idx_a = np.argwhere(np.nan_to_num(np.diff(np.sign(y - yc)),-1))[:,0] plt.plot(v[idx_a], y[idx_a], 'ro') print(v[idx_a]) plt.legend() plt.show() ``` -------------------------------- ### Compute Optical Waveguide Eigenmodes Source: https://context7.com/helgegehring/femwell/llms.txt Calculate effective refractive index, TE/TM fractions, and field distributions for waveguide modes. Requires a defined permittivity distribution based on the mesh subdomains. ```python from skfem import Basis, ElementTriP0 from femwell.maxwell.waveguide import compute_modes # Create basis for piecewise constant permittivity basis0 = Basis(mesh, ElementTriP0()) # Define permittivity distribution (epsilon = n^2) epsilon = basis0.zeros() for subdomain, n in {"core": 3.4777, "box": 1.444, "clad": 1.0}.items(): epsilon[basis0.get_dofs(elements=subdomain)] = n**2 # Compute modes at specified wavelength wavelength = 1.55 # micrometers modes = compute_modes( basis0, epsilon, wavelength=wavelength, num_modes=3, # Number of modes to compute order=2 # Basis function order (1 or 2) ) # Access mode properties for i, mode in enumerate(modes): print(f"Mode {i}: n_eff = {mode.n_eff:.6f}") print(f" TE fraction: {mode.te_fraction:.3f}") print(f" TM fraction: {mode.tm_fraction:.3f}") # Visualize electric field components modes[0].show("E", part="real", colorbar=True) # Plot mode intensity modes[0].show("I", colorbar=True) ``` -------------------------------- ### Plot Subdomain Boundaries Source: https://context7.com/helgegehring/femwell/llms.txt Highlights only the boundaries of subdomains in a mesh, useful for verifying subdomain definitions without showing the entire mesh. ```python from femwell.visualization import plot_subdomain_boundaries import matplotlib.pyplot as plt # Plot subdomain boundaries only plot_subdomain_boundaries(mesh) plt.title("Subdomain Boundaries") plt.show() ``` -------------------------------- ### Generate 2D Meshes from Shapely Polygons Source: https://context7.com/helgegehring/femwell/llms.txt Create a 2D mesh from defined Shapely polygons with localized resolution control. Requires an OrderedDict to define geometry priority and a resolution dictionary for mesh refinement. ```python from collections import OrderedDict from shapely.geometry import Polygon, box from shapely.ops import clip_by_rect import numpy as np from skfem.io.meshio import from_meshio from femwell.mesh import mesh_from_OrderedDict # Define waveguide geometry using Shapely wg_width = 0.5 wg_thickness = 0.22 core = box(-wg_width / 2, 0, wg_width / 2, wg_thickness) env = core.buffer(2, resolution=8) # Create ordered dictionary of polygons (order determines override priority) polygons = OrderedDict( core=core, box=clip_by_rect(env, -np.inf, -np.inf, np.inf, 0), clad=clip_by_rect(env, -np.inf, 0, np.inf, np.inf), ) # Define mesh resolution: finer near the core, coarser elsewhere resolutions = dict( core={"resolution": 0.03, "distance": 0.5} # 30nm resolution, 500nm falloff ) # Generate mesh and convert to scikit-fem format mesh = from_meshio( mesh_from_OrderedDict( polygons, resolutions, filename="mesh.msh", default_resolution_max=0.5 ) ) # Visualize the mesh mesh.draw().show() ``` -------------------------------- ### Compute Mode Overlap Integrals Source: https://context7.com/helgegehring/femwell/llms.txt Calculate overlap integrals between modes to analyze coupling and mode matching. Useful for generating an overlap matrix to verify mode orthonormality. ```python import numpy as np # Calculate overlap integral between two modes overlap = modes[0].calculate_overlap(modes[1]) print(f"Overlap between mode 0 and mode 1: {np.abs(overlap):.6f}") # Build overlap matrix for all modes num_modes = len(modes) overlap_matrix = np.zeros((num_modes, num_modes), dtype=complex) for i in range(num_modes): for j in range(num_modes): overlap_matrix[i, j] = modes[i].calculate_overlap(modes[j]) print("Overlap matrix:") print(np.abs(overlap_matrix)) # Modes should be orthonormal (diagonal ~1, off-diagonal ~0) ``` -------------------------------- ### Plot Mesh Domains Source: https://context7.com/helgegehring/femwell/llms.txt Visualizes the different domains within a mesh, useful for debugging mesh generation and subdomain definitions. ```python from femwell.visualization import plot_domains import matplotlib.pyplot as plt # Plot mesh with colored domains plot_domains(mesh) plt.title("Mesh Domains") plt.show() ``` -------------------------------- ### Calculate Electric Field Source: https://context7.com/helgegehring/femwell/llms.txt Calculates the electric field components from the solved electric potential and permittivity. Requires the electric potential and basis. ```python from skfem import ElementDG # Calculate electric field E_x = basis_u.project(-basis_cap.interpolate(epsilon) * basis_u.interpolate(potential).grad[0]) basis_u.plot(E_x, shading="gouraud", colorbar=True) plt.title("Electric Field E_x") plt.show() ``` -------------------------------- ### Calculate Fiber Overlap Integral Source: https://context7.com/helgegehring/femwell/llms.txt Computes the coupling efficiency between a waveguide mode and a Gaussian fiber mode using the overlap integral. Requires mode data and fiber parameters. ```python from femwell.fiber import e_field_gaussian, overlap import numpy as np # Define fiber parameters mfr = 5.2 # Mode field radius in um fiber_n = 1.0 # Refractive index wavelength = 1.55 # Get waveguide mode field (Ex, Ey), Ez = modes[0].basis.interpolate(modes[0].E) # Create Gaussian fiber field on same basis # The fiber field is evaluated at mesh quadrature points fiber_E = e_field_gaussian( r=np.sqrt(modes[0].basis.X[0]**2 + modes[0].basis.X[1]**2), z=0, mfr=mfr, refractive_index=fiber_n, wavelength=wavelength ) # Calculate overlap integral fiber_coupling = overlap(modes[0].basis, Ex, fiber_E) print(f"Fiber coupling efficiency: {fiber_coupling**2:.4f}") ``` -------------------------------- ### Plot Mode Field Components Source: https://context7.com/helgegehring/femwell/llms.txt Visualizes individual components (Ex, Ey, Ez) of a mode's electric field. Requires a computed mode object. ```python import matplotlib.pyplot as plt # Plot mode field components individually mode = modes[0] fig, axs = plt.subplots(1, 3, figsize=(12, 4)) for ax, comp in zip(axs, ["x", "y", "z"]): mode.plot_component("E", comp, part="real", ax=ax, colorbar=True) plt.tight_layout() plt.show() ``` -------------------------------- ### Calculate Coaxial Cable Impedance Source: https://context7.com/helgegehring/femwell/llms.txt Computes the characteristic impedance of a coaxial cable using mode analysis. Requires defining the cable geometry, dielectric properties, and frequency. ```python import shapely from skfem import Functional, Basis, ElementTriP0 from skfem.helpers import inner import scipy.constants from collections import OrderedDict from femwell.mesh import from_meshio, mesh_from_OrderedDict # Define coaxial cable geometry radius_inner = 0.512e-3 # Inner conductor radius (m) radius_outer = 2.23e-3 # Outer conductor radius (m) core = shapely.Point(0, 0).buffer(radius_inner) isolator = shapely.Point(0, 0).buffer(radius_outer) polygons_coax = OrderedDict( surface=shapely.LineString(isolator.exterior), surface_core=shapely.LinearRing(core.exterior), isolator=isolator - core, ) resolutions_coax = dict(isolator={"resolution": 0.05, "distance": 1}) mesh_coax = from_meshio( mesh_from_OrderedDict(polygons_coax, resolutions_coax, default_resolution_max=1) ) # Set up dielectric basis_coax = Basis(mesh_coax, ElementTriP0(), intorder=4) epsilon_coax = basis_coax.zeros() + 1.29 # Polyethylene dielectric # Compute TEM mode with metallic boundaries frequency = 10e9 # 10 GHz modes_coax = compute_modes( basis_coax, epsilon_coax, wavelength=scipy.constants.speed_of_light / frequency, num_modes=1, metallic_boundaries=("surface", "surface_core") ) print(f"Propagation constant: {1/modes_coax.n_effs[0]:.6f}") # Calculate current for impedance @Functional(dtype=np.complex64) def current_form(w): return inner(np.array([w.n[1], -w.n[0]]), w.H) (ht, ht_basis), (hz, hz_basis) = modes_coax[0].basis.split(modes_coax[0].H) facet_basis = ht_basis.boundary(facets=mesh_coax.boundaries["isolator___isolator"]) current = abs(current_form.assemble(facet_basis, H=facet_basis.interpolate(ht))) # Characteristic impedance Z0 = V/I (normalized to 1V) Z0 = 1 / current print(f"Characteristic impedance: {Z0:.1f} Ohms") ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.