├── .git_archival.txt ├── .gitattributes ├── .github ├── pull_request_template.md └── workflows │ ├── cmake_macos.yml │ ├── cmake_ubuntu.yml │ ├── cmake_windows.yml │ ├── publish-to-pypi.yml │ ├── ubuntu_test.yml │ └── windows_test.yml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── MANIFEST.in ├── README.md ├── benchmarks ├── CMakeLists.txt └── benchmark.cpp ├── examples ├── Abstract │ ├── Continuous │ │ ├── Network1.JSON │ │ ├── Network1.cpp │ │ ├── Network1.py │ │ └── Network2.JSON │ ├── Droplet │ │ ├── Network1.JSON │ │ ├── Network1.cpp │ │ ├── Network1.py │ │ └── dropletAbstract.JSON │ └── Mixing │ │ ├── Case1.JSON │ │ ├── Case10.JSON │ │ ├── Case11.JSON │ │ ├── Case12.JSON │ │ ├── Case2.JSON │ │ ├── Case3.JSON │ │ ├── Case4.JSON │ │ ├── Case5.JSON │ │ ├── Case6.JSON │ │ ├── Case7.JSON │ │ ├── Case8.JSON │ │ ├── Case9.JSON │ │ ├── DiffusionCase1.JSON │ │ ├── DiffusionCase2.JSON │ │ ├── DiffusionCase3.JSON │ │ ├── DiffusionCase4.JSON │ │ ├── Network1.JSON │ │ ├── Network2.JSON │ │ ├── Network3.JSON │ │ ├── Network4.JSON │ │ ├── Network5.JSON │ │ └── Network6.JSON ├── CFD │ ├── Network1a.JSON │ ├── Network1b.JSON │ ├── Network1c.JSON │ ├── Network1d.JSON │ ├── Network2a.JSON │ ├── Network2b.JSON │ ├── Network2c.JSON │ ├── Network2d.JSON │ ├── Network3a.JSON │ ├── Network3b.JSON │ ├── Network3c.JSON │ ├── Network3d.JSON │ ├── Network4a.JSON │ ├── Network4b.JSON │ ├── Network4c.JSON │ └── Network4d.JSON ├── Hybrid │ ├── Mixing1a.JSON │ ├── Network1a.JSON │ ├── Network1a.cpp │ ├── Network1a.py │ ├── Network1a_ESS.JSON │ ├── Network1b.JSON │ ├── Network1c.JSON │ ├── Network1d.JSON │ ├── Network2a.JSON │ ├── Network2b.JSON │ ├── Network2c.JSON │ ├── Network2d.JSON │ ├── Network3a.JSON │ ├── Network3b.JSON │ ├── Network3c.JSON │ ├── Network3d.JSON │ ├── Network4a.JSON │ ├── Network4b.JSON │ ├── Network4c.JSON │ ├── Network4d.JSON │ └── OoC-1.JSON └── STL │ ├── Network1a.stl │ ├── Network1b.stl │ ├── Network1c.stl │ ├── Network1d.stl │ ├── Network2a.stl │ ├── Network2b.stl │ ├── Network2c.stl │ ├── Network2d.stl │ ├── Network3a.stl │ ├── Network3b.stl │ ├── Network3c.stl │ ├── Network3d.stl │ ├── Network4a.stl │ ├── Network4b.stl │ ├── Network4c.stl │ ├── Network4d.stl │ ├── T-shape.stl │ ├── cross.stl │ ├── cross10.stl │ ├── cross20.stl │ ├── cross30.stl │ ├── cross45.stl │ ├── cube.stl │ ├── cube0.stl │ ├── cube10.stl │ ├── cube20.stl │ ├── cube30.stl │ ├── cube45.stl │ └── invT-shape.stl ├── images ├── mmft_dark.png └── mmft_light.png ├── incl └── windows │ ├── CMakeLists.txt │ └── unistd.h ├── pyproject.toml ├── python └── mmft │ └── simulator │ ├── CMakeLists.txt │ ├── __init__.py │ └── bindings.cpp ├── script.sed ├── setup.py ├── src ├── CMakeLists.txt ├── architecture │ ├── CMakeLists.txt │ ├── Channel.h │ ├── Channel.hh │ ├── ChannelPosition.h │ ├── ChannelPosition.hh │ ├── Edge.h │ ├── Edge.hh │ ├── FlowRatePump.h │ ├── FlowRatePump.hh │ ├── Membrane.h │ ├── Membrane.hh │ ├── MixturePump.h │ ├── MixturePump.hh │ ├── Module.h │ ├── Module.hh │ ├── ModuleOpening.h │ ├── Network.h │ ├── Network.hh │ ├── Node.h │ ├── Node.hh │ ├── PressurePump.h │ ├── PressurePump.hh │ ├── Tank.h │ └── Tank.hh ├── baseSimulator.h ├── baseSimulator.hh ├── hybridDynamics │ ├── CMakeLists.txt │ ├── Naive.h │ ├── Naive.hh │ ├── Scheme.h │ └── Scheme.hh ├── main.cpp ├── nodalAnalysis │ ├── CMakeLists.txt │ ├── NodalAnalysis.h │ └── NodalAnalysis.hh ├── olbProcessors │ ├── CMakeLists.txt │ ├── navierStokesAdvectionDiffusionCouplingPostProcessor2D.h │ ├── navierStokesAdvectionDiffusionCouplingPostProcessor2D.hh │ ├── saturatedFluxPostProcessor2D.h │ ├── saturatedFluxPostProcessor2D.hh │ ├── setFunctionalRegularizedHeatFlux.h │ └── setFunctionalRegularizedHeatFlux.hh ├── porting │ ├── CMakeLists.txt │ ├── jsonPorter.h │ ├── jsonPorter.hh │ ├── jsonReaders.h │ ├── jsonReaders.hh │ ├── jsonWriters.h │ └── jsonWriters.hh ├── result │ ├── CMakeLists.txt │ ├── Results.h │ └── Results.hh └── simulation │ ├── CFDSim.h │ ├── CFDSim.hh │ ├── CMakeLists.txt │ ├── Droplet.h │ ├── Droplet.hh │ ├── Fluid.h │ ├── Fluid.hh │ ├── Injection.h │ ├── Injection.hh │ ├── MembraneModels.h │ ├── MembraneModels.hh │ ├── MixingModels.h │ ├── MixingModels.hh │ ├── Mixture.h │ ├── Mixture.hh │ ├── MixtureInjection.h │ ├── MixtureInjection.hh │ ├── ResistanceModels.h │ ├── ResistanceModels.hh │ ├── Simulation.h │ ├── Simulation.hh │ ├── Specie.h │ ├── Specie.hh │ ├── Tissue.h │ ├── Tissue.hh │ ├── events │ ├── BoundaryEvent.h │ ├── BoundaryEvent.hh │ ├── CMakeLists.txt │ ├── Event.h │ ├── InjectionEvent.h │ ├── InjectionEvent.hh │ ├── MergingEvent.h │ └── MergingEvent.hh │ └── simulators │ ├── CMakeLists.txt │ ├── cfdSimulator.h │ ├── cfdSimulator.hh │ ├── essContinuous.h │ ├── essContinuous.hh │ ├── essMixing.h │ ├── essMixing.hh │ ├── olbContinuous.h │ ├── olbContinuous.hh │ ├── olbMixing.h │ ├── olbMixing.hh │ ├── olbOoc.h │ └── olbOoc.hh └── tests ├── CMakeLists.txt ├── abstract ├── Architecture.test.cpp ├── BigDroplet.test.cpp ├── CMakeLists.txt ├── Continuous.test.cpp ├── DiffusionMixing.test.cpp ├── GradientGenerator.test.cpp ├── InstantaneousMixing.test.cpp ├── Tank.test.cpp ├── Topology.test.cpp └── test_helpers.h ├── hybrid ├── CMakeLists.txt ├── Hybrid.test.cpp └── Opening.test.cpp ├── python └── testHybridSim.py └── test.cpp /.git_archival.txt: -------------------------------------------------------------------------------- 1 | node: 7e917548421da626634f1d0321bde723bca51eab 2 | node-date: 2025-06-26T13:53:04+02:00 3 | describe-name: v0.2.1-45-g7e917548 4 | ref-names: HEAD -> main 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | .git_archival.txt export-subst 2 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## This PR updates 2 | 3 | (Add description) 4 | 5 | ## PR Checklist 6 | - [ ] Did you include comments/documentation? 7 | - [ ] Did you include and pass unit tests? -------------------------------------------------------------------------------- /.github/workflows/cmake_macos.yml: -------------------------------------------------------------------------------- 1 | name: MacOS-build 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | runs-on: macos-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v3 11 | with: 12 | submodules: recursive 13 | 14 | - name: Configure CMake 15 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} 16 | 17 | - name: Build 18 | run: cmake --build ${{github.workspace}}/build -------------------------------------------------------------------------------- /.github/workflows/cmake_ubuntu.yml: -------------------------------------------------------------------------------- 1 | name: Ubuntu-build 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v3 11 | with: 12 | submodules: recursive 13 | 14 | - name: Install CMake 15 | uses: ssrobins/install-cmake@v1 16 | with: 17 | version: 4.0.3 18 | 19 | - name: Configure CMake 20 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} 21 | 22 | - name: Build 23 | run: cmake --build ${{github.workspace}}/build -------------------------------------------------------------------------------- /.github/workflows/cmake_windows.yml: -------------------------------------------------------------------------------- 1 | name: Windows-build 2 | 3 | on: [push] 4 | 5 | defaults: 6 | run: 7 | shell: pwsh 8 | 9 | jobs: 10 | build: 11 | runs-on: windows-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | with: 16 | submodules: recursive 17 | 18 | # - uses: msys2/setup-msys2@v2 19 | # with: 20 | # msystem: CLANG64 21 | 22 | # - name: Configure CMake 23 | # run: cmake -S . -B build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -G "Visual Studio 17 2022" -T ClangCL -A x64 24 | 25 | # - name: Build 26 | # run: cmake --build build -------------------------------------------------------------------------------- /.github/workflows/publish-to-pypi.yml: -------------------------------------------------------------------------------- 1 | name: Publish Python 🐍 distributions 📦 to PyPI 2 | 3 | on: 4 | release: 5 | types: [published] 6 | pull_request: 7 | merge_group: 8 | push: 9 | branches: [main] 10 | workflow_dispatch: 11 | 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | build_wheels: 18 | name: ${{ matrix.runs-on.os }} ${{ matrix.python }} wheels 19 | runs-on: ${{ matrix.runs-on.os }} 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | runs-on: 24 | - { os: ubuntu-latest, shell: bash } 25 | # - { os: macos-latest, shell: bash } 26 | #- { os: windows-latest, shell: "msys2 {0}" } 27 | python: ["cp38", "cp39", "cp310", "cp311", "cp312"] 28 | defaults: 29 | run: 30 | shell: ${{ matrix.runs-on.shell }} 31 | steps: 32 | - uses: actions/checkout@v3 33 | with: 34 | fetch-depth: 0 35 | submodules: recursive 36 | - if: runner.os == 'Windows' 37 | uses: msys2/setup-msys2@v2 38 | with: 39 | msystem: MINGW64 40 | path-type: inherit 41 | install: >- 42 | mingw-w64-x86_64-gcc 43 | - name: Build wheels 44 | run: | 45 | pipx run cibuildwheel 46 | env: 47 | CIBW_ARCHS_WINDOWS: auto64 48 | CIBW_ENVIRONMENT_WINDOWS: CC=gcc CXX=g++ 49 | - name: Upload wheels 50 | uses: actions/upload-artifact@v4 51 | with: 52 | name: cibw-wheels-${{ runner.os }}-${{ matrix.python }}-${{ strategy.job-index }} 53 | path: ./wheelhouse/*.whl 54 | 55 | build_sdist: 56 | name: Build Python 🐍 source distribution 57 | runs-on: ubuntu-latest 58 | steps: 59 | - uses: actions/checkout@v3 60 | with: 61 | fetch-depth: 0 62 | submodules: recursive 63 | - name: Set up Python 64 | uses: actions/setup-python@v5 65 | with: 66 | python-version: "3.x" 67 | - name: Build SDist 68 | run: pipx run build --sdist 69 | - name: Install sdist 70 | run: python -m pip install --verbose dist/*.tar.gz 71 | - uses: actions/upload-artifact@v4 72 | with: 73 | path: dist/*.tar.gz 74 | 75 | Upload-PyPi: 76 | needs: [build_wheels, build_sdist] 77 | runs-on: ubuntu-latest 78 | if: github.event_name == 'release' && github.event.action == 'published' 79 | steps: 80 | - uses: actions/download-artifact@v4.1.7 81 | with: 82 | name: artifact 83 | path: dist 84 | - name: Publish wheels and source distribution to PyPi 85 | uses: pypa/gh-action-pypi-publish@release/v1 86 | with: 87 | password: ${{ secrets.PYPI_API_TOKEN }} 88 | skip-existing: true 89 | verbose: true 90 | -------------------------------------------------------------------------------- /.github/workflows/ubuntu_test.yml: -------------------------------------------------------------------------------- 1 | name: Ubuntu-test 2 | 3 | on: 4 | pull_request: 5 | types: [opened, reopened, edited] 6 | branches: [main, develop] 7 | 8 | jobs: 9 | test: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v3 14 | with: 15 | submodules: recursive 16 | 17 | - name: Install CMake 18 | uses: ssrobins/install-cmake@v1 19 | with: 20 | version: 4.0.3 21 | 22 | - name: Configure CMake 23 | run: cmake -DTEST=ON -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} 24 | 25 | - name: Build 26 | run: cmake --build ${{github.workspace}}/build 27 | 28 | - name: Test 29 | working-directory: ${{github.workspace}}/build 30 | run: ./simulatorTest -------------------------------------------------------------------------------- /.github/workflows/windows_test.yml: -------------------------------------------------------------------------------- 1 | name: Windows-test 2 | 3 | on: 4 | pull_request: 5 | types: [opened, reopened, edited] 6 | branches: [main, develop] 7 | 8 | defaults: 9 | run: 10 | shell: pwsh 11 | 12 | jobs: 13 | test: 14 | runs-on: windows-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | with: 19 | submodules: recursive 20 | 21 | - uses: msys2/setup-msys2@v2 22 | 23 | # - name: Configure CMake 24 | # run: cmake -DTEST=ON -S . -B build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -G "MinGW Makefiles" 25 | 26 | # - name: Build 27 | # run: cmake --build build 28 | 29 | # - name: Test 30 | # working-directory: ${{github.workspace}}/build 31 | # run: ./simulatorTest -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Python wheels 30 | *.whl 31 | *.egg* 32 | *.pyc 33 | 34 | # Executables 35 | *.exe 36 | *.out 37 | *.app 38 | *.stl 39 | *.JSON 40 | test.py 41 | 42 | # Visualization files 43 | *.vtk 44 | *.vtm 45 | *.vti 46 | 47 | # Exclude directories 48 | build/ 49 | external/*/ 50 | .cache/ 51 | .vscode 52 | images/* 53 | tmp/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/pybind11"] 2 | path = external/pybind11 3 | url = ../../pybind/pybind11 4 | branch = stable 5 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | graft external/pybind11 2 | -------------------------------------------------------------------------------- /benchmarks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${TARGET_NAME} PRIVATE ${SOURCE_LIST}) 2 | target_link_libraries(${TARGET_NAME} PUBLIC gtest gtest_main) 3 | target_link_libraries(${TARGET_NAME} PUBLIC nlohmann_json::nlohmann_json) 4 | target_link_libraries(${TARGET_NAME} PUBLIC lbmLib) 5 | target_link_libraries(${TARGET_NAME} PUBLIC simLib) 6 | -------------------------------------------------------------------------------- /benchmarks/benchmark.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include "benchmark/benchmark.h" 3 | 4 | #include "../src/baseSimulator.h" 5 | #include "../src/baseSimulator.hh" 6 | 7 | using T = double; 8 | 9 | void BM_simRun(benchmark::State& state) { 10 | 11 | std::string file = "../examples/Hybrid/Network4a.JSON"; 12 | 13 | // Load and set the network from a JSON file 14 | arch::Network network = porting::networkFromJSON(file); 15 | 16 | // Load and set the simulation from a JSON file 17 | sim::Simulation testSimulation = porting::simulationFromJSON(file, &network); 18 | for (auto _ : state) { 19 | testSimulation.simulate(); 20 | } 21 | } 22 | BENCHMARK(BM_simRun); 23 | 24 | BENCHMARK_MAIN(); -------------------------------------------------------------------------------- /examples/Abstract/Continuous/Network1.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "network": { 3 | "nodes": [ 4 | { 5 | "x": 0.0, 6 | "y": 0.0, 7 | "z": 0.0, 8 | "ground": true 9 | }, 10 | { 11 | "x": 1e-3, 12 | "y": 2e-3, 13 | "z": 0.0 14 | }, 15 | { 16 | "x": 1e-3, 17 | "y": 1e-3, 18 | "z": 0.0 19 | }, 20 | { 21 | "x": 1e-3, 22 | "y": 0.0, 23 | "z": 0.0 24 | }, 25 | { 26 | "x": 2e-3, 27 | "y": 2e-3, 28 | "z": 0.0 29 | }, 30 | { 31 | "x": 2e-3, 32 | "y": 1e-3, 33 | "z": 0.0 34 | }, 35 | { 36 | "x": 2e-3, 37 | "y": 0.0, 38 | "z": 0.0 39 | }, 40 | { 41 | "x": 3e-3, 42 | "y": 1e-3, 43 | "z": 0.0, 44 | "ground": true 45 | } 46 | ], 47 | "channels": [ 48 | { 49 | "node1": 0, 50 | "node2": 1, 51 | "width": 1e-4, 52 | "height": 1e-4 53 | }, 54 | { 55 | "node1": 0, 56 | "node2": 2, 57 | "width": 1e-4, 58 | "height": 1e-4 59 | }, 60 | { 61 | "node1": 0, 62 | "node2": 3, 63 | "width": 1e-4, 64 | "height": 1e-4 65 | }, 66 | { 67 | "node1": 1, 68 | "node2": 4, 69 | "width": 1e-4, 70 | "height": 1e-4 71 | }, 72 | { 73 | "node1": 2, 74 | "node2": 5, 75 | "width": 1e-4, 76 | "height": 1e-4 77 | }, 78 | { 79 | "node1": 3, 80 | "node2": 6, 81 | "width": 1e-4, 82 | "height": 1e-4 83 | }, 84 | { 85 | "node1": 4, 86 | "node2": 5, 87 | "width": 1e-4, 88 | "height": 1e-4 89 | }, 90 | { 91 | "node1": 6, 92 | "node2": 5, 93 | "width": 1e-4, 94 | "height": 1e-4 95 | }, 96 | { 97 | "node1": 5, 98 | "node2": 7, 99 | "width": 1e-4, 100 | "height": 1e-4 101 | } 102 | ] 103 | }, 104 | "simulation": { 105 | "platform": "Continuous", 106 | "type": "Abstract", 107 | "resistanceModel": "Rectangular", 108 | "fluids": [ 109 | { 110 | "name": "Water", 111 | "concentration": 1, 112 | "density": 997, 113 | "viscosity": 1e-3 114 | } 115 | ], 116 | "pumps": [ 117 | { 118 | "channel":0, 119 | "type": "PumpPressure", 120 | "deltaP": 1000 121 | }, 122 | { 123 | "channel":1, 124 | "type": "PumpPressure", 125 | "deltaP": 1000 126 | }, 127 | { 128 | "channel":2, 129 | "type": "PumpPressure", 130 | "deltaP": 1000 131 | } 132 | ], 133 | "fixtures": [ 134 | { 135 | "name": "Setup #1", 136 | "phase": 0 137 | } 138 | ], 139 | "activeFixture": 0 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /examples/Abstract/Continuous/Network1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | using T = double; 7 | 8 | int main(int argc, char const* argv []) { 9 | 10 | // define simulation 11 | sim::Simulation testSimulation; 12 | testSimulation.setType(sim::Type::Abstract); 13 | testSimulation.setPlatform(sim::Platform::Continuous); 14 | 15 | // define network 16 | arch::Network network; 17 | testSimulation.setNetwork(&network); 18 | 19 | // nodes 20 | auto node0 = network.addNode(0.0, 0.0, true); 21 | auto node1 = network.addNode(1e-3, 2e-3, false); 22 | auto node2 = network.addNode(1e-3, 1e-3, false); 23 | auto node3 = network.addNode(1e-3, 0.0, false); 24 | auto node4 = network.addNode(2e-3, 2e-3, false); 25 | auto node5 = network.addNode(2e-3, 1e-3, false); 26 | auto node6 = network.addNode(2e-3, 0.0, false); 27 | auto node7 = network.addNode(3e-3, 1e-3, true); 28 | 29 | // pressure pump 30 | auto pressure = 1e3; 31 | auto pump0 = network.addPressurePump(node0->getId(), node1->getId(), pressure); 32 | auto pump1 = network.addPressurePump(node0->getId(), node2->getId(), pressure); 33 | auto pump2 = network.addPressurePump(node0->getId(), node3->getId(), pressure); 34 | 35 | // channels 36 | auto cWidth = 100e-6; 37 | auto cHeight = 100e-6; 38 | auto cLength = 1000e-6; 39 | 40 | auto c1 = network.addChannel(node1->getId(), node4->getId(), cHeight, cWidth, cLength, arch::ChannelType::NORMAL); 41 | auto c2 = network.addChannel(node2->getId(), node5->getId(), cHeight, cWidth, cLength, arch::ChannelType::NORMAL); 42 | auto c3 = network.addChannel(node3->getId(), node6->getId(), cHeight, cWidth, cLength, arch::ChannelType::NORMAL); 43 | auto c4 = network.addChannel(node4->getId(), node5->getId(), cHeight, cWidth, cLength, arch::ChannelType::NORMAL); 44 | auto c5 = network.addChannel(node6->getId(), node5->getId(), cHeight, cWidth, cLength, arch::ChannelType::NORMAL); 45 | auto c6 = network.addChannel(node5->getId(), node7->getId(), cHeight, cWidth, cLength, arch::ChannelType::NORMAL); 46 | 47 | // fluids 48 | auto fluid0 = testSimulation.addFluid(1e-3, 997.0, 1.0); 49 | //--- continuousPhase --- 50 | testSimulation.setContinuousPhase(fluid0->getId()); 51 | 52 | // Define and set the resistance model 53 | sim::ResistanceModel1D resistanceModel = sim::ResistanceModel1D(testSimulation.getContinuousPhase()->getViscosity()); 54 | testSimulation.setResistanceModel(&resistanceModel); 55 | 56 | // check if chip is valid 57 | network.isNetworkValid(); 58 | network.sortGroups(); 59 | 60 | // simulate 61 | testSimulation.simulate(); 62 | 63 | // results 64 | result::SimulationResult* result = testSimulation.getSimulationResults(); 65 | result->printLastState(); 66 | 67 | return 0; 68 | } -------------------------------------------------------------------------------- /examples/Abstract/Continuous/Network1.py: -------------------------------------------------------------------------------- 1 | from mmft.simulator import * 2 | 3 | # Continuous Abstract 4 | def abstractContinuous(): 5 | 6 | network = Network() 7 | 8 | # Nodes 9 | n0 = network.addNode(0.0, 0.0, True) 10 | n1 = network.addNode(1e-3, 2e-3, False) 11 | n2 = network.addNode(1e-3, 1e-3, False) 12 | n3 = network.addNode(1e-3, 0.0, False) 13 | n4 = network.addNode(2e-3, 2e-3, False) 14 | n5 = network.addNode(2e-3, 1e-3, False) 15 | n6 = network.addNode(2e-3, 0.0, False) 16 | n7 = network.addNode(3e-3, 1e-3, True) 17 | 18 | # Channels 19 | network.addPressurePump(n0, n1, 1e3) 20 | network.addPressurePump(n0, n2, 1e3) 21 | network.addPressurePump(n0, n3, 1e3) 22 | network.addChannel(n1, n4, 1e-4, 1e-4, ChannelType.normal) 23 | network.addChannel(n2, n5, 1e-4, 1e-4, ChannelType.normal) 24 | network.addChannel(n3, n6, 1e-4, 1e-4, ChannelType.normal) 25 | network.addChannel(n4, n5, 1e-4, 1e-4, ChannelType.normal) 26 | network.addChannel(n6, n5, 1e-4, 1e-4, ChannelType.normal) 27 | network.addChannel(n5, n7, 1e-4, 1e-4, ChannelType.normal) 28 | 29 | network.sort() 30 | network.valid() 31 | 32 | simulation = Simulation() 33 | 34 | # Simulation meta-data 35 | simulation.setType(Type.abstract) 36 | simulation.setPlatform(Platform.continuous) 37 | simulation.setNetwork(network) 38 | 39 | # Fluid & Resistance Model 40 | f0 = simulation.addFluid(997, 1e-3, 1.0) 41 | simulation.setContinuousPhase(f0) 42 | simulation.setRectangularResistanceModel() 43 | 44 | simulation.simulate() 45 | 46 | simulation.saveResult("continuousAbstract.JSON") 47 | 48 | def main(): 49 | abstractContinuous() 50 | 51 | if __name__ == "__main__": 52 | main() -------------------------------------------------------------------------------- /examples/Abstract/Droplet/Network1.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "network": { 3 | "nodes": [ 4 | { 5 | "x": 0.0, 6 | "y": 0.0, 7 | "z": 0.0 8 | }, 9 | { 10 | "x": 1e-3, 11 | "y": 0.0, 12 | "z": 0.0 13 | }, 14 | { 15 | "x": 2e-3, 16 | "y": 0.0, 17 | "z": 0.0 18 | }, 19 | { 20 | "x": 2.5e-3, 21 | "y": 0.86602540378e-3, 22 | "z": 0.0 23 | }, 24 | { 25 | "x": 3e-3, 26 | "y": 0.0, 27 | "z": 0.0 28 | }, 29 | { 30 | "x": 4e-3, 31 | "y": 0.0, 32 | "z": 0.0, 33 | "ground": true, 34 | "sink": true 35 | } 36 | ], 37 | "channels": [ 38 | { 39 | "node1": 0, 40 | "node2": 1, 41 | "width": 1e-4, 42 | "height": 3e-5 43 | }, 44 | { 45 | "node1": 1, 46 | "node2": 2, 47 | "width": 1e-4, 48 | "height": 3e-5 49 | }, 50 | { 51 | "node1": 2, 52 | "node2": 3, 53 | "width": 1e-4, 54 | "height": 3e-5 55 | }, 56 | { 57 | "node1": 2, 58 | "node2": 4, 59 | "width": 1e-4, 60 | "height": 3e-5 61 | }, 62 | { 63 | "node1": 3, 64 | "node2": 4, 65 | "width": 1e-4, 66 | "height": 3e-5 67 | }, 68 | { 69 | "node1": 4, 70 | "node2": 5, 71 | "width": 1e-4, 72 | "height": 3e-5 73 | }, 74 | { 75 | "node1": 5, 76 | "node2": 0, 77 | "width": 1e-4, 78 | "height": 3e-5 79 | } 80 | ] 81 | }, 82 | "simulation": { 83 | "platform": "BigDroplet", 84 | "type": "Abstract", 85 | "resistanceModel": "Rectangular", 86 | "fluids": [ 87 | { 88 | "name": "Water", 89 | "concentration": 1, 90 | "density": 1e3, 91 | "viscosity": 1e-3 92 | }, 93 | { 94 | "name": "Oil", 95 | "concentration": 1, 96 | "density": 1e3, 97 | "viscosity": 3e-3 98 | } 99 | ], 100 | "pumps": [ 101 | { 102 | "channel":6, 103 | "type": "PumpFlowrate", 104 | "flowRate": 3e-11 105 | } 106 | ], 107 | "fixtures": [ 108 | { 109 | "name": "Setup #1", 110 | "phase": 0, 111 | "bigDropletInjections": [ 112 | { 113 | "fluid": 1, 114 | "volume": 4.5e-13, 115 | "channel": 0, 116 | "pos": 0.5, 117 | "t0": 0, 118 | "deltaT": 0, 119 | "t1": 0 120 | } 121 | ] 122 | } 123 | ], 124 | "activeFixture": 0, 125 | "settings": { 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /examples/Abstract/Droplet/Network1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | using T = double; 7 | 8 | int main(int argc, char const* argv []) { 9 | // define simulation 10 | sim::Simulation testSimulation; 11 | testSimulation.setType(sim::Type::Abstract); 12 | testSimulation.setPlatform(sim::Platform::BigDroplet); 13 | 14 | // define network 15 | arch::Network network; 16 | testSimulation.setNetwork(&network); 17 | 18 | // nodes 19 | auto node1 = network.addNode(0.0, 0.0, false); 20 | auto node2 = network.addNode(1e-3, 0.0, false); 21 | auto node3 = network.addNode(2e-3, 0.0, false); 22 | auto node4 = network.addNode(2.5e-3, 0.86602540378e-3, false); 23 | auto node5 = network.addNode(3e-3, 0.0, false); 24 | auto node0 = network.addNode(4e-3, 0.0, false); 25 | 26 | // flowRate pump 27 | auto flowRate = 3e-11; 28 | auto pump = network.addFlowRatePump(node0->getId(), node1->getId(), flowRate); 29 | 30 | // channels 31 | auto cWidth = 100e-6; 32 | auto cHeight = 30e-6; 33 | auto cLength = 1000e-6; 34 | 35 | auto c1 = network.addChannel(node1->getId(), node2->getId(), cHeight, cWidth, cLength, arch::ChannelType::NORMAL); 36 | auto c2 = network.addChannel(node2->getId(), node3->getId(), cHeight, cWidth, cLength, arch::ChannelType::NORMAL); 37 | auto c3 = network.addChannel(node3->getId(), node4->getId(), cHeight, cWidth, cLength, arch::ChannelType::NORMAL); 38 | auto c4 = network.addChannel(node3->getId(), node5->getId(), cHeight, cWidth, cLength, arch::ChannelType::NORMAL); 39 | auto c5 = network.addChannel(node4->getId(), node5->getId(), cHeight, cWidth, cLength, arch::ChannelType::NORMAL); 40 | auto c6 = network.addChannel(node5->getId(), node0->getId(), cHeight, cWidth, cLength, arch::ChannelType::NORMAL); 41 | 42 | //--- sink --- 43 | network.setSink(node0->getId()); 44 | //--- ground --- 45 | network.setGround(node0->getId()); 46 | 47 | // fluids 48 | auto fluid0 = testSimulation.addFluid(1e-3, 1e3, 1.0); 49 | auto fluid1 = testSimulation.addFluid(3e-3, 1e3, 1.0); 50 | //--- continuousPhase --- 51 | testSimulation.setContinuousPhase(fluid0->getId()); 52 | 53 | // droplet 54 | auto dropletVolume = 1.5 * cWidth * cWidth * cHeight; 55 | auto droplet0 = testSimulation.addDroplet(fluid1->getId(), dropletVolume); 56 | testSimulation.addDropletInjection(droplet0->getId(), 0.0, c1->getId(), 0.5); 57 | 58 | // Define and set the resistance model 59 | sim::ResistanceModel1D resistanceModel = sim::ResistanceModel1D(testSimulation.getContinuousPhase()->getViscosity()); 60 | testSimulation.setResistanceModel(&resistanceModel); 61 | 62 | // check if chip is valid 63 | network.isNetworkValid(); 64 | network.sortGroups(); 65 | 66 | // simulate 67 | testSimulation.simulate(); 68 | 69 | // results 70 | result::SimulationResult* result = testSimulation.getSimulationResults(); 71 | result->printLastState(); 72 | 73 | return 0; 74 | } -------------------------------------------------------------------------------- /examples/Abstract/Droplet/Network1.py: -------------------------------------------------------------------------------- 1 | from mmft.simulator import * 2 | 3 | # Droplet Abstract 4 | def abstractDroplet(): 5 | 6 | network = Network() 7 | 8 | # Nodes 9 | n0 = network.addNode(0.0, 0.0, False) 10 | n1 = network.addNode(1e-3, 0.0, False) 11 | n2 = network.addNode(2e-3, 0.0, False) 12 | n3 = network.addNode(2.5e-3, 0.86602540378e-3, False) 13 | n4 = network.addNode(3e-3, 0.0, False) 14 | n5 = network.addNode(4e-3, 0.0, True, True) 15 | 16 | # Channels 17 | c0 = network.addChannel(n0, n1, 1e-4, 3e-5, ChannelType.normal) 18 | network.addChannel(n1, n2, 1e-4, 3e-5, ChannelType.normal) 19 | network.addChannel(n2, n3, 1e-4, 3e-5, ChannelType.normal) 20 | network.addChannel(n2, n4, 1e-4, 3e-5, ChannelType.normal) 21 | network.addChannel(n3, n4, 1e-4, 3e-5, ChannelType.normal) 22 | network.addChannel(n4, n5, 1e-4, 3e-5, ChannelType.normal) 23 | network.addFlowRatePump(n5, n0, 3e-11) 24 | 25 | network.sort() 26 | network.valid() 27 | 28 | simulation = Simulation() 29 | 30 | # Simulation meta-data 31 | simulation.setType(Type.abstract) 32 | simulation.setPlatform(Platform.bigDroplet) 33 | simulation.setNetwork(network) 34 | 35 | # Fluid & Resistance Model 36 | water = simulation.addFluid(1e3, 1e-3, 1.0) 37 | oil = simulation.addFluid(1e3, 3e-3, 1.0) 38 | simulation.setContinuousPhase(water) 39 | simulation.setRectangularResistanceModel() 40 | d1 = simulation.addDroplet(oil, 4.5e-13) 41 | simulation.injectDroplet(d1, 0.0, c0, 0.5) 42 | 43 | simulation.simulate() 44 | 45 | simulation.saveResult("dropletAbstract.JSON") 46 | 47 | def main(): 48 | abstractDroplet() 49 | 50 | if __name__ == "__main__": 51 | main() -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Case1.JSON: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "network": { 4 | "nodes": [ 5 | { 6 | "x": 0.0, 7 | "y": 0.0, 8 | "z": 0.0, 9 | "ground": true 10 | }, 11 | { 12 | "x": 1e-3, 13 | "y": 0.0, 14 | "z": 0.0 15 | }, 16 | { 17 | "x": 0.0, 18 | "y": 2e-3, 19 | "z": 0.0, 20 | "ground": true 21 | }, 22 | { 23 | "x": 1e-3, 24 | "y": 2e-3, 25 | "z": 0.0 26 | }, 27 | { 28 | "x": 3e-3, 29 | "y": 1e-3, 30 | "z": 0.0 31 | }, 32 | { 33 | "x": 4e-3, 34 | "y": 1e-3, 35 | "z": 0.0, 36 | "ground": true, 37 | "sink": true 38 | } 39 | ], 40 | "channels": [ 41 | { 42 | "node1": 0, 43 | "node2": 1, 44 | "width": 1e-4, 45 | "height": 1e-4 46 | }, 47 | { 48 | "node1": 2, 49 | "node2": 3, 50 | "width": 1e-4, 51 | "height": 1e-4 52 | }, 53 | { 54 | "node1": 1, 55 | "node2": 4, 56 | "width": 1e-4, 57 | "height": 1e-4 58 | }, 59 | { 60 | "node1": 3, 61 | "node2": 4, 62 | "width": 1e-4, 63 | "height": 1e-4 64 | }, 65 | { 66 | "node1": 4, 67 | "node2": 5, 68 | "width": 1e-4, 69 | "height": 1e-4 70 | } 71 | ] 72 | }, 73 | "simulation": { 74 | "platform": "Mixing", 75 | "type": "Abstract", 76 | "resistanceModel": "Rectangular", 77 | "mixingModel": "Instantaneous", 78 | "fluids": [ 79 | { 80 | "name": "Water", 81 | "concentration": 1, 82 | "density": 1e3, 83 | "viscosity": 1e-3 84 | } 85 | ], 86 | "species": [ 87 | { 88 | "name": "Oxygen", 89 | "diffusivity": 2.3e-9, 90 | "saturationConcentration": 8.3, 91 | "molecularSize": 0.0 92 | } 93 | ], 94 | "mixtures": [ 95 | { 96 | "species": [0], 97 | "concentrations": [4.0] 98 | } 99 | ], 100 | "pumps": [ 101 | { 102 | "channel":0, 103 | "type": "PumpFlowrate", 104 | "flowRate": 3e-11 105 | }, 106 | { 107 | "channel":1, 108 | "type": "PumpFlowrate", 109 | "flowRate": 3e-11 110 | } 111 | ], 112 | "fixtures": [ 113 | { 114 | "name": "Setup #1", 115 | "phase": 0, 116 | "mixtureInjections": [ 117 | { 118 | "mixture": 0, 119 | "channel": 2, 120 | "t0": 0.0 121 | } 122 | ] 123 | } 124 | ], 125 | "activeFixture": 0, 126 | "settings": { 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Case10.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Network5", 3 | "simulation": { 4 | "platform": "Mixing", 5 | "type": "Abstract", 6 | "resistanceModel": "Rectangular", 7 | "mixingModel": "Instantaneous", 8 | "fluids": [ 9 | { 10 | "name": "Water", 11 | "concentration": 1, 12 | "density": 1e3, 13 | "viscosity": 1e-3 14 | } 15 | ], 16 | "species": [ 17 | { 18 | "name": "Oxygen", 19 | "diffusivity": 2.3e-9, 20 | "saturationConcentration": 8.3, 21 | "molecularSize": 0.0 22 | }, 23 | { 24 | "name": "Glucose", 25 | "diffusivity": 3.0e-8, 26 | "saturationConcentration": 109, 27 | "molecularSize": 0.0 28 | } 29 | ], 30 | "mixtures": [ 31 | { 32 | "species": [0], 33 | "concentrations": [4.0] 34 | }, 35 | { 36 | "species": [0, 1], 37 | "concentrations": [2.0, 18.0] 38 | }, 39 | { 40 | "species": [1], 41 | "concentrations": [8.0] 42 | } 43 | ], 44 | "pumps": [ 45 | { 46 | "channel":0, 47 | "type": "PumpFlowrate", 48 | "flowRate": 3e-11 49 | }, 50 | { 51 | "channel":1, 52 | "type": "PumpFlowrate", 53 | "flowRate": 3e-11 54 | }, 55 | { 56 | "channel":2, 57 | "type": "PumpFlowrate", 58 | "flowRate": 3e-11 59 | } 60 | ], 61 | "fixtures": [ 62 | { 63 | "name": "Setup #1", 64 | "phase": 0, 65 | "mixtureInjections": [ 66 | { 67 | "mixture": 0, 68 | "channel": 3, 69 | "t0": 0.0 70 | }, 71 | { 72 | "mixture": 1, 73 | "channel": 4, 74 | "t0": 0.5 75 | }, 76 | { 77 | "mixture": 2, 78 | "channel": 5, 79 | "t0": 2.0 80 | } 81 | ] 82 | } 83 | ], 84 | "activeFixture": 0, 85 | "settings": { 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Case11.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Network6", 3 | "simulation": { 4 | "platform": "Mixing", 5 | "type": "Abstract", 6 | "resistanceModel": "Rectangular", 7 | "mixingModel": "Instantaneous", 8 | "fluids": [ 9 | { 10 | "name": "Water", 11 | "concentration": 1, 12 | "density": 1e3, 13 | "viscosity": 1e-3 14 | } 15 | ], 16 | "species": [ 17 | { 18 | "name": "Oxygen", 19 | "diffusivity": 2.3e-9, 20 | "saturationConcentration": 8.3, 21 | "molecularSize": 0.0 22 | } 23 | ], 24 | "mixtures": [ 25 | { 26 | "species": [0], 27 | "concentrations": [4.0] 28 | } 29 | ], 30 | "pumps": [ 31 | { 32 | "channel":0, 33 | "type": "PumpFlowrate", 34 | "flowRate": 3e-11 35 | }, 36 | { 37 | "channel":2, 38 | "type": "PumpFlowrate", 39 | "flowRate": 3e-11 40 | } 41 | ], 42 | "fixtures": [ 43 | { 44 | "name": "Setup #1", 45 | "phase": 0, 46 | "mixtureInjections": [ 47 | { 48 | "mixture": 0, 49 | "channel": 1, 50 | "t0": 0.0 51 | } 52 | ] 53 | } 54 | ], 55 | "activeFixture": 0, 56 | "settings": { 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Case12.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Network6", 3 | "simulation": { 4 | "platform": "Mixing", 5 | "type": "Abstract", 6 | "resistanceModel": "Rectangular", 7 | "mixingModel": "Instantaneous", 8 | "fluids": [ 9 | { 10 | "name": "Water", 11 | "concentration": 1, 12 | "density": 1e3, 13 | "viscosity": 1e-3 14 | } 15 | ], 16 | "species": [ 17 | { 18 | "name": "Oxygen", 19 | "diffusivity": 2.3e-9, 20 | "saturationConcentration": 8.3, 21 | "molecularSize": 0.0 22 | }, 23 | { 24 | "name": "Glucose", 25 | "diffusivity": 3.0e-8, 26 | "saturationConcentration": 109, 27 | "molecularSize": 0.0 28 | } 29 | ], 30 | "mixtures": [ 31 | { 32 | "species": [0], 33 | "concentrations": [4.0] 34 | }, 35 | { 36 | "species": [0, 1], 37 | "concentrations": [2.0, 18.0] 38 | } 39 | ], 40 | "pumps": [ 41 | { 42 | "channel":0, 43 | "type": "PumpFlowrate", 44 | "flowRate": 3e-11 45 | }, 46 | { 47 | "channel":2, 48 | "type": "PumpFlowrate", 49 | "flowRate": 3e-11 50 | } 51 | ], 52 | "fixtures": [ 53 | { 54 | "name": "Setup #1", 55 | "phase": 0, 56 | "mixtureInjections": [ 57 | { 58 | "mixture": 0, 59 | "channel": 1, 60 | "t0": 0.0 61 | }, 62 | { 63 | "mixture": 1, 64 | "channel": 3, 65 | "t0": 0.0 66 | } 67 | ] 68 | } 69 | ], 70 | "activeFixture": 0, 71 | "settings": { 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Case2.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Network1", 3 | "simulation": { 4 | "platform": "Mixing", 5 | "type": "Abstract", 6 | "resistanceModel": "Rectangular", 7 | "mixingModel": "Instantaneous", 8 | "fluids": [ 9 | { 10 | "name": "Water", 11 | "concentration": 1, 12 | "density": 1e3, 13 | "viscosity": 1e-3 14 | } 15 | ], 16 | "species": [ 17 | { 18 | "name": "Oxygen", 19 | "diffusivity": 2.3e-9, 20 | "saturationConcentration": 8.3, 21 | "molecularSize": 0.0 22 | } 23 | ], 24 | "mixtures": [ 25 | { 26 | "species": [0], 27 | "concentrations": [4.0] 28 | }, 29 | { 30 | "species": [0], 31 | "concentrations": [5.0] 32 | } 33 | ], 34 | "pumps": [ 35 | { 36 | "channel":0, 37 | "type": "PumpFlowrate", 38 | "flowRate": 3e-11 39 | }, 40 | { 41 | "channel":1, 42 | "type": "PumpFlowrate", 43 | "flowRate": 3e-11 44 | } 45 | ], 46 | "fixtures": [ 47 | { 48 | "name": "Setup #1", 49 | "phase": 0, 50 | "mixtureInjections": [ 51 | { 52 | "mixture": 0, 53 | "channel": 2, 54 | "t0": 0.0 55 | }, 56 | { 57 | "mixture": 1, 58 | "channel": 3, 59 | "t0": 0.5 60 | } 61 | ] 62 | } 63 | ], 64 | "activeFixture": 0, 65 | "settings": { 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Case3.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Network2", 3 | "simulation": { 4 | "platform": "Mixing", 5 | "type": "Abstract", 6 | "resistanceModel": "Rectangular", 7 | "mixingModel": "Instantaneous", 8 | "fluids": [ 9 | { 10 | "name": "Water", 11 | "concentration": 1, 12 | "density": 1e3, 13 | "viscosity": 1e-3 14 | } 15 | ], 16 | "species": [ 17 | { 18 | "name": "Oxygen", 19 | "diffusivity": 2.3e-9, 20 | "saturationConcentration": 8.3, 21 | "molecularSize": 0.0 22 | } 23 | ], 24 | "mixtures": [ 25 | { 26 | "species": [0], 27 | "concentrations": [4.0] 28 | } 29 | ], 30 | "pumps": [ 31 | { 32 | "channel":0, 33 | "type": "PumpFlowrate", 34 | "flowRate": 3e-11 35 | } 36 | ], 37 | "fixtures": [ 38 | { 39 | "name": "Setup #1", 40 | "phase": 0, 41 | "mixtureInjections": [ 42 | { 43 | "mixture": 0, 44 | "channel": 1, 45 | "t0": 0.0 46 | } 47 | ] 48 | } 49 | ], 50 | "activeFixture": 0, 51 | "settings": { 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Case4.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Network2", 3 | "simulation": { 4 | "platform": "Mixing", 5 | "type": "Abstract", 6 | "resistanceModel": "Rectangular", 7 | "mixingModel": "Instantaneous", 8 | "fluids": [ 9 | { 10 | "name": "Water", 11 | "concentration": 1, 12 | "density": 1e3, 13 | "viscosity": 1e-3 14 | } 15 | ], 16 | "species": [ 17 | { 18 | "name": "Oxygen", 19 | "diffusivity": 2.3e-9, 20 | "saturationConcentration": 8.3, 21 | "molecularSize": 0.0 22 | }, 23 | { 24 | "name": "Glucose", 25 | "diffusivity": 3.0e-8, 26 | "saturationConcentration": 109, 27 | "molecularSize": 0.0 28 | } 29 | ], 30 | "mixtures": [ 31 | { 32 | "species": [0], 33 | "concentrations": [4.0] 34 | }, 35 | { 36 | "species": [0, 1], 37 | "concentrations": [2.0, 18.0] 38 | } 39 | ], 40 | "pumps": [ 41 | { 42 | "channel":0, 43 | "type": "PumpFlowrate", 44 | "flowRate": 3e-11 45 | } 46 | ], 47 | "fixtures": [ 48 | { 49 | "name": "Setup #1", 50 | "phase": 0, 51 | "mixtureInjections": [ 52 | { 53 | "mixture": 0, 54 | "channel": 1, 55 | "t0": 0.0 56 | }, 57 | { 58 | "mixture": 1, 59 | "channel": 1, 60 | "t0": 3.0 61 | } 62 | ] 63 | } 64 | ], 65 | "activeFixture": 0, 66 | "settings": { 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Case5.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Network3", 3 | "simulation": { 4 | "platform": "Mixing", 5 | "type": "Abstract", 6 | "resistanceModel": "Rectangular", 7 | "mixingModel": "Instantaneous", 8 | "fluids": [ 9 | { 10 | "name": "Water", 11 | "concentration": 1, 12 | "density": 1e3, 13 | "viscosity": 1e-3 14 | } 15 | ], 16 | "species": [ 17 | { 18 | "name": "Oxygen", 19 | "diffusivity": 2.3e-9, 20 | "saturationConcentration": 8.3, 21 | "molecularSize": 0.0 22 | } 23 | ], 24 | "mixtures": [ 25 | { 26 | "species": [0], 27 | "concentrations": [4.0] 28 | } 29 | ], 30 | "pumps": [ 31 | { 32 | "channel":0, 33 | "type": "PumpFlowrate", 34 | "flowRate": 3e-11 35 | } 36 | ], 37 | "fixtures": [ 38 | { 39 | "name": "Setup #1", 40 | "phase": 0, 41 | "mixtureInjections": [ 42 | { 43 | "mixture": 0, 44 | "channel": 1, 45 | "t0": 0.0 46 | } 47 | ] 48 | } 49 | ], 50 | "activeFixture": 0, 51 | "settings": { 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Case6.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Network3", 3 | "simulation": { 4 | "platform": "Mixing", 5 | "type": "Abstract", 6 | "resistanceModel": "Rectangular", 7 | "mixingModel": "Instantaneous", 8 | "fluids": [ 9 | { 10 | "name": "Water", 11 | "concentration": 1, 12 | "density": 1e3, 13 | "viscosity": 1e-3 14 | } 15 | ], 16 | "species": [ 17 | { 18 | "name": "Oxygen", 19 | "diffusivity": 2.3e-9, 20 | "saturationConcentration": 8.3, 21 | "molecularSize": 0.0 22 | }, 23 | { 24 | "name": "Glucose", 25 | "diffusivity": 3.0e-8, 26 | "saturationConcentration": 109, 27 | "molecularSize": 0.0 28 | } 29 | ], 30 | "mixtures": [ 31 | { 32 | "species": [0], 33 | "concentrations": [4.0] 34 | }, 35 | { 36 | "species": [0, 1], 37 | "concentrations": [2.0, 18.0] 38 | } 39 | ], 40 | "pumps": [ 41 | { 42 | "channel":0, 43 | "type": "PumpFlowrate", 44 | "flowRate": 3e-11 45 | } 46 | ], 47 | "fixtures": [ 48 | { 49 | "name": "Setup #1", 50 | "phase": 0, 51 | "mixtureInjections": [ 52 | { 53 | "mixture": 0, 54 | "channel": 1, 55 | "t0": 0.0 56 | }, 57 | { 58 | "mixture": 1, 59 | "channel": 1, 60 | "t0": 0.5 61 | } 62 | ] 63 | } 64 | ], 65 | "activeFixture": 0, 66 | "settings": { 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Case7.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Network4", 3 | "simulation": { 4 | "platform": "Mixing", 5 | "type": "Abstract", 6 | "resistanceModel": "Rectangular", 7 | "mixingModel": "Instantaneous", 8 | "fluids": [ 9 | { 10 | "name": "Water", 11 | "concentration": 1, 12 | "density": 1e3, 13 | "viscosity": 1e-3 14 | } 15 | ], 16 | "species": [ 17 | { 18 | "name": "Oxygen", 19 | "diffusivity": 2.3e-9, 20 | "saturationConcentration": 8.3, 21 | "molecularSize": 0.0 22 | } 23 | ], 24 | "mixtures": [ 25 | { 26 | "species": [0], 27 | "concentrations": [4.0] 28 | } 29 | ], 30 | "pumps": [ 31 | { 32 | "channel":0, 33 | "type": "PumpFlowrate", 34 | "flowRate": 3e-11 35 | }, 36 | { 37 | "channel":2, 38 | "type": "PumpFlowrate", 39 | "flowRate": 3e-11 40 | } 41 | ], 42 | "fixtures": [ 43 | { 44 | "name": "Setup #1", 45 | "phase": 0, 46 | "mixtureInjections": [ 47 | { 48 | "mixture": 0, 49 | "channel": 1, 50 | "t0": 0.0 51 | }, 52 | { 53 | "mixture": 0, 54 | "channel": 3, 55 | "t0": 0.0 56 | } 57 | ] 58 | } 59 | ], 60 | "activeFixture": 0, 61 | "settings": { 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Case8.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Network4", 3 | "simulation": { 4 | "platform": "Mixing", 5 | "type": "Abstract", 6 | "resistanceModel": "Rectangular", 7 | "mixingModel": "Instantaneous", 8 | "fluids": [ 9 | { 10 | "name": "Water", 11 | "concentration": 1, 12 | "density": 1e3, 13 | "viscosity": 1e-3 14 | } 15 | ], 16 | "species": [ 17 | { 18 | "name": "Oxygen", 19 | "diffusivity": 2.3e-9, 20 | "saturationConcentration": 8.3, 21 | "molecularSize": 0.0 22 | }, 23 | { 24 | "name": "Glucose", 25 | "diffusivity": 3.0e-8, 26 | "saturationConcentration": 109, 27 | "molecularSize": 0.0 28 | } 29 | ], 30 | "mixtures": [ 31 | { 32 | "species": [0], 33 | "concentrations": [4.0] 34 | }, 35 | { 36 | "species": [0, 1], 37 | "concentrations": [2.0, 18.0] 38 | }, 39 | { 40 | "species": [1], 41 | "concentrations": [8.0] 42 | } 43 | ], 44 | "pumps": [ 45 | { 46 | "channel":0, 47 | "type": "PumpFlowrate", 48 | "flowRate": 3e-11 49 | }, 50 | { 51 | "channel":2, 52 | "type": "PumpFlowrate", 53 | "flowRate": 3e-11 54 | } 55 | ], 56 | "fixtures": [ 57 | { 58 | "name": "Setup #1", 59 | "phase": 0, 60 | "mixtureInjections": [ 61 | { 62 | "mixture": 0, 63 | "channel": 1, 64 | "t0": 0.0 65 | }, 66 | { 67 | "mixture": 1, 68 | "channel": 3, 69 | "t0": 0.0 70 | }, 71 | { 72 | "mixture": 2, 73 | "channel": 3, 74 | "t0": 2.0 75 | } 76 | ] 77 | } 78 | ], 79 | "activeFixture": 0, 80 | "settings": { 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Case9.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "_comment": "Network5", 3 | "simulation": { 4 | "platform": "Mixing", 5 | "type": "Abstract", 6 | "resistanceModel": "Rectangular", 7 | "mixingModel": "Instantaneous", 8 | "fluids": [ 9 | { 10 | "name": "Water", 11 | "concentration": 1, 12 | "density": 1e3, 13 | "viscosity": 1e-3 14 | } 15 | ], 16 | "species": [ 17 | { 18 | "name": "Oxygen", 19 | "diffusivity": 2.3e-9, 20 | "saturationConcentration": 8.3, 21 | "molecularSize": 0.0 22 | } 23 | ], 24 | "mixtures": [ 25 | { 26 | "species": [0], 27 | "concentrations": [4.0] 28 | } 29 | ], 30 | "pumps": [ 31 | { 32 | "channel":0, 33 | "type": "PumpFlowrate", 34 | "flowRate": 3e-11 35 | }, 36 | { 37 | "channel":1, 38 | "type": "PumpFlowrate", 39 | "flowRate": 3e-11 40 | }, 41 | { 42 | "channel":2, 43 | "type": "PumpFlowrate", 44 | "flowRate": 3e-11 45 | } 46 | ], 47 | "fixtures": [ 48 | { 49 | "name": "Setup #1", 50 | "phase": 0, 51 | "mixtureInjections": [ 52 | { 53 | "mixture": 0, 54 | "channel": 3, 55 | "t0": 0.0 56 | }, 57 | { 58 | "mixture": 0, 59 | "channel": 4, 60 | "t0": 0.5 61 | }, 62 | { 63 | "mixture": 0, 64 | "channel": 5, 65 | "t0": 2.0 66 | } 67 | ] 68 | } 69 | ], 70 | "activeFixture": 0, 71 | "settings": { 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Network1.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "network": { 3 | "nodes": [ 4 | { 5 | "x": 0.0, 6 | "y": 0.0, 7 | "z": 0.0, 8 | "ground": true 9 | }, 10 | { 11 | "x": 1e-3, 12 | "y": 0.0, 13 | "z": 0.0 14 | }, 15 | { 16 | "x": 0.0, 17 | "y": 2e-3, 18 | "z": 0.0, 19 | "ground": true 20 | }, 21 | { 22 | "x": 1e-3, 23 | "y": 2e-3, 24 | "z": 0.0 25 | }, 26 | { 27 | "x": 3e-3, 28 | "y": 1e-3, 29 | "z": 0.0 30 | }, 31 | { 32 | "x": 4e-3, 33 | "y": 1e-3, 34 | "z": 0.0, 35 | "ground": true, 36 | "sink": true 37 | } 38 | ], 39 | "channels": [ 40 | { 41 | "node1": 0, 42 | "node2": 1, 43 | "width": 1e-4, 44 | "height": 1e-4 45 | }, 46 | { 47 | "node1": 2, 48 | "node2": 3, 49 | "width": 1e-4, 50 | "height": 1e-4 51 | }, 52 | { 53 | "node1": 1, 54 | "node2": 4, 55 | "width": 1e-4, 56 | "height": 1e-4 57 | }, 58 | { 59 | "node1": 3, 60 | "node2": 4, 61 | "width": 1e-4, 62 | "height": 1e-4 63 | }, 64 | { 65 | "node1": 4, 66 | "node2": 5, 67 | "width": 1e-4, 68 | "height": 1e-4 69 | } 70 | ] 71 | }} 72 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Network2.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "network": { 3 | "nodes": [ 4 | { 5 | "x": 0.0, 6 | "y": 1e-3, 7 | "z": 0.0, 8 | "ground": true 9 | }, 10 | { 11 | "x": 1e-3, 12 | "y": 1e-3, 13 | "z": 0.0 14 | }, 15 | { 16 | "x": 3e-3, 17 | "y": 1e-3, 18 | "z": 0.0 19 | }, 20 | { 21 | "x": 5e-3, 22 | "y": 0.0, 23 | "z": 0.0, 24 | "ground": true, 25 | "sink": true 26 | }, 27 | { 28 | "x": 5e-3, 29 | "y": 2e-3, 30 | "z": 0.0, 31 | "ground": true, 32 | "sink": true 33 | } 34 | ], 35 | "channels": [ 36 | { 37 | "node1": 0, 38 | "node2": 1, 39 | "width": 1e-4, 40 | "height": 1e-4 41 | }, 42 | { 43 | "node1": 1, 44 | "node2": 2, 45 | "width": 1e-4, 46 | "height": 1e-4 47 | }, 48 | { 49 | "node1": 2, 50 | "node2": 3, 51 | "width": 1e-4, 52 | "height": 1e-4 53 | }, 54 | { 55 | "node1": 2, 56 | "node2": 4, 57 | "width": 1e-4, 58 | "height": 1e-4 59 | } 60 | ] 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Network3.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "network": { 3 | "nodes": [ 4 | { 5 | "x": 0.0, 6 | "y": 1e-3, 7 | "z": 0.0, 8 | "ground": true 9 | }, 10 | { 11 | "x": 1e-3, 12 | "y": 1e-3, 13 | "z": 0.0 14 | }, 15 | { 16 | "x": 2e-3, 17 | "y": 1e-3, 18 | "z": 0.0 19 | }, 20 | { 21 | "x": 4e-3, 22 | "y": 0.0, 23 | "z": 0.0, 24 | "ground": true, 25 | "sink": true 26 | }, 27 | { 28 | "x": 4e-3, 29 | "y": 1e-3, 30 | "z": 0.0, 31 | "ground": true, 32 | "sink": true 33 | }, 34 | { 35 | "x": 4e-3, 36 | "y": 2e-3, 37 | "z": 0.0, 38 | "ground": true, 39 | "sink": true 40 | } 41 | ], 42 | "channels": [ 43 | { 44 | "node1": 0, 45 | "node2": 1, 46 | "width": 1e-4, 47 | "height": 1e-4 48 | }, 49 | { 50 | "node1": 1, 51 | "node2": 2, 52 | "width": 1e-4, 53 | "height": 1e-4 54 | }, 55 | { 56 | "node1": 2, 57 | "node2": 3, 58 | "width": 1e-4, 59 | "height": 1e-4 60 | }, 61 | { 62 | "node1": 2, 63 | "node2": 4, 64 | "width": 1e-4, 65 | "height": 1e-4 66 | }, 67 | { 68 | "node1": 2, 69 | "node2": 5, 70 | "width": 1e-4, 71 | "height": 1e-4 72 | } 73 | ] 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Network4.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "network": { 3 | "nodes": [ 4 | { 5 | "x": 0.0, 6 | "y": 0.0, 7 | "z": 0.0, 8 | "ground": true 9 | }, 10 | { 11 | "x": 1e-3, 12 | "y": 0.0, 13 | "z": 0.0 14 | }, 15 | { 16 | "x": 0.0, 17 | "y": 2e-3, 18 | "z": 0.0, 19 | "ground": true 20 | }, 21 | { 22 | "x": 1e-3, 23 | "y": 2e-3, 24 | "z": 0.0 25 | }, 26 | { 27 | "x": 3e-3, 28 | "y": 1e-3, 29 | "z": 0.0 30 | }, 31 | { 32 | "x": 4e-3, 33 | "y": 0.0, 34 | "z": 0.0, 35 | "ground": true, 36 | "sink": true 37 | }, 38 | { 39 | "x": 4e-3, 40 | "y": 2e-3, 41 | "z": 0.0, 42 | "ground": true, 43 | "sink": true 44 | } 45 | ], 46 | "channels": [ 47 | { 48 | "node1": 0, 49 | "node2": 1, 50 | "width": 1e-4, 51 | "height": 1e-4 52 | }, 53 | { 54 | "node1": 1, 55 | "node2": 4, 56 | "width": 1e-4, 57 | "height": 1e-4 58 | }, 59 | { 60 | "node1": 2, 61 | "node2": 3, 62 | "width": 1e-4, 63 | "height": 1e-4 64 | }, 65 | { 66 | "node1": 3, 67 | "node2": 4, 68 | "width": 1e-4, 69 | "height": 1e-4 70 | }, 71 | { 72 | "node1": 4, 73 | "node2": 5, 74 | "width": 1e-4, 75 | "height": 1e-4 76 | }, 77 | { 78 | "node1": 4, 79 | "node2": 6, 80 | "width": 1e-4, 81 | "height": 1e-4 82 | } 83 | ] 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Network5.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "network": { 3 | "nodes": [ 4 | { 5 | "x": 0.0, 6 | "y": 0.0, 7 | "z": 0.0, 8 | "ground": true 9 | }, 10 | { 11 | "x": 1e-3, 12 | "y": 0.0, 13 | "z": 0.0 14 | }, 15 | { 16 | "x": 0.0, 17 | "y": 1e-3, 18 | "z": 0.0, 19 | "ground": true 20 | }, 21 | { 22 | "x": 1e-3, 23 | "y": 1e-3, 24 | "z": 0.0 25 | }, 26 | { 27 | "x": 0.0, 28 | "y": 2e-3, 29 | "z": 0.0, 30 | "ground": true 31 | }, 32 | { 33 | "x": 1e-3, 34 | "y": 2e-3, 35 | "z": 0.0 36 | }, 37 | { 38 | "x": 3e-3, 39 | "y": 1e-3, 40 | "z": 0.0 41 | }, 42 | { 43 | "x": 4e-3, 44 | "y": 1e-3, 45 | "z": 0.0, 46 | "ground": true, 47 | "sink": true 48 | } 49 | ], 50 | "channels": [ 51 | { 52 | "node1": 0, 53 | "node2": 1, 54 | "width": 1e-4, 55 | "height": 1e-4 56 | }, 57 | { 58 | "node1": 2, 59 | "node2": 3, 60 | "width": 1e-4, 61 | "height": 1e-4 62 | }, 63 | { 64 | "node1": 4, 65 | "node2": 5, 66 | "width": 1e-4, 67 | "height": 1e-4 68 | }, 69 | { 70 | "node1": 1, 71 | "node2": 6, 72 | "width": 1e-4, 73 | "height": 1e-4 74 | }, 75 | { 76 | "node1": 3, 77 | "node2": 6, 78 | "width": 1e-4, 79 | "height": 1e-4 80 | }, 81 | { 82 | "node1": 5, 83 | "node2": 6, 84 | "width": 1e-4, 85 | "height": 1e-4 86 | }, 87 | { 88 | "node1": 6, 89 | "node2": 7, 90 | "width": 1e-4, 91 | "height": 1e-4 92 | } 93 | ] 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /examples/Abstract/Mixing/Network6.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "network": { 3 | "nodes": [ 4 | { 5 | "x": 0.0, 6 | "y": 2e-3, 7 | "z": 0.0, 8 | "ground": true 9 | }, 10 | { 11 | "x": 1e-3, 12 | "y": 2e-3, 13 | "z": 0.0 14 | }, 15 | { 16 | "x": 6e-3, 17 | "y": 0.0, 18 | "z": 0.0, 19 | "ground": true 20 | }, 21 | { 22 | "x": 5e-3, 23 | "y": 0.0, 24 | "z": 0.0 25 | }, 26 | { 27 | "x": 3e-3, 28 | "y": 1e-3, 29 | "z": 0.0 30 | }, 31 | { 32 | "x": 2e-3, 33 | "y": 0.0, 34 | "z": 0.0, 35 | "ground": true, 36 | "sink": true 37 | }, 38 | { 39 | "x": 4e-3, 40 | "y": 2e-3, 41 | "z": 0.0, 42 | "ground": true, 43 | "sink": true 44 | } 45 | ], 46 | "channels": [ 47 | { 48 | "node1": 0, 49 | "node2": 1, 50 | "width": 1e-4, 51 | "height": 1e-4 52 | }, 53 | { 54 | "node1": 1, 55 | "node2": 4, 56 | "width": 1e-4, 57 | "height": 1e-4 58 | }, 59 | { 60 | "node1": 2, 61 | "node2": 3, 62 | "width": 1e-4, 63 | "height": 1e-4 64 | }, 65 | { 66 | "node1": 3, 67 | "node2": 4, 68 | "width": 1e-4, 69 | "height": 1e-4 70 | }, 71 | { 72 | "node1": 4, 73 | "node2": 5, 74 | "width": 1e-4, 75 | "height": 1e-4 76 | }, 77 | { 78 | "node1": 4, 79 | "node2": 6, 80 | "width": 1e-4, 81 | "height": 1e-4 82 | } 83 | ] 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /examples/CFD/Network1a.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 1.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 2.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 1.0e-3, 19 | "y": 1.05e-3 20 | }, 21 | { 22 | "iD": 3, 23 | "x": 1.0e-3, 24 | "y": 0.05e-3 25 | }, 26 | { 27 | "iD": 4, 28 | "x": 3.0e-3, 29 | "y": 1.05e-3 30 | }, 31 | { 32 | "iD": -1, 33 | "x": 3.00000001e-3, 34 | "y": 1.05e-3 35 | } 36 | ], 37 | "Channels": 38 | [ 39 | { 40 | "iD": 0, 41 | "nA": 0, 42 | "nB": 1, 43 | "width": 1e-4, 44 | "height": 1e-4 45 | }, 46 | { 47 | "iD": 1, 48 | "nA": 0, 49 | "nB": 2, 50 | "width": 1e-4, 51 | "height": 1e-4 52 | }, 53 | { 54 | "iD": 2, 55 | "nA": 0, 56 | "nB": 3, 57 | "width": 1e-4, 58 | "height": 1e-4 59 | }, 60 | { 61 | "iD": 3, 62 | "nA": 4, 63 | "nB": -1, 64 | "width": 1e-4, 65 | "height": 1e-4 66 | } 67 | ], 68 | "Modules": 69 | [ 70 | { 71 | "iD": 0, 72 | "Type":"LBM", 73 | "name": "Paper1a-CFD-20", 74 | "stlFile": "../examples/STL/Network1a.stl", 75 | "charPhysLength": 1e-4, 76 | "charPhysVelocity": 1e-1, 77 | "alpha": 0.0, 78 | "resolution": 20, 79 | "epsilon": 1e-9, 80 | "tau": 0.55, 81 | "posX": 1.0e-3, 82 | "posY": 0.0e-3, 83 | "sizeX": 2e-3, 84 | "sizeY": 2.1e-3, 85 | "Openings": 86 | [ 87 | { 88 | "nodeId": 1, 89 | "normalX": 1.0, 90 | "normalY": 0.0, 91 | "width": 1e-4 92 | }, 93 | { 94 | "nodeId": 2, 95 | "normalX": 1.0, 96 | "normalY": 0.0, 97 | "width": 1e-4 98 | }, 99 | { 100 | "nodeId": 3, 101 | "normalX": 1.0, 102 | "normalY": 0.0, 103 | "width": 1e-4 104 | }, 105 | { 106 | "nodeId": 4, 107 | "normalX": -1.0, 108 | "normalY": 0.0, 109 | "width": 1e-4 110 | } 111 | ] 112 | } 113 | ] 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /examples/CFD/Network1b.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 1.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 4.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 1.0e-3, 19 | "y": 2.05e-3 20 | }, 21 | { 22 | "iD": 3, 23 | "x": 1.0e-3, 24 | "y": 0.05e-3 25 | }, 26 | { 27 | "iD": 4, 28 | "x": 5.0e-3, 29 | "y": 2.05e-3 30 | }, 31 | { 32 | "iD": -1, 33 | "x": 5.00000001e-3, 34 | "y": 2.05e-3 35 | } 36 | ], 37 | "Channels": 38 | [ 39 | { 40 | "iD": 0, 41 | "nA": 0, 42 | "nB": 1, 43 | "width": 1e-4, 44 | "height": 1e-4 45 | }, 46 | { 47 | "iD": 1, 48 | "nA": 0, 49 | "nB": 2, 50 | "width": 1e-4, 51 | "height": 1e-4 52 | }, 53 | { 54 | "iD": 2, 55 | "nA": 0, 56 | "nB": 3, 57 | "width": 1e-4, 58 | "height": 1e-4 59 | }, 60 | { 61 | "iD": 3, 62 | "nA": 4, 63 | "nB": -1, 64 | "width": 1e-4, 65 | "height": 1e-4 66 | } 67 | ], 68 | "Modules": 69 | [ 70 | { 71 | "iD": 0, 72 | "Type":"LBM", 73 | "name": "Paper1b-CFD-20", 74 | "stlFile": "../examples/STL/Network1b.stl", 75 | "charPhysLength": 1e-4, 76 | "charPhysVelocity": 1e-1, 77 | "alpha": 0.0, 78 | "resolution": 20, 79 | "epsilon": 1e-9, 80 | "tau": 0.55, 81 | "posX": 1.0e-3, 82 | "posY": 0.0e-3, 83 | "sizeX": 4e-3, 84 | "sizeY": 4.1e-3, 85 | "Openings": 86 | [ 87 | { 88 | "nodeId": 1, 89 | "normalX": 1.0, 90 | "normalY": 0.0, 91 | "width": 1e-4 92 | }, 93 | { 94 | "nodeId": 2, 95 | "normalX": 1.0, 96 | "normalY": 0.0, 97 | "width": 1e-4 98 | }, 99 | { 100 | "nodeId": 3, 101 | "normalX": 1.0, 102 | "normalY": 0.0, 103 | "width": 1e-4 104 | }, 105 | { 106 | "nodeId": 4, 107 | "normalX": -1.0, 108 | "normalY": 0.0, 109 | "width": 1e-4 110 | } 111 | ] 112 | } 113 | ] 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /examples/CFD/Network1c.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 1.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 4.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 1.0e-3, 19 | "y": 2.05e-3 20 | }, 21 | { 22 | "iD": 3, 23 | "x": 1.0e-3, 24 | "y": 0.05e-3 25 | }, 26 | { 27 | "iD": 4, 28 | "x": 7.0e-3, 29 | "y": 2.05e-3 30 | }, 31 | { 32 | "iD": -1, 33 | "x": 7.00000001e-3, 34 | "y": 2.05e-3 35 | } 36 | ], 37 | "Channels": 38 | [ 39 | { 40 | "iD": 0, 41 | "nA": 0, 42 | "nB": 1, 43 | "width": 1e-4, 44 | "height": 1e-4 45 | }, 46 | { 47 | "iD": 1, 48 | "nA": 0, 49 | "nB": 2, 50 | "width": 1e-4, 51 | "height": 1e-4 52 | }, 53 | { 54 | "iD": 2, 55 | "nA": 0, 56 | "nB": 3, 57 | "width": 1e-4, 58 | "height": 1e-4 59 | }, 60 | { 61 | "iD": 3, 62 | "nA": 4, 63 | "nB": -1, 64 | "width": 1e-4, 65 | "height": 1e-4 66 | } 67 | ], 68 | "Modules": 69 | [ 70 | { 71 | "iD": 0, 72 | "Type":"LBM", 73 | "name": "Paper1c-CFD-20", 74 | "stlFile": "../examples/STL/Network1c.stl", 75 | "charPhysLength": 1e-4, 76 | "charPhysVelocity": 1e-1, 77 | "alpha": 0.0, 78 | "resolution": 20, 79 | "epsilon": 1e-9, 80 | "tau": 0.55, 81 | "posX": 1.0e-3, 82 | "posY": 0.0e-3, 83 | "sizeX": 6e-3, 84 | "sizeY": 4.1e-3, 85 | "Openings": 86 | [ 87 | { 88 | "nodeId": 1, 89 | "normalX": 1.0, 90 | "normalY": 0.0, 91 | "width": 1e-4 92 | }, 93 | { 94 | "nodeId": 2, 95 | "normalX": 1.0, 96 | "normalY": 0.0, 97 | "width": 1e-4 98 | }, 99 | { 100 | "nodeId": 3, 101 | "normalX": 1.0, 102 | "normalY": 0.0, 103 | "width": 1e-4 104 | }, 105 | { 106 | "nodeId": 4, 107 | "normalX": -1.0, 108 | "normalY": 0.0, 109 | "width": 1e-4 110 | } 111 | ] 112 | } 113 | ] 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /examples/CFD/Network1d.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 1.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 8.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 1.0e-3, 19 | "y": 4.05e-3 20 | }, 21 | { 22 | "iD": 3, 23 | "x": 1.0e-3, 24 | "y": 0.05e-3 25 | }, 26 | { 27 | "iD": 4, 28 | "x": 9.0e-3, 29 | "y": 4.05e-3 30 | }, 31 | { 32 | "iD": -1, 33 | "x": 9.00000001e-3, 34 | "y": 4.05e-3 35 | } 36 | ], 37 | "Channels": 38 | [ 39 | { 40 | "iD": 0, 41 | "nA": 0, 42 | "nB": 1, 43 | "width": 1e-4, 44 | "height": 1e-4 45 | }, 46 | { 47 | "iD": 1, 48 | "nA": 0, 49 | "nB": 2, 50 | "width": 1e-4, 51 | "height": 1e-4 52 | }, 53 | { 54 | "iD": 2, 55 | "nA": 0, 56 | "nB": 3, 57 | "width": 1e-4, 58 | "height": 1e-4 59 | }, 60 | { 61 | "iD": 3, 62 | "nA": 4, 63 | "nB": -1, 64 | "width": 1e-4, 65 | "height": 1e-4 66 | } 67 | ], 68 | "Modules": 69 | [ 70 | { 71 | "iD": 0, 72 | "Type":"LBM", 73 | "name": "Paper1d-CFD-20", 74 | "stlFile": "../examples/STL/Network1d.stl", 75 | "charPhysLength": 1e-4, 76 | "charPhysVelocity": 1e-1, 77 | "alpha": 0.0, 78 | "resolution": 20, 79 | "epsilon": 1e-9, 80 | "tau": 0.55, 81 | "posX": 1.0e-3, 82 | "posY": 0.0e-3, 83 | "sizeX": 8e-3, 84 | "sizeY": 8.1e-3, 85 | "Openings": 86 | [ 87 | { 88 | "nodeId": 1, 89 | "normalX": 1.0, 90 | "normalY": 0.0, 91 | "width": 1e-4 92 | }, 93 | { 94 | "nodeId": 2, 95 | "normalX": 1.0, 96 | "normalY": 0.0, 97 | "width": 1e-4 98 | }, 99 | { 100 | "nodeId": 3, 101 | "normalX": 1.0, 102 | "normalY": 0.0, 103 | "width": 1e-4 104 | }, 105 | { 106 | "nodeId": 4, 107 | "normalX": -1.0, 108 | "normalY": 0.0, 109 | "width": 1e-4 110 | } 111 | ] 112 | } 113 | ] 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /examples/CFD/Network2a.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 0.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 0.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 4.0e-3, 19 | "y": 0.05e-3 20 | }, 21 | { 22 | "iD": -1, 23 | "x": 4.00000001e-3, 24 | "y": 0.05e-3 25 | } 26 | ], 27 | "Channels": 28 | [ 29 | { 30 | "iD": 0, 31 | "nA": 0, 32 | "nB": 1, 33 | "width": 1e-4, 34 | "height": 1e-4 35 | }, 36 | { 37 | "iD": 1, 38 | "nA": 2, 39 | "nB": -1, 40 | "width": 1e-4, 41 | "height": 1e-4 42 | } 43 | ], 44 | "Modules": 45 | [ 46 | { 47 | "iD": 0, 48 | "Type":"LBM", 49 | "name": "Paper2a-CFD-20", 50 | "stlFile": "../examples/STL/Network2a.stl", 51 | "charPhysLength": 1e-4, 52 | "charPhysVelocity": 1e-1, 53 | "alpha": 0.0, 54 | "resolution": 20, 55 | "tau": 0.55, 56 | "epsilon": 1e-9, 57 | "posX": 1.0e-3, 58 | "posY": 0.0e-3, 59 | "sizeX": 3e-3, 60 | "sizeY": 1.1e-3, 61 | "Openings": 62 | [ 63 | { 64 | "nodeId": 1, 65 | "normalX": 1.0, 66 | "normalY": 0.0, 67 | "width": 1e-4 68 | }, 69 | { 70 | "nodeId": 2, 71 | "normalX": -1.0, 72 | "normalY": 0.0, 73 | "width": 1e-4 74 | } 75 | ] 76 | } 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/CFD/Network2b.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 0.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 0.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 7.0e-3, 19 | "y": 0.05e-3 20 | }, 21 | { 22 | "iD": -1, 23 | "x": 7.00000001e-3, 24 | "y": 0.05e-3 25 | } 26 | ], 27 | "Channels": 28 | [ 29 | { 30 | "iD": 0, 31 | "nA": 0, 32 | "nB": 1, 33 | "width": 1e-4, 34 | "height": 1e-4 35 | }, 36 | { 37 | "iD": 1, 38 | "nA": 2, 39 | "nB": -1, 40 | "width": 1e-4, 41 | "height": 1e-4 42 | } 43 | ], 44 | "Modules": 45 | [ 46 | { 47 | "iD": 0, 48 | "Type":"LBM", 49 | "name": "Paper2b-CFD-20", 50 | "stlFile": "../examples/STL/Network2b.stl", 51 | "charPhysLength": 1e-4, 52 | "charPhysVelocity": 1e-1, 53 | "alpha": 0.0, 54 | "resolution": 20, 55 | "epsilon": 1e-9, 56 | "tau": 0.55, 57 | "posX": 1.0e-3, 58 | "posY": 0.0e-3, 59 | "sizeX": 6e-3, 60 | "sizeY": 2.1e-3, 61 | "Openings": 62 | [ 63 | { 64 | "nodeId": 1, 65 | "normalX": 1.0, 66 | "normalY": 0.0, 67 | "width": 1e-4 68 | }, 69 | { 70 | "nodeId": 2, 71 | "normalX": -1.0, 72 | "normalY": 0.0, 73 | "width": 1e-4 74 | } 75 | ] 76 | } 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/CFD/Network2c.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 0.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 0.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 10.0e-3, 19 | "y": 0.05e-3 20 | }, 21 | { 22 | "iD": -1, 23 | "x": 10.00000001e-3, 24 | "y": 0.05e-3 25 | } 26 | ], 27 | "Channels": 28 | [ 29 | { 30 | "iD": 0, 31 | "nA": 0, 32 | "nB": 1, 33 | "width": 1e-4, 34 | "height": 1e-4 35 | }, 36 | { 37 | "iD": 1, 38 | "nA": 2, 39 | "nB": -1, 40 | "width": 1e-4, 41 | "height": 1e-4 42 | } 43 | ], 44 | "Modules": 45 | [ 46 | { 47 | "iD": 0, 48 | "Type":"LBM", 49 | "name": "Paper2c-CFD-20", 50 | "stlFile": "../examples/STL/Network2c.stl", 51 | "charPhysLength": 1e-4, 52 | "charPhysVelocity": 1e-1, 53 | "alpha": 0.0, 54 | "resolution": 20, 55 | "epsilon": 1e-9, 56 | "tau": 0.55, 57 | "posX": 1.0e-3, 58 | "posY": 0.0e-3, 59 | "sizeX": 9e-3, 60 | "sizeY": 3.1e-3, 61 | "Openings": 62 | [ 63 | { 64 | "nodeId": 1, 65 | "normalX": 1.0, 66 | "normalY": 0.0, 67 | "width": 1e-4 68 | }, 69 | { 70 | "nodeId": 2, 71 | "normalX": -1.0, 72 | "normalY": 0.0, 73 | "width": 1e-4 74 | } 75 | ] 76 | } 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/CFD/Network2d.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 0.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 0.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 13.0e-3, 19 | "y": 0.05e-3 20 | }, 21 | { 22 | "iD": -1, 23 | "x": 13.00000001e-3, 24 | "y": 0.05e-3 25 | } 26 | ], 27 | "Channels": 28 | [ 29 | { 30 | "iD": 0, 31 | "nA": 0, 32 | "nB": 1, 33 | "width": 1e-4, 34 | "height": 1e-4 35 | }, 36 | { 37 | "iD": 1, 38 | "nA": 2, 39 | "nB": -1, 40 | "width": 1e-4, 41 | "height": 1e-4 42 | } 43 | ], 44 | "Modules": 45 | [ 46 | { 47 | "iD": 0, 48 | "Type":"LBM", 49 | "name": "Paper2d-CFD-20", 50 | "stlFile": "../examples/STL/Network2d.stl", 51 | "charPhysLength": 1e-4, 52 | "charPhysVelocity": 1e-1, 53 | "alpha": 0.0, 54 | "resolution": 20, 55 | "epsilon": 1e-9, 56 | "tau": 0.55, 57 | "posX": 1.0e-3, 58 | "posY": 0.0e-3, 59 | "sizeX": 12e-3, 60 | "sizeY": 4.1e-3, 61 | "Openings": 62 | [ 63 | { 64 | "nodeId": 1, 65 | "normalX": 1.0, 66 | "normalY": 0.0, 67 | "width": 1e-4 68 | }, 69 | { 70 | "nodeId": 2, 71 | "normalX": -1.0, 72 | "normalY": 0.0, 73 | "width": 1e-4 74 | } 75 | ] 76 | } 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/CFD/Network3a.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 1.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 1.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 5.0e-3, 19 | "y": 0.05e-3 20 | }, 21 | { 22 | "iD": -1, 23 | "x": 5.00000001e-3, 24 | "y": 0.05e-3 25 | } 26 | ], 27 | "Channels": 28 | [ 29 | { 30 | "iD": 0, 31 | "nA": 0, 32 | "nB": 1, 33 | "width": 1e-4, 34 | "height": 1e-4 35 | }, 36 | { 37 | "iD": 1, 38 | "nA": 2, 39 | "nB": -1, 40 | "width": 1e-4, 41 | "height": 1e-4 42 | } 43 | ], 44 | "Modules": 45 | [ 46 | { 47 | "iD": 0, 48 | "Type":"LBM", 49 | "name": "Paper3a-CFD-20", 50 | "stlFile": "../examples/STL/Network3a.stl", 51 | "charPhysLength": 1e-4, 52 | "charPhysVelocity": 1e-1, 53 | "alpha": 0.0, 54 | "resolution": 20, 55 | "epsilon": 1e-9, 56 | "tau": 0.55, 57 | "posX": 1.0e-3, 58 | "posY": 0.0e-3, 59 | "sizeX": 4e-3, 60 | "sizeY": 2.1e-3, 61 | "Openings": 62 | [ 63 | { 64 | "nodeId": 1, 65 | "normalX": 1.0, 66 | "normalY": 0.0, 67 | "width": 1e-4 68 | }, 69 | { 70 | "nodeId": 2, 71 | "normalX": -1.0, 72 | "normalY": 0.0, 73 | "width": 1e-4 74 | } 75 | ] 76 | } 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/CFD/Network3b.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 2.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 2.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 9.0e-3, 19 | "y": 0.05e-3 20 | }, 21 | { 22 | "iD": -1, 23 | "x": 9.00000001e-3, 24 | "y": 0.05e-3 25 | } 26 | ], 27 | "Channels": 28 | [ 29 | { 30 | "iD": 0, 31 | "nA": 0, 32 | "nB": 1, 33 | "width": 1e-4, 34 | "height": 1e-4 35 | }, 36 | { 37 | "iD": 1, 38 | "nA": 2, 39 | "nB": -1, 40 | "width": 1e-4, 41 | "height": 1e-4 42 | } 43 | ], 44 | "Modules": 45 | [ 46 | { 47 | "iD": 0, 48 | "Type":"LBM", 49 | "name": "Paper3b-CFD-20", 50 | "stlFile": "../examples/STL/Network3b.stl", 51 | "charPhysLength": 1e-4, 52 | "charPhysVelocity": 1e-1, 53 | "alpha": 0.0, 54 | "resolution": 20, 55 | "epsilon": 1e-9, 56 | "tau": 0.55, 57 | "posX": 1.0e-3, 58 | "posY": 0.0e-3, 59 | "sizeX": 8e-3, 60 | "sizeY": 4.1e-3, 61 | "Openings": 62 | [ 63 | { 64 | "nodeId": 1, 65 | "normalX": 1.0, 66 | "normalY": 0.0, 67 | "width": 1e-4 68 | }, 69 | { 70 | "nodeId": 2, 71 | "normalX": -1.0, 72 | "normalY": 0.0, 73 | "width": 1e-4 74 | } 75 | ] 76 | } 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/CFD/Network3c.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 1.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 3.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 13.0e-3, 19 | "y": 0.05e-3 20 | }, 21 | { 22 | "iD": -1, 23 | "x": 13.00000001e-3, 24 | "y": 0.05e-3 25 | } 26 | ], 27 | "Channels": 28 | [ 29 | { 30 | "iD": 0, 31 | "nA": 0, 32 | "nB": 1, 33 | "width": 1e-4, 34 | "height": 1e-4 35 | }, 36 | { 37 | "iD": 1, 38 | "nA": 2, 39 | "nB": -1, 40 | "width": 1e-4, 41 | "height": 1e-4 42 | } 43 | ], 44 | "Modules": 45 | [ 46 | { 47 | "iD": 0, 48 | "Type":"LBM", 49 | "name": "Paper3c-CFD-20", 50 | "stlFile": "../examples/STL/Network3c.stl", 51 | "charPhysLength": 1e-4, 52 | "charPhysVelocity": 1e-1, 53 | "alpha": 0.0, 54 | "resolution": 20, 55 | "epsilon": 1e-9, 56 | "tau": 0.55, 57 | "posX": 1.0e-3, 58 | "posY": 0.0e-3, 59 | "sizeX": 12e-3, 60 | "sizeY": 6.1e-3, 61 | "Openings": 62 | [ 63 | { 64 | "nodeId": 1, 65 | "normalX": 1.0, 66 | "normalY": 0.0, 67 | "width": 1e-4 68 | }, 69 | { 70 | "nodeId": 2, 71 | "normalX": -1.0, 72 | "normalY": 0.0, 73 | "width": 1e-4 74 | } 75 | ] 76 | } 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/CFD/Network3d.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 4.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 4.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 17.0e-3, 19 | "y": 0.05e-3 20 | }, 21 | { 22 | "iD": -1, 23 | "x": 17.00000001e-3, 24 | "y": 0.05e-3 25 | } 26 | ], 27 | "Channels": 28 | [ 29 | { 30 | "iD": 0, 31 | "nA": 0, 32 | "nB": 1, 33 | "width": 1e-4, 34 | "height": 1e-4 35 | }, 36 | { 37 | "iD": 1, 38 | "nA": 2, 39 | "nB": -1, 40 | "width": 1e-4, 41 | "height": 1e-4 42 | } 43 | ], 44 | "Modules": 45 | [ 46 | { 47 | "iD": 0, 48 | "Type":"LBM", 49 | "name": "Paper3d-CFD-20", 50 | "stlFile": "../examples/STL/Network3d.stl", 51 | "charPhysLength": 1e-4, 52 | "charPhysVelocity": 1e-1, 53 | "alpha": 0.0, 54 | "resolution": 20, 55 | "epsilon": 1e-9, 56 | "tau": 0.55, 57 | "posX": 1.0e-3, 58 | "posY": 0.0e-3, 59 | "sizeX": 16e-3, 60 | "sizeY": 8.1e-3, 61 | "Openings": 62 | [ 63 | { 64 | "nodeId": 1, 65 | "normalX": 1.0, 66 | "normalY": 0.0, 67 | "width": 1e-4 68 | }, 69 | { 70 | "nodeId": 2, 71 | "normalX": -1.0, 72 | "normalY": 0.0, 73 | "width": 1e-4 74 | } 75 | ] 76 | } 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/CFD/Network4a.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 1.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 1.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 5.0e-3, 19 | "y": 0.05e-3 20 | }, 21 | { 22 | "iD": -1, 23 | "x": 5.00000001e-3, 24 | "y": 0.05e-3 25 | } 26 | ], 27 | "Channels": 28 | [ 29 | { 30 | "iD": 0, 31 | "nA": 0, 32 | "nB": 1, 33 | "width": 1e-4, 34 | "height": 1e-4 35 | }, 36 | { 37 | "iD": 1, 38 | "nA": 2, 39 | "nB": -1, 40 | "width": 1e-4, 41 | "height": 1e-4 42 | } 43 | ], 44 | "Modules": 45 | [ 46 | { 47 | "iD": 0, 48 | "Type":"LBM", 49 | "name": "Paper4a-CFD-20", 50 | "stlFile": "../examples/STL/Network4a.stl", 51 | "charPhysLength": 1e-4, 52 | "charPhysVelocity": 1e-1, 53 | "alpha": 0.0, 54 | "resolution": 20, 55 | "epsilon": 1e-9, 56 | "tau": 0.55, 57 | "posX": 1.0e-3, 58 | "posY": 0.0e-3, 59 | "sizeX": 4e-3, 60 | "sizeY": 1.1e-3, 61 | "Openings": 62 | [ 63 | { 64 | "nodeId": 1, 65 | "normalX": 1.0, 66 | "normalY": 0.0, 67 | "width": 1e-4 68 | }, 69 | { 70 | "nodeId": 2, 71 | "normalX": -1.0, 72 | "normalY": 0.0, 73 | "width": 1e-4 74 | } 75 | ] 76 | } 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/CFD/Network4b.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 1.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 2.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 9.0e-3, 19 | "y": 0.05e-3 20 | }, 21 | { 22 | "iD": -1, 23 | "x": 9.00000001e-3, 24 | "y": 0.05e-3 25 | } 26 | ], 27 | "Channels": 28 | [ 29 | { 30 | "iD": 0, 31 | "nA": 0, 32 | "nB": 1, 33 | "width": 1e-4, 34 | "height": 1e-4 35 | }, 36 | { 37 | "iD": 1, 38 | "nA": 2, 39 | "nB": -1, 40 | "width": 1e-4, 41 | "height": 1e-4 42 | } 43 | ], 44 | "Modules": 45 | [ 46 | { 47 | "iD": 0, 48 | "Type":"LBM", 49 | "name": "Paper4b-CFD-20", 50 | "stlFile": "../examples/STL/Network4b.stl", 51 | "charPhysLength": 1e-4, 52 | "charPhysVelocity": 1e-1, 53 | "alpha": 0.0, 54 | "resolution": 20, 55 | "epsilon": 1e-9, 56 | "tau": 0.55, 57 | "posX": 1.0e-3, 58 | "posY": 0.0e-3, 59 | "sizeX": 8e-3, 60 | "sizeY": 2.1e-3, 61 | "Openings": 62 | [ 63 | { 64 | "nodeId": 1, 65 | "normalX": 1.0, 66 | "normalY": 0.0, 67 | "width": 1e-4 68 | }, 69 | { 70 | "nodeId": 2, 71 | "normalX": -1.0, 72 | "normalY": 0.0, 73 | "width": 1e-4 74 | } 75 | ] 76 | } 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/CFD/Network4c.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 1.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 3.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 13.0e-3, 19 | "y": 0.05e-3 20 | }, 21 | { 22 | "iD": -1, 23 | "x": 13.00000001e-3, 24 | "y": 0.05e-3 25 | } 26 | ], 27 | "Channels": 28 | [ 29 | { 30 | "iD": 0, 31 | "nA": 0, 32 | "nB": 1, 33 | "width": 1e-4, 34 | "height": 1e-4 35 | }, 36 | { 37 | "iD": 1, 38 | "nA": 2, 39 | "nB": -1, 40 | "width": 1e-4, 41 | "height": 1e-4 42 | } 43 | ], 44 | "Modules": 45 | [ 46 | { 47 | "iD": 0, 48 | "Type":"LBM", 49 | "name": "Paper4c-CFD-20", 50 | "stlFile": "../examples/STL/Network4c.stl", 51 | "charPhysLength": 1e-4, 52 | "charPhysVelocity": 1e-1, 53 | "alpha": 0.0, 54 | "resolution": 20, 55 | "epsilon": 1e-9, 56 | "tau": 0.55, 57 | "posX": 1.0e-3, 58 | "posY": 0.0e-3, 59 | "sizeX": 12e-3, 60 | "sizeY": 3.1e-3, 61 | "Openings": 62 | [ 63 | { 64 | "nodeId": 1, 65 | "normalX": 1.0, 66 | "normalY": 0.0, 67 | "width": 1e-4 68 | }, 69 | { 70 | "nodeId": 2, 71 | "normalX": -1.0, 72 | "normalY": 0.0, 73 | "width": 1e-4 74 | } 75 | ] 76 | } 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/CFD/Network4d.JSON: -------------------------------------------------------------------------------- 1 | { 2 | "Network": 3 | { 4 | "Nodes": 5 | [ 6 | { 7 | "iD": 0, 8 | "x": 0.0e-3, 9 | "y": 1.05e-3 10 | }, 11 | { 12 | "iD": 1, 13 | "x": 1.0e-3, 14 | "y": 4.05e-3 15 | }, 16 | { 17 | "iD": 2, 18 | "x": 17.0e-3, 19 | "y": 0.05e-3 20 | }, 21 | { 22 | "iD": -1, 23 | "x": 17.00000001e-3, 24 | "y": 0.05e-3 25 | } 26 | ], 27 | "Channels": 28 | [ 29 | { 30 | "iD": 0, 31 | "nA": 0, 32 | "nB": 1, 33 | "width": 1e-4, 34 | "height": 1e-4 35 | }, 36 | { 37 | "iD": 1, 38 | "nA": 2, 39 | "nB": -1, 40 | "width": 1e-4, 41 | "height": 1e-4 42 | } 43 | ], 44 | "Modules": 45 | [ 46 | { 47 | "iD": 0, 48 | "Type":"LBM", 49 | "name": "Paper4d-CFD-20", 50 | "stlFile": "../examples/STL/Network4d.stl", 51 | "charPhysLength": 1e-4, 52 | "charPhysVelocity": 1e-1, 53 | "alpha": 0.0, 54 | "resolution": 20, 55 | "epsilon": 1e-9, 56 | "tau": 0.55, 57 | "posX": 1.0e-3, 58 | "posY": 0.0e-3, 59 | "sizeX": 16e-3, 60 | "sizeY": 4.1e-3, 61 | "Openings": 62 | [ 63 | { 64 | "nodeId": 1, 65 | "normalX": 1.0, 66 | "normalY": 0.0, 67 | "width": 1e-4 68 | }, 69 | { 70 | "nodeId": 2, 71 | "normalX": -1.0, 72 | "normalY": 0.0, 73 | "width": 1e-4 74 | } 75 | ] 76 | } 77 | ] 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/Hybrid/Network1a.py: -------------------------------------------------------------------------------- 1 | from mmft.simulator import * 2 | 3 | # Continuous Hybrid 4 | def hybridContinuous(): 5 | 6 | network = Network() 7 | 8 | # Nodes 9 | n0 = network.addNode(0.0, 0.0, True) 10 | n1 = network.addNode(1e-3, 2e-3, False) 11 | n2 = network.addNode(1e-3, 1e-3, False) 12 | n3 = network.addNode(1e-3, 0.0, False) 13 | n4 = network.addNode(2e-3, 2e-3, False) 14 | n5 = network.addNode(1.75e-3, 1e-3, False) 15 | n6 = network.addNode(2e-3, 0.0, False) 16 | n7 = network.addNode(2e-3, 1.25e-3, False) 17 | n8 = network.addNode(2e-3, 0.75e-3, False) 18 | n9 = network.addNode(2.25e-3, 1e-3, False) 19 | n10 = network.addNode(3e-3, 1e-3, True) 20 | 21 | # Channels 22 | network.addChannel(n0, n1, 1e-4, 1e-4, ChannelType.normal) 23 | network.addChannel(n0, n2, 1e-4, 1e-4, ChannelType.normal) 24 | network.addChannel(n0, n3, 1e-4, 1e-4, ChannelType.normal) 25 | network.addChannel(n1, n4, 1e-4, 1e-4, ChannelType.normal) 26 | network.addChannel(n2, n5, 1e-4, 1e-4, ChannelType.normal) 27 | network.addChannel(n3, n6, 1e-4, 1e-4, ChannelType.normal) 28 | network.addChannel(n4, n7, 1e-4, 1e-4, ChannelType.normal) 29 | network.addChannel(n6, n8, 1e-4, 1e-4, ChannelType.normal) 30 | network.addChannel(n9, n10, 1e-4, 1e-4, ChannelType.normal) 31 | 32 | # Module 33 | m0 = network.addModule( [1.75e-3, 0.75e-3], [5e-4, 5e-4], [n5, n7, n8, n9]) 34 | 35 | # Pressure Pumps 36 | network.addPressurePump(n0, n1, 1e3) 37 | network.addPressurePump(n0, n2, 1e3) 38 | network.addPressurePump(n0, n3, 1e3) 39 | 40 | network.valid() 41 | 42 | simulation = Simulation() 43 | 44 | # Simulation meta-data 45 | simulation.setType(Type.hybrid) 46 | simulation.setPlatform(Platform.continuous) 47 | simulation.setNetwork(network) 48 | 49 | # Fluid & Resistance Model 50 | f0 = simulation.addFluid(1e3, 1e-3, 1.0) 51 | simulation.setContinuousPhase(f0) 52 | simulation.setPoiseuilleResistanceModel() 53 | 54 | s1 = simulation.addLbmSimulator("1a", "../STL/cross.stl", m0, [n5, n7, n8, n9], \ 55 | [[1.0, 0.0], [0.0, -1.0], [0.0, 1.0], [-1.0, 0.0]], [1e-4, 1e-4, 1e-4, 1e-4], \ 56 | 1e-4, 1e-1, 20, 1e-1, 0.55) 57 | 58 | s1.setNaiveScheme(0.1, 0.5, 10) 59 | 60 | network.sort() 61 | 62 | simulation.simulate() 63 | 64 | simulation.saveResult("continuousHybrid.JSON") 65 | 66 | def main(): 67 | hybridContinuous() 68 | 69 | if __name__ == "__main__": 70 | main() -------------------------------------------------------------------------------- /images/mmft_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cda-tum/mmft-simulator/7e917548421da626634f1d0321bde723bca51eab/images/mmft_dark.png -------------------------------------------------------------------------------- /images/mmft_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cda-tum/mmft-simulator/7e917548421da626634f1d0321bde723bca51eab/images/mmft_light.png -------------------------------------------------------------------------------- /incl/windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(HEADER_LIST 2 | unistd.h 3 | ) 4 | 5 | target_sources(${TARGET_NAME} PUBLIC ${HEADER_LIST}) 6 | target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) -------------------------------------------------------------------------------- /incl/windows/unistd.h: -------------------------------------------------------------------------------- 1 | #ifndef _UNISTD_H 2 | #define _UNISTD_H 1 3 | 4 | /* This is intended as a drop-in replacement for unistd.h on Windows. 5 | * Please add functionality as needed. 6 | * https://stackoverflow.com/a/826027/1202830 7 | */ 8 | 9 | #include 10 | #include 11 | #include /* for getpid() and the exec..() family */ 12 | #include /* for _getcwd() and _chdir() */ 13 | 14 | #define srandom srand 15 | #define random rand 16 | 17 | /* Values for the second argument to access. 18 | These may be OR'd together. */ 19 | #define R_OK 4 /* Test for read permission. */ 20 | #define W_OK 2 /* Test for write permission. */ 21 | //#define X_OK 1 /* execute permission - unsupported in windows*/ 22 | #define F_OK 0 /* Test for existence. */ 23 | 24 | #define access _access 25 | #define dup2 _dup2 26 | #define execve _execve 27 | #define ftruncate _chsize 28 | #define unlink _unlink 29 | #define fileno _fileno 30 | #define getcwd _getcwd 31 | #define chdir _chdir 32 | #define isatty _isatty 33 | #define lseek _lseek 34 | /* read, write, and close are NOT being #defined here, because while there are file handle specific versions for Windows, they probably don't work for sockets. You need to look at your app and consider whether to call e.g. closesocket(). */ 35 | 36 | #ifdef _WIN64 37 | #define ssize_t __int64 38 | #else 39 | #define ssize_t long 40 | #endif 41 | 42 | #define STDIN_FILENO 0 43 | #define STDOUT_FILENO 1 44 | #define STDERR_FILENO 2 45 | 46 | #endif /* unistd.h */ 47 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools>=61", 4 | "setuptools_scm[toml]>=7", 5 | "ninja>=1.10; sys_platform != 'win32'", 6 | "cmake>=3.21" 7 | ] 8 | build-backend = "setuptools.build_meta" 9 | 10 | [project] 11 | name = "mmft.simulator" 12 | description = "A simulator for closed channel-based microfluidic devices" 13 | readme = "README.md" 14 | authors = [ 15 | { name = "Michel Takken", email = "michel.takken@tum.de"} 16 | ] 17 | keywords = ["MMFT", "microfluidics", "simulation", "design automation"] 18 | license = { file = "LICENSE" } 19 | 20 | classifiers=[ 21 | "Development Status :: 3 - Alpha", 22 | "Programming Language :: Python :: 3", 23 | "Programming Language :: Python :: 3.8", 24 | "Programming Language :: Python :: 3.9", 25 | "Programming Language :: Python :: 3.10", 26 | "Programming Language :: Python :: 3.11", 27 | "Programming Language :: C++", 28 | "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", 29 | "Operating System :: MacOS", 30 | "Operating System :: POSIX :: Linux", 31 | "Intended Audience :: Science/Research", 32 | "Natural Language :: English", 33 | "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", 34 | ] 35 | requires-python = ">=3.8" 36 | dynamic = ["version"] 37 | 38 | [tool.setuptools.packages.find] 39 | where = ["python"] 40 | exclude = ["src*"] 41 | 42 | [tool.setuptools_scm] 43 | 44 | [tool.cibuildwheel] 45 | build = "cp3*" 46 | skip = "*-musllinux_*" 47 | archs = "auto64" 48 | test-command = "python -c \"from mmft import simulator\"" 49 | build-frontend = "build" 50 | 51 | [tool.cibuildwheel.macos] 52 | environment = { MACOSX_DEPLOYMENT_TARGET = "10.15" } 53 | -------------------------------------------------------------------------------- /python/mmft/simulator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # add pybind11 library 2 | add_subdirectory("${PROJECT_SOURCE_DIR}/external/pybind11" "external/pybind11" EXCLUDE_FROM_ALL) 3 | 4 | set(PYTHON_MODULE_NAME "pysimulator") 5 | if(NOT TARGET ${PYTHON_MODULE_NAME}) 6 | pybind11_add_module(${PYTHON_MODULE_NAME} bindings.cpp) 7 | target_link_libraries(${PYTHON_MODULE_NAME} PRIVATE simLib) 8 | target_compile_definitions(${PYTHON_MODULE_NAME} PRIVATE VERSION_INFO=${SIMULATOR_VERSION_INFO}) 9 | endif() 10 | -------------------------------------------------------------------------------- /python/mmft/simulator/__init__.py: -------------------------------------------------------------------------------- 1 | """MMFT Simulation Package""" 2 | 3 | from mmft.simulator.pysimulator import ( 4 | ChannelType, 5 | Network, 6 | Platform, 7 | Simulation, 8 | Type 9 | ) 10 | 11 | __all__ = [ 12 | 'ChannelType', 13 | 'Network', 14 | 'Platform', 15 | 'Simulation', 16 | 'Type' 17 | ] 18 | -------------------------------------------------------------------------------- /script.sed: -------------------------------------------------------------------------------- 1 | :a;$!{N;ba}; s/#ifdef _WIN32/#ifdef _WIN321/; -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_LIST 2 | baseSimulator.hh 3 | ) 4 | 5 | set(HEADER_LIST 6 | baseSimulator.h 7 | ) 8 | 9 | # add subdirectories 10 | add_subdirectory(nodalAnalysis) 11 | add_subdirectory(architecture) 12 | add_subdirectory(hybridDynamics) 13 | add_subdirectory(simulation) 14 | add_subdirectory(olbProcessors) 15 | add_subdirectory(porting) 16 | add_subdirectory(result) 17 | 18 | target_sources(${TARGET_NAME} PUBLIC ${SOURCE_LIST} ${HEADER_LIST}) 19 | target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) -------------------------------------------------------------------------------- /src/architecture/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_LIST 2 | Channel.hh 3 | ChannelPosition.hh 4 | Membrane.hh 5 | Module.hh 6 | Network.hh 7 | Tank.hh 8 | Edge.hh 9 | FlowRatePump.hh 10 | Node.hh 11 | PressurePump.hh 12 | ) 13 | 14 | set(HEADER_LIST 15 | Channel.h 16 | ChannelPosition.h 17 | Membrane.h 18 | Module.h 19 | ModuleOpening.h 20 | Network.h 21 | Tank.h 22 | Edge.h 23 | FlowRatePump.h 24 | Node.h 25 | PressurePump.h 26 | ) 27 | 28 | target_sources(${TARGET_NAME} PUBLIC ${SOURCE_LIST} ${HEADER_LIST}) 29 | target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) 30 | target_link_libraries(${TARGET_NAME} PUBLIC nlohmann_json::nlohmann_json) 31 | -------------------------------------------------------------------------------- /src/architecture/ChannelPosition.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ChannelPosition.h 3 | */ 4 | 5 | #pragma once 6 | 7 | namespace arch { 8 | 9 | // Forward declared dependencies 10 | template 11 | class RectangularChannel; 12 | 13 | /** 14 | * @brief Class to specify the boundary position of one end of a droplet. 15 | */ 16 | template 17 | class ChannelPosition { 18 | private: 19 | RectangularChannel* channel = nullptr; ///< Channel in which one end of droplet currently is. 20 | T position; ///< Exact relative position (between 0.0 and 1.0) within the channel. 21 | 22 | public: 23 | /** 24 | * @brief Constructor to create the position of one end of a droplet. 25 | * @param[in] channel Channel in which this end of the droplet currently is. 26 | * @param[in] position Relative position (between 0.0 and 1.0) of the droplet end in this channel. 27 | */ 28 | ChannelPosition(RectangularChannel* channel, T position); 29 | 30 | /** 31 | * @brief Change the channel of the channel position (at which one end of the droplet currently is). 32 | * @param[in] channel New channel to which the position should be set. 33 | */ 34 | void setChannel(RectangularChannel* const channel); 35 | 36 | /** 37 | * @brief Reset relative position. 38 | * @param[in] position Relative position (between 0.0 and 1.0) within a channel. 39 | */ 40 | void setPosition(T position); 41 | 42 | /** 43 | * @brief Add the volume shift to the current position. 44 | * @param[in] volumeShift Shift of the volume in flow direction in L. 45 | */ 46 | void addToPosition(T volumeShift); 47 | 48 | /** 49 | * @brief Returns pointer to channel in which this end of the droplet currently is. 50 | * @return Pointer to channel at which this end of the droplet currently is. 51 | */ 52 | RectangularChannel* getChannel() const; 53 | 54 | /** 55 | * @brief Returns relative position within the channel. 56 | * @return Relative position (between 0.0 and 1.0) at which this end of the droplet currently is. 57 | */ 58 | T getPosition() const; 59 | 60 | /** 61 | * @brief Returns absolute position within channel in m. 62 | * @return Absolute position in m. 63 | */ 64 | T getAbsolutePosition() const; 65 | 66 | /** 67 | * @brief Calculates and returns volume towards node A. 68 | * @return Volume towards node A in L. 69 | */ 70 | T getVolumeA() const; 71 | 72 | /** 73 | * @brief Calculates and returns volume towards node B. 74 | * @return Volume towards node B in L. 75 | */ 76 | T getVolumeB() const; 77 | }; 78 | 79 | } // namespace arch -------------------------------------------------------------------------------- /src/architecture/ChannelPosition.hh: -------------------------------------------------------------------------------- 1 | #include "ChannelPosition.h" 2 | 3 | namespace arch { 4 | 5 | template 6 | ChannelPosition::ChannelPosition(RectangularChannel* channel, T position) : channel(channel), position(position) {} 7 | 8 | template 9 | void ChannelPosition::setChannel(RectangularChannel* const channel) { 10 | this->channel = channel; 11 | } 12 | 13 | template 14 | void ChannelPosition::setPosition(T position) { 15 | // ensure that position stays in range (e.g., due to rounding errors) 16 | if (position < 0.0) { 17 | this->position = 0.0; 18 | } else if (position > 1.0) { 19 | this->position = 1.0; 20 | } else { 21 | this->position = position; 22 | } 23 | } 24 | 25 | template 26 | void ChannelPosition::addToPosition(T volumeShift) { 27 | T newPosition = position + volumeShift / channel->getVolume(); 28 | setPosition(newPosition); 29 | } 30 | 31 | template 32 | RectangularChannel* ChannelPosition::getChannel() const { 33 | return channel; 34 | } 35 | 36 | template 37 | T ChannelPosition::getPosition() const { 38 | return position; 39 | } 40 | 41 | template 42 | T ChannelPosition::getAbsolutePosition() const { 43 | return position * channel->getLength(); 44 | } 45 | 46 | template 47 | T ChannelPosition::getVolumeA() const { 48 | return position * channel->getVolume(); 49 | } 50 | 51 | template 52 | T ChannelPosition::getVolumeB() const { 53 | return (1.0 - position) * channel->getVolume(); 54 | } 55 | 56 | } // namespace arch -------------------------------------------------------------------------------- /src/architecture/Edge.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Edge.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | namespace arch { 10 | 11 | // Forward declared dependencies 12 | template 13 | class Node; 14 | 15 | /** 16 | * @brief Abstract class to specify an edge, which is a connection between two nodes. Multiple components of a chip are an edge. 17 | */ 18 | template 19 | class Edge { 20 | protected: 21 | int const id; ///< Id of the edge. 22 | int nodeA; ///< Node at one end of the edge. 23 | int nodeB; ///< Node at other end of the edge. 24 | 25 | public: 26 | /** 27 | * @brief Constructor of the edge. 28 | * @param[in] id Id of the edge. 29 | * @param[in] nodeA Node at one end of the edge. 30 | * @param[in] nodeB Node at other end of the edge. 31 | */ 32 | Edge(int id, int nodeA, int nodeB); 33 | 34 | virtual ~Edge() = default; 35 | 36 | /** 37 | * @brief Get id of the edge. 38 | * @return Id of the edge. 39 | */ 40 | int getId() const; 41 | 42 | /** 43 | * @brief Get pressure over the edge. 44 | * @return Pressure over the edge in Pa. 45 | */ 46 | virtual T getPressure() const = 0; 47 | 48 | /** 49 | * @brief Get flow rate in the edge. 50 | * @return Flow rate of the edge in m^3/s. 51 | */ 52 | virtual T getFlowRate() const = 0; 53 | 54 | /** 55 | * @brief Get overall resistance over an edge. 56 | * @return Resistance over an edge in Pas/m^3. 57 | */ 58 | virtual T getResistance() const = 0; 59 | 60 | /** 61 | * @brief Get pointer to node 0 (node at one end of the edge). 62 | * @return Pointer to node 0 (node at one end of the edge). 63 | */ 64 | int getNodeA() const; 65 | 66 | /** 67 | * @brief Get pointer to node 1 (node at other end of the edge). 68 | * @return Pointer to node 1 (node at other end of the edge). 69 | */ 70 | int getNodeB() const; 71 | 72 | /** 73 | * @brief Get the nodes at the ends of the channel. 74 | * @returns Nodes at the ends of the channel. 75 | */ 76 | std::vector getNodes() const; 77 | }; 78 | 79 | } // namespace arch -------------------------------------------------------------------------------- /src/architecture/Edge.hh: -------------------------------------------------------------------------------- 1 | #include "Edge.h" 2 | 3 | namespace arch { 4 | 5 | template 6 | Edge::Edge(int id_, int nodeA_, int nodeB_) : id(id_), nodeA(nodeA_), nodeB(nodeB_){}; 7 | 8 | template 9 | int Edge::getId() const { 10 | return id; 11 | } 12 | 13 | template 14 | int Edge::getNodeA() const { 15 | return nodeA; 16 | } 17 | 18 | template 19 | int Edge::getNodeB() const { 20 | return nodeB; 21 | } 22 | 23 | template 24 | std::vector Edge::getNodes() const { 25 | return std::vector (nodeA, nodeB); 26 | } 27 | 28 | } // namespace arch -------------------------------------------------------------------------------- /src/architecture/FlowRatePump.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file FlowRatePump.h 3 | */ 4 | 5 | #pragma once 6 | 7 | namespace arch { 8 | 9 | // Forward declared dependencies 10 | template 11 | class Edge; 12 | 13 | template 14 | class Node; 15 | 16 | /** 17 | * @brief Class to specify a flow rate pump, which is a component of a chip. 18 | */ 19 | template 20 | class FlowRatePump : public virtual Edge { 21 | private: 22 | T flowRate; ///< Volumetric flow rate of the pump in m^3/s. 23 | T pressure; ///< Pressure of a channel in Pa. 24 | 25 | public: 26 | /** 27 | * @brief Constructor to create a flow rate pump. 28 | * @param[in] id Id of the flow rate pump. 29 | * @param[in] nodeA Pointer to node at one end of the flow rate pump. 30 | * @param[in] nodeB Pointer to node at other end of the flow rate pump. 31 | * @param[in] flowRate Volumetric flow rate of the pump in m^3/s. 32 | */ 33 | FlowRatePump(int id, int nodeA, int nodeB, T flowRate); 34 | 35 | /** 36 | * @brief Set pressure of the pump. 37 | * @param[in] pressure Pressure of the pump in Pa. 38 | */ 39 | void setPressure(T pressure); 40 | 41 | /** 42 | * @brief Set volumetric flow rate of the pump. 43 | * @param[in] flowRate New volumetric flow rate to set in m^3/s. 44 | */ 45 | void setFlowRate(T flowRate); 46 | 47 | /** 48 | * @brief Get pressure of the pump. 49 | * @return Pressure of flow rate pump in Pa. 50 | */ 51 | T getPressure() const override; 52 | 53 | /** 54 | * @brief Get volumetric flow rate of pump. 55 | * @return Volumetric flow rate of pump in m^3/s. 56 | */ 57 | T getFlowRate() const override; 58 | 59 | /** 60 | * @brief Get resistance over flow rate pump. 61 | * @return Resistance over flow rate pump in Pas/L. 62 | */ 63 | T getResistance() const override; 64 | }; 65 | 66 | } // namespace arch -------------------------------------------------------------------------------- /src/architecture/FlowRatePump.hh: -------------------------------------------------------------------------------- 1 | #include "FlowRatePump.h" 2 | 3 | namespace arch { 4 | 5 | template 6 | FlowRatePump::FlowRatePump(int id, int nodeA_, int nodeB_, T flowRate_) : 7 | Edge(id, nodeA_, nodeB_), flowRate(flowRate_) { } 8 | 9 | template 10 | void FlowRatePump::setPressure(T pressure_) { 11 | this->pressure = pressure_; 12 | } 13 | 14 | template 15 | void FlowRatePump::setFlowRate(T flowRate_) { 16 | this->flowRate = flowRate_; 17 | } 18 | 19 | template 20 | T FlowRatePump::getPressure() const { 21 | return pressure; 22 | } 23 | 24 | template 25 | T FlowRatePump::getFlowRate() const { 26 | return flowRate; 27 | } 28 | 29 | template 30 | T FlowRatePump::getResistance() const { 31 | return getPressure() / getFlowRate(); 32 | } 33 | 34 | } // namespace arch 35 | -------------------------------------------------------------------------------- /src/architecture/MixturePump.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file MixturePump.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include "Edge.h" 8 | #include "Fluid.h" 9 | 10 | namespace arch { 11 | 12 | /** 13 | * @brief Abstract class to specify a pump, which is a component of a chip. 14 | * 15 | */ 16 | template 17 | class MixturePump : public virtual Edge { 18 | private: 19 | int mixtureId; // Id of the mixture that is pumped through the chip by the pump. 20 | 21 | public: 22 | /** 23 | * @brief Construct a new Pump object 24 | */ 25 | MixturePump(); 26 | 27 | /** 28 | * @brief Set the mixture that should be pumped through the chip by this pump 29 | * 30 | * @param mixtureId Id of the mixture. 31 | */ 32 | void setMixture(int mixtureId); 33 | 34 | /** 35 | * @brief Get the mixture that is pumped through the chip by this pump 36 | * 37 | * @return Id of the mixture. 38 | */ 39 | int getMixtureId(); 40 | }; 41 | 42 | } // namespace arch -------------------------------------------------------------------------------- /src/architecture/MixturePump.hh: -------------------------------------------------------------------------------- 1 | #include "MixturePump.h" 2 | 3 | namespace arch { 4 | 5 | template 6 | MixturePump::MixturePump() { } 7 | 8 | template 9 | void MixturePump::setMixture(int mixtureId) { 10 | this->mixtureId = mixtureId; 11 | } 12 | 13 | template 14 | int MixturePump::getMixtureId() { 15 | return mixtureId; 16 | } 17 | 18 | } // namespace arch -------------------------------------------------------------------------------- /src/architecture/Module.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Module.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace arch { 12 | 13 | // Forward declared dependencies 14 | template 15 | class Node; 16 | 17 | template 18 | struct Opening; 19 | 20 | /** 21 | * @brief An enum to specify the type of module. 22 | */ 23 | enum class ModuleType { 24 | NORMAL, ///< A placeholder module with no special functionality. 25 | MIXER, ///< A mixer module that mixes the incoming fluids to a certain degree. 26 | HEATER, ///< A heater module that heats the passing fluid to a certain degree. 27 | ORGAN, ///< An organ module that models the functionality of an organ in the network. 28 | LBM, ///< A CFD module that maps the LBM simulation result from an OLB solver on the 1D level. 29 | ESS_LBM ///< A CFD module that maps the LBM simulation result from an ESS solver on the 1D level. 30 | 31 | }; 32 | 33 | /** 34 | * @brief Class to specify a module, which is a functional component in a network. 35 | */ 36 | template 37 | class Module { 38 | protected: 39 | int const id; ///< Id of the module. 40 | std::vector pos; ///< Position (x, y) of the lower left corner of the module. 41 | std::vector size; ///< Size (x, y) of the rectangular module. 42 | std::unordered_map>> boundaryNodes; ///< List of nodes that are placed on the boundary of the module. 43 | ModuleType moduleType = ModuleType::NORMAL; ///< Type of module. 44 | 45 | public: 46 | /** 47 | * @brief Constructor of the module. 48 | * @param[in] id Id of the module. 49 | * @param[in] pos Absolute position of the module in _m_, from the bottom left corner of the microfluidic device. 50 | * @param[in] size Size of the module in _m_. 51 | * @param[in] boundaryNodes Map of nodes that are on the boundary of the module. 52 | */ 53 | Module(int id, std::vector pos, std::vector size, std::unordered_map>> boundaryNodes); 54 | 55 | /** 56 | * @brief Get id of the module. 57 | * @returns id. 58 | */ 59 | int getId() const; 60 | 61 | /** 62 | * @brief Get position of the module. 63 | * @returns Absolute position of the left bottom corner of the module, with respect to the left bottom corner of the device. 64 | */ 65 | std::vector getPosition() const; 66 | 67 | /** 68 | * @brief Get size of the module. 69 | * @returns Size of the module in m x m. 70 | */ 71 | std::vector getSize() const; 72 | 73 | /** 74 | * @brief Set the nodes on the boundary of the module. 75 | * @param[in] boundaryNodes 76 | */ 77 | void setNodes(std::unordered_map>> boundaryNodes); 78 | 79 | /** 80 | * @brief Get the nodes on the boundary of the module. 81 | * @returns Nodes on the boundary of the module. 82 | */ 83 | std::unordered_map>> getNodes() const; 84 | 85 | /** 86 | * @brief Returns the type of the module. 87 | * @returns What type the channel has. 88 | */ 89 | void setModuleTypeLbm(); 90 | 91 | /** 92 | * @brief Returns the type of the module. 93 | * @returns What type the channel has. 94 | */ 95 | void setModuleTypeEssLbm(); 96 | 97 | /** 98 | * @brief Returns the type of the module. 99 | * @returns What type the channel has. 100 | */ 101 | ModuleType getModuleType() const; 102 | }; 103 | 104 | } // namespace arch 105 | -------------------------------------------------------------------------------- /src/architecture/Module.hh: -------------------------------------------------------------------------------- 1 | #include "Module.h" 2 | 3 | namespace arch { 4 | 5 | template 6 | Module::Module (int id_, std::vector pos_, std::vector size_, std::unordered_map>> boundaryNodes_) : 7 | id(id_), pos(pos_), size(size_), boundaryNodes(boundaryNodes_) { } 8 | 9 | template 10 | int Module::getId() const { 11 | return id; 12 | } 13 | 14 | template 15 | std::vector Module::getPosition() const { 16 | return pos; 17 | } 18 | 19 | template 20 | std::vector Module::getSize() const { 21 | return size; 22 | } 23 | 24 | template 25 | void Module::setNodes(std::unordered_map>> boundaryNodes_) { 26 | this->boundaryNodes = boundaryNodes_; 27 | } 28 | 29 | template 30 | std::unordered_map>> Module::getNodes() const { 31 | return boundaryNodes; 32 | } 33 | 34 | template 35 | void Module::setModuleTypeLbm() { 36 | moduleType = ModuleType::LBM; 37 | } 38 | 39 | template 40 | void Module::setModuleTypeEssLbm() { 41 | moduleType = ModuleType::ESS_LBM; 42 | } 43 | 44 | template 45 | ModuleType Module::getModuleType() const { 46 | return moduleType; 47 | } 48 | 49 | } // namespace arch -------------------------------------------------------------------------------- /src/architecture/ModuleOpening.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ModuleOpening.h 3 | */ 4 | 5 | #pragma once 6 | 7 | namespace arch { 8 | 9 | /** 10 | * @brief Struct that defines an opening, which is an in-/outlet of the CFD domain. 11 | */ 12 | template 13 | struct Opening { 14 | std::shared_ptr> node; 15 | std::vector normal; 16 | std::vector tangent; 17 | T width; 18 | T height; 19 | T radial; 20 | 21 | /** 22 | * @brief Constructor of an opening. 23 | * @param[in] node The module node in the network that corresponds to this opening. 24 | * @param[in] normal The normal direction of the opening, pointing into the CFD domain. 25 | * @param[in] width The width of the opening. 26 | * @param[in] height The height of the opening. 27 | */ 28 | Opening(std::shared_ptr> node_, std::vector normal_, T width_, T height_=1e-4) : 29 | node(node_), normal(normal_), width(width_), height(height_) { 30 | 31 | // Rotate the normal vector 90 degrees counterclockwise to get the tangent 32 | T theta = 0.5*M_PI; 33 | tangent = { cos(theta)*normal_[0] - sin(theta)*normal_[1], 34 | sin(theta)*normal_[0] + cos(theta)*normal_[1]}; 35 | radial = (-1) * atan2(normal_[1], normal_[0]); 36 | } 37 | }; 38 | 39 | } // namespace arch 40 | -------------------------------------------------------------------------------- /src/architecture/Node.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Node.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | namespace arch { 10 | 11 | /** 12 | * @brief Class to specify a node, which defines connections between components of a Network. 13 | */ 14 | template 15 | class Node { 16 | private: 17 | int const id; 18 | std::vector pos; 19 | T pressure = 0; 20 | bool ground = false; 21 | bool sink = false; 22 | 23 | public: 24 | /** 25 | * @brief Constructor of the node. 26 | * @param[in] id Id of the node. 27 | * @param[in] x Absolute x position of the node. 28 | * @param[in] y Absolute y position of the node. 29 | */ 30 | Node(int id, T x, T y, bool ground=false); 31 | 32 | /** 33 | * @brief Get position of the node. 34 | * @param[in] pos Vector of the absolute position of the node. 35 | */ 36 | void setPosition(std::vector pos); 37 | 38 | /** 39 | * @brief Set pressure level at the node. 40 | * @param[in] pressure Pressure level at the node in Pa. 41 | */ 42 | void setPressure(T pressure); 43 | 44 | /** 45 | * @brief Set the sink role to the node. 46 | * @param[in] sink Boolean value for sink role. 47 | */ 48 | void setSink(bool sink); 49 | 50 | /** 51 | * @brief Set the ground node role to the node. 52 | * @param[in] ground Boolean value for ground node role. 53 | */ 54 | void setGround(bool ground); 55 | 56 | /** 57 | * @brief Get the sink node role of the node. 58 | * @returns Boolean value for sink role. 59 | */ 60 | bool getSink(); 61 | 62 | /** 63 | * @brief Get the ground node role of the node. 64 | * @returns Boolean value for ground node role. 65 | */ 66 | bool getGround(); 67 | 68 | /** 69 | * @brief Get id of the node. 70 | * @returns id. 71 | */ 72 | int getId() const; 73 | 74 | /** 75 | * @brief Get position of the node. 76 | * @returns Absolute position of the node 77 | */ 78 | std::vector getPosition() const; 79 | 80 | /** 81 | * @brief Get pressure level at node. 82 | * @return Pressure level at node. 83 | */ 84 | T getPressure() const; 85 | }; 86 | 87 | } // namespace arch -------------------------------------------------------------------------------- /src/architecture/Node.hh: -------------------------------------------------------------------------------- 1 | #include "Node.h" 2 | 3 | namespace arch { 4 | 5 | template 6 | Node::Node(int id_, T x_, T y_, bool ground_) : 7 | id(id_), ground(ground_) { 8 | pos.push_back(x_); 9 | pos.push_back(y_); 10 | } 11 | 12 | template 13 | void Node::setPosition(std::vector pos_) { 14 | this->pos = pos_; 15 | } 16 | 17 | template 18 | void Node::setPressure(T pressure_) { 19 | this->pressure = pressure_; 20 | } 21 | 22 | template 23 | int Node::getId() const { 24 | return id; 25 | } 26 | 27 | template 28 | std::vector Node::getPosition() const { 29 | return pos; 30 | } 31 | 32 | template 33 | T Node::getPressure() const { 34 | return pressure; 35 | } 36 | 37 | template 38 | void Node::setSink(bool sink_) { 39 | sink = sink_; 40 | } 41 | 42 | template 43 | void Node::setGround(bool ground_) { 44 | ground = ground_; 45 | } 46 | 47 | template 48 | bool Node::getGround() { 49 | return ground; 50 | } 51 | 52 | template 53 | bool Node::getSink() { 54 | return sink; 55 | } 56 | 57 | } // namespace arch -------------------------------------------------------------------------------- /src/architecture/PressurePump.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file PressurePump.h 3 | */ 4 | 5 | #pragma once 6 | 7 | namespace arch { 8 | 9 | // Forward declared dependencies 10 | template 11 | class Edge; 12 | 13 | template 14 | class Node; 15 | 16 | /** 17 | * @brief Class to specify a pressure pump, which is a component of a chip. 18 | */ 19 | template 20 | class PressurePump : public virtual Edge { 21 | private: 22 | T pressure; ///< Pressure of pump in Pa. 23 | T flowRate = 0; ///< Flow rate of pump in m^3/s. 24 | 25 | public: 26 | /** 27 | * @brief Constructor to create pressure pump. 28 | * @param[in] id Id of the pressure pump. 29 | * @param[in] node0 Pointer to node at one end of the pressure pump. 30 | * @param[in] node1 Pointer to node at other end of the pressure pump. 31 | * @param[in] pressure Pressure of the pump in Pa. 32 | */ 33 | PressurePump(int id, int nodeA, int nodeB, T pressure); 34 | 35 | /** 36 | * @brief Set pressure of the pump. 37 | * @param[in] pressure Pressure of the pump in Pa. 38 | */ 39 | void setPressure(T pressure); 40 | 41 | /** 42 | * @brief Set flow rate of the pump. 43 | * @param[in] flowRate Flow rate of pump in m^3/s. 44 | */ 45 | void setFlowRate(T flowRate); 46 | 47 | /** 48 | * @brief Get pressure of pump. 49 | * @return Pressure of pump in Pa. 50 | */ 51 | T getPressure() const override; 52 | 53 | /** 54 | * @brief Get flow rate of pump. 55 | * @return Flow rate of pump in m^3/s. 56 | */ 57 | T getFlowRate() const override; 58 | 59 | /** 60 | * @brief Get resistance of pump. 61 | * @return Resistance of pump in Pas/L. 62 | */ 63 | T getResistance() const override; 64 | }; 65 | 66 | } // namespace arch 67 | -------------------------------------------------------------------------------- /src/architecture/PressurePump.hh: -------------------------------------------------------------------------------- 1 | #include "PressurePump.h" 2 | 3 | namespace arch { 4 | 5 | template 6 | PressurePump::PressurePump(int id_, int nodeA_, int nodeB_, T pressure_) : 7 | Edge(id_, nodeA_, nodeB_), pressure(pressure_) { } 8 | 9 | template 10 | void PressurePump::setPressure(T pressure_) { 11 | this->pressure = pressure_; 12 | } 13 | 14 | template 15 | void PressurePump::setFlowRate(T flowRate_) { 16 | this->flowRate = flowRate_; 17 | } 18 | 19 | template 20 | T PressurePump::getPressure() const { 21 | return pressure; 22 | } 23 | 24 | template 25 | T PressurePump::getFlowRate() const { 26 | return flowRate; 27 | } 28 | 29 | template 30 | T PressurePump::getResistance() const { 31 | return getPressure() / getFlowRate(); 32 | } 33 | 34 | } // namespace arch 35 | -------------------------------------------------------------------------------- /src/architecture/Tank.hh: -------------------------------------------------------------------------------- 1 | #include "Tank.h" 2 | 3 | namespace arch { 4 | 5 | template 6 | Tank::Tank(int id, std::shared_ptr> nodeA, std::shared_ptr> nodeB, T height, T width, T length) : Edge(id, nodeA->getId(), nodeB->getId()), 7 | height(height), width(width), length(length), pressureDifference(nodeA->getPressure() - nodeB->getPressure()) {} 8 | 9 | template 10 | Tank::Tank(int id, std::shared_ptr> nodeA, std::shared_ptr> nodeB, T resistance) : Edge(id, nodeA->getId(), nodeB->getId()), 11 | tankResistance(resistance), pressureDifference(nodeA->getPressure() - nodeB->getPressure()) {} 12 | 13 | template 14 | void Tank::setDimensions(T width_, T height_, T length_) { 15 | this->height = height_; 16 | this->width = width_; 17 | this->length = length_; 18 | } 19 | 20 | template 21 | void Tank::setHeight(T height_) { 22 | this->height = height_; 23 | } 24 | 25 | template 26 | void Tank::setWidth(T width_) { 27 | this->width = width_; 28 | } 29 | 30 | template 31 | void Tank::setLength(T length_) { 32 | this->length = length_; 33 | } 34 | 35 | template 36 | T Tank::getHeight() const { 37 | return height; 38 | } 39 | 40 | template 41 | T Tank::getWidth() const { 42 | return width; 43 | } 44 | 45 | template 46 | T Tank::getLength() const { 47 | return length; 48 | } 49 | 50 | template 51 | T Tank::getArea() const { 52 | return width * length; 53 | } 54 | 55 | template 56 | T Tank::getVolume() const { 57 | return width * height * length; 58 | } 59 | 60 | template 61 | T Tank::getPressure() const { 62 | return pressureDifference; 63 | } 64 | 65 | template 66 | T Tank::getFlowRate() const { 67 | // there is no flow in a tank, thus the tank does not have a flow-rate 68 | // to ensure time-accurate concentration changes 69 | // mixtures move through the tank based on the flow-rate of the connected channel 70 | throw std::logic_error("Tank has no flow rate!"); 71 | } 72 | 73 | template 74 | T Tank::getResistance() const { 75 | return tankResistance; 76 | } 77 | 78 | } // namespace arch 79 | -------------------------------------------------------------------------------- /src/baseSimulator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file baseSimulator.h 3 | */ 4 | #pragma once 5 | 6 | #include "simulation/CFDSim.h" 7 | #include "simulation/Droplet.h" 8 | #include "simulation/Fluid.h" 9 | #include "simulation/Injection.h" 10 | #include "simulation/MembraneModels.h" 11 | #include "simulation/Mixture.h" 12 | #include "simulation/MixtureInjection.h" 13 | #include "simulation/MixingModels.h" 14 | #include "simulation/ResistanceModels.h" 15 | #include "simulation/Simulation.h" 16 | #include "simulation/simulators/cfdSimulator.h" 17 | #include "simulation/simulators/olbContinuous.h" 18 | #include "simulation/simulators/olbMixing.h" 19 | #include "simulation/simulators/olbOoc.h" 20 | #include "simulation/Specie.h" 21 | #include "simulation/Tissue.h" 22 | #include "simulation/events/BoundaryEvent.h" 23 | #include "simulation/events/Event.h" 24 | #include "simulation/events/InjectionEvent.h" 25 | #include "simulation/events/MergingEvent.h" 26 | 27 | #include "nodalAnalysis/NodalAnalysis.h" 28 | 29 | #include "hybridDynamics/Scheme.h" 30 | #include "hybridDynamics/Naive.h" 31 | 32 | #include "architecture/Channel.h" 33 | #include "architecture/ChannelPosition.h" 34 | #include "architecture/Edge.h" 35 | #include "architecture/FlowRatePump.h" 36 | #include "architecture/Membrane.h" 37 | #include "architecture/Module.h" 38 | #include "architecture/ModuleOpening.h" 39 | #include "architecture/Network.h" 40 | #include "architecture/Node.h" 41 | #include "architecture/PressurePump.h" 42 | #include "architecture/Tank.h" 43 | 44 | #include "olbProcessors/navierStokesAdvectionDiffusionCouplingPostProcessor2D.h" 45 | #include "olbProcessors/saturatedFluxPostProcessor2D.h" 46 | #include "olbProcessors/setFunctionalRegularizedHeatFlux.h" 47 | 48 | #include "porting/jsonPorter.h" 49 | #include "porting/jsonReaders.h" 50 | #include "porting/jsonWriters.h" 51 | 52 | #include "result/Results.h" 53 | 54 | #ifdef USE_ESSLBM 55 | #include "simulation/simulators/essContinuous.h" 56 | #include "simulation/simulators/essMixing.h" 57 | #endif -------------------------------------------------------------------------------- /src/baseSimulator.hh: -------------------------------------------------------------------------------- 1 | #include "simulation/CFDSim.hh" 2 | #include "simulation/Droplet.hh" 3 | #include "simulation/Fluid.hh" 4 | #include "simulation/Injection.hh" 5 | #include "simulation/MembraneModels.hh" 6 | #include "simulation/Mixture.hh" 7 | #include "simulation/MixtureInjection.hh" 8 | #include "simulation/MixingModels.hh" 9 | #include "simulation/ResistanceModels.hh" 10 | #include "simulation/Simulation.hh" 11 | #include "simulation/simulators/cfdSimulator.hh" 12 | #include "simulation/simulators/olbContinuous.hh" 13 | #include "simulation/simulators/olbMixing.hh" 14 | #include "simulation/simulators/olbOoc.hh" 15 | #include "simulation/Specie.hh" 16 | #include "simulation/Tissue.hh" 17 | #include "simulation/events/BoundaryEvent.hh" 18 | #include "simulation/events/InjectionEvent.hh" 19 | #include "simulation/events/MergingEvent.hh" 20 | 21 | #include "nodalAnalysis/NodalAnalysis.hh" 22 | 23 | #include "hybridDynamics/Scheme.hh" 24 | #include "hybridDynamics/Naive.hh" 25 | 26 | #include "architecture/Channel.hh" 27 | #include "architecture/ChannelPosition.hh" 28 | #include "architecture/Edge.hh" 29 | #include "architecture/FlowRatePump.hh" 30 | #include "architecture/Membrane.hh" 31 | #include "architecture/Module.hh" 32 | #include "architecture/Network.hh" 33 | #include "architecture/Node.hh" 34 | #include "architecture/PressurePump.hh" 35 | #include "architecture/Tank.hh" 36 | 37 | #include "olbProcessors/navierStokesAdvectionDiffusionCouplingPostProcessor2D.hh" 38 | #include "olbProcessors/saturatedFluxPostProcessor2D.hh" 39 | #include "olbProcessors/setFunctionalRegularizedHeatFlux.hh" 40 | 41 | #include "porting/jsonPorter.hh" 42 | #include "porting/jsonReaders.hh" 43 | #include "porting/jsonWriters.hh" 44 | 45 | #include "result/Results.hh" 46 | 47 | #ifdef USE_ESSLBM 48 | #include "simulation/simulators/essContinuous.hh" 49 | #include "simulation/simulators/essMixing.hh" 50 | #endif -------------------------------------------------------------------------------- /src/hybridDynamics/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_LIST 2 | Scheme.hh 3 | Naive.hh 4 | ) 5 | 6 | set(HEADER_LIST 7 | Scheme.h 8 | Naive.h 9 | ) 10 | 11 | target_sources(${TARGET_NAME} PUBLIC ${SOURCE_LIST} ${HEADER_LIST}) 12 | target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) 13 | target_link_libraries(${TARGET_NAME} PUBLIC eigen) -------------------------------------------------------------------------------- /src/hybridDynamics/Naive.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Naive.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace arch { 12 | 13 | // Forward declared dependencies 14 | template 15 | class Module; 16 | 17 | } 18 | 19 | namespace mmft{ 20 | 21 | /** 22 | * @brief The Naive Scheme is an update scheme that sets the relaxation factor of an iterative update scheme to a 23 | * given constant for all nodes. 24 | */ 25 | template 26 | class NaiveScheme : public Scheme { 27 | 28 | public: 29 | /** 30 | * @brief Constructor of the Naive Scheme with provided constants. 31 | * @param[in] modules The map of modules with boundary nodes upon which this scheme acts. 32 | * @param[in] alpha The relaxation value for the pressure value update. 33 | * @param[in] beta The relaxation value of the flow rate value update. 34 | * @param[in] theta The amount of LBM stream and collide cycles between updates for a module. 35 | */ 36 | NaiveScheme(const std::unordered_map>>& modules, T alpha, T beta, int theta); 37 | 38 | /** 39 | * @brief Constructor of the Naive Scheme with provided constants. 40 | * @param[in] modules The map of modules with boundary nodes upon which this scheme acts. 41 | * @param[in] alpha The relaxation value for the pressure value update. 42 | * @param[in] beta The relaxation value of the flow rate value update. 43 | * @param[in] theta The amount of LBM stream and collide cycles between updates for a module. 44 | */ 45 | NaiveScheme(const std::shared_ptr> module, T alpha, T beta, int theta); 46 | 47 | /** 48 | * @brief Constructor of the Naive Scheme with provided constants. 49 | * @param[in] modules The map of modules with boundary nodes upon which this scheme acts. 50 | * @param[in] alpha The relaxation value for the pressure value update. 51 | * @param[in] beta The relaxation value of the flow rate value update. 52 | * @param[in] theta The amount of LBM stream and collide cycles between updates for a module. 53 | */ 54 | NaiveScheme(const std::shared_ptr> module, std::unordered_map alpha, std::unordered_map beta, int theta); 55 | 56 | /** 57 | * @brief Constructor of the Naive Scheme with provided constants. 58 | * @param[in] nodeIds The Ids of the set of nodes on which this scheme acts 59 | * @param[in] moduleIds The Ids of the set of modules on which this scheme acts. 60 | * @param[in] alpha The relaxation value for the pressure value update. 61 | * @param[in] beta The relaxation value of the flow rate value update. 62 | * @param[in] theta The amount of LBM stream and collide cycles between updates for a module. 63 | */ 64 | NaiveScheme(std::vector nodeIds, std::vector moduleIds, T alpha, T beta, int theta); 65 | 66 | /** 67 | * @brief Constructor of the Naive Scheme with provided constants. The ids of the nodes and modules 68 | * are passed in the maps. 69 | * @param[in] alpha The relaxation value for the pressure value update. 70 | * @param[in] beta The relaxation value of the flow rate value update. 71 | * @param[in] theta The amount of LBM stream and collide cycles between updates for a module. 72 | */ 73 | NaiveScheme(std::unordered_map alpha, std::unordered_map beta, std::unordered_map theta); 74 | 75 | }; 76 | 77 | } // namespace mmft -------------------------------------------------------------------------------- /src/hybridDynamics/Naive.hh: -------------------------------------------------------------------------------- 1 | #include "Naive.h" 2 | 3 | namespace mmft { 4 | 5 | template 6 | NaiveScheme::NaiveScheme(const std::unordered_map>>& modules, T alpha, T beta, int theta) : 7 | Scheme(modules, alpha, beta, theta) { } 8 | 9 | template 10 | NaiveScheme::NaiveScheme(const std::shared_ptr> module, T alpha, T beta, int theta) : 11 | Scheme(module, alpha, beta, theta) { } 12 | 13 | template 14 | NaiveScheme::NaiveScheme(const std::shared_ptr> module, std::unordered_map alpha, std::unordered_map beta, int theta) : 15 | Scheme(module, alpha, beta, theta) { } 16 | 17 | template 18 | NaiveScheme::NaiveScheme(std::vector nodeIds, std::vector moduleIds, T alpha, T beta, int theta) : 19 | Scheme() 20 | { 21 | for (auto nodeId : nodeIds) { 22 | this->alpha.try_emplace(nodeId, alpha); 23 | } 24 | for (auto nodeId : nodeIds) { 25 | this->beta.try_emplace(nodeId, beta); 26 | } 27 | for (auto moduleId : moduleIds) { 28 | this->alpha.try_emplace(moduleId, theta); 29 | } 30 | } 31 | 32 | template 33 | NaiveScheme::NaiveScheme(std::unordered_map alpha_, std::unordered_map beta_, std::unordered_map theta_) : 34 | Scheme(alpha_, beta_, theta_) { } 35 | 36 | } // namespace mmft -------------------------------------------------------------------------------- /src/hybridDynamics/Scheme.hh: -------------------------------------------------------------------------------- 1 | #include "Scheme.h" 2 | 3 | namespace mmft { 4 | 5 | template 6 | Scheme::Scheme() { } 7 | 8 | template 9 | Scheme::Scheme(std::unordered_map alpha_, std::unordered_map beta_, std::unordered_map theta_) : 10 | alpha(alpha_), beta(beta_), theta(theta_) { } 11 | 12 | template 13 | Scheme::Scheme(const std::unordered_map>>& modules_, T alpha_, T beta_, int theta_) 14 | { 15 | for (auto& [key, module] : modules_) { 16 | for (auto& [nodeId, node] : module->getNodes()) { 17 | alpha.try_emplace(nodeId, alpha_); 18 | beta.try_emplace(nodeId, beta_); 19 | } 20 | theta.try_emplace(module->getId(), theta_); 21 | } 22 | } 23 | 24 | template 25 | Scheme::Scheme(const std::shared_ptr> module_, T alpha_, T beta_, int theta_) 26 | { 27 | for (auto& [nodeId, node] : module_->getNodes()) { 28 | alpha.try_emplace(nodeId, alpha_); 29 | beta.try_emplace(nodeId, beta_); 30 | } 31 | theta.try_emplace(module_->getId(), theta_); 32 | } 33 | 34 | template 35 | Scheme::Scheme(const std::shared_ptr> module_, std::unordered_map alpha_, std::unordered_map beta_, int theta_) : 36 | alpha(alpha_), beta(beta_) 37 | { 38 | theta.try_emplace(module_->getId(), theta_); 39 | } 40 | 41 | template 42 | void Scheme::setAlpha(T alpha_) { 43 | for (auto& a : alpha) { 44 | a = static_cast(alpha_); 45 | } 46 | } 47 | 48 | template 49 | void Scheme::setAlpha(int nodeId_, T alpha_) { 50 | alpha.at(nodeId_) = alpha_; 51 | } 52 | 53 | template 54 | void Scheme::setAlpha(std::unordered_map alpha_) { 55 | alpha = alpha_; 56 | } 57 | 58 | template 59 | void Scheme::setBeta(T beta_) { 60 | for (auto& b : beta) { 61 | b = static_cast(beta_); 62 | } 63 | } 64 | 65 | template 66 | void Scheme::setBeta(int nodeId_, T beta_) { 67 | beta.at(nodeId_) = beta_; 68 | } 69 | 70 | template 71 | void Scheme::setBeta(std::unordered_map beta_) { 72 | beta = beta_; 73 | } 74 | 75 | template 76 | void Scheme::setTheta(int theta_) { 77 | for (auto& t : theta) { 78 | t = static_cast(theta_); 79 | } 80 | } 81 | 82 | template 83 | void Scheme::setTheta(int moduleId_, int theta_) { 84 | theta.at(moduleId_) = theta_; 85 | } 86 | 87 | template 88 | void Scheme::setTheta(std::unordered_map theta_) { 89 | theta = theta_; 90 | } 91 | 92 | template 93 | T Scheme::getAlpha(int nodeId_) const { 94 | return alpha.at(nodeId_); 95 | } 96 | 97 | template 98 | const std::unordered_map& Scheme::getAlpha() const { 99 | return alpha; 100 | } 101 | 102 | template 103 | T Scheme::getBeta(int nodeId_) const { 104 | return beta.at(nodeId_); 105 | } 106 | 107 | template 108 | const std::unordered_map& Scheme::getBeta() const { 109 | return beta; 110 | } 111 | 112 | template 113 | int Scheme::getTheta(int moduleId_) const { 114 | return theta.at(moduleId_); 115 | } 116 | 117 | template 118 | const std::unordered_map& Scheme::getTheta() const { 119 | return theta; 120 | } 121 | 122 | } // namespace mmft 123 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | //#include 2 | 3 | //namespace py = pybind11; 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #ifdef USE_ESSLBM 10 | #include 11 | #endif 12 | 13 | using T = double; 14 | 15 | int main(int argc, char const* argv []) { 16 | 17 | #ifdef USE_ESSLBM 18 | MPI_Init(NULL,NULL); 19 | #endif 20 | 21 | std::string file = argv[1]; 22 | 23 | // Load and set the network from a JSON file 24 | std::cout << "[Main] Create network object..." << std::endl; 25 | arch::Network network = porting::networkFromJSON(file); 26 | 27 | // Load and set the simulation from a JSON file 28 | std::cout << "[Main] Create simulation object..." << std::endl; 29 | sim::Simulation testSimulation = porting::simulationFromJSON(file, &network); 30 | 31 | std::cout << "[Main] Simulation..." << std::endl; 32 | // Perform simulation and store results 33 | testSimulation.simulate(); 34 | 35 | std::cout << "[Main] Results..." << std::endl; 36 | // Print the results 37 | testSimulation.getSimulationResults()->printStates(); 38 | 39 | //std::cout << "Write diffusive mixtures" << std::endl; 40 | //testSimulation.getSimulationResults()->writeMixture(1); 41 | 42 | #ifdef USE_ESSLBM 43 | MPI_Finalize(); 44 | #endif 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /src/nodalAnalysis/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_LIST 2 | NodalAnalysis.hh 3 | ) 4 | 5 | set(HEADER_LIST 6 | NodalAnalysis.h 7 | ) 8 | 9 | target_sources(${TARGET_NAME} PUBLIC ${SOURCE_LIST} ${HEADER_LIST}) 10 | target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) 11 | target_link_libraries(${TARGET_NAME} PUBLIC eigen) -------------------------------------------------------------------------------- /src/nodalAnalysis/NodalAnalysis.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file NodalAnalysis.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "Eigen/Dense" 12 | 13 | using Eigen::MatrixXd; 14 | using Eigen::VectorXd; 15 | 16 | namespace arch { 17 | 18 | // Forward declared dependencies 19 | template 20 | class Network; 21 | 22 | } // namespace arch 23 | 24 | namespace sim { 25 | 26 | // Forward declared dependencies 27 | template 28 | class CFDSimulator; 29 | 30 | } // namespace sim 31 | 32 | namespace nodal { 33 | 34 | template 35 | class NodalAnalysis { 36 | private: 37 | const arch::Network* network = nullptr; 38 | 39 | int nNodes; // Number of nodes 40 | int nPressurePumps; // Number of pressurePumps 41 | 42 | bool pressureConvergence; 43 | 44 | Eigen::MatrixXd A; // matrix A = [G, B; C, D] 45 | Eigen::VectorXd z; // vector z = [i; e] 46 | Eigen::VectorXd x; // vector x = [v; j] 47 | 48 | std::unordered_set conductingNodeIds; 49 | std::unordered_map groundNodeIds; 50 | 51 | void readConductance(); // loop through channels and build matrix G 52 | void updateReferenceP(); // update the reference pressure for each group 53 | void readPressurePumps(); // loop through pressure pumps and build matrix B, C and vector e 54 | void readFlowRatePumps(); // loop through flowRate pumps and build vector i 55 | void solve(); // solve equation x = A^(-1) * z 56 | void setResults(); // set pressure of nodes to v and flow rate at pressure pumps to j 57 | void initGroundNodes(); // initialize the ground nodes of the groups 58 | void clear(); 59 | 60 | // For hybrid simulations 61 | void readCfdSimulators(std::unordered_map>>& cfdSimulators); 62 | void writeCfdSimulators(std::unordered_map>>& cfdSimulators); 63 | void initGroundNodes(std::unordered_map>>& cfdSimulators); 64 | 65 | // Helper functions 66 | bool contains( const std::unordered_set& set, int key); 67 | bool contains( const std::unordered_map& map, int key); 68 | void printSystem(); 69 | 70 | public: 71 | /** 72 | * @brief Creates a NodalAnalysis object 73 | */ 74 | NodalAnalysis(const arch::Network* network); 75 | 76 | /** 77 | * @brief Conducts the Modifed Nodal Analysis (e.g., http://qucs.sourceforge.net/tech/node14.html) and computes the pressure levels for each node. 78 | * Hence, the passed nodes contain the final pressure levels when the function is finished. 79 | * 80 | * @param[in] network Pointer to the network on which the nodal analysis is conducted. Results are stored in the network's nodes. 81 | */ 82 | void conductNodalAnalysis(); 83 | 84 | /** 85 | * @brief Conducts the Modifed Nodal Analysis (e.g., http://qucs.sourceforge.net/tech/node14.html) and computes the pressure levels for each node. 86 | * Hence, the passed nodes contain the final pressure levels when the function is finished. 87 | * 88 | * @param[in] network Pointer to the network on which the nodal analysis is conducted. Results are stored in the network's nodes. 89 | * @param[in] cfdSimulators The cfd simulators for a hybrid simulation 90 | */ 91 | bool conductNodalAnalysis(std::unordered_map>>& cfdSimulators); 92 | 93 | }; 94 | 95 | 96 | } // namespace nodal -------------------------------------------------------------------------------- /src/olbProcessors/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_LIST 2 | navierStokesAdvectionDiffusionCouplingPostProcessor2D.hh 3 | saturatedFluxPostProcessor2D.hh 4 | setFunctionalRegularizedHeatFlux.hh 5 | ) 6 | 7 | set(HEADER_LIST 8 | navierStokesAdvectionDiffusionCouplingPostProcessor2D.h 9 | saturatedFluxPostProcessor2D.h 10 | setFunctionalRegularizedHeatFlux.h 11 | ) 12 | 13 | target_sources(${TARGET_NAME} PUBLIC ${SOURCE_LIST} ${HEADER_LIST}) 14 | target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) 15 | target_link_libraries(${TARGET_NAME} PUBLIC lbmLib) -------------------------------------------------------------------------------- /src/olbProcessors/navierStokesAdvectionDiffusionCouplingPostProcessor2D.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace olb { 7 | 8 | /** 9 | * Class for the coupling between a Navier-Stokes (NS) lattice and an 10 | * Advection-Diffusion (AD) lattice. 11 | */ 12 | 13 | //====================================================================== 14 | // ========== AD coupling in Single Direction 2D =======================// 15 | //====================================================================== 16 | template 17 | class NavierStokesAdvectionDiffusionSingleCouplingPostProcessor2D : public LocalPostProcessor2D { 18 | private: 19 | typedef DESCRIPTOR L; 20 | int x0, x1, y0, y1; 21 | const std::vector velFactors; 22 | std::vector>*> tPartners; 23 | std::vector*> partners; 24 | 25 | public: 26 | NavierStokesAdvectionDiffusionSingleCouplingPostProcessor2D(int x0_, int x1_, int y0_, int y1_, std::vector velFactors, 27 | std::vector* > partners_); 28 | int extent() const override 29 | { 30 | return 0; 31 | } 32 | int extent(int whichDirection) const override 33 | { 34 | return 0; 35 | } 36 | void process(BlockLattice& blockLattice) override; 37 | void processSubDomain(BlockLattice& blockLattice, 38 | int x0_, int x1_, int y0_, int y1_) override; 39 | }; 40 | 41 | template 42 | class NavierStokesAdvectionDiffusionSingleCouplingGenerator2D : public LatticeCouplingGenerator2D { 43 | private: 44 | const std::vector velFactors; 45 | 46 | public: 47 | NavierStokesAdvectionDiffusionSingleCouplingGenerator2D(int x0_, int x1_, int y0_, int y1_, std::vector velFactors_); 48 | PostProcessor2D* generate(std::vector* > partners) const override; 49 | LatticeCouplingGenerator2D* clone() const override; 50 | }; 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/olbProcessors/navierStokesAdvectionDiffusionCouplingPostProcessor2D.hh: -------------------------------------------------------------------------------- 1 | #include "navierStokesAdvectionDiffusionCouplingPostProcessor2D.h" 2 | 3 | namespace olb { 4 | 5 | //===================================================================================== 6 | //=========== NavierStokesAdvectionDiffusionSingleCouplingPostProcessor2D ============ 7 | //===================================================================================== 8 | 9 | template 10 | NavierStokesAdvectionDiffusionSingleCouplingPostProcessor2D:: 11 | NavierStokesAdvectionDiffusionSingleCouplingPostProcessor2D(int x0_, int x1_, int y0_, int y1_, std::vector velFactors_, std::vector* > partners_) 12 | : x0(x0_), x1(x1_), y0(y0_), y1(y1_), velFactors(velFactors_), partners(partners_) 13 | { 14 | this->getName() = "NavierStokesAdvectionDiffusionSingleCouplingPostProcessor2D"; 15 | for (long unsigned int i = 0; i> *>(partners[i])); 17 | } 18 | } 19 | 20 | template 21 | void NavierStokesAdvectionDiffusionSingleCouplingPostProcessor2D:: 22 | processSubDomain(BlockLattice& blockLattice, 23 | int x0_, int x1_, int y0_, int y1_) 24 | { 25 | int newX0, newX1, newY0, newY1; 26 | if ( util::intersect ( 27 | x0, x1, y0, y1, 28 | x0_, x1_, y0_, y1_, 29 | newX0, newX1, newY0, newY1 ) ) { 30 | 31 | for (long unsigned int i = 0; iget(iX,iY); 36 | // Velocity coupling 37 | T u[DESCRIPTOR::d] { }; 38 | cell.computeU(u); 39 | for ( int d = 0; d(u); 43 | } 44 | } 45 | } 46 | } 47 | } 48 | 49 | template 50 | void NavierStokesAdvectionDiffusionSingleCouplingPostProcessor2D:: 51 | process(BlockLattice& blockLattice) 52 | { 53 | processSubDomain(blockLattice, x0, x1, y0, y1); 54 | } 55 | 56 | /// LatticeCouplingGenerator for advectionDiffusion coupling 57 | 58 | template 59 | NavierStokesAdvectionDiffusionSingleCouplingGenerator2D:: 60 | NavierStokesAdvectionDiffusionSingleCouplingGenerator2D(int x0_, int x1_, int y0_, int y1_, std::vector velFactors_) 61 | : LatticeCouplingGenerator2D(x0_, x1_, y0_, y1_), velFactors(velFactors_) 62 | { } 63 | 64 | template 65 | PostProcessor2D* NavierStokesAdvectionDiffusionSingleCouplingGenerator2D::generate ( 66 | std::vector* > partners) const 67 | { 68 | return new NavierStokesAdvectionDiffusionSingleCouplingPostProcessor2D( 69 | this->x0,this->x1,this->y0,this->y1, this->velFactors, partners); 70 | } 71 | 72 | template 73 | LatticeCouplingGenerator2D* NavierStokesAdvectionDiffusionSingleCouplingGenerator2D::clone() const 74 | { 75 | return new NavierStokesAdvectionDiffusionSingleCouplingGenerator2D(*this); 76 | } 77 | 78 | } // namespace olb 79 | -------------------------------------------------------------------------------- /src/olbProcessors/saturatedFluxPostProcessor2D.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace olb { 7 | 8 | //////// SaturationFluxProcessor2D //////////////////////////// 9 | 10 | template 11 | class SaturatedFluxProcessor2D : public LocalPostProcessor2D { 12 | public: 13 | SaturatedFluxProcessor2D(int x0_, int x1_, int y0_, int y1_, 14 | int discreteNormalX_, int discreteNormalY_, T *Vmax, T *Km); 15 | int extent() const override 16 | { 17 | return 1; 18 | } 19 | int extent(int whichDirection) const override 20 | { 21 | return 1; 22 | } 23 | void process(BlockLattice& blockLattice) override; 24 | void processSubDomain(BlockLattice& blockLattice, 25 | int x0_,int x1_,int y0_,int y1_ ) override; 26 | private: 27 | int x0, x1, y0, y1; 28 | int discreteNormalX, discreteNormalY; 29 | T *Vmax; 30 | T *Km; 31 | }; 32 | 33 | /// Generator class for the FreeEnergyWall PostProcessor handling the wetting boundary condition. 34 | template 35 | class SaturatedFluxProcessorGenerator2D : public PostProcessorGenerator2D { 36 | public: 37 | SaturatedFluxProcessorGenerator2D(int x0_, int x1_, int y0_, int y1_, 38 | int discreteNormalX_, int discreteNormalY_, T *Vmax_, T *Km_); 39 | PostProcessor2D* generate() const override; 40 | PostProcessorGenerator2D* clone() const override; 41 | private: 42 | int discreteNormalX; 43 | int discreteNormalY; 44 | T *Vmax; 45 | T *Km; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /src/olbProcessors/saturatedFluxPostProcessor2D.hh: -------------------------------------------------------------------------------- 1 | #include "saturatedFluxPostProcessor2D.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace olb { 7 | 8 | //////// SaturationFluxProcessor2D //////////////////////////// 9 | 10 | template 11 | SaturatedFluxProcessor2D:: 12 | SaturatedFluxProcessor2D(int x0_, int x1_, int y0_, int y1_, int discreteNormalX_, int discreteNormalY_, T *Vmax_, T *Km_) 13 | : x0(x0_), x1(x1_), y0(y0_), y1(y1_), 14 | discreteNormalX(discreteNormalX_), discreteNormalY(discreteNormalY_), 15 | Vmax(Vmax_), Km(Km_) 16 | { 17 | this->getName() = "SaturatedFluxProcessor2D"; 18 | } 19 | 20 | template 21 | void SaturatedFluxProcessor2D:: 22 | processSubDomain(BlockLattice& blockLattice, int x0_, int x1_, int y0_, int y1_) 23 | { 24 | int newX0, newX1, newY0, newY1; 25 | if ( util::intersect ( 26 | x0, x1, y0, y1, 27 | x0_, x1_, y0_, y1_, 28 | newX0, newX1, newY0, newY1 ) ) { 29 | 30 | T u[2]; 31 | for (int iX=newX0; iX<=newX1; ++iX) { 32 | for (int iY=newY0; iY<=newY1; ++iY) { 33 | T tempFluid = blockLattice.get(iX-discreteNormalX, iY-discreteNormalY).computeRho(); 34 | T flux = ((*Vmax) * tempFluid) / ((*Km) + tempFluid); 35 | u[0] = flux*discreteNormalX; 36 | u[1] = flux*discreteNormalY; 37 | blockLattice.get(iX,iY).defineU(u); 38 | } 39 | } 40 | } 41 | } 42 | 43 | template 44 | void SaturatedFluxProcessor2D:: 45 | process(BlockLattice& blockLattice) 46 | { 47 | processSubDomain(blockLattice, x0, x1, y0, y1); 48 | } 49 | 50 | template 51 | SaturatedFluxProcessorGenerator2D:: 52 | SaturatedFluxProcessorGenerator2D(int x0_, int x1_, int y0_, int y1_, int discreteNormalX_, 53 | int discreteNormalY_, T *Vmax_, T *Km_) 54 | : PostProcessorGenerator2D(x0_, x1_, y0_, y1_), discreteNormalX(discreteNormalX_), 55 | discreteNormalY(discreteNormalY_), Vmax(Vmax_), Km(Km_) 56 | { } 57 | 58 | template 59 | PostProcessor2D* 60 | SaturatedFluxProcessorGenerator2D::generate() const 61 | { 62 | return new SaturatedFluxProcessor2D 63 | (this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY, Vmax, Km); 64 | } 65 | 66 | template 67 | PostProcessorGenerator2D* 68 | SaturatedFluxProcessorGenerator2D::clone() const 69 | { 70 | return new SaturatedFluxProcessorGenerator2D 71 | (this->x0, this->x1, this->y0, this->y1, discreteNormalX, discreteNormalY, Vmax, Km); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/olbProcessors/setFunctionalRegularizedHeatFlux.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace olb { 7 | 8 | ///Initialising the FunctionalRegularizedHeatFluxBoundary on the superLattice domain 9 | ///This is an advection diffusion boundary -->MixinDynamics = AdvectionDiffusionRLBdynamics 10 | template> 11 | void setFunctionalRegularizedHeatFluxBoundary(SuperLattice& sLattice,T omega, SuperGeometry& superGeometry, int material, T *Vmax=nullptr, T *Km=nullptr); 12 | 13 | ///Initialising the RegularizedHeatFluxBoundary on the superLattice domain 14 | template 15 | void setFunctionalRegularizedHeatFluxBoundary(SuperLattice& sLattice,T omega, FunctorPtr>&& indicator, T *Vmax=nullptr, T *Km=nullptr); 16 | 17 | 18 | ///Set RegularizedHeatFluxBoundary for indicated cells inside the block domain 19 | template 20 | void setFunctionalRegularizedHeatFluxBoundary(BlockLattice& block, T omega, BlockIndicatorF2D& indicator, T *Vmax, T *Km); 21 | 22 | }//namespace olb 23 | -------------------------------------------------------------------------------- /src/porting/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_LIST 2 | jsonPorter.hh 3 | jsonReaders.hh 4 | jsonWriters.hh 5 | ) 6 | 7 | set(HEADER_LIST 8 | jsonPorter.h 9 | jsonReaders.h 10 | jsonWriters.h 11 | ) 12 | 13 | target_sources(${TARGET_NAME} PUBLIC ${SOURCE_LIST} ${HEADER_LIST}) 14 | target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) 15 | target_link_libraries(${TARGET_NAME} PUBLIC lbmLib) -------------------------------------------------------------------------------- /src/porting/jsonWriters.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file jsonWriters.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "nlohmann/json.hpp" 14 | 15 | using ordered_json = nlohmann::ordered_json; 16 | 17 | namespace sim { 18 | 19 | // Forward declared dependencies 20 | template 21 | class Simulation; 22 | 23 | } // namespace sim 24 | 25 | namespace arch { 26 | 27 | template 28 | class Network; 29 | 30 | } // namespace arch 31 | 32 | namespace result { 33 | 34 | // Forward declared dependencies 35 | template 36 | class State; 37 | 38 | } // namespace result 39 | 40 | namespace porting { 41 | 42 | /** 43 | * @brief Write the pressures at the nodes in a network at a state (timestamp) of the simulation 44 | * @param[in] state the state (timestamp) of the simulation that should be written 45 | * @return The json string containing the result 46 | */ 47 | template 48 | auto writePressures (result::State* state); 49 | 50 | /** 51 | * @brief Write the flow rates in the channels of a network at a state (timestamp) of the simulation 52 | * @param[in] state the state (timestamp) of the simulation that should be written 53 | * @return The json string containing the result 54 | */ 55 | template 56 | auto writeChannels (arch::Network* network, result::State* state); 57 | 58 | /** 59 | * @brief Write the location of the vtk results of a module at a state (timestamp) of the simulation 60 | * @param[in] state the state (timestamp) of the simulation that should be written 61 | * @return The json string containing the result 62 | */ 63 | template 64 | auto writeModules (result::State* state); 65 | 66 | /** 67 | * @brief Write the droplet positions at a state (timestamp) of the simulation 68 | * @param[in] state the state (timestamp) of the simulation that should be written 69 | * @param[in] simulation pointer to the simulation of which the results are written 70 | * @return The json string containing the result 71 | */ 72 | template 73 | auto writeDroplets (result::State* state, sim::Simulation* simulation); 74 | 75 | /** 76 | * @brief Write set of fluids of the simulation 77 | * @param[in] simulation pointer to the simulation of which the results are written 78 | * @return The json string containing the result 79 | */ 80 | template 81 | auto writeFluids (sim::Simulation* simulation); 82 | 83 | template 84 | auto writeMixtures (sim::Simulation* simulation); 85 | 86 | /** 87 | * @brief Return the simulation type of the simulation 88 | * @param[in] simulation pointer to the simulation of which the results are written 89 | * @return String of the simulation type 90 | */ 91 | template 92 | std::string writeSimType (sim::Simulation* simulation); 93 | 94 | /** 95 | * @brief Return the platform of the simulation 96 | * @param[in] simulation pointer to the simulation of which the results are written 97 | * @return String of the platform 98 | */ 99 | template 100 | std::string writeSimPlatform (sim::Simulation* simulation); 101 | 102 | } // namespace porting -------------------------------------------------------------------------------- /src/result/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_LIST 2 | Results.hh 3 | ) 4 | 5 | set(HEADER_LIST 6 | Results.h 7 | ) 8 | 9 | target_sources(${TARGET_NAME} PUBLIC ${SOURCE_LIST} ${HEADER_LIST}) 10 | target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) 11 | target_link_libraries(${TARGET_NAME} PUBLIC lbmLib) -------------------------------------------------------------------------------- /src/simulation/CFDSim.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file CFDSim.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | namespace sim { 11 | 12 | // Forward declared dependencies 13 | template 14 | class CFDSimulator; 15 | 16 | /** 17 | * @brief Conduct the NS simulation step (of theta iterations) for all CFD simulators on the simulation. 18 | * The amount of collide and stream iterations, theta, is obtained from the update scheme of the simulator. 19 | * @returns A boolean for whether all simulators have converged, or not. 20 | */ 21 | template 22 | bool conductCFDSimulation(const std::unordered_map>>& cfdSimulators); 23 | 24 | /** 25 | * @brief Conduct the coupling step between the AD lattice and the NS lattice for all simulators. 26 | */ 27 | template 28 | void coupleNsAdLattices(const std::unordered_map>>& cfdSimulators); 29 | 30 | /** 31 | * @brief Conduct the AD simulation step (of theta iterations) for all CFD simulators on the simulation. 32 | * The amount of collide and stream iterations, theta, is obtained from the update scheme of the simulator. 33 | * @returns A boolean for whether all simulators have converged, or not. 34 | */ 35 | template 36 | bool conductADSimulation(const std::unordered_map>>& cfdSimulators); 37 | 38 | } // namespace sim -------------------------------------------------------------------------------- /src/simulation/CFDSim.hh: -------------------------------------------------------------------------------- 1 | #include "CFDSim.h" 2 | 3 | namespace sim { 4 | 5 | template 6 | bool conductCFDSimulation(const std::unordered_map>>& cfdSimulators) { 7 | 8 | bool allConverge = true; 9 | 10 | // loop through modules and perform the collide and stream operations 11 | for (const auto& cfdSimulator : cfdSimulators) { 12 | 13 | // Assertion that the current module is of lbm type, and can conduct CFD simulations. 14 | #ifndef USE_ESSLBM 15 | assert(cfdSimulator.second->getModule()->getModuleType() == arch::ModuleType::LBM); 16 | #elif USE_ESSLBM 17 | assert(cfdSimulator.second->getModule()->getModuleType() == arch::ModuleType::ESS_LBM); 18 | #endif 19 | cfdSimulator.second->solve(); 20 | 21 | if (!cfdSimulator.second->hasConverged()) { 22 | allConverge = false; 23 | } 24 | 25 | } 26 | 27 | return allConverge; 28 | } 29 | 30 | template 31 | void coupleNsAdLattices(const std::unordered_map>>& cfdSimulators) { 32 | 33 | // loop through modules and perform the coupling between the NS and AD lattices 34 | for (const auto& cfdSimulator : cfdSimulators) { 35 | 36 | // Assertion that the current module is of lbm type, and can conduct CFD simulations. 37 | #ifndef USE_ESSLBM 38 | assert(cfdSimulator.second->getModule()->getModuleType() == arch::ModuleType::LBM); 39 | #elif USE_ESSLBM 40 | assert(cfdSimulator.second->getModule()->getModuleType() == arch::ModuleType::ESS_LBM); 41 | throw std::runtime_error("Coupling between NS and AD fields not defined for ESS LBM."); 42 | #endif 43 | 44 | cfdSimulator.second->executeCoupling(); 45 | 46 | } 47 | } 48 | 49 | template 50 | bool conductADSimulation(const std::unordered_map>>& cfdSimulators) { 51 | 52 | bool allConverge = true; 53 | 54 | // loop through modules and perform the collide and stream operations 55 | for (const auto& cfdSimulator : cfdSimulators) { 56 | 57 | // Assertion that the current module is of lbm type, and can conduct CFD simulations. 58 | #ifndef USE_ESSLBM 59 | assert(cfdSimulator.second->getModule()->getModuleType() == arch::ModuleType::LBM); 60 | #elif USE_ESSLBM 61 | assert(cfdSimulator.second->getModule()->getModuleType() == arch::ModuleType::ESS_LBM); 62 | throw std::runtime_error("Simulation of Advection Diffusion not defined for ESS LBM."); 63 | #endif 64 | cfdSimulator.second->adSolve(); 65 | 66 | if (!cfdSimulator.second->hasAdConverged()) { 67 | allConverge = false; 68 | } 69 | 70 | } 71 | 72 | return allConverge; 73 | } 74 | 75 | } // namespace sim 76 | -------------------------------------------------------------------------------- /src/simulation/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_LIST 2 | CFDSim.hh 3 | Droplet.hh 4 | Fluid.hh 5 | Injection.hh 6 | MixingModels.hh 7 | Mixture.hh 8 | MixtureInjection.hh 9 | ResistanceModels.hh 10 | Simulation.hh 11 | Specie.hh 12 | Tissue.hh 13 | ) 14 | 15 | set(HEADER_LIST 16 | CFDSim.h 17 | Droplet.h 18 | Fluid.h 19 | Injection.h 20 | MixingModels.h 21 | Mixture.h 22 | MixtureInjection.h 23 | ResistanceModels.h 24 | Simulation.h 25 | Specie.h 26 | Tissue.h 27 | ) 28 | 29 | target_sources(${TARGET_NAME} PUBLIC ${SOURCE_LIST} ${HEADER_LIST}) 30 | target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) 31 | target_link_libraries(${TARGET_NAME} PUBLIC lbmLib) 32 | 33 | add_subdirectory(events) 34 | add_subdirectory(simulators) -------------------------------------------------------------------------------- /src/simulation/Fluid.hh: -------------------------------------------------------------------------------- 1 | #include "Fluid.h" 2 | 3 | namespace sim { 4 | 5 | template 6 | Fluid::Fluid(int id_, T density_, T viscosity_, T concentration_) : id(id_), density(density_), 7 | viscosity(viscosity_), concentration(concentration_) { } 8 | 9 | template 10 | Fluid::Fluid(int id_, T density_, T viscosity_, T concentration_, std::string name_) : id(id_), 11 | density(density_), viscosity(viscosity_), concentration(concentration_), name(name_) { } 12 | 13 | template 14 | Fluid::Fluid(int id_, T density_, T viscosity_, T concentration_, T molecularSize_, std::string name_) : id(id_), 15 | density(density_), viscosity(viscosity_), concentration(concentration_), molecularSize(molecularSize_), name(name_) { } 16 | 17 | template 18 | void Fluid::setName(std::string name_) { 19 | this->name = std::move(name_); 20 | } 21 | 22 | template 23 | int Fluid::getId() const { 24 | return id; 25 | } 26 | 27 | template 28 | std::string Fluid::getName() const { 29 | return name; 30 | } 31 | 32 | template 33 | T Fluid::getViscosity() const { 34 | return viscosity; 35 | } 36 | 37 | template 38 | T Fluid::getDensity() const { 39 | return density; 40 | } 41 | 42 | template 43 | T Fluid::getConcentration() const { 44 | return concentration; 45 | } 46 | 47 | template 48 | void Fluid::addMixedFluid(Fluid* fluid) { 49 | mixedFluids.push_back(fluid); 50 | } 51 | 52 | template 53 | const std::vector*>& Fluid::getMixedFluids() const { 54 | return mixedFluids; 55 | } 56 | 57 | } // namespace sim -------------------------------------------------------------------------------- /src/simulation/Injection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Injection.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | namespace arch { 11 | 12 | // Forward declared dependencies 13 | template 14 | class ChannelPosition; 15 | 16 | template 17 | class RectangularChannel; 18 | 19 | } 20 | 21 | namespace sim { 22 | 23 | // Forward declared dependencies 24 | template 25 | class Droplet; 26 | 27 | /** 28 | * @brief Class that contains all paramaters necessary to conduct an injection. 29 | */ 30 | template 31 | class DropletInjection { 32 | private: 33 | const int id; ///< Unique identifier of an injection. 34 | std::string name = ""; ///< Name of the injection. 35 | Droplet* droplet = nullptr; ///< Pointer to droplet to be injected. 36 | T injectionTime; ///< Time at which the injection should take place in s elapsed since the start of the simulation. 37 | arch::ChannelPosition injectionPosition; ///< Position at which the droplet should be injected. 38 | 39 | public: 40 | /** 41 | * @brief Create an injection. 42 | * @param[in] id Unique identifier of an injection. 43 | * @param[in] droplet Pointer to the droplet to be injected. 44 | * @param[in] injectionTime Time at which the droplet should be injected in s elapsed since the start of the simulation in s. 45 | * @param[in] channel Channel in which the droplet should be injected. The channel must be able to fully contain the droplet. 46 | * @param[in] injectionPosition Relative position (between 0.0 and 1.0) of the middle of the droplet in channel. Head and tail position must be in same channel. 47 | */ 48 | DropletInjection(int id, Droplet* droplet, T injectionTime, arch::RectangularChannel* channel, T injectionPosition); 49 | 50 | /** 51 | * @brief Set name of injection. 52 | * @param[in] name Name of injection. 53 | */ 54 | void setName(std::string name); 55 | 56 | /** 57 | * @brief Retrieve unique identifier of injection. 58 | * @return Unique identifier of injection. 59 | */ 60 | int getId() const; 61 | 62 | /** 63 | * @brief Retireve name of injection. 64 | * @return Name of injection. 65 | */ 66 | std::string getName() const; 67 | 68 | /** 69 | * @brief Retrieve time at which the droplet should be injected. 70 | * @return Time in s elapsed since the start of the simulation at which the injection of the droplet should take place in s. 71 | */ 72 | T getInjectionTime() const; 73 | 74 | /** 75 | * @brief Retrieve position at which the injection should take place. 76 | * @return Position at which the injection should take place. An injection can only take place in channels that are able to fully contain droplet. 77 | */ 78 | const arch::ChannelPosition& getInjectionPosition() const; 79 | 80 | /** 81 | * @brief Retrieve pointer to the droplet that should be injected. 82 | * @return Droplet to be injected. 83 | */ 84 | Droplet* getDroplet() const; 85 | }; 86 | 87 | } // namespace sim 88 | -------------------------------------------------------------------------------- /src/simulation/Injection.hh: -------------------------------------------------------------------------------- 1 | #include "Injection.h" 2 | 3 | namespace sim { 4 | 5 | template 6 | DropletInjection::DropletInjection(int id, Droplet* droplet, T injectionTime, arch::RectangularChannel* channel, T injectionPosition) : 7 | id(id), droplet(droplet), injectionTime(injectionTime), injectionPosition(arch::ChannelPosition(channel, injectionPosition)) { } 8 | 9 | template 10 | void DropletInjection::setName(std::string name) { 11 | name = std::move(name); 12 | } 13 | 14 | template 15 | int DropletInjection::getId() const { 16 | return id; 17 | } 18 | 19 | template 20 | std::string DropletInjection::getName() const { 21 | return name; 22 | } 23 | 24 | template 25 | T DropletInjection::getInjectionTime() const { 26 | return injectionTime; 27 | } 28 | 29 | template 30 | const arch::ChannelPosition& DropletInjection::getInjectionPosition() const { 31 | return injectionPosition; 32 | } 33 | 34 | template 35 | Droplet* DropletInjection::getDroplet() const { 36 | return droplet; 37 | } 38 | 39 | } // namespace sim 40 | -------------------------------------------------------------------------------- /src/simulation/MixtureInjection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file MixtureInjection.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace arch { 12 | 13 | // Forward declared dependencies 14 | template 15 | class ChannelPosition; 16 | 17 | template 18 | class RectangularChannel; 19 | 20 | } 21 | 22 | namespace sim { 23 | 24 | // Forward declared dependencies 25 | template 26 | class Mixture; 27 | 28 | /** 29 | * @brief Class that contains all paramaters necessary to conduct an injection of a mixture. 30 | */ 31 | template 32 | class MixtureInjection { 33 | private: 34 | const int id; ///< Unique identifier of an injection. 35 | std::string name = ""; ///< Name of the injection. 36 | int mixtureId; ///< Id of mixture to be injected. 37 | arch::RectangularChannel* injectionChannel = nullptr; ///< Channel at which the fluid is injected. 38 | T injectionTime; ///< Time at which the injection should start in s elapsed since the start of the simulation. 39 | bool performed = false; ///< Information if the change of the input mixture was already performed or not. 40 | 41 | public: 42 | /** 43 | * @brief Create a mixture injection. 44 | * @param[in] id Unique identifier of an injection. 45 | * @param[in] mixture Pointer to the mixture to be injected. 46 | * @param[in] injectionPump Pump from which the fluid is injected 47 | * @param[in] injectionTime Time at which the fluid injection should start, in s elapsed since the start of the simulation in s. 48 | */ 49 | MixtureInjection(int id, int mixtureId, arch::RectangularChannel* channel, T injectionTime); 50 | 51 | /** 52 | * @brief Set name of injection. 53 | * @param[in] name Name of injection. 54 | */ 55 | void setName(std::string name); 56 | 57 | /** 58 | * @brief Retrieve unique identifier of injection. 59 | * @return Unique identifier of injection. 60 | */ 61 | int getId() const; 62 | 63 | /** 64 | * @brief Retireve name of injection. 65 | * @return Name of injection. 66 | */ 67 | std::string getName() const; 68 | 69 | /** 70 | * @brief Retrieve time at which the droplet should be injected. 71 | * @return Time in s elapsed since the start of the simulation at which the injection of the fluid should take place in s. 72 | */ 73 | T getInjectionTime() const; 74 | 75 | /** 76 | * @brief Retrieve pump from which the injection should take place. 77 | * @return Pump from which the injection should take place. 78 | */ 79 | arch::RectangularChannel* getInjectionChannel(); 80 | 81 | /** 82 | * @brief Retrieve pointer to the fluid that should be injected. 83 | * @return Mixture to be injected. 84 | */ 85 | int getMixtureId(); 86 | 87 | /** 88 | * @brief Update the state if the input mixture change was already performed or not. 89 | * 90 | * @param performed If the input mixture change was performed or not. 91 | */ 92 | void setPerformed(bool performed); 93 | 94 | /** 95 | * @brief Get information if the change of the input mixture was already performed or not. 96 | * 97 | * @return true: Change was already performed. 98 | * @return false: Change was not yet performed. 99 | */ 100 | bool wasPerformed(); 101 | }; 102 | 103 | } // namespace sim -------------------------------------------------------------------------------- /src/simulation/MixtureInjection.hh: -------------------------------------------------------------------------------- 1 | #include "MixtureInjection.h" 2 | 3 | namespace sim { 4 | 5 | template 6 | MixtureInjection::MixtureInjection(int id, int mixtureId, arch::RectangularChannel* injectionChannel, T injectionTime) : id(id), mixtureId(mixtureId), injectionChannel(injectionChannel), injectionTime(injectionTime) {} 7 | 8 | template 9 | void MixtureInjection::setName(std::string name) { 10 | this->name = std::move(name); 11 | } 12 | 13 | template 14 | int MixtureInjection::getId() const { 15 | return id; 16 | } 17 | 18 | template 19 | std::string MixtureInjection::getName() const { 20 | return name; 21 | } 22 | 23 | template 24 | T MixtureInjection::getInjectionTime() const { 25 | return injectionTime; 26 | } 27 | 28 | template 29 | arch::RectangularChannel* MixtureInjection::getInjectionChannel() { 30 | return injectionChannel; 31 | } 32 | 33 | template 34 | int MixtureInjection::getMixtureId() { 35 | return mixtureId; 36 | } 37 | 38 | template 39 | void MixtureInjection::setPerformed(bool performed) { 40 | this->performed = performed; 41 | } 42 | 43 | template 44 | bool MixtureInjection::wasPerformed() { 45 | return performed; 46 | } 47 | 48 | } // namespace sim -------------------------------------------------------------------------------- /src/simulation/ResistanceModels.hh: -------------------------------------------------------------------------------- 1 | #include "ResistanceModels.h" 2 | 3 | namespace sim { 4 | 5 | // ### ResistanceModel ### 6 | template 7 | ResistanceModel::ResistanceModel(T continuousPhaseViscosity_) : continuousPhaseViscosity(continuousPhaseViscosity_) {} 8 | 9 | // ### ResistanceModel1D ### 10 | template 11 | ResistanceModel1D::ResistanceModel1D(T continuousPhaseViscosity_) : ResistanceModel(continuousPhaseViscosity_) {} 12 | 13 | template 14 | T ResistanceModel1D::getChannelResistance(arch::RectangularChannel const* const channel) const { 15 | T a = computeFactorA(channel->getWidth(), channel->getHeight()); 16 | 17 | return channel->getLength() * a * this->continuousPhaseViscosity / (channel->getWidth() * pow(channel->getHeight(), 3)); 18 | } 19 | 20 | template 21 | T ResistanceModel1D::computeFactorA(T width, T height) const { 22 | return 12. / (1. - 192. * height * tanh(M_PI * width / (2. * height)) / (pow(M_PI, 5.) * width)); 23 | } 24 | 25 | template 26 | T ResistanceModel1D::getDropletResistance(arch::RectangularChannel const* const channel, Droplet* droplet, T volumeInsideChannel) const { 27 | T a = computeFactorA(channel->getWidth(), channel->getHeight()); 28 | T dropletLength = volumeInsideChannel / (channel->getWidth() * channel->getHeight()); 29 | T resistance = 3 * dropletLength * a * this->continuousPhaseViscosity / (channel->getWidth() * pow(channel->getHeight(), 3)); 30 | 31 | if (resistance < 0.0) { 32 | std::cout << "droplet length: \t" << dropletLength << std::endl; 33 | std::cout << "volume inside channel: \t" << volumeInsideChannel << std::endl; 34 | std::cout << "a: \t\t" << a << std::endl; 35 | std::cout << "continuous phase viscosity: \t" << this->continuousPhaseViscosity << std::endl; 36 | std::cout << "channel width: \t" << channel->getWidth() << std::endl; 37 | std::cout << "channel height: \t" << channel->getHeight() << std::endl; 38 | throw std::invalid_argument("Negative droplet resistance. Droplet " + std::to_string(droplet->getId()) + " has a resistance of " + std::to_string(resistance)); 39 | } 40 | 41 | return resistance; 42 | } 43 | 44 | // ### ResistanceModelPoiseuille ### 45 | template 46 | ResistanceModelPoiseuille::ResistanceModelPoiseuille(T continuousPhaseViscosity_) : ResistanceModel(continuousPhaseViscosity_) {} 47 | 48 | template 49 | T ResistanceModelPoiseuille::getChannelResistance(arch::RectangularChannel const* const channel) const { 50 | T a = computeFactorA(channel->getWidth(), channel->getHeight()); 51 | 52 | return channel->getLength() * a * this->continuousPhaseViscosity / (channel->getHeight() * pow(channel->getWidth(), 3)); 53 | } 54 | 55 | template 56 | T ResistanceModelPoiseuille::computeFactorA(T width, T height) const { 57 | return 12.; 58 | } 59 | 60 | template 61 | T ResistanceModelPoiseuille::getDropletResistance(arch::RectangularChannel const* const channel, Droplet* droplet, T volumeInsideChannel) const { 62 | throw std::invalid_argument("The resistance model is not compatible with droplet simulations."); 63 | } 64 | } // namespace sim -------------------------------------------------------------------------------- /src/simulation/Specie.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Specie.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | namespace sim { 11 | 12 | /** 13 | * @brief Class to define a specie. 14 | */ 15 | template 16 | class Specie { 17 | private: 18 | int const id; ///< Unique identifier of the specie. 19 | std::string name = ""; ///< Name of the specie. 20 | T diffusivity; ///< Diffusivity coefficient of the specie in the continuous phase in m^2/s. 21 | T satConc; ///< Saturation concentration of the specie in the continuous phase in g/m^3. 22 | 23 | public: 24 | /** 25 | * @brief Constructs a specie. 26 | * @param[in] id Unique identifier of the specie. 27 | * @param[in] diffusivity Diffusivity of the specie in the continuous phase in m^2/s. 28 | * @param[in] satConc Saturation concentration of the specie in de continuous phase in g/m^3. 29 | */ 30 | Specie(int id, T diffusivity, T satConc); 31 | 32 | /** 33 | * @brief Set name of specie. 34 | * @param[in] name Name of the specie. 35 | */ 36 | void setName(std::string name); 37 | 38 | /** 39 | * @brief Retrieve the unique identifier of the specie. 40 | * @return Unique identifier of the specie. 41 | */ 42 | int getId() const; 43 | 44 | /** 45 | * @brief Retrieve name of the specie. 46 | * @return The name of the specie. 47 | */ 48 | std::string getName() const; 49 | 50 | /** 51 | * @brief Retrieve diffusivity of the specie in the continuous phase. 52 | * @return The diffusivity of the specie in m^2/s. 53 | */ 54 | T getDiffusivity() const; 55 | 56 | /** 57 | * @brief Retrieve saturation concentration of the specie in the continuous phase. 58 | * @return The saturation concentration of the specie in g/m^3. 59 | */ 60 | T getSatConc() const; 61 | 62 | /** 63 | * @brief Set the diffusivity of the specie in the continuous phase. 64 | * @param[in] diffusivity The diffusivity of the specie in m^2/s. 65 | */ 66 | void setDiffusivity(T diffusivity); 67 | 68 | /** 69 | * @brief Set the saturation concentration of the specie in the continuous phase. 70 | * @param[in] satConc The saturation concentration of the specie in g/m^3. 71 | */ 72 | void setSatConc(T satConc); 73 | 74 | }; 75 | 76 | } // namespace sim -------------------------------------------------------------------------------- /src/simulation/Specie.hh: -------------------------------------------------------------------------------- 1 | #include "Specie.h" 2 | 3 | #include 4 | 5 | namespace sim { 6 | 7 | template 8 | Specie::Specie(int id_, T diffusivity_, T satConc_) : id(id_), diffusivity(diffusivity_), satConc(satConc_) { } 9 | 10 | template 11 | void Specie::setName(std::string name_) { 12 | this->name = std::move(name_); 13 | } 14 | 15 | template 16 | int Specie::getId() const { 17 | return id; 18 | } 19 | 20 | template 21 | std::string Specie::getName() const { 22 | return name; 23 | } 24 | 25 | template 26 | T Specie::getDiffusivity() const { 27 | return diffusivity; 28 | } 29 | 30 | template 31 | T Specie::getSatConc() const { 32 | return satConc; 33 | } 34 | 35 | template 36 | void Specie::setDiffusivity(T diffusivity_) { 37 | this->diffusivity = diffusivity_; 38 | } 39 | 40 | template 41 | void Specie::setSatConc(T satConc_) { 42 | this->satConc = satConc_; 43 | } 44 | 45 | 46 | } // namespace sim -------------------------------------------------------------------------------- /src/simulation/Tissue.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Tissue.h 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | namespace sim { 11 | 12 | // Forward declared dependencies 13 | template 14 | class Specie; 15 | 16 | /** 17 | * @brief Class that describes a tissue. 18 | */ 19 | template 20 | class Tissue { 21 | private: 22 | 23 | int id; 24 | std::string name; 25 | 26 | std::unordered_map*> species; 27 | std::unordered_map vMax; // vMax values for the enzymatic kinetics per species for this tissue, according to Michaelis-Menten kinetics 28 | std::unordered_map kM; // kM values for the enzymatic kinetics per species for this tissue, according to Michaelis-Menten kinetics 29 | 30 | public: 31 | /** 32 | * @brief Construct a new tissue. 33 | * @param[in] id The id of this tissue. 34 | */ 35 | Tissue(int id); 36 | 37 | /** 38 | * @brief Construct a new tissue. 39 | * @param[in] id The id of this tissue. 40 | * @param[in] specie A pointer to a species that interacts in enzymatic transformation. 41 | * @param[in] vMax The maximum elimination rate of a species in enzymatic transformation. 42 | * @param[in] kM The concentration associated with 0.5vMax for a species in enzymatic transformation. 43 | */ 44 | Tissue(int id, Specie* specie, T vMax, T kM); 45 | 46 | /** 47 | * @brief Construct a new tissue. 48 | * @param[in] id The id of this tissue. 49 | * @param[in] species An unordered map of pointers to species that interact in enzymatic transformation. 50 | * @param[in] vMax An unordered map of the maximum eleimination rate of species in enzymatic transformation. 51 | * @param[in] kM An unordered map of the concentration associated with 0.5vMax for species in enzymatic transformation. 52 | */ 53 | Tissue(int id, std::unordered_map*> species, std::unordered_map vMax, std::unordered_map kM); 54 | 55 | /** 56 | * @brief Get the name of this tissue. 57 | */ 58 | std::string getName(); 59 | 60 | /** 61 | * @brief Set the name of this tissue. 62 | * @param[in] name The new name of this tissue. 63 | */ 64 | void setName(std::string name); 65 | 66 | /** 67 | * @brief Add a new specie interaction to this tissue. 68 | * @param[in] specie A pointer to a species that interacts in enzymatic transformation. 69 | * @param[in] vMax The maximum eleimination rate of a species in enzymatic transformation. 70 | * @param[in] kM The concentration associated with 0.5vMax for a species in enzymatic transformation. 71 | */ 72 | void addSpecie(Specie* species, T vMax, T kM); 73 | 74 | /** 75 | * @brief Add a set of species interactions to this tissue. 76 | * @param[in] species An unordered map of pointers to species that interact in enzymatic transformation. 77 | * @param[in] vMax An unordered map of the maximum eleimination rate of species in enzymatic transformation. 78 | * @param[in] kM An unordered map of the concentration associated with 0.5vMax for species in enzymatic transformation. 79 | */ 80 | void addSpecies(std::unordered_map*> species, std::unordered_map vMax, std::unordered_map kM); 81 | 82 | std::unordered_map*>& getSpecies(); 83 | 84 | T* getVmax(int speciesId); 85 | 86 | T* getkM(int speciesId); 87 | 88 | }; 89 | 90 | } /// namespace sim -------------------------------------------------------------------------------- /src/simulation/Tissue.hh: -------------------------------------------------------------------------------- 1 | #include "Tissue.h" 2 | 3 | namespace sim { 4 | 5 | template 6 | Tissue::Tissue(int id_) : id(id_) { } 7 | 8 | template 9 | Tissue::Tissue(int id_, Specie* specie_, T vMax_, T kM_) : 10 | id(id_), species(specie_), vMax(vMax_), kM(kM_) { } 11 | 12 | template 13 | Tissue::Tissue(int id_, std::unordered_map*> species_, std::unordered_map vMax_, std::unordered_map kM_) : 14 | id(id_), species(species_), vMax(vMax_), kM(kM_) { } 15 | 16 | template 17 | void Tissue::setName(std::string name_) { 18 | this->name = name_; 19 | } 20 | 21 | template 22 | std::string Tissue::getName() { 23 | return this->name; 24 | } 25 | 26 | template 27 | void Tissue::addSpecie(Specie* specie_, T vMax_, T kM_) { 28 | int specieId = specie_->getId(); 29 | 30 | auto const result = species->try_emplace(specieId, specie_); 31 | if (!result.second) { 32 | std::string errorString = "Cannot add species " + std::to_string(specieId) + " to tissue " + std::to_string(id) + ": This species is already defined for the tissue."; 33 | throw std::invalid_argument(errorString); 34 | } 35 | vMax->try_emplace(specieId, vMax_); 36 | kM->try_emplace(specieId, kM_); 37 | } 38 | 39 | template 40 | void Tissue::addSpecies(std::unordered_map*> species_, std::unordered_map vMax_, std::unordered_map kM_) { 41 | 42 | for (auto& [key, specie_] : species_) { 43 | auto const result = species->try_emplace(key, specie_); 44 | if (!result.second) { 45 | std::string errorString = "Cannot add species " + std::to_string(key) + " to tissue " + std::to_string(id) + ": This species is already defined for the tissue."; 46 | throw std::invalid_argument(errorString); 47 | } 48 | if (vMax_.count(key)) { 49 | vMax->try_emplace(key, vMax_.at(key)); 50 | } else { 51 | std::string errorString = "No vMax value was given for species " + std::to_string(key) + "."; 52 | throw std::invalid_argument(errorString); 53 | } 54 | if (kM_.count(key)) { 55 | kM->try_emplace(key, kM_.at(key)); 56 | } else { 57 | std::string errorString = "No kM value was given for species " + std::to_string(key) + "."; 58 | throw std::invalid_argument(errorString); 59 | } 60 | } 61 | } 62 | 63 | template 64 | std::unordered_map*>& Tissue::getSpecies() { 65 | return species; 66 | } 67 | 68 | template 69 | T* Tissue::getVmax(int speciesId) { 70 | auto vMaxIter = vMax.find(speciesId); 71 | return &(vMaxIter->second); 72 | } 73 | 74 | template 75 | T* Tissue::getkM(int speciesId) { 76 | auto kMIter = kM.find(speciesId); 77 | return &(kMIter->second); 78 | } 79 | 80 | } // namespace sim -------------------------------------------------------------------------------- /src/simulation/events/BoundaryEvent.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file BoundaryHeadEvent.h 4 | */ 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | namespace arch { 11 | 12 | // Forward declared dependencies 13 | template 14 | class Network; 15 | 16 | } 17 | 18 | namespace sim { 19 | 20 | // Forward declared dependencies 21 | template 22 | class Droplet; 23 | 24 | template 25 | class DropletBoundary; 26 | 27 | template 28 | class Event; 29 | 30 | /** 31 | * @brief Class for a boundary head event that takes place when the boundary head reaches the end of a channel. 32 | */ 33 | template 34 | class BoundaryHeadEvent : public Event { 35 | private: 36 | Droplet& droplet; ///< Droplet for which the event should take place. 37 | DropletBoundary& boundary; ///< Boundary of the droplet that is effected by the event. 38 | const arch::Network& network; ///< Microfluidic biochip that is simulated. 39 | 40 | public: 41 | /** 42 | * @brief Construct a new boundary head event. 43 | * @param time Time at which the event should take place, in s elapsed since the start of the simulation. 44 | * @param droplet Droplet for which the event should happen. 45 | * @param boundary Boundary that is effected by the event. 46 | * @param chip Microfluidic biochip. 47 | */ 48 | BoundaryHeadEvent(T time, Droplet& droplet, DropletBoundary& boundary, const arch::Network& network); 49 | 50 | /** 51 | * @brief Perform the boundary head event. 52 | */ 53 | void performEvent() override; 54 | 55 | /** 56 | * @brief Print the boundary head event. 57 | */ 58 | void print() override; 59 | }; 60 | 61 | /** 62 | * @brief Class for a boundary tail event that takes place when the tail boundary reaches the end of a channel. 63 | */ 64 | template 65 | class BoundaryTailEvent : public Event { 66 | private: 67 | Droplet& droplet; ///< Droplet for which the event should take place. 68 | DropletBoundary& boundary; ///< Boundary of the droplet that is effected by the event. 69 | const arch::Network& network; ///< Microfluidic biochip that is simulated. 70 | 71 | public: 72 | /** 73 | * @brief Construct a new boundary tail event. 74 | * @param time Time at which the event should take place, in s elapsed since the start of the simulation. 75 | * @param droplet Droplet for which the event should happen. 76 | * @param boundary Boundary that is effected by the event. 77 | * @param chip Microfluidic biochip. 78 | */ 79 | BoundaryTailEvent(T time, Droplet& droplet, DropletBoundary& boundary, const arch::Network& network); 80 | 81 | /** 82 | * @brief Perform the boundary tail event. 83 | */ 84 | void performEvent() override; 85 | 86 | /** 87 | * @brief print the boundary tail event. 88 | */ 89 | void print() override; 90 | }; 91 | 92 | } // namespace sim 93 | -------------------------------------------------------------------------------- /src/simulation/events/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_LIST 2 | BoundaryEvent.hh 3 | InjectionEvent.hh 4 | MergingEvent.hh 5 | ) 6 | 7 | set(HEADER_LIST 8 | BoundaryEvent.h 9 | Event.h 10 | InjectionEvent.h 11 | MergingEvent.h 12 | ) 13 | 14 | target_sources(${TARGET_NAME} PRIVATE ${SOURCE_LIST} ${HEADER_LIST}) 15 | target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}) -------------------------------------------------------------------------------- /src/simulation/events/Event.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Event.h 3 | */ 4 | #pragma once 5 | 6 | namespace sim { 7 | 8 | /** 9 | * @brief 10 | * Interface for all events. 11 | */ 12 | template 13 | class Event { 14 | protected: 15 | T time; ///< Time at which the event should take place, in s elapsed since the start of the simulation. 16 | int priority; ///< Priority of the event. 17 | 18 | /** 19 | * @brief Specifies an event to take place. 20 | * @param[in] time The time at which the event should take place, in s elapsed since the start of the simulation. 21 | * @param[in] priority Priority of an event, which is important when two events occur at the same time (the lower the value the higher the priority). 22 | */ 23 | Event(T time, int priority) : time(time), priority(priority) {} 24 | 25 | public: 26 | /** 27 | * @brief Virtual constructor of an event to take place. 28 | */ 29 | virtual ~Event() {} 30 | 31 | /** 32 | * @brief Function to get the time at which an event should take place. 33 | * @return Time in s (elapsed since the start of the simulation). 34 | */ 35 | T getTime() const { return time; } 36 | 37 | /** 38 | * @brief Get the priority of the event 39 | * @return Priority value 40 | */ 41 | T getPriority() const { return priority; } 42 | 43 | /** 44 | * @brief Function that is called at the time of the event to perform the event. 45 | */ 46 | virtual void performEvent() = 0; 47 | 48 | /** 49 | * @brief Function that prints the contents of this Event. 50 | */ 51 | virtual void print() = 0; 52 | }; 53 | 54 | /** 55 | * @brief Class to trigger the calculation of the simulation parameters after a minimal time step. 56 | */ 57 | template 58 | class TimeStepEvent : public Event { 59 | public: 60 | /** 61 | * @brief Construct class to schedule a minimal tim estep event. 62 | * @param[in] time Time after minimal time step passed in s elapsed since the start of the simulation. 63 | */ 64 | TimeStepEvent(T time) : Event(time, 2) { } 65 | 66 | /** 67 | * @brief Do nothing except for logging the event. As the event exists, the simulation will be forwarded to this time point in the simulation algorithm and therefore it is ensured that the simulation parameters at this point in time are calculated. 68 | */ 69 | void performEvent() override { return; }; 70 | 71 | /** 72 | * @brief Print the time step event 73 | */ 74 | void print() override { 75 | std::cout << "\n Time Step Event at t=" << this->time << " with priority " << this->priority << "\n" << std::endl; 76 | }; 77 | }; 78 | 79 | } // namespace sim -------------------------------------------------------------------------------- /src/simulation/events/InjectionEvent.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file InjectionEvent.h 3 | */ 4 | 5 | #pragma once 6 | 7 | namespace sim { 8 | 9 | // Forward declared dependencies 10 | template 11 | class Event; 12 | 13 | template 14 | class DropletInjection; 15 | 16 | /** 17 | * @brief Class for an injection event that takes place when a droplet is injected into the network. 18 | */ 19 | template 20 | class DropletInjectionEvent : public Event { 21 | private: 22 | DropletInjection& injection; ///< Specifies if the injection event. 23 | 24 | public: 25 | /** 26 | * @brief Defines an injection event to take place at a certain time. 27 | * @param[in] time The time at which the event should take place in s elapsed since the start of the simulation. 28 | * @param[in,out] injection A class containing all details necessary to conduct an injection event. 29 | */ 30 | DropletInjectionEvent(T time, DropletInjection& injection); 31 | 32 | /** 33 | * @brief Conducts the injection event. 34 | */ 35 | void performEvent() override; 36 | 37 | /** 38 | * @brief Print the injection event. 39 | */ 40 | void print() override; 41 | }; 42 | 43 | /** 44 | * @brief Class for an injection event that takes place when a mixture is injected into the network. 45 | */ 46 | template 47 | class MixtureInjectionEvent : public Event { 48 | private: 49 | MixtureInjection& injection; ///< Specifies the mixture injection. 50 | MixingModel* mixingModel = nullptr; ///< Pointer to the active mixing model. 51 | 52 | public: 53 | /** 54 | * @brief Defines an injection event to take place at a certain time. 55 | * @param[in] time The time at which the event should take place in s elapsed since the start of the simulation. 56 | * @param[in,out] injection A class containing all details necessary to conduct an injection event. 57 | */ 58 | MixtureInjectionEvent(T time, MixtureInjection& injection, MixingModel* mixingModel); 59 | 60 | /** 61 | * @brief Conducts the injection event. 62 | */ 63 | void performEvent() override; 64 | 65 | /** 66 | * @brief Print the injection event. 67 | */ 68 | void print() override; 69 | }; 70 | 71 | /** 72 | * @brief Class for an injection event that takes place when a mixture starts to be injected into the network. 73 | */ 74 | template 75 | class PermanentMixtureInjectionEvent : public Event { 76 | private: 77 | MixtureInjection& injection; ///< Specifies the mixture injection. 78 | MixingModel* mixingModel = nullptr; ///< Pointer to the active mixing model. 79 | 80 | public: 81 | /** 82 | * @brief Defines an injection event to take place at a certain time. 83 | * @param[in] time The time at which the event should take place in s elapsed since the start of the simulation. 84 | * @param[in,out] injection A class containing all details necessary to conduct an injection event. 85 | * @param[in] mixingModel Pointer to active mixing model. 86 | */ 87 | PermanentMixtureInjectionEvent(T time, MixtureInjection& injection, MixingModel* mixingModel); 88 | 89 | /** 90 | * @brief Conducts the injection event. 91 | */ 92 | void performEvent() override; 93 | 94 | /** 95 | * @brief Print the injection event. 96 | */ 97 | void print() override; 98 | }; 99 | } // namespace sim 100 | -------------------------------------------------------------------------------- /src/simulation/events/InjectionEvent.hh: -------------------------------------------------------------------------------- 1 | #include "InjectionEvent.h" 2 | 3 | namespace sim { 4 | 5 | template 6 | DropletInjectionEvent::DropletInjectionEvent(T time, DropletInjection& injection) : 7 | Event(time, 1), injection(injection) {} 8 | 9 | template 10 | void DropletInjectionEvent::performEvent() { 11 | // injection position of the droplet (center of the droplet) 12 | auto channelPosition = injection.getInjectionPosition(); 13 | auto channel = channelPosition.getChannel(); 14 | auto droplet = injection.getDroplet(); 15 | 16 | // for the injection the two boundaries (basically a head and a tail) of the droplet must lie inside the channel (the volume of the droplet must be small enough) 17 | // this is already checked at the creation of the injection and, thus, we don't need this check here 18 | 19 | // the droplet length is a relative value between 0 and 1 20 | T dropletLength = droplet->getVolume() / channel->getVolume(); 21 | 22 | // compute position of the two boundaries 23 | T position0 = (channelPosition.getPosition() - dropletLength / 2); // is always the position which lies closer to 0 24 | T position1 = (channelPosition.getPosition() + dropletLength / 2); // is always the position which lies closer to 1 25 | 26 | // create corresponding boundaries 27 | // since boundary0 always lies closer to 0, the volume of this boundary points to node1 28 | // since boundary1 always lies closer to 1, the volume of this boundary points to node0 29 | droplet->addBoundary(channel, position0, false, BoundaryState::NORMAL); 30 | droplet->addBoundary(channel, position1, true, BoundaryState::NORMAL); 31 | 32 | // set droplet state 33 | droplet->setDropletState(DropletState::NETWORK); 34 | } 35 | 36 | template 37 | void DropletInjectionEvent::print() { 38 | std::cout << "\n Droplet Injection Event at t=" << this->time << " with priority " << this->priority << "\n" << std::endl; 39 | } 40 | 41 | 42 | template 43 | MixtureInjectionEvent::MixtureInjectionEvent(T time, MixtureInjection& injection, MixingModel* mixingModel) : 44 | Event(time, 1), injection(injection), mixingModel(mixingModel) { } 45 | 46 | template 47 | void MixtureInjectionEvent::performEvent() { 48 | 49 | auto channel = injection.getInjectionChannel(); 50 | auto mixture = injection.getMixtureId(); 51 | 52 | mixingModel->injectMixtureInEdge(mixture, channel->getId()); 53 | 54 | injection.setPerformed(true); 55 | } 56 | 57 | template 58 | void MixtureInjectionEvent::print() { 59 | std::cout << "\n Mixture Injection Event at t=" << this->time << " with priority " << this->priority << "\n" << std::endl; 60 | } 61 | 62 | template 63 | PermanentMixtureInjectionEvent::PermanentMixtureInjectionEvent(T time, MixtureInjection& injection, MixingModel* mixingModel) : 64 | Event(time, 1), injection(injection), mixingModel(mixingModel) { } 65 | 66 | template 67 | void PermanentMixtureInjectionEvent::performEvent() { 68 | 69 | auto channel = injection.getInjectionChannel(); 70 | auto mixture = injection.getMixtureId(); 71 | 72 | mixingModel->addPermanentMixtureInjection(mixture, channel->getId()); 73 | 74 | injection.setPerformed(true); 75 | } 76 | 77 | template 78 | void PermanentMixtureInjectionEvent::print() { 79 | std::cout << "\n Permanent Mixture Injection Event starts at t=" << this->time << " with priority " << this->priority << "\n" << std::endl; 80 | } 81 | 82 | } // namespace sim 83 | -------------------------------------------------------------------------------- /src/simulation/simulators/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_LIST 2 | cfdSimulator.hh 3 | olbContinuous.hh 4 | olbMixing.hh 5 | olbOoc.hh 6 | ) 7 | 8 | set(HEADER_LIST 9 | cfdSimulator.h 10 | olbContinuous.h 11 | olbMixing.h 12 | olbOoc.h 13 | ) 14 | 15 | if(USE_ESSLBM) 16 | target_sources(${TARGET_NAME} PUBLIC essContinuous.hh essContinuous.h) 17 | target_sources(${TARGET_NAME} PUBLIC essMixing.hh essMixing.h) 18 | endif() 19 | 20 | target_sources(${TARGET_NAME} PRIVATE ${SOURCE_LIST} ${HEADER_LIST}) 21 | target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}) -------------------------------------------------------------------------------- /src/simulation/simulators/cfdSimulator.hh: -------------------------------------------------------------------------------- 1 | #include "cfdSimulator.h" 2 | 3 | namespace sim{ 4 | 5 | template 6 | CFDSimulator::CFDSimulator (int id_, std::string name_, std::string stlFile_, std::shared_ptr> cfdModule_, std::unordered_map> openings_, ResistanceModel* resistanceModel_) : 7 | id(id_), name(name_), stlFile(stlFile_), cfdModule(cfdModule_), moduleOpenings(openings_) 8 | { 9 | // Create this module's network, required for initial condition 10 | moduleNetwork = std::make_shared> (cfdModule_->getNodes()); 11 | 12 | // Complete this module's network by defining the channels lengths and resistances for a fully connected graph 13 | for (auto& [key, channel] : moduleNetwork->getChannels()) { 14 | auto& nodeA = moduleNetwork->getNodes().at(channel->getNodeA()); 15 | auto& nodeB = moduleNetwork->getNodes().at(channel->getNodeB()); 16 | T dx = nodeA->getPosition().at(0) - nodeB->getPosition().at(0); 17 | T dy = nodeA->getPosition().at(1) - nodeB->getPosition().at(1); 18 | channel->setLength(sqrt(dx*dx + dy*dy)); 19 | } 20 | for (auto& [key, channel] : moduleNetwork->getChannels()) { 21 | T resistance = resistanceModel_->getChannelResistance(channel.get()); 22 | channel->setResistance(resistance); 23 | } 24 | } 25 | 26 | template 27 | CFDSimulator::CFDSimulator (int id_, std::string name_, std::string stlFile_, std::shared_ptr> cfdModule_, std::unordered_map> openings_, std::shared_ptr> updateScheme_, ResistanceModel* resistanceModel_) : 28 | CFDSimulator (id_, name_, stlFile_, cfdModule_, openings_, resistanceModel_) 29 | { 30 | updateScheme = updateScheme_; 31 | } 32 | 33 | template 34 | int CFDSimulator::getId() const { 35 | return id; 36 | } 37 | 38 | template 39 | std::shared_ptr> CFDSimulator::getModule() const { 40 | return cfdModule; 41 | }; 42 | 43 | template 44 | std::shared_ptr> CFDSimulator::getNetwork() const { 45 | return moduleNetwork; 46 | } 47 | 48 | 49 | template 50 | bool CFDSimulator::getInitialized() const { 51 | return initialized; 52 | } 53 | 54 | template 55 | void CFDSimulator::setInitialized(bool initialization_) { 56 | this->initialized = initialization_; 57 | } 58 | 59 | template 60 | void CFDSimulator::setUpdateScheme(const std::shared_ptr>& updateScheme_) { 61 | this->updateScheme = updateScheme_; 62 | } 63 | 64 | template 65 | void CFDSimulator::setVtkFolder(std::string vtkFolder_) { 66 | this->vtkFolder = vtkFolder_; 67 | } 68 | 69 | template 70 | std::string CFDSimulator::getVtkFile() { 71 | return this->vtkFile; 72 | } 73 | 74 | template 75 | T CFDSimulator::getAlpha(int nodeId_) { 76 | return updateScheme->getAlpha(nodeId_); 77 | } 78 | 79 | template 80 | T CFDSimulator::getBeta(int nodeId_) { 81 | return updateScheme->getBeta(nodeId_); 82 | } 83 | 84 | template 85 | void CFDSimulator::setGroundNodes(std::unordered_map groundNodes_){ 86 | this->groundNodes = groundNodes_; 87 | } 88 | 89 | template 90 | std::unordered_map> CFDSimulator::getOpenings() const { 91 | return moduleOpenings; 92 | } 93 | 94 | template 95 | std::unordered_map CFDSimulator::getGroundNodes(){ 96 | return groundNodes; 97 | } 98 | 99 | } // namespace sim -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(abstract) 2 | add_subdirectory(hybrid) 3 | 4 | target_sources(${TARGET_NAME} PRIVATE ${SOURCE_LIST}) 5 | target_link_libraries(${TARGET_NAME} PUBLIC gtest gtest_main) 6 | target_link_libraries(${TARGET_NAME} PUBLIC nlohmann_json::nlohmann_json) 7 | target_link_libraries(${TARGET_NAME} PUBLIC lbmLib) 8 | target_link_libraries(${TARGET_NAME} PUBLIC simLib) 9 | -------------------------------------------------------------------------------- /tests/abstract/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_LIST 2 | Architecture.test.cpp 3 | BigDroplet.test.cpp 4 | Continuous.test.cpp 5 | GradientGenerator.test.cpp 6 | InstantaneousMixing.test.cpp 7 | Tank.test.cpp 8 | Topology.test.cpp 9 | ) 10 | 11 | target_sources(${TARGET_NAME} PRIVATE ${SOURCE_LIST}) 12 | target_link_libraries(${TARGET_NAME} PUBLIC lbmLib) 13 | target_link_libraries(${TARGET_NAME} PUBLIC simLib) 14 | -------------------------------------------------------------------------------- /tests/hybrid/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCE_LIST 2 | Hybrid.test.cpp 3 | Opening.test.cpp 4 | ) 5 | 6 | target_sources(${TARGET_NAME} PRIVATE ${SOURCE_LIST}) 7 | target_link_libraries(${TARGET_NAME} PUBLIC lbmLib) -------------------------------------------------------------------------------- /tests/test.cpp: -------------------------------------------------------------------------------- 1 | #include "baseSimulator.h" 2 | #include "baseSimulator.hh" 3 | 4 | #include "gtest/gtest.h" 5 | 6 | #include "abstract/Architecture.test.cpp" 7 | #include "abstract/BigDroplet.test.cpp" 8 | #include "abstract/Continuous.test.cpp" 9 | #include "abstract/GradientGenerator.test.cpp" 10 | #include "abstract/InstantaneousMixing.test.cpp" 11 | #include "abstract/Tank.test.cpp" 12 | #include "abstract/Topology.test.cpp" 13 | #include "hybrid/Hybrid.test.cpp" 14 | #include "hybrid/Opening.test.cpp" 15 | --------------------------------------------------------------------------------