Skip to content
Merged
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
28 changes: 28 additions & 0 deletions .github/workflows/windows-installer-version.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Windows installer version

on:
pull_request:
paths:
- packaging/windows/**
- .github/workflows/windows-installer-version.yml
push:
branches: [master]
paths:
- packaging/windows/**
- .github/workflows/windows-installer-version.yml
workflow_dispatch:

permissions:
contents: read

jobs:
version:
runs-on: windows-2022
steps:
- uses: actions/checkout@v5
- name: Install NSIS
shell: pwsh
run: choco install nsis --no-progress -y
- name: Check version ordering and installer metadata
shell: pwsh
run: ./packaging/windows/test-version.ps1 -BuildInstaller
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@

当你需要了解或操作 SPONGE 时:

- 如果你是人类用户:请阅读 `docs` 文件夹中的开发与使用文档。
- 如果你是人类用户:请从[快速入门](docs/getting-started.md)和
[输入参数参考](docs/input-reference/README.md)开始。
- 如果你是 AI 助手:
- 若用于使用 SPONGE:将本项目的 `skills` 安装到你的全局 skills 目录,例如 `~/.claude/skills` 或 `~/.agents/skills`。
- 若用于开发 SPONGE:将你的项目级 skills 目录链接到本项目的 `skills`,例如 `.claude/skills` 或 `.agents/skills`。
Expand Down
3 changes: 2 additions & 1 deletion README_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ Official website: https://spongemm.cn

When you need to understand or work with SPONGE:

- If you are a human user, read the development and usage documents in the `docs` folder.
- If you are a human user, start with the [Getting Started guide](docs/getting-started.md)
and the [Input File Reference](docs/input-reference/README.md).
- If you are an AI assistant:
- For using SPONGE, install this project's `skills` into your global skills directory, for example `~/.claude/skills` or `~/.agents/skills`.
- For developing SPONGE, link your project-level skills directory to this project's `skills`, for example `.claude/skills` or `.agents/skills`.
Expand Down
1 change: 0 additions & 1 deletion SPONGE/NO_PBC/generalized_Born.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ void GENERALIZED_BORN_INFORMATION::Initial(CONTROLLER* controller, float cutoff,
else
{
controller->printf(" Error: GB need radii and scaled factor");
getchar();
exit(1);
}

Expand Down
3 changes: 1 addition & 2 deletions SPONGE/control.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include "control.h"

#define SPONGE_CODENAME "2026-04-01 April Fools' Day"
#define SPONGE_VERSION "v" SPONGE_VERSION_STR " " SPONGE_CODENAME
#define SPONGE_VERSION "v" SPONGE_VERSION_STR

static const char* SPONGE_ASCII_ART = R"( ____ ____ ___ _ _ ____ _____
/ ___|| _ \ / _ \| \ | |/ ___| ____|
Expand Down
4 changes: 2 additions & 2 deletions SPONGE/virtual_atoms/virtual_atom_math.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ __device__ __forceinline__ void Virtual_Atom_Add_Source_Force(
}

__host__ __device__ __forceinline__ VECTOR
Virtual_Atom_Type_0_Position(VECTOR source, float h_double)
Virtual_Atom_Type_0_Position(VECTOR source, float h)
{
source.z = 2.0f * h_double - source.z;
source.z = 2.0f * h - source.z;
return source;
}

Expand Down
5 changes: 2 additions & 3 deletions SPONGE/virtual_atoms/virtual_atoms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ static __global__ void v0_Coordinate_Refresh(const int virtual_numbers,
VIRTUAL_TYPE_0 v_temp = v_info[i];
int atom_v = v_temp.virtual_atom;
int atom_1 = v_temp.from_1;
crd[atom_v] =
Virtual_Atom_Type_0_Position(crd[atom_1], v_temp.h_double);
crd[atom_v] = Virtual_Atom_Type_0_Position(crd[atom_1], v_temp.h);
}
}

Expand Down Expand Up @@ -592,7 +591,7 @@ void VIRTUAL_INFORMATION::Initial(CONTROLLER* controller,
temp_vl->v0_info.h_virtual_type_0[count0[this_level]]
.from_1 = record.from[0];
temp_vl->v0_info.h_virtual_type_0[count0[this_level]]
.h_double = 2 * record.parameter[0];
.h = record.parameter[0];
count0[this_level]++;
break;

Expand Down
7 changes: 2 additions & 5 deletions SPONGE/virtual_atoms/virtual_atoms.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,13 @@
// own source. Repeated source indices alone are not self-dependencies.
//
// Virtual atom type 0: reflection in a plane normal to the z axis.
// Intended: x_v = x_1, y_v = y_1, z_v = 2 * h - z_1.
// NOTE: the loader stores h_double = 2 * h, but the current position
// helper computes z_v = 2 * h_double - z_1 (i.e. 4 * h - z_1).
// This legacy factor-of-two discrepancy is not corrected here.
// Position: x_v = x_1, y_v = y_1, z_v = 2 * h - z_1.
// Force: F_1 += (F_v.x, F_v.y, -F_v.z).
struct VIRTUAL_TYPE_0
{
int virtual_atom;
int from_1;
float h_double;
float h;
};

struct VIRTUAL_TYPE_0_INFROMATION
Expand Down
3 changes: 1 addition & 2 deletions benchmarks/bundled_io/tests/test_bundled_io_ab_production.py
Original file line number Diff line number Diff line change
Expand Up @@ -19594,11 +19594,10 @@ def _canonicalize_virtual_atom_positions(
for record in records_by_level[level]:
source = [coordinates[index] for index in record.source_atoms]
if record.kind == 0:
h_double = 2.0 * record.parameters[0]
coordinates[record.atom] = [
source[0][0],
source[0][1],
2.0 * h_double - source[0][2],
2.0 * record.parameters[0] - source[0][2],
]
elif record.kind == 1:
delta = _lower_triangular_periodic_displacement(
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/validation/nopbc/tests/test_virtual_atoms.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def test_type0_virtual_atom_reflects_force_and_clears_target(
output_coordinates, forces = _run(case_dir, len(coordinates), mpi_np)

np.testing.assert_allclose(
output_coordinates[1], (100.0, 100.0, 5.0), atol=2.0e-5
output_coordinates[1], (100.0, 100.0, 1.0), atol=2.0e-5
)
np.testing.assert_allclose(forces[1], 0.0, atol=1.0e-7)
virtual_force = -forces[2]
Expand Down
8 changes: 5 additions & 3 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,13 @@ dt = 0.002
cutoff = 8.0
default_in_file_prefix = "WAT"
constrain_mode = "SHAKE"
thermostat = "middle_langevin"
thermostat_tau = 0.1
thermostat_seed = 2026
target_temperature = 300.0
write_information_interval = 1000

[thermostat]
mode = "middle_langevin"
tau = 0.1
seed = 2026
```

Use the command that matches how SPONGE was installed.
Expand Down
4 changes: 3 additions & 1 deletion docs/input-reference/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Input File Reference

SPONGE input files use TOML format. The default filename is `mdin.spg.toml`, specified via the `-mdin` flag:
SPONGE automatically reads `mdin.spg.toml` from the working directory. If it
is absent, the legacy `mdin.txt` input is also recognized. Use `-mdin` to
select another input file explicitly:

```bash
SPONGE -mdin mdin.spg.toml
Expand Down
7 changes: 4 additions & 3 deletions packaging/windows/installer.nsi
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

; ---------- Build-time defines (set by installer.ps1) ----------
; !define PRODUCT_VERSION "2.0.0.0"
; !define DISPLAY_VERSION "2.0.0"
; !define VARIANT "CPU"
; !define STAGE_DIR "release-artifacts\nsis\stage"
; !define OUTPUT_PATH "release-artifacts\nsis\SPONGE-CPU-v2.0.0-installer.exe"
Expand All @@ -23,7 +24,7 @@
!define UNINSTALL_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\SPONGE-${VARIANT}"

; ---------- Installer attributes ----------
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
Name "${PRODUCT_NAME} ${DISPLAY_VERSION}"
OutFile "${OUTPUT_PATH}"
InstallDir "$PROGRAMFILES64\${INSTALL_DIR}"
InstallDirRegKey HKLM "${REG_KEY}" "InstallDir"
Expand All @@ -34,7 +35,7 @@ Unicode true
VIProductVersion "${PRODUCT_VERSION}"
VIAddVersionKey "FileVersion" "${PRODUCT_VERSION}"
VIAddVersionKey "ProductName" "${PRODUCT_NAME}"
VIAddVersionKey "ProductVersion" "${PRODUCT_VERSION}"
VIAddVersionKey "ProductVersion" "${DISPLAY_VERSION}"
VIAddVersionKey "CompanyName" "SPONGE Development Team"
VIAddVersionKey "FileDescription" "${PRODUCT_NAME} Installer"
VIAddVersionKey "LegalCopyright" "Copyright (c) 2022-2026 SPONGE Development Team"
Expand Down Expand Up @@ -99,7 +100,7 @@ Section "$(SEC_MAIN_NAME)" SecMain
WriteRegStr HKLM "${UNINSTALL_KEY}" \
"Publisher" "SPONGE Development Team"
WriteRegStr HKLM "${UNINSTALL_KEY}" \
"DisplayVersion" "${PRODUCT_VERSION}"
"DisplayVersion" "${DISPLAY_VERSION}"
WriteRegDWORD HKLM "${UNINSTALL_KEY}" \
"NoModify" 1
WriteRegDWORD HKLM "${UNINSTALL_KEY}" \
Expand Down
44 changes: 30 additions & 14 deletions packaging/windows/installer.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,45 @@ $PSNativeCommandUseErrorActionPreference = $true
function Get-ProductVersion {
param([string]$TagName)

if ($TagName -match '^v(\d+)\.(\d+)\.(\d+)$') {
return "$($Matches[1]).$($Matches[2]).$($Matches[3]).0"
if (-not $TagName) {
return "0.0.0.0"
}

if ($TagName -match '^v(\d+)\.(\d+)\.(\d+)(alpha|beta|rc)(\d+)$') {
$major = [int]$Matches[1]
$minor = [int]$Matches[2]
$patch = [int]$Matches[3]
if ($TagName -cnotmatch '\Av(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(?:-(alpha|beta|rc)\.(0|[1-9][0-9]*))?\z') {
throw "Unsupported release tag: $TagName"
}

$parts = foreach ($index in 1..3) {
$value = 0
if (-not [int]::TryParse($Matches[$index], [ref]$value) -or $value -gt 65535) {
throw "Release version components must be in 0..65535: $TagName"
}
$value
}

# Disjoint prerelease ranges preserve alpha < beta < rc < stable.
# The revision is a 16-bit value; reserve its maximum for stable releases.
$revision = 65535
if ($Matches[4]) {
$channel = $Matches[4]
$number = [int]$Matches[5]
$number = 0
if (-not [int]::TryParse($Matches[5], [ref]$number) -or $number -gt 19999) {
throw "Prerelease number must be in 0..19999: $TagName"
}

$offset = switch ($channel) {
"alpha" { 0 }
"beta" { 20 }
"rc" { 40 }
default { 0 }
"beta" { 20000 }
"rc" { 40000 }
}

return "$major.$minor.$patch.$($offset + $number)"
$revision = $offset + $number
}

return "2.0.0.0"
return "$($parts -join '.').$revision"
}

# Validate before staging files or creating output directories.
$productVersion = Get-ProductVersion $Tag
$repoRoot = Resolve-Path "."
$envPrefix = Join-Path $repoRoot ".pixi\envs\$EnvName"
$exeDir = Join-Path $envPrefix "bin"
Expand Down Expand Up @@ -76,7 +91,7 @@ foreach ($dllDir in @($exeDir, $runtimeBinDir)) {

# Resolve paths
$tagLabel = if ($Tag) { $Tag } else { "dev" }
$productVersion = Get-ProductVersion $Tag
$displayVersion = if ($Tag) { $Tag.Substring(1) } else { "dev" }
$variantUpper = $Variant.ToUpper()
$outputPath = Join-Path (Resolve-Path $OutputDir) "SPONGE-$variantUpper-$tagLabel-installer.exe"
$nsiFullPath = Join-Path $repoRoot $NsiPath
Expand All @@ -102,6 +117,7 @@ $utf8Bom = New-Object System.Text.UTF8Encoding $true
# Build installer
& $makensis `
/DPRODUCT_VERSION="$productVersion" `
/DDISPLAY_VERSION="$displayVersion" `
/DVARIANT="$variantUpper" `
/DSTAGE_DIR="$stageFullPath" `
/DOUTPUT_PATH="$outputPath" `
Expand Down
95 changes: 95 additions & 0 deletions packaging/windows/test-version.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
param([switch]$BuildInstaller)

$ErrorActionPreference = "Stop"
$PSNativeCommandUseErrorActionPreference = $true
$installerPath = Join-Path $PSScriptRoot "installer.ps1"

# Load only the version function, without running the packaging entry point.
$parseErrors = $null
$ast = [System.Management.Automation.Language.Parser]::ParseFile(
$installerPath, [ref]$null, [ref]$parseErrors
)
if ($parseErrors.Count) { throw "Installer parse errors: $parseErrors" }
$function = $ast.Find({
param($node)
$node -is [System.Management.Automation.Language.FunctionDefinitionAst] -and
$node.Name -eq "Get-ProductVersion"
}, $false)
if (-not $function) { throw "Get-ProductVersion not found" }
. ([scriptblock]::Create($function.Extent.Text))

$cases = [ordered]@{
"" = "0.0.0.0"
"v0.0.0" = "0.0.0.65535"
"v2.0.0-alpha.0" = "2.0.0.0"
"v2.0.0-alpha.21" = "2.0.0.21"
"v2.0.0-alpha.19999" = "2.0.0.19999"
"v2.0.0-beta.0" = "2.0.0.20000"
"v2.0.0-beta.1" = "2.0.0.20001"
"v2.0.0-beta.2" = "2.0.0.20002"
"v2.0.0-beta.19999" = "2.0.0.39999"
"v2.0.0-rc.0" = "2.0.0.40000"
"v2.0.0-rc.19999" = "2.0.0.59999"
"v2.0.0" = "2.0.0.65535"
"v2.0.1-alpha.0" = "2.0.1.0"
"v2.1.0-alpha.0" = "2.1.0.0"
"v3.0.0-alpha.0" = "3.0.0.0"
"v65535.65535.65535" = "65535.65535.65535.65535"
}
$previous = $null
foreach ($case in $cases.GetEnumerator()) {
$actual = Get-ProductVersion $case.Key
if ($actual -cne $case.Value) {
throw "$($case.Key): expected $($case.Value), got $actual"
}
$version = [version]$actual
if ($null -ne $previous -and $version -le $previous) {
throw "Version ordering failed: $previous >= $version"
}
$previous = $version
}

$invalidTags = @(
"v65536.0.0", "v0.65536.0", "v0.0.65536",
"v65536.0.0-beta.1", "v0.65536.0-rc.1", "v0.0.65536-alpha.1",
"v999999999999999999999.0.0", "v2.0.0-beta.999999999999999999999",
"v2.0.0-alpha.20000", "v2.0.0-beta.20000", "v2.0.0-rc.20000",
"v2.0.0-beta.-1", "v2.0.0-beta.01", "v02.0.0", "v2.00.0", "v2.0.00",
"2.0.0", "v2.0", "v2.0.0beta2", "v2.0.0-preview.1", "v2.0.0+build.1",
"V2.0.0", "v2.0.0-BETA.1", " v2.0.0", "v2.0.0`n"
)
foreach ($tag in $invalidTags) {
$rejected = $false
try { $null = Get-ProductVersion $tag } catch { $rejected = $true }
if (-not $rejected) { throw "Invalid tag was accepted: $tag" }
}
Write-Host "Passed $($cases.Count) version cases, $($cases.Count - 1) ordering checks, and $($invalidTags.Count) invalid tags."

if ($BuildInstaller) {
# Exercise the real packaging script using an inert payload; no SPONGE build needed.
$tempRoot = Join-Path ([System.IO.Path]::GetTempPath()) ([guid]::NewGuid().ToString())
$payloadDir = Join-Path $tempRoot ".pixi/envs/version-test/bin"
New-Item -ItemType Directory -Path $payloadDir -Force | Out-Null
Set-Content -Path (Join-Path $payloadDir "SPONGE.exe") -Value "version test payload"
Copy-Item (Join-Path $PSScriptRoot "installer.nsi") $tempRoot
Copy-Item (Join-Path $PSScriptRoot "../../LICENSE") $tempRoot
Push-Location $tempRoot
try {
foreach ($tag in @("v2.0.0-alpha.19999", "v2.0.0-beta.2", "v2.0.0-rc.19999", "v2.0.0", "v2.0.1-alpha.0")) {
& $installerPath -EnvName "version-test" -Variant CPU -Tag $tag `
-NsiPath "installer.nsi" -LicensePath "LICENSE"
$exe = Join-Path $tempRoot "release-artifacts/nsis/SPONGE-CPU-$tag-installer.exe"
$info = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($exe)
$fixedVersion = "$($info.FileMajorPart).$($info.FileMinorPart).$($info.FileBuildPart).$($info.FilePrivatePart)"
$fixedProductVersion = "$($info.ProductMajorPart).$($info.ProductMinorPart).$($info.ProductBuildPart).$($info.ProductPrivatePart)"
if ($fixedVersion -ne $cases[$tag] -or $fixedProductVersion -ne $cases[$tag] -or
$info.FileVersion -ne $cases[$tag] -or $info.ProductVersion -ne $tag.Substring(1)) {
throw "Installer version metadata mismatch for $tag"
}
}
Write-Host "Passed 5 NSIS installer metadata checks."
} finally {
Pop-Location
Remove-Item -Recurse -Force $tempRoot
}
}
2 changes: 1 addition & 1 deletion tests/virtual_atoms/test_virtual_atom_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ bool Check_Math()
const Boundary periodic = Boundary{BoundaryPolicy::Periodic, cell, rcell};
const VECTOR force_v(1.2f, -0.7f, 0.4f);

ok &= Check_Vector("type 0 compatibility position",
ok &= Check_Vector("type 0 reflection position",
Virtual_Atom_Type_0_Position({1.0f, 2.0f, 3.0f}, 4.0f),
{1.0f, 2.0f, 5.0f});
ok &= Check_Vector("type 0 source force",
Expand Down