# CP2K-RS Extended Interface

This directory contains custom extensions to the CP2K C API that provide additional functionality beyond the standard `libcp2k.h` interface.

## Overview

The standard `libcp2k.h` provides approximately 25 basic functions for interacting with CP2K. While these cover fundamental operations (force environments, energy/force calculations), they represent less than 1% of CP2K's capabilities.

This extensions directory provides a framework for exposing additional CP2K functionality to Rust in a maintainable way.

## Directory Structure

```
extensions/
├── README.md                    # This file
├── fortran/                     # Fortran wrapper modules
│   ├── libcp2k_extended.F90      # Quickstep/DFT internals
│   ├── libcp2k_mpi.F90           # MPI-aware init/finalize wrappers
│   └── stress_tensor_wrapper.F90 # Legacy stress/virial wrapper (not built)
├── include/                     # C header files
│   └── libcp2k_extended.h
└── patches/                     # Git patches for CP2K (if needed)
```

## Current Extensions

### Implemented

1. **MPI-aware initialization** (`libcp2k_mpi.F90`)
   - `cp2k_init_with_mpi_check()`
   - `cp2k_finalize_with_mpi_check()`

2. **Extended Quickstep/DFT access** (`libcp2k_extended.F90`)
   - Stress and virial tensors
   - Eigenvalues, occupations, HOMO/LUMO
   - MO coefficient matrix + dimensions
   - Electron density grid + metadata
   - Electron count, Fermi energy, total spin
   - K-point counts and eigenvalues
   - Atomic charges and dipole moment (exposed; see implementation notes in `libcp2k_extended.F90`)

3. **Legacy stress wrapper** (`stress_tensor_wrapper.F90`)
   - Kept for reference; the build currently compiles `libcp2k_extended.F90` instead.

### Planned / future extensions

- Basis set metadata queries
- Restart file save/load helpers
- Position constraints

## How Extensions Work

### Architecture

```
┌─────────────────────────────────────┐
│   CP2K Fortran Core                 │
│   (thousands of subroutines)        │
└──────────────┬──────────────────────┘
               │
               ↓
┌──────────────┴──────────────────────┐
│   f77_interface.F                   │
│   (internal Fortran API)            │
└──────────────┬──────────────────────┘
               │
               ↓
┌──────────────┴──────────────────────┐
│   libcp2k.F (standard)              │
│   + stress_tensor_wrapper.F90       │ ← Our extensions
│   + [other wrappers]                │
└──────────────┬──────────────────────┘
               │
               ↓ ISO_C_BINDING
┌──────────────┴──────────────────────┐
│   libcp2k.h (standard)              │
│   + libcp2k_extended.h              │ ← Our headers
└──────────────┬──────────────────────┘
               │
               ↓
┌──────────────┴──────────────────────┐
│   Rust FFI (bindgen)                │
│   + Safe Rust wrappers              │
└─────────────────────────────────────┘
```

### Implementation Process

To add a new extension:

1. **Study CP2K internals** - Find the relevant Fortran subroutines
2. **Create Fortran wrapper** - Use `ISO_C_BINDING` to expose functionality
3. **Add C declaration** - Update `libcp2k_extended.h`
4. **Update build system** - Modify `build.rs` to compile the extension
5. **Create Rust FFI** - Add unsafe extern declarations
6. **Add safe wrapper** - Wrap in safe Rust API
7. **Write tests** - Test with real CP2K calculations
8. **Document** - Add examples and API docs

## Building with Extensions

### Prerequisites

- Fortran compiler (gfortran or ifort)
- CP2K source code (the build system clones this automatically)
- All standard CP2K dependencies

### Build Commands

```bash
# Build with extensions (requires building CP2K)
CP2K_RS_BUILD_CP2K=1 cargo build --release --features build-cp2k

# Or use the build script
./build_with_cp2k.sh
```

### Development Build

For faster iteration during development:

```bash
# Header-only mode (no actual CP2K library)
cargo build --release
```

This compiles the Rust code and FFI layer without building CP2K itself.

## Example: Stress Tensor Usage

### Fortran Wrapper (stress_tensor_wrapper.F90)

```fortran
SUBROUTINE cp2k_get_stress_tensor(env_id, stress) BIND(C)
   USE ISO_C_BINDING
   USE f77_interface
   INTEGER(C_INT), VALUE :: env_id
   REAL(C_DOUBLE), DIMENSION(3,3), INTENT(OUT) :: stress
   
   ! Implementation details...
END SUBROUTINE
```

### C Header (libcp2k_extended.h)

```c
void cp2k_get_stress_tensor(int env_id, double stress[3][3]);
```

### Rust Usage

```rust
use cp2k_rs::ForceEnv;

let mut force_env = ForceEnv::new("input.inp", "output.out")?;
force_env.calc_energy_force()?;

// Get stress tensor (with extension)
let stress = force_env.get_stress_tensor()?;
println!("Stress tensor (GPa):\n{}", stress);

// Calculate pressure
let pressure = (stress[[0,0]] + stress[[1,1]] + stress[[2,2]]) / 3.0;
println!("Pressure: {} GPa", pressure);
```

## Testing Extensions

### Integration Test Example

```rust
#[test]
#[cfg(feature = "build-cp2k")]
fn test_stress_tensor() {
    use cp2k_rs::{init, finalize, ForceEnv};
    
    init().unwrap();
    
    let mut force_env = ForceEnv::new(
        "tests/data/stress_test.inp",
        "stress_test.out"
    ).unwrap();
    
    force_env.calc_energy_force().unwrap();
    let stress = force_env.get_stress_tensor().unwrap();
    
    // Stress tensor should be symmetric
    assert!((stress[[0,1]] - stress[[1,0]]).abs() < 1e-6);
    assert!((stress[[0,2]] - stress[[2,0]]).abs() < 1e-6);
    assert!((stress[[1,2]] - stress[[2,1]]).abs() < 1e-6);
    
    finalize().unwrap();
}
```

## Troubleshooting

### Build Errors

**Problem**: Fortran compilation fails
```
error: undefined reference to 'some_cp2k_function'
```

**Solution**: Ensure you're building with CP2K source:
```bash
CP2K_RS_BUILD_CP2K=1 cargo build --features build-cp2k
```

### Runtime Errors

**Problem**: Function returns zero values
```rust
let stress = force_env.get_stress_tensor()?; // All zeros
```

**Solution**: Ensure energy/force calculation was done first:
```rust
force_env.calc_energy_force()?;  // Must call this first
let stress = force_env.get_stress_tensor()?;
```

### Include Path Issues

**Problem**: Can't find CP2K headers during compilation

**Solution**: The build system automatically configures include paths. If issues persist, check that `CP2K_SRC_DIR` environment variable points to CP2K source.

## Resources

- [CP2K Source Code](https://github.com/cp2k/cp2k)
- [CP2K Developer Documentation](https://www.cp2k.org/dev:index)
- [ISO_C_BINDING Tutorial](https://gcc.gnu.org/onlinedocs/gfortran/ISO_005fC_005fBINDING.html)
- [Rust FFI Nomicon](https://doc.rust-lang.org/nomicon/ffi.html)
- [Main Proposal Document](../INTERFACE_EXPANSION_PROPOSAL.md)

## License

This code is licensed under GPL-2.0-or-later, consistent with CP2K's license.

## Support

For questions or issues with extensions:
1. Check the main project README
2. Review the [Interface Expansion Proposal](../INTERFACE_EXPANSION_PROPOSAL.md)
3. Open an issue on the project repository
4. For CP2K-specific questions, consult the [CP2K mailing list](https://groups.google.com/g/cp2k)
