diff --git a/.gitignore b/.gitignore index 5a0d7f2..fb10b1f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.slo *.lo *.o +.idea/* # Compiled Dynamic libraries *.so @@ -185,4 +186,4 @@ $RECYCLE.BIN/ .vscode # Doxygen Folder -Doxygen \ No newline at end of file +Doxygen diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..a387d8c --- /dev/null +++ b/CLAUDE.md @@ -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 \ No newline at end of file diff --git a/Legacy DLL/CMakeLists.txt b/Legacy DLL/CMakeLists.txt index 0a6aa45..5dc6fa3 100644 --- a/Legacy DLL/CMakeLists.txt +++ b/Legacy DLL/CMakeLists.txt @@ -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) diff --git a/MSX Core/src/msxfuncs.c b/MSX Core/src/msxfuncs.c index 18718a0..0313c0d 100644 --- a/MSX Core/src/msxfuncs.c +++ b/MSX Core/src/msxfuncs.c @@ -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) diff --git a/MSX Core/src/msxfuncs.h b/MSX Core/src/msxfuncs.h index 2cb8fcc..65c8306 100644 --- a/MSX Core/src/msxfuncs.h +++ b/MSX Core/src/msxfuncs.h @@ -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 *); diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 diff --git a/docker_embedded_build.sh b/docker_embedded_build.sh new file mode 100755 index 0000000..0cf877b --- /dev/null +++ b/docker_embedded_build.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +cd 'MSX Core' || exit + +mkdir -p build +cd build || exit +cmake .. || exit +cmake --build . --config Release +