generated from gpauloski/python-template
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #186 from proxystore/issue-140-rebased
Add physics app based on Globus Compute golf demo
- Loading branch information
Showing
8 changed files
with
664 additions
and
1 deletion.
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
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,24 @@ | ||
# Physics Simulations | ||
|
||
This application is modified from the [Globus Compute Golf Demo](https://github.com/globus-labs/globus-compute-golf-demo){target=_blank}. | ||
|
||
Simulates the physics of golf balls landing on a randomly generated golf green using perlin noise for terrain generation and [pybullet3](https://github.com/bulletphysics/bullet3){target=_blank} for physics simulations. | ||
This application is embarrassingly parallel---every ball is simulated in its own task. | ||
|
||
## Installation | ||
|
||
This application requires numpy, matplotlib, scipy, and pybullet3 which can be installed automatically when installing the TaPS package. | ||
```bash | ||
pip install -e .[physics] | ||
``` | ||
|
||
## Example | ||
|
||
The following command simulated 32 balls where each ball is simulated in a separate task. | ||
```bash | ||
python -m taps.run --app physics --app.simulations 32 --engine.executor process-pool | ||
``` | ||
The initial and final ball positions are plotted and saved to `{run_dir}/images/`. | ||
By default, the simulations run at "real time". | ||
I.e., sleeps are added at each timestep to ensure timesteps take as long as they would in real life. | ||
This can be disabled with `--app.real-time false`. |
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
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
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,88 @@ | ||
from __future__ import annotations | ||
|
||
from typing import Literal | ||
from typing import Optional | ||
|
||
from pydantic import Field | ||
|
||
from taps.apps import App | ||
from taps.apps import AppConfig | ||
from taps.plugins import register | ||
|
||
|
||
@register('app') | ||
class PhysicsConfig(AppConfig): | ||
"""Physics application configuration.""" | ||
|
||
name: Literal['physics'] = Field( | ||
'physics', | ||
description='Application name.', | ||
) | ||
simulations: int = Field(description='Number of parallel simulations.') | ||
ball_diameter: float = Field( | ||
0.2, | ||
description='Golf ball diameter in meters.', | ||
) | ||
ball_mass: float = Field(0.05, description='Golf ball mass in kilograms.') | ||
tick_rate: int = Field(240, description='Simulation steps per seconds.') | ||
total_time: int = Field(10, description='Simulation runtime in seconds.') | ||
real_time: bool = Field(True, description='Simulate at real time.') | ||
seed: Optional[int] = Field(None, description='Random seed.') # noqa: UP007 | ||
terrain_width: int = Field( | ||
20, | ||
description='Terrain width/length in meters.', | ||
) | ||
terrain_height: int = Field(3, description='Terrain max height in meters.') | ||
terrain_resolution: int = Field( | ||
10, | ||
description='Terrain vertices per meter.', | ||
) | ||
terrain_scale: float = Field( | ||
10.0, | ||
description='Noise map scale (how far away map is viewed from).', | ||
) | ||
terrain_octaves: int = Field(3, description='Detail level in noise map.') | ||
terrain_persistence: float = Field( | ||
0.2, | ||
description='Octave contributions (amplitude).', | ||
) | ||
terrain_lacunarity: float = Field( | ||
2.0, | ||
description='Detail added/removed at each octave (frequency).', | ||
) | ||
terrain_filter_size: int = Field( | ||
2, | ||
description='Terrain smoothing filter size.', | ||
) | ||
|
||
def get_app(self) -> App: | ||
"""Create an application instance from the config.""" | ||
from taps.apps.physics import PhysicsApp | ||
from taps.apps.physics import SimulationConfig | ||
from taps.apps.physics import TerrainConfig | ||
|
||
terrain = TerrainConfig( | ||
width=self.terrain_width, | ||
height=self.terrain_height, | ||
resolution=self.terrain_resolution, | ||
scale=self.terrain_scale, | ||
octaves=self.terrain_octaves, | ||
persistence=self.terrain_persistence, | ||
lacunarity=self.terrain_lacunarity, | ||
filter_size=self.terrain_filter_size, | ||
) | ||
|
||
simulation = SimulationConfig( | ||
ball_diameter=self.ball_diameter, | ||
ball_mass=self.ball_mass, | ||
tick_rate=self.tick_rate, | ||
total_time=self.total_time, | ||
real_time=self.real_time, | ||
) | ||
|
||
return PhysicsApp( | ||
num_simulations=self.simulations, | ||
terrain=terrain, | ||
simulation=simulation, | ||
seed=self.seed, | ||
) |
Oops, something went wrong.