Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8634c78
Phase 1: ETACEPotential with AtomsCalculators interface
jameskermode Dec 23, 2025
ccf925a
Phase 2: SiteEnergyModel interface and StackedCalculator
jameskermode Dec 23, 2025
657500a
Refactor StackedCalculator to separate file
jameskermode Dec 23, 2025
07b3641
Phase 5: Training assembly functions for ETACEPotential
jameskermode Dec 23, 2025
e4c661f
Optimize StackedCalculator with @generated functions
jameskermode Dec 23, 2025
5da6c25
Add benchmark scripts for ACE vs ETACE performance comparison
jameskermode Dec 23, 2025
2650538
Update plan with implementation progress and benchmark results
jameskermode Dec 23, 2025
d3b9c0c
Extend training assembly tests and add ACEfit integration
jameskermode Dec 23, 2025
e81a708
Add ETModels to docs and ETACE silicon integration test
jameskermode Dec 23, 2025
f3519ff
Optimize energy_forces_virial_basis with pre-allocation
jameskermode Dec 23, 2025
99f2d98
Fix ETACE integration test: compare many-body only
jameskermode Dec 23, 2025
c64168b
Refactor et_calculators.jl and stackedcalc.jl to reduce duplication
jameskermode Dec 24, 2025
40bf060
Unify ETACEPotential as type alias for WrappedSiteCalculator
jameskermode Dec 24, 2025
491b7ba
Update development plan: unified architecture (remove E0Model)
jameskermode Dec 30, 2025
389fdd1
Refactor to unified WrappedSiteCalculator (Phase 6.1-6.3)
jameskermode Dec 30, 2025
feff6a6
Add convert2et_full and parameter copying utilities (Phase 6.4-6.5)
jameskermode Dec 30, 2025
16f5ce3
Update tests for unified WrappedSiteCalculator (Phase 6.6)
jameskermode Dec 30, 2025
bee2636
Fix ETOneBody.site_grads to return consistent interface
jameskermode Dec 30, 2025
146cae9
Fix test suite issues: project activation and ETOneBody interface
jameskermode Dec 30, 2025
9af1174
Fix ET ACE and ET Pair test failures
jameskermode Dec 31, 2025
7e28b05
Fix parameter paths in convert2et_full and add full model benchmark
jameskermode Dec 31, 2025
e2bd3f3
Improve memory efficiency in ETPairModel site_grads
jameskermode Dec 31, 2025
41378df
Update EquivariantTensors to 0.4.2 and improve ET pair memory efficiency
jameskermode Dec 31, 2025
42d6b08
Revert et_pair.jl to Zygote-based site_grads and fix et_ace.jl API
jameskermode Dec 31, 2025
00e7c2b
Add GPU benchmark script and LuxCUDA test dependency
jameskermode Dec 31, 2025
d377f4a
Update development plan with completed status
jameskermode Dec 31, 2025
e609e24
Add training assembly support for ETPairModel and ACEfit integration
jameskermode Dec 31, 2025
e147496
Add comprehensive tests for training assembly of ETPairPotential, ETO…
jameskermode Dec 31, 2025
86f5856
Address PR #313 feedback: ET 0.4.3 compat and site_grads type stability
jameskermode Jan 1, 2026
1e22042
update plan
jameskermode Jan 2, 2026
91fd433
Address PR #313 review feedback and fix ETOneBody issues
jameskermode Jan 4, 2026
f10f833
Add ETACE models tutorial example
jameskermode Jan 5, 2026
504b995
Add ETACE tutorial to documentation
jameskermode Jan 5, 2026
4971a56
Add missing dependencies to docs/Project.toml
jameskermode Jan 5, 2026
10a6866
Fix Literate.jl inline comment parsing in ETACE tutorial
jameskermode Jan 5, 2026
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
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ ConcreteStructs = "0.2.3"
DecoratedParticles = "0.1.3"
DynamicPolynomials = "0.6"
EmpiricalPotentials = "0.2"
EquivariantTensors = "0.4"
EquivariantTensors = "0.4.3"
ExtXYZ = "0.2.0"
Folds = "0.2"
ForwardDiff = "0.10, 1"
Expand All @@ -79,7 +79,7 @@ OffsetArrays = "1"
Optim = "1"
Optimisers = "0.3.4, 0.4"
OrderedCollections = "1"
Polynomials4ML = "0.5.6"
Polynomials4ML = "0.5"
PrettyTables = "1.3, 2"
Reexport = "1"
Roots = "2"
Expand Down
198 changes: 198 additions & 0 deletions benchmark/benchmark_full_model.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
# Benchmark: Full model (1+2+many body) with StackedCalculator
# Compares ACE CPU vs ETACE CPU vs ETACE GPU for energy and forces

using ACEpotentials
M = ACEpotentials.Models
ETM = ACEpotentials.ETModels

import EquivariantTensors as ET
import AtomsCalculators
using StaticArrays, Lux, Random, LuxCore, LinearAlgebra
using AtomsBase, AtomsBuilder, Unitful
using BenchmarkTools
using Printf

# GPU detection
dev = identity
has_cuda = false

try
using CUDA
if CUDA.functional()
@info "Using CUDA"
CUDA.versioninfo()
global has_cuda = true
global dev = cu
else
@info "CUDA is not functional"
end
catch e
@info "Couldn't load CUDA: $e"
end

if !has_cuda
@info "No GPU available. Using CPU only."
end

rng = Random.MersenneTwister(1234)

# Build models with E0s and pair potential enabled
elements = (:Si, :O)
level = M.TotalDegree()
max_level = 8
order = 2
maxl = 4

rin0cuts = M._default_rin0cuts(elements)
rin0cuts = (x -> (rin = x.rin, r0 = x.r0, rcut = 5.5)).(rin0cuts)

# E0s for one-body
E0s = Dict(:Si => -158.54496821, :O => -2042.0330099956639)

model = M.ace_model(; elements = elements, order = order,
Ytype = :solid, level = level, max_level = max_level,
maxl = maxl, pair_maxn = max_level,
rin0cuts = rin0cuts,
init_WB = :glorot_normal, init_Wpair = :glorot_normal,
pair_learnable = true, # Keep learnable for ET conversion
E0s = E0s)

ps, st = Lux.setup(rng, model)

# Create old ACE calculator (full model with E0s and pair)
ace_calc = M.ACEPotential(model, ps, st)

# Convert to full ETACE with StackedCalculator
et_calc = ETM.convert2et_full(model, ps, st)

rcut = maximum(a.rcut for a in model.pairbasis.rin0cuts)

# Function to create system of given size
function make_system(n_repeat)
sys = AtomsBuilder.bulk(:Si, cubic=true) * n_repeat
rattle!(sys, 0.1u"Å")
AtomsBuilder.randz!(sys, [:Si => 0.5, :O => 0.5])
return sys
end

# Benchmark configurations
configs = [
(2, 2, 2), # 64 atoms
(3, 3, 2), # 144 atoms
(4, 4, 2), # 256 atoms
(4, 4, 4), # 512 atoms
(5, 5, 4), # 800 atoms
]

println()
println("=" ^ 90)
println("BENCHMARK: Full Model (1+2+many body) - ACE vs ETACE StackedCalculator")
println("=" ^ 90)
println()

# --- ENERGY BENCHMARK ---
println("### ENERGY ###")
println()

if has_cuda
println("| Atoms | Edges | ACE CPU (ms) | ETACE CPU (ms) | ETACE GPU (ms) | CPU Speedup | GPU Speedup |")
println("|-------|---------|--------------|----------------|----------------|-------------|-------------|")
else
println("| Atoms | Edges | ACE CPU (ms) | ETACE CPU (ms) | CPU Speedup |")
println("|-------|---------|--------------|----------------|-------------|")
end

for cfg in configs
sys = make_system(cfg)
natoms = length(sys)

# Count edges
G = ET.Atoms.interaction_graph(sys, rcut * u"Å")
nedges = length(G.edge_data)

# Warmup ACE
_ = AtomsCalculators.potential_energy(sys, ace_calc)

# Warmup ETACE CPU
_ = AtomsCalculators.potential_energy(sys, et_calc)

# Benchmark ACE CPU
t_ace = @belapsed AtomsCalculators.potential_energy($sys, $ace_calc) samples=5 evals=3
t_ace_ms = t_ace * 1000

# Benchmark ETACE CPU
t_etace_cpu = @belapsed AtomsCalculators.potential_energy($sys, $et_calc) samples=5 evals=3
t_etace_cpu_ms = t_etace_cpu * 1000

cpu_speedup = t_ace_ms / t_etace_cpu_ms

if has_cuda
# For GPU we need to handle the StackedCalculator with GPU-capable models
# TODO: GPU version of StackedCalculator
t_etace_gpu_ms = NaN
gpu_speedup = NaN

@printf("| %5d | %7d | %12.2f | %14.2f | %14s | %10.1fx | %10s |\n",
natoms, nedges, t_ace_ms, t_etace_cpu_ms, "N/A", cpu_speedup, "N/A")
else
@printf("| %5d | %7d | %12.2f | %14.2f | %10.1fx |\n",
natoms, nedges, t_ace_ms, t_etace_cpu_ms, cpu_speedup)
end
end

println()

# --- FORCES BENCHMARK ---
println("### FORCES ###")
println()

if has_cuda
println("| Atoms | Edges | ACE CPU (ms) | ETACE CPU (ms) | ETACE GPU (ms) | CPU Speedup | GPU Speedup |")
println("|-------|---------|--------------|----------------|----------------|-------------|-------------|")
else
println("| Atoms | Edges | ACE CPU (ms) | ETACE CPU (ms) | CPU Speedup |")
println("|-------|---------|--------------|----------------|-------------|")
end

for cfg in configs
sys = make_system(cfg)
natoms = length(sys)

# Count edges
G = ET.Atoms.interaction_graph(sys, rcut * u"Å")
nedges = length(G.edge_data)

# Warmup ACE
_ = AtomsCalculators.forces(sys, ace_calc)

# Warmup ETACE CPU
_ = AtomsCalculators.forces(sys, et_calc)

# Benchmark ACE CPU
t_ace = @belapsed AtomsCalculators.forces($sys, $ace_calc) samples=5 evals=3
t_ace_ms = t_ace * 1000

# Benchmark ETACE CPU
t_etace_cpu = @belapsed AtomsCalculators.forces($sys, $et_calc) samples=5 evals=3
t_etace_cpu_ms = t_etace_cpu * 1000

cpu_speedup = t_ace_ms / t_etace_cpu_ms

if has_cuda
t_etace_gpu_ms = NaN
gpu_speedup = NaN

@printf("| %5d | %7d | %12.2f | %14.2f | %14s | %10.1fx | %10s |\n",
natoms, nedges, t_ace_ms, t_etace_cpu_ms, "N/A", cpu_speedup, "N/A")
else
@printf("| %5d | %7d | %12.2f | %14.2f | %10.1fx |\n",
natoms, nedges, t_ace_ms, t_etace_cpu_ms, cpu_speedup)
end
end

println()
println("Notes:")
println("- ACE CPU: Original ACEpotentials model (full: E0 + pair + many-body)")
println("- ETACE CPU: StackedCalculator with ETOneBody + ETPairModel + ETACE")
println("- CPU Speedup = ACE CPU / ETACE CPU")
println("- Graph construction time included in ETACE timings")
Loading
Loading