Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,23 @@ related areas on our [careers page](https://deepmind.com/careers/).
For a full list of our publications, please see
https://deepmind.com/research/publications/

## 📊 Datasets and Resources

**📋 [Complete Resource Index](open-source-resources.md)** - Comprehensive list of all datasets, code, and external resources

### Quick Access to Major Datasets:
- **[MeshGraphNets](meshgraphnets/)** - CFD and cloth simulation datasets
- **[RL Unplugged](rl_unplugged/)** - Offline reinforcement learning benchmarks
- **[WikiGraphs](wikigraphs/)** - Wikipedia-Knowledge Graph paired dataset
- **[Learning to Simulate](learning_to_simulate/)** - Physics simulation datasets
- **[Nowcasting](nowcasting/)** - UK precipitation radar data

**🔗 External Repositories:**
- [DeepMind Lab](https://github.com/deepmind/lab) - 3D learning environments
- [OpenSpiel](https://github.com/deepmind/open_spiel) - Multi-agent RL
- [dm-haiku](https://github.com/deepmind/dm-haiku) - JAX neural networks
- [Acme](https://github.com/deepmind/acme) - RL research framework

## Projects

* [Magnetic control of tokamak plasmas through deep reinforcement learning](fusion_tcv), Nature 2022
Expand Down
2 changes: 1 addition & 1 deletion gated_linear_networks/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
absl-py==0.10.0
aiohttp==3.6.2
aiohttp==3.12.14
astunparse==1.6.3
async-timeout==3.0.1
attrs==20.2.0
Expand Down
16 changes: 16 additions & 0 deletions learning_to_simulate/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ Download dataset (e.g. WaterRamps):
mkdir -p /tmp/datasets
bash ./learning_to_simulate/download_dataset.sh WaterRamps /tmp/datasets

**Cross-platform alternatives:**

For Python (recommended):

python ./learning_to_simulate/download_dataset.py WaterRamps /tmp/datasets

For Windows PowerShell:

.\learning_to_simulate\download_dataset.ps1 -DatasetName "WaterRamps" -OutputDir "/tmp/datasets"

Train a model:

mkdir -p /tmp/models
Expand Down Expand Up @@ -95,6 +105,12 @@ Where:

The provided script `./download_dataset.sh` may be used to download all files from each dataset into a folder given its name.

**Additional download tools:**
* `download_dataset.py`: Cross-platform Python script with progress bars, resume capability, and better error handling
* `download_dataset.ps1`: Windows PowerShell script for Windows users who prefer native PowerShell

These tools address common issues with dataset downloading across different operating systems and provide improved user experience.

An additional smaller dataset `WaterDropSample`, which includes only the first two trajectories of `WaterDrop` for each split, is provided for debugging purposes.


Expand Down
65 changes: 65 additions & 0 deletions learning_to_simulate/download_dataset.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# PowerShell script for downloading Learning to Simulate datasets
# Usage: .\download_dataset.ps1 -DatasetName "WaterDrop" -OutputDir ".\datasets"

param(
[Parameter(Mandatory=$true)]
[string]$DatasetName,

[Parameter(Mandatory=$true)]
[string]$OutputDir
)

function Download-FileWithProgress {
param(
[string]$Url,
[string]$FilePath
)

try {
Write-Host "📥 Downloading $(Split-Path $FilePath -Leaf)..." -ForegroundColor Blue

# Use Invoke-WebRequest with progress
$response = Invoke-WebRequest -Uri $Url -OutFile $FilePath -PassThru

if (Test-Path $FilePath) {
$fileSize = (Get-Item $FilePath).Length
Write-Host "✅ Downloaded $(Split-Path $FilePath -Leaf) ($([math]::Round($fileSize/1MB, 2)) MB)" -ForegroundColor Green
return $true
}
return $false
}
catch {
Write-Host "❌ Error downloading $(Split-Path $FilePath -Leaf): $($_.Exception.Message)" -ForegroundColor Red
return $false
}
}

# Main script
$baseUrl = "https://storage.googleapis.com/learning-to-simulate-complex-physics/Datasets/$DatasetName/"
$files = @('metadata.json', 'train.tfrecord', 'valid.tfrecord', 'test.tfrecord')

# Create output directory
$datasetDir = Join-Path $OutputDir $DatasetName
if (!(Test-Path $datasetDir)) {
New-Item -ItemType Directory -Path $datasetDir -Force | Out-Null
}

Write-Host "🔄 Downloading dataset '$DatasetName' to $datasetDir" -ForegroundColor Yellow

$successCount = 0
foreach ($filename in $files) {
$url = $baseUrl + $filename
$filepath = Join-Path $datasetDir $filename

if (Download-FileWithProgress -Url $url -FilePath $filepath) {
$successCount++
}
}

Write-Host "`n🎉 Download complete! $successCount/$($files.Count) files downloaded successfully." -ForegroundColor Cyan

if ($successCount -eq $files.Count) {
Write-Host "✅ All files downloaded to: $datasetDir" -ForegroundColor Green
} else {
Write-Host "⚠️ Some downloads failed. Check your internet connection and try again." -ForegroundColor Yellow
}
157 changes: 157 additions & 0 deletions learning_to_simulate/download_dataset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#!/usr/bin/env python3
"""
Cross-platform dataset downloader for Learning to Simulate project.

This script provides a robust, cross-platform alternative to the bash script
for downloading datasets. It includes progress bars, resume capability, and
better error handling.

Usage:
python download_dataset.py <dataset_name> <output_dir>

Example:
python download_dataset.py WaterDrop ./datasets
python download_dataset.py Sand ./datasets
"""

import os
import sys
import argparse
import requests
from pathlib import Path
from tqdm import tqdm


def download_file(url, filepath, resume=True):
"""Download a file with progress bar and resume capability."""
headers = {}
mode = 'wb'

# Check if file exists and get its size for resume
if resume and filepath.exists():
existing_size = filepath.stat().st_size
headers['Range'] = f'bytes={existing_size}-'
mode = 'ab'
print(f"Resuming download from byte {existing_size}")

try:
response = requests.get(url, headers=headers, stream=True)
response.raise_for_status()

# Get total file size
total_size = int(response.headers.get('content-length', 0))
if 'content-range' in response.headers:
# If resuming, adjust total size
total_size = int(response.headers['content-range'].split('/')[-1])

# Create progress bar
progress_bar = tqdm(
total=total_size,
unit='B',
unit_scale=True,
desc=filepath.name
)

# If resuming, set initial position
if mode == 'ab' and filepath.exists():
progress_bar.update(filepath.stat().st_size)

# Download file
with open(filepath, mode) as f:
for chunk in response.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
progress_bar.update(len(chunk))

progress_bar.close()
print(f"✅ Successfully downloaded {filepath.name}")
return True

except requests.exceptions.RequestException as e:
print(f"❌ Error downloading {filepath.name}: {e}")
return False


def download_dataset(dataset_name, output_dir):
"""Download all files for a specific dataset."""
base_url = f"https://storage.googleapis.com/learning-to-simulate-complex-physics/Datasets/{dataset_name}/"
files = ['metadata.json', 'train.tfrecord', 'valid.tfrecord', 'test.tfrecord']

# Create output directory
dataset_dir = Path(output_dir) / dataset_name
dataset_dir.mkdir(parents=True, exist_ok=True)

print(f"🔄 Downloading dataset '{dataset_name}' to {dataset_dir}")

success_count = 0
for filename in files:
url = base_url + filename
filepath = dataset_dir / filename

print(f"\n📥 Downloading {filename}...")
if download_file(url, filepath):
success_count += 1
else:
print(f"⚠️ Failed to download {filename}")

print(f"\n🎉 Download complete! {success_count}/{len(files)} files downloaded successfully.")

if success_count == len(files):
print(f"✅ All files downloaded to: {dataset_dir}")
return True
else:
print(f"⚠️ Some downloads failed. Check your internet connection and try again.")
return False


def main():
parser = argparse.ArgumentParser(
description="Download datasets for Learning to Simulate project",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Available datasets:
- WaterDrop
- Sand
- Goop
- MultiMaterial
- RandomFloor
- Continuous
- WaterDropSample
- SandSample
- GoopSample
- MultiMaterialSample
- RandomFloorSample
- ContinuousSample

Examples:
python download_dataset.py WaterDrop ./datasets
python download_dataset.py Sand /tmp/learning_to_simulate
"""
)

parser.add_argument('dataset_name', help='Name of the dataset to download')
parser.add_argument('output_dir', help='Output directory to save the dataset')

args = parser.parse_args()

# Validate dataset name
valid_datasets = [
'WaterDrop', 'Sand', 'Goop', 'MultiMaterial', 'RandomFloor', 'Continuous',
'WaterDropSample', 'SandSample', 'GoopSample', 'MultiMaterialSample',
'RandomFloorSample', 'ContinuousSample'
]

if args.dataset_name not in valid_datasets:
print(f"⚠️ Warning: '{args.dataset_name}' is not in the list of known datasets.")
print(f"Valid datasets: {', '.join(valid_datasets)}")
response = input("Continue anyway? (y/N): ")
if response.lower() != 'y':
return

# Download dataset
success = download_dataset(args.dataset_name, args.output_dir)
sys.exit(0 if success else 1)


if __name__ == "__main__":
main()
21 changes: 10 additions & 11 deletions meshgraphnets/core_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,23 +52,22 @@ def _update_node_features(self, node_features, edge_sets):
return self._model_fn()(tf.concat(features, axis=-1))

def _build(self, graph):
"""Applies GraphNetBlock and returns updated MultiGraph."""
"""Applies GraphNetBlock and returns updated MultiGraph per MeshGraphNets paper."""

# apply edge functions
# Apply edge functions with immediate residual connections
new_edge_sets = []
for edge_set in graph.edge_sets:
updated_features = self._update_edge_features(graph.node_features,
edge_set)
# Compute edge update
edge_update = self._update_edge_features(graph.node_features, edge_set)
# Apply residual connection immediately
updated_features = edge_set.features + edge_update
new_edge_sets.append(edge_set._replace(features=updated_features))

# apply node function
new_node_features = self._update_node_features(graph.node_features,
new_edge_sets)
# Apply node function with residual connection
node_update = self._update_node_features(graph.node_features, new_edge_sets)
# Apply residual connection to node features
new_node_features = graph.node_features + node_update

# add residual connections
new_node_features += graph.node_features
new_edge_sets = [es._replace(features=es.features + old_es.features)
for es, old_es in zip(new_edge_sets, graph.edge_sets)]
return MultiGraph(new_node_features, new_edge_sets)


Expand Down
Loading