Skip to content

Add Differentiable Physics: Mass-Spring System example #1332

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

AbhiLegend
Copy link

Summary

This PR adds a simple Differentiable Physics example implementing a Mass-Spring System using PyTorch.

  • Particles are connected by springs and evolve under the influence of spring forces and gravity.
  • The system is fully differentiable, allowing optimization of particle positions via gradient descent.
  • Semi-implicit Euler integration is used for better numerical stability.
  • The example does not require any external dependencies beyond PyTorch.

Files Added

  • examples/differentiable_physics/mass_spring.py
  • examples/differentiable_physics/README.md
  • examples/differentiable_physics/requirements.txt

Features

  • Training mode: Optimize particle positions to match a target configuration.
  • Evaluation mode: Forward simulate without optimization.
  • Particle 0 is pinned at (0,0) to prevent system drift.
  • Gravity strength is customizable.
  • Fully differentiable simulation with simple, clean code structure.

Testing

  • Verified mass_spring.py runs successfully in both train and eval modes.
  • Added a bash function to run_python_examples.sh for CI testing (5 epochs, 3 steps for quick test).
  • Local testing was performed with Git Bash on Windows (python -m uv is used for compatibility).
  • Confirmed loss convergence and expected particle behavior.

Notes

  • Minor residual errors are expected due to the elasticity of springs and gravitational force.
  • Example is designed to prioritize educational clarity and maintain a low dependency footprint.

Thank you for reviewing!

Copy link

netlify bot commented Apr 29, 2025

Deploy Preview for pytorch-examples-preview canceled.

Name Link
🔨 Latest commit f1a806e
🔍 Latest deploy log https://app.netlify.com/projects/pytorch-examples-preview/deploys/682ce2476390c90008af215c

@AbhiLegend
Copy link
Author

@msaroufim I have just updated the example with PR, request you to check if it fits in the "differentiable physics" section

@AbhiLegend AbhiLegend mentioned this pull request May 1, 2025
12 tasks
@msaroufim
Copy link
Member

msaroufim commented May 13, 2025

I don't see any testing changes that were made, you probably want to update this file https://github.com/pytorch/examples/blob/main/run_python_examples.sh

I do also think it's worth making some visualization for the work and putting it in the main README

@AbhiLegend AbhiLegend requested a review from msaroufim as a code owner May 13, 2025 22:00
@AbhiLegend
Copy link
Author

I don't see any testing changes that were made, you probably want to update this file https://github.com/pytorch/examples/blob/main/run_python_examples.sh

I do also think it's worth making some visualization for the work and putting it in the main README

I have updated the PR.Thanks

@AbhiLegend
Copy link
Author

I don't see any testing changes that were made, you probably want to update this file https://github.com/pytorch/examples/blob/main/run_python_examples.sh

I do also think it's worth making some visualization for the work and putting it in the main README

Updated all the changes.

@AbhiLegend
Copy link
Author

@msaroufim , can you please review the PR? Please lemme know if something else is required for this example. Thanks :)

@@ -0,0 +1 @@
torch
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @AbhiLegend,

matplotlib dependency is missing.



def train(args):
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to use accelerator API here

Suggested change
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
device = torch.accelerator.current_accelerator() if torch.accelerator.is_available() else torch.device("cpu")
print(f"Using device: {device}")


- Python 3.8+
- PyTorch

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

matplotlib is missing

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add

Suggested change
pip install -r requirements.txt

to be consistent with other examples



def evaluate(args):
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
device = torch.accelerator.current_accelerator() if torch.accelerator.is_available() else torch.device("cpu")
print(f"Using device: {device}")

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jafraustro Final update:

  • Added accelerator code to mass_spring.py
  • requirements.txt updated with matplotlib dependency
    Ready for review

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AbhiLegend
Copy link
Author

@jafraustro I made the changes.

Copy link
Contributor

@jafraustro jafraustro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

#
# To test examples on CUDA accelerator, run as:
# USE_CUDA=True ./run_python_examples.sh
# To run specific examples:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these changes be better moved to separate PR. These are unrelated to the example being added and some are arguable.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made it to as it was.

#
# To test examples on hardware accelerator (CUDA, MPS, XPU, etc.), run as:
# USE_ACCEL=True ./run_python_examples.sh
# NOTE: USE_ACCEL relies on torch.accelerator API and not all examples are converted
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why a note was dropped? it highlights the planned work which is not yet done and I believe is helpful for maintenance.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed

#
# Script requires uv to be installed. When executed, script will install prerequisites from
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This highlights the convention that each example is expected to have requirements.txt and discusses the behavior. Can this, please, be restored?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

restored to original

#
# To force script to create virtual environment for each example, run as:
# To force venv per example:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

venv might be confused with the type of virtual environment. I would prefer to use full naming "virtual environment per example".

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

# VIRTUAL_ENV=".venv" ./run_python_examples.sh
# Script will remove environments it creates in a teardown step after execution of each example.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I don't see why this needs to be dropped. That's explicit clarification of the behavior. It's helpful.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rectified.


BASE_DIR="$(pwd)/$(dirname $0)"
source $BASE_DIR/utils.sh

# TODO: Leave only USE_ACCEL and drop USE_CUDA once all examples will be converted
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This work is not completed. Why drop the TODO?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made the changes.

echo "training..."
uv run train.py --epochs 1 --dev_every 1 --no-bidirectional --dry-run || error "couldn't train snli"
}

function fx() {
# uv run custom_tracer.py || error "fx custom tracer has failed" UnboundLocalError: local variable 'tabulate' referenced before assignment
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cleanup, here and in few places below. But someone needs to clarify whether this can be dropped or not. In any case - better not to mix up such changes with the new example.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

Comment on lines 154 to 156
pushd differentiable_physics
python -m uv run mass_spring.py --mode train --epochs 5 --steps 3 || error "differentiable_physics example failed"
popd
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason to use different pattern for tests just for this example? One potential problem - python might not actually exist on the system as typically you get python3 and need to create a symbolic link to it in one way or another.

Suggested change
pushd differentiable_physics
python -m uv run mass_spring.py --mode train --epochs 5 --steps 3 || error "differentiable_physics example failed"
popd
uv run mass_spring.py --mode train --epochs 5 --steps 3 || error "differentiable_physics example failed"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rectified it.

@AbhiLegend
Copy link
Author

@dvrogozh made the changes as perrequest.

exit 1
fi

fi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add the empty line at the end

@@ -154,6 +154,9 @@ function vision_transformer() {

function word_language_model() {
uv run main.py --epochs 1 --dry-run $CUDA_FLAG --mps || error "word_language_model failed"
for model in "RNN_TANH" "RNN_RELU" "LSTM" "GRU" "Transformer"; do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is unrelated with the PR. Remove. Or just rebase on top of latest main.

@@ -0,0 +1,3 @@
torch
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Due to usage of torch.accelerator:

Suggested change
torch
torch>=2.6

@AbhiLegend
Copy link
Author

@dvrogozh @jafraustro I have made the changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants