Solvers API

Prismo provides a unified solver interface that supports multiple electromagnetic simulation methods. All solvers implement the same base interface, allowing you to switch between different solvers transparently.

Solver Interface

Abstract base class for electromagnetic solvers.

This module defines the unified interface that all solvers (FDTD, FEM, MEEP) must implement, allowing solver-agnostic simulation orchestration.

class prismo.solvers.base.SolverBase(grid)[source]

Bases: ABC

Abstract base class for all electromagnetic solvers.

This class defines the unified interface that all solvers must implement, allowing the Simulation class to work with any solver type transparently.

__init__(grid)[source]

Initialize the solver.

Parameters:

grid (YeeGrid) – The simulation grid.

abstractmethod step(fields=None)[source]

Perform a single time step.

Parameters:

fields (ElectromagneticFields, optional) – Fields to update. If None, uses internal fields.

Return type:

None

abstractmethod get_fields()[source]

Get the current electromagnetic fields.

Returns:

Current field state.

Return type:

ElectromagneticFields

abstractmethod reset()[source]

Reset simulation to initial state.

Return type:

None

abstractmethod get_time_step()[source]

Get the time step used by the solver.

Returns:

Time step in seconds.

Return type:

float

get_simulation_info()[source]

Get information about the current simulation state.

Returns:

Dictionary with simulation information.

Return type:

dict

__repr__()[source]

String representation.

Return type:

str

class prismo.solvers.base.TimeDomainSolver(grid)[source]

Bases: SolverBase

Base class for time-domain solvers (FDTD, MEEP).

Time-domain solvers advance fields in time using time-stepping.

abstractmethod run(total_time, callback=None)[source]

Run simulation for specified time.

Parameters:
  • total_time (float) – Total simulation time in seconds.

  • callback (callable, optional) – Function called after each time step.

Return type:

None

abstractmethod run_steps(num_steps, callback=None)[source]

Run simulation for specified number of steps.

Parameters:
  • num_steps (int) – Number of time steps to run.

  • callback (callable, optional) – Function called after each time step.

Return type:

None

class prismo.solvers.base.FrequencyDomainSolver(grid)[source]

Bases: SolverBase

Base class for frequency-domain solvers (FEM).

Frequency-domain solvers solve for fields at specific frequencies.

abstractmethod solve(frequency)[source]

Solve for fields at a specific frequency.

Parameters:

frequency (float) – Frequency in Hz.

Returns:

Solution fields at the specified frequency.

Return type:

ElectromagneticFields

abstractmethod solve_eigenvalue(num_modes=1)[source]

Solve eigenvalue problem (e.g., for waveguide modes).

Parameters:

num_modes (int) – Number of modes to compute.

Returns:

(eigenvalues, eigenmodes) where eigenmodes is a list of fields.

Return type:

tuple

Base Classes

SolverBase

class prismo.solvers.base.SolverBase(grid)[source]

Abstract base class for all electromagnetic solvers.

This class defines the unified interface that all solvers must implement, allowing the Simulation class to work with any solver type transparently.

__init__(grid)[source]

Initialize the solver.

Parameters:

grid (YeeGrid) – The simulation grid.

abstractmethod step(fields=None)[source]

Perform a single time step.

Parameters:

fields (ElectromagneticFields, optional) – Fields to update. If None, uses internal fields.

Return type:

None

abstractmethod get_fields()[source]

Get the current electromagnetic fields.

Returns:

Current field state.

Return type:

ElectromagneticFields

abstractmethod reset()[source]

Reset simulation to initial state.

Return type:

None

abstractmethod get_time_step()[source]

Get the time step used by the solver.

Returns:

Time step in seconds.

Return type:

float

get_simulation_info()[source]

Get information about the current simulation state.

Returns:

Dictionary with simulation information.

Return type:

dict

__repr__()[source]

String representation.

Return type:

str

TimeDomainSolver

Base class for time-domain solvers (FDTD, MEEP). These solvers advance fields in time using time-stepping.

class prismo.solvers.base.TimeDomainSolver(grid)[source]

Base class for time-domain solvers (FDTD, MEEP).

Time-domain solvers advance fields in time using time-stepping.

abstractmethod run(total_time, callback=None)[source]

Run simulation for specified time.

Parameters:
  • total_time (float) – Total simulation time in seconds.

  • callback (callable, optional) – Function called after each time step.

Return type:

None

abstractmethod run_steps(num_steps, callback=None)[source]

Run simulation for specified number of steps.

Parameters:
  • num_steps (int) – Number of time steps to run.

  • callback (callable, optional) – Function called after each time step.

Return type:

None

FrequencyDomainSolver

Base class for frequency-domain solvers (FEM). These solvers solve for fields at specific frequencies.

class prismo.solvers.base.FrequencyDomainSolver(grid)[source]

Base class for frequency-domain solvers (FEM).

Frequency-domain solvers solve for fields at specific frequencies.

abstractmethod solve(frequency)[source]

Solve for fields at a specific frequency.

Parameters:

frequency (float) – Frequency in Hz.

Returns:

Solution fields at the specified frequency.

Return type:

ElectromagneticFields

abstractmethod solve_eigenvalue(num_modes=1)[source]

Solve eigenvalue problem (e.g., for waveguide modes).

Parameters:

num_modes (int) – Number of modes to compute.

Returns:

(eigenvalues, eigenmodes) where eigenmodes is a list of fields.

Return type:

tuple

Solver Implementations

FDTDSolver

Native FDTD (Finite-Difference Time-Domain) solver implementation. This is the default solver and provides high performance with GPU acceleration support.

class prismo.core.solver.FDTDSolver(grid, dt=None, material_arrays=None, backend=None)[source]

High-level FDTD solver combining grid, fields, and updater.

This class provides a convenient interface for running FDTD simulations with automatic time stepping and field management.

Parameters:
  • grid (YeeGrid) – Computational grid.

  • dt (float, optional) – Time step. If None, automatically computed for stability.

  • material_arrays (dict, optional) – Material property arrays.

__init__(grid, dt=None, material_arrays=None, backend=None)[source]

Initialize the solver.

Parameters:

grid (YeeGrid) – The simulation grid.

run(total_time, callback=None)[source]

Run FDTD simulation for specified time.

Parameters:
  • total_time (float) – Total simulation time in seconds.

  • callback (callable, optional) – Function called after each time step: callback(solver, step_num).

Return type:

None

run_steps(num_steps, callback=None)[source]

Run FDTD simulation for specified number of steps.

Parameters:
  • num_steps (int) – Number of time steps to run.

  • callback (callable, optional) – Function called after each time step.

Return type:

None

step(fields=None)[source]

Perform a single FDTD time step.

Parameters:

fields (ElectromagneticFields, optional) – Fields to update. If None, uses internal fields.

Return type:

None

get_fields()[source]

Get the current electromagnetic fields.

Return type:

ElectromagneticFields

get_time_step()[source]

Get the time step used by the solver.

Returns:

Time step in seconds.

Return type:

float

reset()[source]

Reset simulation to initial state.

Return type:

None

get_simulation_info()[source]

Get information about the current simulation state.

Return type:

dict

__repr__()[source]

String representation.

Return type:

str

Example Usage:

from prismo.core import Simulation

# Create simulation with FDTD solver (default)
sim = Simulation(
    size=(10e-6, 5e-6, 0),
    resolution=50e6,
    solver_type="fdtd"  # This is the default
)

# Or create solver directly
from prismo.core.solver import FDTDSolver
from prismo.core.grid import YeeGrid, GridSpec

grid_spec = GridSpec(size=(10e-6, 5e-6, 0), resolution=50e6)
grid = YeeGrid(grid_spec)
solver = FDTDSolver(grid)

MEEPSolver

Wrapper for MIT MEEP FDTD solver. This provides access to MEEP’s advanced features while maintaining compatibility with Prismo’s interface.

Note: MEEP is an optional dependency. Install with:

conda install -c conda-forge pymeeus meep
class prismo.solvers.meep_solver.MEEPSolver(grid, material_arrays=None, backend=None)[source]

MIT MEEP FDTD solver wrapper.

This class wraps MIT MEEP’s FDTD solver, providing the same interface as the native FDTDSolver for seamless integration.

Parameters:
  • grid (YeeGrid) – The simulation grid.

  • material_arrays (dict, optional) – Material property arrays (ε, μ, σ).

  • backend (Backend, optional) – Computational backend to use (MEEP handles its own backend).

__init__(grid, material_arrays=None, backend=None)[source]

Initialize the solver.

Parameters:

grid (YeeGrid) – The simulation grid.

step(fields=None)[source]

Perform a single MEEP time step.

Parameters:

fields (ElectromagneticFields, optional) – Fields to update. If None, uses internal fields.

Return type:

None

run(total_time, callback=None)[source]

Run MEEP simulation for specified time.

Parameters:
  • total_time (float) – Total simulation time in seconds.

  • callback (callable, optional) – Function called after each time step.

Return type:

None

run_steps(num_steps, callback=None)[source]

Run MEEP simulation for specified number of steps.

Parameters:
  • num_steps (int) – Number of time steps to run.

  • callback (callable, optional) – Function called after each time step.

Return type:

None

get_fields()[source]

Get the current electromagnetic fields.

Return type:

ElectromagneticFields

reset()[source]

Reset simulation to initial state.

Return type:

None

get_time_step()[source]

Get the time step used by MEEP.

Returns:

Time step in seconds.

Return type:

float

__repr__()[source]

String representation.

Return type:

str

Example Usage:

from prismo.core import Simulation

# Create simulation with MEEP solver
sim = Simulation(
    size=(10e-6, 5e-6, 0),
    resolution=50e6,
    solver_type="meep"  # Use MEEP solver
)

Note: The MEEP solver wrapper is currently a placeholder implementation. Full integration with MEEP’s geometry and material systems is planned for future releases.

FEMSolver

Finite Element Method (FEM) solver using FEniCS/dolfinx for frequency-domain and eigenvalue electromagnetic problems.

Note: FEniCS is an optional dependency and is not available on PyPI. Install with:

conda install -c conda-forge fenics-dolfinx

Or install from source: https://fenicsproject.org/download/

class prismo.solvers.fem_solver.FEMSolver(grid, geometry=None, materials=None, boundary_conditions=None, backend=None)[source]

Finite Element Method solver for electromagnetic simulations.

This solver uses FEniCS/dolfinx for frequency-domain and eigenvalue problems. It supports PMC and magnetic PML boundary conditions.

Parameters:
  • grid (YeeGrid) – The simulation grid.

  • geometry (Any, optional) – Geometry definition (to be integrated with Prismo geometry system).

  • materials (dict, optional) – Material properties dictionary.

  • boundary_conditions (dict, optional) – Boundary condition specification, e.g., {‘x_min’: ‘pmc’, ‘x_max’: ‘pml’}.

  • backend (Backend, optional) – Computational backend to use.

__init__(grid, geometry=None, materials=None, boundary_conditions=None, backend=None)[source]

Initialize the solver.

Parameters:

grid (YeeGrid) – The simulation grid.

solve(frequency)[source]

Solve for fields at a specific frequency.

Parameters:

frequency (float) – Frequency in Hz.

Returns:

Solution fields at the specified frequency.

Return type:

ElectromagneticFields

solve_eigenvalue(num_modes=1)[source]

Solve eigenvalue problem (e.g., for waveguide modes).

Parameters:

num_modes (int) – Number of modes to compute.

Returns:

(eigenvalues, eigenmodes) where eigenmodes is a list of fields.

Return type:

tuple

step(fields=None)[source]

FEM is frequency-domain, so step() is not applicable.

Use solve() or solve_eigenvalue() instead.

Return type:

None

get_fields()[source]

Get the current electromagnetic fields.

Return type:

ElectromagneticFields

reset()[source]

Reset simulation to initial state.

Return type:

None

get_time_step()[source]

FEM is frequency-domain, so time step is not applicable.

Returns:

Returns 0.0 as FEM doesn’t use time stepping.

Return type:

float

__repr__()[source]

String representation.

Return type:

str

Example Usage:

from prismo.core import Simulation

# Create simulation with FEM solver
sim = Simulation(
    size=(10e-6, 5e-6, 0),
    resolution=50e6,
    solver_type="fem"  # Use FEM solver
)

# For frequency-domain problems
fields = sim.solver.solve(frequency=193e12)  # 1550 nm

# For eigenvalue problems (e.g., waveguide modes)
eigenvalues, eigenmodes = sim.solver.solve_eigenvalue(num_modes=3)

Note: The FEM solver is currently a placeholder implementation. Full integration with FEniCS mesh generation, weak form assembly, and boundary conditions is planned for future releases.

Choosing a Solver

  • FDTD (default): Best for time-domain simulations, transient analysis, and broadband frequency sweeps. Supports GPU acceleration.

  • MEEP: Useful when you need MEEP’s specific features or want to compare results with MEEP simulations.

  • FEM: Best for frequency-domain problems, eigenvalue analysis (waveguide modes), and problems requiring unstructured meshes.

Solver Selection in Simulation

The solver type is specified when creating a Simulation:

sim = Simulation(
    size=(10e-6, 5e-6, 0),
    resolution=50e6,
    solver_type="fdtd"  # Options: "fdtd", "meep", "fem"
)

All solvers provide the same interface, so you can switch between them without changing your simulation code (except for frequency-domain specific methods in FEM solver).