Skip to main content

Wave simulations

Project description

waver

License PyPI Python Version tests codecov

Run simulations of the wave equation in nD on grids of variable speed in Python. This library owes a lot of its design and approach to the fdtd library, a Python 3D electromagnetic FDTD simulator.

This package allows for a fair amount of customization over your wave simulation. You can

  • specify the size and spacing of the grid
  • specify the time step for the simulation, which will be checked to ensure stability of the simulation
  • specify the duration of the simulation
  • setting a variable speed array (one value per grid point) to allow for "objects" in your environment
  • set the source of the wave, which can be a point, line, or any (n-1)D subarray
  • record the wave with a detector, which can be the full grid, the full boundary, or a particular boundary
  • use convenience methods to run many simulations with different sources on the same grid and detector combination

You can use napari, a multi-dimensional image viewer for Python, to allow for easy visualization of the detected wave. Some functionality is also available as a napari plugin to allow for running simulations from a graphical user interface.

Results can look like

https://user-images.githubusercontent.com/6531703/128283012-a784ec06-4df9-4ddf-bf4f-e21b927fe4a3.mov


Installation

You can install waver via pip:

pip install waver

Usage

Convenience Methods

The most convenient way to use waver is to use one of two convenience methods that will create and run a simulation for you and return the results.

The first method run_single_source allows you to run a single simulation with a single source on one grid and record the results using a detector. For example

from waver.simulation import run_single_source

single_sim_params = {
    'size': (12.8e-3, 12.8e-3),
    'spacing': 100e-6,
    'duration': 80e-6,
    'min_speed': 343,
    'max_speed': 686,
    'speed': 686,
    'time_step': 50e-9,
    'temporal_downsample': 2,
    'location': (6.4e-3, 6.4e-3),
    'period': 5e-6,
    'ncycles':1,
}

detected_wave, speed_grid = run_single_source(**single_sim_params)

The second method run_multiple_sources allows you to run multiple simulations with multiple sources on the same grid and with the same detector and return the results. For example

from waver.simulation import run_multiple_sources

multi_sim_params = {
    'size': (12.8e-3, 12.8e-3),
    'spacing': 100e-6,
    'duration': 80e-6,
    'min_speed': 343,
    'max_speed': 686,
    'speed': 686,
    'time_step': 50e-9,
    'temporal_downsample': 2,
    'sources': [{
        'location': (6.4e-3, 6.4e-3),
        'period': 5e-6,
        'ncycles':1,
    }]
}

detected_wave, speed_grid = run_multiple_sources(**multi_sim_params)

The main difference between these two methods is that run_multiple_sources takes a sources parameter which takes a list of dictionaries with keys corresponding to source related keyword arguments found in run_single_source.

Visualization

If you want to quickly visualize the results of run_multiple_sources, you can use the run_and_visualize command which will run the simulation and then launch napari with the results, as seen in examples/2D/point_source.py

from waver.datasets import run_and_visualize

run_and_visualize(**multi_sim_params)

Datasets

If you want to run simulations with on many different speed grids you can use the generate_simulation_dataset method as a convenience. The results will be saved to a zarr file of your chosing. You can then use the load_simulation_dataset to load the dataset.

from waver.datasets import generate_simulation_dataset

# Define root path for simulation
path = './simulation_dataset.zarr'
runs = 5

# Define a simulation, 12.8mm, 100um spacing
dataset_sim_params = {
    'size': (12.8e-3, 12.8e-3),
    'spacing': 100e-6,
    'duration': 80e-6,
    'min_speed': 343,
    'max_speed': 686,
    'speed': 'mixed_random_ifft',
    'time_step': 50e-9,
    'sources': [{
        'location': (None, 0),
        'period': 5e-6,
        'ncycles':1,
    }],
    'temporal_downsample': 2,
    'boundary': 1,
    'edge': 1,
}

# Run and save simulation
generate_simulation_dataset(path, runs, **dataset_sim_params)

The generate_simulation_dataset allows the speed to be a string that will specify a particular method of randomly generating speed values for the simulation grid.

The Simulation Object

If you'd like to understand in a little bit more detail how a simulation is defined then you might want to use the unerlying simulation object Simulation and manually set key objects like the Source and Detector. A full example of this is as follows

# Create a simulation
sim = Simulation(size=size, spacing=spacing, max_speed=max_speed, time_step=time_step)

# Set speed array
sim.set_speed(speed=speed, min_speed=min_speed, max_speed=max_speed)

# Add source
sim.add_source(location=location, period=period, ncycles=ncycles, phase=phase)

# Add detector grid
sim.add_detector(spatial_downsample=spatial_downsample,
                    boundary=boundary, edge=edge)

# Run simulation
sim.run(duration=duration, temporal_downsample=temporal_downsample, progress=progress, leave=leave)

# Print simulation wave and speed data
print('wave: ', sim.detected_wave)
print('speed: ', sim.grid_speed)

Note these steps are done inside the run_single_source method for you as a convenience.

Known Limitations

A perfectly matched layer boundary has recently been added, but might not perform well under all conditions. Additional contributions would be welcome here.

Right now the simulations are quite slow. I'd like to add a JAX backend, but havn't done so yet. Contributions would be welcome.

Contributing

Contributions are very welcome. Tests can be run with tox, please ensure the coverage at least stays the same before you submit a pull request.

License

Distributed under the terms of the BSD-3 license, "waver" is free and open source software

Issues

If you encounter any problems, please file an issue along with a detailed description.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

waver-0.0.4.tar.gz (34.3 kB view details)

Uploaded Source

Built Distribution

waver-0.0.4-py3-none-any.whl (23.4 kB view details)

Uploaded Python 3

File details

Details for the file waver-0.0.4.tar.gz.

File metadata

  • Download URL: waver-0.0.4.tar.gz
  • Upload date:
  • Size: 34.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.6.4 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.1 CPython/3.9.6

File hashes

Hashes for waver-0.0.4.tar.gz
Algorithm Hash digest
SHA256 e1447a6f083d139ec75e55598dc3300f65cd3baa012568ec1cc79e7de70f6860
MD5 3785c4197cf1f3f5199248ee803f9705
BLAKE2b-256 69e1a5a53d96295c541933b204f5bfcdfd1d6ca76ef9ce372af820c1a8bba147

See more details on using hashes here.

File details

Details for the file waver-0.0.4-py3-none-any.whl.

File metadata

  • Download URL: waver-0.0.4-py3-none-any.whl
  • Upload date:
  • Size: 23.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.6.4 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.1 CPython/3.9.6

File hashes

Hashes for waver-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 ea991cf7646fe56f5395e2bbae7c7fca31e0a7928f3ab4b9b5e69dbf4f2afa4f
MD5 9e0c73d4cd7a8f2ae64903eeac54a80c
BLAKE2b-256 3ddab933969d341c97c3f1c80d63843e8a5d15c76b33d9b171db0c526f801f23

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page