Skip to content
Open
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
*.slo
*.lo
*.o
.idea/*

# Compiled Dynamic libraries
*.so
Expand Down Expand Up @@ -185,4 +186,4 @@ $RECYCLE.BIN/
.vscode

# Doxygen Folder
Doxygen
Doxygen
144 changes: 144 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Overview

EPANET-MSX is a multi-species extension to the EPANET hydraulic analysis engine for modeling chemical species fate and transport in water distribution systems. The codebase is structured as a modular C/C++ project with three main components designed to provide both backwards compatibility and modern toolkit functionality.

## Architecture

The project is organized into three interdependent modules:

1. **MSX Core** (`MSX Core/`) - Core mathematical and chemical reaction engine
- Contains all simulation algorithms and chemical reaction code
- Provides modern toolkit API via `coretoolkit.h`
- Has no external dependencies (self-contained)
- Key files: `msxtoolkit.c`, `msxchem.c`, `msxqual.c`, `msxcompiler.c`

2. **Legacy DLL** (`Legacy DLL/`) - Backwards compatibility layer
- Parses traditional EPANET (.inp) and MSX (.msx) input files
- Provides legacy API functions for existing applications
- Depends on MSX Core and external EPANET library
- Key files: `legacytoolkit.c`, `msxinp.c`, `msxfile.c`, `msxrpt.c`

3. **CLI** (`CLI/`) - Command-line interface
- Provides executable interface using both Core and Legacy APIs
- Depends on both MSX Core and Legacy DLL
- Main entry point: `CLI/run/msxmain.c`

4. **Example API** (`example-api/`) - Example implementations
- Demonstrates usage of both legacy and modern APIs
- Optional module for building examples

## Build System

The project uses CMake with a specific build order due to dependencies:

### Docker Build (Recommended)
```bash
docker run --rm -it -v "$PWD":/epanet-msx -w /epanet-msx cmake-dev bash
./docker_embedded_build.sh
```

### Quick Build (Local)
```bash
./build.sh
```

### Manual Build Process
Must be built in this exact order:

1. **MSX Core** (no dependencies):
```bash
cd "MSX Core"
mkdir build && cd build
cmake ..
cmake --build . --config Release
```

2. **Legacy DLL** (depends on MSX Core + external EPANET):
```bash
cd "Legacy DLL"
mkdir build && cd build
cmake ..
cmake --build . --config Release
```

3. **Example API** (optional):
```bash
cd example-api
mkdir build && cd build
cmake ..
cmake --build . --config Release
```

4. **CLI** (depends on all above):
```bash
cd CLI
mkdir build && cd build
cmake ..
cmake --build . --config Release
```

### Important Build Notes
- EPANET repository must be built in the same parent directory as epanet-msx
- The build script automatically copies required DLLs to the CLI build directory
- Required DLLs for CLI: `msxcore.dll`, `legacymsx.dll`, `epanet2.dll`, `examples.dll`

## API Usage Patterns

### Modern Core API (MSXproject-based)
```c
MSXproject MSX;
MSX_open(&MSX);
// Configure network, species, chemistry
MSX_init(MSX);
// Set hydraulics
while (timeLeft >= 0) {
MSXstep(MSX, &time, &timeleft);
}
MSX_close(MSX);
```

### Legacy API (Global state)
```c
MSXopen();
// Configure via file parsing
MSXinit();
while (timeLeft >= 0) {
MSXstep(&time, &timeleft);
}
MSXclose();
```

## Key Implementation Details

- **Chemical Solver**: Uses numerical methods (RK5, ROS2, Newton) for reaction kinetics
- **Data Structures**: Hash tables for object lookup, memory pools for allocation
- **Cross-platform**: Windows/Linux compatible with appropriate DLL/shared library handling
- **Thread Safety**: Not thread-safe - single instance per process
- **Error Handling**: Integer return codes with `MSXgeterror()` for message retrieval

## Testing

The repository includes example networks and test cases in `example-api/legacy-examples/`:
- `Batch-NH2Cl/` - Batch reactor chloramine decay
- `Net2-CL2/` - Network chlorine simulation
- `Net3-NH2Cl/` - Large network chloramine modeling
- `As5Adsorb/` - Arsenic adsorption modeling

## Development Workflow

1. Make changes to appropriate module (Core, Legacy DLL, or CLI)
2. Build dependencies first, then target module
3. Test with provided examples
4. For new features, prefer extending Core API over Legacy API
5. Maintain backwards compatibility in Legacy DLL

## File Extensions and Formats

- `.inp` - EPANET hydraulic network input files
- `.msx` - MSX chemical species and reaction input files
- `.rpt` - Text report output files
- `.out` - Binary results output files
2 changes: 1 addition & 1 deletion Legacy DLL/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ IF(MSVC)
target_link_libraries(legacymsx ${EPANET_LIB} ${MSXCORE_LIB} OpenMP::OpenMP_C)
ELSE(TRUE)
add_library(legacymsx SHARED ${MSX_SOURCES})
target_link_libraries(legacymsx ${EPANET_LIB} ${MSXCORE_LIB} OpenMP::OpenMP_C)
target_link_libraries(legacymsx ${EPANET_LIB} ${MSXCORE_LIB} OpenMP::OpenMP_C m)
ENDIF(MSVC)

target_include_directories(legacymsx PUBLIC ${PROJECT_SOURCE_DIR}/include)
Expand Down
8 changes: 8 additions & 0 deletions MSX Core/src/msxfuncs.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ HMODULE hDLL;

#include "msxfuncs.h"

// Define the chemistry function pointers
MSXGETRATES MSXgetPipeRates = NULL;
MSXGETRATES MSXgetTankRates = NULL;
MSXGETEQUIL MSXgetPipeEquil = NULL;
MSXGETEQUIL MSXgetTankEquil = NULL;
MSXGETFORMULAS MSXgetPipeFormulas = NULL;
MSXGETFORMULAS MSXgetTankFormulas = NULL;

//=============================================================================

int MSXfuncs_load(char * libName)
Expand Down
12 changes: 6 additions & 6 deletions MSX Core/src/msxfuncs.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ typedef void (*MSXGETEQUIL)(double *, double *, double * , double *, double *);
typedef void (*MSXGETFORMULAS)(double *, double *, double *, double *);

// Declare each chemistry function
MSXGETRATES MSXgetPipeRates;
MSXGETRATES MSXgetTankRates;
MSXGETEQUIL MSXgetPipeEquil;
MSXGETEQUIL MSXgetTankEquil;
MSXGETFORMULAS MSXgetPipeFormulas;
MSXGETFORMULAS MSXgetTankFormulas;
extern MSXGETRATES MSXgetPipeRates;
extern MSXGETRATES MSXgetTankRates;
extern MSXGETEQUIL MSXgetPipeEquil;
extern MSXGETEQUIL MSXgetTankEquil;
extern MSXGETFORMULAS MSXgetPipeFormulas;
extern MSXGETFORMULAS MSXgetTankFormulas;

// Functions that load and free the chemistry functions
int MSXfuncs_load(char *);
Expand Down
Empty file modified build.sh
100644 → 100755
Empty file.
9 changes: 9 additions & 0 deletions docker_embedded_build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

cd 'MSX Core' || exit

mkdir -p build
cd build || exit
cmake .. || exit
cmake --build . --config Release