A modular simulation engine for process engineering applications, with specialized support for pulp and paper industry processes.
.
├── CMakeLists.txt
├── README.md
├── core/ # Core simulation engine
│ ├── CMakeLists.txt
│ ├── include/
│ └── src/
├── pulp-and-paper/ # Pulp and paper industry modules
│ ├── CMakeLists.txt
│ ├── include/
│ ├── src/
│ └── vendor/ # Third-party dependencies (git submodules)
└── sandbox/ # Examples and testing
├── CMakeLists.txt
└── src/
- Modular Architecture: Core simulation engine with industry-specific modules
- Process Block Simulation: Support for various calculation blocks (Evaporators, etc.)
- Stream Connections: Connect process blocks with material and energy streams
- Tear Stream Handling: Advanced convergence algorithms for recycle streams
- Extensible Design: Easy to add new process equipment and calculation methods
- CMake 3.10 or higher
- C++17 compatible compiler
- GDB (for debugging)
# Clone the repository with submodules
git clone --recursive <repository-url>
cd sma-simulator
# If you already cloned without --recursive, initialize submodules:
# git submodule update --init --recursive
# Create build directory
mkdir build
cd build
# Configure (Debug mode for development)
cmake -DCMAKE_BUILD_TYPE=Debug ..
# Build
make
# Or for release build
cmake -DCMAKE_BUILD_TYPE=Release ..
makeFor debugging with GDB:
cmake -DCMAKE_BUILD_TYPE=Debug ..
make
gdb ./sandbox/sandboxThe sandbox/src/main.cpp provides a complete example of setting up and running a simulation with two connected evaporators:
#include "Evaporator.h"
#include "Ref.h"
#include "Simulator.h"
#include <iostream>
#include <vector>
int main() {
Simulator sim;
// Create evaporator E1
Ref<CalculationBlock> e1(new Evaporator("E1", {
{"A", 2100}, // Heat transfer area
{"Q", 12000}, // Heat duty
{"U", 0.5}, // Heat transfer coefficient
{"D", 25e-3}, // Diameter
}));
// Set E1 input conditions
e1->SetInputPinValue("S", "m", 4.0); // Steam mass flow
e1->SetInputPinValue("S", "P", 1.1); // Steam pressure
e1->SetInputPinValue("F", "T", 86.93); // Feed temperature
e1->SetInputPinValue("F", "m", 8.21); // Feed mass flow
e1->SetInputPinValue("F", "x", 0.14); // Feed concentration
e1->SetCalculationMethod(
Ref<CalculationMethod>(new Evaporator::MethodGivenInletData(e1))
);
// Create evaporator E2
Ref<CalculationBlock> e2(new Evaporator("E2", {
{"A", 2500}, // Heat transfer area
{"Q", 12000}, // Heat duty
{"U", 0.5}, // Heat transfer coefficient
{"D", 25e-3}, // Diameter
}));
// Set E2 input conditions
e2->SetInputPinValue("S", "m", 3.9); // Steam mass flow
e2->SetInputPinValue("S", "P", 0.7); // Steam pressure
e2->SetInputPinValue("F", "T", 25); // Feed temperature
e2->SetInputPinValue("F", "m", 12); // Feed mass flow
e2->SetInputPinValue("F", "x", 0.1); // Feed concentration
e2->SetCalculationMethod(
Ref<CalculationMethod>(new Evaporator::MethodGivenInletData(e2))
);
// Add blocks to simulation
std::vector<Ref<CalculationBlock>> blocks = {};
blocks.push_back(e1);
blocks.push_back(e2);
// Create connections between units (recycle configuration)
std::vector<Ref<Connector>> conns = {};
Ref<Connector> V1("E1", "V", "E2", "S"); // Vapor from E1 to steam of E2
Ref<Connector> L2("E2", "L", "E1", "F"); // Liquid from E2 to feed of E1
// Mark tear stream for convergence
V1->MarkAsTearStream(true);
conns.push_back(V1);
conns.push_back(L2);
// Run simulation
sim.Run(blocks, conns);
// Print results
std::cout << ">>> Results: " << std::endl;
for (auto &block : blocks) {
block->PrintAllValues();
}
}The main simulation engine that coordinates calculation blocks and stream connections.
Base class for process equipment (evaporators, reactors, separators, etc.). Each block has:
- Input and output pins for material and energy streams
- Configurable parameters
- Multiple calculation methods
Link output pins of one block to input pins of another, enabling material and energy balance calculations across the flowsheet.
Smart pointer system for memory management and object lifecycle control.
Handle recycle streams and iterative convergence:
V1->MarkAsTearStream(true);Each process block can use different calculation approaches:
e1->SetCalculationMethod(
Ref<CalculationMethod>(new Evaporator::MethodGivenInletData(e1))
);Flexible parameter setting for equipment specifications:
Evaporator e1("E1", {
{"A", 2100}, // Heat transfer area
{"Q", 12000}, // Heat duty
{"U", 0.5}, // Overall heat transfer coefficient
});- Create a new class inheriting from
CalculationBlock - Implement required calculation methods
- Define input/output pins and parameters
- Add to the appropriate module (core or industry-specific)
Create a new subdirectory similar to pulp-and-paper/ with:
CMakeLists.txtinclude/for headerssrc/for implementationvendor/for third-party dependencies
- Fork the repository
- Create a feature branch
- Add tests in the
sandbox/directory - Ensure all builds pass
- Submit a pull request
I'd like to thank the following contributors and their valuable work that helped shape this simulator:
-
Neto, M. R. V., Cardoso, M., Sermyagina, E., Vakkilainen, E. K., & Oliveira, E. D. (2022). Designing a sequential-modular steady-state simulator for kraft recovery cycle evaporative systems. O PAPEL, 83(3), 72-77.
-
Neto, M. R. V., Cardoso, M., Vakkilainen, E. K., & Oliveira, É. D. (2020). Development of an equation-oriented steady-state evaporation plant simulator. O PAPEL, 81(07), 83-89.
- CoolProp IF97: Steam and water properties calculations
Repository: https://github.com/CoolProp/IF97
Thank you to the CoolProp maintainers for providing this excellent implementation of the IAPWS-IF97 industrial formulation.
This project is licensed under the MIT License - see the LICENSE file for details.
For questions and support, please create an issue or contact [marciorvneto@gmail.com].