├── dashboard ├── openbf_dashboard │ ├── __init__.py │ ├── blood.py │ ├── solver.py │ ├── io.py │ └── vessel.py ├── requirements.txt ├── openBF.py └── pages │ ├── 02_results_visualiser.py │ └── 01_Network_Building_Tool.py ├── docs ├── src │ ├── assets │ │ └── logo.png │ ├── man │ │ ├── examples.md │ │ ├── quickstart.md │ │ ├── overview.md │ │ └── config.md │ └── index.md ├── Project.toml └── make.jl ├── test ├── runtests.jl ├── test_network.jl └── network │ ├── network_inlet.dat │ └── network.yaml ├── benchmark ├── README.md └── benchmarks.jl ├── CITATION.bib ├── models ├── boileau2015 │ ├── adan56 │ │ ├── adan56_inlet.dat │ │ ├── plot.py │ │ └── adan56.yaml │ ├── uta │ │ ├── uta.yaml │ │ └── uta_inlet.dat │ ├── cca │ │ ├── cca.yaml │ │ └── cca_inlet.dat │ ├── ibif │ │ ├── ibif.yaml │ │ └── ibif_inlet.dat │ ├── plot_style.txt │ ├── download_reference_data.py │ └── plot.py ├── README.md ├── alastruey2007 │ ├── circle_of_willis_inlet.dat │ └── circle_of_willis.yaml └── matthys2007 │ ├── invitro_model_inlet.dat │ └── invitro_model.yaml ├── .github ├── workflows │ ├── ci.yml │ └── documentation.yml └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── LICENSE ├── .gitignore ├── Project.toml ├── CONTRIBUTING.md ├── src ├── openBF.jl ├── output.jl ├── network.jl ├── conjunctions.jl ├── anastomosis.jl ├── bifurcations.jl ├── boundary_conditions.jl ├── simulation.jl ├── solver.jl └── vessel.jl ├── README.md └── LICENSE-3RD-PARTY /dashboard/openbf_dashboard/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dashboard/requirements.txt: -------------------------------------------------------------------------------- 1 | streamlit_agraph 2 | pyyaml 3 | matplotlib 4 | seaborn 5 | pandas 6 | -------------------------------------------------------------------------------- /docs/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/INSIGNEO/openBF/HEAD/docs/src/assets/logo.png -------------------------------------------------------------------------------- /docs/Project.toml: -------------------------------------------------------------------------------- 1 | [deps] 2 | Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" 3 | 4 | [compat] 5 | Documenter = "1.2" -------------------------------------------------------------------------------- /test/runtests.jl: -------------------------------------------------------------------------------- 1 | using Test 2 | using DelimitedFiles 3 | using Statistics 4 | using openBF 5 | 6 | @testset "openBF.jl" begin 7 | include("test_network.jl") 8 | end 9 | -------------------------------------------------------------------------------- /test/test_network.jl: -------------------------------------------------------------------------------- 1 | println("test network") 2 | test_folder = "network" 3 | cd(test_folder) 4 | 5 | rm("$test_folder" * "_results/", recursive = true, force = true) 6 | 7 | @test_nowarn openBF.run_simulation("$test_folder.yaml", verbose = false, out_files = false) 8 | 9 | rm("$test_folder" * "_results/", recursive = true) 10 | cd("..") 11 | -------------------------------------------------------------------------------- /benchmark/README.md: -------------------------------------------------------------------------------- 1 | # benchmark 2 | 3 | In the REPL 4 | 5 | 6 | ```julia 7 | using PkgBenchmark 8 | using openBF 9 | 10 | bmresults = benchmarkpkg(openBF) 11 | export_markdown("bm_results.md", bmresults) 12 | 13 | jresults = judge(openBF, "v2.2.0") # or any other tag following this release 14 | export_markdown("judge_bm_results.md", jresults) 15 | ``` 16 | -------------------------------------------------------------------------------- /CITATION.bib: -------------------------------------------------------------------------------- 1 | @article{Benemerito_2024, 2 | doi = {10.1088/1361-6579/ad9663}, 3 | url = {https://dx.doi.org/10.1088/1361-6579/ad9663}, 4 | year = {2024}, 5 | month = {dec}, 6 | publisher = {IOP Publishing}, 7 | volume = {45}, 8 | number = {12}, 9 | pages = {125002}, 10 | author = {I Benemerito and A Melis and A Wehenkel and A Marzo}, 11 | title = {openBF: an open-source finite volume 1D blood flow solver}, 12 | journal = {Physiological Measurement} 13 | } 14 | -------------------------------------------------------------------------------- /dashboard/openBF.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | st.title("openBF") 4 | 5 | md_body = """ 6 | 7 | openBF is an open-source 1D blood flow solver based on MUSCL finite-volume numerical scheme. 8 | 9 | [[github]](https://github.com/INSIGNEO/openBF) | [[docs]](https://insigneo.github.io/openBF/stable) 10 | 11 | ![](https://user-images.githubusercontent.com/4661737/97332078-f4101d80-1871-11eb-970d-b7761c069688.png) 12 | 13 | """ 14 | st.markdown(md_body) 15 | -------------------------------------------------------------------------------- /test/network/network_inlet.dat: -------------------------------------------------------------------------------- 1 | 0. 1.e-10 2 | 0.02193 1.e-10 3 | 0.041305 0.000105089 4 | 0.06068 0.00027323 5 | 0.080055 0.000404592 6 | 0.09943 0.000535952 7 | 0.118805 0.000567479 8 | 0.128492 0.000572734 9 | 0.13818 0.000567479 10 | 0.157555 0.000535952 11 | 0.17693 0.000488663 12 | 0.196305 0.000451882 13 | 0.244742 0.000315266 14 | 0.322242 0.000178651 15 | 0.351305 0.000136615 16 | 0.390055 1.e-10 17 | 0.415117 -0.000162888 18 | 0.437555 -2.10178e-55 19 | 0.48693 1.e-10 20 | 0.515992 5.25444e-66 21 | 0.583805 1.e-10 22 | 1 1.e-10 -------------------------------------------------------------------------------- /models/boileau2015/adan56/adan56_inlet.dat: -------------------------------------------------------------------------------- 1 | 0. 1.e-10 2 | 0.02193 1.e-10 3 | 0.041305 0.000105089 4 | 0.06068 0.00027323 5 | 0.080055 0.000404592 6 | 0.09943 0.000535952 7 | 0.118805 0.000567479 8 | 0.128492 0.000572734 9 | 0.13818 0.000567479 10 | 0.157555 0.000535952 11 | 0.17693 0.000488663 12 | 0.196305 0.000451882 13 | 0.244742 0.000315266 14 | 0.322242 0.000178651 15 | 0.351305 0.000136615 16 | 0.390055 1.e-10 17 | 0.415117 -0.000162888 18 | 0.437555 -2.10178e-55 19 | 0.48693 1.e-10 20 | 0.515992 5.25444e-66 21 | 0.583805 1.e-10 22 | 1 1.e-10 -------------------------------------------------------------------------------- /models/boileau2015/uta/uta.yaml: -------------------------------------------------------------------------------- 1 | project_name: uta 2 | inlet_file: "uta_inlet.dat" 3 | write_results: ["P", "Q", "A", "u"] 4 | blood: 5 | rho: 1060.0 6 | mu: 4.0e-3 7 | solver: 8 | Ccfl: 0.9 9 | cycles: 10 10 | jump: 100 11 | convergence_tolerance: 1.0 12 | network: 13 | - label: upper_thoracic_aorta 14 | sn: 1 15 | tn: 2 16 | L: 24.137e-2 17 | E: 400.0e3 18 | R0: 9.87e-3 19 | h0: 0.82e-3 20 | gamma_profile: 9 21 | R1: 1.1752e7 22 | R2: 1.1167e8 23 | Cc: 1.0163e-8 24 | inlet_impedance_matching: false 25 | -------------------------------------------------------------------------------- /models/boileau2015/cca/cca.yaml: -------------------------------------------------------------------------------- 1 | project_name: cca 2 | inlet_file: "cca_inlet.dat" 3 | write_results: ["P", "Q", "A", "u"] 4 | blood: 5 | rho: 1060.0 6 | mu: 4.0e-3 7 | solver: 8 | Ccfl: 0.9 9 | cycles: 10 10 | jump: 100 11 | convergence_tolerance: 1.0 12 | network: 13 | - label: common_carotid_artery 14 | sn: 1 15 | tn: 2 16 | L: 126.0e-3 17 | E: 700.0e3 18 | R0: 2.6485e-3 19 | h0: 0.24e-3 20 | gamma_profile: 2 21 | R1: 2.4875e8 22 | R2: 1.8697e9 23 | Cc: 1.7529e-10 24 | inlet_impedance_matching: false 25 | -------------------------------------------------------------------------------- /docs/make.jl: -------------------------------------------------------------------------------- 1 | push!(LOAD_PATH, "../src/") 2 | using Documenter, openBF 3 | 4 | makedocs( 5 | format = Documenter.HTML(prettyurls = get(ENV, "CI", nothing) == "true"), 6 | sitename = "openBF", 7 | pages = [ 8 | "Home" => "index.md", 9 | "Overview" => "man/overview.md", 10 | "Quickstart" => "man/quickstart.md", 11 | "Configuration" => "man/config.md", 12 | "Examples" => "man/examples.md", 13 | ], 14 | ) 15 | 16 | 17 | # TODO: add link to dashboard 18 | 19 | deploydocs( 20 | repo = "github.com/INSIGNEO/openBF.git", 21 | ) 22 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | test: 7 | runs-on: ${{ matrix.os }} 8 | strategy: 9 | matrix: 10 | julia-version: ['1.10.7', '1.11.2'] 11 | julia-arch: [x64] 12 | os: [ubuntu-latest, windows-latest, macOS-latest] 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - uses: julia-actions/setup-julia@v1 17 | with: 18 | version: ${{ matrix.julia-version }} 19 | arch: ${{ matrix.julia-arch }} 20 | - uses: julia-actions/julia-buildpkg@v1 21 | - uses: julia-actions/julia-runtest@v1 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2023 INSIGNEO Institute for in silico Medicine 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /models/README.md: -------------------------------------------------------------------------------- 1 | ## Models 2 | 3 | - Single arteries: 4 | - [Upper Thoracic Aorta](boileau2015/uta) 5 | - [Common Carotid artery](boileau2015/cca) 6 | - Bifurcation: 7 | - [Iliac bifurcation](boileau2015/ibif) 8 | - Systemic circulation: 9 | - [ADAN56](boileau2015/adan56) 10 | - [In vitro model](matthys2007) 11 | - [Circle of Willis](alastruey2007) 12 | 13 | ## Contribute 14 | 15 | You are welcome to submit your own models developed with openBF. This can be done through a pull request for the `models/` directory. Your submission should consist of a folder containing openBF configurations files and a readme describing the network with relevant references. -------------------------------------------------------------------------------- /benchmark/benchmarks.jl: -------------------------------------------------------------------------------- 1 | using openBF 2 | using BenchmarkTools 3 | 4 | function bmodel(modelname) 5 | cwd = pwd() 6 | println(cwd) 7 | cd(joinpath("models", "boileau2015", modelname)) 8 | openBF.run_simulation("$modelname.yaml") 9 | cd(cwd) 10 | end 11 | 12 | const SUITE = BenchmarkGroup() 13 | 14 | SUITE["single_vessel"] = BenchmarkGroup() 15 | SUITE["single_vessel"]["cca"] = @benchmarkable bmodel("cca") 16 | SUITE["single_vessel"]["uta"] = @benchmarkable bmodel("uta") 17 | 18 | SUITE["bifurcation"] = BenchmarkGroup() 19 | SUITE["bifurcation"]["ibif"] = @benchmarkable bmodel("ibif") 20 | 21 | SUITE["circulation"] = BenchmarkGroup() 22 | SUITE["circulation"]["adan56"] = @benchmarkable bmodel("adan56") -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[IDEA]" 5 | labels: new feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/documentation.yml: -------------------------------------------------------------------------------- 1 | name: Documentation 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | tags: '*' 8 | 9 | jobs: 10 | build: 11 | permissions: 12 | contents: write 13 | statuses: write 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: julia-actions/setup-julia@v1 18 | with: 19 | version: '1.11.2' 20 | - name: Install dependencies 21 | run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()' 22 | - name: Build and deploy 23 | env: 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | run: julia --project=docs/ docs/make.jl 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/*_results 2 | **/.DS_Store 3 | docs/build 4 | Manifest.toml 5 | README.html 6 | *.ipynb 7 | *.dat 8 | *.yml 9 | *.yaml 10 | *.conv 11 | **/*.swp 12 | **/*.pyc 13 | tmp_sim 14 | plot* 15 | !models/**/*.yaml 16 | !models/**/*.dat 17 | models/charlton2019/**/* 18 | adan56/* 19 | baselines/* 20 | cha/* 21 | wang2015/* 22 | invitro*/* 23 | scale_study/* 24 | **/__pycache__ 25 | 26 | # validation 27 | validation/* 28 | 29 | # models 30 | models/Boileau2015/*/*_ref 31 | models/Boileau2015/*/*_results 32 | models/**/*.eps 33 | models/**/*.png 34 | !models/Boileau2015/plot.py 35 | !models/Boileau2015/plot_style.txt 36 | !models/Boileau2015/adan56/plot.py 37 | 38 | # benchmark 39 | benchmark/tune.json 40 | bm_results.md 41 | judge_bm_results.md 42 | -------------------------------------------------------------------------------- /dashboard/openbf_dashboard/blood.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | 4 | def get_blood_props(): 5 | c3, c4 = st.columns([1, 1]) 6 | y = {} 7 | with c3: 8 | y["rho"] = st.number_input( 9 | "$\\rho$ $(kg \cdot m^{-3})$", 10 | help="density", 11 | value=1060.0, 12 | step=10.0, 13 | min_value=1030.0, 14 | max_value=1090.0, 15 | ) 16 | 17 | with c4: 18 | y["mu"] = st.number_input( 19 | "$\\mu$ $(Pa \cdot s)$", 20 | help="dynamic viscosity", 21 | value=0.004, 22 | step=0.001, 23 | min_value=0.001, 24 | max_value=0.009, 25 | format="%e", 26 | ) 27 | return y 28 | -------------------------------------------------------------------------------- /Project.toml: -------------------------------------------------------------------------------- 1 | name = "openBF" 2 | uuid = "e815b1a4-10eb-11ea-25f1-272ff651e618" 3 | authors = ["alessandro "] 4 | version = "2.7.1" 5 | 6 | [deps] 7 | DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" 8 | Glob = "c27321d9-0574-5035-807b-f59d2c89b15c" 9 | Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" 10 | LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" 11 | PkgBenchmark = "32113eaa-f34f-5b0d-bd6c-c81e245fc73d" 12 | Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" 13 | ProgressMeter = "92933f4c-e287-5a05-a399-4b506db050ca" 14 | StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" 15 | Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" 16 | Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" 17 | YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6" 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Version [e.g. 22] 29 | 30 | **Additional context** 31 | Add any other context about the problem here. 32 | -------------------------------------------------------------------------------- /models/boileau2015/ibif/ibif.yaml: -------------------------------------------------------------------------------- 1 | project_name: ibif 2 | inlet_file: "ibif_inlet.dat" 3 | write_results: ["P", "Q", "A", "u"] 4 | blood: 5 | rho: 1060.0 6 | mu: 4.0e-3 7 | solver: 8 | Ccfl: 0.9 9 | cycles: 10 10 | jump: 100 11 | convergence_tolerance: 1.0 12 | network: 13 | - label: parent 14 | sn: 1 15 | tn: 2 16 | L: 8.6e-2 17 | E: 500.0e3 18 | R0: 0.7581e-2 19 | h0: 0.9e-3 20 | gamma_profile: 9 21 | - label: d1 22 | sn: 2 23 | tn: 3 24 | L: 8.5e-2 25 | E: 700.0e3 26 | R0: 0.5492e-2 27 | h0: 0.68e-3 28 | gamma_profile: 9 29 | R1: 6.8123e7 30 | R2: 3.1013e9 31 | Cc: 3.6664e-10 32 | inlet_impedance_matching: false 33 | - label: d2 34 | sn: 2 35 | tn: 4 36 | L: 8.5e-2 37 | E: 700.0e3 38 | R0: 0.5492e-2 39 | h0: 0.68e-3 40 | gamma_profile: 9 41 | R1: 6.8123e7 42 | R2: 3.1013e9 43 | Cc: 3.6664e-10 44 | inlet_impedance_matching: false -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to openBF 2 | 3 | Following there is a set of guidelins for contributing to openBF development. Feel free to propose changes to this document via a pull request. 4 | 5 | ## How can I contribute? 6 | 7 | ### Reporting bugs 8 | - Check the [open issues](https://github.com/INSIGNEO/openBF/issues) to avoid duplicates 9 | - Ensure you are using the latest Julia version compatible with openBF 10 | - Open a bug report (see [here](https://github.com/atom/atom/blob/master/CONTRIBUTING.md#how-do-i-submit-a-good-bug-report) for a _good_ bug report template) OR try to fix it and make a pull request 11 | 12 | ### Suggest Enhancements 13 | Currently, openBF is in active development and new features will be added in the future. Feel free to suggest more enhancements through the issues tracker. 14 | 15 | ### New vascular networks 16 | We collect vascular networks in the [models](models) folder. If you have used openBF to analyse a new network, please make a pull request so that we can keep expanding our model repository. 17 | -------------------------------------------------------------------------------- /models/boileau2015/plot_style.txt: -------------------------------------------------------------------------------- 1 | xtick.color: 323034 2 | ytick.color: 323034 3 | text.color: 323034 4 | lines.markeredgecolor: black 5 | patch.facecolor : bc80bd 6 | patch.force_edgecolor : True 7 | patch.linewidth: 0.8 8 | scatter.edgecolors: black 9 | grid.color: b1afb5 10 | axes.titlesize: 16 11 | legend.title_fontsize: 12 12 | xtick.labelsize: 12 13 | ytick.labelsize: 12 14 | axes.labelsize: 12 15 | font.size: 10 16 | axes.prop_cycle : (cycler('color', ['bc80bd' ,'fb8072', 'b3de69','fdb462','fccde5','8dd3c7','ffed6f','bebada','80b1d3', 'ccebc5', 'd9d9d9'])) 17 | mathtext.fontset: stix 18 | font.family: STIXGeneral 19 | lines.linewidth: 2 20 | legend.frameon: False 21 | legend.fontsize: 14 22 | legend.columnspacing: 1.5 23 | legend.labelspacing: 0.4 24 | text.usetex: False 25 | axes.titlelocation: left 26 | axes.formatter.use_mathtext: True 27 | axes.autolimit_mode: round_numbers 28 | axes.labelpad: 3 29 | axes.formatter.limits: -4, 4 30 | axes.labelcolor: black 31 | axes.edgecolor: black 32 | axes.linewidth: 0.6 33 | axes.spines.right : False 34 | axes.spines.top : False 35 | axes.grid: False 36 | figure.titlesize: 18 37 | figure.dpi: 100 -------------------------------------------------------------------------------- /dashboard/openbf_dashboard/solver.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | 4 | def get_solver_props(): 5 | y = {} 6 | c1, c2 = st.columns([1, 1]) 7 | with c1: 8 | y["Ccfl"] = st.number_input( 9 | "CFL", 10 | value=0.9, 11 | min_value=0.01, 12 | max_value=1.0, 13 | step=0.1, 14 | help="Courant's number", 15 | ) 16 | y["cycles"] = st.number_input( 17 | "cycles", 18 | value=100, 19 | min_value=1, 20 | step=10, 21 | help="simulation length in cardiac cycles", 22 | ) 23 | with c2: 24 | y["jump"] = st.number_input( 25 | "jumps", 26 | value=100, 27 | min_value=10, 28 | step=10, 29 | help="number of time steps in the output files", 30 | ) 31 | y["convergence tolerance"] = st.number_input( 32 | "convergence tolerance $(mmHg)$", 33 | value=1.0, 34 | min_value=0.1, 35 | max_value=100.0, 36 | help="stop simulation when error < tolerance", 37 | ) 38 | 39 | return y 40 | -------------------------------------------------------------------------------- /docs/src/man/examples.md: -------------------------------------------------------------------------------- 1 | The repository [models](https://github.com/insigneo/openbf/models) folder contains configuration and inlet files for: 2 | 3 | - In-vitro model from _Matthys KS, Alastruey J, Peiró J, Khir AW, Segers P, Verdonck PR, Parker KH, Sherwin SJ. [Pulse wave propagation in a model human arterial network: assessment of 1-D numerical simulations against in vitro measurements](https://www.sciencedirect.com/science/article/pii/S0021929011004386). Journal of biomechanics. 2007 Dec 31;40(15):3476-86._ 4 | 5 | - Circle of Willis model from _Alastruey J, Parker KH, Peiró J, Byrd SM, Sherwin SJ. [Modelling the circle of Willis to assess the effects of anatomical variations and occlusions on cerebral flows](http://www.sciencedirect.com/science/article/pii/S0021929006002946). Journal of biomechanics. 2007 Dec 31;40(8):1794-805_ 6 | 7 | - Benchmark models from _Boileau E, Nithiarasu P, Blanco PJ, Müller LO, Fossan FE, Hellevik LR, Donders WP, Huberts W, Willemet M, Alastruey J. [A benchmark study of numerical schemes for one‐dimensional arterial blood flow modelling](https://onlinelibrary.wiley.com/doi/abs/10.1002/cnm.2732). International journal for numerical methods in biomedical engineering. 2015 Oct 1;31(10)._ 8 | -------------------------------------------------------------------------------- /src/openBF.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Copyright 2015-2024 INSIGNEO Institute for in silico Medicine 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | =# 16 | 17 | __precompile__(true) 18 | module openBF 19 | 20 | using Printf 21 | using LinearAlgebra 22 | using DelimitedFiles 23 | using StaticArrays 24 | using YAML 25 | using Glob 26 | using Graphs 27 | using ProgressMeter 28 | using Statistics 29 | 30 | export run_simulation 31 | 32 | include("vessel.jl") 33 | include("network.jl") 34 | include("solver.jl") 35 | include("simulation.jl") 36 | include("boundary_conditions.jl") 37 | include("conjunctions.jl") 38 | include("bifurcations.jl") 39 | include("output.jl") 40 | include("anastomosis.jl") 41 | end 42 | -------------------------------------------------------------------------------- /dashboard/openbf_dashboard/io.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | def parse_project_name(s: str) -> str: 4 | if s: 5 | return s.replace(" ", "_").lower() 6 | else: 7 | raise ValueError("project_name must be defined") 8 | 9 | def get_io(): 10 | i = {} 11 | i["project_name"] = parse_project_name( 12 | st.text_input( 13 | "project_name", 14 | value="my_simulation", 15 | ) 16 | ) 17 | 18 | i["inlet_file"] = st.text_input( 19 | "inlet_file", 20 | help="path to project_name_inlet.dat file", 21 | value="inlet.dat", 22 | key=f"inlet_file", 23 | ) 24 | 25 | i["output_directory"] = st.text_input( 26 | "output_directory", 27 | help="where to save the output files", 28 | value=f"{i['project_name']}_results", 29 | key=f"output_directory", 30 | ) 31 | 32 | i["write_results"] = [] 33 | st.text("write_results") 34 | check_cols = st.columns(4) 35 | for j, q in enumerate(["P", "Q", "A", "u"]): 36 | with check_cols[j]: 37 | if st.checkbox(q, key=f"save_{q}", value=q in ["P", "Q"]): 38 | i["write_results"].append(q) 39 | 40 | return i 41 | -------------------------------------------------------------------------------- /dashboard/pages/02_results_visualiser.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import pandas as pd 3 | import matplotlib.pyplot as plt 4 | import seaborn as sns 5 | from pathlib import Path 6 | 7 | 8 | def strip_filename(filename): 9 | p = Path(filename) 10 | vessel, q = p.stem.rsplit("_", 1) 11 | return vessel, q 12 | 13 | 14 | MULTIPLIERS = {"P": 1 / 133.332, "Q": 1e6, "A": 1, "u": 1,} 15 | UNITS = { 16 | "P": "$(mmHg)$", 17 | "Q": "$(ml \cdot s^{-1})$", 18 | "A": "$(m^2)$", 19 | "u": "$(m \cdot s^{-1})$", 20 | } 21 | 22 | uploaded_file = st.file_uploader("Pick a file") 23 | if uploaded_file: 24 | vessel, q = strip_filename(uploaded_file.name) 25 | df = pd.read_csv(uploaded_file, sep=" ", header=None) 26 | 27 | col_names = ["time", "inlet", "2/5", "middle", "4/5", "outlet"] 28 | cols = dict(zip(range(7), col_names)) 29 | df = df.rename(columns=cols) 30 | 31 | for c in col_names[1:]: 32 | df[c] = df[c].apply(lambda x: MULTIPLIERS[q] * x) 33 | 34 | c1, c2, c3 = st.columns([1, 1, 1]) 35 | with c1: 36 | inlet = st.checkbox("inlet") 37 | with c2: 38 | middle = st.checkbox("middle") 39 | with c3: 40 | outlet = st.checkbox("outlet") 41 | fig = plt.figure() 42 | ax = fig.add_subplot(111) 43 | 44 | if inlet: 45 | sns.lineplot(data=df, x="time", y="inlet", ax=ax) 46 | if middle: 47 | sns.lineplot(data=df, x="time", y="middle", ax=ax) 48 | if outlet: 49 | sns.lineplot(data=df, x="time", y="outlet", ax=ax) 50 | 51 | plt.ylabel(f"{q} {UNITS[q]}") 52 | plt.title(vessel) 53 | plt.xlabel("time $(s)$") 54 | 55 | sns.despine() 56 | st.pyplot(fig) 57 | -------------------------------------------------------------------------------- /test/network/network.yaml: -------------------------------------------------------------------------------- 1 | project_name: "network" 2 | write_results: ["P", "Q", "A", "u", "c"] 3 | blood: 4 | rho: 1060.0 5 | mu: 0.004 6 | solver: 7 | Ccfl: 0.9 8 | cycles: 2 9 | jump: 10 10 | convergence_tolerance: 1.0 11 | network: 12 | - label: v0 13 | sn: 1 14 | tn: 2 15 | L: 0.01 16 | M: 10 17 | Rp: 0.82e-2 18 | Rd: 0.758242250e-2 19 | E: 125000.0 20 | gamma profile: 9 21 | - label: v1 22 | sn: 2 23 | tn: 3 24 | L: 0.01 25 | R0: 0.5492e-2 26 | E: 125000.0 27 | - label: v2 28 | sn: 2 29 | tn: 4 30 | L: 0.01 31 | M: 10 32 | R0: 0.5492e-2 33 | E: 125000.0 34 | - label: v3 35 | sn: 4 36 | tn: 5 37 | L: 0.01 38 | M: 10 39 | R0: 0.5492e-2 40 | E: 125000.0 41 | - label: v4 42 | sn: 3 43 | tn: 5 44 | L: 0.01 45 | M: 10 46 | R0: 0.5492e-2 47 | E: 125000.0 48 | - label: v5 49 | sn: 5 50 | tn: 6 51 | L: 0.01 52 | M: 10 53 | R0: 0.758242250e-2 54 | E: 125000.0 55 | - label: v6 56 | sn: 6 57 | tn: 7 58 | L: 0.01 59 | M: 10 60 | R0: 0.5492e-2 61 | E: 125000.0 62 | Rt: 0.0 63 | - label: v7 64 | sn: 6 65 | tn: 8 66 | L: 0.01 67 | M: 10 68 | R0: 0.5492e-2 69 | E: 125000.0 70 | - label: v8 71 | sn: 8 72 | tn: 9 73 | L: 0.01 74 | M: 10 75 | R0: 0.0043590032887046775 76 | E: 125000.0 77 | Rt: 0.0 78 | - label: v9 79 | sn: 8 80 | tn: 10 81 | L: 0.01 82 | R0: 0.0043590032887046775 83 | E: 125000.0 84 | - label: v10 85 | sn: 10 86 | tn: 11 87 | L: 0.01 88 | R0: 0.0043590032887046775 89 | E: 125000.0 90 | Rt: 0.2 91 | -------------------------------------------------------------------------------- /src/output.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Copyright 2015-2024 INSIGNEO Institute for in silico Medicine 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | =# 16 | 17 | function save_waveforms(idx::Int64, t::Float64, v::Vessel) 18 | for k in keys(v.waveforms) 19 | if k == "A" 20 | v.waveforms[k][idx, :] = [t, v.A[1], v.A[v.node2], v.A[v.node3], v.A[v.node4], v.A[end]] 21 | elseif k == "Q" 22 | v.waveforms[k][idx, :] = [t, v.Q[1], v.Q[v.node2], v.Q[v.node3], v.Q[v.node4], v.Q[end]] 23 | elseif k == "u" 24 | v.waveforms[k][idx, :] = [t, v.u[1], v.u[v.node2], v.u[v.node3], v.u[v.node4], v.u[end]] 25 | elseif k == "P" 26 | # TODO 27 | # this ---------------------------v should be a call to compute_pressure instead and handle time 28 | v.waveforms[k][idx, :] = [t, [pressure(v.A[i], v.A0[i], v.beta[i], v.Pext) - v.Pout for i=(1, v.node2, v.node3, v.node4, v.M)]...] 29 | end 30 | end 31 | end 32 | 33 | 34 | function flush_waveforms(v::Vessel) 35 | for k in keys(v.waveforms) 36 | open("$(v.label)_$k.last", "w") do io 37 | writedlm(io, v.waveforms[k], " ") 38 | end 39 | end 40 | end 41 | 42 | 43 | function append_last_to_out(v::Vessel) 44 | for k in keys(v.waveforms) 45 | open("$(v.label)_$k.out", "a") do io 46 | last = readdlm(v.label * "_$k.last") 47 | writedlm(io, last, " ") 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /src/network.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Copyright 2015-2024 INSIGNEO Institute for in silico Medicine 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | =# 16 | 17 | struct Heart 18 | cardiac_period::Float64 19 | input_data::Array{Float64,2} 20 | end 21 | 22 | load_input_data(project_name::String) = readdlm(project_name * "_inlet.dat") 23 | function Heart(inlet_file::String) 24 | input_data = readdlm(inlet_file) 25 | cardiac_period = input_data[end, 1] 26 | Heart(cardiac_period, input_data) 27 | end 28 | 29 | struct Network 30 | graph::SimpleDiGraph{Int64} 31 | edges::Vector{Graphs.SimpleGraphs.SimpleEdge{Int64}} 32 | vessels::Dict{Tuple{Int,Int},Vessel} 33 | blood::Blood 34 | heart::Heart 35 | Ccfl::Float64 36 | end 37 | number_of_nodes(config::Vector{Dict{Any,Any}}) = maximum(c["tn"] for c in config) 38 | function Network( 39 | config::Vector{Dict{Any,Any}}, 40 | blood::Blood, 41 | heart::Heart, 42 | Ccfl::Float64, 43 | jump::Int64, 44 | tokeep::Vector{String}; 45 | verbose = true, 46 | ) 47 | prog = verbose ? Progress(length(config); desc = "Building network:") : nothing 48 | 49 | graph = SimpleDiGraph(number_of_nodes(config)) 50 | 51 | vessels = Dict() 52 | for vessel_config in config 53 | vessel = Vessel(vessel_config, blood, jump, tokeep) 54 | Graphs.add_edge!(graph, vessel.sn, vessel.tn) 55 | vessels[(vessel.sn, vessel.tn)] = vessel 56 | verbose && next!(prog) 57 | end 58 | check(graph) 59 | Network(graph, collect(Graphs.edges(graph)), vessels, blood, heart, Ccfl) 60 | end 61 | 62 | function check(g::SimpleDiGraph) 63 | δin(g) != 0 && error("no input vessel") 64 | δout(g) != 0 && error("no output vessel(s)") 65 | has_self_loops(g) && error("self loop detected, i.e. sn == tn") 66 | Δin(g) > 2 || Δout(g) > 2 && error("vertex belonging to more than 3 vessels") 67 | end 68 | -------------------------------------------------------------------------------- /models/boileau2015/download_reference_data.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import tempfile 3 | import time 4 | import zipfile 5 | from pathlib import Path 6 | 7 | import requests 8 | 9 | SIMULATIONS = ["cca", "uta", "ibif", "adan56"] 10 | 11 | 12 | def make_folder_structure(): 13 | for simulation in SIMULATIONS: 14 | if not (p := Path(simulation, f"{simulation}_ref")).exists(): 15 | p.mkdir() 16 | 17 | 18 | def download_boileau2015_data(dst_folder): 19 | retry = 5 20 | while retry > 1: 21 | print("Downloading Boileau2015 supplementary material") 22 | headers = { 23 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3" 24 | } 25 | response = requests.get( 26 | "https://onlinelibrary.wiley.com/action/downloadSupplement?doi=10.1002%2Fcnm.2732&file=cnm2732-sup-0001-Supplementary.zip", 27 | headers=headers, 28 | ) 29 | 30 | if response.status_code == 200: 31 | with tempfile.TemporaryDirectory() as temp_dir: 32 | zip_path = Path(temp_dir, "nm2732-sup-0001-Supplementary.zip") 33 | with zip_path.open("wb") as z: 34 | z.write(response.content) 35 | 36 | print("Extracting files") 37 | with zipfile.ZipFile(zip_path, "r") as z: 38 | z.extractall(temp_dir) 39 | 40 | print("Copying files") 41 | root_path = Path(temp_dir, "SuppMaterial_1DBenchmark_Boileau_etal") 42 | for sim, folder in zip( 43 | SIMULATIONS, 44 | [ 45 | "Benchmark2_CommonCarotidArtery", 46 | "Benchmark3_UpperThoracicAorta", 47 | "Benchmark4_AorticBifurcation", 48 | ], 49 | ): 50 | print(sim) 51 | tmp_data = Path(root_path, folder, "NumData") 52 | dst_path = Path(dst_folder, sim, f"{sim}_ref") 53 | 54 | if len(list(dst_path.glob("*"))) == 0: 55 | tmp_data.rename(dst_path) 56 | sys.exit() 57 | 58 | else: 59 | print("Failed to retrieve Boileau2015 data, retrying...") 60 | retry -= 1 61 | time.sleep(5) 62 | 63 | print("Failed downloading data after 5 retries") 64 | 65 | 66 | if __name__ == "__main__": 67 | make_folder_structure() 68 | download_boileau2015_data(Path.cwd()) 69 | -------------------------------------------------------------------------------- /dashboard/pages/01_Network_Building_Tool.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import yaml 3 | from streamlit_agraph import agraph, Node, Edge, Config 4 | from openbf_dashboard.blood import get_blood_props 5 | from openbf_dashboard.solver import get_solver_props 6 | from openbf_dashboard.vessel import get_vessel 7 | from openbf_dashboard.io import get_io 8 | 9 | 10 | st.set_page_config( 11 | page_title="network_builder", 12 | layout="wide", 13 | ) 14 | 15 | c1, c2 = st.columns([1, 1]) 16 | 17 | with c1: 18 | y = {} 19 | 20 | with st.expander("Input/Output"): 21 | y |= get_io() 22 | 23 | with st.expander("Blood"): 24 | y["blood"] = get_blood_props() 25 | 26 | with st.expander("Solver"): 27 | y["solver"] = get_solver_props() 28 | 29 | 30 | 31 | st.divider() 32 | y["network"] = [] 33 | vessels = st.number_input( 34 | "number of vessels", 35 | min_value=1, 36 | step=1, 37 | ) 38 | for i in range(vessels): 39 | v = get_vessel(i) 40 | if v: 41 | y["network"].append(v) 42 | 43 | 44 | with c2: 45 | st.download_button( 46 | "Download .yaml", 47 | data=yaml.dump( 48 | y, 49 | sort_keys=False, 50 | default_flow_style=False, 51 | ), 52 | file_name=f"{y['project_name']}.yaml", 53 | ) 54 | 55 | with st.expander("Graph"): 56 | nodes = [] 57 | edges = [] 58 | seen_nodes = [] 59 | for v in y["network"]: 60 | if v["sn"] not in seen_nodes: 61 | nodes.append( 62 | Node( 63 | id=v["sn"], 64 | label=str(v["sn"]), 65 | size=10 if "inlet" in v else 5, 66 | ) 67 | ) 68 | seen_nodes.append(v["sn"]) 69 | 70 | if v["tn"] not in seen_nodes: 71 | nodes.append( 72 | Node( 73 | id=v["tn"], 74 | label=str(v["tn"]), 75 | size=1 if "outlet" in v else 5, 76 | ) 77 | ) 78 | seen_nodes.append(v["tn"]) 79 | 80 | edges.append(Edge(source=v["sn"], label=v["label"], target=v["tn"])) 81 | 82 | config = Config( 83 | width=750, 84 | height=950, 85 | directed=True, 86 | hierarchical=False, 87 | physics=True, 88 | ) 89 | 90 | agraph(nodes=nodes, edges=edges, config=config) 91 | 92 | with c1: 93 | st.divider() 94 | 95 | if y: 96 | st.json(y) 97 | -------------------------------------------------------------------------------- /docs/src/man/quickstart.md: -------------------------------------------------------------------------------- 1 | ## Installation 2 | 3 | The latest Julia binary can be downloaded for all platforms from the official [website](https://julialang.org/downloads/). 4 | 5 | openBF can be installed via Julia REPL. Start `julia` in a terminal session and run 6 | 7 | ```julia 8 | julia> ] 9 | 10 | (@v1.11) pkg> add https://github.com/INSIGNEO/openBF.git 11 | ``` 12 | 13 | ## Run a simulation 14 | 15 | openBF API consists of a single function 16 | 17 | ```julia 18 | run_simulation( 19 | yaml_config_path::String; 20 | verbose::Bool = false, # show progress bars 21 | out_files::Bool = false, # save .out files with the all the cycles 22 | save_stats::Bool = false, # save .conv file with simulation stats 23 | ) 24 | ``` 25 | 26 | whose main argument is the name of a `.yaml` file (see [here](https://learnxinyminutes.com/docs/yaml/) for an introduction to yaml) containining the description of the vascular network, blood properties, and numerical solver parameters (see [Configuration](config.md)). 27 | 28 | Running a simulation consists in calling 29 | 30 | ```julia 31 | using openBF 32 | run_simulation("input.yml", verbose=true, save_stats=true) 33 | ``` 34 | 35 | This will create a `_results` folder containing all the output files from the simulation. 36 | 37 | ## Outputs 38 | 39 | Simulation results are saved in the `_results` directory or in the `output_directory` specified. There, for each artery in your network, you'll find a file per output quantity (these are specified in the `write_results` list). 40 | 41 | By default only `.last` files are saved. Thes contains only the _last_ simulated cardiac cycle; at convergence, these are the files you want to look at. 42 | 43 | You can also set `out_files = true` when calling `run_simulation`. This results in the writing of `.out` files which contain the _whole_ simulation history, i.e., all the cardiac cycles simulated. 44 | 45 | When setting `save_stats=true`, a `.conv` file is written in the results dolder. This reads 46 | 47 | ``` 48 | # boolean: true or false 49 | # integer 50 | # float, seconds 51 | # integer, bytes 52 | # float, percentage 53 | ``` 54 | 55 | ### `.last`/`.out` Format 56 | 57 | These files contain as many rows as defined in the config by the `jump` parameter (default `100`), and 6 columns. The first column contains the simulation time for the current cardiac cycles; column 2-6 report waveforms at five locations along the vessel, namely _inlet_, _1/4th_ of the length, _mid-point_, _3/4th_ of the length and _outlet_. 58 | -------------------------------------------------------------------------------- /src/conjunctions.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Copyright 2015-2024 INSIGNEO Institute for in silico Medicine 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | =# 16 | 17 | getUconj(v1::Vessel, v2::Vessel) = SVector{4,Float64}(v1.u[end], v2.u[1], 18 | sqrt(sqrt(v1.A[end])), sqrt(sqrt(v2.A[1]))) 19 | 20 | getFconj(v1::Vessel, v2::Vessel, U, k, W, ρ) = SVector{4,Float64}(U[1] + 4k[1] * U[3] - W[1], 21 | U[2] - 4k[2] * U[4] - W[2], 22 | U[1] * (U[3] * U[3] * U[3] * U[3]) - U[2] * (U[4] * U[4] * U[4] * U[4]), 23 | 0.5 * ρ * U[1] * U[1] + v1.beta[end] * (U[3] * U[3] / sqrt(v1.A0[end]) - 1) - 24 | (0.5 * ρ * U[2] * U[2] + v2.beta[1] * (U[4] * U[4] / sqrt(v2.A0[1]) - 1))) 25 | 26 | function getJconj(v1::Vessel, v2::Vessel, U, k, ρ) 27 | J::Array{Float64, 2} = zeros(Float64, 4, 4) 28 | 29 | J[1, 1] = 1.0 30 | J[2, 2] = 1.0 31 | 32 | J[1, 3] = 4k[1] 33 | J[2, 4] = -4k[2] 34 | 35 | J[3, 1] = U[3] * U[3] * U[3] * U[3] 36 | J[3, 2] = -U[4] * U[4] * U[4] * U[4] 37 | J[3, 3] = 4U[1] * U[3] * U[3] * U[3] 38 | J[3, 4] = -4U[2] * U[4] * U[4] * U[4] 39 | 40 | J[4, 3] = 2v1.beta[end] * U[3] / sqrt(v1.A0[end]) 41 | J[4, 4] = -2v2.beta[1] * U[4] / sqrt(v2.A0[1]) 42 | 43 | J[4, 1] = ρ * U[1] 44 | J[4, 2] = -ρ * U[2] 45 | 46 | SMatrix{4, 4, Float64, 16}(J) 47 | end 48 | 49 | function NRconj(U, W, J, F, k, v1::Vessel, v2::Vessel, ρ) 50 | while norm(F)>1e-5 51 | U += J \ (-F) 52 | F = getFconj(v1, v2, U, k, W, ρ) 53 | J = getJconj(v1, v2, U, k, ρ) 54 | end 55 | U 56 | end 57 | 58 | function updateConj!(v1::Vessel, v2::Vessel, U) 59 | v1.u[end] = U[1] 60 | v2.u[1] = U[2] 61 | 62 | v1.A[end] = U[3] * U[3] * U[3] * U[3] 63 | v1.Q[end] = v1.u[end] * v1.A[end] 64 | 65 | v2.A[1] = U[4] * U[4] * U[4] * U[4] 66 | v2.Q[1] = v2.u[1] * v2.A[1] 67 | end 68 | 69 | function join_vessels!(v1::Vessel, v2::Vessel, ρ::Float64) 70 | k = (sqrt(1.5*v1.gamma[end]), sqrt(1.5*v2.gamma[1])) 71 | U = getUconj(v1, v2) 72 | W = (U[1] + 4k[1] * U[3], U[2] - 4k[2] * U[4]) 73 | F = getFconj(v1, v2, U, k, W, ρ) 74 | J = getJconj(v1, v2, U, k, ρ) 75 | 76 | # solve 77 | U = NRconj(U, W, J, F, k, v1, v2, ρ) 78 | 79 | updateConj!(v1, v2, U) 80 | end 81 | -------------------------------------------------------------------------------- /src/anastomosis.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Copyright 2015-2024 INSIGNEO Institute for in silico Medicine 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | =# 16 | 17 | getUan(v1::Vessel, v2::Vessel, v3::Vessel) = SVector{6, Float64}( 18 | v1.u[end], 19 | v2.u[end], 20 | v3.u[1], 21 | sqrt(sqrt(v1.A[end])), 22 | sqrt(sqrt(v2.A[end])), 23 | sqrt(sqrt(v3.A[1])), 24 | ) 25 | 26 | function solveAnastomosis(v1::Vessel, v2::Vessel, v3::Vessel) 27 | k = (sqrt(1.5*v1.gamma[end]), sqrt(1.5*v2.gamma[end]), sqrt(1.5*v3.gamma[1])) 28 | U = getUan(v1, v2, v3) 29 | W = (U[1] + 4k[1]* U[4], U[2] + 4k[2] * U[5], U[3] - 4k[3] * U[6]) 30 | J = getJan(v1, v2, v3, U, k) 31 | F = getFan(v1, v2, v3, U, k, W) 32 | 33 | U = NRan(U, W, J, F, k, v1, v2, v3) 34 | 35 | #Update vessel quantities 36 | v1.u[end] = U[1] 37 | v2.u[end] = U[2] 38 | v3.u[1] = U[3] 39 | 40 | v1.A[end] = U[4] * U[4] * U[4] * U[4] 41 | v2.A[end] = U[5] * U[5] * U[5] * U[5] 42 | v3.A[1] = U[6] * U[6] * U[6] * U[6] 43 | 44 | v1.Q[end] = v1.u[end] * v1.A[end] 45 | v2.Q[end] = v2.u[end] * v2.A[end] 46 | v3.Q[1] = v3.u[1] * v3.A[1] 47 | end 48 | 49 | 50 | function getFan(v1::Vessel, v2::Vessel, v3::Vessel, U, k, W) 51 | SVector{6, Float64}(U[1] + 4k[1] * U[4] - W[1], 52 | U[2] + 4k[2] * U[5] - W[2], 53 | U[3] - 4k[3] * U[6] - W[3], 54 | U[1] * (U[4] * U[4] * U[4] * U[4]) + U[2] * (U[5] * U[5] * U[5] * U[5]) - U[3] * (U[6] * U[6] * U[6] * U[6]), 55 | v1.beta[end] * (U[4]^2 / sqrt(v1.A0[end]) - 1) - (v3.beta[1] * ((U[6])^2 / sqrt(v3.A0[1]) - 1)), 56 | v2.beta[end] * (U[5]^2 / sqrt(v2.A0[end]) - 1) - (v3.beta[1] * ((U[6]^2) / sqrt(v3.A0[1]) - 1))) 57 | end 58 | 59 | function getJan(v1::Vessel, v2::Vessel, v3::Vessel, U, k) 60 | J::Array{Float64, 2} = zeros(Float64, 6, 6) 61 | 62 | J[1, 1] = 1.0 63 | J[2, 2] = 1.0 64 | J[3, 3] = 1.0 65 | 66 | J[1, 4] = 4k[1] 67 | J[2, 5] = 4k[2] 68 | J[3, 6] = -4k[3] 69 | 70 | J[4, 1] = U[4] * U[4] * U[4] * U[4] 71 | J[4, 2] = U[5] * U[5] * U[5] * U[5] 72 | J[4, 3] = -U[6] * U[6] * U[6] * U[6] 73 | J[4, 4] = 4U[1] * (U[4] * U[4] * U[4]) 74 | J[4, 5] = 4U[2] * (U[5] * U[5] * U[5]) 75 | J[4, 6] = -4U[3] * (U[6] * U[6] * U[6]) 76 | 77 | J[5, 4] = 2v1.beta[end] * U[4] / sqrt(v1.A0[end]) 78 | J[5, 6] = -2v3.beta[1] * U[6] / sqrt(v3.A0[1]) 79 | 80 | J[6, 5] = 2v2.beta[end] * U[5] / sqrt(v2.A0[end]) 81 | J[6, 6] = -2v3.beta[1] * U[6] / sqrt(v3.A0[1]) 82 | 83 | SMatrix{6, 6, Float64, 36}(J) 84 | end 85 | 86 | function NRan(U, W, J, F, k, v1, v2, v3) 87 | while norm(F)>1e-5 88 | U += J \ (-F) 89 | F = getFan(v1, v2, v3, U, k, W) 90 | J = getJan(v1, v2, v3, U, k) 91 | end 92 | U 93 | end 94 | -------------------------------------------------------------------------------- /src/bifurcations.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Copyright 2015-2024 INSIGNEO Institute for in silico Medicine 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | =# 16 | 17 | 18 | getUbif(v1::Vessel, v2::Vessel, v3::Vessel) = SVector{6,Float64}(v1.u[end], v2.u[1], v3.u[1], 19 | sqrt(sqrt(v1.A[end])), sqrt(sqrt(v2.A[1])), sqrt(sqrt(v3.A[1]))) 20 | 21 | function getJbif(v1::Vessel, v2::Vessel, v3::Vessel, U, k) 22 | J::Array{Float64, 2} = zeros(Float64, 6,6) 23 | 24 | J[1, 1] = 1.0 25 | J[2, 2] = 1.0 26 | J[3, 3] = 1.0 27 | 28 | J[1, 4] = 4k[1] 29 | J[2, 5] = -4k[2] 30 | J[3, 6] = -4k[3] 31 | 32 | J[4, 1] = (U[4] * U[4] * U[4] * U[4]) 33 | J[4, 2] = -(U[5] * U[5] * U[5] * U[5]) 34 | J[4, 3] = -(U[6] * U[6] * U[6] * U[6]) 35 | J[4, 4] = 4U[1] * (U[4] * U[4] * U[4]) 36 | J[4, 5] = -4U[2] * (U[5] * U[5] * U[5]) 37 | J[4, 6] = -4U[3] * (U[6] * U[6] * U[6]) 38 | 39 | J[5, 4] = 2v1.beta[end] * U[4] / sqrt(v1.A0[end]) 40 | J[5, 5] = -2v2.beta[1] * U[5] / sqrt(v2.A0[1]) 41 | 42 | J[6, 4] = 2v1.beta[end] * U[4] / sqrt(v1.A0[end]) 43 | J[6, 6] = -2v3.beta[1] * U[6] / sqrt(v3.A0[1]) 44 | 45 | SMatrix{6, 6, Float64, 36}(J) 46 | end 47 | 48 | function getF(v1::Vessel, v2::Vessel, v3::Vessel, U, k, W) 49 | SVector{6,Float64}(U[1] + 4k[1] * U[4] - W[1], 50 | U[2] - 4k[2] * U[5] - W[2], 51 | U[3] - 4k[3] * U[6] - W[3], 52 | U[1] * (U[4] * U[4] * U[4] * U[4]) - U[2] * (U[5] * U[5] * U[5] * U[5]) - 53 | U[3] * (U[6] * U[6] * U[6] * U[6]), 54 | v1.beta[end] * (U[4] * U[4] / sqrt(v1.A0[end]) - 1) - 55 | (v2.beta[1] * (U[5] * U[5] / sqrt(v2.A0[1]) - 1)), 56 | v1.beta[end] * (U[4] * U[4] / sqrt(v1.A0[end]) - 1) - 57 | (v3.beta[1] * (U[6] * U[6] / sqrt(v3.A0[1]) - 1))) 58 | end 59 | 60 | function NRbif(U, W, J, F, k, v1::Vessel, v2::Vessel, v3::Vessel) 61 | while norm(F)>1e-5 62 | U += J \ (-F) 63 | F = getF(v1, v2, v3, U, k, W) 64 | J = getJbif(v1, v2, v3, U, k) 65 | end 66 | U 67 | end 68 | 69 | function updateBif!(v1::Vessel, v2::Vessel, v3::Vessel, U) 70 | v1.u[end] = U[1] 71 | v2.u[1] = U[2] 72 | v3.u[1] = U[3] 73 | 74 | v1.A[end] = U[4] * U[4] * U[4] * U[4] 75 | v2.A[1] = U[5] * U[5] * U[5] * U[5] 76 | v3.A[1] = U[6] * U[6] * U[6] * U[6] 77 | 78 | v1.Q[end] = v1.u[end] * v1.A[end] 79 | v2.Q[1] = v2.u[1] * v2.A[1] 80 | v3.Q[1] = v3.u[1] * v3.A[1] 81 | end 82 | 83 | function join_vessels!(v1::Vessel, v2::Vessel, v3::Vessel) 84 | k = (sqrt(1.5*v1.gamma[end]), sqrt(1.5*v2.gamma[1]), sqrt(1.5*v3.gamma[1])) 85 | U = getUbif(v1, v2, v3) 86 | W = (U[1] + 4k[1] * U[4], U[2] - 4k[2] * U[5], U[3] - 4k[3] * U[6]) 87 | F = getF(v1, v2, v3, U, k, W) 88 | J = getJbif(v1, v2, v3, U, k) 89 | 90 | # solve 91 | U = NRbif(U, W, J, F, k, v1, v2, v3) 92 | 93 | updateBif!(v1, v2, v3, U) 94 | end 95 | -------------------------------------------------------------------------------- /models/boileau2015/adan56/plot.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | 4 | plt.style.use("../plot_style.txt") 5 | 6 | def plot_arteries(arteries, fig_num, j): 7 | fig = plt.figure(fig_num+2) 8 | fig.clf() 9 | 10 | for i, artery in enumerate(arteries): 11 | ax1 = fig.add_subplot(3, 2, i * 2 + 1) 12 | ax2 = fig.add_subplot(3, 2, i * 2 + 2) 13 | 14 | P = np.loadtxt(f"adan56_results/{artery}_P.last") 15 | Q = np.loadtxt(f"adan56_results/{artery}_Q.last") 16 | 17 | ax1.plot(ta, P_ref[:, j] * 1e3 / 133.332, color="dimgrey") 18 | ax2.plot(ta, Q_ref[:, j], label="ref", color="dimgrey") 19 | ax1.plot(np.linspace(0, 1, P.shape[0]), P[:, 3] / 133.332, label="openBF", linestyle="--", color="k") 20 | ax2.plot(np.linspace(0, 1, P.shape[0]), Q[:, 3] * 1e6, label="openBF", linestyle="--", color="k") 21 | 22 | ax1.set_title(artery) 23 | plt.legend() 24 | j += 1 25 | 26 | plt.tight_layout() 27 | 28 | 29 | P_ref = np.loadtxt("adan56_ref/FVM_P_adan.txt") 30 | Q_ref = np.loadtxt("adan56_ref/FVM_Q_adan.txt") 31 | 32 | t_adan = P_ref[:,0] 33 | t0_index = np.argwhere(t_adan == t_adan[-1]-1.) 34 | P_ref = P_ref[t0_index[0][0]:, :] 35 | Q_ref = Q_ref[t0_index[0][0]:, :] 36 | ta = np.linspace(0, 1, len(P_ref[:,0])) 37 | 38 | 39 | fig = plt.figure(4, figsize=(10,12)) 40 | fig.clf() 41 | 42 | mapping = dict(zip(["aortic_arch_I", "thoracic_aorta_III", "abdominal_aorta_V", 43 | "common_carotid_R", "renal_R", "common_iliac_R", 44 | "internal_carotid_R", "radial_R", "internal_iliac_R", 45 | "posterior_interosseous_R", "femoral_R_I", "anterior_tibial_R",], 46 | ["aortic_arch", "thoracic_aorta", "abdominal_aorta", "common_carotid", 47 | "renal", "common_iliac", "internal_carotid", "radial", "internal_iliac", 48 | "posterior_interosseous", "femoral", "anterior_tibial"])) 49 | 50 | for i, artery in enumerate(["aortic_arch_I", "thoracic_aorta_III", "abdominal_aorta_V", 51 | "common_carotid_R", "renal_R", "common_iliac_R", 52 | "internal_carotid_R", "radial_R", "internal_iliac_R", 53 | "posterior_interosseous_R", "femoral_R_I", "anterior_tibial_R",]): 54 | 55 | axP = fig.add_subplot(6, 4, (2*i)+1) 56 | axQ = fig.add_subplot(6, 4, (2*i)+2) 57 | 58 | axP.plot(ta, P_ref[:, i+1] * 1e3 / 133.332, color="dimgrey") 59 | axQ.plot(ta, Q_ref[:, i+1], label="Boileau2015-FV1D", color="dimgrey") 60 | 61 | P = np.loadtxt(f"../../adan56avg_results/{artery}_P.last") 62 | Q = np.loadtxt(f"../../adan56avg_results/{artery}_Q.last") 63 | axP.plot(np.linspace(0, 1, P.shape[0]), P[:, 3] / 133.332, label="openBF", linestyle="--", color="k") 64 | axQ.plot(np.linspace(0, 1, P.shape[0]), Q[:, 3] * 1e6, label="openBF", linestyle="--", color="k") 65 | 66 | axP.set_ylabel("$P$ (kPa)") 67 | axQ.set_ylabel("$Q$ (ml$\cdot$s$^{-1}$)") 68 | 69 | for ax in [axP, axQ]: 70 | ax.set_xlim(0,1) 71 | ax.set_xlabel("$t\,/\,T_c$") 72 | 73 | axP.set_title(mapping[artery].replace("_", " ").title()) 74 | 75 | if i == 1: 76 | legend_handle, legend_labels = ax.get_legend_handles_labels() 77 | 78 | fig.legend( 79 | legend_handle, 80 | legend_labels, 81 | loc="lower center", 82 | bbox_to_anchor=(0.5, 0), 83 | ncol=3, 84 | ) 85 | plt.tight_layout(rect=[0, 0.03, 1, 1]) 86 | plt.savefig("adan56.eps", dpi=300, format="eps") 87 | 88 | -------------------------------------------------------------------------------- /docs/src/man/overview.md: -------------------------------------------------------------------------------- 1 | The cardiovascular system is a complex network of elastic vessels through which blood is pumped by contraction of the heart. This pulsatile regime and vessel elasticity cause pressure to propagate along the arterial circulation as waves. Mechanical discontinuities caused by bifurcation, bends or cardiovascular pathology cause pressure waves to be reflected in all directions. 2 | 3 | ![](https://miro.medium.com/v2/resize:fit:1400/format:webp/1*XFQ5yKLnyEci7hLaQh0nEQ.png) 4 | 5 | Pressure waves measured at a specific location can be seen as the result of a superimposition of incident (forward) and reflected (backward) waves. The analysis of this superposition mechanism allows for the study of mechanical properties upstream and downstream of the measurement point and can be a rich source of diagnostic information about the system through which these waves propagate. However, given the vascular system complexity, it is at present difficult to ascribe a particular waveform feature to a specific trait of the arterial circulation. 6 | 7 | The understanding of the cause-effect mechanisms governing wave propagation in the cardiovascular system was used at [INSIGNEO](https://www.sheffield.ac.uk/insigneo) to develop a computer model that can reproduce this behaviour in a quantitative way. openBF is a Julia package for the solution of one-dimensional (1D) blood flow in networks of elastic arteries. 8 | 9 | ## Why 1D? 10 | 11 | The 1D model is derived from the three-dimensional formulation of the viscous fluid motion equations, the Navier-Stokes equations. These are simplified by assuming the arteries to be long, narrow, and elastic tubes and the blood to be incompressible (i.e., its density is constant over time) and behaving as a Newtonian fluid (i.e., its viscosity does not depend on its velocity). 12 | 13 | ![](https://miro.medium.com/v2/resize:fit:1400/format:webp/1*z7oY7GOWzD9YsTRiZjxpYw.png) 14 | 15 | 16 | ## Does it work? 17 | 18 | Despite all the above assumptions, the resulting partial differential equation system is complex enough to simulate the physics of pulse wave transmission and reflection. This is at the expense of results accuracy in areas where the flow structure is inherently three-dimensional, e.g., in the proximity of heart valves and bifurcations. Conversely, the computational requirements are small compared to 3D simulations, allowing the simulation of the entire cardiovascular system rather than only circumscribed parts. 19 | 20 | ![](https://miro.medium.com/v2/resize:fit:2000/format:webp/1*HpOB3AYJ2dfPJGiF9Vf6Fw.png) 21 | 22 | 23 | ## Acknowledgements 24 | 25 | The software openBF was developed at INSIGNEO Institute for in silico Medicine at The University of Sheffield (UK) as part of A. Melis’ PhD thesis under the supervision of [Dr. A. Marzo](https://www.sheffield.ac.uk/mecheng/academic-staff/alberto-marzo). We gratefully acknowledge funding from the UK Engineering and Physical Sciences Research Council (Grant Number EP/K037145/1). 26 | openBF is based on MUSCL finite-volume numerical scheme, written in Julia, and released under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) free software license on GitHub. 27 | 28 | The solver is currently used in several HPC systems within the H2020 [CompBioMed](https://www.compbiomed.eu) Centre of Excellence in Computational Biomedicine (Grant Agreement №675451). In [SURFSara](https://www.surf.nl/en/research-it)’s HPC-Cloud, it is being used for large-scale sensitivity analysis and uncertainty quantification studies, towards clinical application. The simulations reported in the thesis and in this [paper](https://pubmed.ncbi.nlm.nih.gov/28337862/) where run in TUoS’s ShARC tier-3 cluster. More information can be found on the official page and in CompBioMed [Software Hub](https://www.compbiomed.eu/services/software-hub/compbiomed-software-openbf/). 29 | -------------------------------------------------------------------------------- /src/boundary_conditions.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Copyright 2015-2024 INSIGNEO Institute for in silico Medicine 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | =# 16 | 17 | function inbc!(v::Vessel, t::Float64, dt::Float64, h::Heart) 18 | v.Q[1] = inlet_from_data(t, h) 19 | incompat!(v, dt) 20 | end 21 | 22 | function inlet_from_data(t::Float64, h::Heart) 23 | idt = h.input_data[:, 1] 24 | idq = h.input_data[:, 2] 25 | t_hat = div(t, h.cardiac_period) 26 | t -= t_hat * h.cardiac_period 27 | idx = 0 28 | for i = 1:length(idt) 29 | if ((t >= idt[i]) && (t <= idt[i+1])) 30 | idx = i 31 | break 32 | end 33 | end 34 | idq[idx] + (t - idt[idx]) * (idq[idx+1] - idq[idx]) / (idt[idx+1] - idt[idx]) 35 | end 36 | 37 | function riemann_invariants(i::Int64, v::Vessel) 38 | c = wave_speed(v.A[i], v.gamma[i+1]) 39 | (v.u[i] - 4c, v.u[i] + 4c) 40 | end 41 | 42 | function inv_riemann_invariants(W1::Float64, W2::Float64) 43 | 0.5 * (W1 + W2) 44 | end 45 | 46 | function incompat!(v::Vessel, dt::Float64) 47 | W11, W21 = riemann_invariants(1, v) 48 | W12, W22 = riemann_invariants(2, v) 49 | 50 | W11 += (W12 - W11) * (wave_speed(v.A[1], v.gamma[2]) - v.u[1]) * dt / v.dx 51 | W21 = 2 * v.Q[1] / v.A[1] - W11 52 | 53 | v.u[1] = inv_riemann_invariants(W11, W21) 54 | v.A[1] = v.Q[1] / v.u[1] 55 | end 56 | 57 | 58 | function outbc!(v::Vessel, dt::Float64, ρ::Float64) 59 | if v.usewk3 60 | wk3!(v, dt, ρ) 61 | else 62 | outcompat!(v, dt) 63 | end 64 | end 65 | 66 | function outcompat!(v::Vessel, dt::Float64) 67 | W1M1, W2M1 = riemann_invariants(v.M - 1, v) 68 | W1M, W2M = riemann_invariants(v.M, v) 69 | 70 | W2M += (W2M1 - W2M) * (v.u[end] + wave_speed(v.A[end], v.gamma[end-1])) * dt / v.dx 71 | W1M = v.W1M0 - v.Rt * (W2M - v.W2M0) 72 | 73 | v.u[end] = inv_riemann_invariants(W1M, W2M) 74 | v.Q[end] = v.A[end] * v.u[end] 75 | end 76 | 77 | 78 | function wk3!(v::Vessel, dt::Float64, ρ::Float64) 79 | # inlet impedance matching 80 | if v.inlet_impedance_matching 81 | v.R1 = ρ * wave_speed(v.A[end], v.gamma[end-1]) / v.A[end] 82 | v.R2 = abs(v.total_peripheral_resistance - v.R1) 83 | end 84 | 85 | v.Pc += dt / v.Cc * (v.A[end] * v.u[end] - (v.Pc - v.Pout) / v.R2) 86 | As = v.A[end] 87 | 88 | ssAl = sqrt(sqrt(v.A[end])) 89 | sgamma = 2 * sqrt(6 * v.gamma[end-1]) 90 | sA0 = sqrt(v.A0[end]) 91 | bA0 = v.beta[end] / sA0 92 | 93 | fun(As) = 94 | As * v.R1 * (v.u[end] + sgamma * (ssAl - sqrt(sqrt(As)))) - 95 | (v.Pext + bA0 * (sqrt(As) - sA0)) + v.Pc 96 | 97 | dfun(As) = v.R1 * (v.u[end] + sgamma * (ssAl - 1.25 * sqrt(sqrt(As)))) - bA0 * 0.5 / sqrt(As) 98 | As = newtone(fun, dfun, As) 99 | us = (pressure(As, v.A0[end], v.beta[end], v.Pext) - v.Pout) / (As * v.R1) 100 | 101 | v.A[end] = As 102 | v.u[end] = us 103 | end 104 | 105 | function newtone(f::Function, df::Function, xn) 106 | for _=1:10 107 | xn -= f(xn) / df(xn) 108 | end 109 | xn 110 | end 111 | 112 | function update_ghost_cells!(n::Network) 113 | for v in values(n.vessels) 114 | v.U00A = v.A[1] 115 | v.U00Q = v.Q[1] 116 | v.UM1A = v.A[v.M] 117 | v.UM1Q = v.Q[v.M] 118 | end 119 | end 120 | -------------------------------------------------------------------------------- /models/alastruey2007/circle_of_willis_inlet.dat: -------------------------------------------------------------------------------- 1 | 0. 1e-10 2 | 0.002578035547264837 2.56124465958138E-005 3 | 0.003393710709713199 3.36811539912829E-005 4 | 0.0059650704553832895 4.177784047547E-005 5 | 0.009170487057840973 4.94284574347936E-005 6 | 0.010010864793439905 5.93369189432453E-005 7 | 0.010376168468273744 6.67321452255263E-005 8 | 0.012926340166176845 7.56801527227304E-005 9 | 0.01451422136132946 9.23614862371485E-005 10 | 0.016201070659940642 9.99876101754423E-005 11 | 0.017471013427211995 0.0001075554 12 | 0.020402135358299905 0.0001214888 13 | 0.023930465311209792 0.0001399359 14 | 0.028295824046381035 0.0001645119 15 | 0.026918057658251032 0.000154428 16 | 0.03073172516188269 0.0001742385 17 | 0.03189199714515675 0.0001827436 18 | 0.03403888593035917 0.0001906408 19 | 0.03492388001451435 0.0002011793 20 | 0.038064419539087235 0.0002104471 21 | 0.040496879860507096 0.000219206 22 | 0.04179812091860691 0.0002276309 23 | 0.04400928385223826 0.0002365792 24 | 0.04524897867634825 0.0002447204 25 | 0.04781773066229314 0.0002520836 26 | 0.04825931130908814 0.0002570951 27 | 0.05169503474699591 0.000269928 28 | 0.05584752992047398 0.0002857146 29 | 0.05857256639550357 0.0002973052 30 | 0.060729229105548926 0.0003079513 31 | 0.06329992771284071 0.0003158621 32 | 0.06552985202893921 0.0003232765 33 | 0.07017188165304727 0.0003416705 34 | 0.072866628791904 0.0003504176 35 | 0.07616981051342328 0.0003600254 36 | 0.07935389677963692 0.0003701899 37 | 0.08217141559063404 0.0003794143 38 | 0.0881612948038028 0.0003955052 39 | 0.0898785045828254 0.0004017383 40 | 0.09305115473607764 0.0004086865 41 | 0.09629424544666804 0.0004184198 42 | 0.09970823755353275 0.0004251408 43 | 0.1044045334157312 0.0004349606 44 | 0.10739651083492935 0.0004421729 45 | 0.11208655893945291 0.0004502355 46 | 0.12529049627824204 0.0004691686 47 | 0.13209403274454806 0.0004757346 48 | 0.14195587677511196 0.0004816832 49 | 0.15118867422798982 0.0004828657 50 | 0.15923524282995888 0.0004814854 51 | 0.17149320756725395 0.0004727298 52 | 0.17908984060176092 0.0004639881 53 | 0.18633931950344984 0.0004529558 54 | 0.1908920333569709 0.0004462297 55 | 0.1944216361449847 0.0004377929 56 | 0.1977609086919464 0.0004314446 57 | 0.20434676965897108 0.000416517 58 | 0.20756354993662007 0.0004074998 59 | 0.21021939023172004 0.000399629 60 | 0.21315701345267835 0.0003915542 61 | 0.21440837593190787 0.0003859508 62 | 0.21819180066650468 0.0003773916 63 | 0.22184483741484307 0.0003662131 64 | 0.22448175334249298 0.0003586952 65 | 0.22699863988501517 0.0003514713 66 | 0.22845089041029526 0.0003427761 67 | 0.2315916110292935 0.000332231 68 | 0.23493932257647693 0.0003203106 69 | 0.23702991542876756 0.0003123746 70 | 0.23869874505593663 0.0003050008 71 | 0.24037281503836283 0.0002991008 72 | 0.2415334233398554 0.0002918094 73 | 0.24371590091650996 0.0002858794 74 | 0.2452131896253768 0.0002779329 75 | 0.24822884643422222 0.0002679685 76 | 0.25164374401321377 0.0002511075 77 | 0.2541601416007874 0.000243746 78 | 0.25554524231314446 0.0002360288 79 | 0.2562286150625521 0.000229589 80 | 0.2587555031914805 0.0002251781 81 | 0.2640128766209537 0.0001869393 82 | 0.272074635987772 0.0001573269 83 | 0.2754215099732381 0.0001451708 84 | 0.2789255157109933 0.0001261297 85 | 0.28120203109537595 0.0001172777 86 | 0.28108344981888517 0.0001087565 87 | 0.28473390330850895 0.00010019 88 | 0.286967117151581 9.1919439098079E-005 89 | 0.2873823337426697 8.53488258384314E-005 90 | 0.2888989666287907 0.000078509 91 | 0.28871798979721464 7.09485046416387E-005 92 | 0.2901025045397525 6.30664748773388E-005 93 | 0.2929796825573084 5.60495464122786E-005 94 | 0.2931255590558738 4.723713113178E-005 95 | 0.29428327458950987 3.9132112040346E-005 96 | 0.2940458836084278 3.32816747801435E-005 97 | 0.29582314161601897 2.32969279995693E-005 98 | 0.29868830566476534 1.47068744481865E-005 99 | 0.30228300134292435 0.000002143 100 | 0.31013659663831217 1e-10 101 | 1. 1e-10 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # __openBF.jl__ 2 | 3 | [![TUoS](https://img.shields.io/badge/-The%20University%20of%20Sheffield-blue.svg?colorA=ffffff&colorB=009fe3&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAMAAAAolt3jAAABsFBMVEUAAABmZplVVYBLPHheUYZJPXlSR3pCOnNgWIdoYI9FPnVMQXc0JGM0KmhEOXI0MW8xMW2Ph6yYkrOWj6%2BOiayinLqWkbIcWJkdWJezrsW2sciclrWmoL0cWpkbXJuCfqQVba4Vba2tqsKBgKWXkbGgm7ioo7%2Bln7umobyppcClob0RdrgSd7ikoLuXkbEeeKwieqmYkrKkn7sAneAAn%2BMBnN8Dn%2BIEj9IEkNQEoOMFi88GicwHnuAInuAVaqkVgrEWa6sWiskYj84ek88mk8wmqOInqOIqhrA4qd45qd87kaA8q988q%2BA9qN0%2Fk51Aqd1CqdxCqd1JnqtNnc9OnKVPnItSmsZUmqZVlsFVnYZVns1bst9ds99ftN9isNtitN9joa1msdtnveZqoaRqrNZqvuZsrdZvk2lylWR0nKZ2oJx%2BfKOBf6WEn5eGr3iIr3eduNWfmbifmrifudWim6mjnKmloLymrz2psTuuqb6uqsOwq8C0taG2tqS4tqy4tra6uTC6ui6%2FsCK%2FsCPBvdHDv9LFwtfGwtjOy9rPzdvUlaHmkpb%2B%2FPz%2B%2Fv7%2F%2FPz%2F%2F%2F9OZpcfAAAAM3RSTlMABQYRExUZHyAgJS8xMTFTVFleZmiJkpOTmp2oqba9wsTFxcfO0dPX3OLj5%2Bf19v39%2Fv4kncL4AAAAvElEQVR4AWNgYBIQV9Q20NdRkOBnZGBg4DExTQ9taIzMMDbhA3PdzMqbmyosXaHc4kCvvHy%2FgAIINzElvL%2B%2FvzcoLQ7E5bX1TOhq624P8bDhBnLZTEwye%2Fr7%2BpNNTFgYgMApJreuprY%2BK94RyOGSlEv19XZx9vFPkpViZ1BRZ7WKdq%2Bsto%2B1ZtZQYhAp1FS2iCopDTaX1yoSZmDgkNHrsAuLcOjUleZkAAGxqtbsnJYyUQYoEFIzMlQVBLEA%2FZgsl9iPrB4AAAAASUVORK5CYII%3D)](https://www.sheffield.ac.uk) 4 | [![INSIGNEO](https://img.shields.io/badge/-INSIGNEO-red.svg?colorA=ffffff&colorB=cf2020&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAMAAAAolt3jAAABC1BMVEUAAAD%2FAAC%2FAADMGhrRFxfSHh7VHBzJGxvTISHKICDMHx%2FOHR3RJCTTIyPOISHPICDMHR3NIyPNICDRISHQHx%2FQHx%2FOHx%2FQISHOICDQICDQHx%2FOHx%2FPISHQISHQICDOICDQISHOICDQICDPISHPICDQISHPICDPICDOHx%2FPISHPISHQISHPICDPISHPISHQICDOICDOICDPHx%2FPICDPICDOICDPICDPICDPICDPHx%2FPICDPICDQICDPICDPHx%2FQISHOICDPICDPICDPICDPICDPHx%2FMISHOICDPICDQICDPICDPISHPHx%2FPICDPICDPICDPICDPICDPICDOICDPHx%2FPICDPICDPICDPICDi8V76AAAAWHRSTlMAAgQKCxESExcYGRocHR8gIyRITVFSU1ZYYWJjZGZnaWxucXV5fH%2BAg4SFjI%2BUlZeYqKuusbK2ubrDxcbHycvMzdHU2Nrb4uLl5%2Bnq6%2Bzt7u%2F09vf7%2FP3%2B%2FHERCQAAAKVJREFUeAEdx%2BVCg2AAhtHHAANDMQRD7ECwO7DDjViM7b3%2FK9n4zr9Dxdk6jjc4s02si46kK7tMLGDuW%2Fq%2FvdxZlt5shh7VWhsGTqWvTVYll0q4PjMyy7VuYHQ7nIL98oVMAey183sI9EtNPpzXfz7BV8aHIpi%2Fe3ch1iuHysYxnFxHTDf1bD7xpMKBxa6Kk6WVKFXPY8BLZTQWMMYOHvK%2FZHcS6AOapR0V%2FpSSVQAAAABJRU5ErkJggg%3D%3D)](https://insigneo.org/) 5 | [![CompBioMed](https://img.shields.io/badge/-CompBioMed-yellow.svg?colorA=grey&colorB=f4b540&logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAAoAAAAQCAMAAAAYoR5yAAAA81BMVEUAAAD%2F%2F%2F%2Bqqqr%2F%2F8z%2FzLP%2FyKT%2F1ar%2F4KP%2F9dj%2F5L%2Fm1bP%2F3bv%2Fx4Dw4eHbzJn%2F26%2F52Zn%2FzobQypT%2F6LveyLH%2FyID63d3%2F05P%2Fx3nt19fZzbT%2Fv2Dx0sHk0NDPtX7%2Fxln207D53abEr3f8vFjx1Jz%2FxWP%2FvmL%2FwWT%2Fw0f8vk7t0aj12aLBsnzz0qbTvZritmTAq3vWtF6%2FrIHHr4rJsor6vGPYu3vCsIft17rewJLCq3nw267KtYn%2Fv1vKtJL%2FvFPzz5v547H536P9uE%2FLrG7LsnHGsHbyvmXexIzWq130qkP3y3%2F8tUr3yYD6s0T8sz78tETsoiaWAAAAUXRSTlMAAgMFCg4YGRocHh4gIiMjKCorLS4uNDQ3OT1ISkxPUFFTVldYXV5eYWJkZWdnaGlqamttbW9wcXN1dnh5e35%2Bf3%2BAgYSFio6Sl5ydn6GkqK2fR9KlAAAAd0lEQVQI1zXGRQKCABRAwWdhY3d3t9iJ3d7%2FNC74zmo4H%2FH4AGBxoWIzetKUnDFu321c2vtUrdLx0y5j8oj9u3sPzFL9Ps9K86%2FmSho5FK77sgmglGKamLUA6gH6rkzHDzTcBDfe6BJYO6A4DKdDFmpOQG2PuskfKZ4MqTH%2F64gAAAAASUVORK5CYII%3D)](http://www.compbiomed.eu/) 6 | 7 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Mentioned in Awesome Julia.jl](https://awesome.re/mentioned-badge.svg)](https://github.com/svaksha/Julia.jl/blob/master/Biology.md#bioinformatics) 8 | 9 | [![DOI](https://zenodo.org/badge/92175375.svg)](https://doi.org/10.5281/zenodo.13850604) 10 | 11 | openbf ci status 12 | 13 | [![chat](https://dcbadge.vercel.app/api/server/eVU5bDEm8X)](https://discord.gg/eVU5bDEm8X) 14 | 15 | [![openBF](https://static.streamlit.io/badges/streamlit_badge_black_white.svg)](https://openBF.streamlit.app) 16 | 17 | openBF is an open-source 1D blood flow solver based on MUSCL finite-volume numerical scheme, written in [Julia](https://julialang.org/downloads/) and released under [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0) free software license. 18 | 19 | Read the [documentation](https://insigneo.github.io/openBF/stable) for installation and run instructions. 20 | 21 | ## Release notes 22 | 23 | ### v2.0.0 24 | This is a complete re-write of openBF solver with several bugfixes and few new functionalities. 25 | Config files should be backward compatible but please refer to the new [documentation](https://insigneo.github.io/openBF/stable) for more details. 26 | 27 | Currently not supported: 28 | - multiple inlets 29 | 30 | If your workflow relies on this feature, we recommend to use [release v1.5.1](https://github.com/INSIGNEO/openBF/releases/tag/v1.5.1). 31 | 32 | --- 33 | 34 | ### Citation 35 | 36 | ``` 37 | @article{Benemerito_2024, 38 | doi = {10.1088/1361-6579/ad9663}, 39 | url = {https://dx.doi.org/10.1088/1361-6579/ad9663}, 40 | year = {2024}, 41 | month = {dec}, 42 | publisher = {IOP Publishing}, 43 | volume = {45}, 44 | number = {12}, 45 | pages = {125002}, 46 | author = {I Benemerito and A Melis and A Wehenkel and A Marzo}, 47 | title = {openBF: an open-source finite volume 1D blood flow solver}, 48 | journal = {Physiological Measurement} 49 | } 50 | ``` 51 | -------------------------------------------------------------------------------- /models/boileau2015/cca/cca_inlet.dat: -------------------------------------------------------------------------------- 1 | 0.000000000000000000e+00 4.522272753764271518e-06 2 | 1.111111111111111154e-02 4.459151493369108714e-06 3 | 2.222222222222222307e-02 4.270211436687907413e-06 4 | 3.333333333333333287e-02 4.047046491496753214e-06 5 | 4.444444444444444614e-02 3.864850534090660021e-06 6 | 5.555555555555555941e-02 3.795904737716332879e-06 7 | 6.666666666666666574e-02 3.921117155243199364e-06 8 | 7.777777777777777901e-02 4.306046124414433703e-06 9 | 8.888888888888889228e-02 4.990795876233012416e-06 10 | 1.000000000000000056e-01 5.973796090414800810e-06 11 | 1.111111111111111188e-01 7.177599382042515321e-06 12 | 1.222222222222222321e-01 8.479194364466723996e-06 13 | 1.333333333333333315e-01 9.789680990363213150e-06 14 | 1.444444444444444586e-01 1.103503448579041034e-05 15 | 1.555555555555555580e-01 1.207046941067246844e-05 16 | 1.666666666666666852e-01 1.274502952813232043e-05 17 | 1.777777777777777846e-01 1.307545662477458176e-05 18 | 1.888888888888888840e-01 1.322723356328885269e-05 19 | 2.000000000000000111e-01 1.330027611638510493e-05 20 | 2.111111111111111105e-01 1.326686829451594170e-05 21 | 2.222222222222222376e-01 1.313045827332801567e-05 22 | 2.333333333333333370e-01 1.297939976257387453e-05 23 | 2.444444444444444642e-01 1.284431427358671897e-05 24 | 2.555555555555555913e-01 1.265288301919150900e-05 25 | 2.666666666666666630e-01 1.236765778934774118e-05 26 | 2.777777777777777901e-01 1.203620303284990105e-05 27 | 2.888888888888889173e-01 1.167726012065493197e-05 28 | 2.999999999999999889e-01 1.124638041360719092e-05 29 | 3.111111111111111160e-01 1.073951518191492873e-05 30 | 3.222222222222222432e-01 1.021724664468131475e-05 31 | 3.333333333333333703e-01 9.712385979140264027e-06 32 | 3.444444444444444420e-01 9.211967043394362495e-06 33 | 3.555555555555555691e-01 8.727720079077438278e-06 34 | 3.666666666666666963e-01 8.291947638373486877e-06 35 | 3.777777777777777679e-01 7.893845023464596803e-06 36 | 3.888888888888888951e-01 7.499054848091733268e-06 37 | 4.000000000000000222e-01 7.113021790669797204e-06 38 | 4.111111111111111494e-01 6.762245179994133680e-06 39 | 4.222222222222222210e-01 6.447776793301955715e-06 40 | 4.333333333333333481e-01 6.173371635023873377e-06 41 | 4.444444444444444753e-01 5.977847359612110184e-06 42 | 4.555555555555555469e-01 5.891127276719836197e-06 43 | 4.666666666666666741e-01 5.898560390876281251e-06 44 | 4.777777777777778012e-01 5.977176109310090899e-06 45 | 4.888888888888889284e-01 6.115841560146191055e-06 46 | 5.000000000000000000e-01 6.278880684465122685e-06 47 | 5.111111111111111827e-01 6.404806298677957383e-06 48 | 5.222222222222222543e-01 6.457862249367258448e-06 49 | 5.333333333333333259e-01 6.436699816990932728e-06 50 | 5.444444444444445086e-01 6.337546385372510595e-06 51 | 5.555555555555555802e-01 6.160532750708398362e-06 52 | 5.666666666666666519e-01 5.941795523679593566e-06 53 | 5.777777777777778345e-01 5.729805283636493136e-06 54 | 5.888888888888889062e-01 5.542777711717886510e-06 55 | 5.999999999999999778e-01 5.383742762081236091e-06 56 | 6.111111111111111605e-01 5.266238291457180700e-06 57 | 6.222222222222222321e-01 5.188775150420545977e-06 58 | 6.333333333333333037e-01 5.118144951651296626e-06 59 | 6.444444444444444864e-01 5.028444448335769243e-06 60 | 6.555555555555555580e-01 4.923216276876083530e-06 61 | 6.666666666666667407e-01 4.804998094925161381e-06 62 | 6.777777777777778123e-01 4.667698867979685534e-06 63 | 6.888888888888888840e-01 4.529216582774128812e-06 64 | 7.000000000000000666e-01 4.425621689836006946e-06 65 | 7.111111111111111382e-01 4.368361070685657070e-06 66 | 7.222222222222222099e-01 4.346716274893982910e-06 67 | 7.333333333333333925e-01 4.360872146182763037e-06 68 | 7.444444444444444642e-01 4.409041751677258738e-06 69 | 7.555555555555555358e-01 4.460489705878833247e-06 70 | 7.666666666666667185e-01 4.483771057722683955e-06 71 | 7.777777777777777901e-01 4.480264690260942619e-06 72 | 7.888888888888889728e-01 4.459228015827431010e-06 73 | 8.000000000000000444e-01 4.415051917784992281e-06 74 | 8.111111111111111160e-01 4.357079789995703772e-06 75 | 8.222222222222222987e-01 4.319678682401102158e-06 76 | 8.333333333333333703e-01 4.318477394105276221e-06 77 | 8.444444444444444420e-01 4.337886266277900024e-06 78 | 8.555555555555556246e-01 4.370982969731143281e-06 79 | 8.666666666666666963e-01 4.422015555653073377e-06 80 | 8.777777777777777679e-01 4.468996095825814591e-06 81 | 8.888888888888889506e-01 4.478688255321557696e-06 82 | 9.000000000000000222e-01 4.454219417052037556e-06 83 | 9.111111111111110938e-01 4.418775221966065377e-06 84 | 9.222222222222222765e-01 4.372737543579065604e-06 85 | 9.333333333333333481e-01 4.317118285967872230e-06 86 | 9.444444444444445308e-01 4.285657458373796433e-06 87 | 9.555555555555556024e-01 4.301073176200235511e-06 88 | 9.666666666666666741e-01 4.338086534128967208e-06 89 | 9.777777777777778567e-01 4.372057560189827103e-06 90 | 9.888888888888889284e-01 4.410845059326091013e-06 91 | 1.000000000000000000e+00 4.443052017293809235e-06 92 | 1.011111111111111072e+00 4.425192674560983887e-06 93 | 1.022222222222222365e+00 4.356330886383273651e-06 94 | 1.033333333333333437e+00 4.289741008640001453e-06 95 | 1.044444444444444509e+00 4.245606306610788958e-06 96 | 1.055555555555555580e+00 4.201489238398525249e-06 97 | 1.066666666666666652e+00 4.185766616426958643e-06 98 | 1.077777777777777724e+00 4.268421394991178443e-06 99 | 1.088888888888889017e+00 4.426181465936223048e-06 100 | 1.100000000000000089e+00 4.522272753764273212e-06 101 | -------------------------------------------------------------------------------- /models/boileau2015/uta/uta_inlet.dat: -------------------------------------------------------------------------------- 1 | 0.000000000000000000e+00 1.297902587706564030e-06 2 | 9.646464646464646131e-03 1.992359977822207845e-05 3 | 1.929292929292929226e-02 6.051409114873273028e-05 4 | 2.893939393939393839e-02 1.251579529622365284e-04 5 | 3.858585858585858452e-02 2.123515868765870956e-04 6 | 4.823232323232323066e-02 2.973352420574871440e-04 7 | 5.787878787878787679e-02 3.634231939873193516e-04 8 | 6.752525252525251598e-02 4.099659955059099478e-04 9 | 7.717171717171716905e-02 4.409985786341042899e-04 10 | 8.681818181818182212e-02 4.651478538361411238e-04 11 | 9.646464646464646131e-02 4.827837517253131573e-04 12 | 1.061111111111111005e-01 4.962868124668907196e-04 13 | 1.157575757575757536e-01 5.060854674255281646e-04 14 | 1.254040404040404066e-01 5.091581925826868917e-04 15 | 1.350505050505050320e-01 5.074368449602661415e-04 16 | 1.446969696969696850e-01 5.010740279701975629e-04 17 | 1.543434343434343381e-01 4.918917765489903100e-04 18 | 1.639898989898989912e-01 4.768796155084369017e-04 19 | 1.736363636363636442e-01 4.574016228063572886e-04 20 | 1.832828282828282696e-01 4.386276196252084829e-04 21 | 1.929292929292929226e-01 4.196083054410296989e-04 22 | 2.025757575757575757e-01 4.003247764711369782e-04 23 | 2.122222222222222010e-01 3.718911059397892295e-04 24 | 2.218686868686868541e-01 3.374004885261615424e-04 25 | 2.315151515151515071e-01 3.038806648284323483e-04 26 | 2.411616161616161602e-01 2.680262817439713454e-04 27 | 2.508080808080808133e-01 2.367299843297686844e-04 28 | 2.604545454545454386e-01 2.068729342297937390e-04 29 | 2.701010101010100639e-01 1.813640405781655500e-04 30 | 2.797474747474747447e-01 1.552440059318470475e-04 31 | 2.893939393939393701e-01 1.191733596619777639e-04 32 | 2.990404040404040509e-01 8.780865494471137649e-05 33 | 3.086868686868686762e-01 2.802974689942088759e-05 34 | 3.183333333333333015e-01 -4.370178344576868890e-05 35 | 3.279797979797979823e-01 -4.378266031418031630e-05 36 | 3.376262626262626076e-01 -1.146105713847934992e-05 37 | 3.472727272727272885e-01 -3.436835742044251670e-06 38 | 3.569191919191919138e-01 -1.299100160097326128e-06 39 | 3.665656565656565391e-01 -2.094853275012251977e-06 40 | 3.762121212121212199e-01 -2.115801458749342654e-06 41 | 3.858585858585858452e-01 -9.862227252147240544e-07 42 | 3.955050505050504706e-01 -2.179634783836791819e-06 43 | 4.051515151515151514e-01 -1.028630001658693130e-06 44 | 4.147979797979797767e-01 -1.574181236158349648e-06 45 | 4.244444444444444020e-01 -1.419892489625112347e-06 46 | 4.340909090909090828e-01 -1.112444578286891605e-06 47 | 4.437373737373737081e-01 -1.528627046028773843e-06 48 | 4.533838383838383890e-01 -6.756453029997436137e-07 49 | 4.630303030303030143e-01 -1.090321065202441970e-06 50 | 4.726767676767676396e-01 -2.953545273704283841e-07 51 | 4.823232323232323204e-01 -7.769488597916741519e-08 52 | 4.919696969696969457e-01 -2.557657100934678315e-07 53 | 5.016161616161616266e-01 3.743807064578989320e-07 54 | 5.112626262626261964e-01 -3.454437395956790029e-07 55 | 5.209090909090908772e-01 -6.372308572451869556e-08 56 | 5.305555555555555580e-01 -3.897833500794703411e-07 57 | 5.402020202020201278e-01 -7.083516214537940012e-07 58 | 5.498484848484848087e-01 -3.732912732780579292e-07 59 | 5.594949494949494895e-01 -7.496007801754086246e-07 60 | 5.691414141414141703e-01 -3.347279510381871294e-08 61 | 5.787878787878787401e-01 7.818996514720715569e-10 62 | 5.884343434343434209e-01 3.080645688925917995e-07 63 | 5.980808080808081018e-01 8.724633545337208159e-07 64 | 6.077272727272726716e-01 7.593916367102675446e-07 65 | 6.173737373737373524e-01 1.459367889612547165e-06 66 | 6.270202020202020332e-01 1.083129468039229710e-06 67 | 6.366666666666666030e-01 8.275982180210055901e-07 68 | 6.463131313131312838e-01 6.763940053061121550e-07 69 | 6.559595959595959647e-01 3.128880664335573645e-08 70 | 6.656060606060605345e-01 -1.133048947715953000e-08 71 | 6.752525252525252153e-01 -8.153256104392395154e-07 72 | 6.848989898989898961e-01 -1.235993431284040320e-06 73 | 6.945454545454545769e-01 -1.665288241593293828e-06 74 | 7.041919191919191467e-01 -2.045607673767120194e-06 75 | 7.138383838383838276e-01 -1.666710918977812579e-06 76 | 7.234848484848485084e-01 -1.682538576059341169e-06 77 | 7.331313131313130782e-01 -1.042946531246257169e-06 78 | 7.427777777777777590e-01 -6.033669735596844979e-07 79 | 7.524242424242424399e-01 -2.374757071983510264e-07 80 | 7.620707070707070097e-01 9.077148615027277896e-08 81 | 7.717171717171716905e-01 -2.593091486842228820e-07 82 | 7.813636363636363713e-01 2.442884965554384301e-08 83 | 7.910101010101009411e-01 -1.545121472600197436e-07 84 | 8.006565656565656219e-01 -2.289759639407189700e-07 85 | 8.103030303030303028e-01 -2.766353251663086223e-07 86 | 8.199494949494948726e-01 -9.383976189807954643e-07 87 | 8.295959595959595534e-01 -1.348233736718816772e-06 88 | 8.392424242424242342e-01 -2.412195013534019521e-06 89 | 8.488888888888888040e-01 -3.190302627495958199e-06 90 | 8.585353535353534848e-01 -3.875022250529422051e-06 91 | 8.681818181818181657e-01 -4.489251961184144183e-06 92 | 8.778282828282828465e-01 -4.631997912634797747e-06 93 | 8.874747474747474163e-01 -5.031624091355188513e-06 94 | 8.971212121212120971e-01 -4.709222187147530128e-06 95 | 9.067676767676767779e-01 -4.561342748525834999e-06 96 | 9.164141414141413478e-01 -4.157319468677851551e-06 97 | 9.260606060606060286e-01 -3.337728214146740726e-06 98 | 9.357070707070707094e-01 -2.297686419730282171e-06 99 | 9.453535353535352792e-01 -1.502625888694806848e-06 100 | 9.549999999999999600e-01 1.297902587706486315e-06 -------------------------------------------------------------------------------- /models/boileau2015/ibif/ibif_inlet.dat: -------------------------------------------------------------------------------- 1 | 0.000000000000000000e+00 -5.239489231023915536e-07 2 | 1.111111111111111154e-02 -1.810043543947649782e-06 3 | 2.222222222222222307e-02 -4.106752263203652509e-06 4 | 3.333333333333333287e-02 -6.307155406759066627e-06 5 | 4.444444444444444614e-02 -7.453316028919026914e-06 6 | 5.555555555555555941e-02 -7.309722996010778137e-06 7 | 6.666666666666666574e-02 -6.197508131371585217e-06 8 | 7.777777777777777901e-02 -4.412937386033050817e-06 9 | 8.888888888888889228e-02 -1.865784178552097541e-06 10 | 1.000000000000000056e-01 1.765273247947420437e-06 11 | 1.111111111111111188e-01 6.625078440213615815e-06 12 | 1.222222222222222321e-01 1.252104753433897402e-05 13 | 1.333333333333333315e-01 1.920573178717305051e-05 14 | 1.444444444444444586e-01 2.677024308819679155e-05 15 | 1.555555555555555580e-01 3.562926121035754368e-05 16 | 1.666666666666666852e-01 4.598767697454575590e-05 17 | 1.777777777777777846e-01 5.727420543835721757e-05 18 | 1.888888888888888840e-01 6.813722078324621991e-05 19 | 2.000000000000000111e-01 7.707321840328036373e-05 20 | 2.111111111111111105e-01 8.316552026728771436e-05 21 | 2.222222222222222376e-01 8.636129978080214677e-05 22 | 2.333333333333333370e-01 8.718360874086027276e-05 23 | 2.444444444444444642e-01 8.623107266273786846e-05 24 | 2.555555555555555913e-01 8.387275860560686593e-05 25 | 2.666666666666666630e-01 8.026984295557315521e-05 26 | 2.777777777777777901e-01 7.555489242274063418e-05 27 | 2.888888888888889173e-01 6.991174273120610285e-05 28 | 2.999999999999999889e-01 6.347783338191834092e-05 29 | 3.111111111111111160e-01 5.626067660094025965e-05 30 | 3.222222222222222432e-01 4.828992549022265770e-05 31 | 3.333333333333333703e-01 3.989393478370251709e-05 32 | 3.444444444444444420e-01 3.168527124293345421e-05 33 | 3.555555555555555691e-01 2.408491475986813282e-05 34 | 3.666666666666666963e-01 1.685928263790101785e-05 35 | 3.777777777777777679e-01 9.332803157868673947e-06 36 | 3.888888888888888951e-01 1.221459386476058274e-06 37 | 4.000000000000000222e-01 -6.810527145834715347e-06 38 | 4.111111111111111494e-01 -1.358180240306974179e-05 39 | 4.222222222222222210e-01 -1.838636713962990893e-05 40 | 4.333333333333333481e-01 -2.143290971749338717e-05 41 | 4.444444444444444753e-01 -2.329872060883883496e-05 42 | 4.555555555555555469e-01 -2.416692999531072332e-05 43 | 4.666666666666666741e-01 -2.379516435394250564e-05 44 | 4.777777777777778012e-01 -2.214276017953382861e-05 45 | 4.888888888888889284e-01 -1.974726869296072272e-05 46 | 5.000000000000000000e-01 -1.734254538386544020e-05 47 | 5.111111111111111827e-01 -1.522231256756220318e-05 48 | 5.222222222222222543e-01 -1.313099008534702736e-05 49 | 5.333333333333333259e-01 -1.074976851507047505e-05 50 | 5.444444444444445086e-01 -8.151778532917409610e-06 51 | 5.555555555555555802e-01 -5.748893785602686741e-06 52 | 5.666666666666666519e-01 -3.904220464966048215e-06 53 | 5.777777777777778345e-01 -2.686285556511387382e-06 54 | 5.888888888888889062e-01 -1.952846777477422843e-06 55 | 5.999999999999999778e-01 -1.557977158573065957e-06 56 | 6.111111111111111605e-01 -1.428106984690457702e-06 57 | 6.222222222222222321e-01 -1.491732694493028930e-06 58 | 6.333333333333333037e-01 -1.633848893916421188e-06 59 | 6.444444444444444864e-01 -1.785925925062549406e-06 60 | 6.555555555555555580e-01 -2.051507851562523016e-06 61 | 6.666666666666667407e-01 -2.663863828970359351e-06 62 | 6.777777777777778123e-01 -3.739547050960389822e-06 63 | 6.888888888888888840e-01 -5.076244289743019663e-06 64 | 7.000000000000000666e-01 -6.269804766542887362e-06 65 | 7.111111111111111382e-01 -7.071058511233771672e-06 66 | 7.222222222222222099e-01 -7.575742239734086784e-06 67 | 7.333333333333333925e-01 -8.014752219741598846e-06 68 | 7.444444444444444642e-01 -8.419865022937885718e-06 69 | 7.555555555555555358e-01 -8.600209680439256687e-06 70 | 7.666666666666667185e-01 -8.429971494648805962e-06 71 | 7.777777777777777901e-01 -8.022938266533514274e-06 72 | 7.888888888888889728e-01 -7.566095801927185752e-06 73 | 8.000000000000000444e-01 -7.098279433111552240e-06 74 | 8.111111111111111160e-01 -6.568990729712377425e-06 75 | 8.222222222222222987e-01 -6.037601030251277555e-06 76 | 8.333333333333333703e-01 -5.643254574514988833e-06 77 | 8.444444444444444420e-01 -5.375199879333458125e-06 78 | 8.555555555555556246e-01 -5.056608503029805432e-06 79 | 8.666666666666666963e-01 -4.652311985696004512e-06 80 | 8.777777777777777679e-01 -4.447961326576372164e-06 81 | 8.888888888888889506e-01 -4.748228476792333338e-06 82 | 9.000000000000000222e-01 -5.448030853072816225e-06 83 | 9.111111111111110938e-01 -6.087928154143909244e-06 84 | 9.222222222222222765e-01 -6.355140246645855874e-06 85 | 9.333333333333333481e-01 -6.353499199540407426e-06 86 | 9.444444444444445308e-01 -6.299503166887456157e-06 87 | 9.555555555555556024e-01 -6.133293284942808649e-06 88 | 9.666666666666666741e-01 -5.628094249643691837e-06 89 | 9.777777777777778567e-01 -4.804947720027944289e-06 90 | 9.888888888888889284e-01 -3.992908349549955654e-06 91 | 1.000000000000000000e+00 -3.425824900698486656e-06 92 | 1.011111111111111072e+00 -2.988425260950394039e-06 93 | 1.022222222222222365e+00 -2.502029112748187246e-06 94 | 1.033333333333333437e+00 -2.097731471409650300e-06 95 | 1.044444444444444509e+00 -2.053044079734801498e-06 96 | 1.055555555555555580e+00 -2.274448730253089779e-06 97 | 1.066666666666666652e+00 -2.220509840415812151e-06 98 | 1.077777777777777724e+00 -1.531464435157532165e-06 99 | 1.088888888888889017e+00 -6.373840759172933434e-07 100 | 1.100000000000000089e+00 -5.239489231024034121e-07 101 | -------------------------------------------------------------------------------- /dashboard/openbf_dashboard/vessel.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | from typing import Dict 3 | 4 | 5 | def get_vessel(i: int) -> Dict: 6 | v = {} 7 | with st.expander(f"vessel index {i}"): 8 | 9 | v["to_save"] = st.checkbox(label="to_save", key=f"to_save {i}", value=True) 10 | c1, c2 = st.columns([1, 1]) 11 | with c1: 12 | v["label"] = st.text_input( 13 | "label", 14 | value="vessel_name", 15 | key=f"label {i}", 16 | ) 17 | 18 | sn = st.number_input( 19 | label="sn", 20 | min_value=1, 21 | step=1, 22 | help="source node", 23 | key=f"sn {i}", 24 | ) 25 | L = st.number_input( 26 | "$\ell$ $(m)$", 27 | min_value=0.001, 28 | max_value=1.0, 29 | step=0.01, 30 | value=0.01, 31 | format="%6.5f", 32 | help="length", 33 | key=f"l {i}", 34 | ) 35 | Rp = st.number_input( 36 | "$R_{0p}$ $(m)$", 37 | min_value=0.0001, 38 | max_value=1.0, 39 | step=0.0001, 40 | value=0.001, 41 | format="%7.6f", 42 | help="proximal radius", 43 | key=f"r0p {i}", 44 | ) 45 | E = st.number_input( 46 | "E $(Pa)$", 47 | min_value=1e3, 48 | value=125e3, 49 | help="wall Young's modulus", 50 | format="%e", 51 | key=f"E {i}", 52 | ) 53 | with c2: 54 | 55 | tn = st.number_input( 56 | label="tn", 57 | min_value=2, 58 | step=1, 59 | help="target node", 60 | key=f"tn {i}", 61 | ) 62 | M = st.number_input( 63 | label="M", 64 | min_value=5, 65 | value=int(max(5, L * 1e3)), 66 | help="number of nodes along the vessel", 67 | key=f"m {i}", 68 | ) 69 | Rd = st.number_input( 70 | "$R_{0d}$ $(m)$", 71 | min_value=0.0001, 72 | max_value=1.0, 73 | step=0.0001, 74 | value=0.001, 75 | format="%7.6f", 76 | help="distal radius", 77 | key=f"r0d {i}", 78 | ) 79 | Pext = st.number_input( 80 | "$P_{ext}$ $(Pa)$", 81 | value=0.0, 82 | step=1e3, 83 | format="%e", 84 | help="external pressure", 85 | key=f"pext {i}", 86 | ) 87 | 88 | gamma_profile = st.slider( 89 | "$\gamma_v$", 90 | min_value=2, 91 | max_value=9, 92 | help="velocity profile gamma value", 93 | key=f"gamma {i}", 94 | ) 95 | 96 | 97 | if sn == tn: 98 | raise ValueError("source node must be different than target node") 99 | 100 | v["sn"] = sn 101 | v["tn"] = tn 102 | v["L"] = L 103 | v["M"] = M 104 | v["Rp"] = Rp 105 | v["Rd"] = Rd 106 | v["E"] = E 107 | v["gamma profile"] = gamma_profile 108 | v["Pext"] = Pext 109 | 110 | if st.checkbox("outlet", key=f"outlet box {i}"): 111 | v["outlet"] = st.radio( 112 | "", 113 | options=["Rt", "wk2", "wk3"], 114 | index=2, 115 | horizontal=True, 116 | label_visibility="collapsed", 117 | key=f"outlet {i}", 118 | ) 119 | 120 | if v["outlet"] == "Rt": 121 | v["Rt"] = st.number_input( 122 | "$R_t$", 123 | min_value=0.0, 124 | max_value=1.0, 125 | step=0.1, 126 | help="reflection coefficient", 127 | key=f"rt {i}", 128 | ) 129 | elif v["outlet"] in ["wk2", "wk3"]: 130 | v["inlet_impedance_matching"] = st.checkbox(label="inlet_impedance_matching", value=False, key=f"inlet_impedance_matching {i}") 131 | c3, c4 = st.columns([1, 1]) 132 | with c3: 133 | v["R1"] = st.number_input( 134 | "$R_1$ $(Pa \cdot s \cdot m^{-3}$)", 135 | min_value=0.0, 136 | value=1e9, 137 | format="%e", 138 | help="proximal resistance", 139 | key=f"r1 {i}", 140 | ) 141 | if v["outlet"] == "wk3": 142 | v["R2"] = st.number_input( 143 | "$R_2$ $(Pa \cdot s \cdot m^{-3}$)", 144 | min_value=0.0, 145 | value=1e6, 146 | format="%e", 147 | help="distal resistance", 148 | key=f"r2 {i}", 149 | ) 150 | with c4: 151 | v["Cc"] = st.number_input( 152 | "$C_c$ $(m^3 \cdot Pa$)", 153 | min_value=0.0, 154 | value=1e-10, 155 | format="%e", 156 | help="compliance", 157 | key=f"cc {i}", 158 | ) 159 | 160 | return v 161 | -------------------------------------------------------------------------------- /docs/src/man/config.md: -------------------------------------------------------------------------------- 1 | Here is a description of the config file and its entries. You can also use openBF [webapp](https://openBF.streamlit.app) to quickly fill in config files. 2 | 3 | --- 4 | 5 | The first line in the configuration file contains the `project_name` variable. 6 | 7 | 8 | ```yaml 9 | project_name: "my_simulation_name" 10 | ``` 11 | 12 | This is a string that will be used to name the results folder. At the end of the simulation, all the results files will be found in `project_name_results/` directory. 13 | 14 | ```yaml 15 | inlet_file: "my_inlet.dat" 16 | ``` 17 | 18 | The inlet BC is given trough an ASCII file containing a list of values (volumetric flow rate) in time. For now, the inlet vessel is the one whose `sn` node is `1`. 19 | 20 | ```yaml 21 | output_directory: "put/results/in/this/directory/please" 22 | ``` 23 | 24 | You can specify where to save results, if not the default directory will be `./_results`. 25 | 26 | Following the `write_results` list is defined. 27 | 28 | ```yaml 29 | write_results: ["P"] # ["P", "Q", "u", "A"] 30 | ``` 31 | 32 | Here you can specify which quantities to write in the output files (`P`ressure [ $Pa$ ], `Q` flow [ $m^3 \cdot s^{-1}$ ], `u` velocity [ $m \cdot s^{-1}$ ] and `A`rea [ $m^2 $ ]). These are all optional but at least one is recommended. 33 | 34 | Then there are three main sections: `solver`, `blood`, and `network`. 35 | 36 | ## solver 37 | 38 | ```yaml 39 | solver: 40 | Ccfl: 0.9 41 | cycles: 100 42 | convergence_tolerance: 5.0 43 | jump: 100 44 | ``` 45 | 46 | It contains the values for the numerical scheme parameters: 47 | 48 | - `Ccfl` is the Courant's number used to compute the $\Delta t$ and it is usually taken equal to $0.9$. 49 | 50 | - `cycles` is the maximum number of cardiac cycles to be simulated. This is used to stop openBF execution in case of non-converging simulations. An openBF simulation usually takes less than 20 cardiac cycles to converge. 51 | 52 | - `convergence_tolerance` is the maximum error in $mmHg$ allowed between two consecutive cardiac cycle to claim convergence. 53 | 54 | - `jump` is the number of time-points to be saved in the result files. 55 | 56 | ## blood 57 | 58 | ```yaml 59 | blood: 60 | rho: 1060.0 61 | mu: 0.004 62 | ``` 63 | 64 | Blood rheological properties: 65 | 66 | - `mu` dynamic viscosity in $Pa \cdot s$; 67 | - `rho` density in $kg \cdot m^{-3}$. 68 | 69 | ## network 70 | 71 | This contains the list of vessels in the network. Each vessel has the following __mandatory__ properties: 72 | 73 | - `label` the vessel name that will be used to name result files; 74 | - `sn` segment source node; 75 | - `tn` segment target node; 76 | - `L` vessel lenght in $m$; 77 | - `E` wall Young's modulus in $Pa$; 78 | - `R0` or `Rp` and `Rd` describe the lumen radius. If `R0` is defined, the vessel is assumed to have a constant reference lumen radius; it `Rp` and `Rd` are specified, the vessel is set to taper linearly from the proximal lumen radius (i.e. `Rp`, the lumen radius at `sn`) to the distal lumen radius (i.e. `Rd`, the lumen radius at `tn`). 79 | 80 | __Optional__ parameters are: 81 | 82 | - `to_save` a boolean flag (default `true`) to tell openBF to save results for the current vessel; 83 | 84 | - `M` is the number of division along the vessels used to compute the artery $\Delta x$. When not specified, openBF automatically meshes the arteries so that $\Delta x$ is at least $1 mm$; 85 | 86 | - `Pext` vessel external pressure in $Pa$, default $0.0 Pa$; 87 | 88 | - `gamma_profile` is the radial velocity profile parameter used in the calculation of the viscous losses term, default $2$ (parabolic profile). 89 | 90 | 91 | ## Boundary conditions 92 | 93 | The system boundary conditions (BCs) are applied to inlet vessel(s) and outlet vessel(s). 94 | 95 | In the case a vessel outlet is not connected to any other vessel, an outlet BC must be assigned by imposing a reflection coefficient `Rt` or by coupling a _windkessel_ model. In case of `Rt`: 96 | 97 | - `Rt` -1.0 ≥ Rt ≤ 1.0 98 | 99 | In case of two-element windkessel: 100 | - `R1` peripheral resistance [ $Pa \cdot s \cdot m^{-3}$ ] 101 | - `Cc` peripheral compliance [ $m^3 \cdot Pa^{-1}$ ] 102 | 103 | In case of three-element windkessel: 104 | - `R1` first peripheral resistance [ $Pa \cdot s \cdot m^{-3}$ ] 105 | - `R2` second peripheral resistance [ $Pa \cdot s \cdot m^{-3}$ ] 106 | - `Cc` peripheral compliance [ $m^3 \cdot Pa^{-1}$ ] 107 | 108 | You can also enable `inlet_impedance_matching` to let openBF optimise `R1` at runtime. This will match the windkessel inlet impedance and minimise artificial reflections (recommended). Also optional (default $0.0 Pa$) is the windkessel outlet pressure `Pout`. 109 | 110 | ## Template 111 | 112 | The configuration file template is reported below. This contains all the mandatory and optional paramenter that can be specified in openBF. The parameter type is reported for each line after the #. 113 | 114 | ```yml 115 | project_name: # String 116 | inlet_file: .dat 117 | write_results: ["P"] # ["P", "Q", "u", "A"] 118 | output_directory: "put/results/in/this/directory/please" 119 | 120 | solver: 121 | Ccfl: # 0.0 < Ccfl ≤ 1.0; Float 122 | cycles: # Int 123 | convergence_tolerance: # Pressure, Float 124 | jump: # Int 125 | 126 | blood: 127 | mu: # [Pa⋅s]; Float 128 | rho: # [kg/m^3]; Float 129 | 130 | network: 131 | - label: # String 132 | to_save: true # Bool (default true) 133 | sn: # Int 134 | tn: # Int 135 | 136 | L: # [m]; Float 137 | M: # Int (optional) 138 | E: # [Pa]; Float 139 | h0: # [m]; Float (optional) 140 | 141 | R0: # [m]; Float 142 | #------ OR ------ to assign a linear tapering 143 | Rp: 144 | Rd: 145 | 146 | Pext: # [Pa]; Float (optional) 147 | 148 | gamma_profile: # ≥ 2.0; Float 149 | 150 | # outlet wk2 151 | R1: # [Pa⋅s⋅m^-3]; Float 152 | Cc: # [m^3⋅Pa^-1]; Float 153 | #------ OR ------ outlet wk3 154 | R1: 155 | R2: 156 | Cc: 157 | inlet_impedance_matching: true # Bool (default false) 158 | Pout: # [Pa]; Float 159 | #------ OR ------ outlet reflection 160 | Rt: # 1.0 ≤ Rt ≥ -1.0; Float 161 | ``` 162 | -------------------------------------------------------------------------------- /models/matthys2007/invitro_model_inlet.dat: -------------------------------------------------------------------------------- 1 | 0.0 3.9539646836e-06 2 | 0.004105005 1.13003248114e-05 3 | 0.00821001 2.32990641561e-05 4 | 0.012315015 3.91508781543e-05 5 | 0.01642002 5.72821878002e-05 6 | 0.020525025 7.57409322851e-05 7 | 0.02463003 9.27041788517e-05 8 | 0.028735035 0.000106941991208 9 | 0.03284004 0.000118097113261 10 | 0.036945045 0.000126700298466 11 | 0.04105005 0.000133925887222 12 | 0.045155055 0.000141173130267 13 | 0.04926006 0.000149609468794 14 | 0.053365065 0.000159817096107 15 | 0.05747007 0.000171643943436 16 | 0.061575075 0.000184290062924 17 | 0.06568008 0.000196584724369 18 | 0.069785085 0.000207353382021 19 | 0.07389009 0.000215754007447 20 | 0.077995095 0.000221482859813 21 | 0.0821001 0.000224800612802 22 | 0.086205105 0.000226391534029 23 | 0.09031011 0.000227119682997 24 | 0.094415115 0.00022777084959 25 | 0.09852012 0.000228861698246 26 | 0.102625125 0.000230564327707 27 | 0.10673013 0.000232749581519 28 | 0.110835135 0.000235112823855 29 | 0.11494014 0.000237324635572 30 | 0.119045145 0.00023915098574 31 | 0.12315015 0.000240508814757 32 | 0.127255155 0.000241452956454 33 | 0.13136016 0.000242116400402 34 | 0.135465165 0.000242638661332 35 | 0.13957017 0.000243113540946 36 | 0.143675175 0.000243571821106 37 | 0.14778018 0.000243994980847 38 | 0.151885185 0.000244342016678 39 | 0.15599019 0.00024456863201 40 | 0.160095195 0.000244626599675 41 | 0.1642002 0.000244445824433 42 | 0.168305205 0.000243914649311 43 | 0.17241021 0.000242878351449 44 | 0.176515215 0.000241168825448 45 | 0.18062022 0.000238662900543 46 | 0.184725225 0.000235349667476 47 | 0.18883023 0.000231376925929 48 | 0.192935235 0.000227049226512 49 | 0.19704024 0.000222765518969 50 | 0.201145245 0.000218907814467 51 | 0.20525025 0.000215714269833 52 | 0.209355255 0.000213181222885 53 | 0.21346026 0.000211033242135 54 | 0.217565265 0.000208778900078 55 | 0.22167027 0.000205839957338 56 | 0.225775275 0.000201714137174 57 | 0.22988028 0.00019611752357 58 | 0.233985285 0.000189057983098 59 | 0.23809029 0.000180814681626 60 | 0.242195295 0.000171832337044 61 | 0.2463003 0.000162569754606 62 | 0.250405305 0.000153358506584 63 | 0.25451031 0.000144322769462 64 | 0.258615315 0.000135386853455 65 | 0.26272032 0.000126362132316 66 | 0.266825325 0.000117073500877 67 | 0.27093033 0.000107469809212 68 | 0.275035335 9.76696078441e-05 69 | 0.27914034 8.79208027816e-05 70 | 0.283245345 7.84899813899e-05 71 | 0.28735035 6.95293140826e-05 72 | 0.291455355 6.0982486342e-05 73 | 0.29556036 5.25793244802e-05 74 | 0.299665365 4.39347713926e-05 75 | 0.30377037 3.47239368357e-05 76 | 0.307875375 2.48682130252e-05 77 | 0.31198038 1.46534173784e-05 78 | 0.316085385 4.71732957275e-06 79 | 0.32019039 -4.11271270163e-06 80 | 0.324295395 -1.10954901075e-05 81 | 0.3284004 -1.58795907069e-05 82 | 0.332505405 -1.87275499605e-05 83 | 0.33661041 -2.05674024431e-05 84 | 0.340715415 -2.28278007723e-05 85 | 0.34482042 -2.70819750339e-05 86 | 0.348925425 -3.45921655651e-05 87 | 0.35303043 -4.58868425729e-05 88 | 0.357135435 -6.05029041065e-05 89 | 0.36124044 -7.69823061209e-05 90 | 0.365345445 -9.31397004773e-05 91 | 0.36945045 -0.000106537430207 92 | 0.373555455 -0.000115042181184 93 | 0.37766046 -0.000117313413117 94 | 0.381765465 -0.000113094701096 95 | 0.38587047 -0.000103237941369 96 | 0.389975475 -8.94676783096e-05 97 | 0.39408048 -7.39640056432e-05 98 | 0.398185485 -5.8886036092e-05 99 | 0.40229049 -4.59622869383e-05 100 | 0.406395495 -3.62412672635e-05 101 | 0.4105005 -3.00387644365e-05 102 | 0.414605505 -2.70580376168e-05 103 | 0.41871051 -2.66148001189e-05 104 | 0.422815515 -2.78826693741e-05 105 | 0.42692052 -3.00880084509e-05 106 | 0.431025525 -3.26168343363e-05 107 | 0.43513053 -3.50357066707e-05 108 | 0.439235535 -3.70581923591e-05 109 | 0.44334054 -3.84991147275e-05 110 | 0.447445545 -3.92493863455e-05 111 | 0.45155055 -3.92819141366e-05 112 | 0.455655555 -3.86754745862e-05 113 | 0.45976056 -3.76296084313e-05 114 | 0.463865565 -3.64453752918e-05 115 | 0.46797057 -3.54628232148e-05 116 | 0.472075575 -3.49684645732e-05 117 | 0.47618058 -3.5104272376e-05 118 | 0.480285585 -3.58148968235e-05 119 | 0.48439059 -3.68587538045e-05 120 | 0.488495595 -3.78852074137e-05 121 | 0.4926006 -3.85536283675e-05 122 | 0.496705605 -3.865170146e-05 123 | 0.50081061 -3.81681025055e-05 124 | 0.504915615 -3.72903195326e-05 125 | 0.50902062 -3.63264284671e-05 126 | 0.513125625 -3.55792945239e-05 127 | 0.51723063 -3.52211813635e-05 128 | 0.521335635 -3.52180248396e-05 129 | 0.52544064 -3.53345993956e-05 130 | 0.529545645 -3.52210200783e-05 131 | 0.53365065 -3.45492258849e-05 132 | 0.537755655 -3.31477007093e-05 133 | 0.54186066 -3.10819317247e-05 134 | 0.545965665 -2.86477063483e-05 135 | 0.55007067 -2.62771135791e-05 136 | 0.554175675 -2.43906032501e-05 137 | 0.55828068 -2.32497419875e-05 138 | 0.562385685 -2.28659912349e-05 139 | 0.56649069 -2.30003702658e-05 140 | 0.570595695 -2.32548588876e-05 141 | 0.5747007 -2.32217444471e-05 142 | 0.578805705 -2.26350947278e-05 143 | 0.58291071 -2.14676548644e-05 144 | 0.587015715 -1.99371572704e-05 145 | 0.59112072 -1.84204371187e-05 146 | 0.595225725 -1.73086953819e-05 147 | 0.59933073 -1.68593377446e-05 148 | 0.603435735 -1.71005724724e-05 149 | 0.60754074 -1.782413815e-05 150 | 0.611645745 -1.86672625431e-05 151 | 0.61575075 -1.92505515262e-05 152 | 0.619855755 -1.93173409296e-05 153 | 0.62396076 -1.8820316963e-05 154 | 0.628065765 -1.79227414728e-05 155 | 0.63217077 -1.69158858524e-05 156 | 0.636275775 -1.60877320512e-05 157 | 0.64038078 -1.55973671795e-05 158 | 0.644485785 -1.54070188551e-05 159 | 0.64859079 -1.53002148147e-05 160 | 0.652695795 -1.49793305393e-05 161 | 0.6568008 -1.42028399255e-05 162 | 0.660905805 -1.29052225347e-05 163 | 0.66501081 -1.12480025159e-05 164 | 0.669115815 -9.57706405118e-06 165 | 0.67322082 -8.29895615967e-06 166 | 0.677325825 -7.72250395284e-06 167 | 0.68143083 -7.9280262216e-06 168 | 0.685535835 -8.71784058747e-06 169 | 0.68964084 -9.67117702722e-06 170 | 0.693745845 -1.02856380154e-05 171 | 0.69785085 -1.01520082175e-05 172 | 0.701955855 -9.09390935831e-06 173 | 0.70606086 -7.21544237924e-06 174 | 0.710165865 -4.83501670721e-06 175 | 0.71427087 -2.32903229396e-06 176 | 0.718375875 5.2745007285e-08 177 | 0.72248088 2.32300148449e-06 178 | 0.726585885 4.78170077282e-06 179 | 0.73069089 7.90861468422e-06 180 | 0.734795895 1.2154454757e-05 181 | 0.7389009 1.77051761881e-05 182 | 0.743005905 2.43116036327e-05 183 | 0.74711091 3.125956694e-05 184 | 0.751215915 3.7508604135e-05 185 | 0.75532092 4.19661062608e-05 186 | 0.759425925 4.38108383161e-05 187 | 0.76353093 4.27554074592e-05 188 | 0.767635935 3.91521133135e-05 189 | 0.77174094 3.38972687527e-05 190 | 0.775845945 2.81586857861e-05 191 | 0.77995095 2.30150295928e-05 192 | 0.784055955 1.91306298919e-05 193 | 0.78816096 1.65812609979e-05 194 | 0.792265965 1.48965870967e-05 195 | 0.79637097 1.33097634039e-05 196 | 0.800475975 1.11301090358e-05 197 | 0.80458098 8.10743333146e-06 198 | 0.808685985 4.65417907992e-06 199 | 0.81279099 1.83625730461e-06 200 | 0.816895995 1.12091227885e-06 201 | 0.821001 3.9539646836e-06 202 | -------------------------------------------------------------------------------- /docs/src/index.md: -------------------------------------------------------------------------------- 1 | # openBF 2 | 3 | openBF is an open-source 1D blood flow solver based on MUSCL finite-volume numerical scheme, written in [Julia](https://julialang.org/downloads/) and released under [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0) free software license. 4 | 5 | openBF has been developed by [Dr. A. Melis](https://alemel.is) under the supervision of [Dr. A. Marzo](https://www.sheffield.ac.uk/mecheng/academic-staff/alberto-marzo) as part of the PhD project on cardiovascular modelling at [INSIGNEO](https://www.sheffield.ac.uk/insigneo) Institute, Department of Mechanical Engineering of The University of Sheffield. All the contributors are listed on [github](https://github.com/INSIGNEO/openBF/graphs/contributors). 6 | 7 | The accompaigning [PhD Thesis](https://etheses.whiterose.ac.uk/19175/) contains the relevant theoretical background and the explanation of the numerical scheme implemented. A multiscale validation study is presented in [this](https://iopscience.iop.org/article/10.1088/1361-6579/ad9663) paper. A shorter backgound introduction is given in the [Overview](man/overview.md) page. 8 | 9 | Head over to the [Quickstart](man/quickstart.md) section for installation and running instructions. 10 | 11 | ## Publications 12 | 13 | openBF has been used in the following works: 14 | 15 | - Benemerito I, Melis A, Wehenkel A, Marzo A. [openBF: an open-source finite volume 1D blood flow solver](https://iopscience.iop.org/article/10.1088/1361-6579/ad9663), _Physiological Measurement_, 2024. DOI: 10.1088/1361-6579-ad9663 16 | 17 | - Wang N, Benemerito I, Sourbron S, Marzo A. [An in silico modelling approach to predict haemodynamic outcomes in diabetic and hypertensive kidney disease](https://link.springer.com/article/10.1007/s10439-024-03573-2), _Annals of Biomedical Engineering_, 2024. DOI: 10.1007/s10439-024-03573-2 18 | 19 | - Benemerito I, Mustafa A, Wang N, Narata AP, Narracott A, Marzo A. [A multiscale computational framework to evaluate flow alterations during mechanical thrombectomy for treatment of ischaemic stroke](https://www.frontiersin.org/articles/10.3389/fcvm.2023.1117449/full), _Frontiers in Cardiovascular Medicine_, 2023. DOI: 10.3389/fcvm.2023.1117449 20 | 21 | - Wehenkel A, Behrmann J, Miller AC, Sapiro G, Sener O, Cuturi M, Jacobsen JH. [Simulation-based inference for cardiovascular models](https://arxiv.org/abs/2307.13918), _arXiv_, 2023. 22 | 23 | - Lahtinen J, Moura F, Samavaki M, Siltanen S, Pursiainen S. [In silico study of the effects of cerebral circulation on source localization using a dynamical anatomical atlas of the human head](https://iopscience.iop.org/article/10.1088/1741-2552/acbdc1), _Journal of Neural Engineering_, 2023. DOI: 10.1088/1741-2552/acbdc1 24 | 25 | - Ning W, Sharma K, Sourbron SP, Benemerito I, Marzo A. [Distinguishing hypertensive renal injury from diabetic nephropathy using MR imaging and computational modelling of renal blood flow](https://vph-conference.org/), _VPH2022_ September 2022, Porto, PO _In proceedings_ 26 | 27 | - Benemerito I, Narata AP, Narracott A, Marzo A. [Determining clinically-viable biomarkers for ischaemic stroke through a mechanistic and machine learning approach](https://link.springer.com/article/10.1007/s10439-022-02956-7), _Annals of Biomedical Engineering_, 2022. DOI: 10.1007/s10439-022-02956-7 28 | 29 | - Moura F, Beraldo RG, Ferreira LA, Siltanen S. [Anatomical atlas of the upper part of the human head for electroencephalography and bioimpedance applications](https://iopscience.iop.org/article/10.1088/1361-6579/ac3218), _Physiological Measurement_, 2021. DOI: 10.1088/1361-6579/ac3218. 30 | 31 | - Mustafa A. [An efficient computational approach to guide intervention in treatment of stroke](https://etheses.whiterose.ac.uk/29992/), _PhD Thesis_, 2021 32 | 33 | - Benemerito I, Jordan B, Mustafa A, Marzo A. [Quantification of the effects of ageing, hypertension and atherosclerosis on flow reversal during a mechanical thrombectomy procedure](https://www.sheffield.ac.uk/insigneo/overview/events/biomedeng-2021-conference), _BioMedEng21_ September 2021, Sheffield, UK _In proceedings_ 34 | 35 | - Benemerito I, Narata AP, Narracott A, Marzo A. [Pulsatility indices can inform on distal perfusion following ischaemic stroke](https://www.cmbbe-symposium.com/2021/wp-content/uploads/sites/2/2021/09/Program-CMBBE21-A4.qxp_Detailed.pdf), _CMMBE_ September 2021, Online event, _In proceedings_ 36 | 37 | - Benemerito I, Narata AP, Narracott A, Marzo A. [Identification of biomarkers for perfusion following an ischaemic event](https://cbmc21.vfairs.com/), _CMBE_ September 2021, Online event, _In proceedings_ 38 | 39 | - Mercuri M, Wustmann K, von Tengg-Kobligk H, Goksu C, Hose DR, Narracott A. [Subject-specific simulation for non-invasive assessment of aortic coarctation: towards a translational approach](https://www.sciencedirect.com/science/article/pii/S1350453319302449), _Medical Engineering & Physics_, 2020. DOI: 10.1016/j.medengphy.2019.12.003 40 | 41 | - Melis A, Moura F, Larrabide I, Janot K, Clayton RH, Narata AP, Marzo A. [Improved biomechanical metrics of cerebral vasospasm identified via sensitivity analysis of a 1D cerebral circulation model](https://www.sciencedirect.com/science/article/pii/S0021929019302830), _Journal of Biomechanics_, 2019. DOI: 10.1016/j.biomech.2019.04.019 42 | 43 | - Melis A. [Gaussian process emulators for 1D vascular models](http://etheses.whiterose.ac.uk/19175/), _PhD Thesis_, 2017. 44 | 45 | - Melis A, Clayton RH, Marzo A. [Bayesian sensitivity analysis of a 1D vascular model with Gaussian process emulators](http://rdcu.be/AqLm). _International Journal for Numerical Methods in Biomedical Engineering_, 2017. DOI: 10.1002/cnm.2882 46 | 47 | - Melis A, Clayton RH, Marzo A. [A more efficient approach to perform sensitivity analyses in 0D/1D cardiovascular models](http://www.compbiomed.net/2015/cmbe-proceedings.htm), _CMBE_ July 2015, Cachan, FR. _In proceedings_ 48 | 49 | Have you used openBF for your research? Let us know! 50 | 51 | ## Cite 52 | 53 | If you find openBF useful in your work, we kindly request that you cite the following figshare repository 54 | 55 | ```bibtex 56 | @misc{openBF.jl-2018, 57 | title={openBF: Julia software for 1D blood flow modelling}, 58 | url={https://figshare.com/articles/openBF_Julia_software_for_1D_blood_flow_modelling/7166183/1}, 59 | DOI={10.15131/shef.data.7166183}, 60 | abstractNote={ 61 | openBF is an open-source 1D blood flow solver based on MUSCL finite-volume numerical scheme, written in Julia and released under Apache 2.0 free software license. 62 | 63 | See https://github.com/INSIGNEO/openBF for the git repository and https://insigneo.github.io/openBF/ for the documentation. 64 | }, 65 | publisher={figshare}, 66 | author={Melis, Alessandro}, 67 | year={2018}, 68 | month={Oct}} 69 | ``` 70 | 71 | and the accompaining PhD thesis 72 | 73 | ```bibtex 74 | @phdthesis{wreo19175, 75 | month = {August}, 76 | title = {Gaussian process emulators for 1D vascular models}, 77 | school = {University of Sheffield}, 78 | author = {Alessandro Melis}, 79 | publisher = {University of Sheffield}, 80 | year = {2017}, 81 | url = {https://etheses.whiterose.ac.uk/19175/}, 82 | } 83 | ``` 84 | -------------------------------------------------------------------------------- /models/alastruey2007/circle_of_willis.yaml: -------------------------------------------------------------------------------- 1 | project_name: circle_of_willis 2 | write_results: ["P", "u"] 3 | blood: 4 | rho: 1060.0 5 | mu: 0.004 6 | solver: 7 | Ccfl: 0.9 8 | cycles: 100 9 | jump: 100 10 | convergence_tolerance: 1.0 11 | network: 12 | - label: 1-Ascendingaorta 13 | sn: 1 14 | tn: 2 15 | L: 0.04 16 | E: 400000.0 17 | M: 40 18 | Rp: 0.012 19 | Rd: 0.012 20 | gamma profile: 9 21 | - label: 2-AorticarchI 22 | sn: 2 23 | tn: 3 24 | L: 0.02 25 | E: 400000.0 26 | M: 20 27 | Rp: 0.0112 28 | Rd: 0.0112 29 | gamma profile: 9 30 | - label: 3-Brachiocephalic 31 | sn: 2 32 | tn: 4 33 | L: 0.034 34 | E: 400000.0 35 | M: 34 36 | Rp: 0.0062 37 | Rd: 0.0062 38 | gamma profile: 9 39 | - label: 4-AorticarchII 40 | sn: 3 41 | tn: 5 42 | L: 0.039 43 | E: 400000.0 44 | M: 39 45 | Rp: 0.0107 46 | Rd: 0.0107 47 | gamma profile: 9 48 | - label: 5-L-commoncarotid 49 | sn: 3 50 | tn: 6 51 | L: 0.208 52 | E: 400000.0 53 | M: 208 54 | Rp: 0.0025 55 | Rd: 0.0025 56 | gamma profile: 9 57 | - label: 6-R-commoncarotid 58 | sn: 4 59 | tn: 7 60 | L: 0.177 61 | E: 400000.0 62 | M: 177 63 | Rp: 0.0025 64 | Rd: 0.0025 65 | gamma profile: 9 66 | - label: 7-R-subclavian 67 | sn: 4 68 | tn: 8 69 | L: 0.034 70 | E: 400000.0 71 | M: 34 72 | Rp: 0.00423 73 | Rd: 0.00423 74 | gamma profile: 9 75 | - label: 8-Thoracicaorta 76 | sn: 5 77 | tn: 9 78 | L: 0.156 79 | E: 400000.0 80 | M: 156 81 | Rp: 0.00999 82 | Rd: 0.00999 83 | outlet: wk3 84 | R1: 180000000.0 85 | Cc: 3.87e-09 86 | gamma profile: 9 87 | - label: 9-L-subclavian 88 | sn: 5 89 | tn: 10 90 | L: 0.034 91 | E: 400000.0 92 | M: 34 93 | Rp: 0.00423 94 | Rd: 0.00423 95 | gamma profile: 9 96 | - label: 10-L-ext-carotid 97 | sn: 6 98 | tn: 11 99 | L: 0.177 100 | E: 800000.0 101 | M: 177 102 | Rp: 0.0015 103 | Rd: 0.0015 104 | outlet: wk3 105 | R1: 5430000000.0 106 | Cc: 1.27e-10 107 | gamma profile: 9 108 | - label: 11-L-int-carotidI 109 | sn: 6 110 | tn: 12 111 | L: 0.177 112 | E: 800000.0 113 | M: 177 114 | Rp: 0.002 115 | Rd: 0.002 116 | gamma profile: 9 117 | - label: 12-R-int-carotidI 118 | sn: 7 119 | tn: 13 120 | L: 0.177 121 | E: 800000.0 122 | M: 177 123 | Rp: 0.002 124 | Rd: 0.002 125 | gamma profile: 9 126 | - label: 13-R-ext-carotid 127 | sn: 7 128 | tn: 14 129 | L: 0.177 130 | E: 800000.0 131 | M: 177 132 | Rp: 0.0015 133 | Rd: 0.0015 134 | outlet: wk3 135 | R1: 5430000000.0 136 | Cc: 1.27e-10 137 | gamma profile: 9 138 | - label: 14-R-vertebral 139 | sn: 8 140 | tn: 15 141 | L: 0.148 142 | E: 800000.0 143 | M: 148 144 | Rp: 0.00136 145 | Rd: 0.00136 146 | gamma profile: 9 147 | - label: 15-R-brachial 148 | sn: 8 149 | tn: 16 150 | L: 0.422 151 | E: 400000.0 152 | M: 422 153 | Rp: 0.00403 154 | Rd: 0.00403 155 | outlet: wk3 156 | R1: 2680000000.0 157 | Cc: 2.58e-10 158 | gamma profile: 9 159 | - label: 16-L-brachial 160 | sn: 10 161 | tn: 17 162 | L: 0.422 163 | E: 400000.0 164 | M: 422 165 | Rp: 0.00403 166 | Rd: 0.00403 167 | outlet: wk3 168 | R1: 2680000000.0 169 | Cc: 2.58e-10 170 | gamma profile: 9 171 | - label: 17-L-vertebral 172 | sn: 10 173 | tn: 15 174 | L: 0.148 175 | E: 800000.0 176 | M: 148 177 | Rp: 0.00136 178 | Rd: 0.00136 179 | gamma profile: 9 180 | - label: 18-L-int-carotidII 181 | sn: 12 182 | tn: 18 183 | L: 0.005 184 | E: 1600000.0 185 | M: 5 186 | Rp: 0.002 187 | Rd: 0.002 188 | gamma profile: 9 189 | - label: 19-L-PCoA 190 | sn: 19 191 | tn: 12 192 | L: 0.015 193 | E: 1600000.0 194 | M: 15 195 | Rp: 0.00073 196 | Rd: 0.00073 197 | gamma profile: 9 198 | - label: 20-R-PCoA 199 | sn: 20 200 | tn: 13 201 | L: 0.015 202 | E: 1600000.0 203 | M: 15 204 | Rp: 0.00073 205 | Rd: 0.00073 206 | gamma profile: 9 207 | - label: 21-R-int-carotidII 208 | sn: 13 209 | tn: 21 210 | L: 0.005 211 | E: 1600000.0 212 | M: 5 213 | Rp: 0.002 214 | Rd: 0.002 215 | gamma profile: 9 216 | - label: 22-Basilar 217 | sn: 15 218 | tn: 22 219 | L: 0.029 220 | E: 1600000.0 221 | M: 28 222 | Rp: 0.00162 223 | Rd: 0.00162 224 | gamma profile: 9 225 | - label: 23-L-MCA 226 | sn: 18 227 | tn: 23 228 | L: 0.119 229 | E: 1600000.0 230 | M: 119 231 | Rp: 0.00143 232 | Rd: 0.00143 233 | outlet: wk3 234 | R1: 5970000000.0 235 | Cc: 1.16e-10 236 | gamma profile: 9 237 | - label: 24-R-MCA 238 | sn: 21 239 | tn: 24 240 | L: 0.119 241 | E: 1600000.0 242 | M: 119 243 | Rp: 0.00143 244 | Rd: 0.00143 245 | outlet: wk3 246 | R1: 5970000000.0 247 | Cc: 1.16e-10 248 | gamma profile: 9 249 | - label: 25-L-ACAA1 250 | sn: 18 251 | tn: 25 252 | L: 0.012 253 | E: 1600000.0 254 | M: 12 255 | Rp: 0.00117 256 | Rd: 0.00117 257 | gamma profile: 9 258 | - label: 26-R-ACAA1 259 | sn: 21 260 | tn: 26 261 | L: 0.012 262 | E: 1600000.0 263 | M: 12 264 | Rp: 0.00117 265 | Rd: 0.00117 266 | gamma profile: 9 267 | - label: 27-L-PCAP1 268 | sn: 22 269 | tn: 19 270 | L: 0.005 271 | E: 1600000.0 272 | M: 5 273 | Rp: 0.00107 274 | Rd: 0.00107 275 | gamma profile: 9 276 | - label: 28-R-PCA-P1 277 | sn: 22 278 | tn: 20 279 | L: 0.005 280 | E: 1600000.0 281 | M: 5 282 | Rp: 0.00107 283 | Rd: 0.00107 284 | gamma profile: 9 285 | - label: 29-L-ACA-A2 286 | sn: 25 287 | tn: 27 288 | L: 0.103 289 | E: 1600000.0 290 | M: 103 291 | Rp: 0.0012 292 | Rd: 0.0012 293 | outlet: wk3 294 | R1: 8480000000.0 295 | Cc: 8.2e-11 296 | gamma profile: 9 297 | - label: 30-R-ACA-A2 298 | sn: 26 299 | tn: 28 300 | L: 0.103 301 | E: 1600000.0 302 | M: 103 303 | Rp: 0.0012 304 | Rd: 0.0012 305 | outlet: wk3 306 | R1: 8480000000.0 307 | Cc: 8.2e-11 308 | gamma profile: 9 309 | - label: 31-ACoA 310 | sn: 25 311 | tn: 26 312 | L: 0.003 313 | E: 1600000.0 314 | M: 5 315 | Rp: 0.00074 316 | Rd: 0.00074 317 | gamma profile: 9 318 | - label: 32-L-PCA-P2 319 | sn: 19 320 | tn: 29 321 | L: 0.086 322 | E: 1600000.0 323 | M: 86 324 | Rp: 0.00105 325 | Rd: 0.00105 326 | outlet: wk3 327 | R1: 11080000000.0 328 | Cc: 6.2e-11 329 | gamma profile: 9 330 | - label: 33-R-PCA-P2 331 | sn: 20 332 | tn: 30 333 | L: 0.086 334 | E: 1600000.0 335 | M: 86 336 | Rp: 0.00105 337 | Rd: 0.00105 338 | outlet: wk3 339 | R1: 11080000000.0 340 | Cc: 6.2e-11 341 | gamma profile: 9 342 | -------------------------------------------------------------------------------- /models/matthys2007/invitro_model.yaml: -------------------------------------------------------------------------------- 1 | project_name: invitro_model 2 | write_results: ["P", "Q"] 3 | blood: 4 | rho: 1050.0 5 | mu: 0.0025 6 | solver: 7 | Ccfl: 0.9 8 | cycles: 100 9 | jump: 100 10 | convergence_tolerance: 1.0 11 | network: 12 | - label: v1 13 | sn: 1 14 | tn: 2 15 | L: 0.036 16 | E: 683224.72873 17 | M: 36 18 | Rp: 0.0144 19 | Rd: 0.013 20 | gamma profile: 9 21 | - label: v2 22 | sn: 2 23 | tn: 3 24 | L: 0.028 25 | E: 689627.056087 26 | M: 28 27 | Rp: 0.011 28 | Rd: 0.00729 29 | gamma profile: 9 30 | - label: v3 31 | sn: 3 32 | tn: 4 33 | L: 0.145 34 | E: 701344.643961 35 | M: 145 36 | Rp: 0.00537 37 | Rd: 0.00386 38 | outlet: wk3 39 | R1: 2670000000.0 40 | Cc: 1e-13 41 | gamma profile: 9 42 | - label: v4 43 | sn: 3 44 | tn: 5 45 | L: 0.218 46 | E: 685437.626959 47 | M: 218 48 | Rp: 0.00436 49 | Rd: 0.00334 50 | gamma profile: 9 51 | - label: v5 52 | sn: 5 53 | tn: 6 54 | L: 0.165 55 | E: 672370.044545 56 | M: 165 57 | Rp: 0.00334 58 | Rd: 0.00278 59 | gamma profile: 9 60 | - label: v6 61 | sn: 6 62 | tn: 7 63 | L: 0.235 64 | E: 676958.952069 65 | M: 235 66 | Rp: 0.00207 67 | Rd: 0.00207 68 | outlet: wk3 69 | R1: 3920000000.0 70 | Cc: 1e-13 71 | gamma profile: 9 72 | - label: v7 73 | sn: 6 74 | tn: 8 75 | L: 0.177 76 | E: 689695.573386 77 | M: 177 78 | Rp: 0.0021 79 | Rd: 0.0021 80 | outlet: wk3 81 | R1: 3240000000.0 82 | Cc: 1e-13 83 | gamma profile: 9 84 | - label: v8 85 | sn: 2 86 | tn: 9 87 | L: 0.021 88 | E: 676746.681416 89 | M: 21 90 | Rp: 0.013 91 | Rd: 0.0125 92 | gamma profile: 9 93 | - label: v9 94 | sn: 9 95 | tn: 10 96 | L: 0.178 97 | E: 706203.082009 98 | M: 178 99 | Rp: 0.00558 100 | Rd: 0.00373 101 | outlet: wk3 102 | R1: 3110000000.0 103 | Cc: 1e-13 104 | gamma profile: 9 105 | - label: v10 106 | sn: 9 107 | tn: 11 108 | L: 0.029 109 | E: 671553.78194 110 | M: 29 111 | Rp: 0.0125 112 | Rd: 0.0118 113 | gamma profile: 9 114 | - label: v11 115 | sn: 11 116 | tn: 12 117 | L: 0.227 118 | E: 698554.184936 119 | M: 227 120 | Rp: 0.00442 121 | Rd: 0.00339 122 | gamma profile: 9 123 | - label: v12 124 | sn: 12 125 | tn: 13 126 | L: 0.175 127 | E: 698549.765792 128 | M: 175 129 | Rp: 0.00339 130 | Rd: 0.00284 131 | gamma profile: 9 132 | - label: v13 133 | sn: 13 134 | tn: 14 135 | L: 0.245 136 | E: 684480.692899 137 | M: 245 138 | Rp: 0.00207 139 | Rd: 0.00207 140 | outlet: wk3 141 | R1: 3740000000.0 142 | Cc: 1e-13 143 | gamma profile: 9 144 | - label: v14 145 | sn: 13 146 | tn: 15 147 | L: 0.191 148 | E: 694061.608164 149 | M: 191 150 | Rp: 0.00207 151 | Rd: 0.00207 152 | outlet: wk3 153 | R1: 3770000000.0 154 | Cc: 1e-13 155 | gamma profile: 9 156 | - label: v15 157 | sn: 11 158 | tn: 16 159 | L: 0.056 160 | E: 683145.847472 161 | M: 56 162 | Rp: 0.0118 163 | Rd: 0.011 164 | gamma profile: 9 165 | - label: v16 166 | sn: 16 167 | tn: 17 168 | L: 0.195 169 | E: 684853.806986 170 | M: 195 171 | Rp: 0.00412 172 | Rd: 0.00322 173 | outlet: wk3 174 | R1: 2590000000.0 175 | Cc: 1e-13 176 | gamma profile: 9 177 | - label: v17 178 | sn: 16 179 | tn: 18 180 | L: 0.072 181 | E: 675178.969386 182 | M: 72 183 | Rp: 0.011 184 | Rd: 0.00926 185 | gamma profile: 9 186 | - label: v18 187 | sn: 18 188 | tn: 19 189 | L: 0.038 190 | E: 678030.939641 191 | M: 38 192 | Rp: 0.00397 193 | Rd: 0.00397 194 | gamma profile: 9 195 | - label: v19 196 | sn: 19 197 | tn: 20 198 | L: 0.013 199 | E: 680213.764316 200 | M: 13 201 | Rp: 0.00431 202 | Rd: 0.00431 203 | gamma profile: 9 204 | - label: v20 205 | sn: 20 206 | tn: 21 207 | L: 0.191 208 | E: 655677.818214 209 | M: 191 210 | Rp: 0.00183 211 | Rd: 0.00183 212 | outlet: wk3 213 | R1: 3540000000.0 214 | Cc: 1e-13 215 | gamma profile: 9 216 | - label: v21 217 | sn: 20 218 | tn: 22 219 | L: 0.198 220 | E: 702496.708576 221 | M: 198 222 | Rp: 0.00192 223 | Rd: 0.00192 224 | outlet: wk3 225 | R1: 4240000000.0 226 | Cc: 1e-13 227 | gamma profile: 9 228 | - label: v22 229 | sn: 19 230 | tn: 23 231 | L: 0.186 232 | E: 679062.295831 233 | M: 186 234 | Rp: 0.00331 235 | Rd: 0.00289 236 | outlet: wk3 237 | R1: 3750000000.0 238 | Cc: 1e-13 239 | gamma profile: 9 240 | - label: v23 241 | sn: 18 242 | tn: 24 243 | L: 0.062 244 | E: 675509.6448 245 | M: 62 246 | Rp: 0.00926 247 | Rd: 0.00801 248 | gamma profile: 9 249 | - label: v24 250 | sn: 24 251 | tn: 25 252 | L: 0.12 253 | E: 661516.470398 254 | M: 120 255 | Rp: 0.00259 256 | Rd: 0.00259 257 | outlet: wk3 258 | R1: 3460000000.0 259 | Cc: 1e-13 260 | gamma profile: 9 261 | - label: v25 262 | sn: 24 263 | tn: 26 264 | L: 0.007 265 | E: 681713.317604 266 | M: 7 267 | Rp: 0.0079 268 | Rd: 0.0079 269 | gamma profile: 9 270 | - label: v26 271 | sn: 26 272 | tn: 27 273 | L: 0.118 274 | E: 684061.941605 275 | M: 118 276 | Rp: 0.00255 277 | Rd: 0.00255 278 | outlet: wk3 279 | R1: 3450000000.0 280 | Cc: 1e-13 281 | gamma profile: 9 282 | - label: v27 283 | sn: 26 284 | tn: 28 285 | L: 0.104 286 | E: 687436.089311 287 | M: 104 288 | Rp: 0.0078 289 | Rd: 0.00588 290 | gamma profile: 9 291 | - label: v28 292 | sn: 28 293 | tn: 29 294 | L: 0.205 295 | E: 692444.986296 296 | M: 205 297 | Rp: 0.0039 298 | Rd: 0.00338 299 | gamma profile: 9 300 | - label: v29 301 | sn: 29 302 | tn: 30 303 | L: 0.216 304 | E: 714263.751693 305 | M: 216 306 | Rp: 0.00338 307 | Rd: 0.00231 308 | gamma profile: 9 309 | - label: v30 310 | sn: 30 311 | tn: 31 312 | L: 0.206 313 | E: 665179.173719 314 | M: 206 315 | Rp: 0.00231 316 | Rd: 0.0021 317 | gamma profile: 9 318 | - label: v31 319 | sn: 28 320 | tn: 32 321 | L: 0.201 322 | E: 688672.654228 323 | M: 201 324 | Rp: 0.00402 325 | Rd: 0.00334 326 | gamma profile: 9 327 | - label: v32 328 | sn: 32 329 | tn: 33 330 | L: 0.195 331 | E: 713776.539748 332 | M: 195 333 | Rp: 0.00334 334 | Rd: 0.00226 335 | gamma profile: 9 336 | - label: v33 337 | sn: 33 338 | tn: 34 339 | L: 0.207 340 | E: 688122.521471 341 | M: 207 342 | Rp: 0.00226 343 | Rd: 0.00212 344 | gamma profile: 9 345 | - label: v34 346 | sn: 31 347 | tn: 35 348 | L: 0.163 349 | E: 658738.249745 350 | M: 163 351 | Rp: 0.00155 352 | Rd: 0.00155 353 | outlet: wk3 354 | R1: 5160000000.0 355 | Cc: 1e-13 356 | gamma profile: 9 357 | - label: v35 358 | sn: 31 359 | tn: 36 360 | L: 0.151 361 | E: 676978.372391 362 | M: 151 363 | Rp: 0.00153 364 | Rd: 0.00153 365 | outlet: wk3 366 | R1: 5650000000.0 367 | Cc: 1e-13 368 | gamma profile: 9 369 | - label: v36 370 | sn: 34 371 | tn: 37 372 | L: 0.149 373 | E: 667185.529175 374 | M: 149 375 | Rp: 0.00158 376 | Rd: 0.00158 377 | outlet: wk3 378 | R1: 4590000000.0 379 | Cc: 1e-13 380 | gamma profile: 9 381 | - label: v37 382 | sn: 34 383 | tn: 38 384 | L: 0.126 385 | E: 676820.268487 386 | M: 126 387 | Rp: 0.00155 388 | Rd: 0.00155 389 | outlet: wk3 390 | R1: 3160000000.0 391 | Cc: 1e-13 392 | gamma profile: 9 393 | -------------------------------------------------------------------------------- /src/simulation.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Copyright 2015-2024 INSIGNEO Institute for in silico Medicine 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | =# 16 | 17 | 18 | # -------------------- deprecated ???? ----------------------------------------- 19 | function compute_pressure(n::Network) 20 | compute_pressure.(values(n.vessels), Ref(n.blood.rho), Ref("temp")) 21 | compute_pressure.(values(n.vessels), Ref(n.blood.rho), Ref("last")) 22 | end 23 | function compute_pressure(v::Vessel, rho::Float64, ext::String) 24 | A = readdlm(v.label * "_A.$(ext)") 25 | 26 | P = zeros(Float64, size(A)) 27 | P[:,1] = A[:,1] 28 | 29 | for (i, j) in enumerate([1, v.node2, v.node3, v.node4, v.M]) 30 | @. P[:,i+1] = pressure(A[:,i+1], v.A0[j], v.beta[j], v.Pext) 31 | 32 | if v.viscoelastic 33 | P[:,i+1] .+= v.Cv[j] .* rho ./ A[:,i+1] .* diff([A[:,i+1];A[end,i+1]])./diff([A[:,1];A[end,1]+(A[end,1]-A[end-1,1])]) 34 | end 35 | end 36 | 37 | open(v.label * "_P.$(ext)", "w") do io 38 | writedlm(io, P) 39 | end 40 | end 41 | # ------------------------------------------------------------------------------ 42 | 43 | load_yaml_config(yaml_config::String) = YAML.load_file(yaml_config) 44 | 45 | function get_conv_error(n::Network) 46 | error, edge = findmax(get_conv_error, n.vessels) 47 | error, n.vessels[edge].label 48 | end 49 | 50 | function get_conv_error(v::Vessel) 51 | current = v.waveforms["P"][:,4] 52 | prev = readdlm(v.label * "_P.last")[:, 4] 53 | sqrt(mean(current - prev) .^ 2) / 133.332 54 | end 55 | 56 | getprog(cycle::Int64, verbose::Bool) = 57 | verbose ? 58 | ProgressUnknown(desc = "Solving cycle #$cycle:", spinner = true, showspeed = true) : 59 | nothing 60 | function get_inlet_file(config)::String 61 | if ~haskey(config, "inlet_file") 62 | return config["project_name"]::String * "_inlet.dat" 63 | end 64 | config["inlet_file"] 65 | end 66 | 67 | function preamble(yaml_config, verbose, savedir) 68 | 69 | verbose && println("Loading config...") 70 | config = load_yaml_config(yaml_config) 71 | 72 | project_name = config["project_name"] 73 | verbose && println("project name: $project_name") 74 | 75 | if savedir == "" 76 | results_dir = get(config, "output_directory", project_name * "_results") 77 | else 78 | results_dir = savedir 79 | end 80 | isdir(results_dir) && rm(results_dir, recursive = true) 81 | ~isdir(results_dir) && mkpath(results_dir) 82 | yaml_config_name = last(splitpath(yaml_config)) 83 | cp(yaml_config, joinpath(results_dir, yaml_config_name), force = true) 84 | 85 | inlet_file = get_inlet_file(config) 86 | try 87 | cp(inlet_file, joinpath(results_dir, inlet_file), force = true) 88 | catch 89 | cp(joinpath([splitpath(yaml_config)[1:end-1]; inlet_file]), joinpath(results_dir, inlet_file), force=true) 90 | end 91 | cd(results_dir) 92 | 93 | config 94 | end 95 | 96 | function run_simulation( 97 | yaml_config::String; 98 | verbose::Bool = true, 99 | out_files::Bool = false, 100 | save_stats::Bool = false, 101 | savedir::String = "", 102 | ) 103 | initial_dir = pwd() 104 | config::Dict{String, Any} = preamble(yaml_config, verbose, savedir) 105 | 106 | blood = Blood(config["blood"]) 107 | heart = Heart(get_inlet_file(config)::String) 108 | 109 | tempsave::Vector{String} = deepcopy(get(config, "write_results", [])) 110 | "P" ∉ tempsave && push!(tempsave, "P") 111 | network = Network( 112 | config["network"], 113 | blood, 114 | heart, 115 | config["solver"]["Ccfl"]::Float64, 116 | config["solver"]["jump"]::Int64, 117 | tempsave, 118 | verbose = verbose, 119 | ) 120 | total_time = float(config["solver"]["cycles"]) * heart.cardiac_period 121 | jump::Int64 = config["solver"]["jump"] 122 | checkpoints = range(0, stop = heart.cardiac_period, length = jump) 123 | 124 | verbose && println("\nStart simulation") 125 | 126 | current_time = 0.0 127 | passed_cycles = 0 128 | prog = getprog(passed_cycles, verbose) 129 | counter = 1 130 | conv_error::Float64 = floatmax() 131 | converged = false 132 | 133 | try 134 | stats = @timed while true 135 | 136 | # step 137 | dt = calculateΔt(network) 138 | solve!(network, dt, current_time) 139 | update_ghost_cells!(network) 140 | verbose && next!(prog) 141 | 142 | if current_time >= checkpoints[counter] 143 | save_waveforms.(counter, current_time, values(network.vessels)) 144 | counter += 1 145 | end 146 | 147 | # at the end of the cardiac cycle 148 | if (current_time - heart.cardiac_period * passed_cycles) >= heart.cardiac_period && 149 | (current_time - heart.cardiac_period * passed_cycles + dt) > heart.cardiac_period 150 | 151 | # check convergence 152 | if passed_cycles > 0 153 | # compute_pressure(network) 154 | conv_error, error_loc = get_conv_error(network) 155 | end 156 | 157 | flush_waveforms.(values(network.vessels)) 158 | out_files && append_last_to_out.(values(network.vessels)) 159 | 160 | if verbose 161 | if passed_cycles > 0 162 | finish!( 163 | prog, 164 | showvalues = [("RMSE (mmHg)", conv_error), ("@", error_loc)], 165 | ) 166 | else 167 | finish!(prog) 168 | end 169 | println() 170 | end 171 | 172 | checkpoints = checkpoints .+ heart.cardiac_period 173 | passed_cycles += 1 174 | prog = getprog(passed_cycles, verbose) 175 | counter = 1 176 | end 177 | 178 | # at the end of the simulation 179 | if current_time >= total_time || 180 | passed_cycles == config["solver"]["cycles"] || 181 | conv_error < config["solver"]["convergence_tolerance"] 182 | verbose && finish!(prog) 183 | converged = true 184 | break 185 | end 186 | current_time += dt 187 | end 188 | tokeep::Vector{String} = get(config, "write_results", []) 189 | cleanup.(values(network.vessels), Ref(tokeep)) 190 | 191 | verbose && printstats(stats, converged, passed_cycles) 192 | save_stats && savestats(stats, converged, passed_cycles, config["project_name"]) 193 | catch e 194 | println("\nAn error occurred, terminating simulation.\n") 195 | println(e) 196 | end 197 | 198 | cd(initial_dir) 199 | end 200 | 201 | function cleanup(v::Vessel, tokeep) 202 | ~v.tosave && rm.(glob("$(v.label)_*")) 203 | for l in ("P", "A", "Q", "u") 204 | l ∉ tokeep && rm.(glob("$(v.label)_$l.*"), force=true) 205 | end 206 | end 207 | 208 | function printstats(s, converged, passed_cycles) 209 | if converged 210 | println("Simulation converged after $passed_cycles cardiac cycles") 211 | else 212 | println("Simulation not converged, stopping after $passed_cycles cardiac cycles") 213 | end 214 | @printf "Elapsed time: %5.2fs\n" s.time 215 | @printf "Memory: %5.2fGB\n" s.bytes*1e-9 216 | gctime = @sprintf "GC time: %5.2f" s.gctime 217 | println("$(gctime)%") 218 | end 219 | 220 | function savestats(s, converged, passed_cycles, simulation_name) 221 | open("$simulation_name.conv", "w") do io 222 | println(io, "$converged") 223 | println(io, "$passed_cycles") 224 | println(io, "$(s.time)") 225 | println(io, "$(s.bytes)") 226 | println(io, "$(s.gctime)") 227 | end 228 | end 229 | -------------------------------------------------------------------------------- /models/boileau2015/plot.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | 4 | plt.style.use("plot_style.txt") 5 | 6 | 7 | def plot_single_artery_validation( 8 | Tt, 9 | B3D, 10 | FV, 11 | P, 12 | Q, 13 | A, 14 | xlims, 15 | shift, 16 | figname, 17 | figformat, 18 | fignum, 19 | title, 20 | ): 21 | T = P[:, 0] 22 | t0 = np.argwhere(T > T[-1] - Tt) 23 | t0 = t0[0][0] 24 | 25 | P = P[t0:, :] 26 | Q = Q[t0:, :] 27 | A = A[t0:, :] 28 | 29 | T = np.linspace(0.0, Tt, P.shape[0]) 30 | 31 | R = np.sqrt(A / np.pi) 32 | R -= np.min(R) 33 | dP = P[:, 1] - P[:, -1] 34 | 35 | t0FV = np.argwhere(FV[:, 0] > FV[-1, 0] - Tt - 0.05) 36 | t0FV = t0FV[0][0] 37 | tFV = np.linspace(0.0, Tt, len(FV[t0FV:-50, 0])) 38 | 39 | t3d = np.linspace(19, 19.955, B3D.shape[0]) 40 | 41 | waves = [P[:, 3] * 1e-3, Q[:, 3] * 1e6, R[:, 3] * 1e3, dP * 1e-3] 42 | titles = [ 43 | "(a) Pressure", 44 | "(b) Flow", 45 | "(c) Radius Change", 46 | "(d) Pressure Difference", 47 | ] 48 | ylabels = [ 49 | "$P$ (kPa)", 50 | "$Q$ (ml$\cdot$s$^{-1}$)", 51 | "$\Delta r$ (mm)", 52 | "$\Delta P$ (kPa)", 53 | ] 54 | 55 | fig = plt.figure(fignum, figsize=(12, 3)) 56 | fig.clf() 57 | 58 | for i in range(4): 59 | ax = fig.add_subplot(1, 4, i + 1) 60 | 61 | if figname == "cca": 62 | ax.plot( 63 | tFV / T[-1], 64 | FV[t0FV:-50, i + 1], 65 | color="slategrey", 66 | label="Boileau2015-FV1D", 67 | ) 68 | ax.plot( 69 | B3D[:, 0] / T[-1], 70 | B3D[:, i + 1], 71 | linestyle=":", 72 | color="gray", 73 | label="Xiao2015-3D", 74 | ) 75 | ax.plot( 76 | T[:-shift] / T[-1], 77 | waves[i][shift:], 78 | "k", 79 | linestyle="--", 80 | label="openBF", 81 | ) 82 | ax.plot(T[-shift:] / T[-1], waves[i][:shift], "k", linestyle="--") 83 | else: 84 | ax.plot( 85 | FV[:, 0] / FV[len(tFV), 0], 86 | FV[:, i + 1], 87 | color="slategrey", 88 | label="Boileau2015-FV1D", 89 | ) 90 | ax.plot( 91 | B3D[:, 0] / B3D[-1, 0], 92 | B3D[:, i + 1], 93 | linestyle=":", 94 | color="gray", 95 | label="Xiao2015-3D", 96 | ) 97 | ax.plot(T / T[-1], waves[i], "k", linestyle="--", label="openBF") 98 | 99 | ax.set_xlim(0, 1.0) 100 | ax.set_ylim(xlims[i]) 101 | ax.set_xlabel("$t\,/\,T_c$") 102 | 103 | if i == 1: 104 | legend_handle, legend_labels = ax.get_legend_handles_labels() 105 | ax.set_ylabel(ylabels[i]) 106 | # ax.set_title(titles[i]) 107 | 108 | fig.legend( 109 | legend_handle, 110 | legend_labels, 111 | loc="lower center", 112 | bbox_to_anchor=(0.5, 0), 113 | ncol=3, 114 | ) 115 | # plt.suptitle(title) 116 | 117 | plt.tight_layout(rect=[0, 0.09, 1, 1]) 118 | 119 | plt.savefig(f"{figname}.{figformat}", dpi=300, format=figformat) 120 | 121 | 122 | def plot_iliac_bifurcation_validation(fignum, figname, figformat): 123 | B3Da = np.loadtxt("ibif/ibif_ref/B3D_AortaMid.txt") 124 | B3Di = np.loadtxt("ibif/ibif_ref/B3D_IliacMid.txt") 125 | B3Dj = np.loadtxt("ibif/ibif_ref/B3D_Junction.txt") 126 | 127 | P = np.loadtxt("ibif/ibif_results/parent_P.last") 128 | Q = np.loadtxt("ibif/ibif_results/parent_Q.last") 129 | A = np.loadtxt("ibif/ibif_results/parent_A.last") 130 | R = np.sqrt(A[:, 3] / np.pi) 131 | R0 = 0.83183427183602578 * 1e-2 + 0.000125 132 | dR = R - np.min(R) # R0 133 | 134 | Rb = np.sqrt(A[:, -1] / np.pi) 135 | R0b = 0.83183427183602578 * 1e-2 + 0.000125 136 | dRb = Rb - R0b 137 | 138 | P1 = np.loadtxt("ibif/ibif_results/d1_P.last") 139 | Q1 = np.loadtxt("ibif/ibif_results/d1_Q.last") 140 | A1 = np.loadtxt("ibif/ibif_results/d1_A.last") 141 | R1 = np.sqrt(A1[:, 3] / np.pi) 142 | R01 = 0.58844816698429576 * 1e-2 + 0.00003 143 | dR1 = R1 - np.min(R1) # R01 144 | 145 | FV = np.loadtxt("ibif/ibif_ref/FV_aorta-bif.dat") 146 | FVb = np.loadtxt("ibif/ibif_ref/FV_aorta_bif-bif.dat") 147 | FVi = np.loadtxt("ibif/ibif_ref/FV_iliac-bif.dat") 148 | 149 | fig = plt.figure(fignum, figsize=(9, 6)) 150 | fig.clf() 151 | 152 | t3d = np.linspace(0.0, 1.0, B3Da.shape[0]) 153 | 154 | qs1d = [FV, FVb, FVi] 155 | qs3d = [B3Da, B3Dj, B3Di] 156 | qsobf = [ 157 | [P[:, 3] / 1000, Q[:, 3] * 1e6, dR * 1e3], 158 | [P[:, -1] / 1000, Q[:, -1] * 1e6, dRb * 1e3], 159 | [P1[:, 3] / 1000, Q1[:, 3] * 1e6, dR1 * 1e3], 160 | ] 161 | ylims = [ 162 | [(8, 18), (-24, 80), (-0.05, 0.9)], 163 | [(7, 19), (-20, 70), (-0.1, 0.9)], 164 | [(7, 18), (-10, 30), (-0.07, 0.46)], 165 | ] 166 | for i, location in enumerate(["aorta", "junction", "iliac"]): 167 | for j, q in enumerate( 168 | [ 169 | "$P$ (kPa)", 170 | "$Q$ (ml$\cdot$s$^{-1}$)", 171 | "$\Delta r$ (mm)", 172 | ] 173 | ): 174 | ax = fig.add_subplot(3, 3, 3 * i + j + 1) 175 | ax.plot( 176 | (qs1d[i][8800:9900, 0] - 8.8) / 1.1, 177 | qs1d[i][8800:9900, j + 1], 178 | color="slategrey", 179 | label="Boileau2015-FV1D", 180 | ) 181 | ax.plot( 182 | t3d, qs3d[i][:, j + 1], color="gray", linestyle=":", label="Xiao2015-3D" 183 | ) 184 | ax.plot( 185 | (P[:, 0] - P[0, 0]) / (P[-1, 0] - P[0, 0]), 186 | qsobf[i][j], 187 | "k", 188 | linestyle="--", 189 | label="openBF", 190 | ) 191 | 192 | ax.set_xlim(0, 1) 193 | ax.set_ylim(ylims[i][j]) 194 | ax.set_ylabel(q) 195 | 196 | if i == 1 and j == 1: 197 | legend_handle, legend_labels = ax.get_legend_handles_labels() 198 | 199 | ax.set_xlabel("$t\,/\,T_c$") 200 | # ax.set_ylabel(ylabels[i]) 201 | if j == 0: 202 | ax.annotate( 203 | location, 204 | xy=(0, 0.5), 205 | xytext=(-ax.yaxis.labelpad - 5, 0), 206 | xycoords=ax.yaxis.label, 207 | textcoords="offset points", 208 | size="large", 209 | ha="right", 210 | va="center", 211 | ) 212 | 213 | fig.legend( 214 | legend_handle, 215 | legend_labels, 216 | loc="lower center", 217 | bbox_to_anchor=(0.5, 0), 218 | ncol=3, 219 | ) 220 | 221 | plt.tight_layout(rect=[0, 0.09, 1, 1]) 222 | 223 | plt.savefig(f"{figname}.{figformat}", dpi=300, format=figformat) 224 | 225 | 226 | # uta 227 | B3D = np.loadtxt("uta/uta_ref/B3D_aortic.txt") 228 | FV = np.loadtxt("uta/uta_ref/FV_aortic.dat") 229 | P = np.loadtxt("uta/uta_results/upper_thoracic_aorta_P.last") 230 | Q = np.loadtxt("uta/uta_results/upper_thoracic_aorta_Q.last") 231 | A = np.loadtxt("uta/uta_results/upper_thoracic_aorta_A.last") 232 | Tt = 9.549999999999999600e-01 233 | xlims = [(8.5, 18), (-80, 520), (-0.1, 1.7), (-3, 5)] 234 | shift = 0 235 | figname = "uta" 236 | figformat = "eps" 237 | fignum = 1 238 | title = "Upper Thoracic Aorta" 239 | 240 | plot_single_artery_validation( 241 | Tt, B3D, FV, P, Q, A, xlims, shift, figname, figformat, fignum, title 242 | ) 243 | 244 | # cca 245 | Tt = 1.1 246 | B3D = np.loadtxt("cca/cca_ref/B3D_commoncarotid.txt") 247 | FV = np.loadtxt("cca/cca_ref/FV_carotid.dat") 248 | P = np.loadtxt("cca/cca_results/common_carotid_artery_P.out") 249 | Q = np.loadtxt("cca/cca_results/common_carotid_artery_Q.out") 250 | A = np.loadtxt("cca/cca_results/common_carotid_artery_A.out") 251 | xlims = [(10, 17.5), (3, 13), (-0.01, 0.2), (-0.2, 0.8)] 252 | shift = 5 253 | figname = "cca" 254 | fignum = 2 255 | title = "Common Carotid Artery" 256 | 257 | plot_single_artery_validation( 258 | Tt, B3D, FV, P, Q, A, xlims, shift, figname, figformat, fignum, title 259 | ) 260 | 261 | # ibif 262 | fignum = 3 263 | figname = "ibif" 264 | plot_iliac_bifurcation_validation(fignum, figname, figformat) 265 | -------------------------------------------------------------------------------- /src/solver.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Copyright 2015-2024 INSIGNEO Institute for in silico Medicine 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | =# 16 | 17 | 18 | function calculateΔt(n::Network) 19 | minΔt = 1.0 20 | Δt = 1.0 21 | for (_, v) in n.vessels 22 | maxspeed = 0.0 23 | for i=eachindex(v.u) 24 | @inbounds speed = abs(v.u[i] + wave_speed(v.A[i], v.gamma[i+1])) 25 | isnan(speed) && continue 26 | maxspeed = max(maxspeed, speed) 27 | end 28 | Δt = v.dx / maxspeed 29 | isnan(Δt) && continue 30 | minΔt = min(minΔt, Δt) 31 | end 32 | minΔt*n.Ccfl 33 | end 34 | 35 | function skipthis(n::Network, s, t) 36 | if n.vessels[(s, t)].solved 37 | return true 38 | end 39 | 40 | if s == 1 41 | return false 42 | end 43 | 44 | indeg::Int64 = Graphs.indegree(n.graph, s) 45 | 46 | if indeg == 1 47 | parent_src = first(Graphs.inneighbors(n.graph, s)) 48 | return ~n.vessels[parent_src, s].solved 49 | end 50 | 51 | if indeg == 2 52 | parent_src = Graphs.inneighbors(n.graph, s) 53 | return ~(n.vessels[first(parent_src), s].solved && n.vessels[last(parent_src), s].solved) 54 | end 55 | 56 | # TODO: this should error 57 | 58 | return false 59 | end 60 | 61 | function solve!(n::Network, dt::Float64, current_time::Float64)::Nothing 62 | for (k, v) in n.vessels 63 | v.solved = false 64 | end 65 | 66 | while ~all(v.solved for v in values(n.vessels)) 67 | for edge in n.edges 68 | s = Graphs.src(edge) 69 | t = Graphs.dst(edge) 70 | 71 | skipthis(n, s, t) && continue 72 | 73 | # inlet 74 | s == 1 && inbc!(n.vessels[(s, t)], current_time, dt, n.heart) 75 | 76 | # TODO: multiple inlets 77 | 78 | # downstream 79 | outdeg::Int64 = Graphs.outdegree(n.graph, t) 80 | if outdeg == 0 # outlet 81 | outbc!(n.vessels[(s, t)], dt, n.blood.rho) 82 | elseif outdeg == 1 83 | indeg::Int64 = Graphs.indegree(n.graph, t) 84 | d::Int64 = first(Graphs.outneighbors(n.graph, t)) 85 | if indeg == 1 # conjunction 86 | join_vessels!(n.vessels[(s, t)], n.vessels[(t, d)], n.blood.rho) 87 | elseif indeg == 2 # anastomosis 88 | ps::Vector{Int64} = Graphs.inneighbors(n.graph, t) 89 | solveAnastomosis( 90 | n.vessels[(ps[1], t)], 91 | n.vessels[(ps[2], t)], 92 | n.vessels[(t, d)], 93 | ) 94 | end 95 | elseif outdeg == 2 # bifurcation 96 | ds::Vector{Int64} = Graphs.outneighbors(n.graph, t) 97 | join_vessels!(n.vessels[(s, t)], n.vessels[t, ds[1]], n.vessels[t, ds[2]]) 98 | end 99 | 100 | muscl!(n.vessels[(s, t)], dt, n.blood) 101 | n.vessels[(s, t)].solved = true 102 | end 103 | end 104 | end 105 | 106 | function muscl!(v::Vessel, dt::Float64, b::Blood) 107 | dxDt = v.dx / dt 108 | invDxDt = 1.0 / dxDt 109 | 110 | # step-1 111 | # i = 1 112 | @inbounds v.vA[1] = v.U00A 113 | @inbounds v.vQ[1] = v.U00Q 114 | # 2:v.M+1 115 | for i = eachindex(v.A, v.Q) 116 | @inbounds v.vA[i+1] = v.A[i] 117 | @inbounds v.vQ[i+1] = v.Q[i] 118 | end 119 | # i = M+2 120 | @inbounds v.vA[end] = v.UM1A 121 | @inbounds v.vQ[end] = v.UM1Q 122 | 123 | # 124 | limiter!(v, v.vA, v.slopesA) 125 | limiter!(v, v.vQ, v.slopesQ) 126 | 127 | # 128 | for i = eachindex(v.Al) 129 | @inbounds v.Al[i] = v.vA[i] + v.slopesA[i] 130 | @inbounds v.Ar[i] = v.vA[i] - v.slopesA[i] 131 | 132 | @inbounds v.Ql[i] = v.vQ[i] + v.slopesQ[i] 133 | @inbounds v.Qr[i] = v.vQ[i] - v.slopesQ[i] 134 | 135 | @inbounds v.Fl[i] = v.Ql[i] * v.Ql[i] / v.Al[i] + v.gamma[i] * v.Al[i] * sqrt(v.Al[i]) 136 | @inbounds v.Fr[i] = v.Qr[i] * v.Qr[i] / v.Ar[i] + v.gamma[i] * v.Ar[i] * sqrt(v.Ar[i]) 137 | end 138 | 139 | # 140 | for i = 1:v.M+1 141 | @inbounds v.fluxA[i] = 0.5 * (v.Qr[i+1] + v.Ql[i] - dxDt * (v.Ar[i+1] - v.Al[i])) 142 | @inbounds v.fluxQ[i] = 0.5 * (v.Fr[i+1] + v.Fl[i] - dxDt * (v.Qr[i+1] - v.Ql[i])) 143 | end 144 | 145 | # step-2 146 | for i = 2:v.M+1 147 | @inbounds v.vA[i] += invDxDt * (v.fluxA[i-1] - v.fluxA[i]) 148 | @inbounds v.vQ[i] += invDxDt * (v.fluxQ[i-1] - v.fluxQ[i]) 149 | end 150 | # i=1 151 | @inbounds v.vA[1] = v.vA[2] 152 | @inbounds v.vQ[1] = v.vQ[2] 153 | # i=M+2 154 | @inbounds v.vA[end] = v.vA[end-1] 155 | @inbounds v.vQ[end] = v.vQ[end-1] 156 | 157 | # 158 | limiter!(v, v.vA, v.slopesA) 159 | limiter!(v, v.vQ, v.slopesQ) 160 | 161 | # 162 | for i = eachindex(v.Al) 163 | @inbounds v.Al[i] = v.vA[i] + v.slopesA[i] 164 | @inbounds v.Ar[i] = v.vA[i] - v.slopesA[i] 165 | 166 | @inbounds v.Ql[i] = v.vQ[i] + v.slopesQ[i] 167 | @inbounds v.Qr[i] = v.vQ[i] - v.slopesQ[i] 168 | 169 | @inbounds v.Fl[i] = v.Ql[i] * v.Ql[i] / v.Al[i] + v.gamma[i] * v.Al[i] * sqrt(v.Al[i]) 170 | @inbounds v.Fr[i] = v.Qr[i] * v.Qr[i] / v.Ar[i] + v.gamma[i] * v.Ar[i] * sqrt(v.Ar[i]) 171 | end 172 | 173 | # 174 | for i = 1:v.M+1 175 | @inbounds v.fluxA[i] = 0.5 * (v.Qr[i+1] + v.Ql[i] - dxDt * (v.Ar[i+1] - v.Al[i])) 176 | @inbounds v.fluxQ[i] = 0.5 * (v.Fr[i+1] + v.Fl[i] - dxDt * (v.Qr[i+1] - v.Ql[i])) 177 | end 178 | 179 | # 2:v.M+1 180 | for i = eachindex(v.A) 181 | @inbounds v.A[i] = 182 | 0.5 * (v.A[i] + v.vA[i+1] + invDxDt * (v.fluxA[i] - v.fluxA[i+1])) 183 | @inbounds v.Q[i] = 184 | 0.5 * (v.Q[i] + v.vQ[i+1] + invDxDt * (v.fluxQ[i] - v.fluxQ[i+1])) 185 | end 186 | 187 | #source term 188 | for i = eachindex(v.Q) # 1:v.M 189 | #viscosity 190 | @inbounds v.Q[i] -= 2 * (v.gamma_profile + 2) * pi * b.mu * v.Q[i] / (v.A[i] * b.rho) * dt 191 | 192 | if v.tapered 193 | #dP/dA0 194 | @inbounds v.Q[i] += dt * 0.5 * v.beta[i] * sqrt(v.A[i])*v.A[i] / (v.A0[i] * b.rho) * v.dA0dx[i] 195 | 196 | #dP/dh0 197 | @inbounds v.Q[i] -= dt * (v.A[i] / b.rho) * (sqrt(v.A[i] / v.A0[i]) - 1.0) * v.dTaudx[i] 198 | end 199 | 200 | # update 201 | @inbounds v.u[i] = v.Q[i] / v.A[i] 202 | end 203 | 204 | #parabolic system (visco-elastic) 205 | if v.viscoelastic 206 | a = v.Cv.*dt/(v.dx*v.dx) 207 | Tupper = -a[2:end] 208 | Tlower = -a[1:end-1] 209 | Tdiagonal = 1.0.+2.0.*a 210 | Tdiagonal[1] -= a[1] 211 | Tdiagonal[end] -= a[end] 212 | 213 | T = Tridiagonal(Tupper, Tdiagonal, Tlower) 214 | 215 | d = (1.0 .- 2.0.*a).*v.Q 216 | d[1] += a[2]*v.Q[2] + a[1]*v.Q[1] 217 | d[2:end-1] .+= a[1:end-2].*v.Q[1:end-2] .+ a[3:end].*v.Q[3:end] 218 | d[end] += a[end-1]*v.Q[end-1] + a[end]*v.Q[end] 219 | 220 | v.Q = T\d 221 | end 222 | end 223 | 224 | function limiter!( 225 | v::Vessel, 226 | U::Vector{Float64}, 227 | slopes::Vector{Float64}, 228 | ) 229 | for i = 2:v.M+2 230 | @inbounds v.dUA[i] = (U[i] - U[i-1]) * v.invDx 231 | @inbounds v.dUQ[i-1] = (U[i] - U[i-1]) * v.invDx 232 | end 233 | superbee!(slopes, v.dUA, v.dUQ, v.halfDx) 234 | end 235 | 236 | # https://discourse.julialang.org/t/optimising-superbee-function/112568/12 237 | function superbee!(s::Vector{Float64}, a::Vector{Float64}, b::Vector{Float64}, h::Float64) 238 | @simd for i = eachindex(s) 239 | # @inbounds is inferred automatically - yay for safety AND speed! 240 | ai = a[i] 241 | bi = b[i] 242 | t1 = max(min(ai,2bi),min(2ai,bi)) 243 | t2 = min(max(ai,2bi),max(2ai,bi)) 244 | s[i] = ifelse(ai>0, ifelse(bi>0, t1, zero(Float64)), ifelse(bi<0, t2, zero(Float64)))*h 245 | end 246 | end 247 | -------------------------------------------------------------------------------- /src/vessel.jl: -------------------------------------------------------------------------------- 1 | #= 2 | Copyright 2015-2024 INSIGNEO Institute for in silico Medicine 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | =# 16 | 17 | struct Blood 18 | mu::Float64 19 | rho::Float64 20 | Cf::Float64 21 | end 22 | 23 | function Blood(config::Dict) 24 | μ = config["mu"] 25 | ρ = config["rho"] 26 | Cf = 8π * μ / ρ 27 | Blood(μ, ρ, Cf) 28 | end 29 | 30 | mutable struct Vessel 31 | solved::Bool 32 | label::SubString{String} 33 | tosave::Bool 34 | 35 | #Topological notation 36 | sn::Int64 37 | tn::Int64 38 | 39 | #Numerical constants 40 | M::Int64 41 | dx::Float64 42 | invDx::Float64 43 | halfDx::Float64 44 | 45 | #Physical constants 46 | beta::Vector{Float64} 47 | Cv::Vector{Float64} 48 | viscoelastic::Bool 49 | gamma::Vector{Float64} 50 | A0::Vector{Float64} 51 | tapered::Bool 52 | dA0dx::Vector{Float64} 53 | dTaudx::Vector{Float64} 54 | Pext::Float64 55 | gamma_profile::Int64 56 | 57 | #Iterative solution 58 | A::Vector{Float64} 59 | Q::Vector{Float64} 60 | u::Vector{Float64} 61 | P::Vector{Float64} 62 | 63 | #Riemann invariants 64 | W1M0::Float64 65 | W2M0::Float64 66 | 67 | #Ghost cells 68 | U00A::Float64 69 | U00Q::Float64 70 | UM1A::Float64 71 | UM1Q::Float64 72 | 73 | #Saving locations 74 | node2::Int64 75 | node3::Int64 76 | node4::Int64 77 | 78 | #Peripheral boundary condition 79 | usewk3::Bool 80 | Rt::Float64 81 | R1::Float64 82 | R2::Float64 83 | total_peripheral_resistance::Float64 84 | inlet_impedance_matching::Bool 85 | Cc::Float64 86 | Pc::Float64 87 | Pout::Float64 88 | 89 | #MUSCLArrays 90 | fluxA::Vector{Float64} 91 | fluxQ::Vector{Float64} 92 | 93 | vA::Vector{Float64} 94 | vQ::Vector{Float64} 95 | 96 | dUA::Vector{Float64} 97 | dUQ::Vector{Float64} 98 | 99 | slopesA::Vector{Float64} 100 | slopesQ::Vector{Float64} 101 | 102 | Al::Vector{Float64} 103 | Ar::Vector{Float64} 104 | 105 | Ql::Vector{Float64} 106 | Qr::Vector{Float64} 107 | 108 | Fl::Vector{Float64} 109 | Fr::Vector{Float64} 110 | 111 | # waveforms 112 | waveforms::Dict{String, Array{Float64, 2}} 113 | end 114 | 115 | wave_speed(A::Float64, gamma::Float64) = sqrt(1.5 * gamma * sqrt(A)) 116 | wave_speed(v::Vessel) = wave_speed.(v.A, v.gamma) 117 | 118 | pressure(A::Float64, A0::Float64, beta::Float64, Pext::Float64) = 119 | Pext + beta * (sqrt(A / A0) - 1.0) 120 | 121 | function mesh(config::Dict{Any,Any}) 122 | L = config["L"] 123 | M = get(config, "M", 5) 124 | M = max(M, 5) 125 | M = max(M, ceil(Int, config["L"] * 1e3)) 126 | 127 | dx = L / M 128 | invDx = M / L 129 | halfDx = 0.5 * dx 130 | 131 | L, M, dx, invDx, halfDx 132 | end 133 | 134 | function radii(config::Dict{Any,Any}) 135 | ~haskey(config, "R0") && 136 | ~haskey(config, "Rp") && 137 | error("missing radius in $(config["label"])") 138 | R0 = get(config, "R0", 0.0) 139 | Rp = get(config, "Rp", R0) 140 | Rd = get(config, "Rd", Rp) 141 | Rp, Rd 142 | end 143 | 144 | function Vessel(config::Dict{Any,Any}, b::Blood, jump::Int64, tokeep::Vector{String}) 145 | vessel_name = config["label"] 146 | tosave = get(config, "to_save", true) 147 | sn = config["sn"] 148 | tn = config["tn"] 149 | Rp, Rd = radii(config) 150 | L, M, dx, invDx, halfDx = mesh(config) 151 | E = config["E"] 152 | 153 | Pext = get(config, "Pext", 0.0) 154 | initial_pressure = get(config, "initial_pressure", 0.0) 155 | initial_flow = get(config, "initial_flow", 0.0) 156 | 157 | sigma = 0.5 158 | 159 | A0 = zeros(Float64, M) 160 | R0 = zeros(Float64, M) 161 | h0 = zeros(Float64, M) .+ get(config, "h0", 0.0) 162 | 163 | dA0dx = zeros(Float64, M) 164 | dTaudx = zeros(Float64, M) 165 | radius_slope = (Rd - Rp) / (M - 1) 166 | tapered = ~isapprox(Rd, Rp, atol=1e-4) # less than 1μm difference = no tapering 167 | ah = 0.2802 168 | bh = -5.053e2 169 | ch = 0.1324 170 | dh = -0.1114e2 171 | for i = 1:M 172 | R0[i] = radius_slope * (i - 1) * dx + Rp 173 | if ~haskey(config, "h0") 174 | h0[i] = R0[i] * (ah * exp(bh * R0[i]) + ch * exp(dh * R0[i])) 175 | end 176 | A0[i] = pi * R0[i] * R0[i] 177 | dA0dx[i] = 2 * pi * R0[i] * radius_slope 178 | 179 | if haskey(config, "h0") 180 | dTaudx[i] = 0.0 181 | else 182 | dTaudx[i] = (sqrt(pi) * E * radius_slope * 1.3 * (h0[i] / R0[i] + R0[i] * (ah * bh * exp(bh * R0[i]) + ch * dh * exp(dh * R0[i])))) 183 | end 184 | end 185 | 186 | beta = sqrt.(pi ./ A0) .* h0 * E / (1 - sigma^2) 187 | gamma = zeros(Float64, M + 2) 188 | gamma[2:M+1] = beta ./ (3 * b.rho * R0 * sqrt(pi)) 189 | gamma[1] = gamma[2] # ghost cells 190 | gamma[end] = gamma[end-1] 191 | 192 | # TODO: add to docs 193 | # TODO: visco-elastic -> visco_elastic ??? 194 | viscoelastic = get(config, "visco-elastic", false) 195 | if viscoelastic 196 | b0=0.6 197 | b1=0.00150 198 | Γ=b1*0.5./R0 .+ b0 199 | Cv=Γ./(b.rho.*sqrt.(A0)) 200 | else 201 | Cv = zeros(Float64, M) 202 | end 203 | 204 | A = zeros(Float64, M) + A0 205 | Q = zeros(Float64, M) .+ initial_flow 206 | u = zeros(Float64, M) + Q ./ A 207 | P = pressure.(A, A0, beta, Pext) 208 | 209 | U00A = A0[1] 210 | UM1A = A0[M] 211 | U00Q = initial_flow 212 | UM1Q = initial_flow 213 | 214 | c = wave_speed(A[end], gamma[end-1]) 215 | W1M0 = u[end] - 4c 216 | W2M0 = u[end] + 4c 217 | 218 | node2 = round(Int, M * 0.25) 219 | node3 = round(Int, M * 0.5) 220 | node4 = round(Int, M * 0.75) 221 | 222 | Rt = get(config, "Rt", 0.0) 223 | R1 = get(config, "R1", 0.0) 224 | R2 = get(config, "R2", 0.0) 225 | Cc = get(config, "Cc", 0.0) 226 | if R2 == 0.0 227 | R2 = R1 - b.rho * wave_speed(A0[end], gamma[end-1]) / A0[end] 228 | end 229 | total_peripheral_resistance = R1 + R2 230 | inlet_impedance_matching = get(config, "inlet_impedance_matching", false) 231 | usewk3 = R2 != 0.0 232 | 233 | # `Pc` is the pressure through the peripheral compliance of the three 234 | # elements windkessel. It is set to zero to simulate the pressure at the 235 | # artery-vein interface. 236 | Pc = 0.0 237 | Pout = get(config, "Pout", 0.0) 238 | 239 | # MUSCL arrays 240 | fluxA = zeros(Float64, M + 2) 241 | fluxQ = zeros(Float64, M + 2) 242 | 243 | vA = zeros(Float64, M + 2) 244 | vQ = zeros(Float64, M + 2) 245 | 246 | dUA = zeros(Float64, M + 2) 247 | dUQ = zeros(Float64, M + 2) 248 | 249 | slopesA = zeros(Float64, M + 2) 250 | slopesQ = zeros(Float64, M + 2) 251 | 252 | Al = zeros(Float64, M + 2) 253 | Ar = zeros(Float64, M + 2) 254 | 255 | Ql = zeros(Float64, M + 2) 256 | Qr = zeros(Float64, M + 2) 257 | 258 | Fl = zeros(Float64, M + 2) 259 | Fr = zeros(Float64, M + 2) 260 | 261 | gamma_profile = get(config, "gamma_profile", 2) 262 | 263 | waveforms = Dict() 264 | for q in tokeep 265 | waveforms[q] = zeros(Float64, jump, 6) 266 | end 267 | 268 | solved = false 269 | 270 | Vessel( 271 | solved, 272 | vessel_name, 273 | tosave, 274 | sn, 275 | tn, 276 | M, 277 | dx, 278 | invDx, 279 | halfDx, 280 | beta, 281 | Cv, 282 | viscoelastic, 283 | gamma, 284 | A0, 285 | tapered, 286 | dA0dx, 287 | dTaudx, 288 | Pext, 289 | gamma_profile, 290 | A, 291 | Q, 292 | u, 293 | P, 294 | W1M0, 295 | W2M0, 296 | U00A, 297 | U00Q, 298 | UM1A, 299 | UM1Q, 300 | node2, 301 | node3, 302 | node4, 303 | usewk3, 304 | Rt, 305 | R1, 306 | R2, 307 | total_peripheral_resistance, 308 | inlet_impedance_matching, 309 | Cc, 310 | Pc, 311 | Pout, 312 | fluxA, 313 | fluxQ, 314 | vA, 315 | vQ, 316 | dUA, 317 | dUQ, 318 | slopesA, 319 | slopesQ, 320 | Al, 321 | Ar, 322 | Ql, 323 | Qr, 324 | Fl, 325 | Fr, 326 | waveforms, 327 | ) 328 | end 329 | -------------------------------------------------------------------------------- /LICENSE-3RD-PARTY: -------------------------------------------------------------------------------- 1 | The Julia language is licensed under the MIT License. The "language" consists 2 | of the compiler (the contents of src/), most of the standard library (base/), 3 | and some utilities (most of the rest of the files in this repository). See below 4 | for exceptions. 5 | 6 | > Copyright (c) 2009-2016: Jeff Bezanson, Stefan Karpinski, Viral B. Shah, 7 | > and other contributors: 8 | > 9 | > https://github.com/JuliaLang/julia/contributors 10 | > 11 | > Permission is hereby granted, free of charge, to any person obtaining 12 | > a copy of this software and associated documentation files (the 13 | > "Software"), to deal in the Software without restriction, including 14 | > without limitation the rights to use, copy, modify, merge, publish, 15 | > distribute, sublicense, and/or sell copies of the Software, and to 16 | > permit persons to whom the Software is furnished to do so, subject to 17 | > the following conditions: 18 | > 19 | > The above copyright notice and this permission notice shall be 20 | > included in all copies or substantial portions of the Software. 21 | > 22 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | > EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | > MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | > NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 | > LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | > OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 | > WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | Julia includes code from the following projects, which have their own licenses: 31 | 32 | - [crc32c.c](http://stackoverflow.com/questions/17645167/implementing-sse-4-2s-crc32c-in-software) (CRC-32c checksum code by Mark Adler) [[ZLib](https://opensource.org/licenses/Zlib)]. 33 | - [LDC](https://github.com/ldc-developers/ldc/blob/master/LICENSE) (for ccall/cfunction ABI definitions) [BSD-3]. The portion of code that Julia uses from LDC is [BSD-3] licensed. 34 | - [LLVM](http://releases.llvm.org/3.9.0/LICENSE.TXT) (for parts of src/jitlayers.cpp and src/disasm.cpp) [BSD-3, effectively] 35 | - [MUSL](http://git.musl-libc.org/cgit/musl/tree/COPYRIGHT) (for getopt implementation on Windows) [MIT] 36 | - [MINGW](https://sourceforge.net/p/mingw/mingw-org-wsl/ci/legacy/tree/mingwrt/mingwex/dirname.c) (for dirname implementation on Windows) [MIT] 37 | - [NetBSD](http://www.netbsd.org/about/redistribution.html) (for setjmp, longjmp, and strptime implementations on Windows) [BSD-3] 38 | - [Python](https://docs.python.org/2/license.html) (for strtod implementation on Windows) [BSD-3, effectively] 39 | - [randmtzig.c](https://github.com/JuliaLang/julia/blob/master/test/perf/micro/randmtzig.c) for Gaussian random number generation (for C benchmarks only) [BSD-3] 40 | 41 | The Julia language links to the following external libraries, which have their 42 | own licenses: 43 | 44 | - [FEMTOLISP](https://github.com/JeffBezanson/femtolisp) [BSD-3] 45 | - [LIBUNWIND](http://git.savannah.gnu.org/gitweb/?p=libunwind.git;a=blob_plain;f=LICENSE;hb=master) [MIT] 46 | - [LIBUV](https://github.com/joyent/libuv/blob/master/LICENSE) [MIT] 47 | - [LLVM](http://releases.llvm.org/3.9.0/LICENSE.TXT) [BSD-3, effectively] 48 | - [UTF8PROC](https://github.com/JuliaLang/utf8proc) [MIT] 49 | 50 | 51 | Julia's standard library uses the following external libraries, which have 52 | their own licenses: 53 | 54 | - [ARPACK](http://www.caam.rice.edu/software/ARPACK/RiceBSD.txt#LICENSE) [BSD-3] 55 | - [DSFMT](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/LICENSE.txt) [BSD-3] 56 | - [OPENLIBM](https://github.com/JuliaLang/openlibm/blob/master/LICENSE.md) [MIT, BSD-2, ISC] 57 | - [OPENSPECFUN](https://github.com/JuliaLang/openspecfun) [MIT, public domain] 58 | - [FADDEEVA](http://ab-initio.mit.edu/Faddeeva) [MIT] 59 | - [FFTW](http://fftw.org/doc/License-and-Copyright.html) [GPL2+] 60 | - [GMP](http://gmplib.org/manual/Copying.html#Copying) [LGPL3+ or GPL2+] 61 | - [LIBGIT2](https://github.com/libgit2/libgit2/blob/development/COPYING) [GPL2+ with unlimited linking exception] 62 | - [CURL](https://curl.haxx.se/docs/copyright.html) [MIT/X derivative] 63 | - [LIBSSH2](https://github.com/libssh2/libssh2/blob/master/COPYING) [BSD-3] 64 | - [MBEDTLS](https://tls.mbed.org/how-to-get) [either GPLv2 or Apache 2.0] 65 | - [MPFR](http://www.mpfr.org/mpfr-current/mpfr.html#Copying) [LGPL3+] 66 | - [OPENBLAS](https://raw.github.com/xianyi/OpenBLAS/master/LICENSE) [BSD-3] 67 | - [LAPACK](http://netlib.org/lapack/LICENSE.txt) [BSD-3] 68 | - [PCRE](http://www.pcre.org/licence.txt) [BSD-3] 69 | - [SUITESPARSE](http://faculty.cse.tamu.edu/davis/suitesparse.html) [mix of LGPL2+ and GPL2+; see individual module licenses] 70 | 71 | 72 | The following components of Julia's standard library have separate licenses: 73 | 74 | - base/grisu/* (see [double-conversion](https://github.com/google/double-conversion/blob/master/LICENSE)) 75 | - base/sparse/umfpack.jl (see [SUITESPARSE](http://faculty.cse.tamu.edu/davis/suitesparse.html)) 76 | - base/sparse/cholmod.jl (see [SUITESPARSE](http://faculty.cse.tamu.edu/davis/suitesparse.html)) 77 | - base/special/exp.jl (see [FREEBSD MSUN](https://github.com/freebsd/freebsd) [FreeBSD/2-clause BSD/Simplified BSD License]) 78 | 79 | 80 | Julia's build process uses the following external tools: 81 | 82 | - [PATCHELF](http://hydra.nixos.org/build/1524660/download/1/README) 83 | - [OBJCONV](http://www.agner.org/optimize/#objconv) 84 | 85 | 86 | Julia bundles the following external programs and libraries on some platforms: 87 | 88 | - [7-Zip](http://www.7-zip.org/license.txt) 89 | - [BUSYBOX](https://github.com/rmyorston/busybox-w32/blob/master/LICENSE) 90 | - [ZLIB](http://zlib.net/zlib_license.html) 91 | - [LIBEXPAT](http://expat.cvs.sourceforge.net/viewvc/expat/expat/README) 92 | 93 | On some platforms, distributions of Julia contain SSL certificate authority certificates, 94 | released under the [Mozilla Public License](https://en.wikipedia.org/wiki/Mozilla_Public_License). 95 | 96 | ------------------------------------------------------------------------------------------ 97 | 98 | The majority of the StaticArrays.jl package is licensed under the MIT "Expat" 99 | License: 100 | 101 | > Copyright (c) 2016: Andy Ferris. 102 | > 103 | > Permission is hereby granted, free of charge, to any person obtaining 104 | > a copy of this software and associated documentation files (the 105 | > "Software"), to deal in the Software without restriction, including 106 | > without limitation the rights to use, copy, modify, merge, publish, 107 | > distribute, sublicense, and/or sell copies of the Software, and to 108 | > permit persons to whom the Software is furnished to do so, subject to 109 | > the following conditions: 110 | > 111 | > The above copyright notice and this permission notice shall be 112 | > included in all copies or substantial portions of the Software. 113 | > 114 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 115 | > EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 116 | > MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 117 | > IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 118 | > CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 119 | > TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 120 | > SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 121 | 122 | However, a small part of the 3x3 eigenvalue solver is under the Boost Software 123 | License - see src/eigen.jl 124 | 125 | ------------------------------------------------------------------------------------------ 126 | 127 | YAML.jl is licensed under the MIT License: 128 | 129 | > Copyright (c) 2013: Daniel C. Jones 130 | > 131 | > Permission is hereby granted, free of charge, to any person obtaining 132 | > a copy of this software and associated documentation files (the 133 | > "Software"), to deal in the Software without restriction, including 134 | > without limitation the rights to use, copy, modify, merge, publish, 135 | > distribute, sublicense, and/or sell copies of the Software, and to 136 | > permit persons to whom the Software is furnished to do so, subject to 137 | > the following conditions: 138 | > 139 | > The above copyright notice and this permission notice shall be 140 | > included in all copies or substantial portions of the Software. 141 | > 142 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 143 | > EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 144 | > MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 145 | > NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 146 | > LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 147 | > OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 148 | > WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 149 | 150 | ------------------------------------------------------------------------------------------ 151 | 152 | The ArgParse Julia module is licensed under the MIT License: 153 | 154 | > Copyright (c) 2012: Carlo Baldassi 155 | > 156 | > Permission is hereby granted, free of charge, to any person obtaining 157 | > a copy of this software and associated documentation files (the 158 | > "Software"), to deal in the Software without restriction, including 159 | > without limitation the rights to use, copy, modify, merge, publish, 160 | > distribute, sublicense, and/or sell copies of the Software, and to 161 | > permit persons to whom the Software is furnished to do so, subject to 162 | > the following conditions: 163 | > 164 | > The above copyright notice and this permission notice shall be 165 | > included in all copies or substantial portions of the Software. 166 | > 167 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 168 | > EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 169 | > MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 170 | > NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 171 | > LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 172 | > OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 173 | > WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 174 | 175 | Portions of this software are derived from Python 3.5.1 code, and therefore is licensed under 176 | the permissive but slightly more strict Python Software Foundation license, and is partially 177 | copyright 2001-2016 Python Software Foundation; All Rights Reserved. 178 | 179 | > 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and 180 | > the Individual or Organization ("Licensee") accessing and otherwise using Python 181 | > 3.5.1 software in source or binary form and its associated documentation. 182 | > 183 | > 2. Subject to the terms and conditions of this License Agreement, PSF hereby 184 | > grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, 185 | > analyze, test, perform and/or display publicly, prepare derivative works, 186 | > distribute, and otherwise use Python 3.5.1 alone or in any derivative 187 | > version, provided, however, that PSF's License Agreement and PSF's notice of 188 | > copyright, i.e., "Copyright © 2001-2016 Python Software Foundation; All Rights 189 | > Reserved" are retained in Python 3.5.1 alone or in any derivative version 190 | > prepared by Licensee. 191 | > 192 | > 3. In the event Licensee prepares a derivative work that is based on or 193 | > incorporates Python 3.5.1 or any part thereof, and wants to make the 194 | > derivative work available to others as provided herein, then Licensee hereby 195 | > agrees to include in any such work a brief summary of the changes made to Python 196 | > 3.5.1. 197 | > 198 | > 4. PSF is making Python 3.5.1 available to Licensee on an "AS IS" basis. 199 | > PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF 200 | > EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR 201 | > WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE 202 | > USE OF PYTHON 3.5.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 203 | > 204 | > 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 3.5.1 205 | > FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF 206 | > MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 3.5.1, OR ANY DERIVATIVE 207 | > THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 208 | > 209 | > 6. This License Agreement will automatically terminate upon a material breach of 210 | > its terms and conditions. 211 | > 212 | > 7. Nothing in this License Agreement shall be deemed to create any relationship 213 | > of agency, partnership, or joint venture between PSF and Licensee. This License 214 | > Agreement does not grant permission to use PSF trademarks or trade name in a 215 | > trademark sense to endorse or promote products or services of Licensee, or any 216 | > third party. 217 | > 218 | > 8. By copying, installing or otherwise using Python 3.5.1, Licensee agrees 219 | > to be bound by the terms and conditions of this License Agreement. 220 | -------------------------------------------------------------------------------- /models/boileau2015/adan56/adan56.yaml: -------------------------------------------------------------------------------- 1 | project_name: adan56 2 | inlet_file: "adan56_inlet.dat" 3 | write_results: ["P", "Q", "A"] 4 | blood: 5 | rho: 1060.0 6 | mu: 0.004 7 | solver: 8 | Ccfl: 0.9 9 | cycles: 10 10 | jump: 100 11 | convergence_tolerance: 1.0 12 | network: 13 | - label: aortic_arch_I 14 | sn: 1 15 | tn: 2 16 | L: 0.0744137655 17 | E: 225000.0 18 | M: 74 19 | Rp: 0.01595 20 | Rd: 0.0129524399 21 | gamma_profile: 2 22 | Pext: 10000.0 23 | - label: brachiocephalic_trunk 24 | sn: 2 25 | tn: 3 26 | L: 0.0473512778 27 | E: 225000.0 28 | M: 47 29 | Rp: 0.00672809 30 | Rd: 0.00615874 31 | gamma_profile: 2 32 | Pext: 10000.0 33 | - label: aortic_arch_II 34 | sn: 2 35 | tn: 4 36 | L: 0.0096038364 37 | E: 225000.0 38 | M: 9 39 | Rp: 0.0129524399 40 | Rd: 0.0125655749 41 | gamma_profile: 2 42 | Pext: 10000.0 43 | - label: subclavian_R_I 44 | sn: 3 45 | tn: 5 46 | L: 0.015740629 47 | E: 225000.0 48 | M: 15 49 | Rp: 0.00489563 50 | Rd: 0.0041773477 51 | gamma_profile: 2 52 | Pext: 10000.0 53 | - label: common_carotid_R 54 | sn: 3 55 | tn: 6 56 | L: 0.0812193581 57 | E: 225000.0 58 | M: 81 59 | Rp: 0.00447559 60 | Rd: 0.00332624 61 | gamma_profile: 2 62 | Pext: 10000.0 63 | - label: vertebral_R 64 | sn: 5 65 | tn: 7 66 | L: 0.2044531883 67 | E: 225000.0 68 | M: 204 69 | Rp: 0.00133527 70 | Rd: 0.00133527 71 | outlet: wk3 72 | R1: 1810426462.5 73 | R2: 7241705849.9 74 | Cc: 3.128659004e-11 75 | gamma_profile: 2 76 | Pext: 10000.0 77 | - label: subclavian_R_II 78 | sn: 5 79 | tn: 8 80 | L: 0.0411187821 81 | E: 225000.0 82 | M: 41 83 | Rp: 0.0041773477 84 | Rd: 0.002301 85 | gamma_profile: 2 86 | Pext: 10000.0 87 | - label: axillary_R 88 | sn: 8 89 | tn: 9 90 | L: 0.1200020481 91 | E: 225000.0 92 | M: 120 93 | Rp: 0.002301 94 | Rd: 0.002077 95 | gamma_profile: 2 96 | Pext: 10000.0 97 | - label: brachial_R 98 | sn: 9 99 | tn: 10 100 | L: 0.2231082046 101 | E: 225000.0 102 | M: 223 103 | Rp: 0.002077 104 | Rd: 0.00182827 105 | gamma_profile: 2 106 | Pext: 10000.0 107 | - label: radial_R 108 | sn: 10 109 | tn: 11 110 | L: 0.3008857661 111 | E: 225000.0 112 | M: 300 113 | Rp: 0.001378 114 | Rd: 0.001378 115 | outlet: wk3 116 | R1: 1153880920.0 117 | R2: 4615523680.2 118 | Cc: 4.90883154e-11 119 | gamma_profile: 2 120 | Pext: 10000.0 121 | - label: ulnar_R_I 122 | sn: 10 123 | tn: 12 124 | L: 0.0297562408 125 | E: 225000.0 126 | M: 29 127 | Rp: 0.001408 128 | Rd: 0.001408 129 | gamma_profile: 2 130 | Pext: 10000.0 131 | - label: common_interosseous_R 132 | sn: 12 133 | tn: 13 134 | L: 0.0162660658 135 | E: 225000.0 136 | M: 16 137 | Rp: 0.000959 138 | Rd: 0.000959 139 | gamma_profile: 2 140 | Pext: 10000.0 141 | - label: ulnar_R_II 142 | sn: 12 143 | tn: 14 144 | L: 0.2392616296 145 | E: 225000.0 146 | M: 239 147 | Rp: 0.001408 148 | Rd: 0.001408 149 | outlet: wk3 150 | R1: 1174863776.7 151 | R2: 4699455106.8 152 | Cc: 4.821160687e-11 153 | gamma_profile: 2 154 | Pext: 10000.0 155 | - label: posterior_interosseous_R 156 | sn: 13 157 | tn: 15 158 | L: 0.2305613685 159 | E: 225000.0 160 | M: 230 161 | Rp: 0.000676 162 | Rd: 0.000676 163 | outlet: wk3 164 | R1: 4781305280.3 165 | R2: 19125221121.3 166 | Cc: 1.184657059e-11 167 | gamma_profile: 2 168 | Pext: 10000.0 169 | - label: external_carotid_R 170 | sn: 6 171 | tn: 16 172 | L: 0.0608968774 173 | E: 225000.0 174 | M: 60 175 | Rp: 0.00226547 176 | Rd: 0.00226547 177 | outlet: wk3 178 | R1: 939080951.9 179 | R2: 3756323807.7 180 | Cc: 6.031649393e-11 181 | gamma_profile: 2 182 | Pext: 10000.0 183 | - label: internal_carotid_R 184 | sn: 6 185 | tn: 17 186 | L: 0.1321099628 187 | E: 225000.0 188 | M: 132 189 | Rp: 0.00276538 190 | Rd: 0.00276538 191 | outlet: wk3 192 | R1: 576015963.3 193 | R2: 2304063853.4 194 | Cc: 9.833420276e-11 195 | gamma_profile: 2 196 | Pext: 10000.0 197 | - label: common_carotid_L 198 | sn: 4 199 | tn: 18 200 | L: 0.1213190392 201 | E: 225000.0 202 | M: 121 203 | Rp: 0.00447559 204 | Rd: 0.00332624 205 | gamma_profile: 2 206 | Pext: 10000.0 207 | - label: aortic_arch_III 208 | sn: 4 209 | tn: 19 210 | L: 0.0069785313 211 | E: 225000.0 212 | M: 6 213 | Rp: 0.0125655749 214 | Rd: 0.0122844634 215 | gamma_profile: 2 216 | Pext: 10000.0 217 | - label: external_carotid_L 218 | sn: 18 219 | tn: 20 220 | L: 0.0608970599 221 | E: 225000.0 222 | M: 60 223 | Rp: 0.00226547 224 | Rd: 0.00226547 225 | outlet: wk3 226 | R1: 942390426.5 227 | R2: 3769561706.0 228 | Cc: 6.010467524e-11 229 | gamma_profile: 2 230 | Pext: 10000.0 231 | - label: internal_carotid_L 232 | sn: 18 233 | tn: 21 234 | L: 0.1321103835 235 | E: 225000.0 236 | M: 132 237 | Rp: 0.00276538 238 | Rd: 0.00276538 239 | outlet: wk3 240 | R1: 577939870.8 241 | R2: 2311759483.1 242 | Cc: 9.800685746e-11 243 | gamma_profile: 2 244 | Pext: 10000.0 245 | - label: subclavian_L_I 246 | sn: 19 247 | tn: 22 248 | L: 0.0493841253 249 | E: 225000.0 250 | M: 49 251 | Rp: 0.00489563 252 | Rd: 0.0034798354 253 | gamma_profile: 2 254 | Pext: 10000.0 255 | - label: aortic_arch_IV 256 | sn: 19 257 | tn: 23 258 | L: 0.0430576701 259 | E: 225000.0 260 | M: 43 261 | Rp: 0.0122844634 262 | Rd: 0.01055 263 | gamma_profile: 2 264 | Pext: 10000.0 265 | - label: vertebral_L 266 | sn: 22 267 | tn: 24 268 | L: 0.2041538087 269 | E: 225000.0 270 | M: 204 271 | Rp: 0.00133527 272 | Rd: 0.00133527 273 | outlet: wk3 274 | R1: 1924300300.4 275 | R2: 7697201201.8 276 | Cc: 2.943515132e-11 277 | gamma_profile: 2 278 | Pext: 10000.0 279 | - label: subclavian_L_II 280 | sn: 22 281 | tn: 25 282 | L: 0.0411187859 283 | E: 225000.0 284 | M: 41 285 | Rp: 0.0034798354 286 | Rd: 0.002301 287 | gamma_profile: 2 288 | Pext: 10000.0 289 | - label: axillary_L 290 | sn: 25 291 | tn: 26 292 | L: 0.120002137 293 | E: 225000.0 294 | M: 120 295 | Rp: 0.002301 296 | Rd: 0.002077 297 | gamma_profile: 2 298 | Pext: 10000.0 299 | - label: brachial_L 300 | sn: 26 301 | tn: 27 302 | L: 0.2231087827 303 | E: 225000.0 304 | M: 223 305 | Rp: 0.002077 306 | Rd: 0.00182827 307 | gamma_profile: 2 308 | Pext: 10000.0 309 | - label: radial_L 310 | sn: 27 311 | tn: 28 312 | L: 0.3108844061 313 | E: 225000.0 314 | M: 310 315 | Rp: 0.001378 316 | Rd: 0.001378 317 | outlet: wk3 318 | R1: 1133218047.3 319 | R2: 4532872189.2 320 | Cc: 4.998338199e-11 321 | gamma_profile: 2 322 | Pext: 10000.0 323 | - label: ulnar_L_I 324 | sn: 27 325 | tn: 29 326 | L: 0.0297557899 327 | E: 225000.0 328 | M: 29 329 | Rp: 0.001408 330 | Rd: 0.001408 331 | gamma_profile: 2 332 | Pext: 10000.0 333 | - label: common_interosseous_L 334 | sn: 29 335 | tn: 30 336 | L: 0.0162660627 337 | E: 225000.0 338 | M: 16 339 | Rp: 0.000959 340 | Rd: 0.000959 341 | gamma_profile: 2 342 | Pext: 10000.0 343 | - label: ulnar_L_II 344 | sn: 29 345 | tn: 31 346 | L: 0.2392621589 347 | E: 225000.0 348 | M: 239 349 | Rp: 0.001408 350 | Rd: 0.001408 351 | outlet: wk3 352 | R1: 1197626267.1 353 | R2: 4790505068.3 354 | Cc: 4.729528075e-11 355 | gamma_profile: 2 356 | Pext: 10000.0 357 | - label: posterior_interosseous_L 358 | sn: 30 359 | tn: 32 360 | L: 0.2305624697 361 | E: 225000.0 362 | M: 230 363 | Rp: 0.000676 364 | Rd: 0.000676 365 | outlet: wk3 366 | R1: 4798622229.2 367 | R2: 19194488916.9 368 | Cc: 1.180381948e-11 369 | gamma_profile: 2 370 | Pext: 10000.0 371 | - label: thoracic_aorta_I 372 | sn: 23 373 | tn: 33 374 | L: 0.0098970813 375 | E: 225000.0 376 | M: 9 377 | Rp: 0.01055 378 | Rd: 0.010363805 379 | gamma_profile: 2 380 | Pext: 10000.0 381 | - label: posterior_intercostal_T6_R 382 | sn: 33 383 | tn: 34 384 | L: 0.1968810988 385 | E: 225000.0 386 | M: 196 387 | Rp: 0.0014 388 | Rd: 0.0014 389 | outlet: wk3 390 | R1: 24912692207.8 391 | R2: 99650768831.3 392 | Cc: 2.27362302e-12 393 | gamma_profile: 2 394 | Pext: 10000.0 395 | - label: thoracic_aorta_II 396 | sn: 33 397 | tn: 35 398 | L: 0.0078803844 399 | E: 225000.0 400 | M: 7 401 | Rp: 0.010363805 402 | Rd: 0.0102155504 403 | gamma_profile: 2 404 | Pext: 10000.0 405 | - label: posterior_intercostal_T6_L 406 | sn: 35 407 | tn: 36 408 | L: 0.17803022 409 | E: 225000.0 410 | M: 178 411 | Rp: 0.0014 412 | Rd: 0.0014 413 | outlet: wk3 414 | R1: 25558317606.7 415 | R2: 102233270427.0 416 | Cc: 2.21618932e-12 417 | gamma_profile: 2 418 | Pext: 10000.0 419 | - label: thoracic_aorta_III 420 | sn: 35 421 | tn: 37 422 | L: 0.0155559176 423 | E: 225000.0 424 | M: 15 425 | Rp: 0.0102155504 426 | Rd: 0.0099228951 427 | gamma_profile: 2 428 | Pext: 10000.0 429 | - label: posterior_intercostal_T7_R 430 | sn: 37 431 | tn: 38 432 | L: 0.2015603447 433 | E: 225000.0 434 | M: 201 435 | Rp: 0.00155 436 | Rd: 0.00155 437 | outlet: wk3 438 | R1: 23243370855.3 439 | R2: 92973483421.3 440 | Cc: 2.43691291e-12 441 | gamma_profile: 2 442 | Pext: 10000.0 443 | - label: thoracic_aorta_IV 444 | sn: 37 445 | tn: 39 446 | L: 0.0053270486 447 | E: 225000.0 448 | M: 5 449 | Rp: 0.0099228951 450 | Rd: 0.0098226767 451 | gamma_profile: 2 452 | Pext: 10000.0 453 | - label: posterior_intercostal_T7_L 454 | sn: 39 455 | tn: 40 456 | L: 0.1851762417 457 | E: 225000.0 458 | M: 185 459 | Rp: 0.00155 460 | Rd: 0.00155 461 | outlet: wk3 462 | R1: 23442544272.4 463 | R2: 93770177089.7 464 | Cc: 2.41620832e-12 465 | gamma_profile: 2 466 | Pext: 10000.0 467 | - label: thoracic_aorta_V 468 | sn: 39 469 | tn: 41 470 | L: 0.1215607465 471 | E: 225000.0 472 | M: 121 473 | Rp: 0.0098226767 474 | Rd: 0.00753574 475 | gamma_profile: 2 476 | Pext: 10000.0 477 | - label: thoracic_aorta_VI 478 | sn: 41 479 | tn: 42 480 | L: 0.0032476667 481 | E: 225000.0 482 | M: 5 483 | Rp: 0.00753574 484 | Rd: 0.0074949241 485 | gamma_profile: 2 486 | Pext: 10000.0 487 | - label: celiac_trunk 488 | sn: 42 489 | tn: 43 490 | L: 0.0168238334 491 | E: 225000.0 492 | M: 16 493 | Rp: 0.00334998 494 | Rd: 0.00321246 495 | gamma_profile: 2 496 | Pext: 10000.0 497 | - label: abdominal_aorta_I 498 | sn: 42 499 | tn: 44 500 | L: 0.0139884345 501 | E: 225000.0 502 | M: 13 503 | Rp: 0.0074949241 504 | Rd: 0.007319121 505 | gamma_profile: 2 506 | Pext: 10000.0 507 | - label: common_hepatic 508 | sn: 43 509 | tn: 45 510 | L: 0.0665545523 511 | E: 225000.0 512 | M: 66 513 | Rp: 0.00268614 514 | Rd: 0.00268614 515 | outlet: wk3 516 | R1: 334855096.2 517 | R2: 1339420384.8 518 | Cc: 1.6915397489e-10 519 | gamma_profile: 2 520 | Pext: 10000.0 521 | - label: splenic_I 522 | sn: 43 523 | tn: 46 524 | L: 0.003948745 525 | E: 225000.0 526 | M: 5 527 | Rp: 0.00216682 528 | Rd: 0.00216682 529 | gamma_profile: 2 530 | Pext: 10000.0 531 | - label: left_gastric 532 | sn: 46 533 | tn: 47 534 | L: 0.0928669141 535 | E: 225000.0 536 | M: 92 537 | Rp: 0.00150666 538 | Rd: 0.00150666 539 | outlet: wk3 540 | R1: 34339350287.2 541 | R2: 137357401149.0 542 | Cc: 1.64947997e-12 543 | gamma_profile: 2 544 | Pext: 10000.0 545 | - label: splenic_II 546 | sn: 46 547 | tn: 48 548 | L: 0.0644027418 549 | E: 225000.0 550 | M: 64 551 | Rp: 0.00216682 552 | Rd: 0.00216682 553 | outlet: wk3 554 | R1: 473332350.9 555 | R2: 1893329403.6 556 | Cc: 1.1966659457e-10 557 | gamma_profile: 2 558 | Pext: 10000.0 559 | - label: superior_mesenteric 560 | sn: 44 561 | tn: 49 562 | L: 0.2163983238 563 | E: 225000.0 564 | M: 216 565 | Rp: 0.00392612 566 | Rd: 0.00392612 567 | outlet: wk3 568 | R1: 218192533.0 569 | R2: 872770131.9 570 | Cc: 2.5959674129e-10 571 | gamma_profile: 2 572 | Pext: 10000.0 573 | - label: abdominal_aorta_II 574 | sn: 44 575 | tn: 50 576 | L: 0.0043191256 577 | E: 225000.0 578 | M: 5 579 | Rp: 0.007319121 580 | Rd: 0.0072648393 581 | gamma_profile: 2 582 | Pext: 10000.0 583 | - label: renal_L 584 | sn: 50 585 | tn: 51 586 | L: 0.021836535 587 | E: 225000.0 588 | M: 21 589 | Rp: 0.0027089 590 | Rd: 0.0027089 591 | outlet: wk3 592 | R1: 226281607.5 593 | R2: 905126430.2 594 | Cc: 2.5031672325e-10 595 | gamma_profile: 2 596 | Pext: 10000.0 597 | - label: abdominal_aorta_III 598 | sn: 50 599 | tn: 52 600 | L: 0.0119772827 601 | E: 225000.0 602 | M: 11 603 | Rp: 0.0072648393 604 | Rd: 0.0071143118 605 | gamma_profile: 2 606 | Pext: 10000.0 607 | - label: renal_R 608 | sn: 52 609 | tn: 53 610 | L: 0.0377174249 611 | E: 225000.0 612 | M: 37 613 | Rp: 0.00309737 614 | Rd: 0.00309737 615 | outlet: wk3 616 | R1: 227041378.8 617 | R2: 908165515.3 618 | Cc: 2.4947906336e-10 619 | gamma_profile: 2 620 | Pext: 10000.0 621 | - label: abdominal_aorta_IV 622 | sn: 52 623 | tn: 54 624 | L: 0.0540893766 625 | E: 225000.0 626 | M: 54 627 | Rp: 0.0071143118 628 | Rd: 0.00643453 629 | gamma_profile: 2 630 | Pext: 10000.0 631 | - label: inferior_mesenteric 632 | sn: 54 633 | tn: 55 634 | L: 0.0902385435 635 | E: 225000.0 636 | M: 90 637 | Rp: 0.00207748 638 | Rd: 0.00207748 639 | outlet: wk3 640 | R1: 2391290071.9 641 | R2: 9565160287.5 642 | Cc: 2.368682545e-11 643 | gamma_profile: 2 644 | Pext: 10000.0 645 | - label: abdominal_aorta_V 646 | sn: 54 647 | tn: 56 648 | L: 0.042224742 649 | E: 225000.0 650 | M: 42 651 | Rp: 0.00643453 652 | Rd: 0.00590386 653 | gamma_profile: 2 654 | Pext: 10000.0 655 | - label: common_iliac_R 656 | sn: 56 657 | tn: 57 658 | L: 0.076428564 659 | E: 225000.0 660 | M: 76 661 | Rp: 0.00449868 662 | Rd: 0.00409113 663 | gamma_profile: 2 664 | Pext: 10000.0 665 | - label: common_iliac_L 666 | sn: 56 667 | tn: 58 668 | L: 0.0740380184 669 | E: 225000.0 670 | M: 74 671 | Rp: 0.00449868 672 | Rd: 0.00409113 673 | gamma_profile: 2 674 | Pext: 10000.0 675 | - label: external_iliac_R 676 | sn: 57 677 | tn: 59 678 | L: 0.102210634 679 | E: 225000.0 680 | M: 102 681 | Rp: 0.00337758 682 | Rd: 0.003189 683 | gamma_profile: 2 684 | Pext: 10000.0 685 | - label: internal_iliac_R 686 | sn: 57 687 | tn: 60 688 | L: 0.0725094209 689 | E: 225000.0 690 | M: 72 691 | Rp: 0.00281829 692 | Rd: 0.00281829 693 | outlet: wk3 694 | R1: 414555626.7 695 | R2: 1658222507.0 696 | Cc: 1.3663322092e-10 697 | gamma_profile: 2 698 | Pext: 10000.0 699 | - label: femoral_R_I 700 | sn: 59 701 | tn: 61 702 | L: 0.0315912244 703 | E: 225000.0 704 | M: 31 705 | Rp: 0.003189 706 | Rd: 0.0031437249 707 | gamma_profile: 2 708 | Pext: 10000.0 709 | - label: profunda_femoris_R 710 | sn: 61 711 | tn: 62 712 | L: 0.2383937248 713 | E: 225000.0 714 | M: 238 715 | Rp: 0.00214445 716 | Rd: 0.00214445 717 | outlet: wk3 718 | R1: 342687217.5 719 | R2: 1370748870.1 720 | Cc: 1.6528795833e-10 721 | gamma_profile: 2 722 | Pext: 10000.0 723 | - label: femoral_R_II 724 | sn: 61 725 | tn: 63 726 | L: 0.3192853229 727 | E: 225000.0 728 | M: 319 729 | Rp: 0.0031437249 730 | Rd: 0.00268614 731 | gamma_profile: 2 732 | Pext: 10000.0 733 | - label: popliteal_R_I 734 | sn: 63 735 | tn: 64 736 | L: 0.1320290229 737 | E: 225000.0 738 | M: 132 739 | Rp: 0.00268614 740 | Rd: 0.0023676798 741 | gamma_profile: 2 742 | Pext: 10000.0 743 | - label: anterior_tibial_R 744 | sn: 64 745 | tn: 65 746 | L: 0.3862156733 747 | E: 225000.0 748 | M: 386 749 | Rp: 0.0011663 750 | Rd: 0.0011663 751 | outlet: wk3 752 | R1: 2452511040.7 753 | R2: 9810044163.0 754 | Cc: 2.309554151e-11 755 | gamma_profile: 2 756 | Pext: 10000.0 757 | - label: popliteal_R_II 758 | sn: 64 759 | tn: 66 760 | L: 0.0087974289 761 | E: 225000.0 762 | M: 8 763 | Rp: 0.0023676798 764 | Rd: 0.00234646 765 | gamma_profile: 2 766 | Pext: 10000.0 767 | - label: tibiofibular_trunk_R 768 | sn: 66 769 | tn: 67 770 | L: 0.0361626766 771 | E: 225000.0 772 | M: 36 773 | Rp: 0.00234646 774 | Rd: 0.00234646 775 | gamma_profile: 2 776 | Pext: 10000.0 777 | - label: posterior_tibial_R 778 | sn: 67 779 | tn: 68 780 | L: 0.3828848516 781 | E: 225000.0 782 | M: 382 783 | Rp: 0.00122936 784 | Rd: 0.00122936 785 | outlet: wk3 786 | R1: 2115636908.3 787 | R2: 8462547633.2 788 | Cc: 2.677305842e-11 789 | gamma_profile: 2 790 | Pext: 10000.0 791 | - label: external_iliac_L 792 | sn: 58 793 | tn: 69 794 | L: 0.1022106793 795 | E: 225000.0 796 | M: 102 797 | Rp: 0.00337758 798 | Rd: 0.003189 799 | gamma_profile: 2 800 | Pext: 10000.0 801 | - label: internal_iliac_L 802 | sn: 58 803 | tn: 70 804 | L: 0.0725093924 805 | E: 225000.0 806 | M: 72 807 | Rp: 0.00281829 808 | Rd: 0.00281829 809 | outlet: wk3 810 | R1: 415797178.2 811 | R2: 1663188712.7 812 | Cc: 1.3622524035e-10 813 | gamma_profile: 2 814 | Pext: 10000.0 815 | - label: femoral_L_I 816 | sn: 69 817 | tn: 71 818 | L: 0.0315912236 819 | E: 225000.0 820 | M: 31 821 | Rp: 0.003189 822 | Rd: 0.0031437249 823 | gamma_profile: 2 824 | Pext: 10000.0 825 | - label: profunda_femoris_L 826 | sn: 71 827 | tn: 72 828 | L: 0.2383937548 829 | E: 225000.0 830 | M: 238 831 | Rp: 0.00214445 832 | Rd: 0.00214445 833 | outlet: wk3 834 | R1: 342869623.5 835 | R2: 1371478494.0 836 | Cc: 1.652e-10 837 | gamma_profile: 2 838 | Pext: 10000.0 839 | - label: femoral_L_II 840 | sn: 71 841 | tn: 73 842 | L: 0.3192853183 843 | E: 225000.0 844 | M: 319 845 | Rp: 0.0031437249 846 | Rd: 0.00268614 847 | gamma_profile: 2 848 | Pext: 10000.0 849 | - label: popliteal_L_I 850 | sn: 73 851 | tn: 74 852 | L: 0.1320280854 853 | E: 225000.0 854 | M: 132 855 | Rp: 0.00268614 856 | Rd: 0.0023676798 857 | gamma_profile: 2 858 | Pext: 10000.0 859 | - label: anterior_tibial_L 860 | sn: 74 861 | tn: 75 862 | L: 0.3862164058 863 | E: 225000.0 864 | M: 386 865 | Rp: 0.0011663 866 | Rd: 0.0011663 867 | outlet: wk3 868 | R1: 2453282529.0 869 | R2: 9813130116.1 870 | Cc: 2.308827861e-11 871 | gamma_profile: 2 872 | Pext: 10000.0 873 | - label: popliteal_L_II 874 | sn: 74 875 | tn: 76 876 | L: 0.0087973824 877 | E: 225000.0 878 | M: 8 879 | Rp: 0.0023676798 880 | Rd: 0.00234646 881 | gamma_profile: 2 882 | Pext: 10000.0 883 | - label: tibiofibular_trunk_L 884 | sn: 76 885 | tn: 77 886 | L: 0.0361636403 887 | E: 225000.0 888 | M: 36 889 | Rp: 0.00234646 890 | Rd: 0.00234646 891 | gamma_profile: 2 892 | Pext: 10000.0 893 | - label: posterior_tibial_L 894 | sn: 77 895 | tn: 78 896 | L: 0.3828846476 897 | E: 225000.0 898 | M: 382 899 | Rp: 0.00122936 900 | Rd: 0.00122936 901 | outlet: wk3 902 | R1: 2116559027.0 903 | R2: 8466236107.9 904 | Cc: 2.676139423e-11 905 | gamma_profile: 2 906 | Pext: 10000.0 907 | --------------------------------------------------------------------------------