Skip to content

Commit e56f712

Browse files
jameskermodeclaude
andcommitted
Update export CI to test ETACE models, remove outdated ACEModel tests
- Update runtests.jl to only include ETACE-based tests: - etace: ETACE polynomial export tests - hermite: Hermite spline export tests - multispecies: Multi-species model tests - python, lammps, mpi: Integration tests - Update export-ci.yml: - Rename test-export to test-etace-export - Run etace, hermite, multispecies tests - Add juliac compilation step to produce library artifact - Add ACE registry for dependency resolution - Remove outdated test files that used ACEModel (not ETACE): - test_export.jl - test_c_interface_minimal.jl - test_minimal_export.jl - test_portable_python.jl 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent a125118 commit e56f712

File tree

6 files changed

+90
-1234
lines changed

6 files changed

+90
-1234
lines changed

.github/workflows/export-ci.yml

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ jobs:
7878
lammps/src/nlohmann/
7979
retention-days: 1
8080

81-
test-export:
81+
test-etace-export:
82+
name: ETACE Export Tests
8283
runs-on: ubuntu-latest
8384
steps:
8485
- name: Checkout
@@ -89,6 +90,10 @@ jobs:
8990
with:
9091
version: '1.12'
9192

93+
- name: Add ACE registry
94+
run: |
95+
julia -e 'using Pkg; Pkg.Registry.add(RegistrySpec(url="https://github.com/ACEsuit/ACEregistry"))'
96+
9297
- name: Cache Julia packages
9398
uses: actions/cache@v4
9499
with:
@@ -108,9 +113,59 @@ jobs:
108113
Pkg.precompile()
109114
'
110115
111-
- name: Run Julia export tests
116+
- name: Run ETACE export tests (polynomial, hermite, multispecies)
117+
run: |
118+
julia --project=export export/test/runtests.jl etace hermite multispecies
119+
120+
- name: Compile ETACE model to shared library
112121
run: |
113-
julia --project=export export/test/runtests.jl export
122+
# Use one of the exported models from the tests
123+
cd export/test/build
124+
MODEL_FILE=$(ls test_etace_*.jl 2>/dev/null | head -1)
125+
if [ -z "$MODEL_FILE" ]; then
126+
echo "No exported model found, creating one..."
127+
julia --project=../../ -e '
128+
include("../../src/export_ace_model.jl")
129+
using ACEpotentials
130+
using ACEpotentials.Models
131+
using ACEpotentials.ETModels
132+
using Lux, LuxCore, Random
133+
134+
# Create minimal ETACE model for testing
135+
elements = (:Si,)
136+
rcut = 5.5
137+
rin0cuts = Models._default_rin0cuts(elements)
138+
rin0cuts = (x -> (rin = x.rin, r0 = x.r0, rcut = rcut)).(rin0cuts)
139+
140+
ace_model = Models.ace_model(;
141+
elements = elements, order = 2, Ytype = :solid,
142+
level = Models.TotalDegree(), max_level = 6, maxl = 2,
143+
pair_maxn = 6, rin0cuts = rin0cuts,
144+
init_WB = :glorot_normal, init_Wpair = :glorot_normal
145+
)
146+
ps, st = Lux.setup(Random.MersenneTwister(1234), ace_model)
147+
148+
et_model = ETModels.convert2et(ace_model)
149+
et_ps, et_st = LuxCore.setup(Random.MersenneTwister(1234), et_model)
150+
151+
# Copy parameters
152+
et_ps.rembed.post.W[:, :, 1] .= ps.rbasis.Wnlq[:, :, 1, 1]
153+
et_ps.readout.W[1, :, 1] .= ps.WB[:, 1]
154+
155+
et_calc = ETModels.ETACEPotential(et_model, et_ps, et_st, rcut)
156+
export_ace_model(et_calc, "test_etace_model.jl"; for_library=true)
157+
'
158+
MODEL_FILE="test_etace_model.jl"
159+
fi
160+
echo "Compiling $MODEL_FILE..."
161+
162+
# Use juliac to compile
163+
JULIAC_SCRIPT=$(julia -e 'print(joinpath(Sys.BINDIR, "..", "share", "julia", "juliac.jl"))')
164+
julia --startup-file=no -C generic --project=../../ "$JULIAC_SCRIPT" \
165+
--experimental --compile-ccallable \
166+
--output-lib libace_test.so --trim=safe "$MODEL_FILE"
167+
168+
ls -la libace_test.so
114169
115170
- name: Upload compiled library
116171
uses: actions/upload-artifact@v4
@@ -121,7 +176,7 @@ jobs:
121176

122177
test-python:
123178
runs-on: ubuntu-latest
124-
needs: test-export
179+
needs: test-etace-export
125180
steps:
126181
- name: Checkout
127182
uses: actions/checkout@v4
@@ -178,7 +233,7 @@ jobs:
178233
179234
test-lammps-serial:
180235
runs-on: ubuntu-latest
181-
needs: [build-lammps, test-export]
236+
needs: [build-lammps, test-etace-export]
182237
steps:
183238
- name: Checkout
184239
uses: actions/checkout@v4
@@ -340,7 +395,7 @@ jobs:
340395
test-ase-ace-library:
341396
name: ase-ace (library calculator)
342397
runs-on: ubuntu-latest
343-
needs: test-export
398+
needs: test-etace-export
344399
steps:
345400
- name: Checkout
346401
uses: actions/checkout@v4
@@ -399,7 +454,7 @@ jobs:
399454
test-ase-ace-julia:
400455
name: ase-ace (julia calculator)
401456
runs-on: ubuntu-latest
402-
needs: test-export
457+
needs: test-etace-export
403458
steps:
404459
- name: Checkout
405460
uses: actions/checkout@v4

export/test/runtests.jl

Lines changed: 28 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
11
#=
22
Export Test Suite - Main Test Runner
33
4-
This file orchestrates all export-related tests:
5-
1. Julia export functionality (model export, compilation, evaluation)
6-
2. ETACE export functionality (ETACE model export with solid harmonics)
7-
3. Python calculator integration
8-
4. LAMMPS plugin integration (serial)
9-
5. Multi-species model tests
4+
This file orchestrates all export-related tests for ETACE models:
5+
1. ETACE export functionality (polynomial radial basis)
6+
2. Hermite spline export (machine-precision splined radial basis)
7+
3. Multi-species model tests
8+
4. Python calculator integration
9+
5. LAMMPS plugin integration (serial)
1010
6. MPI parallel tests
1111
1212
Usage:
1313
julia --project=.. runtests.jl # Run all available tests
14-
julia --project=.. runtests.jl export # Run only ACEModel export tests
15-
julia --project=.. runtests.jl etace # Run only ETACE export tests
16-
julia --project=.. runtests.jl python # Run only Python tests
17-
julia --project=.. runtests.jl portable # Run only portable Python tests
18-
julia --project=.. runtests.jl lammps # Run only LAMMPS tests
19-
julia --project=.. runtests.jl multispecies # Run only multi-species tests
20-
julia --project=.. runtests.jl mpi # Run only MPI tests
14+
julia --project=.. runtests.jl etace # Run ETACE polynomial export tests
15+
julia --project=.. runtests.jl hermite # Run Hermite spline export tests
16+
julia --project=.. runtests.jl multispecies # Run multi-species tests
17+
julia --project=.. runtests.jl python # Run Python tests
18+
julia --project=.. runtests.jl lammps # Run LAMMPS tests
19+
julia --project=.. runtests.jl mpi # Run MPI tests
2120
=#
2221

2322
using Test
@@ -36,59 +35,6 @@ const PROJECT_DIR = dirname(EXPORT_DIR)
3635
# Global test artifacts (created once, reused across tests)
3736
const TEST_ARTIFACTS = Dict{String, Any}()
3837

39-
"""
40-
setup_test_model()
41-
42-
Fit a small Si model for testing. Returns (potential, test_data).
43-
Caches the result for reuse across test files.
44-
"""
45-
function setup_test_model()
46-
if haskey(TEST_ARTIFACTS, "potential")
47-
return TEST_ARTIFACTS["potential"], TEST_ARTIFACTS["test_data"]
48-
end
49-
50-
@info "Setting up test model (fitting Si potential)..."
51-
52-
# Load training data using example_dataset
53-
dataset = ACEpotentials.example_dataset("Si_tiny")
54-
data = dataset.train
55-
56-
# Create small model for fast testing
57-
model = ACEpotentials.ace1_model(
58-
elements = [:Si],
59-
order = 2,
60-
totaldegree = 6,
61-
rcut = 5.5,
62-
)
63-
64-
# Data keys matching Si_tiny dataset
65-
data_keys = (
66-
energy_key = "dft_energy",
67-
force_key = "dft_force",
68-
virial_key = "dft_virial",
69-
)
70-
71-
weights = Dict("default" => Dict("E" => 30.0, "F" => 1.0, "V" => 1.0))
72-
73-
# Fit model
74-
ACEpotentials.acefit!(data, model;
75-
data_keys...,
76-
weights = weights,
77-
solver = ACEfit.BLR(),
78-
)
79-
80-
# Get the fitted potential
81-
potential = model
82-
83-
# Store for reuse
84-
TEST_ARTIFACTS["potential"] = potential
85-
TEST_ARTIFACTS["test_data"] = data
86-
87-
@info "Test model ready"
88-
89-
return potential, data
90-
end
91-
9238
"""
9339
get_test_structure()
9440
@@ -160,58 +106,6 @@ function check_mpi_available()
160106
end
161107
end
162108

163-
"""
164-
get_compiled_library()
165-
166-
Get path to compiled test library. Compiles if not exists.
167-
"""
168-
function get_compiled_library()
169-
if haskey(TEST_ARTIFACTS, "lib_path")
170-
return TEST_ARTIFACTS["lib_path"]
171-
end
172-
173-
# Set up model first
174-
potential, _ = setup_test_model()
175-
176-
# Export and compile
177-
build_dir = joinpath(TEST_DIR, "build")
178-
mkpath(build_dir)
179-
180-
@info "Exporting model to Julia code..."
181-
include(joinpath(EXPORT_DIR, "src", "export_ace_model.jl"))
182-
model_file = joinpath(build_dir, "test_ace_model.jl")
183-
export_ace_model(potential, model_file; for_library=true)
184-
185-
@info "Compiling to shared library..."
186-
lib_path = joinpath(build_dir, "libace_test.so")
187-
188-
# Run juliac
189-
juliac_cmd = `julia --project=$(EXPORT_DIR) -e "
190-
using PackageCompiler
191-
PackageCompiler.juliac(
192-
\"$(model_file)\",
193-
\"$(lib_path)\";
194-
compile_library=true,
195-
trim=true,
196-
verbose=true
197-
)
198-
"`
199-
200-
# Alternative: use juliac directly if available
201-
# juliac_cmd = `juliac --output-lib $(lib_path) --trim=safe --project=$(EXPORT_DIR) $(model_file)`
202-
203-
run(juliac_cmd)
204-
205-
if !isfile(lib_path)
206-
error("Compilation failed: $lib_path not created")
207-
end
208-
209-
TEST_ARTIFACTS["lib_path"] = lib_path
210-
TEST_ARTIFACTS["model_file"] = model_file
211-
212-
return lib_path
213-
end
214-
215109
# Parse command line args for selective testing
216110
function get_test_selection()
217111
if length(ARGS) == 0
@@ -229,27 +123,33 @@ end
229123
function main()
230124
selection = get_test_selection()
231125

232-
@info "ACE Export Test Suite"
233-
@info "====================="
126+
@info "ACE Export Test Suite (ETACE)"
127+
@info "=============================="
234128
@info "Test selection: $selection"
235129
@info "Python available: $(check_python_available())"
236130
@info "LAMMPS available: $(check_lammps_available())"
237131
@info "MPI available: $(check_mpi_available())"
238132
@info ""
239133

240134
@testset "ACE Export Tests" verbose=true begin
241-
# Julia export tests (ACEModel)
242-
if should_run_test(selection, :export) || should_run_test(selection, :all)
243-
@info "Running Julia export tests (ACEModel)..."
244-
include(joinpath(TEST_DIR, "test_export.jl"))
245-
end
246-
247-
# ETACE export tests
135+
# ETACE export tests (polynomial radial basis)
248136
if should_run_test(selection, :etace) || should_run_test(selection, :all)
249-
@info "Running ETACE export tests..."
137+
@info "Running ETACE export tests (polynomial)..."
250138
include(joinpath(TEST_DIR, "test_etace_export.jl"))
251139
end
252140

141+
# Hermite spline export tests
142+
if should_run_test(selection, :hermite) || should_run_test(selection, :all)
143+
@info "Running Hermite spline export tests..."
144+
include(joinpath(TEST_DIR, "test_hermite_spline_export.jl"))
145+
end
146+
147+
# Multi-species tests
148+
if should_run_test(selection, :multispecies) || should_run_test(selection, :all)
149+
@info "Running multi-species export tests..."
150+
include(joinpath(TEST_DIR, "test_multispecies.jl"))
151+
end
152+
253153
# Python tests
254154
if should_run_test(selection, :python) || should_run_test(selection, :all)
255155
if check_python_available()
@@ -260,16 +160,6 @@ function main()
260160
end
261161
end
262162

263-
# Portable Python tests (validates relocatable deployment)
264-
if should_run_test(selection, :portable) || should_run_test(selection, :all)
265-
if check_python_available()
266-
@info "Running portable Python tests..."
267-
include(joinpath(TEST_DIR, "test_portable_python.jl"))
268-
else
269-
@warn "Skipping portable Python tests (Python/numpy/ase not available)"
270-
end
271-
end
272-
273163
# LAMMPS tests (serial)
274164
if should_run_test(selection, :lammps) || should_run_test(selection, :all)
275165
if check_lammps_available()
@@ -280,12 +170,6 @@ function main()
280170
end
281171
end
282172

283-
# Multi-species tests
284-
if should_run_test(selection, :multispecies) || should_run_test(selection, :all)
285-
@info "Running multi-species export tests..."
286-
include(joinpath(TEST_DIR, "test_multispecies.jl"))
287-
end
288-
289173
# MPI tests
290174
if should_run_test(selection, :mpi) || should_run_test(selection, :all)
291175
if check_mpi_available() && check_lammps_available()

0 commit comments

Comments
 (0)