Imported from ALaDyn/ALaDyn (
AGENTS.md). Install upstream withnpx skills add ALaDyn/ALaDyn. Copyright stays with the author.
AGENTS.md - AI Agent Guidelines for ALaDyn
This document provides guidelines for AI coding agents working with the ALaDyn codebase.
Project Overview
ALaDyn (Acceleration by Laser and Dynamics of charged particles) is a Particle-in-Cell (PIC) code for plasma physics simulations. It is primarily written in Fortran with some C++ helper utilities.
Main Use Cases
- Laser Wakefield Acceleration (LWFA)
- Plasma Wakefield Acceleration (PWFA)
- Target Normal Sheath Acceleration (TNSA)
Repository Structure
ALaDyn/
├── src/ # Main source code
│ ├── ALaDyn.F90 # Main program entry point
│ ├── cpp_lib/ # C++ utility functions (filesystem, debugging)
│ ├── depot/ # Legacy/deprecated bunch utilities
│ ├── diagnostics/ # Output diagnostics and run info
│ ├── dynamics/ # Particle dynamics (Boris push, evolution)
│ ├── fft/ # FFT implementations (modern and legacy)
│ ├── fields/ # Grid field operations
│ ├── grid/ # Grid parameters and stretched grids
│ ├── IO/ # Input/output routines
│ ├── ionization/ # Ionization physics
│ ├── parallel/ # MPI parallelization
│ ├── particles/ # Particle data structures and utilities
│ ├── start/ # Initialization and startup routines
│ └── work/ # Common parameters, precision, utilities
├── cmake/ # CMake modules and build scripts (GIT SUBMODULE)
├── docs/ # Documentation
├── examples/ # Example input files
├── scripts/ # Build and utility scripts
└── deprecated/ # Deprecated code
Important: Git Submodules
The cmake/ directory is a Git submodule pointing to https://github.com/cenit/ccm
To initialize submodules after cloning:
git submodule update --init --recursive
The cmake submodule contains:
build.ps1- PowerShell build script with vcpkg integrationbuild-doc.ps1- Documentation build scriptutils.psm1- PowerShell utility module- Various helper scripts for deployment and configuration
Always ensure submodules are initialized before running CI builds or using cmake/build.ps1
Build System
- CMake (minimum version 3.15) is used for building
- vcpkg is the preferred package manager for dependencies
- Supported compilers: GNU (gfortran), Intel (ifort), PGI
Building the Code (Powershell required, do not bypass)
.\cmake\build.ps1 -UseVCPKG -DisableInteractive -DoNotUpdateVCPKG -DoNotUpdateTOOL -DoNotDeleteBuildFolder -EnableTEST
Important build.ps1 Flags
| Flag | Description |
|---|---|
-UseVCPKG |
Use vcpkg for dependency management |
-DisableInteractive |
Disable interactive prompts (required for CI) |
-DoNotUpdateVCPKG |
Skip vcpkg updates |
-DoNotUpdateTOOL |
Skip tool self-updates |
-DoNotDeleteBuildFolder |
Keep build folder after completion |
-EnableTEST |
Enable building and running tests |
-BuildDebug |
Build debug version (in addition to release) |
-DoNotUseNinja |
Use Makefile generator instead of Ninja (see note below) |
Note: Without -BuildDebug, only the release build is produced. The build output goes to build_release/ for release builds.
Ninja vs Makefile Generator
By default, build.ps1 uses the Ninja generator for faster builds. However, Ninja can cause issues with Fortran code, particularly:
-
Preprocessing corruption: Ninja's handling of Fortran preprocessing (
.F90files with preprocessor directives) can corrupt source files, causing cryptic errors likeInvalid character in namepointing to valid Fortran kind specifiers (e.g.,1.0_dp). -
Module dependency ordering: Fortran modules must be compiled in dependency order. While CMake handles this, Ninja's parallel execution can sometimes cause race conditions.
Recommendation: If you encounter unexplained compilation errors in Fortran files (especially test files or files using use statements with kind parameters), try adding -DoNotUseNinja to switch to the Makefile generator:
.\cmake\build.ps1 -UseVCPKG -DisableInteractive -DoNotUpdateVCPKG -DoNotUpdateTOOL -DoNotDeleteBuildFolder -EnableTEST -DoNotUseNinja
The Makefile generator is slower but more reliable for Fortran projects.
Manual CMake (if failing do not trigger code modifications in reaction)
mkdir build && cd build
cmake ..
cmake --build . --target install
Dependencies
- MPI (OpenMPI or MPICH)
- FFTW3 (or Intel MKL)
Running on HPC Systems
# Generate and submit job script
./scripts/run.sh -n 2 -t 136 -a MyProject
# Dry run (see generated script)
./scripts/run.sh -p marconi-knl --dry-run
# Local execution
./scripts/run.sh --local -t 4
Code Style Guidelines
Fortran Style
-
File Extensions:
.F90for preprocessed Fortran (capital F).f90for standard Fortran (lowercase f)
-
License Header: All source files must include the standard copyright header:
!*****************************************************************************************************! ! Copyright 2008-2020 The ALaDyn Collaboration ! !*****************************************************************************************************! -
Module Structure:
module module_name use dependency_module implicit none ! Module-level declarations contains subroutine/function definitions end module -
Indentation: Use 1 space for module/program body indentation, standard indentation for nested constructs
-
Naming Conventions:
- Module names:
snake_case(e.g.,precision_def,boris_push,grid_param) - Subroutine/function names:
snake_case(e.g.,lpf_momenta_and_positions) - Variables:
snake_casefor multi-word, lowercase for single word - Constants/parameters: lowercase (e.g.,
dp,sp,zero_dp)
- Module names:
-
Precision: Use precision kinds from
precision_defmodule:dpfor double precision realsspfor single precision realsdp_intfor 64-bit integershp_intfor 16-bit integers
-
Comments: Use
!for inline comments,!!for documentation comments (FORD-compatible)
C++ Style
-
File Extension:
.cpp -
License Header: Use C-style block comments with asterisks:
/******************************************************************************************************* * Copyright 2008-2020 The ALaDyn Collaboration * ******************************************************************************************************/ -
Standard: C++11 minimum (C++17 preferred for
std::filesystem) -
Fortran Interop: Use
extern "C"blocks with trailing underscore naming:extern "C" { void function_name_(char* arg, size_t len) { ... } }
Testing and CI
- GitHub Actions workflow in
.github/workflows/ccpp.yml - CI runs on Ubuntu and macOS
- Tests are run automatically via
ctestafter each build - All code modifications must include corresponding tests
Test Suite Structure
tests/
├── CMakeLists.txt # Test build configuration
├── test_framework/ # Test utilities and assertions
│ ├── test_assertions.f90 # Assertion macros for testing
│ └── test_runner.f90 # Test suite runner utilities
├── unit/ # Unit tests for individual modules
│ ├── test_precision_def.f90
│ ├── test_phys_param.f90
│ ├── test_util.f90
│ ├── test_stretched_grid.f90
│ ├── test_grid_param.f90
│ ├── test_boris_push.f90
│ └── test_array_alloc.f90
└── integration/ # Integration tests
├── test_smoke.f90 # Basic functionality smoke test
└── test_lwfa_scenario.f90 # LWFA physics validation
Running Tests
# After building with CMake
cd build
ctest --output-on-failure
# Run specific test
ctest -R precision_def
# Verbose output
ctest -V
# Run tests in parallel
ctest -j4
Building with Tests
# Enable tests (enabled by default)
cmake .. -DBUILD_TESTING=ON
cmake --build .
ctest
Writing Tests
When adding new functionality, follow these guidelines:
-
Create a test file in
tests/unit/for unit tests ortests/integration/for integration tests -
Use the test framework:
program test_my_module use test_assertions use test_runner implicit none call start_test_suite('my_module') call test_feature_1() call test_feature_2() call end_test_suite('my_module') if (.not. test_suite_passed()) then error stop 1 end if contains subroutine test_feature_1() call run_test('feature_1') call assert_near_dp(expected, actual, tolerance, 'description') call assert_true(condition, 'description') end subroutine end program -
Available assertions:
assert_true(condition, name)- Assert condition is trueassert_false(condition, name)- Assert condition is falseassert_equal_int(expected, actual, name)- Compare integersassert_equal_dp(expected, actual, name)- Compare double precisionassert_near_dp(expected, actual, tol, name)- Compare with toleranceassert_array_near_dp(expected, actual, n, tol, name)- Compare arrays
-
Add the test to CMakeLists.txt:
add_executable(test_my_module unit/test_my_module.f90) target_compile_options(test_my_module PRIVATE ${TEST_Fortran_FLAGS}) target_link_libraries(test_my_module PRIVATE aladyn_test_utils) target_include_directories(test_my_module PRIVATE ${CMAKE_BINARY_DIR}) add_test(NAME my_module_tests COMMAND test_my_module)
Test Categories
| Category | Description | Location |
|---|---|---|
| Unit Tests | Test individual functions/modules in isolation | tests/unit/ |
| Integration Tests | Test interactions between modules | tests/integration/ |
| Physics Tests | Validate physics correctness (LWFA, PWFA, etc.) | tests/integration/ |
Test Coverage Requirements
When making changes, ensure:
- New features: Add unit tests for all new public functions/subroutines
- Bug fixes: Add a test that would have caught the bug
- Physics changes: Add validation tests for physics accuracy
- Performance changes: Document expected behavior, add regression tests
Test Naming Conventions
- Test files:
test_<module_name>.f90 - Test programs:
test_<module_name> - Test subroutines:
test_<feature_name> - Test names (in assertions): descriptive, lowercase with spaces
Making Changes
Before Modifying Code
- Understand the module dependency hierarchy (start from
ALaDyn.F90) - Check if similar patterns exist elsewhere in the codebase
- Verify compilation with at least GNU Fortran
When Adding New Features
- Place code in the appropriate subdirectory under
src/ - Update the relevant
CMakeLists.txtto include new source files - Follow existing module structure and naming conventions
- Add the standard license header to new files
When Fixing Bugs
- Make minimal, surgical changes
- Preserve existing code structure and style
- Do not refactor unrelated code
Key Files to Understand
| File | Purpose |
|---|---|
src/ALaDyn.F90 |
Main program, entry point |
src/work/precision_def.F90 |
Precision definitions (dp, sp, etc.) |
src/work/common_param.f90 |
Common simulation parameters |
src/dynamics/boris_push.f90 |
Core particle pusher algorithms |
src/start/read_input.f90 |
Input file parsing |
CMakeLists.txt |
Main build configuration |
Common Pitfalls
-
Real Precision: The code uses
-fdefault-real-8(GNU) or equivalent flags. Do not assume default real is single precision. -
MPI Compatibility: Some MPI implementations require special handling. Check
FORCE_OLD_MPIoption if using legacympif.h. -
Array Indexing: Fortran uses 1-based indexing by default; some arrays may use custom bounds.
-
Module Dependencies: Fortran modules must be compiled in dependency order. CMake handles this, but be aware when adding new dependencies.
-
Preprocessor Directives:
.F90files may contain preprocessor macros;.f90files should not.
Documentation
- In-code documentation uses FORD format (
!!comments) - User documentation is in
docs/pages/ - Input guide:
docs/pages/NAMELIST_GUIDE.md - Build guide:
docs/pages/BUILD.md
Contributing
See docs/pages/CONTRIBUTING.md for the full contribution workflow:
- Fork the repository
- Create a feature branch (
dev/<yourname>/<feature>) - Make changes and ensure compilation
- Squash commits to meaningful units
- Open a Pull Request